Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. Runtime
Overview
The SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. Runtime is the core engine of OpenCode. It preserves durable conversational history while assembling the system context an agent needs to act in its environment, and it executes provider turns with tool settlement and compaction. The V2 design separates durable prompt admission from process-local model execution so sessions survive restarts and can later be clustered.
Stakeholders
| Stakeholder | Interest |
|---|---|
| End users | Sessions that survive crashes and restart with full history replay |
| Core team | Clean separation of durable admission from execution; no legacy tool loops |
| Operators | Introspectable, replayable sessions; interruption that targets the right process |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall persist each user prompt as a durable `session_input` row before scheduling execution. | Must | The system shall persist each user prompt as a durable session_input row before scheduling execution. |
| FR-02MustThe system shall promote admitted prompts into session history only at a safe provider-turn boundary. | Must | The system shall promote admitted prompts into session history only at a safe provider-turn boundary. |
| FR-03MustThe system shall render a baseline system context at the start of each context epoch and reuse it across restarts. | Must | The system shall render a baseline system context at the start of each context epoch and reuse it across restarts. |
| FR-04MustThe system shall make exactly one `llm.stream(request)` call per provider turn and reload projected history before durable continuation. | Must | The system shall make exactly one llm.stream(request) call per provider turn and reload projected history before durable continuation. |
| FR-05MustThe system shall execute tool calls through the LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped tool registry and persist bounded model tool output to history. | Must | The system shall execute tool calls through the LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped tool registry and persist bounded model tool output to history. |
| FR-06MustThe system shall spill oversized tool output to managed tool-output files while retaining a bounded preview in history. | Must | The system shall spill oversized tool output to managed tool-output files while retaining a bounded preview in history. |
| FR-07MustThe system shall start a new context epoch with a fresh baseline on completed compaction. | Must | The system shall start a new context epoch with a fresh baseline on completed compaction. |
| FR-08MustThe system shall emit durable mid-conversation system messages when context sources change, admitted lazily at the next safe boundary. | Must | The system shall emit durable mid-conversation system messages when context sources change, admitted lazily at the next safe boundary. |
| FR-09MustThe system shall interrupt the active process-local ownership chain for a session and treat idle/missing interruption as a no-op. | Must | The system shall interrupt the active process-local ownership chain for a session and treat idle/missing interruption as a no-op. |
| FR-10ShouldThe system shall treat steering prompts and queued prompts with distinct promotion semantics at safe boundaries. | Should | The system shall treat steering prompts and queued prompts with distinct promotion semantics at safe boundaries. |
| FR-11ShouldThe system shall coalesce prompt wakeups and allow different sessions to run concurrently via the run coordinator. | Should | The system shall coalesce prompt wakeups and allow different sessions to run concurrently via the run coordinator. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustSessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. drains shall be process-local and resumable from durable artifacts after a crash. | Must | Reliability | SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. drains shall be process-local and resumable from durable artifacts after a crash. |
| NFR-02MustContext source rendering shall be deterministic regardless of concurrent producer evaluation. | Must | Correctness | Context source rendering shall be deterministic regardless of concurrent producer evaluation. |
| NFR-03ShouldProvider-turn allowance shall reset once per batch of promoted inputs, not per input. | Should | Performance | Provider-turn allowance shall reset once per batch of promoted inputs, not per input. |
| NFR-04ShouldEach drain and compaction shall be traceable through EffectThe functional effect system used pervasively in the core runtime. telemetry. | Should | Observability | Each drain and compaction shall be traceable through EffectThe functional effect system used pervasively in the core runtime. telemetry. |
Constraints
- Prompt admission and execution must remain separate;
SessionV2.prompt(...)admits one durable row then schedules advisorySessionExecution.wake. - Reusing a session ID adopts the existing session; reusing a prompt message ID reconciles an exact retry only when session, prompt, and delivery mode match.
SessionExecutionis process-global and session-ID based; no layer may take a session ID into execution plumbing.- Local session drains remain process-local until clustering is implemented.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe system shall persist each user prompt as a durable `session_input` row before scheduling execution.
- Given a client posts a prompt to an existing session
- When the server receives it
- Then a durable
session_inputrow exists before any provider call is scheduled
- FR-02MustThe system shall promote admitted prompts into session history only at a safe provider-turn boundary.
- Given an admitted prompt and an in-progress drain requiring continuation
- When the runner reaches a safe provider-turn boundary
- Then the prompt is promoted into session history exactly once
- FR-04MustThe system shall make exactly one `llm.stream(request)` call per provider turn and reload projected history before durable continuation.
- Given a provider turn is running
- When it executes
- Then exactly one
llm.streamcall occurs and projected history was reloaded beforehand
- FR-07MustThe system shall start a new context epoch with a fresh baseline on completed compaction.
- Given history exceeds compaction thresholds
- When compaction completes
- Then a new context epoch begins with a freshly rendered baseline and earlier mid-conversation system messages leave projected model history
- FR-08MustThe system shall emit durable mid-conversation system messages when context sources change, admitted lazily at the next safe boundary.
- Given a context source value changes during a drain
- When the next safe provider-turn boundary is reached
- Then one combined mid-conversation system message is admitted durably
- FR-09MustThe system shall interrupt the active process-local ownership chain for a session and treat idle/missing interruption as a no-op.
- Given an active ownership chain for a session
- When an interruption is requested
- Then the active chain is targeted and an idle session yields a no-op
- NFR-02MustContext source rendering shall be deterministic regardless of concurrent producer evaluation.
- Given multiple context sources registered with stable keys
- When the system context is rendered
- Then the output is identical regardless of producer evaluation order
Conflicts
None identified yet.
Open Questions
- How should post-crash continuation recovery retry provider work (explicitly deferred design)?
- When will clustered session execution move beyond process-local drains?
Specification: SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. Runtime
Overview
The V2 session runtime admits durable prompts, promotes them at safe boundaries, renders an immutable baseline system context per epoch, and runs one provider turn at a time with tool settlement and compaction.
Execution is coordinated by a process-global SessionExecution that discovers placement through SessionStore and a location map; drains have no durable identity.
Architecture
SessionV2.prompt() ββadmitβββΆ session_input (durable)
β advisory wake
βΌ
SessionExecution (process-global)
β drain
SessionRunCoordinator
(joins resumes, coalesces wakeups)
β
SessionRunner (LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped)
ββββββββββββββββββΌββββββββββββββββββ
βΌ βΌ βΌ
prompt promotion system context llm.stream (1x)
(safe boundary) registry/epoch β
βΌ
tool registry (LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.)
β
bounded model tool output
+ managed output files
Data Models
session_input
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | ulid | PK, not null | Prompt/message identity |
| session_id | id | FK, not null | Owning session |
| delivery | enum | not null | steer or queue |
| status | enum | not null | admitted, promoted, etc. |
context_epoch
| Field | Type | Constraints | Description |
|---|---|---|---|
| session_id | id | FK, not null | Owning session |
| baseline | text | not null | Immutable baseline system context |
| snapshot | json | not null | Context snapshot per source key |
mid_conversation_system_message
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | ulid | PK | Message identity |
| session_id | id | FK | Owning session |
| rendered | text | not null | Exact combined text sent to the model |
APIApplication Programming Interface Contracts
Internal runtime contracts (not HTTP; the HTTP surface is covered by FEAT-0006).
SessionV2.prompt(request) -> Prompt
Request
| Field | Type | Required | Description |
|---|---|---|---|
| sessionID | id | yes | Target session |
| messageID | id | yes | Prompt identity (reused for exact-retry reconciliation) |
| delivery | enum | no | Defaults to steer |
Behavior: admits one durable session_input row, then schedules SessionExecution.wake(sessionID) unless resume: false requests admit-only behavior.
Sequences
Prompt admission and promotion
Client -> SessionV2.prompt -> session_input (admitted)
SessionV2.prompt -> SessionExecution.wake (advisory)
SessionExecution -> SessionRunCoordinator (join/coalesce)
SessionRunner -> promote eligible input at safe boundary
SessionRunner -> render baseline if new epoch
SessionRunner -> llm.stream (single call)
Model -> tool calls -> Tool Registry -> bounded output -> history
CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch.
SessionRunner detects threshold -> compaction
compaction complete -> new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. -> fresh baseline + snapshot
earlier mid-conversation system messages leave projected model history
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Admission vs execution | Separate; prompt admits then wakes | Survives crashes; enables future clustering |
| Drains | Process-local, no durable identity | Clustering deferred; durable recovery reasons from artifacts |
| Provider turns | One llm.stream per turn, history reloaded |
Avoids bridging legacy tool loops |
| Interruption | Targets active process-local ownership chain | Idle/missing interruption is a no-op |
| Context admission | Lazy at safe boundary | Deterministic; never pushed asynchronously |
Risks and Unknowns
- Post-crash continuation recovery has no durable drain identity and requires a separate explicit design before it may retry provider work.
- Clustering moves drains off a single process; placement semantics for explicit workspace identity are reserved for the future.
experimental.chat.system.transformcan mutate the baseline arbitrarily and has no V2 plugin equivalent yet.
Out of Scope
- HTTP APIApplication Programming Interface surface (see FEAT-0006).
- Provider/model catalog resolution (see FEAT-0003).
- Tool execution semantics beyond bounded output (see FEAT-0002).
requirements
- How should post-crash continuation recovery retry provider work (explicitly deferred design)?
- When will clustered session execution move beyond process-local drains?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). & Tool System
Overview
The AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). & Tool System defines how OpenCode selects an agent configuration, resolves model and permissions, and executes tool calls returned by the model. It provides a LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped tool registry of built-in tools, a permission model for local and provider-executed tools, and the skill mechanism for invoking specialized workflows.
Stakeholders
| Stakeholder | Interest |
|---|---|
| End users | Tools that act correctly within the current directory; safe permission prompts |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks./agent authors | Stable agent definition format and tool extension points |
| Core team | Tool registry invariants; bounded output; permission model integrity |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall provide built-in agents including a full-access `build` agent and a read-only `plan` agent. | Must | The system shall provide built-in agents including a full-access build agent and a read-only plan agent. |
| FR-02MustThe system shall expose built-in tools for filesystem access (`read`, `write`, `edit`, `apply_patch`, `glob`, `grep`), shell execution (`shell`), and web access (`webfetch`, `websearch`). | Must | The system shall expose built-in tools for filesystem access (read, write, edit, apply_patch, glob, grep), shell execution (shell), and web access (webfetch, websearch). |
| FR-03MustThe system shall enforce a tool registry that bounds every tool's model-visible output using a configured maximum lines or bytes. | Must | The system shall enforce a tool registry that bounds every tool's model-visible output using a configured maximum lines or bytes. |
| FR-04MustThe system shall enforce LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped filesystem authority, allowing absolute paths only within managed tool-output storage. | Must | The system shall enforce LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped filesystem authority, allowing absolute paths only within managed tool-output storage. |
| FR-05MustThe system shall retain the effective agent of the provider turn that issued a tool call so a later agent switch cannot change that call's policy. | Must | The system shall retain the effective agent of the provider turn that issued a tool call so a later agent switch cannot change that call's policy. |
| FR-06MustThe system shall select the agent and model when a provider turn starts and apply later changes only to the next turn. | Must | The system shall select the agent and model when a provider turn starts and apply later changes only to the next turn. |
| FR-07MustThe system shall provide auxiliary tools: `task`, `todo`/`todowrite`, `question`, `plan`, `lsp`, and `skill`. | Must | The system shall provide auxiliary tools: task, todo/todowrite, question, plan, lsp, and skill. |
| FR-08ShouldThe system shall allow tools to apply tool-specific truncation before the registry enforces the final limit. | Should | The system shall allow tools to apply tool-specific truncation before the registry enforces the final limit. |
| FR-09ShouldThe system shall expose a permission APIApplication Programming Interface for deferring and resolving pending permission requests per session. | Should | The system shall expose a permission APIApplication Programming Interface for deferring and resolving pending permission requests per session. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustTools shall not read or write outside LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped authority except managed tool-output paths. | Must | Security | Tools shall not read or write outside LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped authority except managed tool-output paths. |
| NFR-02MustA successful tool operation shall remain successful even if its managed output file cannot be retained. | Must | Reliability | A successful tool operation shall remain successful even if its managed output file cannot be retained. |
| NFR-03ShouldTool settlement bounding shall be interruption-safe so raw oversized success is never published before a correction. | Should | Performance | Tool settlement bounding shall be interruption-safe so raw oversized success is never published before a correction. |
Constraints
- Provider-executed tool results are provider-native transcript facts outside generic registry bounding and need provider-aware pruning.
- Local tool authorization and pending permission requests retain the effective agent of the issuing provider turn.
- Custom agents and tools may be contributed under
.opencode/agentand.opencode/tool.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe system shall provide built-in agents including a full-access `build` agent and a read-only `plan` agent.
- Given a fresh install
- When the user lists agents
- Then
build(full access) andplan(read-only, denies edits) are available
- FR-03MustThe system shall enforce a tool registry that bounds every tool's model-visible output using a configured maximum lines or bytes.
- Given a tool returns very large text output
- When the registry settles the result
- Then the model-visible output is bounded to the configured line/byte limit with a managed output path retained
- FR-04MustThe system shall enforce LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped filesystem authority, allowing absolute paths only within managed tool-output storage.
- Given a tool attempts to read an arbitrary absolute path
- When the path is outside LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped authority and not a managed output path
- Then the operation is denied
- FR-05MustThe system shall retain the effective agent of the provider turn that issued a tool call so a later agent switch cannot change that call's policy.
- Given a tool call is in flight and the user switches agents
- When a permission check runs for that call
- Then the policy of the original agent still applies
- NFR-02MustA successful tool operation shall remain successful even if its managed output file cannot be retained.
- Given a tool operation succeeded
- When retaining its managed output file fails
- Then the operation remains successful and a lossy bounded output is recorded with diagnostics
Conflicts
None identified yet.
Open Questions
- How should provider-executed tool results be context-controlled given some providers require exact structured round-trip payloads?
Specification: AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). & Tool System
Overview
Agents bind a system instruction set, model selection, and permission policy. Tool calls flow through a LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped registry that validates results, bounds model-visible output, and manages oversized output as temporary files. Permissions and agent selection are pinned to the provider turn that issued the call.
Architecture
provider turn starts -> select agent + model (sampled)
model returns tool calls βββββββββββββββΆ Tool Registry (LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.-scoped)
β validate structured result
β tool-specific truncation (optional)
β generic bounding (max lines/bytes)
βΌ
bounded model tool output ββΆ session history
oversized text βββββββββββββΆ managed output file
permission: effective agent of issuing turn retained until settlement
Data Models
tool_result
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | ulid | PK | Result identity |
| session_id | id | FK | Owning session |
| tool | text | not null | Tool name |
| structured | json | nullable | Validated structured result |
| bounded_text | text | not null | Model-visible bounded output |
| managed_path | text | nullable | Managed output file path |
permission_request
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | ulid | PK | Request identity |
| session_id | id | FK | Owning session |
| agent | text | not null | Effective agent at issue time |
| status | enum | not null | pending, allowed, denied |
APIApplication Programming Interface Contracts
POST /project/:projectID/session/:sessionID/permission/:permissionID
Resolves a pending permission request for a session.
| Status | Code | Description |
|---|---|---|
| 200 | OK | Permission resolved, session updated |
Sequences
Tool call settlement
Model -> tool call -> Registry.validate(structured)
Registry -> optional tool-specific truncation
Registry -> generic bounding (lines or bytes, whichever first)
Registry -> bounded output to history + managed path for overflow
settlement is interruption-safe; raw oversized success never published pre-correction
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Bounding | Provider-independent aggregate limit per settlement | Token pressure belongs to context assembly, not the tool |
| Truncation strategy | Preserve beginning and end by default | Maximizes signal in bounded preview |
| Managed output | Flat shared dir, globally unique names, temporary | Keeps history compact; absolute paths readable by ordinary tools |
| Permission scope | Pinned to issuing provider turn's agent | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). switches mid-call cannot change policy |
Risks and Unknowns
- Provider-executed tool results need provider-aware pruning and are exempt from generic bounding.
- Managed tool-output files may expire; the bounded output, not the file, is the durable record.
Out of Scope
- MCPModel Context Protocol-provided tools (see FEAT-0007 / MCPModel Context Protocol integration).
- SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. lifecycle and compaction (see FEAT-0001).
requirements
- How should provider-executed tool results be context-controlled given some providers require exact structured round-trip payloads?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: LLMLarge Language Model Provider Layer
Overview
The LLMLarge Language Model Provider Layer lets OpenCode talk to many model providers through a provider-neutral catalog and thin protocol adapters. Provider/model metadata is data-driven via models.devThe upstream data source for provider/model metadata; new providers are added there first., so adding a provider should require little or no code. It partitions provider-semantic model request options, provider-neutral generation controls, and compatibility wire fields.
Stakeholders
| Stakeholder | Interest |
|---|---|
| End users | Broad provider/model choice; stable behavior across providers |
| Contributors | Add providers via models.devThe upstream data source for provider/model metadata; new providers are added there first. without code changes |
| Core team | Clean separation between catalog, protocol adapters, and session runner |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall maintain a catalog of models with provider-semantic model request options resolved from models.devThe upstream data source for provider/model metadata; new providers are added there first.. | Must | The system shall maintain a catalog of models with provider-semantic model request options resolved from models.devThe upstream data source for provider/model metadata; new providers are added there first.. |
| FR-02MustThe system shall partition model request options, generation controls, and compatibility request body fields into separate catalog domains. | Must | The system shall partition model request options, generation controls, and compatibility request body fields into separate catalog domains. |
| FR-03MustThe system shall encode provider wire fields only in the selected protocol adapter, not in the session runner. | Must | The system shall encode provider wire fields only in the selected protocol adapter, not in the session runner. |
| FR-04MustThe system shall support provider authentication including OAuth flows (e.g. Codex/GitHub Copilot, OpenAI, xAI, Cloudflare, Azure, DigitalOcean, Snowflake Cortex). | Must | The system shall support provider authentication including OAuth flows (e.g. Codex/GitHub Copilot, OpenAI, xAI, Cloudflare, Azure, DigitalOcean, Snowflake Cortex). |
| FR-05MustThe system shall map generation controls from the catalog into the LLMLarge Language Model package's provider-option namespace. | Must | The system shall map generation controls from the catalog into the LLMLarge Language Model package's provider-option namespace. |
| FR-06ShouldThe system shall expose model status (available, deprecated, hidden) so the UI can filter models. | Should | The system shall expose model status (available, deprecated, hidden) so the UI can filter models. |
| FR-07ShouldThe system shall preserve structured tool errors across provider round-trips. | Should | The system shall preserve structured tool errors across provider round-trips. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustNew providers shall be addable via upstream metadata with no code change. | Must | Extensibility | New providers shall be addable via upstream metadata with no code change. |
| NFR-02ShouldProvider errors shall be classified and surfaced as retryable or terminal. | Should | Reliability | Provider errors shall be classified and surfaced as retryable or terminal. |
Constraints
- Provider support is data-driven through models.devThe upstream data source for provider/model metadata; new providers are added there first.; contributors must PRPull Request models.devThe upstream data source for provider/model metadata; new providers are added there first. first.
- A shared ingestion adapter partitions legacy and models.devThe upstream data source for provider/model metadata; new providers are added there first. AI-SDKSoftware Development Kit-shaped options before routing.
- A model/provider switch preserves the current context epoch and conversation history.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe system shall maintain a catalog of models with provider-semantic model request options resolved from models.devThe upstream data source for provider/model metadata; new providers are added there first..
- Given models.devThe upstream data source for provider/model metadata; new providers are added there first. metadata is available
- When the catalog is built
- Then models and their request options are resolvable per provider
- FR-03MustThe system shall encode provider wire fields only in the selected protocol adapter, not in the session runner.
- Given a provider turn
- When the request is encoded
- Then wire encoding happens only in that provider's protocol adapter
- FR-04MustThe system shall support provider authentication including OAuth flows (e.g. Codex/GitHub Copilot, OpenAI, xAI, Cloudflare, Azure, DigitalOcean, Snowflake Cortex).
- Given a provider requiring OAuth
- When the user authenticates
- Then the flow completes and credentials are stored for that provider
- NFR-01MustNew providers shall be addable via upstream metadata with no code change.
- Given a new provider added to models.devThe upstream data source for provider/model metadata; new providers are added there first.
- When metadata is refreshed
- Then the provider is usable without code changes in this repo
Conflicts
None identified yet.
Open Questions
- How should deprecated or hidden models be surfaced to users who pinned them?
Specification: LLMLarge Language Model Provider Layer
Overview
A provider-neutral catalog holds models, generation controls, and request options. The session runner maps catalog options into the LLMLarge Language Model package's provider-option namespace, and the selected protocol adapter alone encodes provider wire fields. Provider auth, model status, and structured tool errors are handled in dedicated modules.
Architecture
models.devThe upstream data source for provider/model metadata; new providers are added there first. metadata ββΆ ingestion adapter (partition legacy + AI-SDKSoftware Development Kit shapes)
β
βΌ
CatalogThe provider-neutral registry of models, request options, and generation controls. (3 domains)
ββββββββββββββββββββΌβββββββββββββββββββββββ
βΌ βΌ βΌ
model request opts generation controls compatibility fields
β β β
ββββββββββΆ session runner maps to provider-option namespace
β
βΌ
protocol adapter (per provider) ββΆ llm.stream()
β
auth.ts Β· model-status.ts Β· error.ts
Data Models
catalog_model
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | text | PK | Provider:model identifier |
| provider | text | not null | Owning provider |
| status | enum | not null | available, deprecated, hidden |
| request_options | json | not null | Provider-semantic options |
| generation | json | not null | Provider-neutral generation controls |
APIApplication Programming Interface Contracts
GET /provider?directory=\ -> Provider
Returns available providers and models for the resolved directory.
| Status | Code | Description |
|---|---|---|
| 200 | OK | Provider list returned |
Sequences
Model request resolution
session turn -> CatalogThe provider-neutral registry of models, request options, and generation controls..resolve(model, variant)
CatalogThe provider-neutral registry of models, request options, and generation controls. -> model request options + generation controls
session runner -> map to provider-option namespace
protocol adapter -> encode wire fields -> llm.stream
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Provider data | models.devThe upstream data source for provider/model metadata; new providers are added there first. upstream | Minimizes per-provider code |
| Option domains | Split request options, generation controls, compatibility | Keeps provider semantics out of session runner |
| Wire encoding | Protocol adapter only | Single owner of provider wire format |
| Switch behavior | Preserve context epoch and history | Mid-conversation model changes are non-disruptive |
Risks and Unknowns
- Legacy and models.devThe upstream data source for provider/model metadata; new providers are added there first. AI-SDKSoftware Development Kit-shaped options differ and require a partitioning ingestion adapter.
- Some providers require exact structured tool round-trip payloads, constraining pruning and compaction.
Out of Scope
- SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. execution and provider turn scheduling (see FEAT-0001).
- PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks.-defined providers beyond the catalog (see FEAT-0007).
requirements
- How should deprecated or hidden models be surfaced to users who pinned them?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: Terminal UI
Overview
The Terminal UI (TUITerminal User Interface) is OpenCode's primary interactive surface, rendering the agent conversation, tool output, permissions, and session controls inside the terminal. It is built with SolidJS on opentuiThe terminal UI framework (SolidJS-based) used by the TUI. and runs against the core server, optionally in a worker thread during development.
Stakeholders
| Stakeholder | Interest |
|---|---|
| End users | Fast, responsive terminal experience with keyboard-driven controls |
| Core team | Stable rendering pipeline; correct worker-thread rejection handling |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall render an interactive conversation view with streaming model output. | Must | The system shall render an interactive conversation view with streaming model output. |
| FR-02MustThe system shall let users switch between agents (e.g. via the Tab key). | Must | The system shall let users switch between agents (e.g. via the Tab key). |
| FR-03MustThe system shall surface permission prompts and tool activity inline. | Must | The system shall surface permission prompts and tool activity inline. |
| FR-04MustThe system shall scope file autocomplete to the active session. | Must | The system shall scope file autocomplete to the active session. |
| FR-05ShouldThe system shall provide a thinking-mode toggle for reasoning model output. | Should | The system shall provide a thinking-mode toggle for reasoning model output. |
| FR-06ShouldThe system shall preserve worker-thread rejection handling when run via `bun dev`. | Should | The system shall preserve worker-thread rejection handling when run via bun dev. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustPrimary interactions shall be keyboard-driven. | Must | Usability | Primary interactions shall be keyboard-driven. |
| NFR-02ShouldStreaming output shall render without blocking input. | Should | Performance | Streaming output shall render without blocking input. |
Constraints
- TUITerminal User Interface code lives in
packages/opencode/src/cli/cmd/tui/and thepackages/tuipackage. - During development the server may run in a worker thread;
bun dev spawnor a separately debugged server may be needed for breakpoints.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe system shall render an interactive conversation view with streaming model output.
- Given an active session
- When the model streams a response
- Then tokens render incrementally in the conversation view
- FR-04MustThe system shall scope file autocomplete to the active session.
- Given the user is entering a file path in a session
- When autocomplete triggers
- Then only files relevant to the active session's scope are suggested
- FR-06ShouldThe system shall preserve worker-thread rejection handling when run via `bun dev`.
- Given the TUITerminal User Interface runs via
bun devwith a worker-thread server - When the worker rejects a promise
- Then the rejection is handled and does not crash the TUITerminal User Interface
- Given the TUITerminal User Interface runs via
Conflicts
None identified yet.
Open Questions
- What is the long-term split between
packages/tuiand the in-repocli/cmd/tuicode?
Specification: Terminal UI
Overview
The TUITerminal User Interface is a SolidJS application rendered to the terminal via opentuiThe terminal UI framework (SolidJS-based) used by the TUI.. It connects to the core server (local socket by default) and projects sessions, messages, tool activity, and permissions, with keyboard-driven navigation.
Architecture
opentuiThe terminal UI framework (SolidJS-based) used by the TUI. (terminal renderer) βββ SolidJS UI (packages/tui + cli/cmd/tui)
β
βΌ
core server (local) ββ sessions, tools, providers
Data Models
The TUITerminal User Interface consumes server-projected Message and Part shapes; it holds no durable model of its own.
APIApplication Programming Interface Contracts
The TUITerminal User Interface consumes the HTTP APIApplication Programming Interface (see FEAT-0006), notably session, message, and permission routes.
Sequences
Streaming a response
TUITerminal User Interface -> POST message -> server
server -> SSE/event stream -> TUITerminal User Interface
TUITerminal User Interface -> incrementally render parts (text, tool calls, tool output)
TUITerminal User Interface -> inline permission prompt when required
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Framework | SolidJS on opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | Reactive UI in the terminal; shared mental model with web app |
| Dev server | Worker thread under bun dev |
Keeps TUITerminal User Interface and server in one process; spawn variant for debugging |
Risks and Unknowns
- Worker-thread debugging can mis-map breakpoints; documented workarounds use
bun dev spawnor a separately debugged server. - The split between
packages/tuiand in-repo TUITerminal User Interface code may need consolidation.
Out of Scope
- Web and desktop frontends (see FEAT-0005).
- Server-side session execution (see FEAT-0001).
requirements
- What is the long-term split between
packages/tuiand the in-repocli/cmd/tuicode?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: Web & Desktop Apps
Overview
OpenCode ships a SolidJS web app of shared UI components and an Electron desktop application that wraps it. The web app lets users interact with sessions through a browser against a running server, while the desktop app packages that experience as a native application with cross-platform installers.
Stakeholders
| Stakeholder | Interest |
|---|---|
| End users | A polished graphical experience without a terminal |
| Desktop users | Native installers (dmg, exe, deb/rpm/AppImage) and auto-update |
| Core team | Shared component library between web and desktop |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe web app shall connect to a running OpenCode server and render sessions, messages, and tool activity. | Must | The web app shall connect to a running OpenCode server and render sessions, messages, and tool activity. |
| FR-02MustThe desktop app shall wrap the web UI in Electron and run a local server. | Must | The desktop app shall wrap the web UI in Electron and run a local server. |
| FR-03MustThe desktop app shall be packaged for macOS (Apple Silicon + Intel), Windows, and Linux. | Must | The desktop app shall be packaged for macOS (Apple Silicon + Intel), Windows, and Linux. |
| FR-04ShouldThe web app shall share UI components with other surfaces via `packages/app` and `packages/ui`. | Should | The web app shall share UI components with other surfaces via packages/app and packages/ui. |
| FR-05ShouldThe desktop app shall be installable via Homebrew Cask and Scoop extras. | Should | The desktop app shall be installable via Homebrew Cask and Scoop extras. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustThe graphical experience shall match TUITerminal User Interface capabilities for core session flows. | Must | Usability | The graphical experience shall match TUITerminal User Interface capabilities for core session flows. |
| NFR-02ShouldThe web dev server shall hot-reload UI changes independently of the core server. | Should | Performance | The web dev server shall hot-reload UI changes independently of the core server. |
Constraints
- UI/core product features require design review with the core team before implementation.
- The web app requires a separately running server for full functionality.
- Desktop packaging uses Electron;
trustedDependenciesincludeselectron.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe web app shall connect to a running OpenCode server and render sessions, messages, and tool activity.
- Given a server is running
- When the web app loads
- Then sessions render and new prompts can be submitted
- FR-02MustThe desktop app shall wrap the web UI in Electron and run a local server.
- Given the desktop app is launched
- When it starts
- Then a local server is available and the web UI is displayed
- FR-03MustThe desktop app shall be packaged for macOS (Apple Silicon + Intel), Windows, and Linux.
- Given a desktop release build
- When packaged
- Then dmg (mac arm64/x64), Windows exe, and Linux deb/rpm/AppImage artifacts are produced
Conflicts
None identified yet.
Open Questions
- What is the update mechanism and cadence for desktop auto-updates across platforms?
Specification: Web & Desktop Apps
Overview
packages/app provides the shared SolidJS web UI consumed by both the browser experience and the Electron desktop shell.
packages/desktop wraps that UI, bundles a local server, and produces cross-platform installers via its build/package scripts.
Architecture
Browser βββΆ web app (packages/app, SolidJS + Vite + Tailwind)
β shared components (packages/ui)
Electron shell (packages/desktop) ββ wraps βββΆ web app
β
βΌ
local OpenCode server
Data Models
The apps consume server-projected Message/Part and config shapes; they hold no durable model beyond local UI/session view state.
APIApplication Programming Interface Contracts
The apps consume the HTTP APIApplication Programming Interface (see FEAT-0006).
Sequences
Desktop launch
Electron main -> start local server (default port 4096)
Electron -> load web app (bundled or dev server)
web app -> connect to local server -> render sessions
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Shared UI | packages/app + packages/ui |
Single component library across web and desktop |
| Desktop shell | Electron | Cross-platform native packaging with a web UI |
| Dev workflow | Web dev server hot-reloads independent of core server | Faster UI iteration |
Risks and Unknowns
- Auto-update cadence and mechanism across macOS, Windows, and Linux are not fully specified here.
- Parity between graphical and TUITerminal User Interface capabilities must be maintained as features land.
Out of Scope
- Terminal UI (see FEAT-0004).
- Server implementation (see FEAT-0006).
requirements
- What is the update mechanism and cadence for desktop auto-updates across platforms?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: HTTP APIApplication Programming Interface Server
Overview
The HTTP APIApplication Programming Interface Server is OpenCode's headless surface, letting any client (TUITerminal User Interface, web, desktop, SDKSoftware Development Kit, editor integrations) drive projects and sessions over HTTP. It exposes multi-project, multi-session routes under a project-scoped namespace, plus config, provider, and agent resolution.
Stakeholders
| Stakeholder | Interest |
|---|---|
| SDKSoftware Development Kit / editor authors | Stable, documented REST routes |
| Operators | Headless deployment on a known port; auth |
| Core team | Project-scoped routing; clean projection of messages and parts |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe server shall run headless on a configurable port (default 4096) via `serve`. | Must | The server shall run headless on a configurable port (default 4096) via serve. |
| FR-02MustThe server shall support multiple projects and per-project sessions (`GET/POST /project`, `/project/:projectID/session...`). | Must | The server shall support multiple projects and per-project sessions (GET/POST /project, /project/:projectID/session...). |
| FR-03MustThe server shall expose session lifecycle routes: create, init, abort, share/unshare, compact, revert/unrevert, delete. | Must | The server shall expose session lifecycle routes: create, init, abort, share/unshare, compact, revert/unrevert, delete. |
| FR-04MustThe server shall expose message routes that return `{ info, parts }` projections and accept new messages. | Must | The server shall expose message routes that return { info, parts } projections and accept new messages. |
| FR-05MustThe server shall expose permission resolution (`POST .../permission/:permissionID`) and file routes (`find/file`, `file`, `file/status`). | Must | The server shall expose permission resolution (POST .../permission/:permissionID) and file routes (find/file, file, file/status). |
| FR-06ShouldThe server shall resolve provider, config, and agent by directory query parameter. | Should | The server shall resolve provider, config, and agent by directory query parameter. |
| FR-07ShouldThe server shall accept logs via `POST /log`. | Should | The server shall accept logs via POST /log. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustThe SDKSoftware Development Kit shall be regenerable from the server routes via `./script/generate.ts`. | Must | Compatibility | The SDKSoftware Development Kit shall be regenerable from the server routes via ./script/generate.ts. |
| NFR-02ShouldAuthenticated routes shall be enforceable for hosted/enterprise deployments. | Should | Security | Authenticated routes shall be enforceable for hosted/enterprise deployments. |
Constraints
- Server routing is HonoThe web framework used for the HTTP API server.-based and lives in
packages/serverandpackages/opencode/src/server. - Some directory-resolved routes (
/provider,/config,/project/:id/agent,/find/file) are noted as awkward in the spec and may change. - APIApplication Programming Interface/SDKSoftware Development Kit changes require regenerating the SDKSoftware Development Kit and related files.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe server shall run headless on a configurable port (default 4096) via `serve`.
- Given the server is started with
serve - When no port is specified
- Then it listens on port 4096
- Given the server is started with
- FR-02MustThe server shall support multiple projects and per-project sessions (`GET/POST /project`, `/project/:projectID/session...`).
- Given two initialized projects
- When a client lists sessions per project
- Then each project returns only its own sessions
- FR-04MustThe server shall expose message routes that return `{ info, parts }` projections and accept new messages.
- Given a session with messages
- When a client calls the message route
- Then each item is returned as
{ info: Message, parts: Part[] }
- NFR-01MustThe SDKSoftware Development Kit shall be regenerable from the server routes via `./script/generate.ts`.
- Given a route change in
packages/opencode/src/server/server.ts - When
./script/generate.tsruns - Then the SDKSoftware Development Kit and related files are regenerated to match
- Given a route change in
Conflicts
None identified yet.
Open Questions
- Should the awkward directory-resolved routes be refactored into the project-scoped namespace?
Specification: HTTP APIApplication Programming Interface Server
Overview
A HonoThe web framework used for the HTTP API server.-based server exposes project- and session-scoped REST routes over HTTP. Routes project messages and parts, file access, permissions, and directory-resolved config/provider/agent lookups, and feeds SDKSoftware Development Kit generation.
Architecture
Client (TUITerminal User Interface/Web/Desktop/SDKSoftware Development Kit) ββHTTPβββΆ HonoThe web framework used for the HTTP API server. server (packages/server + opencode/src/server)
β routes: project, session, message,
β permission, file, provider, config, agent, log
βΌ
SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. Runtime + Storage (FEAT-0001)
Data Models
The APIApplication Programming Interface projects server-side SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context., Message, Part, and File shapes; it defines no new durable model.
APIApplication Programming Interface Contracts
GET /project -> Project[]
POST /project/init -> Project
GET /project/:projectID/session -> SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context.[]
GET /project/:projectID/session/:sessionID -> SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context.
POST /project/:projectID/session -> SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | no | Optional session id |
| parentID | string | no | Optional parent session |
| directory | string | yes | Working directory |
DELETE /project/:projectID/session/:sessionID
POST /project/:projectID/session/:sessionID/init
POST /project/:projectID/session/:sessionID/abort
POST /project/:projectID/session/:sessionID/share
DELETE /project/:projectID/session/:sessionID/share
POST /project/:projectID/session/:sessionID/compact
GET /project/:projectID/session/:sessionID/message -> { info: Message, parts: Part[] }[]
GET /project/:projectID/session/:sessionID/message/:messageID ->
POST /project/:projectID/session/:sessionID/message ->
POST /project/:projectID/session/:sessionID/revert -> SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context.
POST /project/:projectID/session/:sessionID/unrevert -> SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context.
POST /project/:projectID/session/:sessionID/permission/:permissionID -> SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context.
GET /project/:projectID/session/:sessionID/find/file -> string[]
GET /project/:projectID/session/:sessionID/file ->
GET /project/:projectID/session/:sessionID/file/status -> File[]
POST /log
GET /provider?directory=\ -> Provider
GET /config?directory=\ -> Config
GET /project/:projectID/agent?directory=\ -> AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`).
GET /project/:projectID/find/file?directory=\ -> File
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Malformed request body or path |
| 404 | NOT_FOUND | Project, session, or message not found |
Sequences
Submit a message
Client -> POST /project/:id/session/:sid/message
Server -> SessionV2.prompt (admit + wake)
Server -> 200 { info, parts }
Client -> poll/subscribe message route for streamed parts
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Framework | HonoThe web framework used for the HTTP API server. | Lightweight, typed routing with EffectThe functional effect system used pervasively in the core runtime. integration |
| Projection | { info, parts } per message |
Uniform shape for streaming and history |
| SDKSoftware Development Kit parity | Generated from routes via script/generate.ts |
Keeps SDKSoftware Development Kit and server in lockstep |
Risks and Unknowns
- Directory-resolved routes (
/provider,/config,/agent,/find/file) are flagged as awkward and may move under the project namespace. - Hosted/enterprise auth on these routes needs explicit policy.
Out of Scope
- SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. runtime internals (see FEAT-0001).
- Generated SDKSoftware Development Kit client (see FEAT-0008).
requirements
- Should the awkward directory-resolved routes be refactored into the project-scoped namespace?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. System
Overview
The PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. System lets packages extend OpenCode through the @opencode-ai/plugin SDKSoftware Development Kit with namespaced hooks and a direct runtime registry.
Plugins can contribute provider integrations, PTYPseudo-Terminal environment overlays, tools, context sources, and TUITerminal User Interface behavior, and the runtime awaits plugin readiness before serving sessions.
Stakeholders
| Stakeholder | Interest |
|---|---|
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. authors | Stable SDKSoftware Development Kit, namespaced hooks, clear lifecycle |
| End users | Installable plugins that load reliably |
| Core team | Direct runtime registry; readiness guarantees; LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. scoping |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall provide a plugin SDKSoftware Development Kit (`@opencode-ai/plugin`) exposing a namespaced hook APIApplication Programming Interface. | Must | The system shall provide a plugin SDKSoftware Development Kit (@opencode-ai/plugin) exposing a namespaced hook APIApplication Programming Interface. |
| FR-02MustThe system shall register plugins through a direct runtime registry and await plugin readiness before proceeding. | Must | The system shall register plugins through a direct runtime registry and await plugin readiness before proceeding. |
| FR-03MustThe system shall allow plugins to contribute provider integrations (e.g. OpenAI, xAI, Azure, Cloudflare, DigitalOcean, Snowflake Cortex, GitHub Copilot). | Must | The system shall allow plugins to contribute provider integrations (e.g. OpenAI, xAI, Azure, Cloudflare, DigitalOcean, Snowflake Cortex, GitHub Copilot). |
| FR-04MustThe system shall allow plugins to supply a PTYPseudo-Terminal environment overlay observed per LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.. | Must | The system shall allow plugins to supply a PTYPseudo-Terminal environment overlay observed per LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.. |
| FR-05ShouldThe system shall support plugin loading and installation flows. | Should | The system shall support plugin loading and installation flows. |
| FR-06ShouldThe system shall allow plugin-defined Context Sources via the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). Registry. | Should | The system shall allow plugin-defined Context Sources via the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). Registry. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustSessions shall not start until required plugins report readiness. | Must | Reliability | Sessions shall not start until required plugins report readiness. |
| NFR-02ShouldPluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks.-defined context registration and hot-reload shall use the same scoped registry seam. | Should | Extensibility | PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks.-defined context registration and hot-reload shall use the same scoped registry seam. |
Constraints
- Built-in and instruction context producers register through the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). Registry with stable contribution keys.
- PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks.-defined context registration and hot-reload lifecycle remain a follow-up built on the same scoped registry seam.
- The PTYPseudo-Terminal environment is a server concern; standalone servers use an empty adapter.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe system shall provide a plugin SDKSoftware Development Kit (`@opencode-ai/plugin`) exposing a namespaced hook APIApplication Programming Interface.
- Given a plugin authored against
@opencode-ai/plugin - When it is loaded
- Then its hooks are registered under a stable namespace
- Given a plugin authored against
- FR-02MustThe system shall register plugins through a direct runtime registry and await plugin readiness before proceeding.
- Given plugins are installed
- When the server starts
- Then it awaits plugin readiness before serving sessions
- FR-04MustThe system shall allow plugins to supply a PTYPseudo-Terminal environment overlay observed per LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions..
- Given a PTYPseudo-Terminal environment plugin is active for a LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions.
- When a PTYPseudo-Terminal is created
- Then the host overlay is applied with the resolved working directory
Conflicts
None identified yet.
Open Questions
- When will plugin-defined Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). hot-reload be implemented on the scoped registry seam?
- Should legacy
experimental.chat.system.transformbe ported to a plugin hook or replaced by plugin-defined Context Sources?
Specification: PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. System
Overview
Plugins are TypeScript packages depending on @opencode-ai/plugin.
A loader discovers and installs them, a direct runtime registry registers their namespaced hooks, and the runtime awaits readiness before serving sessions.
Plugins extend providers, PTYPseudo-Terminal environment, tools, context sources, and TUITerminal User Interface behavior.
Architecture
@opencode-ai/plugin SDKSoftware Development Kit βββΆ plugin package
plugin package ββload/installβββΆ loader.ts
loader βββΆ runtime registry (direct)
runtime registry ββawait readinessβββΆ server ready
hooks βββΆ providers Β· pty-environment Β· tools Β· context sources Β· tui
Data Models
plugin_meta
| Field | Type | Constraints | Description |
|---|---|---|---|
| name | text | PK | PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. package name |
| namespace | text | not null | Hook namespace |
| ready | boolean | not null | Readiness state |
APIApplication Programming Interface Contracts
Plugins integrate via the SDKSoftware Development Kit, not a public HTTP contract.
Sequences
PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. load and readiness
server start -> loader.discover -> registry.register(namespaced hooks)
registry -> await readiness
registry ready -> server serves sessions
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Registry | Direct runtime registry | Avoids indirection; fast lookups |
| Hooks | Namespaced APIApplication Programming Interface | Prevents collisions across plugins |
| Readiness | Awaited before serving | Guarantees plugins are initialized |
| Context sources | Same scoped registry seam as built-ins | Uniform composition; future hot-reload |
Risks and Unknowns
- Hot-reload of plugin-defined Context Sources is not yet implemented.
- Legacy baseline mutation (
experimental.chat.system.transform) has no plugin equivalent yet.
Out of Scope
- Built-in context source producers (see FEAT-0001).
- Provider catalog data (see FEAT-0003).
requirements
- When will plugin-defined Context Source hot-reload be implemented on the scoped registry seam?
- Should legacy
experimental.chat.system.transformbe ported to a plugin hook or replaced by plugin-defined Context Sources?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: SDKSoftware Development Kit & Editor Integrations
Overview
OpenCode is consumable beyond its own frontends through a generated TypeScript SDKSoftware Development Kit, a VSCode extension, MCPModel Context Protocol server integration, and a distributable CLICommand-Line Interface. These surfaces let third-party tools, editors, and automation drive OpenCode sessions programmatically.
Stakeholders
| Stakeholder | Interest |
|---|---|
| SDKSoftware Development Kit consumers | Typed client matching the server APIApplication Programming Interface |
| Editor users | First-class VSCode integration |
| MCPModel Context Protocol users | Compose OpenCode with other MCPModel Context Protocol-aware agents |
| CLICommand-Line Interface users | Installable, standalone executable |
Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall provide a TypeScript SDKSoftware Development Kit generated from the server routes via `./script/generate.ts`. | Must | The system shall provide a TypeScript SDKSoftware Development Kit generated from the server routes via ./script/generate.ts. |
| FR-02MustThe system shall provide a distributable CLICommand-Line Interface executable (`opencode`) built from the same entrypoint as `bun dev`. | Must | The system shall provide a distributable CLICommand-Line Interface executable (opencode) built from the same entrypoint as bun dev. |
| FR-03MustThe system shall integrate MCPModel Context Protocol servers, including a catalog, auth, and an OAuth provider/callback flow. | Must | The system shall integrate MCPModel Context Protocol servers, including a catalog, auth, and an OAuth provider/callback flow. |
| FR-04MustThe system shall provide a VSCode editor extension. | Must | The system shall provide a VSCode editor extension. |
| FR-05ShouldThe system shall produce a single-asset standalone executable via `packages/opencode/script/build.ts --single`. | Should | The system shall produce a single-asset standalone executable via packages/opencode/script/build.ts --single. |
| FR-06ShouldThe system shall expose Slack integration via the `packages/slack` package. | Should | The system shall expose Slack integration via the packages/slack package. |
Non-Functional Requirements
Order rows by priority: Must first, then Should, then May.
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustThe SDKSoftware Development Kit shall stay in lockstep with the server APIApplication Programming Interface by regeneration. | Must | Compatibility | The SDKSoftware Development Kit shall stay in lockstep with the server APIApplication Programming Interface by regeneration. |
| NFR-02ShouldMCPModel Context Protocol OAuth flows shall complete securely with callback handling. | Should | Security | MCPModel Context Protocol OAuth flows shall complete securely with callback handling. |
Constraints
- The JS SDKSoftware Development Kit lives in
packages/sdk/js; the VSCode extension insdks/vscode. - MCPModel Context Protocol integration lives in
packages/opencode/src/mcp. - Regeneration is required after server route or SDKSoftware Development Kit changes.
Acceptance Criteria
Every FR and NFR shall have at least one acceptance criterion.
Order criteria by FRs first (sorted by ID), then NFRs (sorted by ID).
- FR-01MustThe system shall provide a TypeScript SDKSoftware Development Kit generated from the server routes via `./script/generate.ts`.
- Given the server routes
- When
./script/generate.tsruns - Then a typed TypeScript SDKSoftware Development Kit is produced in
packages/sdk/js
- FR-03MustThe system shall integrate MCPModel Context Protocol servers, including a catalog, auth, and an OAuth provider/callback flow.
- Given an MCPModel Context Protocol server requiring OAuth
- When a session connects to it
- Then the OAuth provider and callback flow completes and the server is usable
- FR-04MustThe system shall provide a VSCode editor extension.
- Given VSCode with the extension installed
- When the user opens a project
- Then OpenCode sessions are drivable from the editor
Conflicts
None identified yet.
Open Questions
- What is the release and versioning policy for the generated SDKSoftware Development Kit versus the VSCode extension?
Specification: SDKSoftware Development Kit & Editor Integrations
Overview
A TypeScript SDKSoftware Development Kit is generated from the HonoThe web framework used for the HTTP API server. server routes, an MCPModel Context Protocol layer composes external tool/context servers (with OAuth), and a VSCode extension plus a distributable CLICommand-Line Interface bring OpenCode into editors and automation.
Architecture
HonoThe web framework used for the HTTP API server. server routes ββgenerateβββΆ TypeScript SDKSoftware Development Kit (packages/sdk/js) βββΆ clients
packages/opencode/src/mcp βββΆ MCPModel Context Protocol catalog Β· auth Β· oauth provider/callback βββΆ MCPModel Context Protocol servers
sdks/vscode βββΆ VSCode extension βββΆ local server
packages/cli / build.ts --single βββΆ standalone `opencode` executable
packages/slack βββΆ Slack integration
Data Models
mcp_server
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | text | PK | MCPModel Context Protocol server identity |
| auth | json | nullable | Auth/OAuth state |
| status | enum | not null | connected, pending, error |
APIApplication Programming Interface Contracts
These integrations consume the HTTP APIApplication Programming Interface (see FEAT-0006) and expose editor/MCPModel Context Protocol-specific contracts.
Sequences
MCPModel Context Protocol OAuth connect
session requests MCPModel Context Protocol server -> catalog lookup
auth needed -> oauth-provider initiates flow
oauth-callback completes -> credentials stored
MCPModel Context Protocol server usable by tool registry
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| SDKSoftware Development Kit | Generated from server routes | Type safety in lockstep with APIApplication Programming Interface |
| Standalone build | build.ts --single |
Single-asset executable per platform |
| MCPModel Context Protocol auth | OAuth provider + callback | Supports providers requiring user consent |
Risks and Unknowns
- SDKSoftware Development Kit and extension versioning cadence relative to the server is not specified here.
- MCPModel Context Protocol OAuth reliability depends on provider-specific flows.
Out of Scope
- Server route definitions (see FEAT-0006).
- PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks.-provided tools and providers (see FEAT-0007).
requirements
- What is the release and versioning policy for the generated SDK versus the VSCode extension?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: LLMLarge Language Model Core Package
Overview
The LLMLarge Language Model Core Package (packages/llm) provides a standalone, EffectThe functional effect system used pervasively in the core runtime. Schema-first LLMLarge Language Model abstraction that can be used independently of the rest of OpenCode.
It defines a route/protocol/endpoint/auth/framing architecture for provider-agnostic LLMLarge Language Model calls, with provider adapters for OpenAI, Anthropic, Google, Bedrock, Azure, and others.
The package publishes as @opencode-ai/llm and has no dependency on packages/opencode or packages/core.
Stakeholders
| Stakeholder | Interest |
|---|---|
| LLMLarge Language Model package consumers | Provider-agnostic LLMLarge Language Model calls with a clean schema-first APIApplication Programming Interface |
| Core team | Clear separation from the session runtime; independent versioning |
| Provider adapter authors | Stable contract for adding new providers |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe package shall define a route/protocol abstraction that isolates provider wire encoding from the caller. | Must | The package shall define a route/protocol abstraction that isolates provider wire encoding from the caller. |
| FR-02MustThe package shall support multiple provider protocols: chat, responses, messages, and gemini. | Must | The package shall support multiple provider protocols: chat, responses, messages, and gemini. |
| FR-03MustThe package shall include provider adapters for OpenAI, Anthropic, Google, Bedrock, Azure, and other major providers. | Must | The package shall include provider adapters for OpenAI, Anthropic, Google, Bedrock, Azure, and other major providers. |
| FR-04MustThe package shall implement a tool dispatch mechanism for converting LLMLarge Language Model tool calls into bounded results. | Must | The package shall implement a tool dispatch mechanism for converting LLMLarge Language Model tool calls into bounded results. |
| FR-05MustThe package shall use EffectThe functional effect system used pervasively in the core runtime. Schema for all type definitions, ensuring structured validation at boundaries. | Must | The package shall use EffectThe functional effect system used pervasively in the core runtime. Schema for all type definitions, ensuring structured validation at boundaries. |
| FR-06ShouldThe package shall be publishable as a standalone npm package with no dependency on OpenCode internals. | Should | The package shall be publishable as a standalone npm package with no dependency on OpenCode internals. |
| FR-07ShouldThe package shall expose provider auth configuration and credential management. | Should | The package shall expose provider auth configuration and credential management. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustAdding a new provider shall require only a new adapter module without changing the core protocol. | Must | Extensibility | Adding a new provider shall require only a new adapter module without changing the core protocol. |
| NFR-02MustProvider wire encoding shall be deterministic and schema-validated. | Must | Correctness | Provider wire encoding shall be deterministic and schema-validated. |
| NFR-03ShouldThe package shall coexist with the legacy AI SDKSoftware Development Kit provider path during migration. | Should | Compatibility | The package shall coexist with the legacy AI SDKSoftware Development Kit provider path during migration. |
Constraints
- The package lives at
packages/llmand is built with EffectThe functional effect system used pervasively in the core runtime., EffectThe functional effect system used pervasively in the core runtime. Schema. - Provider protocol adapters live alongside the package; no external plugin mechanism for protocols.
- The package must not depend on
packages/opencodeorpackages/core.
Acceptance Criteria
- FR-01MustThe package shall define a route/protocol abstraction that isolates provider wire encoding from the caller.
- Given a provider protocol is selected
- When a request is encoded
- Then the wire format matches the provider's expected schema
- FR-03MustThe package shall include provider adapters for OpenAI, Anthropic, Google, Bedrock, Azure, and other major providers.
- Given provider adapters for OpenAI, Anthropic, Google, Bedrock, and Azure
- When each is instantiated with valid credentials
- Then a streaming LLMLarge Language Model call completes successfully
- FR-06ShouldThe package shall be publishable as a standalone npm package with no dependency on OpenCode internals.
- Given the package is built
- When published to npm as
@opencode-ai/llm - Then consumers can install and use it independently
- NFR-01MustAdding a new provider shall require only a new adapter module without changing the core protocol.
- Given a new provider adapter is added
- When it implements the route/protocol contract
- Then no changes to the core protocol or existing adapters are required
Conflicts
None identified yet.
Open Questions
- How should the LLMLarge Language Model package migration from the legacy AI SDKSoftware Development Kit path be coordinated across providers?
- Should provider auth live in this package or remain in
packages/opencode/src/provider/?
Specification: LLMLarge Language Model Core Package
Architecture
Caller βββΆ Route (provider-agnostic interface)
β
βΌ
Protocol (wire encoding strategy: chat, responses, messages, gemini)
β
βΌ
Endpoint (HTTP transport, streaming, retries)
β
βΌ
Auth (credential resolution, token management)
β
βΌ
Framing (request/response shaping, tool dispatch)
β
βΌ
Provider Adapter (OpenAI, Anthropic, Google, Bedrock, Azure, ...)
The package exposes a clean layered architecture where each layer has a single responsibility, and all types are defined via EffectThe functional effect system used pervasively in the core runtime. Schema for structural validation.
Data Models
LLMRequest
| Field | Type | Constraints | Description |
|---|---|---|---|
| model | text | not null | Provider:model identifier |
| messages | array | not null | Chronological message list |
| tools | array | nullable | Available tool definitions |
| generation | object | nullable | Generation controls (temperature, top_p, etc.) |
| options | object | nullable | Provider-semantic request options |
LLMResponse
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | text | PK | Response identity |
| content | array | not null | Message content parts |
| tool_calls | array | nullable | Structured tool call list |
| finish_reason | enum | not null | stop, length, tool_calls, error |
APIApplication Programming Interface Contracts
The package exposes an EffectThe functional effect system used pervasively in the core runtime.-based llm.stream(request) function and internal route/protocol/endpoint/auth modules.
No external HTTP APIApplication Programming Interface; consumers call the EffectThe functional effect system used pervasively in the core runtime. functions directly.
Sequences
Stream a completion
Caller -> route.resolve(provider, model)
route -> protocol.chat.encode(request) (or .responses, .messages, .gemini)
protocol -> endpoint.stream(encoded_request, auth)
endpoint -> stream chunks -> protocol.decode(chunk)
protocol -> structured LLMResponse parts -> caller
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Architecture | Route / Protocol / Endpoint / Auth / Framing | Clean separation; each layer independently testable |
| Type system | EffectThe functional effect system used pervasively in the core runtime. Schema | Built-in validation, decoding, and JSON serialization |
| Streaming | Pull-based EffectThe functional effect system used pervasively in the core runtime. Stream | Composable with EffectThe functional effect system used pervasively in the core runtime.'s streaming ecosystem |
| Provider data | In-package adapters | No external dependency on models.devThe upstream data source for provider/model metadata; new providers are added there first.; loaded from package metadata |
Risks and Unknowns
- The legacy AI SDKSoftware Development Kit provider path must coexist during gradual migration; double-maintenance burden until migration completes.
- Provider-specific wire differences (e.g., structured tool round-trip payloads) may constrain the protocol abstraction.
Out of Scope
- SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. runtime integration (see FEAT-0001).
- Provider catalog from models.devThe upstream data source for provider/model metadata; new providers are added there first. (see FEAT-0003).
requirements
- How should the LLM package migration from the legacy AI SDK path be coordinated across providers?
- Should provider auth live in this package or remain in
packages/opencode/src/provider/?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: Enterprise & Cloud Platform
Overview
The Enterprise & Cloud Platform provides SSTThe IaC framework used for cloud infra (`sst.config.ts`).-deployed backend infrastructure for managing OpenCode at scale. It includes a console application for cloud service management, a stats/analytics dashboard, an enterprise self-hosted web app with team and project management, and the supporting infrastructure (monitoring, identity, secrets, data lake). This feature enables organizations to run OpenCode as a managed or self-hosted service.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Enterprise operators | Self-hosted deployment with team management and access control |
| Cloud users | Console-based management of cloud resources |
| Core team | Unified SSTThe IaC framework used for cloud infra (`sst.config.ts`). infrastructure for all managed services |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall provide a console application for managing cloud-deployed OpenCode instances (SSTThe IaC framework used for cloud infra (`sst.config.ts`).). | Must | The system shall provide a console application for managing cloud-deployed OpenCode instances (SSTThe IaC framework used for cloud infra (`sst.config.ts`).). |
| FR-02MustThe system shall provide a stats/analytics dashboard for usage telemetry and reporting. | Must | The system shall provide a stats/analytics dashboard for usage telemetry and reporting. |
| FR-03MustThe system shall provide an enterprise web app supporting team management, projects, and self-hosting on Cloudflare or custom servers. | Must | The system shall provide an enterprise web app supporting team management, projects, and self-hosting on Cloudflare or custom servers. |
| FR-04MustThe system shall deploy infrastructure via SSTThe IaC framework used for cloud infra (`sst.config.ts`). with defined stages: app, console, enterprise, lake, monitoring, stats, identity. | Must | The system shall deploy infrastructure via SSTThe IaC framework used for cloud infra (`sst.config.ts`). with defined stages: app, console, enterprise, lake, monitoring, stats, identity. |
| FR-05ShouldThe system shall include monitoring infrastructure with OpenTelemetry and Sentry integrations. | Should | The system shall include monitoring infrastructure with OpenTelemetry and Sentry integrations. |
| FR-06ShouldThe system shall support identity/auth flows via OpenAuth for enterprise deployments. | Should | The system shall support identity/auth flows via OpenAuth for enterprise deployments. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustInfrastructure shall be defined as code (SSTThe IaC framework used for cloud infra (`sst.config.ts`).) and deployable to multiple environments. | Must | Scalability | Infrastructure shall be defined as code (SSTThe IaC framework used for cloud infra (`sst.config.ts`).) and deployable to multiple environments. |
| NFR-02ShouldEnterprise deployments shall support authenticated routes and team-scoped access control. | Should | Security | Enterprise deployments shall support authenticated routes and team-scoped access control. |
Constraints
- Infrastructure lives under
infra/and is defined with SSTThe IaC framework used for cloud infra (`sst.config.ts`). (sst.config.ts). - Console lives in
packages/console/(with app, core, function, mail, resource, support sub-workspaces). - Stats lives in
packages/stats/(with app, core, server sub-workspaces). - Enterprise app lives in
packages/enterprise/.
Acceptance Criteria
- FR-01MustThe system shall provide a console application for managing cloud-deployed OpenCode instances (SSTThe IaC framework used for cloud infra (`sst.config.ts`).).
- Given SSTThe IaC framework used for cloud infra (`sst.config.ts`). infrastructure is deployed
- When the console app is accessed
- Then it shows managed OpenCode instances and their status
- FR-03MustThe system shall provide an enterprise web app supporting team management, projects, and self-hosting on Cloudflare or custom servers.
- Given an enterprise deployment
- When an admin creates a team and invites members
- Then team members can access shared project sessions
- FR-04MustThe system shall deploy infrastructure via SSTThe IaC framework used for cloud infra (`sst.config.ts`). with defined stages: app, console, enterprise, lake, monitoring, stats, identity.
- Given the SSTThe IaC framework used for cloud infra (`sst.config.ts`). config
- When
sst deployruns - Then all defined stages (app, console, enterprise, lake, monitoring, stats, identity) are deployed
Conflicts
None identified yet.
Open Questions
- What is the pricing/licensing model for enterprise self-hosting vs cloud-managed?
- Should enterprise auth integrate with external identity providers (SAML, OIDC)?
Specification: Enterprise & Cloud Platform
Architecture
SSTThe IaC framework used for cloud infra (`sst.config.ts`). (sst.config.ts) βββΆ infra/
βββ app/ (cloud app service)
βββ console/ (management console)
βββ enterprise/ (self-hosted web app)
βββ lake/ (data warehouse)
βββ monitoring/ (OpenTelemetry, Sentry)
βββ stats/ (analytics dashboard)
βββ identity/ (OpenAuth auth service)
packages/console/ βββΆ SSTThe IaC framework used for cloud infra (`sst.config.ts`). Console (app, core, function, mail, resource, support)
packages/stats/ βββΆ Stats dashboard (app, core, server)
packages/enterprise/ βββΆ Enterprise web app (SolidJS + HonoThe web framework used for the HTTP API server. + SSTThe IaC framework used for cloud infra (`sst.config.ts`).)
The platform uses SSTThe IaC framework used for cloud infra (`sst.config.ts`). for infrastructure-as-code deployment, with separate packages for each service domain.
Data Models
team
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | text | PK | Team identity |
| name | text | not null | Display name |
| members | array | not null | Member references |
deployment_stage
| Field | Type | Constraints | Description |
|---|---|---|---|
| name | text | PK | Stage name (app, console, enterprise, etc.) |
| status | enum | not null | deploying, active, failed |
APIApplication Programming Interface Contracts
Enterprise routes follow the same HTTP APIApplication Programming Interface pattern as the core server (see FEAT-0006) with added authentication middleware.
Sequences
Enterprise deployment
sst deploy --stage enterprise
infra definitions -> Cloudflare/Custom server
enterprise app initializes -> database, auth, teams
admin creates team -> invites members -> members access shared sessions
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| IaC | SSTThe IaC framework used for cloud infra (`sst.config.ts`). | Unified deployment for all services; polyglot stage definitions |
| Enterprise auth | OpenAuth | Open-source, standards-compliant auth service |
| Monitoring | OpenTelemetry + Sentry | Production-grade observability across services |
Risks and Unknowns
- Enterprise licensing and pricing model is not yet defined.
- External identity provider integration (SAML, OIDC) is a likely future requirement.
Out of Scope
- Core session runtime (see FEAT-0001).
- PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. system (see FEAT-0007).
requirements
- What is the pricing/licensing model for enterprise self-hosting vs cloud-managed?
- Should enterprise auth integrate with external identity providers (SAML, OIDC)?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol (ACPAgent Client Protocol)
Overview
The AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol (ACPAgent Client Protocol) implementation provides interoperable agent-to-agent communication within OpenCode. It defines agent, session, tool, event, permission, content, directory, usage, profile, and config operations as a structured protocol, enabling external agents and tools to interact with OpenCode sessions programmatically. ACPAgent Client Protocol is independent from MCPModel Context Protocol and addresses a different use case: driving an OpenCode agent from another agent or automation tool.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Automation users | Drive OpenCode agents from external scripts and CIContinuous Integration pipelines |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). developers | Interoperable protocol for cross-agent communication |
| Core team | Clean separation from MCPModel Context Protocol; protocol evolves independently |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall define ACPAgent Client Protocol operations for agent lifecycle: create, list, describe, delete. | Must | The system shall define ACPAgent Client Protocol operations for agent lifecycle: create, list, describe, delete. |
| FR-02MustThe system shall define ACPAgent Client Protocol operations for session lifecycle: start, send message, list, get, abort. | Must | The system shall define ACPAgent Client Protocol operations for session lifecycle: start, send message, list, get, abort. |
| FR-03MustThe system shall define ACPAgent Client Protocol operations for tool discovery and invocation. | Must | The system shall define ACPAgent Client Protocol operations for tool discovery and invocation. |
| FR-04MustThe system shall define ACPAgent Client Protocol operations for event streaming from active sessions. | Must | The system shall define ACPAgent Client Protocol operations for event streaming from active sessions. |
| FR-05MustThe system shall define ACPAgent Client Protocol permission resolution operations. | Must | The system shall define ACPAgent Client Protocol permission resolution operations. |
| FR-06MustThe system shall define ACPAgent Client Protocol content and directory operations for file access. | Must | The system shall define ACPAgent Client Protocol content and directory operations for file access. |
| FR-07ShouldThe system shall profile agent usage and expose telemetry via ACPAgent Client Protocol. | Should | The system shall profile agent usage and expose telemetry via ACPAgent Client Protocol. |
| FR-08ShouldThe system shall expose agent configuration via ACPAgent Client Protocol operations. | Should | The system shall expose agent configuration via ACPAgent Client Protocol operations. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustACPAgent Client Protocol shall be implemented as a distinct protocol surface, separate from MCPModel Context Protocol. | Must | Compatibility | ACPAgent Client Protocol shall be implemented as a distinct protocol surface, separate from MCPModel Context Protocol. |
| NFR-02ShouldACPAgent Client Protocol operations shall follow consistent naming and response patterns. | Should | Usability | ACPAgent Client Protocol operations shall follow consistent naming and response patterns. |
Constraints
- ACPAgent Client Protocol implementation lives in
packages/opencode/src/acp/. - ACPAgent Client Protocol is a separate protocol from MCPModel Context Protocol (
packages/opencode/src/mcp/).
Acceptance Criteria
- FR-01MustThe system shall define ACPAgent Client Protocol operations for agent lifecycle: create, list, describe, delete.
- Given an ACPAgent Client Protocol client
- When it lists agents
- Then available agents are returned with their capabilities
- FR-02MustThe system shall define ACPAgent Client Protocol operations for session lifecycle: start, send message, list, get, abort.
- Given an ACPAgent Client Protocol client
- When it starts a session and sends a message
- Then a response is streamed back with message content
- FR-07ShouldThe system shall profile agent usage and expose telemetry via ACPAgent Client Protocol.
- Given an ACPAgent Client Protocol session
- When usage data is requested
- Then token counts and provider usage are returned
Conflicts
None identified yet.
Open Questions
- Should ACPAgent Client Protocol be published as a standalone protocol spec, or remain an internal OpenCode implementation?
- How does ACPAgent Client Protocol interact with the permission system when driven by an external agent?
Specification: AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol (ACPAgent Client Protocol)
Architecture
External AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). / Automation ββACPAgent Client ProtocolβββΆ ACPAgent Client Protocol Handler (packages/opencode/src/acp/)
β
βΌ
SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. Runtime (FEAT-0001)
Tool Registry (FEAT-0002)
Provider Layer (FEAT-0003)
ACPAgent Client Protocol handlers translate ACPAgent Client Protocol protocol operations into internal runtime calls, providing a structured interface for external agents.
Data Models
AcpAgent
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | text | PK | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). identity |
| name | text | not null | Display name |
| capabilities | array | not null | Supported operations |
AcpSession
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | text | PK | SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. identity |
| status | enum | not null | active, paused, completed, aborted |
APIApplication Programming Interface Contracts
The ACPAgent Client Protocol module exposes EffectThe functional effect system used pervasively in the core runtime.-based handlers for each operation domain. Wire protocol is JSON over stdin/stdout or TCP (matching MCPModel Context Protocol transport patterns).
AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). operations
List, get, describe, delete agents.
SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. operations
Start session, send message (streaming), list sessions, get session details, abort session.
Tool operations
Discover tools, invoke tools, get tool status.
Event operations
Subscribe to session events, stream events.
Sequences
Drive a session via ACPAgent Client Protocol
ACPAgent Client Protocol Client -> agent:list -> ACPAgent Client Protocol handler -> agent list
ACPAgent Client Protocol Client -> session:start -> handler -> new session
ACPAgent Client Protocol Client -> session:send -> handler -> stream response
ACPAgent Client Protocol Client -> session:events -> handler -> event stream (tool calls, completion)
ACPAgent Client Protocol Client -> session:abort -> handler -> session aborted
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Transport | JSON over stdio/TCP (same as MCPModel Context Protocol) | Familiar pattern; easy to integrate |
| Separation | ACPAgent Client Protocol lives in its own module independent from MCPModel Context Protocol | Avoids conflating agent control with context protocol |
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. binding | ACPAgent Client Protocol sessions map to internal SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. IDs | Reuses existing durable session infrastructure |
Risks and Unknowns
- ACPAgent Client Protocol is a newer protocol with limited adoption; APIApplication Programming Interface stability is not guaranteed.
- Permission model for external agents needs careful design to prevent privilege escalation.
Out of Scope
- MCPModel Context Protocol implementation and servers (see FEAT-0008).
- HTTP APIApplication Programming Interface surface for ACPAgent Client Protocol (goes through the existing server if at all).
requirements
- Should ACP be published as a standalone protocol spec, or remain an internal OpenCode implementation?
- How does ACP interact with the permission system when driven by an external agent?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: Slack Integration
Overview
The Slack Integration (packages/slack) connects OpenCode sessions to Slack conversations via a Slack bot built with @slack/bolt.
It lets users interact with OpenCode agents directly from Slack channels or DMs, bridging the terminal and collaborative chat environments.
Stakeholders
| Stakeholder | Interest |
|---|---|
| Team users | Run OpenCode from Slack without leaving the chat |
| Slack workspace admins | Configure and manage the Slack bot install |
| Core team | Maintain the Slack integration package independently |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall provide a Slack bot that bridges OpenCode sessions into Slack conversations. | Must | The system shall provide a Slack bot that bridges OpenCode sessions into Slack conversations. |
| FR-02MustThe bot shall support sending prompts to OpenCode and receiving responses in Slack. | Must | The bot shall support sending prompts to OpenCode and receiving responses in Slack. |
| FR-03ShouldThe bot shall support slash commands for common OpenCode actions. | Should | The bot shall support slash commands for common OpenCode actions. |
| FR-04ShouldThe bot shall manage session lifecycle (start, list, reattach) from Slack. | Should | The bot shall manage session lifecycle (start, list, reattach) from Slack. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustThe bot shall handle Slack APIApplication Programming Interface rate limits and reconnection gracefully. | Must | Reliability | The bot shall handle Slack APIApplication Programming Interface rate limits and reconnection gracefully. |
| NFR-02ShouldThe bot shall authenticate and scope access to authorized Slack users or channels. | Should | Security | The bot shall authenticate and scope access to authorized Slack users or channels. |
Constraints
- The package lives at
packages/slackand uses@slack/bolt. - The bot requires a running OpenCode server or direct access to session runtime.
Acceptance Criteria
- FR-01MustThe system shall provide a Slack bot that bridges OpenCode sessions into Slack conversations.
- Given the Slack bot is installed in a workspace
- When a user sends a message to the bot
- Then the message is forwarded to OpenCode and the response is returned in Slack
- FR-03ShouldThe bot shall support slash commands for common OpenCode actions.
- Given a user types
/opencode <prompt>in a Slack channel - When the slash command is triggered
- Then the bot responds with the OpenCode agent's output
- Given a user types
Conflicts
None identified yet.
Open Questions
- How should Slack sessions map to OpenCode sessions (1:1, or 1:N per channel)?
- Should the bot support file uploads from Slack (images, documents)?
Specification: Slack Integration
Architecture
Slack βββΆ Slack Bot (packages/slack/, @slack/bolt)
β
βΌ
OpenCode SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. Runtime βββΆ AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). responses βββΆ Slack
The bot listens for events and commands from Slack, translates them into OpenCode session operations, and returns responses to the Slack conversation.
Data Models
SlackSessionMapping
| Field | Type | Constraints | Description |
|---|---|---|---|
| slack_channel | text | PK | Slack channel or DM ID |
| opencode_session_id | text | FK, not null | Mapped OpenCode session ID |
APIApplication Programming Interface Contracts
The bot exposes Slack event handlers and slash commands; no public HTTP APIApplication Programming Interface beyond what Slack requires.
Slash commands
/opencode <prompt>β Send a prompt to the active OpenCode session/opencode-sessionsβ List active sessions
Sequences
Message flow
User sends DM to bot
Slack Events APIApplication Programming Interface -> bot handler
bot -> OpenCode session.prompt(message)
OpenCode streams response -> bot
bot posts response to Slack conversation
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Framework | @slack/bolt | Official Slack SDKSoftware Development Kit; event, command, and action support |
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. mapping | Slack channel to OpenCode session ID | Simple 1:1 mapping for predictable behavior |
| Response mode | Ephemeral or in-channel via message metadata | Lets users choose visibility |
Risks and Unknowns
- SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context.-to-channel mapping persistence (in-memory vs database) is not yet specified.
- Slack's 3000-character message limit may truncate long model responses.
Out of Scope
- Full TUITerminal User Interface-equivalent feature set (see FEAT-0004).
- Multi-user session management in Slack.
requirements
- How should Slack sessions map to OpenCode sessions (1:1, or 1:N per channel)?
- Should the bot support file uploads from Slack (images, documents)?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |
Pipeline Progress ?βͺ not started not yet begunβοΈ draft initial versionπ in review under reviewπ§ in progress actively worked onβ blocked waiting on dependencyβ
done completedβοΈ skipped not applicable
Requirements: GitHub Actions Integration
Overview
The GitHub Actions Integration packages OpenCode as a reusable composite GitHub Action (github/action.yml), enabling AI-powered code review, PRPull Request analysis, and automated engineering tasks directly within GitHub CIContinuous Integration/CD pipelines.
Users can invoke OpenCode in workflows without manual installation or configuration.
Stakeholders
| Stakeholder | Interest |
|---|---|
| CIContinuous Integration/CD users | Run OpenCode in GitHub Actions without manual setup |
| Repository maintainers | Automate PRPull Request review, code analysis, and task execution in CIContinuous Integration |
| Core team | Maintain the action definition and publish lifecycle |
Functional Requirements
| ID | Priority | Requirement |
|---|---|---|
| FR-01MustThe system shall provide a GitHub composite action that installs and runs OpenCode in CIContinuous Integration. | Must | The system shall provide a GitHub composite action that installs and runs OpenCode in CIContinuous Integration. |
| FR-02MustThe action shall accept configurable inputs for the working directory, prompt, and agent selection. | Must | The action shall accept configurable inputs for the working directory, prompt, and agent selection. |
| FR-03MustThe action shall support running OpenCode in headless mode for automated PRPull Request analysis. | Must | The action shall support running OpenCode in headless mode for automated PRPull Request analysis. |
| FR-04ShouldThe action shall preserve session output as CIContinuous Integration artifacts for inspection. | Should | The action shall preserve session output as CIContinuous Integration artifacts for inspection. |
| FR-05ShouldThe action shall be published to the GitHub Marketplace. | Should | The action shall be published to the GitHub Marketplace. |
Non-Functional Requirements
| ID | Priority | Category | Requirement |
|---|---|---|---|
| NFR-01MustThe action shall require minimal YAML configuration (one step). | Must | Usability | The action shall require minimal YAML configuration (one step). |
| NFR-02ShouldThe action shall work on ubuntu-latest, macos-latest, and windows-latest runners. | Should | Compatibility | The action shall work on ubuntu-latest, macos-latest, and windows-latest runners. |
Constraints
- The action definition lives in
github/action.ymlas a composite action. - The action wraps the existing
installscript and CLICommand-Line Interface binary. - Publishing workflows for the action live in
.github/workflows/publish-github-action.yml.
Acceptance Criteria
- FR-01MustThe system shall provide a GitHub composite action that installs and runs OpenCode in CIContinuous Integration.
- Given a workflow using
anomalyco/opencode - When the workflow runs
- Then OpenCode is installed and executes the provided prompt
- Given a workflow using
- FR-03MustThe action shall support running OpenCode in headless mode for automated PRPull Request analysis.
- Given a PRPull Request is opened
- When the action triggers on
pull_request - Then OpenCode analyzes the PRPull Request diff and posts results as a check run
- NFR-01MustThe action shall require minimal YAML configuration (one step).
- Given a minimal workflow setup
- When the action is configured with a prompt and directory
- Then it runs without additional setup steps
Conflicts
None identified yet.
Open Questions
- Should the GitHub Action support persistent sessions across multiple workflow runs?
- How should APIApplication Programming Interface keys for LLMLarge Language Model providers be securely passed to the action (GitHub secrets)?
Specification: GitHub Actions Integration
Architecture
GitHub Workflow ββuses: anomalyco/opencodeβββΆ github/action.yml (composite action)
β
βΌ
install script -> opencode CLICommand-Line Interface
β
βΌ
headless run / PRPull Request analysis / code review
β
βΌ
Check runs, PRPull Request comments, workflow artifacts
The action is a composite action that wraps the install script and CLICommand-Line Interface, exposing inputs for common use cases.
Data Models
No durable models; the action is stateless per invocation.
APIApplication Programming Interface Contracts
GitHub Action Inputs
| Input | Type | Required | Default | Description |
|---|---|---|---|---|
| directory | string | no | . |
Working directory |
| prompt | string | yes | β | Prompt to execute |
| agent | string | no | build |
AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). to use |
| model | string | no | β | Model override |
| github-token | string | no | ${{ github.token }} |
GitHub token for APIApplication Programming Interface access |
Sequences
PRPull Request analysis workflow
pull_request opened
workflow triggers -> checkout repository
action: anomalyco/opencode -> install opencode
opencode run "analyze this PRPull Request diff" -> model analysis
action outputs results -> PRPull Request check run + comment
Technical Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Action type | Composite | No build step; runs the install script directly |
| Secret handling | GitHub secrets via action inputs | Standard GitHub Actions pattern |
| Output | Check runs and PRPull Request comments | Visible in the PRPull Request review UI |
Risks and Unknowns
- Long-running actions may hit GitHub's 6-hour workflow timeout for complex analyses.
- Cost of LLMLarge Language Model APIApplication Programming Interface calls from CIContinuous Integration must be managed by the workflow author.
Out of Scope
- Interactive session support (see FEAT-0001).
- Scheduled/periodic analysis (GitHub cron workflows handle this).
requirements
- Should the GitHub Action support persistent sessions across multiple workflow runs?
- How should API keys for LLM providers be securely passed to the action (GitHub secrets)?
Vocabulary
Domain Terms
| Term | Definition |
|---|---|
| SessionA durable conversational unit tied to a project directory that preserves replayable history and runtime context. | A durable conversational unit tied to a project directory that preserves replayable history and runtime context. |
| System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). | The structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). |
| Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). | The projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context"). |
| Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). | One independently observed typed value within the System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt")., identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). |
| Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. | The span during which one initially rendered System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. |
| Baseline System ContextThe full System Context rendered at the start of a Context Epoch (avoid: "live system prompt"). | The full System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). rendered at the start of a Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition. (avoid: "live system prompt"). |
| Mid-Conversation System MessageA durable chronological instruction telling the model the newly effective state of a changed Context Source (avoid: "system update"). | A durable chronological instruction telling the model the newly effective state of a changed Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). (avoid: "system update"). |
| Context SnapshotThe overwriteable model-hidden JSON state used to compare each Context Source with the value last admitted to a provider turn. | The overwriteable model-hidden JSON state used to compare each Context SourceOne independently observed typed value within the System Context, identified by a stable key, codec, and pure renderers (avoid: "prompt fragment"). with the value last admitted to a provider turn. |
| Provider TurnOne request to a model provider and the response projected from that request. | One request to a model provider and the response projected from that request. |
| Session DrainOne process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. | One process-local execution span that promotes eligible input and runs required provider turns until no immediate continuation remains; it has no durable identity. |
| Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. | A durable user input accepted into the session inbox but not yet included in Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Prompt PromotionThe durable transition that removes an Admitted Prompt from pending input and appends its user message to Session History. | The durable transition that removes an Admitted PromptA durable user input accepted into the session inbox but not yet included in Session History. from pending input and appends its user message to Session HistoryThe projected chronological conversation selected for a provider turn after applying compaction and context epoch cutoffs (avoid: "session context").. |
| Safe Provider-Turn BoundaryThe point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. | The point immediately before a provider call, after input promotion and tool settlement, where context changes may be admitted chronologically. |
| Model Tool OutputThe bounded projection of a tool result persisted in session history and replayed to the model. | The bounded projection of a tool result persisted in session history and replayed to the model. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete output too large for session history. |
| AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). | A named configuration of system instructions, model, and permissions (e.g. build, plan). |
| LocationThe filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. | The filesystem/workspace scope that bounds sessions, tools, model resolution, and permissions. |
| CatalogThe provider-neutral registry of models, request options, and generation controls. | The provider-neutral registry of models, request options, and generation controls. |
Technical Terms
| Term | Definition |
|---|---|
| models.devThe upstream data source for provider/model metadata; new providers are added there first. | The upstream data source for provider/model metadata; new providers are added there first. |
| opentuiThe terminal UI framework (SolidJS-based) used by the TUI. | The terminal UI framework (SolidJS-based) used by the TUITerminal User Interface. |
| EffectThe functional effect system used pervasively in the core runtime. | The functional effect system used pervasively in the core runtime. |
| DrizzleThe ORM used for SQLite schemas (snake_case field names). | The ORM used for SQLite schemas (snake_case field names). |
| SSTThe IaC framework used for cloud infra (`sst.config.ts`). | The IaC framework used for cloud infra (sst.config.ts). |
| HonoThe web framework used for the HTTP API server. | The web framework used for the HTTP APIApplication Programming Interface server. |
| MCPModel Context Protocol | Model Context Protocol; external tool/context servers the agent can call. |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol; interoperable agent communication protocol implemented in OpenCode. |
| PluginA package extending OpenCode via the `@opencode-ai/plugin` SDK and namespaced hooks. | A package extending OpenCode via the @opencode-ai/plugin SDKSoftware Development Kit and namespaced hooks. |
| CompactionThe operation that folds the current complete System Context into a fresh baseline and starts a new Context Epoch. | The operation that folds the current complete System ContextThe structured collection of contextual facts presented to the model as initial instructions and chronological updates (avoid: "system prompt"). into a fresh baseline and starts a new Context EpochThe span during which one initially rendered System Context remains the immutable provider-cache baseline, ending at compaction, session movement, or an incompatible transition.. |
| Generation ControlsProvider-neutral sampling/output controls partitioned from provider wire semantics. | Provider-neutral sampling/output controls partitioned from provider wire semantics. |
| Model Request OptionsProvider-semantic model settings resolved from the Catalog before LLM protocol encoding. | Provider-semantic model settings resolved from the CatalogThe provider-neutral registry of models, request options, and generation controls. before LLMLarge Language Model protocol encoding. |
| PTY EnvironmentThe host-supplied environment overlay applied when creating a PTY. | The host-supplied environment overlay applied when creating a PTYPseudo-Terminal. |
| Managed Tool Output FileA temporary file retaining complete tool output too large for session history. | A temporary file retaining complete tool output too large for session history. |
| SnapshotState snapshots mechanism for saving and restoring session state. | State snapshots mechanism for saving and restoring session state. |
| WorktreeGit worktree management utilities for parallel branch contexts. | Git worktree management utilities for parallel branch contexts. |
Acronyms and Abbreviations
| Abbreviation | Expansion |
|---|---|
| TUITerminal User Interface | Terminal User Interface |
| SDKSoftware Development Kit | Software Development Kit |
| APIApplication Programming Interface | Application Programming Interface |
| CLICommand-Line Interface | Command-Line Interface |
| MCPModel Context Protocol | Model Context Protocol |
| LLMLarge Language Model | Large Language Model |
| LSPLanguage Server Protocol | Language Server Protocol |
| ACPAgent Client Protocol | AgentA named configuration of system instructions, model, and permissions (e.g. `build`, `plan`). Client Protocol |
| ADRArchitecture Decision Record | Architecture Decision Record |
| PTYPseudo-Terminal | Pseudo-Terminal |
| PRPull Request | Pull Request |
| FR / NFRFunctional Requirement / Non-Functional Requirement | Functional Requirement / Non-Functional Requirement |
| ACAcceptance Criterion | Acceptance Criterion |
| CIContinuous Integration | Continuous Integration |
| RICEReach, Impact, Confidence, Effort (prioritization) | Reach, Impact, Confidence, Effort (prioritization) |