/gsd keys
What It Does
Section titled “What It Does”/gsd keys manages the API credentials GSD uses to call external services. It covers every category GSD needs: LLM providers, search engines, tool APIs, and remote bot integrations. All keys are stored in ~/.gsd/agent/auth.json with 600 permissions — the doctor subcommand enforces this automatically.
Keys can come from two sources: auth.json (managed by this command) or environment variables (e.g. ANTHROPIC_API_KEY). auth.json takes priority. When multiple keys are stored for the same provider, GSD uses them in round-robin order. Providers that support OAuth (like Anthropic and GitHub Copilot) show a prompt directing you to use /login for browser-based authentication instead.
Keys are always masked in output — only the first 4 and last 4 characters are shown (e.g. sk-a***cdef). Keys with 8 or fewer characters show only the first 2 and last 2.
/gsd keys [subcommand] [provider]With no arguments, shows the full key status dashboard.
/gsd keys Show key status dashboard/gsd keys list Same as above (aliases: status)/gsd keys add [provider] Add a key interactively/gsd keys remove [provider] Remove a key (aliases: rm, delete)/gsd keys test [provider] Validate key(s) with a live API call (alias: validate)/gsd keys rotate [provider] Replace an existing key/gsd keys doctor Health check all keys (alias: health)The provider argument is optional for all subcommands — omitting it triggers an interactive picker.
How It Works
Section titled “How It Works”Command Flow
Section titled “Command Flow”Subcommands
Section titled “Subcommands”list / status (default)
Section titled “list / status (default)”Prints a grouped dashboard of all known providers organized by category. Each row shows whether the key is configured, its source (auth.json or env), and a masked credential description. Backed-off providers are flagged. Categories are displayed in this order: LLM Providers → Search Providers → Tool Keys → Remote Integrations.
The summary line at the bottom reports how many providers are configured, how many come from auth.json versus environment variables, and — when OAuth credentials are present — how many are OAuth-based.
add [provider]
Section titled “add [provider]”Prompts for a provider (if not given), then:
- If the provider supports OAuth, offers a choice between API key and browser login. Choosing “Browser login (OAuth)” shows a message directing you to use
/loginfor the full browser authentication flow. - Prompts for the API key via text input.
- Validates the key format against known prefixes (e.g. Anthropic keys must start with
sk-ant-). If the prefix doesn’t match, a warning is shown but the key is saved anyway. - Stores the key in
auth.jsonand sets the corresponding environment variable in the current process.
After saving, the session reloads so the new credential is immediately active.
remove [provider] / rm / delete
Section titled “remove [provider] / rm / delete”Shows only currently configured providers. For providers with a single key, a confirmation dialog is shown before removal. For providers with multiple keys, presents a per-key picker (or “Remove all”). Removes the key from auth.json and clears the environment variable.
After removing, the session reloads so the change takes effect immediately.
test [provider] / validate
Section titled “test [provider] / validate”Makes a live API call to validate the key. Tests all configured providers when no argument is given. Each provider has a specific test endpoint — for example, Anthropic uses POST /v1/messages with a minimal payload, OpenAI uses GET /v1/models. Results are reported as:
| Status | Meaning |
|---|---|
valid | HTTP 200 received |
invalid | HTTP 401 or 403 |
rate_limited | HTTP 429 |
error | Network error, timeout (15s), or unexpected status |
skipped | No test endpoint configured, key uses credential chain, or key is not in auth.json |
Note: the test reads credentials from auth.json only. Providers configured solely via environment variable (not stored in auth.json) will show as skipped with “not configured” even though they appear as configured in the dashboard.
rotate [provider]
Section titled “rotate [provider]”Shows only providers with API key credentials. Shows the current masked key, prompts for a new one, then optionally validates it with a live API call before saving. If the new key returns invalid (HTTP 401/403), rotation is cancelled. Any other test outcome (error, rate_limited, skipped) shows a warning but proceeds. OAuth credentials for the same provider are preserved when the API key is replaced.
After rotating, the session reloads so the new key is immediately active.
doctor / health
Section titled “doctor / health”Runs static checks without making network calls:
- Permissions —
auth.jsonmust bechmod 600. Fixes automatically if wrong. - Empty keys — Flags keys stored as empty strings (from skipped onboarding).
- Expired OAuth — Warns on expired tokens; reports tokens expiring within 5 minutes as info.
- Env conflicts — Warns when
auth.jsonand an environment variable hold different values for the same provider (auth.jsonwins). - Backed-off keys — Flags providers where all keys are in rate-limit backoff, including remaining backoff time if known.
- Missing LLM — Errors if no LLM provider has any credential at all.
- Duplicate keys — Warns if the same key value is registered for multiple providers.
Provider Registry
Section titled “Provider Registry”| Category | Providers |
|---|---|
| LLM | Anthropic (Claude), OpenAI, GitHub Copilot, ChatGPT Plus/Pro (Codex), Google Gemini CLI, Antigravity, Google (Gemini), Groq, xAI (Grok), OpenRouter, Mistral, Ollama Cloud, Custom (OpenAI-compat), Cerebras, Azure OpenAI |
| Search | Tavily Search, Brave Search |
| Tool | Context7 Docs, Jina Page Extract |
| Remote | Discord Bot, Slack Bot, Telegram Bot |
Providers with OAuth support (Anthropic, GitHub Copilot, ChatGPT Plus/Pro, Google Gemini CLI, Antigravity) redirect to /login instead of accepting an API key directly.
Storage Details
Section titled “Storage Details”Keys are stored in ~/.gsd/agent/auth.json. The file is created automatically on first use. Its directory is created with mkdirSync({ recursive: true }) if missing.
When auth.json holds a key, GSD also injects it into the current process’s environment (e.g. process.env.ANTHROPIC_API_KEY = key) so downstream tooling picks it up without requiring a shell restart.
What Files It Touches
Section titled “What Files It Touches”Creates
Section titled “Creates”| File | Purpose |
|---|---|
~/.gsd/agent/auth.json | Credential store — created on first add if absent |
~/.gsd/agent/ | Directory created if missing |
| File | Purpose |
|---|---|
~/.gsd/agent/auth.json | Existing credentials for list, test, rotate, remove |
Writes
Section titled “Writes”| File | Purpose |
|---|---|
~/.gsd/agent/auth.json | Updated on add, remove, and rotate |
Examples
Section titled “Examples”Show the key status dashboard:
> /gsd keys
GSD API Key Manager
LLM Providers ✓ anthropic — OAuth (expires in 2h 14m) ✓ openai — API key (sk-p***7890) ✗ google — not configured (aistudio.google.com/apikey) …
Search Providers ✗ tavily — not configured (tavily.com/app/api-keys) …
Source: /Users/you/.gsd/agent/auth.json 2 configured | 1 in auth.json | 1 from env | 1 OAuthAdd a key interactively:
> /gsd keys add openai
API key for OpenAI: [input]● Key saved for OpenAI: sk-p***7890Add a key for a provider that supports OAuth:
> /gsd keys add anthropic
Anthropic (Claude) — how do you want to authenticate? ○ API key ○ Browser login (OAuth)Choosing “Browser login (OAuth)” shows:
Use /login to authenticate via OAuth with Anthropic (Claude).The /login command handles the full browser flow.Test all configured keys:
> /gsd keys test
Testing 3 keys...
API Key Test Results
✓ anthropic — valid 312ms ✗ openai — invalid key (401) 88ms — github-copilot — uses credential chain (not testable)
1 valid | 1 invalid | 1 skippedRun the health check:
> /gsd keys doctor
API Key Health Check
✓ auth.json permissions were 644 — fixed to 600 ⚠ OpenAI: empty key stored (from skipped setup) — run /gsd keys add openai ✗ No LLM provider configured — run /gsd keys add or /login
1 error | 1 warning | 1 fixedRotate a key with validation:
> /gsd keys rotate anthropic
Current key: sk-a***cdefNew API key for Anthropic (Claude): [input]Test key? Validate the new key before saving? [yes]● Key validated successfully (287ms).● Key rotated for Anthropic (Claude): sk-a***9999Remove a specific key:
> /gsd keys remove openai
Remove API key (sk-p***7890) for OpenAI? [yes]● Key removed for OpenAI.Related Commands
Section titled “Related Commands”/gsd doctor— Full GSD health check including key status/gsd prefs— Configure GSD preferences and model settings/gsd setup— Global setup status, includingsetup keysshortcut