# Installation

> Pre-built release binaries (musl/static), `cargo install agent-tools-interface`, Docker image, and platform prerequisites for local vs proxy deployments.

- Repository: Parcha-ai/ati
- GitHub: https://github.com/Parcha-ai/ati
- Human docs: https://grok-wiki.com/public/docs/parcha-ai-ati-a9d4398f11fa
- Complete Markdown: https://grok-wiki.com/public/docs/parcha-ai-ati-a9d4398f11fa/llms-full.txt

## Source Files

- `README.md`
- `Cargo.toml`
- `deploy/Dockerfile`
- `deny.toml`
- `src/cli/init.rs`

---

---
title: "Installation"
description: "Pre-built release binaries (musl/static), `cargo install agent-tools-interface`, Docker image, and platform prerequisites for local vs proxy deployments."
---

ATI ships as a single `ati` binary (crate `agent-tools-interface`). Install it on the host where tool calls execute (developer laptop, agent sandbox, or proxy VM), then point it at `~/.ati/` (or `ATI_DIR`) for manifests, keys, and skills. Proxy deployments add a second install on the secrets host running `ati proxy`; sandboxes only need the client binary plus `ATI_PROXY_URL` and `ATI_SESSION_TOKEN`.

## Supported platforms

| Platform | Release target | Notes |
|----------|----------------|-------|
| Linux x86_64 | `x86_64-unknown-linux-musl` | Static musl binary; no glibc dependency |
| Linux ARM64 | `aarch64-unknown-linux-musl` | Cross-compiled in CI with `cross` |
| macOS Intel | `x86_64-apple-darwin` | Dynamic macOS binary |
| macOS Apple Silicon | `aarch64-apple-darwin` | Dynamic macOS binary |
| Windows | — | Not in the release matrix |

<Info>
Crates.io package name is `agent-tools-interface`; the installed executable is `ati`. Current crate version in tree: `0.8.0-rc.7`.
</Info>

## Pre-built binaries (recommended)

GitHub Releases (tag `v*`) publish auditable binaries built by `.github/workflows/release.yml`. Each target ships as a **raw executable** plus a sidecar `.sha256` file (not always a `.tar.gz` archive).

### Default CLI binary

<CodeGroup>
```bash title="Linux x86_64"
curl -fSL "https://github.com/Parcha-ai/ati/releases/latest/download/ati-x86_64-unknown-linux-musl" \
  -o ati
chmod +x ati
sudo mv ati /usr/local/bin/
```

```bash title="Linux ARM64"
curl -fSL "https://github.com/Parcha-ai/ati/releases/latest/download/ati-aarch64-unknown-linux-musl" \
  -o ati
chmod +x ati
sudo mv ati /usr/local/bin/
```

```bash title="macOS Apple Silicon"
curl -fSL "https://github.com/Parcha-ai/ati/releases/latest/download/ati-aarch64-apple-darwin" \
  -o ati
chmod +x ati
sudo mv ati /usr/local/bin/
```

```bash title="macOS Intel"
curl -fSL "https://github.com/Parcha-ai/ati/releases/latest/download/ati-x86_64-apple-darwin" \
  -o ati
chmod +x ati
sudo mv ati /usr/local/bin/
```
</CodeGroup>

Pin a specific release by replacing `latest` with the tag (for example `v0.8.0`).

### Feature-flavored Linux binaries

The release job also builds optional compile-time features with filename suffixes:

| Asset suffix | Cargo features | Typical use |
|--------------|----------------|-------------|
| *(none)* | default | Sandboxes, local dev, minimal size |
| `-sentry` | `sentry` | Production proxy with error reporting |
| `-sentry-otel` | `sentry`, `otel` | Production proxy with errors + OTLP traces/metrics |

Example (Sentry-enabled musl, matches `deploy/Dockerfile`):

```bash
curl -fSL "https://github.com/Parcha-ai/ati/releases/download/v0.7.9/ati-x86_64-unknown-linux-musl-sentry" \
  -o ati
curl -fSL "https://github.com/Parcha-ai/ati/releases/download/v0.7.9/ati-x86_64-unknown-linux-musl-sentry.sha256" \
  -o ati.sha256
echo "$(awk '{print $1}' ati.sha256)  ati" | sha256sum -c -
chmod +x ati
```

