Shells
Where each script is installed, and how to do it by hand.
The installer writes one file per shell and, where the shell cannot find that file on its own, adds a managed block to your shell’s configuration:
# >>> quarto completions >>>
# <<< quarto completions <<<Re-running the installer replaces that block. --uninstall removes it, and nothing else.
An install already in place stays where it is
Each table below says where a first install goes. Once a script is on disk, that is the file the installer updates. This stays true even when the machine has since gained Oh My Zsh, Homebrew, or bash-completion, and a first install now chooses somewhere else. Copies in the other locations it knows about are removed on the way, so nothing is left behind to shadow the file that is kept.
To move an install, remove it and install again:
curl -fsSL https://m.canouil.dev/quarto-completions/install.sh | bash -s -- --uninstall
curl -fsSL https://m.canouil.dev/quarto-completions/install.sh | bashbash
| What | Where |
|---|---|
| Script | completions/release/quarto.bash |
| Installed to | $XDG_DATA_HOME/bash-completion/completions/quarto when that directory exists, otherwise $XDG_DATA_HOME/quarto-completions/quarto.bash |
| Configuration | None in the first case, a source line in ~/.bashrc in the second |
$XDG_DATA_HOME defaults to ~/.local/share.
The script targets bash 3.2, which is the version macOS ships. Filtering candidates to Quarto’s input formats needs extglob, which the script enables around that one call and restores afterwards.
Manual install:
mkdir -p ~/.local/share/quarto-completions
curl -fsSL https://m.canouil.dev/quarto-completions/completions/release/quarto.bash \
-o ~/.local/share/quarto-completions/quarto.bash
echo '[ -r ~/.local/share/quarto-completions/quarto.bash ] && . ~/.local/share/quarto-completions/quarto.bash' >> ~/.bashrczsh
| What | Where |
|---|---|
| Script | completions/release/_quarto |
| Installed to | The first that applies: $ZSH_CUSTOM/completions/_quarto under Oh My Zsh, $HOMEBREW_PREFIX/share/zsh/site-functions/_quarto under Homebrew, otherwise ~/.zfunc/_quarto |
| Configuration | None in the first two cases, an fpath line in ~/.zshrc followed by compinit in the third |
zsh loads completion functions from the directories on fpath, and only once compinit has run. zsh has no per-user directory of its own on that list. This is why the destination depends on what else is installed.
Oh My Zsh already puts $ZSH_CUSTOM/completions on fpath and calls compinit itself, both while ~/.zshrc is still sourcing it. Anything appended below that runs too late to matter, so the installer writes the file there and leaves your configuration alone. $ZSH_CUSTOM defaults to ~/.oh-my-zsh/custom.
Homebrew’s own shell setup puts $HOMEBREW_PREFIX/share/zsh/site-functions on fpath for the same reason, so a file written there also needs no configuration. The installer uses that directory only when it already exists and you can write to it, and the installer never uses sudo.
Otherwise the file goes to ~/.zfunc, and the managed block adds that directory to fpath and calls compinit -i. It must be -i rather than -C. -C skips the check for new completion functions and reuses the existing dump. By the time the block runs, your own compinit has usually written that dump, and _quarto stays unseen inside it. -i keeps the check for new functions. It only suppresses the warning about insecure directories, and your own call has already reported that warning if there was anything to report.
If your configuration already puts ~/.zfunc on fpath before it runs compinit, you can remove the managed block. The file alone is enough.
Alongside the three destinations above, the installer finds and removes $XDG_DATA_HOME/zsh/site-functions/_quarto. An earlier version of this page told you to put the file there.
Manual install:
mkdir -p ~/.zfunc
curl -fsSL https://m.canouil.dev/quarto-completions/completions/release/_quarto \
-o ~/.zfunc/_quartoUnder Oh My Zsh, write it to ~/.oh-my-zsh/custom/completions/_quarto instead, and add nothing to ~/.zshrc.
fish
| What | Where |
|---|---|
| Script | completions/release/quarto.fish |
| Installed to | $XDG_CONFIG_HOME/fish/completions/quarto.fish |
| Configuration | None |
fish autoloads that directory, so there is nothing to add to config.fish.
Manual install:
mkdir -p ~/.config/fish/completions
curl -fsSL https://m.canouil.dev/quarto-completions/completions/release/quarto.fish \
-o ~/.config/fish/completions/quarto.fishPowerShell
| What | Where |
|---|---|
| Script | completions/release/quarto.ps1 |
| Installed to | Completions/quarto.ps1 beside $PROFILE.CurrentUserAllHosts |
| Configuration | A dot-source line in $PROFILE.CurrentUserAllHosts |
The completer is registered for both quarto and quarto.cmd, because the Windows installation puts the .cmd shim on PATH.
Manual install:
$directory = Join-Path (Split-Path -Parent $PROFILE.CurrentUserAllHosts) 'Completions'
New-Item -ItemType Directory -Path $directory -Force | Out-Null
Invoke-WebRequest `
-Uri https://m.canouil.dev/quarto-completions/completions/release/quarto.ps1 `
-OutFile (Join-Path $directory 'quarto.ps1')
Add-Content -Path $PROFILE.CurrentUserAllHosts -Value ". `"$directory\quarto.ps1`""Channels
Every script is published for four kinds of channel:
release, generated from the current Quarto release.pre-release, generated from the current Quarto pre-release.dev, generated from a Quarto source build atquarto-dev/quarto-cli’smain.- One directory per Quarto minor, from
1.9onwards, generated from that line’s newest patch.
release and pre-release are rolling aliases. They name whichever lines Quarto ships today, so what they hold changes under you the moment Quarto ships a new minor. A minor such as 1.10 names one line and stays there, which is what to write down when pinning. Both are published at once, so the current release is always available under its own number as well as under release.
Swap release for pre-release, dev, or a minor such as 1.9 in any URL above, or pass --channel pre-release, --channel dev, or --channel 1.9 to the installer. With no --channel given, the installer matches the quarto on PATH to its own minor when that is published, and falls back to release otherwise. It selects dev instead, with no flag needed, when that quarto reports version 99.9.9. That is what a source build reports, and a release never reports it.
The dev channel also completes the commands Quarto hides from its own --help: dev-call and its subcommands, inspect, capabilities, create-project, editor-support, completions, and every subcommand of tools. Several of those commands exist on release builds too, just hidden from view, so installing --channel dev deliberately on a release Quarto is a reasonable choice. Its surface then tracks quarto-cli’s main rather than the release you run. Because every source build reports version 99.9.9, that version says nothing about how recent a dev channel is. The commit it was built from is what does. That commit is recorded in spec.json and manifest.json, and stamped into each script’s header, so an installed dev completion can be traced back to a commit.
A minor channel is generated the same way as release. Flags, commands, and arguments come from that line’s own binary, so they are exactly what it has. The one exception is a handful of value sets src/overlay.ts cannot read from --help at all, such as --to’s output formats and publish’s providers. Those come from the current Quarto instead, so an older channel can occasionally offer a value its own Quarto does not accept.
Three lines are kept current, weekly: the release minor and the pre-release minor, written from the same run as the two aliases, and the one minor below release. That one minor is regenerated against its newest patch, so a late fix on a line Quarto has moved on from still reaches you. Anything two minors below release is frozen at the bytes it was last published with.
Each channel also publishes a spec.json, the enriched command surface the four scripts are emitted from. This is for anyone who wants to read the commands, flags, and values as data rather than parse a completion script. No shell loads it, and the installers never download it.
Alongside it comes a manifest.json. It carries the Quarto version the scripts were generated from, a source object naming what that binary was built from, and a SHA-256 for each file, spec.json included. A released channel names its tag, such as v1.10.18. dev names the quarto-dev/quarto-cli branch and the commit its source build came from. The installers check that checksum before writing anything, which catches a truncated or corrupted download. Because the manifest is served from the same site as the scripts, it is the HTTPS connection, not the checksum, that establishes where those bytes came from. The installer also compares that version against the quarto on PATH, by major and minor only, and prints one line when they disagree. A patch difference, or a build that cannot be read, says nothing, and the install always succeeds regardless.
What each channel publishes
One directory per channel, listed below with what it holds. Every link is a file you can download, at that same path under this site.
| Channel | Quarto | Generated | Files |
|---|---|---|---|
release |
1.10.18 | 2026-08-05 | _quarto, quarto.bash, quarto.fish, quarto.ps1, spec.json, manifest.json |
pre-release |
1.11.1 | 2026-08-05 | _quarto, quarto.bash, quarto.fish, quarto.ps1, spec.json, manifest.json |
dev |
99.9.9 | 2026-08-04 | _quarto, quarto.bash, quarto.fish, quarto.ps1, spec.json, manifest.json |
1.11 |
1.11.1 | 2026-08-05 | _quarto, quarto.bash, quarto.fish, quarto.ps1, spec.json, manifest.json |
1.10 |
1.10.18 | 2026-08-05 | _quarto, quarto.bash, quarto.fish, quarto.ps1, spec.json, manifest.json |
1.9 |
1.9.38 | 2026-08-05 | _quarto, quarto.bash, quarto.fish, quarto.ps1, spec.json, manifest.json |