Clink combines the native Windows shell cmd.exe with the powerful command line editing features of the GNU Readline library, which provides rich completion, history, and line-editing capabilities. Readline is best known for its use in the Unix shell Bash, the standard shell for many Linux distributions.
For details, refer to the Clink documentation.
[!NOTE] Starting Clink injects it into a
cmd.exe
process, where it intercepts a handful of Windows API functions so that it can replace the prompt and input line editing with its own Readline-powered enhancements.
Downloads are available from the releases page.
See the issues page for known issues or to file new issues.
You can install Clink by running the setup EXE file from the releases page.
Or by using winget and running winget install clink
.
Or by using scoop and running scoop install clink
.
Or by downloading the ZIP file from releases page, and extracting the files to a directory of your choosing.
Once installed, there are several ways to start Clink.
If Clink is configured for autorun, just start cmd.exe
and Clink is automatically injected and ready to use.
The setup EXE has an option "Autorun when cmd.exe starts". If you didn't use the setup EXE, or if you want to enable or disable autorun later, you can run
clink autorun install
orclink autorun uninstall
to change the autorun configuration. Runclink autorun --help
for more info.
To manually start, run the Clink shortcut from the Start menu (or the clink.bat located in the install directory).
To establish Clink to an existing cmd.exe
process, use clink inject
.
If the Clink install directory isn't in the PATH, then use
install_dir\clink
in place ofclink
to run Clink commands. Once Clink is injected into acmd.exe
process, then it automatically sets an alias so that you can simply useclink
.
You can use Clink right away without configuring anything:
See Getting Started for information on how to get started with using Clink.
The new Clink tries to be as backward compatible with Clink v0.4.9 as possible. However, in some cases upgrading may require a little bit of configuration work. More details can be found in the Clink documentation.
Clink can be extended through its Lua API which allows easy creation of context sensitive match generators, prompt filtering, and more. More details can be found in the Clink documentation.
Clink uses Premake to generate Visual Studio solutions or makefiles for MinGW. Note that Premake >= 5.0.0-beta1 is required.
premake5.exe toolchain
(where toolchain is one of Premake's actions - see premake5.exe --help
).build\toolchain
. For example .build\vs2022\clink.sln
.npm install -g marked@2.0.1
to install the marked markdown library (version 2.0.1).premake5.exe docs
.[!IMPORTANT] Clink documentation uses marked@2.0.1. Newer versions of marked have introduced breaking changes, and I haven't yet rewritten how Clink builds the documentation to accommodate the breaking changes. The security fixes in newer versions aren't relevant since marked is only used at build time with known inputs (the marked library is no longer embedded in the documentation as of commit d5b39ca in Oct 2020).
host::edit_line
is the start of showing a prompt and accepting input.line_editor_impl::update_matches
is where the match pipeline uses .generate()
to collect matches and .select()
to filter the matches.rl_module::on_input
and readline_internal_char
(and the _rl_dispatch
inside it) is where keys are translated through Readline's keymap to invoke commands.rl_complete
or rl_menu_complete
or rl_old_menu_complete
are the Readline completion commands.alternative_matches
builds a Readline match array from the results collected by the match pipeline.The easiest way to debug Clink startup is to use simulated injection rather than real injection: set a breakpoint on initialise_clink
and start clink testbed --hook
under the debugger. All of the usual Clink startup code is executed, but the cross-process injection is only simulated, so the resulting prompts of course are not actually executed by CMD.exe.
To debug Clink startup during real injection, you must attach the debugger to the target CMD.exe before injection, set a breakpoint on initialise_clink
(it will be an unresolved breakpoint at first), and then use clink inject -p process_id
. The debugger should resolve the breakpoint as soon as the Clink DLL is loaded, and should hit the breakpoint soon after.
To debug the actual DLL injection procedure, you must debug both the clink_x64.exe
(or clink_x86.exe
) process and the target CMD.exe process.
process::remote_call_internal
in the Clink process.
LoadLibrary
call into the target CMD.exe process.initialise_clink
call into the target CMD.exe process.initialise_clink
in the target CMD.exe process.remote_call_internal
function to inspect the local side of the operation.
stdcall_thunk
function is the instruction payload that will be copied into the target CMD.exe process.region.base
before the CreateRemoteThread
call executes -- this is the address of the instruction payload that has been copied into the target CMD.exe process.CreateRemoteThread
executes, it will transfer execution to that address in the target CMD.exe process, and you can debug through the execution of the instruction payload itself.[!CAUTION] If the instruction payload references any functions or variables from the Clink process, it will crash during execution inside the target CMD.exe process. Compiler features like the "just my code", "edit and continue", "omit frame pointers", exception handling, inlining, and runtime checks must be configured appropriately to keep the instruction payload self-contained (see the "clink_process" lib in the premake5.lua file).
clink set lua.debug true
to enable using the Lua debugger.clink set lua.break_on_error true
to automatically break into the Lua debugger on any Lua script error.pause()
line in a Lua script to break into the debugger at that spot, if the lua.debug
setting is enabled.help
in the Lua debugger to get help on using the Lua debugger.Perform a 3-way merge over the Readline sources where:
Watch out for changes that may need additional follow-up! Including but not limited to these, for example:
save_restore_initial_states
in rl_module.cpp.'/'
literals instead of calling rl_is_path_separator()
(or in complete.c calling pathfold()
).COLOR_SUPPORT
code.HANDLE_MULTIBYTE
support, which may be incorrect or incomplete on Windows.SIGALRM
or SIGTERM
or most other signaler events since MSVC only supports SIGINT
and SIGBREAK
(which is a Microsoft extension).Clink is distributed under the terms of the GNU General Public License v3.0.