Commands¶
Every
ixtcommand, every flag, copy-paste ready.
Tool Targets¶
Commands that operate on an already installed tool use a <target> selector:
| Form | Meaning |
|---|---|
<spec> |
User-facing install spec, such as ruff, mikefarah/yq, @scope/pkg |
@id:<installed-id> |
Exact installed id, such as @id:yq.mikefarah.github |
<id-prefix> |
Short id prefix, such as yq or yq.mikefarah, only if unambiguous |
Use @id:<installed-id> when two installed tools would otherwise match the
same short spec or id prefix.
Global Flags¶
| Option | Description |
|---|---|
-v / --verbose |
Increase diagnostic output. Repeat as -vv for per-package resolver traces |
Global verbosity can be placed before the command:
For upgrade, it can also be placed after the subcommand:
ixt tool list -v is the exception: there, -v means "show exact installed ids",
not global resolver diagnostics.
tool add¶
Add a tool to ixt.toml without installing it.
tool add only edits the declarative manifest. It does not install tools, does
not touch ixt.lock, and does not query package registries. Simple names use
the local registry first, then fall back to PyPI.
| Option | Description |
|---|---|
--bare |
Persist the tool without exposing any binary (expose = []) |
--slot <slot> |
Persist as a side-by-side slot. Writes <slot> = { install = "..." } |
--runtime <mode> |
Runtime for npm packages. bun-strict writes node_shim = false; node writes runtime = "node" |
--asset-pattern <PATTERN> |
Persist a forced binary asset pattern. Supports {version}, {tag}, {os}, {arch} placeholders |
ixt tool add ruff
ixt tool add @biomejs/biome --runtime node
ixt tool add ruff==0.5.7 --slot ruff-old --bare
ixt tool add BurntSushi/ripgrep \
--asset-pattern 'ripgrep-{version}-{os}-{arch}.tar.gz'
tool install¶
Install a tool in isolation.
| Option | Description |
|---|---|
--from <path> |
Install from a local directory (auto-detected backend). Mutually exclusive with <package>. See Local installs below |
--bare |
Install the env without exposing any binary (configure later with ixt tool config) |
--reinstall |
Reinstall if the tool is already installed |
--slot <slot> |
Install into a side-by-side slot. The installed id becomes <slot>.<base-id> |
--runtime <mode> |
Runtime for npm packages — see Runtime modes below |
--asset-pattern <PATTERN> |
Force the asset selection pattern (binary backend only). Supports {version}, {tag}, {os}, {arch} placeholders |
--save |
Add tool to ixt.toml |
--dry-run |
Print the install plan (backend, spec, env_dir, expose) without installing — no network, no disk writes |
Install, reinstall, and upgrade mutations are serialized per installed tool.
On a handled failure, ixt restores the previous environment, metadata, and
shims; a first install leaves no partial environment or dangling shim. This is
an exception rollback, not a health check after a successful commit and not a
journal for power loss or SIGKILL.
Post-install configuration (expose, inject, uninject) goes through ixt tool config.
Runtime modes¶
| Mode | Behavior |
|---|---|
bun (default) |
Uses bun, rewrites #!/usr/bin/env node shebangs to bun so the host doesn't need node installed |
bun-strict |
Uses bun without rewriting shebangs — host must have node available |
node |
Uses node natively, no bun involved |
Only applies to npm packages; ignored for python and binary backends.
See also: Recipes → side-by-side versions.
Local installs¶
ixt tool install --from <path> installs a tool from a local directory. The backend is auto-detected from the directory contents:
| Marker file | Backend selected |
|---|---|
pyproject.toml / setup.py |
python — uv pip install <path> in an isolated venv |
package.json |
node — bun add <path> in an isolated node_modules |
| (none of the above) | binary — copy directory contents to env, auto-expose binaries |
ixt tool install --from ./my-tool # id = directory basename
ixt tool install --from ./my-tool --slot myalias # id = myalias.my-tool
ixt tool install --from /tmp/repro-bug --reinstall # reinstall over existing env
Local installs are recorded with version="local" and source="local". They are autonomous copies — moving or deleting the source path after install does not break the tool.
Lifecycle differences vs. registry installs:
ixt tool exportskips local installs (not reproducible cross-machine, so they don't appear inixt.toml).ixt tool applyignores them (no entry inixt.tomlto reproduce).ixt tool upgraderefuses local installs and points back toixt tool install --from <path> --reinstallto update.
Use cases: developing an ixt-installable tool before its first release, local fork of a published tool for debugging, reproduction fixtures shared in bug reports.
tool uninstall¶
Remove an installed tool.
| Option | Description |
|---|---|
--all |
Remove all installed tools |
--save |
Remove tool from ixt.toml |
--yes / -y |
Skip the confirmation prompt for --all |
--dry-run |
Print what would be removed (env directory + shims) without touching anything |
ixt tool uninstall ruff
ixt tool uninstall @id:old.ruff.pypi # exact installed id
ixt tool uninstall --all # prompts before removing everything
ixt tool uninstall --all --yes # non-interactive / recovery scripts
ixt tool uninstall ruff --dry-run # preview
To remove an injected package from a tool, use ixt tool config <target> uninject <pkg>.
tool list¶
List installed tools.
tool info¶
Show details about an installed tool.
Displays: spec label, exact installed id, version, backend, exposed binaries, and environment path.
tool upgrade¶
Upgrade an installed tool, respecting any constraint declared in ixt.toml.
ixt tool upgrade <target>
ixt tool upgrade @id:old.ruff.pypi
ixt tool upgrade --all
ixt tool upgrade <target> --dry-run # resolve latest, print, no side effects
ixt tool upgrade --all --no-cache # bypass the latest-version TTL cache
ixt tool upgrade --all -v # print a compact resolution summary
ixt tool upgrade --all -vv # add per-package resolver/API traces
| Option | Description |
|---|---|
--all |
Upgrade every installed tool |
--dry-run |
Resolve latest versions and print old → new without installing |
--no-cache |
Ignore the resolve cache and force a fresh upstream latest-version check |
Shows the version change (e.g., 0.5.0 → 0.6.0) or indicates the tool is already up-to-date.
With --all, progress is printed as each tool finishes ([i/N] name: state)
instead of waiting for the whole batch to complete.
The final --all footer reports the cache state when the latest-version TTL
cache is active; use --no-cache when you need a fresh check now.
-v adds a final resolver summary for latest-version lookups:
[INFO] resolution: version: GitHub latest redirect 38/38 hit, 0 GitHub API calls, 1 GitLab API call, 1 PyPI registry call, 2 npm registry calls
The GitHub latest redirect count is the cheap
github.com/.../releases/latest redirect path. GitHub API calls are counted
separately, so 0 GitHub API calls means no api.github.com release endpoint
was needed during version resolution. Cache hits are not counted as upstream
calls. -vv adds per-package debug lines for the same resolver activity.
Behavior with ixt.toml
version = "==X.Y.Z"— upgrade is refused; the latest upstream version is shown as info so you can decide whether to bump the pin.- Range (
">=1.0,<2.0","~=1.2", …) — the range is forwarded to the backend so the resolved version stays in-bounds. - No version declared — upgrades to latest, as expected.
tool apply¶
Sync installed tools with an ixt.toml file. The toml is the source of truth; apply makes reality match it.
| Option | Description |
|---|---|
--remove |
Also uninstall tools not listed in the file |
--yes / -y |
Skip the y/N confirmation before removals (non-interactive / CI) |
--dry-run |
Print the plan (install / reinstall / inject / reexpose / remove) without touching anything |
--locked |
Install exact versions and binary assets from ixt.lock instead of resolving from registries |
--strict |
With --locked, fail before changes if ixt.toml and ixt.lock diverge |
ixt tool apply # reads ./ixt.toml
ixt tool apply team.toml # reads a specific file
ixt tool apply --dry-run # preview the diff
ixt tool apply --remove # prompts before destroying anything
ixt tool apply --remove --yes
ixt tool apply --locked --strict # exact replay from ixt.lock
ixt.toml keys are written for humans and resolved to installed ids when
applying:
[tools]
"@pypi:ruff" = {} # target id: ruff.pypi
old = { install = "@pypi:ruff", version = "==0.5.0" } # target id: old.ruff.pypi
How drift is detected and fixed
| Drift | Action |
|---|---|
| Tool missing | install |
Version pinned == and differs, or outside declared range |
reinstall from the declared spec |
| Inject list differs only | inject / uninject delta (env is not wiped) |
| Expose rules differ only | re-link shims (cheap) |
Installed tool not listed, with --remove |
uninstall (after confirmation) |
--locked reads ixt.lock next to the selected ixt.toml and materializes
the exact versions recorded there. For binary tools, it also reuses the locked
release asset URL and platform metadata instead of re-running asset selection.
Use --strict in CI and team bootstrap scripts. It first performs the same
local comparison as ixt lock check; if the manifest changed, a
locked version violates its declared constraint, the lock is missing, or the
lock cannot be parsed, apply exits before installing or removing anything.
This preflight does not query PyPI, npm, GitHub, or GitLab.
lock¶
Manage ixt.lock, the generated exact-resolution lockfile for the effective
ixt.toml.
| Command | Description |
|---|---|
lock write |
Resolve the effective ixt.toml and write a deterministic ixt.lock |
lock check |
Locally validate that ixt.lock matches ixt.toml; never resolve upstream |
lock diff |
Print local semantic differences between the manifest and existing lock |
ixt.lock is a machine-written TOML file. Commit it with ixt.toml when you
want reproducible installs across machines or CI jobs. Do not edit it by hand:
change ixt.toml, then run ixt lock write again.
lock write resolves packages but does not install tools or modify
ixt.toml. The lock records the manifest fingerprint, exact resolved versions,
exposure/injection policy, and binary release asset metadata when relevant.
lock check and lock diff reuse those recorded resolutions: run lock write
again when you explicitly want to discover newer upstream releases.
tool export¶
ixt tool export writes installed tools as ixt.toml on stdout. Unlike a raw
snapshot, it preserves each tool's original install intent: the version
constraint is whatever you gave at install time (range, exact pin, or nothing),
so the produced toml stays truthful to what you declared instead of
force-pinning every tool to its currently-resolved patch version. Generated
entries use explicit backend prefixes such as @pypi:ruff and
@npm:@openai/codex.
ixt tool export # all installed tools
ixt tool export > ixt.toml # redirect to a file
ixt tool export ruff @id:bat.sharkdp.github # subset by target selector
asset-index export¶
Export portable binary-resolution metadata.
ixt asset-index export > asset_index.json
ixt asset-index export --from-registry src/ixt/data/registry.toml --all-platforms
ixt asset-index export writes GitHub binary-resolution metadata from the local
cache. --from-registry generates pattern entries from a registry.toml by
calling GitHub Releases during generation. Without --from-registry,
--all-platforms warns and exports only current-platform cache metadata.
registry list¶
List registry short names and their canonical install specs.
The registry is local resolution metadata only: it maps names such as
ripgrep to specs such as @gh:BurntSushi/ripgrep. It does not contain asset
patterns, checksums, exposure rules, or descriptions.
tool config¶
Change settings on an installed tool — exposure rules and injected packages.
tool config never writes to ixt.toml; use
tool apply + ixt.toml for the declarative path, or
tool export to snapshot the current state.
| Action | Purpose |
|---|---|
expose <rules...> |
Replace the tool's exposure rules and re-link its shims |
inject <pkg> |
Install a package into the tool's isolated env |
uninject <pkg> |
Remove a previously injected package |
env <action> |
Draft/WIP runtime-policy command — base, allow, deny, list, reset (status) |
fs <action> |
Draft/WIP runtime-policy command — base, ro, rw, scratch, list, reset (status) |
Exposure & injection¶
ixt tool config ruff expose __all__
ixt tool config httpie expose http https
ixt tool config ripgrep expose rg:ripgrep
ixt tool config httpie inject rich # pull rich into httpie's venv
ixt tool config httpie uninject rich
Use __all__ as the tool name to apply an expose rule to every installed tool at once:
__all__ is only valid with the expose action. Both sides of an explicit
original:alias rule must be portable single-file names. Paths, ./..,
separators, Windows device names, and control characters are rejected before
any existing shim is changed.
environment¶
Show ixt configuration and paths.
--sizes adds a storage summary for config, installed tools, runtimes, and
cache subdirectories. It is read-only.
runtime¶
Inspect and prune ixt-managed runtimes under
$IXT_HOME/installed/runtimes/.
ixt runtime info
ixt runtime prune
ixt runtime prune --all
ixt runtime upgrade uv
ixt runtime upgrade bun
ixt runtime upgrade all
inforeports known ixt-managed runtimes (uv,bun), their paths, size, version when readable, and whether they are currently considered used.pruneremoves unused ixt-managed runtimes.uvis prunable after Python tools are installed because Python tool shims do not execute throughuv.bunis kept when an installed Node tool may run through the managed bun binary.prune --allremoves every known ixt-managed runtime. Use it only when the final image or host does not need those managed runtimes at execution time.upgrade <uv|bun|all>installs or replaces ixt-managed runtimes. This is the repair path printed byixt doctorwhen the manageduvorbunruntime is missing, broken, or behind the latest available release.
This command never touches $IXT_HOME/installed/envs,
$IXT_HOME/installed/bin, $IXT_HOME/config, or $IXT_CACHE_HOME.
Later installs or upgrades can bootstrap missing runtimes again from cache or
network as needed.
cache¶
Inspect and clean regenerable cache content.
ixt cache info
ixt cache prune
ixt cache prune --keep 3
ixt cache clear downloads
ixt cache clear metadata
ixt cache clear tmp
ixt cache clear all
infoshows$IXT_CACHE_HOMEplusdownloads/,metadata/, andtmp/sizes.pruneremoves old indexed download artifacts and keeps the newest two per repository by default: current + previous. Unindexed files are left alone.cleardeletes the selected cache subtree. It never touches$IXT_HOME/config,$IXT_HOME/installed/envs,$IXT_HOME/installed/bin, or$IXT_HOME/installed/runtimes.
The download index lives in $IXT_CACHE_HOME/metadata/downloads.json. Binary
release downloads record their forge, repo, tag, normalized version, asset name,
URL, local path, cache identity, and download timestamp. Since 0.9.1, the
physical cache key includes the release tag and exact URL, so two releases may
safely reuse the same asset filename. Legacy flat entries are never reused;
cache prune removes indexed legacy files and cache clear downloads purges
all remaining unindexed downloads.
tool shell¶
Open a subshell in a tool's environment directory — not activated (no PATH patch, no venv activate, no NODE_PATH). Binaries must be called by explicit path.
tool where¶
Print the absolute path to a tool's environment directory. This command is stdout-only on success, so it is safe in scripts.
doctor¶
Check ixt health and environment.
Reports:
- OS, architecture, detected shell, and Python runtime
- PATH configuration in the current shell
- Shell init configuration in the right file for the detected shell
- Home directory structure
$IXT_HOMEwritability and available disk space- Install mode — detects whether ixt was installed via
uv tool,pipx, orpip --user, and prints the matching upgrade command. Multiple modes detected → flagged as ambiguous; not detected → likely a dev install - ixt-managed runtimes (
uv,bun): local version, latest release when network checks are enabled, and the exact upgrade command (ixt runtime upgrade <name>) - system runtimes (
uv,bun) on PATH. If one is too old or broken,doctorsuggests the tool's self-upgrade command (uv self update,bun upgrade) plus the ixt-managed alternative - GitHub token status
- GitHub, PyPI, and npm registry connectivity by default. Use
--no-networkto skip these probes and latest-runtime lookups - Installed tools count
- Pattern cache — number of learned GitHub asset patterns and its on-disk path
- Downloads cache — size of
$IXT_CACHE_HOME/downloads/(downloaded archives and runtime archives)
Cache mutation is intentionally outside doctor. Use ixt cache info,
ixt cache prune, or ixt cache clear <target> for operational cache work.
setup path¶
Add $IXT_HOME/installed/bin to your shell PATH.
ixt setup path
ixt setup path --check # just check, don't modify
ixt setup path --shell pwsh # override shell detection
Detects your shell from $SHELL and writes a guarded, idempotent block to the right config file:
| Shell | Target file |
|---|---|
bash |
~/.bashrc |
zsh |
~/.zshenv (covers interactive and non-interactive shells) |
fish |
~/.config/fish/conf.d/ixt.fish |
pwsh |
~/.config/powershell/profile.ps1 (Documents/PowerShell/profile.ps1 on Windows) |
The new block prepends $IXT_HOME/installed/bin (so ixt shims shadow same-named binaries elsewhere on PATH) and is guarded by a directory check so the block is a no-op after uninstall. Re-running is safe — repeats are detected and skipped. Old single-line ixt blocks are migrated automatically when their content matches; divergent blocks are left in place with a warning. If the target file is a symlink (Nix, home-manager, chezmoi), setup path refuses to write and prints the snippet to apply manually.
setup completions¶
Print a shell completion script for the ixt CLI.
eval "$(ixt setup completions --shell zsh)"
eval "$(ixt setup completions --shell bash)"
ixt setup completions --shell fish | source
Supported shells: bash, zsh, fish.
The script is generated from ixt's own argparse command tree, so commands,
subcommands, options, fixed choices, and file/directory hints stay aligned with
the CLI parser. Zsh and fish also receive descriptions from the parser help
text. This is for completing the ixt command itself; it does not install
third-party tool completion files.