Auto-detection
The first time you run openusage, no config file is required. The detector inspects your environment and creates accounts for everything it finds. You can override or extend its results by editing ~/.config/openusage/settings.json.
What gets scanned
Detection runs in four phases. Earlier phases win when the same provider/account ID would be produced twice; the process environment beats every file source.
1. Tool detectors
Tool-specific local stores: Cursor's state.vscdb (extracts the auth token), Z.AI Coding Helper's ~/.chelper/config.yaml, Codex's ~/.codex/auth.json (extracts the top-level OPENAI_API_KEY written when you sign in via API key, plus email/plan metadata from the ID token), and the binary+config-dir checks for Claude Code, GitHub Copilot, Gemini CLI, Aider, and Ollama.
2. Environment variables (API platforms)
For each supported provider, the detector checks whether a known env var is set in the running process environment:
| Env var | Provider |
|---|---|
OPENAI_API_KEY | openai |
ANTHROPIC_API_KEY | anthropic |
OPENROUTER_API_KEY | openrouter |
GROQ_API_KEY | groq |
MISTRAL_API_KEY | mistral |
DEEPSEEK_API_KEY | deepseek |
XAI_API_KEY | xai |
GEMINI_API_KEY | gemini_api |
GOOGLE_API_KEY | gemini_api (account id gemini-google) |
ALIBABA_CLOUD_API_KEY | alibaba_cloud |
MOONSHOT_API_KEY | moonshot |
ZAI_API_KEY / ZHIPUAI_API_KEY | zai |
OPENCODE_API_KEY / ZEN_API_KEY | opencode |
If the env var is present, an account is created with api_key_env set to that variable name. The actual key value is read at fetch time, never persisted.
3. File-based credential adoption
When an env var isn't set in the running process — for example because OpenUsage was launched from Spotlight, the Dock, or a desktop launcher that didn't source your shell startup files — the detector falls back to a small set of well-defined credential files:
| Source | Where | What's adopted |
|---|---|---|
| Shell rc files | ~/.zshenv, ~/.zprofile, ~/.zshrc, ~/.bash_profile, ~/.bashrc, ~/.profile, ~/.config/fish/config.fish, plus modular ~/.zshrc.d/*.zsh, ~/.bashrc.d/*.sh, ~/.config/fish/conf.d/*.fish | export VAR=..., plain VAR=..., and fish set -gx VAR ... lines whose name matches one of the API key envs above. Lines that contain shell substitutions ($VAR, $(...), backticks) are skipped — we never invoke a shell. |
| OpenCode | ~/.local/share/opencode/auth.json (%APPDATA%\opencode\auth.json on Windows) | API-key entries for Moonshot, OpenRouter, Z.AI, OpenCode (Zen), and Ollama Cloud. OAuth-typed entries are recognised but not adopted. |
| Aider | .aider.conf.yml and .env in $HOME, the closest git repo root, and the current working directory (Aider's documented search path) | Dedicated openai-api-key/anthropic-api-key YAML scalars, list-form api-key: entries (gemini=..., openrouter=..., etc.), and any standard provider env vars present in the .env files. |
A discovered key always sets the account's credential_source runtime hint with a precise locator (shell_rc:/path, aider_yaml:/path, aider_dotenv:/path, opencode_auth_json, codex_auth_json) so you can audit where a credential came from with openusage detect.
4. OS keychain probes
| Source | Where | What it does |
|---|---|---|
| macOS keychain | Claude Code-credentials generic password (Anthropic's Claude Code CLI) | Annotates the existing claude-code account with credential_source: keychain:Claude Code-credentials, or creates a minimal one if file detection missed it (e.g. when the binary isn't on $PATH over SSH). The secret value itself is read by the claude_code provider at fetch time, not at detect time. |
Local services
| Service | Signal |
|---|---|
| Ollama | local server reachable on 127.0.0.1:11434, or OLLAMA_API_KEY set |
Inspecting what was detected
Run the dedicated subcommand to see exactly what the pipeline found, including which file, env var, or keychain entry every credential came from. Tokens are masked; nothing is written to disk.
$ openusage detect
Tools detected:
Cursor IDE ide /usr/local/bin/cursor
Claude Code CLI cli /usr/local/bin/claude
Ollama cli /usr/local/bin/ollama
Accounts detected:
PROVIDER ACCOUNT AUTH CREDENTIAL SOURCE
claude_code claude-code local - keychain:Claude Code-credentials
cursor cursor-ide token eyJh...hjIs -
openai openai api_key $OPENAI_API_KEY=sk-t...cdef env
openrouter openrouter api_key sk-o...24ff opencode_auth_json
zai zai api_key 45e4...cakq opencode_auth_json
No credentials found for:
- anthropic
- groq
…
Pass --all to also list every provider in the registry. The same logic runs on dashboard startup; set OPENUSAGE_DEBUG=1 openusage to see the per-source [detect] log lines instead.
Merging with manual configuration
settings.json accepts an accounts array. When you launch the dashboard, the resolver:
- Loads manually configured accounts.
- Runs auto-detection.
- Manual wins. For each
(provider, id)pair, the manual entry takes precedence. Detected accounts that don't conflict are appended.
That means you can:
- Disable a detected provider by setting
auto_detect: false(turns off pass 1–3 entirely). - Override a detected account by declaring an account with the same
idand overriding fields likebase_urlorprobe_model. - Add a second account for a provider by giving it a different
idand pointingapi_key_envat a different env var.
{
"auto_detect": true,
"accounts": [
{
"id": "openai-work",
"provider": "openai",
"api_key_env": "OPENAI_WORK_KEY",
"probe_model": "gpt-4.1-mini"
}
]
}
In the example above, auto-detection still creates openai-default from OPENAI_API_KEY if set, and openai-work runs alongside it from the manually declared env var.
When detection misses something
If a provider you expected does not show up, walk through:
- Run
openusage detectand check the "No credentials found for:" list — that's the authoritative inventory of what's missing. - Is the env var either exported in your shell or present in one of the file sources above?
openusage detectwill show theSOURCEcolumn when something is picked up. - Is the binary on the same
$PATHOpenUsage sees?which claudefrom the same shell. - Did the tool's config dir get created? Run the tool once before relaunching.
- Run
OPENUSAGE_DEBUG=1 openusageand look at stderr for skipped detections — every adoption logs[detect] credential_source=....
See provider not detected for a per-provider checklist.
What detection does and does not do
- It does read raw API key values from a small set of documented locations: shell rc files, Aider config, OpenCode
auth.json, Codexauth.json, Z.AI's~/.chelper/config.yaml, Cursor'sstate.vscdb. Adopted values live only in memory under the runtime-onlyTokenfield (json:"-") — they are never written tosettings.json. - It does not invoke any shell or run any user code; shell rc parsing skips lines that would require expansion.
- It does not make network calls during detection itself; that only happens when a provider's
Fetch()runs. - It does not read the secret value of OS keychain entries — only their presence. The
claude_codeprovider performs the actual keychain read at fetch time. - It does not modify any tool's config (only the integration installer does that).