Metadata-Version: 2.4
Name: ixt-cli
Version: 0.8.1
Summary: Universal CLI tool isolator - manage Python, Node, and binary tools with per-tool isolation
Project-URL: Homepage, https://gitlab.com/pytgaen-group/ixt
Project-URL: Repository, https://gitlab.com/pytgaen-group/ixt.git
Project-URL: Issues, https://gitlab.com/pytgaen-group/ixt/-/issues
Project-URL: Documentation, https://ixt-39f604.gitlab.io
Author-email: Gaëtan Montury <10528250-pytgaen@users.noreply.gitlab.com>
License: MIT
Keywords: cli,github,isolation,npm,package-manager,pypi,tool
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://ixt-39f604.gitlab.io/assets/ixt.jpg" alt="ixt" width="600">
</p>

<h1 align="center">ixt — Universal CLI Tool Isolator</h1>

<p align="center">
  <a href="https://gitlab.com/pytgaen-group/ixt/-/releases"><img src="https://img.shields.io/gitlab/v/release/pytgaen-group/ixt?label=release" alt="Release"></a>
  <a href="https://gitlab.com/pytgaen-group/ixt/-/pipelines"><img src="https://img.shields.io/gitlab/pipeline-status/pytgaen-group/ixt?branch=main" alt="Pipeline"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
  <img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+">
</p>

<p align="center">
  <img src="https://ixt-39f604.gitlab.io/assets/wip.jpg" alt="Work in Progress" width="300">
</p>

**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.

```bash
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.

```bash
# 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:

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

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

```bash
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:

```bash
# 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

```bash
# 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:

```bash
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:

```bash
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`:

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

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

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

## 📌 Version pinning

```bash
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)
```

## 🧰 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 export`                             | Export installed tools as ixt.toml (stdout), preserves install intent |
| `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
│   ├── 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

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

uv run pytest                 # test 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>. The GitHub repository (if present) is a **read-only mirror** — please open issues and merge requests on GitLab.

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

## 📄 License

MIT
