# Installation

Install TokenTriage locally, verify the binary, or choose a package, container, Kubernetes, or source-based setup.

Source: https://tokentriage.com/docs/get-started/installation

---
import Callout from '../../../components/Callout.astro';
import Details from '../../../components/Details.astro';
import CodeTabs from '../../../components/CodeTabs.astro';
import NextSteps from '../../../components/NextSteps.astro';

For the fastest local setup, use the one-line installer below. It selects the right binary for
your platform, verifies its checksum, and installs shell completions. You don't need
administrator rights.

Have a terminal with `curl` or `wget` available. You don't need a provider API key, a database,
a sidecar, or a language runtime. A provider key is only needed when you send live traffic;
`tokentriage demo` works without one.

## Install TokenTriage

Choose the command for your platform:

<CodeTabs label="Choose your platform" tabs={[
  { id: 'unix', label: 'macOS / Linux' },
  { id: 'win', label: 'Windows' }
]}>
<Fragment slot="unix">
```console
$ curl -fsSL https://tokentriage.com/install.sh | sh
```
</Fragment>
<Fragment slot="win">
```console
$ irm https://tokentriage.com/install.ps1 | iex
```
</Fragment>
</CodeTabs>

The installer writes to `~/.local/bin` on macOS and Linux, and to
`%LOCALAPPDATA%\Programs\tokentriage` on Windows. If that directory is not on your `PATH`, the
installer prints the exact line to add. Open a new terminal after adding it.

Before writing the binary, the installer checks its SHA-256 hash against the release's
`checksums.txt`. If the check fails, it prints the expected and downloaded hashes, exits with an
error, and installs nothing. The POSIX script explains what it is doing before it calls `sudo`.

<Details summary="Pin a version, change the install directory, or use a mirror">

The installer accepts four optional environment variables:

| Variable | Default | What it does |
|---|---|---|
| `TT_VERSION` | `latest` | installs a specific release, such as `v1.0.0`; pin this in CI |
| `TT_INSTALL_DIR` | `~/.local/bin` or `%LOCALAPPDATA%\Programs\tokentriage` | changes where the binary is written |
| `TT_DOWNLOAD_BASE` | `https://github.com` | downloads release assets from an internal mirror |
| `TT_NO_COMPLETION` | unset | skips shell completions when set to `1` |

Pass the variables to the shell that runs the installer:

```console
$ curl -fsSL https://tokentriage.com/install.sh \
  | env TT_VERSION=v1.0.0 TT_INSTALL_DIR=/usr/local/bin sh
```

An internal mirror uses the same release layout under `<base>/<repo>/releases/...`. The installer
still verifies the mirrored archive against that release's checksums.

</Details>

## Verify the installation

Run `version` to confirm that the binary starts and see which pricing data it contains:

```console
$ tokentriage version
tokentriage v1.0.0 (commit 4f2a91c, built 2026-08-05T09:14:03Z)
pricing snapshot: litellm@2026-07-14#179affb
```

Your version, commit, and build date will match the release you installed. The pricing snapshot
is the dated copy of the provider price table used for cost calculations.

