Skip to content

Latest commit

 

History

History
161 lines (125 loc) · 6.28 KB

CONFIGURATION.md

File metadata and controls

161 lines (125 loc) · 6.28 KB

Configuration

English | Espanol

All settings are environment variables. Defaults are safe: with no configuration at all, the plugin resolves the key from the standard stores and enables every hook.

Credentials

Variable Default Meaning
COMMAND_CODE_API_KEY unset Highest priority. Used as-is (trimmed, surrounding quotes stripped).
COMMANDCODE_KEY_FILE unset Absolute path to a file containing only the key. Ignored when the file is missing or empty, so the cascade keeps going.
COMMANDCODE_API_KEYS unset Comma or whitespace separated pool. Two or more keys enable rotation.
COMMANDCODE_KEYS_FILE unset Pool file, one label=key or bare key per line. # starts a comment.
CMD_ZDR unset Set to 1 to send x-cmd-zdr: 1 (zero data retention).
XDG_CONFIG_HOME ~/.config Base for the third resolution step: $XDG_CONFIG_HOME/commandcode/key.txt.

Resolution order

COMMAND_CODE_API_KEY
      -> COMMANDCODE_KEY_FILE
      -> $XDG_CONFIG_HOME/commandcode/key.txt
      -> /etc/environment (COMMAND_CODE_API_KEY)
      -> ~/.commandcode/auth.json          (apiKey | api_key | token | accessToken)
      -> ~/.commandcode/credentials.json
      -> ~/.commandcode/config.json
      -> none  (injection disabled, everything else keeps working)

resolveApiKeyWithSource() reports which store was used, which is what the tests assert on. resolveApiKey() returns only the string.

Host allow-list

Variable Default Meaning
COMMANDCODE_ALLOWED_HOSTS unset Comma-separated hostnames that may also receive the key, in addition to api.commandcode.ai.

Use this only for a self-hosted gateway that genuinely terminates your Command Code traffic. Every host added here can read the API key.

COMMANDCODE_ALLOWED_HOSTS=gateway.internal,proxy.lan

Key rotation

A pool of two or more keys activates rotation. With one key (or none) the plugin keeps the single-key behaviour and never touches an Authorization header the host already set.

Source Format
COMMANDCODE_API_KEYS key1,key2 or whitespace separated
COMMANDCODE_KEYS_FILE one label=key or bare key per line, # comments
~/.config/commandcode/keys.txt same format, used when neither variable is set

Cooldown recorded per key after a response that blames the credential:

Status Cooldown
402 insufficient credits 24h
401 / 403 invalid or not entitled 24h
429 rate limited Retry-After when present and at most 6h, else 5m
5xx none (not the key's fault)

When every key is cooling down the one that recovers first is used, so the request still reaches upstream. State lives in <state>/commandcode-keys-state.json (mode 0600, labels only, never keys) and each cooldown is appended to <state>/commandcode-rotation.log. | commandcode-errors.log | append | JSON lines, one per decorated failure |

Transport

Variable Default Meaning
CC_NO_CONNECTION_CLOSE unset Set to 1 to stop injecting Connection: close.
sentinel file <plugin>/.disable-connection-close absent Same effect as the variable, togglable without a restart.

Both switches exist so the header can be disabled for measurement without editing code. Disabling it restores keep-alive reuse, which reintroduces the stale-socket ECONNRESET case if that is what you are hitting.

The watchdog timeout (60s after the first chunk) is a constant in src/index.ts (WATCHDOG_TIMEOUT_MS), not an environment variable.

Telemetry and cache

Variable Default Meaning
COMMANDCODE_STATE_DIR $XDG_STATE_HOME/opencode or ~/.local/state/opencode Directory for the three logs and the model cache.

Files written under the state directory:

File Append/overwrite Notes
commandcode-sanitizer.log append JSON lines, one per repaired payload
commandcode-watchdog.log append JSON lines, one per aborted stream
commandcode-retries.log append JSON lines, Command Code retries only
commandcode-rotation.log append JSON lines, one per key cooldown (label, status, reason, reset time)
commandcode-keys-state.json overwrite Cooldown state per key label (0600, no secrets)
commandcode-models-cache.json overwrite { at, models[] }, 6h TTL

Logs are append-only and never rotated by the plugin. At the observed event rate (tens of lines per week) this is not a concern; if you want rotation, point COMMANDCODE_STATE_DIR at a directory managed by logrotate.

Timing constants

Constant Value Location
API request timeout 10s DEFAULT_TIMEOUT_MS in src/client/api.ts
Catalog cache TTL 6h CATALOG_TTL_MS in src/client/api.ts
SSE inactivity window 60s WATCHDOG_TIMEOUT_MS in src/index.ts
Default output limit per model 16384 applyModelCatalog in src/index.ts

OpenCode integration

The plugin registers itself; only the provider block belongs in opencode.json. Install it with the GitHub specifier (no npm, no build), a local clone, or by dropping it into the auto-discovered plugins directory - see the readme for the three options.

{
  "plugins": [
    "github:JoshRob297/opencode-commandcode"
  ],
  "providers": {
    "commandcode": {
      "name": "Command Code",
      "package": "@opencode/ai/providers/openai-compatible",
      "settings": {
        "baseURL": "https://api.commandcode.ai/provider/v1",
        "apiKey": "{file:~/.config/commandcode/key.txt}"
      }
    }
  }
}

Notes:

  • The models map inside the provider is optional. Anything listed there wins for the same id; discovery adds the rest at startup.
  • Keep apiKey in the provider block as a fallback for tooling that bypasses the plugin. The plugin resolves the key independently.
  • Do not load two plugins that register commandcode_quota at the same time.

Testing switches

Variable Default Meaning
COMMANDCODE_LIVE_TESTS unset Set to 1 to run tests/live.test.ts, which calls the real API.
bun test                             # offline, no quota consumed
COMMANDCODE_LIVE_TESTS=1 bun test    # adds the live suite