Skip to content

Isolation in depth

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

ixt's core promise: every tool gets its own dependency environment under $IXT_HOME/installed/envs/<installed-id>/. Python packages, node_modules, and extracted binary archives are not shared between tools, and uninstall is a clean delete of that env plus its shim.

This is dependency isolation, not a runtime security boundary by itself. A tool with no runtime policy still runs with your normal user permissions, environment and filesystem access. Use runtime policy when you also want to restrict what the process can see at execution time.


What isolation looks like

$IXT_HOME/installed/envs/ruff.pypi/
├── .venv/
│   ├── bin/
│   │   ├── ruff          ← the real binary
│   │   └── python        ← venv python, not the system one
│   └── lib/python3.x/site-packages/
└── ixt.json              ← metadata snapshot

One venv per tool. ruff's dependencies are invisible to mypy's, and vice versa.

$IXT_HOME/installed/envs/biome.biomejs.npm/
├── node_modules/
│   ├── .bin/biome        ← the real binary
│   └── @biomejs/biome/
└── ixt.json

One node_modules/ per tool. No global pollution.

$IXT_HOME/installed/envs/fd.sharkdp.github/
├── bin/
│   └── fd                ← extracted binary
├── man/fd.1
└── ixt.json

Extracted archive in its own directory. Nothing shared.

Uninstalling a tool is a clean delete of its envs/<installed-id>/ directory plus removal of its shim from $IXT_HOME/installed/bin/.


Exploring an env — ixt tool shell

Opens a subshell in the tool's environment directory — the environment is not activated. No PATH patch, no venv activate, no NODE_PATH injection. You get a plain shell at the env root; binaries must be called by explicit path.

ixt tool shell ruff
  Entering ruff env (/home/user/.local/share/ixt/installed/envs/ruff.pypi)
  Type exit to return
$

Useful for low-level inspection: browsing installed files, checking exact binary versions, or running a one-off command without going through a shim:

# inside the subshell — Python tool example
.venv/bin/pip list
.venv/bin/ruff check --version
exit

To get the path without launching a shell (for scripts):

cd "$(ixt tool where ruff)"

Extending an env — inject

Add packages into a tool's isolated environment without touching any other env or the system:

ixt tool config httpie inject rich        # add rich into httpie's venv
ixt tool config httpie uninject rich      # remove it

The injected packages are recorded in ixt.json and survive ixt tool upgrade. Declare them in ixt.toml to replay across machines:

[tools]
httpie = { inject = ["rich"] }
jc     = { inject = ["art"] }

When to inject

Inject when a tool optionally benefits from another package — for example httpie with rich for prettier output, or jc with art. The injected package is available inside the tool's env but invisible everywhere else.