<Warning>
SemVer prerelease tags (names containing `-`, e.g. `v0.8.0-rc.7`) are marked **prerelease** on GitHub and are **not** published to crates.io or PyPI. Use the GitHub release asset for RC binaries; stable tags publish to `cargo install` and `pip install ati-client`.
</Warning>

### Verify the binary

<Steps>
<Step title="GitHub attestation (recommended)">

```bash
gh attestation verify ./ati --repo Parcha-ai/ati
```

Failure means the binary was not built by the official CI workflow — do not run it.

</Step>
<Step title="SHA256 checksum">

```bash
curl -fSL "https://github.com/Parcha-ai/ati/releases/latest/download/ati-x86_64-unknown-linux-musl.sha256" -o ati.sha256
echo "$(awk '{print $1}' ati.sha256)  ati" | sha256sum -c -
```

</Step>
<Step title="Embedded dependency audit">

Binaries are built with `cargo-auditable`:

```bash
cargo audit bin ./ati
```

</Step>
<Step title="Runtime smoke test">

```bash
ati version
ati init
ati tool list | head
```

</Step>
</Steps>

## Install from Rust (`cargo install`)

Requires a **stable Rust toolchain** and network access to crates.io.

<CodeGroup>
```bash title="crates.io (stable releases only)"
cargo install agent-tools-interface
```

```bash title="GitHub (any tag/branch)"
cargo install --git https://github.com/Parcha-ai/ati.git
# Pin a tag:
cargo install --git https://github.com/Parcha-ai/ati.git --tag v0.8.0
```

```bash title="Clone and build locally"
git clone https://github.com/Parcha-ai/ati.git && cd ati
cargo build --release
# Binary: target/release/ati
```
</CodeGroup>

Release profile (`Cargo.toml`): `opt-level = "z"`, LTO, `strip = true` for small production binaries.

### Static musl build (sandboxes / minimal Linux)

```bash
# x86_64 Linux (needs musl-tools on Ubuntu/Debian)
cargo build --release --target x86_64-unknown-linux-musl

# aarch64 Linux (CI uses cross)
cargo install cross --locked
cross build --release --target aarch64-unknown-linux-musl
```

Optional features (compile-time only):

| Feature | Enables |
|---------|---------|
| `db` | Postgres persistence (`ATI_DB_URL`, `--migrate`) |
| `otel` | OTLP trace/metric export |
| `sentry` | Sentry error reporting |

```bash
cargo build --release --features db --target x86_64-unknown-linux-musl
cargo build --release --features sentry,otel --target x86_64-unknown-linux-musl
```

## Docker image (proxy server)

`deploy/Dockerfile` builds a **proxy-only** image: Debian slim base, pre-downloaded musl binary, bundled `manifests/` and `specs/`, non-root `ati` user.

```text
  docker build (deploy/Dockerfile)
        │
        ├─ debian:bookworm-slim + ca-certificates + curl
        ├─ Node.js 22 (npx for stdio MCP providers)
        ├─ curl GH release → ati-*-unknown-linux-musl-sentry (+ sha256 verify)
        ├─ COPY manifests/ specs/ → ATI_DIR=/app
        └─ CMD: ati proxy --port 18093 --bind 0.0.0.0
```

<ParamField body="ATI_VERSION" type="string" default="v0.7.9">
Docker build arg selecting the GitHub release tag to download. Bump when cutting a new proxy image.
</ParamField>

<ParamField body="TARGETARCH" type="string">
`arm64` → `aarch64-unknown-linux-musl`; otherwise `x86_64-unknown-linux-musl`.
</ParamField>

Build and run:

```bash
docker build -f deploy/Dockerfile \
  --build-arg ATI_VERSION=v0.7.9 \
  -t ati-proxy:local .

docker run --rm -p 18093:18093 \
  -e ATI_DIR=/app \
  -v "$(pwd)/my-secrets:/app:ro" \
  ati-proxy:local
```

