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, even when the machine has since gained Oh My Zsh, Homebrew, or bash-completion and a first install would now choose 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, which 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 it only when the directory already exists and you can write to it, and it never uses sudo.
Otherwise the file goes to ~/.zfunc, and the managed block adds that directory to fpath and calls compinit -i. It has to be -i rather than -C: -C omits the check for new completion functions and reuses the existing dump, and by the time the block runs your own compinit has usually written one, which would leave _quarto unseen. -i keeps that check and only suppresses the warning about insecure directories, which your own call has already reported if there was anything to report.
If your configuration already puts ~/.zfunc on fpath before it runs compinit, you can delete the managed block: the file alone is enough.
Alongside the three destinations above, the installer finds and cleans up $XDG_DATA_HOME/zsh/site-functions/_quarto, which is where an earlier version of this page told you to put the file.
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, which is what a source build reports and a release never does.
The dev channel additionally 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 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, and it 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, 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, 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, for anything that would rather read the commands, flags, and values as data than parse a completion script. No shell loads it, and the installers never fetch it.
Alongside it comes a manifest.json, carrying 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 verify that checksum before writing anything, which catches a truncated or corrupted download. Since 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 fetch, 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 |