opik-cipx is a local reverse HTTP proxy that sits between Claude Code and
the Anthropic API. Claude Code routes through it via ANTHROPIC_BASE_URL;
opik-cipx owns the TLS leg to api.anthropic.com. It captures every call on
the wire, categorizes input/output bytes into cost buckets — system prompt,
tools, memory, agents, skills, MCP, user input, tool I/O — and ships
per-call spans to Opik so you can answer
"where did my tokens go and how much did they cost?"
Status: actively developed, versioned
v0.0.x. This repo is the public distribution point: it ships the prebuilt binaries (see Releases) and the Claude Code plugin. The source lives in the private comet-ml/cost-intelligence-proxy-internal repo; each release is built from there.
- Wire capture — totals come straight from Anthropic's
response.usage, so token counts and costs are exact, not estimated. - Per-category attribution — request + response bytes are bucketed (system prompt, builtin tools, MCP tools, skills, memory, custom agents, prior assistant turns, tool I/O, user prompts, …) using chars-proportional math over the actual wire bytes. No tokenizer dependency.
- Subagent aware — subagent calls are captured and peer under the same session.
- MCP attribution — MCP tool definitions and results are bucketed separately so you can see what your MCP servers cost.
- Survives Opik outages — a local WAL spools spans; the shipper drains when Opik comes back.
- Single binary —
opik-cipxis the long-lived gateway and the short-lived process Claude Code'sSessionStarthook invokes (subcommandopik-cipx sync).
┌──────────────────────┐ ┌─────────────────────────────┐
│ Claude Code │ HTTP │ opik-cipx (127.0.0.1:9909) │ TLS
│ ANTHROPIC_BASE_URL ─┼────────►│ reverse proxy ─────────────┼──► Anthropic API
│ http://127.0.0.1:99 │ │ capture req + resp │
└──────────────────────┘ │ categorize + build span │
│ WAL spool → Opik shipper │
└────────────────┬────────────┘
│
▼
Opik
The plugin's SessionStart hook execs opik-cipx sync on every Claude Code
launch. sync is idempotent: it installs the OS supervisor (launchd /
systemd) so the daemon auto-restarts on crash, brings the daemon up if it
isn't already running, and upserts ANTHROPIC_BASE_URL into
~/.claude/settings.json so Claude Code routes through
http://127.0.0.1:9909. No filesystem-level CA installs, no per-host MITM
cert dance — Claude Code talks plain HTTP to the loopback listener and
opik-cipx is the only thing holding a TLS session to Anthropic.
From within Claude Code:
/plugin marketplace add comet-ml/cost-intelligence-proxy
/plugin install opik-cipx@opik-enterprise
The plugin installs the SessionStart hook that keeps the opik-cipx gateway
alive between Claude Code sessions, plus the /opik-cipx:opik-cipx skill
(how it works + diagnostics). The hook tolerates a missing binary — it just
prints a hint to install opik-cipx and lets the session continue.
The plugin ships the binary in its own tree, so a clean plugin install needs
nothing more. For a non-plugin setup, drop the binary with install.sh (see
below), then restart Claude Code — the SessionStart hook runs opik-cipx sync, which wires everything up.
If you've cloned this repo locally and want to install your working copy instead of the published version:
/plugin marketplace add /path/to/cost-intelligence-proxy
/plugin install opik-cipx@opik-enterprise
If you'd rather skip the plugin and just run opik-cipx from your shell:
curl -fsSL https://raw.githubusercontent.com/comet-ml/cost-intelligence-proxy/main/install.sh | bashThe installer downloads the latest release for your OS/arch, drops
opik-cipx into ~/.opik-cipx/bin/, and prints the next step. Add that
path to your PATH, then:
opik-cipx sync # supervise + start the daemon and route Claude Code through it
opik-cipx status # confirm it's upTo pin a specific version:
curl -fsSL https://raw.githubusercontent.com/comet-ml/cost-intelligence-proxy/main/install.sh | bash -s -- v0.0.35Grab the right archive from the Releases page:
| Filename | Platform |
|---|---|
opik-cipx-darwin-arm64.tar.gz |
Apple Silicon macOS |
opik-cipx-darwin-amd64.tar.gz |
Intel macOS |
opik-cipx-linux-amd64.tar.gz |
x86_64 Linux |
opik-cipx-linux-arm64.tar.gz |
arm64 Linux |
Each archive contains the opik-cipx binary. Verify against SHA256SUMS
from the same release before extracting:
shasum -a 256 -c <(grep darwin-arm64 SHA256SUMS)
mkdir -p ~/.opik-cipx/bin
tar -xzf opik-cipx-darwin-arm64.tar.gz -C ~/.opik-cipx/bin/For org-wide deployment, push configuration through Claude Code's server-managed settings — Anthropic's admin console delivers JSON to every authenticated user, no MDM required. (Requires Claude for Teams or Enterprise.)
Where to set it up: in Claude.ai, go to Admin Settings → Claude Code → Managed settings and paste the JSON below. Clients pick it up at next startup or within the hourly poll.
{
"extraKnownMarketplaces": {
"opik-enterprise": {
"source": {"source": "github", "repo": "comet-ml/cost-intelligence-proxy"},
"autoUpdate": true
}
},
"enabledPlugins": {
"opik-cipx@opik-enterprise": true
},
"env": {
"OPIK_CIPX_BASE_URL": "https://www.comet.com/opik/api",
"OPIK_CIPX_WORKSPACE": "your-org-cc-workspace",
"OPIK_CIPX_API_KEY": "<workspace-scoped API key>",
"OPIK_CIPX_PROJECT": "cc-{user}",
"ENABLE_TOOL_SEARCH": "auto"
},
"forceRemoteSettingsRefresh": true
}What each piece does:
extraKnownMarketplaces+enabledPlugins— registers this repo as a marketplace and force-enables the plugin for every user. Users see it as managed and can't disable it.OPIK_CIPX_BASE_URL— Opik installation URL the gateway ships traces to.OPIK_CIPX_WORKSPACE— sends Claude Code traces to a dedicated workspace, isolated from any user's personal Opik work.OPIK_CIPX_API_KEY— the workspace-scoped key the gateway uses to write traces. Treat as sensitive; the key is shared with every machine it's deployed to. Provision with the minimum write scope on the CC workspace.OPIK_CIPX_PROJECT— supports{field}tokens (see below), so one config string routes every user to their own project.ENABLE_TOOL_SEARCH— routing Claude Code through opik-cipx sets a non-AnthropicANTHROPIC_BASE_URL, which makes CC (≥ 2.1.70) disable MCP tool search by default. opik-cipx forwards requests unmodified, so it's safe to keep on —autorestores it. (See the MDM section below for the details.)forceRemoteSettingsRefresh: true— fail-closed startup: blocks the CLI at launch until fresh managed settings are fetched, so the brief unenforced window on first launch can't leak unmonitored sessions.
The binary itself still needs to land on each machine separately —
enabling the plugin via managed settings gives every user the hook wiring
and the /opik-cipx:opik-cipx skill, but the actual opik-cipx
binary is dropped by install.sh in your provisioning script — see the
Provisioning section.
Available {field} tokens for OPIK_CIPX_PROJECT:
| Token | Resolves to |
|---|---|
{user} |
local-part of the user's email (before @) — e.g. collinc |
{email} |
full email — e.g. collinc@comet.com |
{hostname} |
machine hostname |
The gateway also resolves the signed-in user's identity (email, username, organization) and attaches it to every trace, so admins can filter by user even inside a shared project.
The Enterprise install above delivers config through Anthropic's admin console (server-managed settings). If you'd rather push it with your own MDM — Jamf, Intune, Workspace ONE, Ansible, a provisioning script — Claude Code also reads an enterprise managed settings file from a fixed system path. Land the same JSON there and every user on the machine picks it up at next launch; no per-user step.
Where the file goes (Claude Code reads it automatically — no env var, no flag points at it):
| Platform | Path |
|---|---|
| macOS | /Library/Application Support/ClaudeCode/managed-settings.json |
| Linux / WSL | /etc/claude-code/managed-settings.json |
| Windows | C:\Program Files\ClaudeCode\managed-settings.json |
(The legacy Windows path C:\ProgramData\ClaudeCode\managed-settings.json was
dropped in Claude Code v2.1.75.) To split config across files, drop *.json
into a managed-settings.d/ directory beside the file — they merge
alphabetically on top of the base, systemd-style.
Managed settings sit at the top of Claude Code's precedence chain —
managed → command-line args → local project (.claude/settings.local.json) →
project (.claude/settings.json) → user (~/.claude/settings.json) — so users
can't override or disable what you set here. The file uses the same schema as
settings.json.
What to put in it — register the marketplace, force-enable the plugin, and set the Opik destination:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"extraKnownMarketplaces": {
"opik-enterprise": {
"source": {"source": "github", "repo": "comet-ml/cost-intelligence-proxy"}
}
},
"enabledPlugins": {
"opik-cipx@opik-enterprise": true
},
"env": {
"OPIK_CIPX_BASE_URL": "https://www.comet.com/opik/api",
"OPIK_CIPX_WORKSPACE": "your-org-cc-workspace",
"OPIK_CIPX_API_KEY": "<workspace-scoped API key>",
"OPIK_CIPX_PROJECT": "cc-{user}",
"ENABLE_TOOL_SEARCH": "auto"
}
}Notes:
- Don't set
ANTHROPIC_BASE_URLhere.opik-cipx syncwrites it into the user's~/.claude/settings.jsonpointing at the loopback listener (http://127.0.0.1:9909), and clears it again when you flip theCIPX_DISABLEDkill-switch. Pinning it in managed settings would sit above the user scope and defeat that teardown, leaving a disabled proxy in the wire path. Letsyncown it. ENABLE_TOOL_SEARCH— because CC now talks to a non-AnthropicANTHROPIC_BASE_URL, it turns MCP tool search off by default (v2.1.70+). opik-cipx is a transparent tee that forwards requests unmodified, so it's safe to turn back on:ENABLE_TOOL_SEARCH=auto(or, equivalently,_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL=1) restores it.- The binary still ships separately. Managed settings only carries the
plugin wiring and env — deploy the
opik-cipxbinary in the same MDM payload withinstall.sh(see Provisioning). - To lock down which marketplaces users may add at all, pair
extraKnownMarketplaceswithstrictKnownMarketplacesin the same file.
Point the gateway at your Opik installation with the OPIK_CIPX_* environment
variables (below) or a ~/.opik-cipx/config.toml file. Resolution precedence
is env var → ~/.opik-cipx/config.toml → built-in default, and changes
take effect on the next daemon (re)start — there is no mid-session hot-reload.
opik-cipx env vars use the OPIK_CIPX_ prefix (Opik destination credentials)
or CIPX_ (proxy behavior) so they don't collide with the standard Opik SDK
variables (OPIK_API_KEY, OPIK_WORKSPACE, etc.) — users running both
opik-cipx and a regular Opik client can configure them independently.
| Variable | Purpose |
|---|---|
OPIK_CIPX_BASE_URL |
Opik installation URL (e.g. https://www.comet.com/opik/api). |
OPIK_CIPX_API_KEY |
API key the gateway uses to write traces. |
OPIK_CIPX_WORKSPACE |
Opik workspace traces land in. |
OPIK_CIPX_PROJECT |
Project name. Supports {user}, {email}, {hostname} templating — see Enterprise install above. |
OPIK_CIPX_DEBUG |
true/on → verbose logging to ~/.opik-cipx/logs/cipx.log. |
| Variable | Purpose |
|---|---|
CIPX_DISABLED |
Master kill-switch. Truthy (1/true/yes/on) tears the install down on the next opik-cipx sync so Claude Code routes directly to Anthropic. |
CIPX_CAPTURE_CONTENT |
false ships counts and costs only, never prompt or completion bytes. |
CIPX_HOME |
Override the state root (default ~/.opik-cipx). |
CIPX_CONFIG |
Path to the opik-cipx config file (default ~/.opik-cipx/config.toml). |
CIPX_UPSTREAM_PROXY |
Forward outbound traffic through this proxy. |
CIPX_SENTRY |
off disables anonymous error reporting. |
CIPX_SENTRY_DSN |
Sentry DSN for anonymous panic/error reports. Telemetry stays off unless this is set. |
Anything you can set with an OPIK_CIPX_* / CIPX_* env var can also live in
~/.opik-cipx/config.toml (env vars win when both are set):
[opik]
base_url = "https://www.comet.com/opik/api"
api_key = "your-api-key"
workspace = "comet-all"
project = "cc-{user}"
[capture]
capture_content = trueOverride the file's location with $CIPX_CONFIG, or the whole state root with
$CIPX_HOME.
There's no per-project marker file and no per-repo toggle — installing the
plugin is the opt-in. Once it's installed, every Claude Code session runs
opik-cipx sync at SessionStart, which keeps the proxy supervised and points
Claude Code's ANTHROPIC_BASE_URL at it. From then on every call is captured
automatically; there is nothing to switch on per repo.
To turn capture off, set the CIPX_DISABLED kill-switch (any of 1,
true, yes, on):
export CIPX_DISABLED=1It's an environment variable, not a file, so it applies wherever it's set — a
single shell or your whole login environment. The next opik-cipx sync (i.e.
the next SessionStart) reads it and tears the install down: it removes the
launchd / systemd supervisor unit and clears the managed ANTHROPIC_BASE_URL,
so Claude Code routes straight to Anthropic with no proxy in the path. As a
backstop, opik-cipx proxy also exits 0 immediately when launched while
disabled, so a stray supervisor can't resurrect it. Either way your Claude
Code session stays healthy — disabling never breaks the wire.
To turn capture back on:
unset CIPX_DISABLED
opik-cipx sync # or just restart Claude Code — SessionStart runs syncSettings take effect only on (re)start — there is no mid-session hot-reload.
Toggling CIPX_DISABLED means restarting Claude Code, or re-running
opik-cipx sync, before the change is picked up.
For environments where prompt and completion bytes can't leave the machine, set:
export CIPX_CAPTURE_CONTENT=falseopik-cipx then ships counts, costs, structure, and identity — but never the
raw prompt or completion bytes. Request/response bodies and tool
arguments/results are dropped, while every cc.categories number, the
cc.usage totals, and all category/skill/memory/agent metadata (paths,
counts, lengths) are kept. Capturing content is the default.
After /plugin install opik-cipx@opik-enterprise:
| Skill | Purpose |
|---|---|
/opik-cipx:opik-cipx |
How opik-cipx works — architecture, the CLI, state layout, enable/disable, privacy/telemetry, and how to read opik-cipx status. Claude pulls it in on its own when you ask about opik-cipx or when spans stop reaching Opik; you can also call it directly. |
opik-cipx status # pid, ports, queue depth, counters, telemetry on/off
opik-cipx logs # tail ~/.opik-cipx/logs/cipx.log
opik-cipx viewer # print the local debug-UI URL (add --open to launch it)The viewer renders the raw request body with every region colored by the category it landed in — unattributed bytes stand out, indicating a categorizer gap or a new CC wire-format variant.
The Opik MCP server gives Claude tools to query your Opik data — traces, experiments, evaluation results — directly in conversation. It's independent of opik-cipx (opik-cipx ingests traces; the MCP server queries them).
For Opik Cloud, add to ~/.claude.json:
{
"mcpServers": {
"opik": {
"command": "npx",
"args": ["-y", "opik-mcp", "--apiKey", "YOUR_OPIK_API_KEY"]
}
}
}For self-hosted Opik, replace with --apiBaseUrl http://localhost:5173/api
(or your URL).
opik-cipx purge # stops the gateway, wipes the WAL spool (drops unshipped spans)
opik-cipx uninstall # stops the daemon, removes the supervisor unit, deletes ~/.opik-cipxopik-cipx uninstall clears the managed ANTHROPIC_BASE_URL and removes
~/.opik-cipx, but the Claude Code plugin owns the SessionStart hook wiring
— to remove that too, uninstall the plugin from Claude Code
(/plugin uninstall opik-cipx@opik-enterprise).
For deploying opik-cipx across a team:
- Homebrew tap (planned) —
brew install comet-ml/tap/opik-cipx. - Provisioning script — drop
install.shinto Ansible / Chef / Salt / whatever you already use. - Container images — none yet; the binary is statically linked so copying it in works.
If you're at an org with a managed-settings rollout, pair the install with the JSON in Enterprise install above.
File issues on the issue tracker for this repo.
© 2026 Comet ML, Inc. All rights reserved. This software is proprietary and confidential.