Commands
Every ketch command in one place: what it does, the form it takes, and one
working example. PKG below is an installed name, an alias, or
owner/repo — most commands that take one also accept @version on the end
(sharkdp/[email protected]). Global flags work everywhere: --root <DIR> points at
a different ketch tree, -v/--verbose shows what ketch is doing, -q/--quiet
prints only errors and requested data, --no-color disables colour, and
--no-emoji drops the icons in front of status lines.
Icons. On a terminal, each status line starts with an icon for what it
reports: 📦 install, ⏫ upgrade or update, 🧹 uninstall or remove, ⏬ download,
🔗 link, ⏪ rollback, 🔍 search, 🩺 doctor, and otherwise ✅ success, ❗ warning,
❌ error, 💡 note. They are on by default (emoji in config.toml,
KETCH_EMOJI) and never appear in a pipe or a file, under TERM=dumb, in
--json or --names-only output, in table data, or in the log.
Install and remove
ketch install [PKG]... [options]
Install one or more packages. Inference picks the release asset matching the
host (architecture, OS, libc); a manifest or --asset says what to do instead.
ketch install BurntSushi/ripgrep # any repo that publishes releases
ketch install rg # or a name the registry knows
ketch install sharkdp/[email protected] # or an exact version
ketch install --path ./mytool # a local binary, archive, symlink, or .app
A package that is already installed is not updated behind your back. With a
newer release, install asks <pkg> <installed> is installed; update to <latest>? (default no) and, on yes, updates it the way ketch upgrade does;
--yes answers yes, and without a terminal it stops with exit 5 and says to
pass --yes or run ketch upgrade. With nothing newer it fails with exit 5:
cannot install <pkg>: <version> is already installed and no update is available (--force reinstalls). An exact version ([email protected]) and a pinned
package behave as before.
Options: --path <PATH> installs a local file (equivalent to
local:<PATH>); --name <NAME> sets the installed name for a single
package; --force/-f reinstalls the requested version even when present;
--pre considers prereleases and keeps the package on them: later
upgrade, outdated and list look for prereleases without --pre, and
info shows channel: pre (an exact prerelease tag, [email protected], does
the same; a plain install moves the package back to stable); --draft
considers GitHub draft releases too, prereleases with them, and keeps the
package on drafts (channel: draft); pkg@<tag> --draft finds a draft by
the tag it will get. GitHub shows drafts only to a token with push access to
the repository (KETCH_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN or
github_token), so without one --draft stops with that reason; a draft's
files download through the API with the token, and are checked like any
other. Other sources have no drafts and refuse --draft; --no-link unpacks without linking onto PATH;
--require-checksum refuses releases with no published checksum;
--asset <NAME> takes one release file by exact name (asks for confirmation,
since the platform check is skipped); -j/--jobs <N> and -y/--yes control
parallelism and prompts. Aliased as ketch i.
A tag that is not a version (nightly, dev, canary, edge) is a
floating tag: the project republishes it under the same name. pkg@nightly
installs it on channel: dev, recording the build it got — the asset's
digest and when it was published. Installing the same tag again is already installed until the tag names another build, and then it takes the new one.
When a release ships several binaries sharing the package's name and no
manifest names one, only one of them is linked: the one --bin <NAME> names;
failing that, the binary named exactly like the package; failing that, a choice
remembered from last time (in state.json, or during ketch sync in
ketch.lock), or a numbered pick in a terminal. Binaries with other names are
linked as usual. With --yes or without a terminal there is no pick, and the
install fails with the candidates listed — see the bin section of
MANIFESTS.md.
--bin <NAME> (single package) answers that question up front, so it works
without a terminal: ketch install owner/rtok --bin rtok-cli. It is stored in
state.json like a pick and reused on later upgrades. It fails when no binary in
the release has that name, and when the package's manifest already has a bin
(change that instead).
ketch uninstall <NAME>...
Remove installed packages. Names resolve like install (installed name,
binary, or owner/repo); a typo stops the command before anything is removed.
The package's whole store folder goes, including anything an interrupted
update left in it.
A name that is not installed prints <name>: not found and exits 4; every
missing name is listed and nothing is removed.
ketch uninstall rg
ketch uninstall fd ripgrep --yes # skip the confirmation
Aliased as ketch remove and ketch rm.
ketch upgrade [NAME]...
Upgrade installed packages to their latest release. Empty means every
unpinned package. Shows a from -> to table, asks, then installs.
Each version is unpacked into a fresh folder of its own, so nothing the old
version shipped can linger in the new one, and a leftover from an interrupted
upgrade is removed first — or the upgrade stops, naming it. The previous
version's folder is kept beside it for ketch rollback until ketch prune.
ketch upgrade # everything unpinned
ketch upgrade ripgrep fd # just these
ketch upgrade --dry-run # show the plan, change nothing
Options: --pre considers prereleases; --draft considers GitHub draft
releases too (a package installed with --draft does without it). A draft
that was published is an upgrade to the release under its tag; a draft that
was deleted is a warning. A package on a floating tag (channel: dev)
follows that tag: the tag naming another build is the upgrade, decided by the
asset's digest, or by when the release was published when the source gives
no digest; a newer version under another tag is not. --force upgrades pinned packages
too; --bin <NAME> (exactly one package) picks which binary to link when the
new release ships several sharing the package's name, as on install;
-j/--jobs <N>, -y/--yes. Pinned and local: packages are skipped unless
forced.
ketch rollback <PKG> [--to <VERSION>]
Switch a package back to a version still on disk. Without --to, restores the
previous retained version.
ketch rollback ripgrep
ketch rollback rg --to 14.1.0
ketch prune [NAME]... [--keep <N>]
Remove retained old versions according to the retention policy. Empty means
every installed package. --keep <N> updates the stored policy.
ketch prune
ketch prune ripgrep --keep 2
ketch pin <NAME>... / ketch unpin <NAME>...
Hold a package at its current version (pin), or release the hold (unpin).
Pinned packages are skipped by upgrade unless --force is passed.
ketch pin ripgrep
ketch upgrade --force # upgrades pinned packages too
ketch unpin ripgrep
ketch link <NAME>... / ketch unlink <NAME>...
Re-create (link) or remove (unlink) the bin-dir links for an installed
package. unlink keeps the payload installed; upgrade preserves the linked
state.
ketch unlink ripgrep # keep it, take it off PATH
ketch link ripgrep # put it back
ketch import winget|brew|linux <NAME> [--dry-run] [--yes]
Add a package another package manager already knows. ketch reads that
manager's definition, converts it to a user manifest in
~/.ketch/manifests/<name>.toml, and installs it the normal way, with the
asset and checksum the definition names.
ketch import brew codex # a Homebrew cask (or formula)
ketch import brew fly --cask # only look for a cask; --formula for a formula
ketch import winget BurntSushi.ripgrep.MSVC # a winget id, case-sensitive
ketch import linux lazygit # Arch Linux, then the AUR
ketch import linux obsidian --dry-run # print the manifest, change nothing
| Source | Where the definition comes from |
|---|---|
winget | the installer manifest of the newest version in winget-pkgs |
brew | the cask or formula JSON from formulae.brew.sh |
linux | the .SRCINFO of the Arch Linux package, or of the AUR's -bin/-appimage package when Arch builds it from source |
Only a package whose downloads are GitHub release assets
(https://github.com/<owner>/<repo>/releases/download/...) converts. A
download from anywhere else — a vendor's CDN, SourceForge, a source tarball,
a GitHub homepage with downloads hosted elsewhere, or a mix — writes
nothing and exits 1 with
<name> can't be converted: it is not distributed through GitHub Releases, and that is not supported yet.
So do installers ketch cannot run (.msi, .msix, Inno or NSIS .exe,
.deb, .rpm), cask artifacts beyond an app or binaries (pkg,
installer), and two files for one platform.
The manifest holds only what ketch needs: name, source, kind for an
app, bin, and one [asset.target] pattern per platform, with the version
replaced by * so it keeps matching. It starts with a
# Written by `ketch import …` line; a file of that name without it is
yours, and import refuses to replace it.
Running it again is safe: when the converted manifest and the installed
version are already what the source says, it prints
Everything is up to date and does nothing. A new version upstream rewrites
the file and upgrades; a changed manifest at the same version reinstalls.
The catalogue addresses can be pointed elsewhere (a mirror, or a test
double) with KETCH_IMPORT_BREW, KETCH_IMPORT_WINGET_API,
KETCH_IMPORT_WINGET_RAW, KETCH_IMPORT_ARCH, KETCH_IMPORT_ARCH_GITLAB and
KETCH_IMPORT_AUR. The winget listing goes through the GitHub API, so it uses
your GitHub token when one is set.
Inspect
ketch list
ketch list [local|remote] [--json] [--names-only] [--pre] [--draft], aliased as ketch ls.
Show what is installed, what the registry offers, or both in one table with the newest version of each.
| Command | Shows | Network |
|---|---|---|
ketch list local | Installed packages, from the install record | Never |
ketch list remote | Packages the registry offers, with their latest version | Needed; fails without it |
ketch list | Both, one row per package, sorted by name | Used for latest; without it, the local part |
"The registry" here is the local copy ketch update fetches, plus your own
manifests in ~/.ketch/manifests (yours win when a name is in both). The few
packages compiled into ketch as a fallback are not listed; run ketch update
to see the registry they come from.
Columns.
package— the name to install, upgrade or uninstall it by.installed— the installed version, followed by the channel it follows when that is not stable:(pre)for prereleases (installed with--pre, or from a prerelease tag),(draft)for GitHub drafts (installed with--draft),(dev)for a floating tag such asnightly; a package on the default stable channel carries no mark.(pinned)meansketch pinholds it;(+N retained)means N earlier versions are kept forketch rollback. Empty for a package that is not installed.latest— the newest release of the package's source.(update available)follows it when that is an update for the installed version.?means the source did not answer. Empty for a package installed from a local path, which has no upstream to ask.source— where the package comes from. For an installed package, that is where it was installed from, and where its next version will come from.description(remoteonly) — the registry's one-line summary, cut to the terminal width (COLUMNSsets another width; nothing is cut when the output is piped).
Markers. In ketch list, an installed package has * in the first column.
On a colour terminal the marker is ●, the name is bold, and
(update available) is yellow. CLICOLOR_FORCE=1 asks for colour even into a
pipe; --no-color and NO_COLOR turn it off.
Update available is decided by the same rule ketch outdated uses, for
every channel. latest is the newest release the package's source reports,
from the same lookup ketch outdated makes: stable releases only, unless
--pre is given, prerelease = true is set in config.toml or in the
package's manifest, or the package is installed on the pre channel; drafts
too with --draft or on the draft channel. That version is compared with
the installed one, and only a strictly newer version counts; a release with
the installed tag does not, with two exceptions. A package on the draft
channel is offered the release its draft was published as, under the same
tag, and a warning says so when that draft is gone. A package on the dev
channel is looked up under its own tag, and latest shows that tag; a new
build published under it is an update. A pinned package is never offered an
update.
Pinned packages are listed with both versions and (pinned), get no
(update available), and are left out of the footer. ketch unpin lets them
move again.
Packages from outside the registry — installed from owner/repo or
another scheme:id reference — are listed too, and their latest comes from
their own source. One installed from a local path (ketch install --path) is
listed with an empty latest.
Under the table, N updates available: ketch upgrade <names> names every
package with an update, as the command that takes them all.
Offline, and packages that do not answer. Latest versions are looked up in
parallel (jobs at a time, 4 by default), with a counter on stderr while they
load. A source that fails — rate-limited, gone, unreachable — shows ? in
latest, and one line under the table names each such package; every other row
is still printed and the command still succeeds. When no source answers at all,
the network is taken to be missing: ketch list prints the ketch list local
table followed by latest: offline and exits 0, while ketch list remote,
which has nothing to show without it, exits non-zero.
Answers are cached for 10 minutes in ~/.ketch/cache/latest.json, per source
and per channel asked (stable, pre, draft, or a dev package's own tag), so
listing twice in a row asks GitHub once. A cache file written by an older ketch
is ignored and replaced. Only
answers are cached, never failures. Delete the file to ask again sooner;
ketch outdated and ketch upgrade never read it.
--json prints, for each mode:
local— an array of{"name", "installed", "channel", "pinned", "retained", "source"}, withretainedthe list of versions kept for rollback andchannelthe release channel the install follows (stable,pre,draftordev).remote— an array of{"name", "latest", "description", "source"}, withlatestnullfor a source that did not answer.- no mode —
{"packages": [...], "unreachable": [...]}. Each package is{"name", "installed", "channel", "latest", "update_available", "pinned", "source"};installedandchannelarenullwhen it is not installed andlatestisnullwhen it is unknown.unreachablenames the packages whoselatestis unknown. Offline,packagesholds only installed packages.
--pre looks for prereleases when filling the latest column, for every
row, the way ketch outdated --pre does. It changes nothing in ketch list local, which asks no source.
--draft looks for GitHub draft releases too, and prereleases with them,
in the latest column of installed packages, the way ketch outdated --draft
does. Registry rows are left alone: drafts are visible only with a token that
has push access to the repository. A package whose source has no drafts is
asked without them, and one without such a token shows ?.
--names-only prints the names alone, one per line, for each mode; it never
touches the network.
Changed in 0.7. ketch list used to show installed packages only, and its
--json was an array of install records; it now shows everything, in the
shape above. Scripts that want the installed packages should call
ketch list local. ketch list --installed is a hidden alias of
ketch list local, kept for one release.
$ ketch list local
package installed source
fd v10.4.2 github:sharkdp/fd
ripgrep 14.1.1 github:BurntSushi/ripgrep
rtok v0.9.0 (pinned) github:pyrlyn/rtok
$ ketch list remote
package latest description
cox v0.1.0 Modular terminal coding agent
ketch v0.6.1 Catch releases straight from GitHub
ripgrep 15.2.0 Recursively search directories for a regex pattern
rtok v0.10.0 Reduce the context AI coding agents must carry
runa ? Run AI models locally (GGUF via llama.cpp) or through the OpenAI and Anthropic APIs
swarfr v0.1.0 Shrink Cargo target directories without slowing builds
? means the latest release could not be checked: runa
$ ketch list
package installed latest source
cox v0.1.0 github:pyrlyn/cox
* fd v10.4.2 v10.5.0 (update available) github:sharkdp/fd
ketch v0.6.1 github:pyrlyn/ketch
* ripgrep 14.1.1 15.2.0 (update available) github:BurntSushi/ripgrep
* rtok v0.9.0 (pinned) v0.10.0 github:pyrlyn/rtok
runa ? github:pyrlyn/runa
swarfr v0.1.0 github:listepo/swarfr
2 updates available: ketch upgrade fd ripgrep
? means the latest release could not be checked: runa
Without a network:
$ ketch list
package installed source
fd v10.4.2 github:sharkdp/fd
ripgrep 14.1.1 github:BurntSushi/ripgrep
rtok v0.9.0 (pinned) github:pyrlyn/rtok
latest: offline
$ ketch list remote
error could not reach any package source to check the latest versions; `ketch list local` works offline
ketch list local --json # installed packages, for scripts
ketch list --names-only # every package name, one per line
ketch list remote --json # the registry with latest versions
ketch outdated [--json] [--pre] [--draft]
Show installed packages that have a newer release. A source that cannot be
reached is a warning, not a failure — unless nothing could be checked at all.
--draft compares against GitHub draft releases too, as on upgrade. A
package on a floating tag is outdated when its tag names another build.
ketch outdated
ketch outdated --json # {"status","outdated","failed","unreachable"}
ketch info <PKG> [--assets] [--releases [--draft]] [--json]
Show details about a package, installed or not: source, description, latest and installed versions, links, retention, verification.
ketch info BurntSushi/ripgrep
ketch info rg --assets # every release asset with its score and why
ketch info rg --releases # the same table `ketch releases` prints, below
--releases adds the package's releases under the details, newest 20, in the
format of ketch releases, and --draft lists drafts among them as
ketch releases --draft does; with
--json they are the releases array. A source that cannot be reached is a
warning and the section is left out (null in JSON).
Aliased as ketch show.
ketch releases <PKG> [--pre] [--draft] [-n <LIMIT>] [--json]
List the releases a package's source has published, newest first as the source returns them, and mark the one that is installed. Needs the network.
$ ketch releases fd -n 3
tag version published kind
v10.5.0 10.5.0 2026-08-26 stable
* v10.4.2 10.4.2 2026-03-10 stable
v10.4.1 10.4.1 2026-03-08 stable
tagandversion— the release's tag and the version ketch reads from it and compares, without the tag's spelling (v10.4.2reads10.4.2). A tag that is not a version at all (nightly) has-for the version.published— the day the source says the release was published, or-.kind—stable;pre, for a release the forge flags as a prerelease or whose version has a prerelease part (2.0.0-rc.1);dev, for a tag that is not a version (a floatingnightly, even when it is also flagged prerelease);draft, for an unpublished GitHub release, listed only with--draftor for a package installed on thedraftchannel.- A
*in the first column (●on a colour terminal) marks the release the package is installed from, when it is among those listed.
Only stable releases are listed unless --pre is given, prerelease = true is
set in config.toml or the package's manifest, or the package is installed on
the pre or dev channel (GitHub flags a nightly as a prerelease); a repository that has never published a stable release lists
its prereleases anyway. --draft lists GitHub drafts too, and prereleases with
them; a package installed with --draft lists them without it. As with
ketch install --draft, that needs a token with push access to the repository
(KETCH_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN or github_token), and stops
naming what is
missing; other sources have no drafts and refuse it. -n (default 20, at least
- caps the list; a source may return fewer. An empty list prints
no releases.
--json prints an array of {"tag", "version", "published_at", "kind", "installed"}; version and published_at are null when unknown.
ketch releases ripgrep
ketch releases sharkdp/fd --pre --json
ketch why <PKG> [--json]
Explain how a package would be resolved, without installing it: which manifest tier answered, which release and asset were picked, and why.
ketch why sharkdp/[email protected]
ketch why rg --json
ketch changelog <PKG> [--latest] [--file] [--release]
Show what changed: the changelog file the package ships, or the release notes published with the release. Prefers the file on disk for the installed version; falls back to the notes.
ketch changelog ripgrep # installed version
ketch changelog ripgrep --latest # newest release instead
ketch changelog ripgrep --file # only the shipped file
ketch changelog ripgrep --release # only the published notes
ketch search <QUERY>... [-n <LIMIT>]
Search GitHub (and searching plugins) for installable repositories.
ketch search fuzzy finder
ketch search ripgrep -n 5
Reproduce
ketch lock [--file <FILE>] [--check]
Write ./ketch.lock from what is installed — the reproducible record of the
machine's tools, pinned to exact releases. See LOCKFILE.md.
ketch lock # write ./ketch.lock
ketch lock --check # has the tree drifted from it?
ketch lock -f tools.lock
ketch sync [--file <FILE>] [--prune] [--dry-run]
Install everything ketch.lock names, at the versions it names. A package the
lockfile does not mention is left alone unless --prune is passed (which asks
first, since it can lose work).
ketch sync # missing or drifted packages only
ketch sync --dry-run # show the +/~/− plan, change nothing
ketch sync --prune --yes # also remove extras, without asking
History
ketch history [PKG] [-n <LIMIT>] [--json]
Show what was installed, upgraded and removed, newest first. Omit the package for the whole tree in one timeline.
ketch history
ketch history ripgrep -n 10
ketch stats [--json]
Summarise everything ketch has recorded in stats.db.
ketch stats
ketch stats --json
Registry and sources
ketch update
Refresh the package registry into ~/.ketch/registry. (For installed
packages, see upgrade.)
ketch update
Runs automatically at the start of install and upgrade unless
auto_update is false in ~/.ketch/config.toml
(KETCH_AUTO_UPDATE=false).
ketch registry validate [DIR] [--fixture <DIR>] [--changed <NAME>] [--json]
Validate a registry tree the way the pre-push hook does: every ketch.toml parsed and
checked, plus name collisions. --fixture offline-installs entries against
local files as extra proof.
ketch registry validate
ketch registry validate ./ketch-registry --fixture ./fixtures
ketch registry status [--json]
Show the local registry copy's age and source, without fetching.
ketch registry status
ketch registry push [--file <FILE>] [--registry <REPO>] [--dry-run] [--yes]
Compare this project's ketch.toml with the registry's copy and open a pull
request with it. Opens straight away for a new package; shows a diff and asks
for an update; reports unchanged and opens nothing when identical. See
REGISTRY.md.
KETCH_GITHUB_TOKEN=... ketch registry push
ketch registry push --dry-run
ketch plugin list [--json] / ketch plugin dir
Show discovered source plugins (ketch-source-<scheme> in ~/.ketch/plugins
and on PATH), or print the plugins directory. See PLUGINS.md.
ketch plugin list
ketch plugin dir
Environment
ketch doctor [--fix] [--json]
Check the environment and the install tree: version, PATH setup, platform
checks, log, registry age, store against state.json. Exits non-zero when a
check fails. On Windows it also warns about user PATH entries that name a ketch
bin dir whose folder is gone — this root's, or any .ketch\bin.
ketch doctor
ketch doctor --fix # repair what can be repaired (the PATH setup)
ketch path [install|uninstall|status]
Put the ketch bin directory on PATH. Bare ketch path shows the status
table; that is the default subcommand.
ketch path # bin dir, PATH state, per-shell table
ketch path install # edit shell startup files (asks per shell)
ketch path install --print # print the line to add by hand
ketch path install --all # act on every known shell
ketch path uninstall # take the block back out again
ketch config create [--file <FILE>] [--force] [--yes]
Write a package config (ketch.toml) by answering questions — source, name,
bin entries, asset patterns — then preview and write the file. A package that
links binaries must name the command it puts on PATH, so the first bin entry
is asked for rather than offered; its name defaults to the package name.
Answers can be piped on stdin, one per line. See MANIFESTS.md.
ketch config create
ketch config create --file ./ketch.toml --yes
ketch config reset [--yes]
Write config.toml in the ketch root with the compiled defaults. Asks first
unless --yes; backs the existing file up beside itself as
config.toml.bak-<unix-seconds> unless it is missing or already matches a
sibling backup.
ketch config reset
ketch config reset --yes
ketch completions <SHELL> [--install]
Print a shell completion script, or install it into the shell's user
completion directory with --install.
ketch completions zsh > _ketch
ketch completions bash --install
The bash and PowerShell scripts also complete package names: installed ones after
uninstall, upgrade, pin, unpin, link, unlink, info, releases,
why, changelog and rollback, and names from the local registry copy after
install and search. It asks the binary for them with the internal
ketch __complete <installed|registry> [PREFIX], which reads the state file and
the registry already on disk and never touches the network. A --root earlier
on the command line is honoured.
--install writes the bash script to
${XDG_DATA_HOME:-~/.local/share}/bash-completion/completions/ketch, where
bash-completion 2 loads it on first use. On macOS that needs more than the
system shell: /bin/bash is 3.2 and bash-completion 2 wants bash 4.2 or newer.
Install a current bash and bash-completion 2 (with Homebrew:
brew install bash bash-completion@2), make that bash your login shell, and
source bash-completion's bash_completion from ~/.bashrc as its caveats
say. The script itself also runs under bash
3.2, so eval "$(ketch completions bash)" in ~/.bashrc works without either.
On Windows, --install (and ketch self install, which installs every
shell's script) also switches completion on, since neither shell loads a
completion directory by itself:
- PowerShell. The script goes to
Documents\PowerShell\Completions\ketch.ps1, and a block between# >>> ketch >>>and# <<< ketch <<<in the CurrentUserAllHosts profile of PowerShell 7 (Documents\PowerShell\profile.ps1) and Windows PowerShell 5.1 (Documents\WindowsPowerShell\profile.ps1) dot-sources it. Documents is the folder PowerShell reports, so a OneDrive redirect is followed. A profile that does not exist yet is created only when that edition is installed and its execution policy runs local scripts; otherwise ketch says why it left it alone. - cmd. cmd has no programmable completion, so it gets doskey macros:
ki(ketch install),ku(ketch upgrade),kl(ketch list) andkun(ketch uninstall), each passing its arguments on. They live in<root>\share\ketch\ketch.doskey, loaded bydoskey /macrofile="…"appended toHKCU\Software\Microsoft\Command Processor\AutoRunwith&after whatever AutoRun already runs.
ketch self uninstall takes the profile blocks out (deleting a profile that
held nothing else) and removes exactly its own command from AutoRun, leaving
the earlier value as it was, or deleting the value when it held only ketch's.
ketch itself
ketch self install [--force] [--link-dir <DIR>]
Install this release of ketch as a package, into the store and bin dir. What the curl/PowerShell/Homebrew installers run.
ketch self install
ketch self upgrade [--dry-run] [--force] [--pre] [--yes]
Upgrade ketch to the latest release. Aliased as ketch self update. A ketch
installed with mise and never self installed is mise's to upgrade: this
refuses, and names mise upgrade.
--pre takes the newest release, prereleases included, instead of GitHub's
latest release. The macOS app's desktop-v* releases are never taken. The
installers take the same flag: install.sh --pre and install.ps1 --pre.
Without it nothing changes.
ketch self upgrade
ketch self upgrade --dry-run
ketch self upgrade --pre
ketch self version
Print the running version and where it lives (target, root, binary, PATH).
ketch self version
ketch self uninstall [--keep-packages] [--dry-run] [--yes]
Remove ketch and everything it installed, permanently. Lists what it is about
to delete and asks first. --keep-packages removes only ketch. A ketch
installed with mise also asks whether to run mise unuse -g for its own copy;
--yes answers that too.
On Windows the running ketch.exe cannot delete itself, so the rest of the
root is removed by a background process once ketch has exited.
The root's own directories (bin, store, cache, …) are emptied only when
ketch created the root — it then holds a .ketch-root marker — or the root
is the default ~/.ketch. A root that already existed, such as ~/.local or
/usr/local, and the home directory itself keep everything ketch did not
record there.
On Windows it also removes what ketch wrote to the registry. Today that is
only the bin dir in the user PATH (HKCU\Environment\Path), written by
install.ps1 or ketch path install. The entry is matched however it is
spelled: case, quotes, / or \, a trailing separator, or an 8.3 short
name. --keep-packages leaves it, as it leaves the shell blocks, because the
packages still in the bin dir need it. ketch never registers itself in Apps &
Features, so there is no entry there to remove.
It also removes the PowerShell profile blocks and the cmd AutoRun addition
that switch completion on — those with --keep-packages too, since both
load ketch itself.
ketch self uninstall --dry-run
ketch self uninstall --keep-packages