dense CLI

One CLI for every coding agent you run. dense puts Claude Code, Codex, and OpenCode through condense: install once, log in once. dense keeps the machine signed in and injects the right base URL and credentials into each run. No key swap, no per-run configuration. Wiring per agent is in Agents. It's open source; releases are built from tagged source on GitHub Actions.

Install

bashcurl -fsSL https://cli.condense.chat/unix | sh
powershellirm https://cli.condense.chat/nt | iex

One install covers every agent. The installer drops the dense binary on your PATH and hands off to dense setup, which logs you in; the same login and token then back Claude Code, Codex, and OpenCode. There is nothing to install per agent, and dense doesn't bundle the agents themselves: it routes the ones you already have.

Setup also offers to route the bare claude command through dense, so you keep typing claude and it just goes through condense.

Log in

Login is a browser device flow: dense login opens login.condense.chat with a one-time code, no key copy/paste. The token is stored under ~/.config/dense/ (%APPDATA%\dense on Windows) with owner-only permissions.

How it works

  1. dense claude <args> resolves the real claude binary and runs it as a child process. Your arguments, stdin/stdout, Ctrl-C, and exit code all belong to Claude Code.
  2. On the child process only (your shell environment is never modified), dense sets ANTHROPIC_BASE_URL=https://api.condense.chat/anthropic and injects its credentials (X-Condense-Auth-Token, X-Condense-Session-Id) via ANTHROPIC_CUSTOM_HEADERS. Headers you already set there are preserved.
  3. Your existing Claude auth keeps working: ANTHROPIC_API_KEY forwards through verbatim as the upstream key.

dense persist places a thin shim ahead of the real claude on your PATH, so the bare command routes through dense. The real binary is never moved or modified; dense unpersist removes the shim instantly.

Codex and OpenCode don't need a wrapper process: their own config points them at the same proxy, and every request carries the same headers. See Agents.

Commands

Command What it does
dense login Authenticate this machine (browser device flow).
dense logout Clear stored credentials.
dense claude <args> Run Claude Code through the proxy; args pass straight through.
dense persist [tools…] Shim the named tools (no args: all) so the bare command routes through dense. Non-destructive.
dense unpersist [tools…] Remove the shims.
dense status Current login, endpoint, and credential locations.
dense doctor Verify the install is wired correctly.
dense self update Update the binary in place (sha256-verified download from GitHub releases).
dense self uninstall Remove dense, its shims, and PATH wiring. Credentials are kept.

Binaries ship for macOS and Linux (x86_64 and aarch64) and Windows; other platforms build from source.

Agents

Claude Code, Codex, and OpenCode all reach the same proxy; only the wiring differs. Claude Code runs through the dense binary itself. Codex and OpenCode point at the matching dialect with a one-time config and send the condense key in X-Condense-Auth-Token.

Agent Wiring How
Claude Code dense binary dense claude, or dense persist and keep typing claude.
Codex One-time config Point ~/.codex/config.toml at the OpenAI Responses dialect (below). dense codex will automate this.
OpenCode One-time config Point the provider baseURL at the matching dialect in opencode.json (below).

Claude Code

Claude Code needs no config, it runs through the dense binary directly. dense claude <args> launches it with the condense base URL and credentials injected, or dense persist puts a shim ahead of claude on your PATH so the bare command routes through condense. Your existing ANTHROPIC_API_KEY forwards through as the upstream key.

Codex

Codex speaks the Responses API, which condense serves at /openai/v1/responses. Define condense as a model provider and select it:

toml# ~/.codex/config.toml
model_provider = "condense"

[model_providers.condense]
name = "condense"
base_url = "https://api.condense.chat/openai/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
env_http_headers = { "X-Condense-Auth-Token" = "CONDENSE_AUTH_TOKEN" }

Export CONDENSE_AUTH_TOKEN=ak_… alongside your OPENAI_API_KEY. Requests authenticated with a ChatGPT login instead of an sk- key are detected and forwarded to the ChatGPT Codex backend automatically.

OpenCode

OpenCode takes a per-provider baseURL and headers. Point the provider you use at the matching condense dialect:

json{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": {
        "baseURL": "https://api.condense.chat/anthropic/v1",
        "headers": {
          "X-Condense-Auth-Token": "{env:CONDENSE_AUTH_TOKEN}"
        }
      }
    }
  }
}

For OpenAI models, set the openai provider's baseURL to https://api.condense.chat/openai/v1 the same way.

dense drives the same public API as any other client. Base URL, authentication, per-request headers, and error shapes are documented in the API reference.