If your shell cannot find `tokentriage`, use the PATH instructions under
[If installation fails](#if-installation-fails).

<Details summary="Run a broader setup check with doctor">

`doctor` checks the environment around the binary. It starts no service, writes no data, and
prints no secrets:

```console
$ tokentriage doctor
✓ binary — tokentriage dev (none), embedded pricing snapshot litellm@2026-07-14#179affb — clean
○ config — no config file (quickstart-less env) — checking the binary + defaults; pass --config to check one
    run: tokentriage doctor --config <path>   (to strictly check a specific config)
○ compile — skipped — no valid config to compile (see the config check)
✓ ports — listen 127.0.0.1:8787 bindable, admin 127.0.0.1:9090 bindable — clean
✓ ledger — C:\tt-home\.tokentriage\decisions.jsonl — 0 rows, 0 torn lines, writable — clean
✓ index — C:\tt-home\.tokentriage\index\decisions.sqlite — open, no rows indexed yet — clean
✓ pricing — embedded table litellm@2026-07-14#179affb loaded, no overrides configured — clean
○ keys — no config upstreams — no credential references to check
○ dashboard — skipped — no valid config (see the config check)
○ instance — not probed — pass --probe to check a running instance's admin plane over HTTP
    run: tokentriage doctor --probe                                   (probes the config's admin address)
    run: tokentriage doctor --probe --probe-url http://127.0.0.1:9090

ok — all checks passed (exit 0)
```

This capture came from a source build on Windows with no configuration file. A release prints its
version instead of `dev`, paths follow your operating system, and configured checks replace the
skipped ones. A failed check exits with status `1` in both text and `--json` output.

</Details>

## Choose another installation method

The one-line installer is the recommended local path. Choose another method when it better matches
how you run software:

| If you want to... | Use |
|---|---|
| try the CLI without changing your `PATH` | `npx`, `uvx`, or `pipx` |
| let an existing package manager handle upgrades | Homebrew or Scoop |
| place the binary yourself or mirror it internally | a release archive |
| run TokenTriage as a service | the container image or Helm chart |
| work on TokenTriage itself | a source build |

<Details summary="Run the CLI without installing it">

Use this path when Node 18+ or Python 3.9+ is already available, or when a CI job should not change
the runner:

```console
$ npx @tokentriage/cli run --anthropic
$ uvx tokentriage-cli run --anthropic
```

`pipx run tokentriage-cli` works like `uvx`.

The CLI is `@tokentriage/cli` on npm and `tokentriage-cli` on PyPI. The unscoped `tokentriage`
package is the instrumentation SDK and does not contain an executable.

Both CLI packages carry the same prebuilt binary as the release archives. The npm package uses
per-platform dependencies instead of downloading a binary in `postinstall`, so it also works with
`npm ci --ignore-scripts`, registry proxies, and offline package caches.

</Details>

<Details summary="Install with Homebrew, Scoop, or go install">

Choose the package manager you already use:

<CodeTabs label="Choose your package manager" tabs={[
  { id: 'brew', label: 'Homebrew' },
  { id: 'scoop', label: 'Scoop' },
  { id: 'go', label: 'go install' }
]}>
<Fragment slot="brew">
```console
$ brew install tokentriage/tap/tokentriage
```
</Fragment>
<Fragment slot="scoop">
<Callout type="note">
Self-hosted packages ship with the self-hosted option, which is under development. Contact
hello@tokentriage.com for early access.
</Callout>
</Fragment>
<Fragment slot="go">
<Callout type="note">
Self-hosted packages ship with the self-hosted option, which is under development. Contact
hello@tokentriage.com for early access.
</Callout>
</Fragment>
</CodeTabs>

Homebrew installs the same prebuilt binary as the one-line installer.

</Details>

<Details summary="Download and verify a release archive yourself">

<Callout type="note">
Self-hosted packages ship with the self-hosted option, which is under development. Contact
hello@tokentriage.com for early access.
</Callout>

</Details>

<Details summary="Deploy with Docker or Kubernetes">

Container images use immutable version tags; no `:latest` tag is published. Use a named volume for
the ledger so the non-root container can write to it:

```console
$ docker run --rm \
  -p 8787:8787 -p 9090:9090 \
  -e ANTHROPIC_API_KEY \
  -v tokentriage-data:/data \
  ghcr.io/tokentriage/tokentriage:v1.0.0
```

Replace `v1.0.0` with the release you want. The container configuration listens on `0.0.0.0` so
Docker can publish its ports. The process runs as UID and GID `65532`; if you use a host bind mount
instead of the named volume, make that directory writable by this user first.

Install the Helm chart directly from the registry:

```console
$ helm install tokentriage oci://ghcr.io/tokentriage/charts/tokentriage \
  --version 0.2.0
```

The chart version is independent of the TokenTriage release version. Run `helm show chart
oci://ghcr.io/tokentriage/charts/tokentriage` to see both the chart version and `appVersion`.

[Deployment and infrastructure](/docs/operate/deployment) covers the resources these commands
create, along with Compose, Kustomize, Terraform, air-gapped operation, and supply-chain
verification.

</Details>

<Details summary="Build from source">

<Callout type="note">
Self-hosted packages ship with the self-hosted option, which is under development. Contact
hello@tokentriage.com for early access.
</Callout>

</Details>

## Upgrade or remove TokenTriage

Use the same method that installed TokenTriage. This keeps package-manager state and deployment
configuration consistent:

| Installation method | Upgrade | Remove |
|---|---|---|
| one-line installer | run the installer again; set `TT_VERSION` to pin a release | delete the binary from the directory printed during installation |
| release archive | replace the old binary with the new release | delete the binary |
| Homebrew | `brew upgrade tokentriage/tap/tokentriage` | `brew uninstall tokentriage` |
| Scoop | `scoop update tokentriage` | `scoop uninstall tokentriage` |
| `go install` or source build | rebuild at the version you want | delete the binary you built |
| `npx`, `uvx`, or `pipx run` | run the package version you want | no installed binary; clear the tool's cache only if needed |
| Docker | change the image tag and pull that version | remove the container; remove its image or volume only if you no longer need them |
| Helm | run `helm upgrade` with the chart version you want | `helm uninstall tokentriage` |

Run `tokentriage version` after an upgrade to confirm the product version and pricing snapshot.
The decision ledger is append-only JSON lines, so a newer binary reads the existing file without a
migration step.

<Callout type="warning" title="Your ledger is separate from the binary">
Removing TokenTriage does not delete `~/.tokentriage`. Delete that directory only if you also want
to permanently remove the decision ledger and its index. Back up any records you need first.
</Callout>

## If installation fails

<Details summary="If your shell reports command not found">

Open a new terminal first. A shell that was already running may still have the old `PATH`.

If that does not fix it, check where the binary landed and whether its directory is on `PATH`:

<CodeTabs label="Choose your platform" tabs={[
  { id: 'unix', label: 'macOS / Linux' },
  { id: 'win', label: 'Windows' }
]}>
<Fragment slot="unix">
```console
$ command -v tokentriage
$ printf '%s\n' "$PATH"
```
</Fragment>
<Fragment slot="win">
```console
$ Get-Command tokentriage
$ $env:Path -split ';'
```
</Fragment>
</CodeTabs>

On macOS and Linux, add the install directory to your shell's startup file, such as `~/.zshrc` for
zsh or `~/.bashrc` for bash, then open another terminal. On Windows, add
`%LOCALAPPDATA%\Programs\tokentriage` to your user `PATH`. The one-line installer prints the exact
command when this is needed.

</Details>

<Details summary="If checksum verification fails">

The installer stops before creating the install directory. Retry the download once in case it was
interrupted. If you use `TT_DOWNLOAD_BASE`, confirm that the archive and `checksums.txt` came from
the same mirrored release.

</Details>

<Details summary="If a custom install directory is not writable">

Choose a directory owned by your user and pass it with `TT_INSTALL_DIR`. The default directories
are user-writable and do not require administrator rights.

</Details>

<NextSteps items={[
  {
    title: "Quickstart",
    href: "/docs/get-started/quickstart",
    description: "Produce a costed table locally with no provider key or configuration file."
  },
  {
    title: "Your first live request",
    href: "/docs/get-started/first-live-request",
    description: "Connect a provider, send one request, and check the recorded cost."
  },
  {
    title: "Deployment and infrastructure",
    href: "/docs/operate/deployment",
    description: "Run TokenTriage with Helm, Kustomize, Compose, or Terraform."
  },
  {
    title: "Configuration reference",
    href: "/docs/reference/configuration",
    description: "Move from a quickstart profile to a validated YAML configuration."
  }
]} />
