A cross-platform port of the CodexBar CLI from Swift to TypeScript, running on the Bun runtime. It mirrors the original CLI's command/flag surface, its text and JSON output shapes, and the core usage / pace / cost logic. macOS-only mechanisms are replaced by cross-platform equivalents: secrets live in the OS keychain (via keytar — Windows Credential Manager, macOS Keychain, Linux libsecret) and WebKit browser scraping becomes a clean file-based stub, so it runs on Windows, Linux, and macOS.
The Swift original lives in CodexBar/ (reference only). The port
lives under src/.
- Bun ≥ 1.1 (developed against 1.3.x)
- A system keychain for secret storage. macOS Keychain and Windows Credential Manager work out of
the box; on Linux install libsecret and a Secret Service provider (e.g.
libsecret-1-0+gnome-keyring). To bypass the keychain and use a file instead, setCODEXBAR_SECRETS_FILE=<path>.
bun install
bun link # exposes the `codexbar` command globally (optional)The only runtime dependency is keytar (native
system-keychain access); typescript + @types/bun are dev deps.
bun run src/cli.ts <command> [flags] # or `codexbar <command>` after `bun link`Commands (mirrors CodexBar/docs/cli.md):
| Command | Description |
|---|---|
usage (default) |
Provider usage windows, pace, credits, reset times (text or JSON) |
cost |
Local token cost usage from Claude/Codex session logs |
cards |
Terminal card grid (--brief for a compact table) |
sessions list / sessions focus |
List local agent sessions (focus is a platform stub) |
serve |
Localhost-only HTTP JSON server (/health, /usage, /cost) |
config validate|dump|providers|enable|disable|set-api-key |
Config management |
cache clear |
Clear cookie / cost caches |
diagnose |
Safe, redacted JSON diagnostic export |
Key flags: --provider <id\|both\|all>, --source auto\|web\|cli\|oauth\|api,
--format text\|json, --pretty, --status, --no-credits,
--account/--account-index/--all-accounts. Globals: -h/--help, -V/--version,
-v/--verbose, --no-color, --log-level, --json-output, --json-only.
Exit codes: 0 success · 1 unexpected · 2 provider missing · 3 parse/format · 4 timeout.
bun run src/cli.ts --version
bun run src/cli.ts usage --provider claude --source oauth --format json --pretty
bun run src/cli.ts cost --days 30 --format json --pretty
bun run src/cli.ts cards --brief
bun run src/cli.ts serve --port 8080 # GET http://127.0.0.1:8080/health
bun run src/cli.ts diagnoseThree providers are implemented as the reference set:
- Claude (reference) — reads
~/.claude/.credentials.jsonOAuth token and callsGET https://api.anthropic.com/api/oauth/usage. Exercises the full session/weekly/pace/identity model with no macOS dependency. - Codex —
~/.codex/auth.jsonOAuth file. - OpenRouter — API-key credits.
The provider registry accepts descriptors, so the remaining ~55 CodexBar providers can be added by
implementing the ProviderDescriptor contract in src/core/contracts.ts.
In: full CLI command/flag surface, text + JSON output parity, UsagePace and UsageFormatter
logic, config load/normalize/validate, local cost scanning + pricing, serve, and the 3 providers
above.
Out (by design): the SwiftUI macOS app, the WidgetKit extension, and WebKit browser-cookie
scraping. Secrets are stored in the OS keychain via keytar
(Windows Credential Manager / macOS Keychain / Linux libsecret), with a file-backed fallback
selected by CODEXBAR_SECRETS_FILE; browser-cookie import is a stub that still honors a manual
cookieHeader from config. --source cli (PTY probes) returns a clean "unsupported" error.
bun run typecheck # tsc --noEmit (strict)
bun test # bun's built-in test runnerservebinds to127.0.0.1only, rejects non-loopbackHostheaders, and intentionally has no auth / TLS / CORS (loopback-only v1). Do not expose it to a network.diagnoseand logs never emit secret values — only booleans indicating presence.- Secrets are only ever sent in provider
Authorizationheaders. They are stored in the OS keychain by default; the file-backed fallback (CODEXBAR_SECRETS_FILE) is written with restrictive0600permissions.