Quirlv0.5.1
Using Quirl

Completion

Canonical Quirl project documentation synced from docs/completion.md.

Quirl's Tab key behaves like Zsh's default completion, then adds a menu with documentation beside each candidate. If you already rely on Zsh completion, the same keystrokes produce the same command lines in Quirl.

What Tab does

Press Tab in the middle of a word. Quirl gathers candidates from every source (see below), then acts once they have all answered:

SituationResultExample
Exactly one matchThe match is inserted, followed by a spacecat my → cat my\ file.txt␠
One directoryThe directory is inserted with a trailing /, ready for the next levelcd cr → cd crates/
Several matches sharing a longer prefixThe word grows to the shared prefix and the menu lists the choicesls Car → ls Cargo.
Several matches, no shared progressThe menu opensgit ch → menu
No matchesNothing changes

While the menu is open, each further Tab puts the next candidate on the line, like Zsh's menu completion: ls Tab Tab gives ls Cargo.lock, and another Tab gives ls Cargo.toml. Once cycling has started, the arrow keys move through the same list. Enter accepts the candidate (adding the separating space), Esc closes the menu and keeps what is on the line, Ctrl-_ (undo) restores the line from before the candidate, and Shift-Tab expands the list into the full picker.

Quirl never types a guess for you. When only a fuzzy match is available, such as gco matching git checkout, the menu shows it for review instead of replacing what you wrote.

Words that invite more typing do not get a trailing space: directories end in /, option assignments such as --color= stay open, and so do host: prefixes. A file completed inside an open quote also closes the quote: cat "my → cat "my file.txt"␠.

Where candidates come from

SourceCompletesNotes
Command catalogCommands, subcommands, options, documented option valuesBuilt from Quirl's curated catalog plus discovered Fish, Bash, and Zsh declarations, --help text, and man pages
FilesystemFiles and directoriescd offers only directories; hidden entries appear when the word starts with .; ~/ expands from HOME
Environment$NAME and ${NAMEShows each value; a variable that names a directory completes with a /, like Zsh's AUTO_PARAM_SLASH
Live ZshAny argument Zsh knows how to completeGit branches and refs, Make targets, SSH hosts, process IDs, package names, and so on
Lua pluginsWhatever trusted plugins registerSee the plugin platform documentation

Candidates that produce the same command line are shown once, even if two sources describe them differently. The plain file listing is a fallback: when Zsh's function for the command answers, its choice wins, so git add offers changed files rather than every file in the directory.

Ranking

Matches are ranked in three tiers:

  1. names that start with exactly what you typed;
  2. names that start with it when case is ignored;
  3. fuzzy subsequence matches.

Only the best tier that has any matches is shown, in alphabetical order with an exact match first. Commands complete one word at a time, as in Zsh: gi offers git and gist, and git ch offers git checkout, git cherry, and git cherry-pick, but not every deeper git … path.

Live Zsh completion

For arguments, an explicit Tab also asks your installed Zsh. Quirl runs Zsh's own completion functions, so dynamic values such as branch names come from the same code that completes them in Zsh.

The request is deliberately contained:

  • It runs only when you press Tab. As-you-type suggestions never start a shell.
  • Zsh starts without your startup files (.zshrc and friends) and with a cleared environment, except PATH, HOME, USER, and LOGNAME.
  • Each request is bounded to 1.5 seconds and 1,024 candidates, and its whole process group is cleaned up afterwards.
  • Zsh's bundled completion functions take precedence. Site directories add functions for commands Zsh does not ship: the system, Debian vendor-completions, Homebrew, and Nix share/zsh/site-functions directories, the per-user ~/.zfunc, ~/.zsh/completions, and ~/.local/share/zsh/site-functions, and rustup's toolchain folder, which carries _cargo. Set QUIRL_ZSH_PATH to a :-separated list to replace the site directories, for example to include a plugin manager's folder.
  • Without Zsh, or for a command with no Zsh completion function, the other sources still answer on their own.
  • Set QUIRL_ZSH_COMPLETION=off before starting Quirl to disable live Zsh completion for the session.

Results keep Zsh's display order: each group is sorted, unless Zsh added it unsorted on purpose, such as recent commits after branch names. A candidate containing /, such as the branch feature/login, is shown as a path only when it names an existing file or directory.

The command's own completion

Many modern tools, including docker, kubectl, gh, helm, and podman, are built on Cobra and complete their own arguments through PROGRAM __complete ARGS.... When Zsh has no function for such a command, an explicit Tab asks the program itself, so docker im offers image and images with their descriptions.

Only a fixed list of known Cobra programs is asked, because any other program would receive __complete as an ordinary argument. Each request runs only on Tab, in its own contained process group, within 1.5 seconds and 256 KiB of output; any failure simply contributes nothing. Set QUIRL_TOOL_COMPLETION=off before starting Quirl to disable these requests.

Checking completion from a script

quirl complete prints the candidates an explicit Tab offers for a partial command line, from the same engine and every source:

$ quirl complete "git checkout f"
feature/one
fix-two

Use --format json for machine-readable output with replacement ranges.

Automatic suggestions

While you type, Quirl can open an informational menu for exact commands and option prefixes, and a selectable one for explicit paths. Enter keeps running the command unless you have moved into the menu with Tab or the arrow keys. The completion.auto and completion.min_chars configuration settings control this behavior.

On this page