> ## Documentation Index
> Fetch the complete documentation index at: https://docs.augustin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Code routing

How Claude Code reaches LLMs across machines. Routes through Bifrost so traffic hits Cecelia (free Bedrock) instead of paid accounts.

## Topology

```
work-laptop (Mac) ─┐
debian-1 / i3      ├──► bifrost.augustin.ai/anthropic ──► Cecelia Bedrock (us-west-2)
pentium / debian-2 ─┘
```

| Machine               | VK name       | VK secret location                                                                                                               |
| --------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| work-laptop           | `work-laptop` | macOS Keychain item `bifrost-vk`                                                                                                 |
| debian-1 (i3 desktop) | `i3`          | `~/apps/bifrost/.env` `BIFROST_VK=`                                                                                              |
| pentium (debian-2)    | `pentium`     | (location not confirmed; receiving traffic but secret distribution mechanism is unclear — investigate as part of the VK reshape) |

## Providers in Bifrost

| Name                        | Account      | Auth                                  | Notes                                                                                                                       |
| --------------------------- | ------------ | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `cecelia`                   | 175342148895 | rotating STS                          | Free, work-funded. Streaming requires `User-Agent: claude-cli/...` (set in `network_config.extra_headers`).                 |
| `isengard-runtime`          | 666654122230 | long-term bearer                      | Personal AWS, paid. 74 models. Budget exhausted for the current month — minimize traffic.                                   |
| `isengard-mantle-openai`    | 666654122230 | long-term bearer                      | Free, work-funded. 38 OpenAI-shape Mantle models at `bedrock-mantle.us-east-1.api.aws`.                                     |
| `isengard-mantle-anthropic` | 666654122230 | long-term bearer (in `extra_headers`) | Free, work-funded. 2 Anthropic-shape Mantle models at the `/anthropic` path suffix.                                         |
| `kiro`                      | —            | aiclient2api token                    | Free Claude via Kiro OAuth. OAuth wedges roughly monthly; recovery requires re-auth on aiclient2api.                        |
| `bedrock`                   | —            | (no keys)                             | Built-in to Bifrost binary, not deletable. Has no keys; any traffic 403s. A routing rule rewrites `bedrock/*` to `cecelia`. |

## VKs

Currently flat-scoped (each VK can reach all 6 providers). Two routing rules force work-laptop traffic onto cecelia regardless of VK scope:

1. `bedrock-to-cecelia-redirect` — any request with `provider == "bedrock"` (the keyless built-in) → cecelia.
2. `work-laptop-anthropic-to-cecelia` — for the work-laptop VK, models matching `us.anthropic.*` or `global.anthropic.*` → cecelia, regardless of which `provider/` prefix the client sent.

| Name               | Used by                    |
| ------------------ | -------------------------- |
| `pentium`          | pentium machine CC         |
| `i3`               | debian-1 i3 desktop CC     |
| `work-laptop`      | work laptop CC and Zed     |
| `augustin-default` | break-glass / personal use |
| `n8n-classifier`   | n8n email classifier       |
| `mastra`           | Mastra agents              |

VK reshape to client-scoped names (e.g. `work-laptop-claude-code`, `i3-kiro`) is planned but not yet done.

## Auth flow

CC reads the API key via `apiKeyHelper` field in `~/.claude/settings.json`. The helper at `~/.claude/bin/api-key-helper.sh` resolves per-OS:

* macOS — `security find-generic-password -s bifrost-vk`
* Linux — reads `BIFROST_VK=` from `~/apps/bifrost/.env`

Zed-launched CC is a separate auth pathway. Zed sets `ANTHROPIC_API_KEY` directly via `~/.config/zed/settings.json` `agent_servers.claude-acp.env` and bypasses the helper. The VK value lives inline there.