| Image default | Value |
|---------------|-------|
| `ATI_DIR` | `/app` (manifests + specs copied in) |
| Listen | `0.0.0.0:18093` |
| User | `ati` (system account) |
| Healthcheck | `GET http://localhost:18093/health` every 30s |
| MCP stdio | Node.js 22 + npm ecosystem via `npx` |

<Note>
The stock Dockerfile does **not** bake in API keys. Mount or inject credentials via encrypted keyring, `ATI_KEY_*` env vars (`ati proxy --env-keys`), or orchestrator-side secret sync. For Postgres audit/virtual keys, use a `-db` build (`--features db`) — see persistence docs.
</Note>

## Initialize `~/.ati/`

After installing `ati`, create the config tree (also auto-created on first use):

```bash
ati init
```

`ati init` creates under `ATI_DIR` (default `~/.ati/`):

| Path | Purpose |
|------|---------|
| `manifests/` | Provider TOML catalog |
| `specs/` | Downloaded OpenAPI specs |
| `skills/` | Installed SKILL.md trees |
| `config.toml` | Optional proxy/JWT settings |

Proxy-oriented init (writes JWT config and keys):

```bash
ati init --proxy              # HS256 secret in config.toml
ati init --proxy --es256      # ES256 key pair: jwt-private.pem (0600), jwt-public.pem
```

`--es256` requires `--proxy`. With `--proxy`, `config.toml` is **always overwritten**; without it, a default stub is written only if missing.

Override data directory:

```bash
export ATI_DIR=/var/lib/ati
ati init --proxy --es256
```

Resolution order for `ATI_DIR`: `ATI_DIR` env → `$HOME/.ati` → fallback `.ati`.

## Deployment prerequisites

Where you install `ati` depends on execution mode. The same binary serves both roles; environment variables select behavior.

```mermaid
flowchart TB
  subgraph sandbox["Agent sandbox / dev host"]
    A[ati binary]
    M[manifests from ATI_DIR or image]
    A --> M
  end

  subgraph local["Local mode (default)"]
    K[keyring.enc or credentials]
    SK["/run/ati/.key optional"]
    A --> K
    SK -.-> K
    A --> U[Upstream APIs / MCP / CLIs]
  end

  subgraph proxy["Proxy mode"]
    P[ati proxy on secrets host]
    KR[keyring + JWT validation]
    P --> KR
    P --> U
    A -->|ATI_PROXY_URL POST /call| P
    JWT[ATI_SESSION_TOKEN] -.-> A
  end
```

### Local and dev installs (single host)

| Requirement | Dev (plaintext) | Local (encrypted keyring) |
|-------------|-----------------|---------------------------|
| Binary | `ati` on `PATH` | Same |
| Data dir | `~/.ati/` or `ATI_DIR` | Same |
| Credentials | `ati key set` → `credentials` (0600) | `keyring.enc` + session key |
| Session key | — | `/run/ati/.key` (default) or `ATI_KEY_FILE`; one-shot unlink after read |
| Scopes | Optional JWT in env for filtering | Same |
| MCP stdio | `npx` / provider command on `PATH` | Same on host running MCP subprocess |
| MCP HTTP | Outbound HTTPS | Same |

No separate proxy process. Keys stay on the machine running `ati run`.

### Proxy installs (split trust)

| Component | Installs | Needs |
|-----------|----------|-------|
| **Proxy host** | `ati` (often `-sentry` or `-sentry-otel` build) | `ATI_DIR` with `manifests/`, `keyring.enc` or `--env-keys`, JWT keys (`ati init --proxy` or env), outbound network to upstreams |
| **Agent sandbox** | `ati` only (musl static typical) | `ATI_PROXY_URL`, `ATI_SESSION_TOKEN`; **no** keyring or API keys |
| **Optional edge** | Caddy/haproxy in front | TLS, HMAC sig-verify secret in keyring; see VM example |

Proxy CLI defaults (`ati proxy`):

<ParamField body="--port" type="number" default="8090">
Listen port.
</ParamField>

