id: opencode
name: opencode
category: feature
displayName: OpenCode
description: "sst's open-source, provider-agnostic AI coding agent (TUI). Model + provider key configurable; auth and session state persist across container rebuilds."
documentationURL: https://opencode.ai/docs/
options:
  version:
    type: string
    default: latest
    description: 'npm-style version spec for `opencode-ai` (`latest`, `^0.4`, `0.4.2`).'
    surface: silent
  model:
    type: string
    default: ''
    description: 'Default model as `provider/model-id` (e.g. `anthropic/claude-sonnet-4-6`, `openai/gpt-4o-mini`). The provider is derived from the prefix before `/`. Empty: pick interactively on first run.'
    surface: yml
  apiToken:
    type: string
    default: ''
    description: 'API key for the model provider (derived from `model`); written to `provider.<x>.options.apiKey` in opencode.json. Empty for `opencode auth login` on first run.'
    surface: env
  npm:
    type: string
    default: ''
    description: 'Custom/local providers only (e.g. Ollama): the AI-SDK driver package, usually `@ai-sdk/openai-compatible`. Setting this switches `model` to custom-provider mode and builds a full provider block from `model` + `baseUrl`. Empty for hosted providers.'
    surface: silent
  baseUrl:
    type: string
    default: ''
    description: 'Custom/local providers only: the endpoint URL, e.g. `http://ollama:11434/v1` (a service on the Docker network). Used together with `npm`.'
    surface: silent
  theme:
    type: string
    default: ''
    description: 'TUI theme, e.g. `system` (follows your terminal), `tokyonight`, `catppuccin`. Written to `~/.config/opencode/tui.json`, so a new workbench looks like the last one. Empty: whatever you pick with `/theme` in the TUI.'
    surface: yml
  lsp:
    type: boolean
    default: false
    description: "Start OpenCode's built-in language servers, so the agent sees type errors and unresolved imports right after an edit instead of when the tests run. Off by default, as upstream. A server whose toolchain is missing does not start."
    surface: yml
feature:
  version: 1.2.1
  # Installs a global npm package, so it has to run after the node
  # feature: otherwise npm resolves the version against the Node the
  # runtime image ships, which a pinned `node:<major>` then replaces.
  installsAfter: [ghcr.io/devcontainers/features/node]
  # `.config` holds opencode.json and the agents/commands, `.local/share` the
  # session database and auth, `.local/state` the XDG state dir - which is
  # where opencode keeps the model picker's recent/favourite list and its
  # per-model variant choice. Without the third one every apply resets the
  # model picker to empty.
  #
  # `.cache/opencode` was left out while it held only models.json and a
  # binary, both cheap to re-fetch. With `lsp` it also holds the language
  # servers opencode downloads on first contact with a file type, which was
  # 28 MB after two of them. Those came back on every apply, in the middle
  # of whatever an agent was doing. Per container, not machine-wide: the
  # directory mixes those downloads with per-install state, and the Go
  # caches show what a genuinely shareable cache looks like.
  persistentHomePaths:
    [
      .config/opencode,
      .local/share/opencode,
      .local/state/opencode,
      .cache/opencode,
    ]
briefing:
  - text: 'OpenCode (`opencode`) — open-source, provider-agnostic AI coding agent. Reads this AGENTS.md as project instructions. Model + provider key (when set in the yml) live in `~/.config/opencode/opencode.json`; otherwise authenticate once with `opencode auth login`.'