`ANTHROPIC_BASE_URL` is set in `~/.claude/settings.json` `env` block (subprocess inheritance lands it in CC's own env at HTTP-call time).

OAuth credentials (`~/.claude/.credentials.json`) take precedence over env-based auth. If CC unexpectedly bypasses Bifrost, `claude auth logout` clears them.

## Path semantics

| Bifrost path                    | Client speaks      | Notes                                             |
| ------------------------------- | ------------------ | ------------------------------------------------- |
| `/anthropic/v1/messages`        | Anthropic Messages | Used by CC.                                       |
| `/openai/v1/chat/completions`   | OpenAI chat        | Used by Mastra, n8n, codex.                       |
| `/bedrock/model/{id}/invoke...` | Bedrock raw        | Avoid for CC — patched stream converter, brittle. |

VK scope decides which provider serves the request, not the path.

## Cecelia STS refresh

`ada credentials print --profile=claude-code-DO-NOT-DELETE` mints temp creds for the Cecelia role
(`CeceliaAmazonInternal` in account 175342148895) and `~/bin/sync-cecelia-creds.sh` PUTs them to
Bifrost at `/api/providers/cecelia/keys/<uuid>`.

**STS TTL is 1 hour** — the role's `MaxSessionDuration` is the AWS default of 3600s.
The Isengard `Admin` role on account 666654122230 separately has a 6h TTL.

The script is idempotent and self-throttling: it reads existing cred age from Bifrost and skips the
refresh if the existing creds are still fresh (default: refresh when within 30 min of expiry).
This makes it safe to run on a 5-minute timer.

Three triggers refresh creds on the Mac:

1. **launchd timer** `com.augustin.sync-cecelia-creds` — every 5 min (`StartInterval=300`, `RunAtLoad=true`).
2. **sleepwatcher** (`brew install sleepwatcher`, started via `brew services`) — runs `~/.wakeup`
   on every wake-from-sleep, which calls the sync script. Required because `StartInterval` does
   not catch up missed ticks across sleep.
3. **`auth.py`** (the `a` alias) — calls `run_sync_cecelia_creds()` after `mwinit -f` and the
   Isengard ada update.

If Bifrost returns `403 ExpiredToken`, run `~/bin/sync-cecelia-creds.sh` manually with `FORCE_SYNC=1`.
If that fails, Midway has likely expired upstream — run `a` first.

## Sync hook

`~/.claude/bin/session-start.sh` runs on every CC session start. It stashes uncommitted edits, pulls origin/main, pops the stash, merges MCP config from `mcp-servers.json` into `~/.claude.json`, then commits and pushes.

The hook propagates: `settings.json`, `mcp-servers.json`, `bin/`, `skills/`, `commands/`, `rules/`, `CLAUDE.md`, `statusline.sh`. It runs async so settings changes apply on the *next* session, not the one that initiated the sync.

## Compliance limits

* **64-char tool names** — Bedrock Converse API rejects MCP tools whose namespaced name (`mcp__server__tool`) exceeds 64 chars. Filter at the MCP server with `--exclude-tools=...`. Plugins whose name alone exceeds 64 chars must be disabled in `enabledPlugins`.
* **Anthropic model IDs on Bedrock** — `cecelia` and `isengard-runtime` need `us.*` or `global.*` cross-region inference profile IDs. Bare `anthropic.*` IDs reject. Mantle is the opposite: bare IDs only.
* **Tool Search through proxies** — Claude Code disables Tool Search by default when `ANTHROPIC_BASE_URL` is non-first-party. Force it on with `ENABLE_TOOL_SEARCH=true` (or `auto:N`) in `~/.claude/settings.json` env block. Otherwise CC sends every MCP tool definition on every request and burns the context window.

## Files

| Path                                                           | Where    | Purpose                                             |
| -------------------------------------------------------------- | -------- | --------------------------------------------------- |
| `~/.claude/settings.json`                                      | both     | apiKeyHelper field, ANTHROPIC\_BASE\_URL env, hooks |
| `~/.claude/bin/api-key-helper.sh`                              | both     | Per-OS VK resolver                                  |
| `~/.claude/bin/session-start.sh`                               | both     | Auto-sync hook                                      |
| `~/.config/zed/settings.json`                                  | Mac      | Zed `agent_servers.claude-acp.env` with VK          |
| `~/Library/LaunchAgents/com.augustin.sync-cecelia-creds.plist` | Mac      | 5-min STS refresh (RunAtLoad=true)                  |
| `~/Library/LaunchAgents/homebrew.mxcl.sleepwatcher.plist`      | Mac      | sleepwatcher service (brew)                         |
| `~/.wakeup`                                                    | Mac      | Sleepwatcher hook — runs sync on wake               |
| `~/bin/sync-cecelia-creds.sh`                                  | Mac      | STS refresh script                                  |
| `~/apps/bifrost/.env`                                          | debian-1 | `BIFROST_VK=` for the i3 machine                    |
| `~/apps/bifrost/compose.yaml`                                  | debian-1 | Bifrost service, image tag                          |
