Skip to main content

ixt

ixt — Universal CLI Tool Isolator

Release Build: GitLab CI PyPI PyPI Downloads License: MIT Python 3.10+

Work in Progress

One CLI for Python, Node, and binary tools — each in its own isolated env.

Zero third-party deps. Zero system pollution. One command, any ecosystem.

  • Day-one GitHub releases — install a tool the day it ships, without waiting for a formula, registry entry, or plugin.
  • No system runtime needed — ixt is pure Python stdlib; uv and bun are bootstrapped on first use, so the host does not need Node, npm, or a package manager pre-installed.
ixt tool install ruff                      # Python (PyPI)
ixt tool install @anthropic-ai/claude-code # npm package via bun
ixt tool install ripgrep                   # Binary (GitHub — via built-in registry)

Each tool gets its own isolated environment. Only the binaries you choose are exposed to your PATH.

📥 Install

From PyPI. The published package is ixt-cli; it installs the ixt command.

# One-shot via uvx (requires uv)
uvx --from ixt-cli ixt --help

# Persistent install via uv tool
uv tool install ixt-cli

Or from source:

git clone https://gitlab.com/pytgaen-group/ixt.git && cd ixt
uv tool install -e .

Then add $IXT_HOME/installed/bin to your PATH:

ixt setup path

Integrity verification

Release tags are SSH-signed. Installing from PyPI does not verify the Git tag signature locally. Use the clone flow when you want to verify a signed release before installing:

# Verify the signed tag (requires the maintainer's SSH public key in git's allowed_signers)
git clone https://gitlab.com/pytgaen-group/ixt.git && cd ixt
git fetch --tags
git verify-tag vX.Y.Z
git checkout --detach vX.Y.Z
uv tool install .

A valid tag signature means the checked-out source matches the maintainer-signed release tag.

🚀 Quick Start

# Install tools from 3 ecosystems
ixt tool install ruff                        # Python linter
ixt tool install @google/gemini-cli          # Node CLI
ixt tool install sharkdp/fd                  # GitHub binary

# List installed tools
ixt tool list
#  ruff          0.5.0   pypi     [ruff]
#  gemini-cli    0.1.12  npm      [gemini]
#  fd            10.2.0  github   [fd]

# Upgrade
ixt tool upgrade ruff
ixt tool upgrade --all

# Uninstall
ixt tool uninstall fd

⚙️ How It Works

ixt auto-detects the backend from the package name:

Format Backend Example
name PyPI (Python) ruff, mypy, httpie
@scope/name npm (Node) @google/gemini-cli
owner/repo GitHub Releases BurntSushi/ripgrep

Each tool is installed in its own isolated environment ($IXT_HOME/installed/envs/<tool>/), and only the requested binaries are exposed in $IXT_HOME/installed/bin/.

For GitHub Releases, ixt learns each tool's asset-URL template on the first install and caches it in $IXT_CACHE_HOME/metadata/asset_patterns.json. Subsequent installs and upgrades resolve the latest tag via a plain 302 on github.com/.../releases/latest and download directly from the CDN — zero calls to api.github.com, no rate limit, no token required. If a maintainer ever renames their release assets, the cache entry is auto-invalidated and ixt falls back to the full release API to relearn.

Force a backend

Use namespace prefixes:

ixt tool install @pypi:ruff
ixt tool install @npm:prettier
ixt tool install @gh:BurntSushi/ripgrep

📚 Built-in Registry

ixt ships with a built-in registry that maps common tool names to their source. No need to remember the GitHub path:

ixt tool install ripgrep    # resolves to @gh:BurntSushi/ripgrep
ixt tool install fd         # resolves to @gh:sharkdp/fd
ixt tool install bat        # resolves to @gh:sharkdp/bat
ixt tool install lazygit    # resolves to @gh:jesseduffield/lazygit

The registry currently includes 50+ popular tools (ripgrep, fd, bat, fzf, jq, delta, starship, zellij, helix, nushell, etc.). For a simple name, ixt checks the registry first and falls back to PyPI when no registry entry matches.

You can add your own entries in $IXT_HOME/config/registry.toml:

[tools]
mytool = "@gh:owner/repo"

For team/project overlays, point IXT_REGISTRY at one or more local registry files separated by ;:

export IXT_REGISTRY="/org/registry.toml;/project/registry.toml"

📌 Version pinning

ixt tool install sharkdp/fd@10.2.0          # exact version
ixt tool install sharkdp/fd@10              # latest 10.x.x
ixt tool install ruff>=0.5.0                # PEP 508 (Python)

🔒 Declarative locks

ixt.toml is the human-edited intent: which tools you want, with optional version bounds, exposure rules, and injections. ixt.lock is generated from that intent and records the exact resolved versions and binary release assets.

For teams and CI, commit both files:

ixt lock write
ixt lock check
ixt tool apply --locked --strict

--locked replays the exact lock instead of resolving newer versions. --strict fails before changing the machine if ixt.toml and ixt.lock diverge. The strict preflight is local: it checks the manifest fingerprint, declared policy, version constraints, and locked binary metadata without contacting PyPI, npm, GitHub, or GitLab. Run ixt lock write when you want to resolve upstream again and refresh the lock.

🧰 Commands