<ParamField body="--bind" type="string" default="127.0.0.1">
Bind address; use `0.0.0.0` for remote sandboxes (Dockerfile uses `0.0.0.0`).
</ParamField>

<ParamField body="--ati-dir" type="string">
Override manifests/keyring directory (Docker/systemd: `/var/lib/ati` or `/app`).
</ParamField>

<ParamField body="--env-keys" type="flag">
Load secrets from `ATI_KEY_*` environment variables instead of `keyring.enc`.
</ParamField>

<ParamField body="--migrate" type="flag">
Apply embedded Postgres migrations when `ATI_DB_URL` is set (`db` feature required).
</ParamField>

Minimal proxy start:

```bash
ati init --proxy --es256
ati key set finnhub_api_key "sk-..."
ati proxy --port 8090 --bind 0.0.0.0 --ati-dir ~/.ati
```

Sandbox client:

```bash
export ATI_PROXY_URL=http://proxy-host:8090
export ATI_SESSION_TOKEN="$(ati token issue --sub agent-1 --scope 'tool:finnhub:* help' --ttl 3600)"
ati run finnhub:quote --symbol AAPL
```

### Optional runtime dependencies by provider type

| Provider handler | Extra host software |
|------------------|---------------------|
| MCP stdio | Command in manifest (commonly `npx` + Node.js) |
| MCP HTTP | Outbound HTTPS only |
| OpenAPI / HTTP | Outbound HTTPS |
| CLI (`ati provider add-cli`) | Wrapped binary on `PATH` (e.g. `gh`, `gcloud`) |
| Skills + LLM assist | LLM API key in keyring for `_llm` internal provider |

The Docker proxy image pre-installs **Node.js 22** specifically for stdio MCP servers launched via `npx`.

### Production proxy checklist

- Set `ATI_JWT_PUBLIC_KEY` / `ATI_JWT_SECRET` (or config.toml `[proxy.jwt]`) so anonymous access is rejected.
- Set `ATI_SSRF_PROTECTION=1` and `ATI_DOWNLOAD_ALLOWLIST` when using `file_manager:download`.
- Prefer `-sentry` / `-sentry-otel` release artifacts or image tags for observability.
- For edge VMs: copy `deploy/examples/vm/` systemd/Caddy templates; bootstrap keyring with `ati edge bootstrap-keyring` when using 1Password.
- Run `cargo deny check` in CI mirrors supply-chain policy (`deny.toml`: no unknown registries, no git deps, license allowlist).

## Troubleshooting

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| `cargo install` resolves old version | Installed during an RC period; crates.io skips prerelease tags | Install from GitHub release asset or `--git --tag` |
| `ati proxy` missing `--migrate` | Binary built without `db` feature | Rebuild with `--features db` or use `-db` release variant |
| MCP stdio spawn fails in container | Node/`npx` missing | Use stock Dockerfile or install Node 22 on host |
| Proxy rejects all calls | JWT enforced, token missing/invalid | `ati token issue` + export `ATI_SESSION_TOKEN` |
| Keyring not loaded in proxy | Wrong `--ati-dir` | Manifests and `keyring.enc` must live under same `ATI_DIR` |
| musl aarch64 build fails locally | Needs cross toolchain | `cargo install cross && cross build ...` |

## Related pages

<CardGroup>
<Card title="Quickstart" href="/quickstart">
Initialize `~/.ati/`, import a provider, store a key, and run your first `ati run`.
</Card>
<Card title="Execution modes" href="/execution-modes">
Dev, local encrypted keyring, and proxy mode — credential placement and threat model.
</Card>
<Card title="Deploy proxy server" href="/deploy-proxy-server">
`ati proxy` flags, systemd/VM layout, passthrough, and health probes.
</Card>
<Card title="Configure JWT and keys" href="/configure-jwt-and-keys">
`ati init --proxy`, token issuance, and keyring management.
</Card>
<Card title="Build, test, and troubleshooting" href="/build-test-and-troubleshooting">
`cargo test`, musl targets, feature flags, and E2E scripts.
</Card>
</CardGroup>
