Skip to content

ixt

ixt โ€” Universal CLI Tool Isolator

One CLI for Python, Node, and binary tools โ€” each in its own isolated env. Optional Linux runtime policy can restrict env vars and filesystem access per tool.

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

Work in Progress


๐Ÿš€ Get started in 30 seconds

# 1. Install ixt (pinned release, SSH-signed)
uv tool install git+https://gitlab.com/pytgaen-group/ixt.git@v0.7.0

# 2. Add ixt-managed shims to your PATH
ixt setup path

# 3. Install your first tool โ€” any ecosystem
ixt tool install ruff                        # Python
ixt tool install @anthropic-ai/claude-code   # Node
ixt tool install BurntSushi/ripgrep          # GitHub binary

That's it. ixt setup path supports bash, zsh, fish, and PowerShell. Each tool lives in its own isolated env; run ixt environment to see the exact config, install, and cache paths for your platform.

Full installation guide CI usage

ixt has no telemetry and no background network activity. It contacts registries only for explicit commands that resolve, download, upgrade, or diagnose remote state.


๐ŸŒŸ Three ecosystems, one command

ixt auto-detects the backend from the package name โ€” no flag, no config, no guessing.

Python tools from PyPI

Simple name โ†’ PyPI. ixt creates one isolated venv per tool with uv venv + uv pip install.

ixt tool install ruff
[INFO]   + ruff 0.5.0  (id: ruff.pypi)
[INFO]     exposed: ruff
$IXT_HOME/installed/envs/ruff.pypi/
โ”œโ”€โ”€ .venv/                   # isolated Python env (uv)
โ”‚   โ””โ”€โ”€ bin/ruff
โ””โ”€โ”€ ixt.json                 # metadata snapshot

Python backend details


Node CLIs from npm

Scoped @scope/name โ†’ npm. Uses bun for fast installs (falls back to npm).

ixt tool install @biomejs/biome
[INFO]   + @biomejs/biome 1.9.4  (id: biome.biomejs.npm)
[INFO]     exposed: biome
$IXT_HOME/installed/envs/biome.biomejs.npm/
โ”œโ”€โ”€ node_modules/            # isolated node_modules (bun)
โ”‚   โ””โ”€โ”€ .bin/biome
โ””โ”€โ”€ ixt.json

Node backend details


Binaries from GitHub Releases

owner/repo โ†’ GitHub Releases. Pure Python stdlib โ€” no runtime, no compiler.

ixt tool install sharkdp/fd
[INFO]   + sharkdp/fd 10.2.0  (id: fd.sharkdp.github)
[INFO]     exposed: fd
$IXT_HOME/installed/envs/fd.sharkdp.github/
โ”œโ”€โ”€ bin/fd                   # extracted binary
โ”œโ”€โ”€ man/fd.1
โ””โ”€โ”€ ixt.json

Binary backend details


Declarative, repeatable setups

Snapshot your tools once, replay them everywhere โ€” local, teammates, CI. Exact repeatability comes from exact version pins; unpinned or ranged entries are resolved when ixt tool apply runs.

ixt tool export > ixt.toml
[tools]
"@pypi:ruff" = { version = "==0.5.0" }
"@npm:@biomejs/biome" = {}
"@gh:BurntSushi/ripgrep" = { expose = ["rg:ripgrep"] }
ixt tool apply              # installs what the config declares
ixt tool apply --remove     # also removes anything not listed

Configuration reference


Runtime policy โ€” one step further

Dependency isolation keeps each tool's packages separate. Runtime policy goes deeper: it controls which environment variables and filesystem paths a tool can access when launched through ixt shims. It does not sandbox install-time package-manager scripts, it does not block network access, and it is not a general malware sandbox. If the install step itself is untrusted, use a disposable VM/container/user.

# Only OS vars pass through โ€” no AWS keys, no GH_TOKEN
ixt tool config ruff env base os-common
ixt tool config ruff env allow '*RUFF*'
# Read-only everywhere except cwd โ€” secrets hidden
ixt tool config ruff fs base app-common
ixt tool config ruff fs scratch ~/.aws ~/.ssh
[tools.ruff]
env_base   = "os-common"
env_allow  = ["*RUFF*"]
fs_base    = "app-common"
fs_scratch = ["~/.aws", "~/.ssh"]

No daemon. The shim is a plain Python file you can read and audit; enforcement is delegated to bubblewrap when env/fs policy needs kernel support. When you reset the policy, it goes back to a direct symlink โ€” zero overhead.

Linux only for now

Enforcement relies on POSIX execve and Linux namespaces. On macOS / Windows the policy is saved to ixt.json but not enforced at runtime โ€” the tool runs with the full environment.

The fs axis additionally requires bubblewrap: sudo apt install bubblewrap ยท sudo dnf install bubblewrap ยท sudo pacman -S bubblewrap ยท sudo apk add bubblewrap. Without bubblewrap, the env axis is hygiene-only: the filtered env reaches the process, but /proc can still expose the parent environment.

Policy reference ยท Real-world scenarios


โœจ Why ixt?

  • One tool, every ecosystem


    Python linters, Node CLIs, Rust/Go/C binaries โ€” all managed the same way, with the same commands.

  • Per-tool isolation


    Each tool gets its own env. No dependency conflicts, ever. Uninstall is a clean rm -rf.

  • Runtime policy


    Restrict env vars and filesystem paths per tool on Linux. Effective filesystem policy requires bubblewrap; network isolation is roadmap.

    Policy reference

  • Zero configuration


    The backend is auto-detected from the package name. ixt tool install <anything> just works.

  • Zero dependencies


    Pure Python stdlib, zero PyPI packages. bun auto-bootstraps on first Node install โ€” uv is typically already there (you used it to install ixt), with an auto-download fallback if missing.


Where to next?

  • Getting started


    Install ixt, verify the signature, add it to PATH, install your first tool.

    Installation guide

  • Commands reference


    Every ixt command, every flag, with copy-paste examples.

    Command reference

  • Configuration


    ixt.toml format, version pinning, exposure rules, the mental model.

    Configuration guide


Coming from uvpipx?

ixt is the successor to uvpipx. Same core concepts (isolation, exposure, injection), generalized across three backends. Directory layout, metadata, and CLI all evolved โ€” a migration script is provided.

Migration guide