Command Description
ixt tool add <pkg> Add a tool to ixt.toml without installing
ixt tool install <pkg> Install a tool in isolation
ixt tool install <pkg> --bare Install the env without exposing any binary
ixt tool uninstall <pkg> Remove a tool
ixt tool list List installed tools
ixt tool info <pkg> Show tool details
ixt tool upgrade <pkg> Upgrade a tool
ixt tool upgrade --all Upgrade all tools
ixt tool apply Sync tools from declarative config
ixt tool apply --locked --strict Sync using exact versions and assets from ixt.lock
ixt tool export Export installed tools as ixt.toml (stdout), preserves install intent
ixt lock write Resolve ixt.toml and write ixt.lock
ixt lock check Validate ixt.lock against ixt.toml locally
ixt lock diff Show semantic differences between ixt.toml and ixt.lock
ixt asset-index export Export portable binary-resolution metadata as JSON
ixt tool config <pkg> expose <rules...> Change exposed binaries
ixt tool config <pkg> inject <dep> Inject a package into the tool's env
ixt tool config <pkg> uninject <dep> Remove an injected package
ixt tool config __all__ expose <rules...> Re-expose every installed tool
ixt tool shell <pkg> Open a subshell in tool's env
ixt tool where <pkg> Print the tool env path
ixt environment [--sizes] Show ixt configuration, paths, and optional storage sizes
ixt doctor Check ixt health (runtimes, PATH, caches)
ixt cache info Show cache paths and sizes
ixt cache prune Keep current + previous indexed download artifacts per repository
ixt cache clear {downloads,metadata,tmp,all} Wipe cache(s); never touches installed tools
ixt runtime info Show ixt-managed runtime state
ixt runtime prune [--all] Remove unused or all ixt-managed runtimes
ixt setup path Add $IXT_HOME/installed/bin to PATH
ixt setup completions --shell zsh Print shell completion code for ixt

🏗️ Architecture

$IXT_HOME/                # default ~/.local/share/ixt (respects $XDG_DATA_HOME)
├── config/
│   ├── ixt.toml          # global declarative manifest fallback
│   ├── ixt.lock          # global lock when using the global ixt.toml
│   ├── registry.toml
│   └── heuristics.toml
└── installed/
    ├── bin/              # PATH-exposed shims
    ├── envs/             # isolated environments
    │   ├── ruff/         #   Python venv
    │   ├── gemini-cli/   #   Node node_modules
    │   └── ripgrep/      #   extracted binary
    └── runtimes/         # auto-bootstrapped: uv, bun

$IXT_CACHE_HOME/          # default ~/.cache/ixt (respects $XDG_CACHE_HOME)
├── downloads/            # downloaded archives and runtime payloads
├── metadata/             # resolve cache, asset templates, downloads index
└── tmp/                  # ixt-owned temporary files

Zero dependencies. ixt uses Python stdlib only — no PyPI packages. bun is auto-downloaded on first Node install. uv is typically already on your PATH (you used it to install ixt), with an auto-download fallback to $IXT_HOME/installed/runtimes/uv if missing.

📊 How ixt compares

uv tool pipx npm -g aqua mise proto ixt
Python tools (PyPI) ✅ (pipx)
npm packages ✅ (npm)
GitHub Releases binaries ✅ (ubi) ~
Day-one GitHub releases ~
Dependency isolation partial
Fine-grained exposure
No system runtime needed
Declarative config YAML TOML TOML TOML

ixt is not a runtime version manager (mise, proto, asdf cover that). It manages the last mile: install, isolate, expose and group CLI tools across three ecosystems.

🛠️ Development

git clone https://gitlab.com/pytgaen-group/ixt.git && cd ixt
uv sync --group dev

uv run pytest                 # hermetic unit suite
uv run ruff check src/ tests/ # lint
uv run ruff format src/ tests/ # format

🤝 Contributing

Development happens on GitLab: https://gitlab.com/pytgaen-group/ixt. Any GitHub repository for this project is a read-only mirror of GitLab; it is not the review or issue tracker. Please open issues and merge requests on GitLab.

Bug reports and reproduction recipes are welcome. See CONTRIBUTING.md for details, or open an issue to start a discussion.

📄 License

MIT. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ixt_cli-0.9.1.tar.gz (292.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ixt_cli-0.9.1-py3-none-any.whl (200.9 kB view details)

Uploaded Python 3

File details

Details for the file ixt_cli-0.9.1.tar.gz.

File metadata

  • Download URL: ixt_cli-0.9.1.tar.gz
  • Upload date:
  • Size: 292.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for ixt_cli-0.9.1.tar.gz
Algorithm Hash digest
SHA256 a0c618418d595de1822f2e3f949291c7bfd84666fce60157443ae7ed5e253453
MD5 fcafd10c514050a5676f82d793dd81d5
BLAKE2b-256 e299b7658349486a37605bd923780a0eb3dee2028711fe9984dbff796ccb0629

See more details on using hashes here.

File details

Details for the file ixt_cli-0.9.1-py3-none-any.whl.

File metadata

  • Download URL: ixt_cli-0.9.1-py3-none-any.whl
  • Upload date:
  • Size: 200.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for ixt_cli-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 87fd2fb9b01666983f5bb322a6fb8ed2125d2d6e89ca7322235f71438410d30a
MD5 199965fa10dc2303e57300b16076a805
BLAKE2b-256 dc324cb967b6d52fff22def6f396fd6a1fd4fcec0bbac7fcbf2f65751c54a00c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page