Skip to content
RunicGet Runic

Runic Docs Reference

Codex provider

Codex has four usage data paths (OAuth API, web dashboard, CLI RPC, CLI PTY) plus a local cost-usage relay. The OAuth API is the default app source when credentials are available; web access is optional for dashboard extras.

Data sources + fallback order

App default selection (debug menu disabled)

  1. OAuth API (auth.json credentials).
  2. CLI RPC, with CLI PTY fallback when needed.
  3. If “Access OpenAI via web” is enabled, dashboard extras load in parallel and the source label becomes primary + openai-web.

CLI default selection (--source auto)

  1. OpenAI web dashboard (when available).
  2. Codex CLI RPC, with CLI PTY fallback when needed.

OAuth API (preferred for the app)

  • Reads OAuth tokens from ~/.codex/auth.json (or $CODEX_HOME/auth.json).
  • Refreshes access tokens when last_refresh is older than 8 days.
  • Calls GET https://chatgpt.com/backend-api/wham/usage (default) with Authorization: Bearer <token>.
  • Pro accounts can report only the weekly cap (seen 2026-10): primary_window is the 7-day window and secondary_window is null. Runic keeps the window’s 7-day length and titles it Weekly instead of Session, with no 5h row — the same way codex’s own /status names limits by duration.

OpenAI web dashboard (optional)

  • Preferences → Usage → “Access OpenAI via web”.
  • URL: https://chatgpt.com/codex/settings/usage.
  • Uses an off-screen WKWebView with a per-account WKWebsiteDataStore.
    • Store key: deterministic UUID from the normalized email.
  • WebKit store can hold multiple accounts concurrently.
  • Cookie import (when WebKit store has no matching session or login required):
    1. Safari: ~/Library/Cookies/Cookies.binarycookies
    2. Chrome/Chromium forks: ~/Library/Application Support/Google/Chrome/*/Cookies
    3. Firefox: ~/Library/Application Support/Firefox/Profiles/*/cookies.sqlite
    • Domains loaded: chatgpt.com, openai.com.
    • No cookie-name filter; we import all matching domain cookies.
  • Account match:
    • Signed-in email extracted from client-bootstrap JSON in HTML (or __NEXT_DATA__).
    • If Codex email is known and does not match, the web path is rejected.
  • Web scrape payload (via OpenAIDashboardScrapeScript + OpenAIDashboardParser):
    • Rate limits (5h + weekly) parsed from body text.
    • Credits remaining parsed from body text.
    • Code review remaining (%).
    • Usage breakdown chart (Recharts bar data + legend colors).
    • Credits usage history table rows.
    • Credits purchase URL (best-effort).
  • Errors surfaced:
    • Login required or Cloudflare interstitial.

Codex CLI RPC (default CLI fallback)

  • Launches local RPC server: codex -s read-only -a untrusted app-server.
  • JSON-RPC over stdin/stdout:
    • initialize (client name/version)
    • account/read
    • account/rateLimits/read
  • Provides:
    • Usage windows (primary + secondary) with reset timestamps.
    • Credits snapshot (balance, hasCredits, unlimited).
    • Account identity (email + plan type) when available.

Codex CLI PTY fallback (/status)

  • Runs codex in a PTY via TTYCommandRunner.
  • Sends /status, parses the rendered screen:
    • Credits: line
    • 5h limit line → percent + reset text
    • Weekly limit line → percent + reset text
  • Retry once with a larger terminal size on parse failure.
  • Detects update prompts and surfaces a “CLI update needed” error.

Account identity resolution (for web matching)

  1. Latest Codex usage snapshot (from RPC, if available).
  2. ~/.codex/auth.json (JWT claims: email + plan).
  3. OpenAI dashboard signed-in email (cached).
  4. Last imported browser cookie email (cached).

Credits

  • Web dashboard fills credits only when OAuth/CLI do not provide them.
  • Credits returned with the primary usage response populate the app directly; a separate CLI probe runs only when that refresh has no balance.
  • When no balance can be retrieved, the menu shows 0 with an unavailable note. A reported zero has no unavailable note, and web fetch errors stay out of the credits section.
  • CLI RPC: account/rateLimits/read → credits balance.
  • CLI PTY fallback: parse Credits: from /status.

Cost usage relay

  • Live source files:
    • Today’s ~/.codex/sessions/YYYY/MM/DD/*.jsonl
    • Or today’s $CODEX_HOME/sessions/... files if CODEX_HOME is set.
  • Historical source:
    • Runic-owned event relay: ~/Library/Application Support/Runic/relay/codex-events.jsonl
    • Daily materialized cache: ~/Library/Application Support/Runic/ledger-cache/codex-daily.json
    • One-time seed from legacy scanner cache: ~/Library/Caches/Runic/cost-usage/codex-v1.json
  • Refresh rule:
    • Provider JSONLs before today are not reopened during normal refresh.
    • runic cost --rebuild --provider codex is the explicit repair path that reopens the 30-day Codex JSONL window.
    • Today’s Codex JSONLs are normalized into relay events with source fingerprints and scan watermarks.
    • Daily totals are materialized from the newest relay snapshot for each day, then merged into the 30-day token/cost view.
    • Legacy cache days with implausible token/request totals are quarantined before any cache seeding.
  • Parser:
    • Parses today’s event_msg token_count entries and turn_context model markers.
    • Computes input/cached/output token deltas and per-model cost.

Key files

  • Web: Sources/RunicCore/OpenAIWeb/*
  • CLI RPC + PTY: Sources/RunicCore/UsageFetcher.swift, Sources/RunicCore/Providers/Codex/CodexStatusProbe.swift
  • Cost usage relay: Sources/RunicCore/CostUsageFetcher.swift, Sources/RunicCore/UsageLedger/CodexUsageLogSource.swift, Sources/RunicCore/UsageLedger/LedgerCache.swift

Read the source ↗ Checked against Runic 2.13.5 · 9730f91