
Security News
pnpm 11.5 Adds Support for Recognizing npm Staged Publishes
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.
opencode-forge
Advanced tools
OpenCode Forge - autonomous dev loops, plan storage, and sandboxing for OpenCode
Loops, plans, sandboxing, and code review for OpenCode AI agents
pnpm add opencode-forge
Add to your opencode.json to enable Forge’s server-side hooks, tools, and agents:
{
"plugin": ["opencode-forge@latest"]
}
For TUI features: Also add to your tui.json to enable the sidebar and execution dialog:
{
"$schema": "https://opencode.ai/tui.json",
"plugin": ["opencode-forge@latest"]
}
Optional — workspace integration: to let worktree loops appear as switchable OpenCode workspaces in the TUI, also export this in the environment that launches opencode:
export OPENCODE_EXPERIMENTAL_WORKSPACES=true
Requires OpenCode ≥ 1.15.0. Without it, loops still run normally — you just don't get workspace switching. See Workspace Integration for details.
Forge ships two user-facing surfaces:
opencode.json. The package declares the server oc-plugin surface and exports ./server for the server entrypoint.tui.json. The package declares the tui oc-plugin surface and exports ./tui for the terminal UI entrypoint.The server plugin provides the core hooks, tools, agents, plan storage, loop orchestration, review persistence, and sandbox support. The TUI plugin layers on the sidebar and execution dialog.
Execution flow dialog with mode and model selection:

New session, Execute here, and Loop launch paths for approved plansThe plugin bundles three user-facing agents plus a hidden auditor-loop variant used by loop audit sessions:
| Agent | Mode | Description |
|---|---|---|
| code | all | Primary coding agent. |
| architect | primary | Read-only planning agent. Researches the codebase, designs implementation plans, and caches them for user approval before execution. |
| auditor | subagent | Read-only code auditor for convention-aware reviews. Invoked via Task tool to review diffs, commits, branches, or PRs against stored conventions and decisions. |
| auditor-loop | primary, hidden | Internal audit agent used for loop-runner audit sessions. |
The auditor agent is a read-only subagent that cannot edit source files or execute plans. It is invoked by other agents via the Task tool to review code changes against stored project conventions and decisions.
Tool restrictions: The auditor cannot use the loop tool to prevent interference with active workflows.
The architect agent operates as a read-only planner with message-level reinforcement via the experimental.chat.messages.transform hook. Final plans are rendered once in the assistant response between <!-- forge-plan:start --> and <!-- forge-plan:end --> markers, then auto-captured into SQL before execution approval. After user approval via the question tool, execution is dispatched programmatically — no additional LLM calls are needed. The user can view and edit the cached plan from the sidebar or command palette before or during execution.
Session-scoped plan storage backed by SQL for managing implementation plans. Loop-associated plans are pruned with expired completed loops.
| Tool | Description |
|---|---|
plan-read | Retrieve the plan. Supports pagination with offset/limit and pattern search. |
section-read | Read a section plan and its status for the active loop session. Supports reading by index or defaulting to the lowest-index incomplete section. |
Review finding storage for persisting audit results across session rotations.
| Tool | Description |
|---|---|
review-write | Store a review finding with file, line, severity, and description. Findings are scoped to the current loop. |
review-read | Retrieve review findings. Filter by file path or search by regex pattern. |
review-delete | Delete a review finding by file and line. |
Iterative development loops with automatic auditing. Loops always run in an isolated git worktree; Docker sandbox is used automatically when available.
| Tool | Description |
|---|---|
loop | Execute a plan using an iterative development loop in an isolated git worktree. Args: title required; plan, loopName, and hostSessionId optional. |
loop-cancel | Cancel an active loop by worktree name |
loop-status | List active/recent loops or get detailed status by worktree name, including cumulative token usage when available. Supports restart=true to restart any non-completed loop (running, cancelled, errored, stalled). Completed loops are history-only and cannot be restarted. |
loop reads the current session's captured plan when plan is omitted. maxIterations, execution model, auditor model, and sandbox behavior come from configuration or the TUI execution dialog, not direct loop tool arguments.
| Command | Description | Agent |
|---|---|---|
/review | Run a code review on current changes | auditor (subtask) |
/loop | Start an iterative development loop in a worktree | code |
/loop-status | Check status of all active loops | code |
/loop-cancel | Cancel the active loop | code |
On first run, the plugin automatically copies the bundled config to your config directory:
XDG_CONFIG_HOME is set: $XDG_CONFIG_HOME/opencode/forge-config.jsonc~/.config/opencode/forge-config.jsoncNote: Configuration is stored at ~/.config/opencode/forge-config.jsonc unless XDG_CONFIG_HOME is set.
The plugin supports JSONC format, allowing comments with // and /* */.
You can edit this file to customize settings. The file is created only if it doesn't already exist.
~/.config/opencode/forge-config.jsonc or $XDG_CONFIG_HOME/opencode/forge-config.jsonc~/.local/share/opencode/forge or $XDG_DATA_HOME/opencode/forge~/.local/share/opencode/forge/logs/forge.logEnable logging.enabled to write logs to disk. To use the default log path, omit logging.file or set it to null (an empty string is not treated as a default). Set logging.debug for more verbose output.
{
// Data directory for plugin storage (SQL stores, logs)
// When empty, resolves to ~/.local/share/opencode/forge (or XDG_DATA_HOME equivalent)
"dataDir": "",
// Logging configuration
"logging": {
"enabled": false, // Enable file logging
"debug": false, // Enable debug-level output
"file": "" // Log file path (omit or set to null for default path)
},
// Session compaction settings
"compaction": {
"customPrompt": true, // Use custom compaction prompt for continuity
"maxContextTokens": 0 // Max tokens for context (0 = unlimited)
},
// Messages transform hook for read-only enforcement
"messagesTransform": {
"enabled": true, // Enable transform hook
"debug": false // Enable debug logging
},
// Model override for plan execution sessions (format: "provider/model")
"executionModel": "",
// Model override for the auditor agent (format: "provider/model")
"auditorModel": "",
// Iterative development loop settings
"loop": {
"enabled": true, // Enable iterative loops
"defaultMaxIterations": 15, // Max iterations (0 = unlimited)
"cleanupWorktree": false, // Auto-remove worktree on cancel
"stallTimeoutMs": 60000, // Stall detection timeout (60s)
"maxConsecutiveStalls": 5, // Consecutive stalls before termination (0 = disabled)
"worktreeLogging": { // Worktree loop completion logging
"enabled": false, // Enable completion logging
"directory": "" // Log directory (defaults to platform data dir)
}
},
// Sandbox configuration (optional; provisioned automatically when available)
// Set "enabled": false to force worktree-only mode even when Docker is available.
"sandbox": {
"enabled": true,
"mode": "docker",
"image": "oc-forge-sandbox:latest"
},
// TUI sidebar widget configuration
"tui": {
"sidebar": true, // Show Forge sidebar in OpenCode TUI
"showVersion": true // Show plugin version in sidebar title
},
// TTL in ms for completed/cancelled loops before cleanup. Default: 604800000 (7 days)
"completedLoopTtlMs": 604800000,
// Per-agent overrides (temperature range: 0.0 - 2.0)
// Keys are agent display names (e.g., "code", "architect", "auditor")
// "agents": {
// "architect": { "temperature": 0.0 },
// "auditor": { "temperature": 0.0 },
// "code": { "temperature": 0.7 }
// }
}
dataDir - Data directory for plugin storage (SQL stores, logs). When empty, resolves to ~/.local/share/opencode/forge (or XDG_DATA_HOME equivalent) (default: "")completedLoopTtlMs - TTL for completed/cancelled/errored/stalled loops before sweep (default: 604800000 / 7 days).executionModel - Model override for plan execution sessions, format: provider/model (e.g. anthropic/claude-sonnet-4-20250514). When set, plan execution (via the architect's approval flow or the TUI Execute panel) uses this model for the new Code session. When empty or omitted, OpenCode's default model is used (typically the model field from opencode.json). Recommended: Set this to a fast, cheap model (e.g. Haiku or MiniMax) and use a smart model (e.g. Opus) for the Architect session — planning needs reasoning, execution needs speed. This value is used as a fallback when no per-launch selection is made.auditorModel - Model override for the auditor agent (provider/model). When set, overrides the auditor agent's default model. When not set, uses platform default (default: ""). This value is used as a fallback when no per-launch selection is made.agents - Per-agent temperature overrides keyed by display name (e.g., "code", "architect", "auditor"). Temperature range: 0.0 - 2.0 (default: undefined)logging.enabled - Enable file logging (default: false)logging.debug - Enable debug-level log output (default: false)logging.file - Log file path. Omitted or null falls back to ~/.local/share/opencode/forge/logs/forge.log (default: ""). Setting to an empty string "" passes the empty string through and logging will fail silently. Logs remain in the data directory, only config has moved.When enabled, logs are written to the specified file with timestamps. The log file has a 10MB size limit with automatic rotation.
compaction.customPrompt - Use a custom compaction prompt optimized for session continuity (default: true)compaction.maxContextTokens - Maximum tokens for context during compaction (default: 0 / unlimited)messagesTransform.enabled - Enable the messages transform hook for Architect read-only enforcement (default: true)messagesTransform.debug - Enable debug logging for messages transform (default: false)loop.enabled - Enable iterative development loops (default: true)loop.defaultMaxIterations - Default max iterations for loops, 0 = unlimited (default: 15)loop.cleanupWorktree - Auto-remove worktree on cancel (default: false)loop.stallTimeoutMs - Watchdog stall detection timeout in milliseconds (default: 60000)loop.maxConsecutiveStalls - Number of consecutive stalls before the loop terminates with reason stall_timeout. Set to 0 to disable stall-based termination (default: 5).loop.worktreeLogging.enabled - Enable worktree loop completion logging (default: false)loop.worktreeLogging.directory - Directory for completion logs, defaults to platform data dir (default: "")sandbox.enabled - Enable sandboxed execution. When false, loops run in worktree-only mode even if Docker is available (default: true)sandbox.mode - Sandbox mode: "docker" (optional; Docker sandbox is provisioned automatically when available)sandbox.image - Docker image for sandbox containers (default: "oc-forge-sandbox:latest")sandbox.resources - Container resource limits mapped directly to docker run flags:
memory - Memory limit, e.g., '8g'. Maps to --memory.memorySwap - Memory+swap limit, e.g., '12g'. Maps to --memory-swap.cpus - Number of CPUs, e.g., '4', '2.5'. Maps to --cpus.shmSize - Shared memory size, e.g., '1g'. Maps to --shm-size.tui.sidebar - Show the forge sidebar widget in OpenCode TUI (default: true)tui.showVersion - Show plugin version number in the sidebar title (default: true)tui.keybinds.executePlan - Open the execution dialog for the current session's plan. Default: <leader>f ("Forge"). Avoid <leader>e — that conflicts with opencode's built-in editor_open and your binding will be shadowed.The plugin includes a TUI sidebar widget and an execution dialog for launching plans directly in the OpenCode terminal interface.
The sidebar shows Forge's connection status and version. Captured plans live on the server in the plansRepo SQL store; the TUI no longer keeps a local archive or in-TUI editor.
Open the dialog from the command palette as Forge: Execute plan (default keybind <leader>f). The plan is sourced from the most recent architect message in the current session — the marked <!-- forge-plan:start --> ... <!-- forge-plan:end --> block is parsed out of the assistant's reply. If no marked plan exists in the session, the dialog will not open and you'll see a toast asking the architect to produce one first.
The dialog provides full control over execution parameters:
Choose from three execution modes:
Two model selectors are available:
Execution Model:
config.executionModelAuditor Model:
config.auditorModel → config.executionModelSelections live on the OpenCode server, not in a TUI-local cache. Every loop execution stamps the chosen execution + auditor model (and variants) into workspace.create.extra.forgeLoop, and the next time the dialog opens it derives defaults and recents from workspace.list() plus the session list. This means the picker is correct even when the TUI runs on a different host than the OpenCode server.
The dialog tracks only loop-mode executions for recents / last-used defaults; New session and Execute here modes do not create a workspace, so they do not contribute to recents.
When installed from the package, the TUI plugin loads automatically when added to your TUI config. The plugin is auto-detected via the ./tui export in package.json.
Add to your ~/.config/opencode/tui.json or project-level tui.json:
{
"$schema": "https://opencode.ai/tui.json",
"plugin": [
"opencode-forge"
]
}
The TUI provides a comprehensive model selection dialog when executing plans. The dialog features:
Models are displayed in priority order:
Each model shows:
anthropic/claude-sonnet-4-20250514)TUI options are configured in ~/.config/opencode/forge-config.jsonc under the tui key:
{
"tui": {
"sidebar": true,
"showVersion": true
}
}
Set sidebar to false to completely disable the widget.
For local development, reference the built TUI file directly:
{
"$schema": "https://opencode.ai/tui.json",
"plugin": [
"/path/to/opencode-forge/dist/tui.js"
]
}
Plan with a smart model, execute with a fast model. The architect agent researches the codebase and designs an implementation plan; the code agent implements it.
The architect is read-only and must output exactly one final plan between <!-- forge-plan:start --> and <!-- forge-plan:end --> markers. Forge auto-captures that marked plan into SQL storage for the current session.
The captured plan is the source of truth for execution. The architect's own message in the chat history is the human-readable view; programmatic access is via the plan-read tool.
After the architect presents a summary, the user chooses an execution mode from the execution dialog:
| Mode | When to choose it |
|---|---|
New session | Default for normal implementation |
Execute here | When preserving current context matters |
Loop | Safer autonomous iteration |
The dialog also lets you pick the execution model and auditor model at launch time. Those selections are remembered per project and pre-filled on later launches. Optional variant selectors accompany each model selector, letting you choose provider-specific reasoning or thinking-effort levels (e.g., low, high, max) when the model exposes them. Variant selections are also persisted per project.
Execution is immediate — there are no additional LLM calls between approval and execution. The system intercepts the user's approval answer, reads the cached plan, and dispatches it programmatically to the code agent. The architect never processes the approval response.
Model selection follows this priority order:
For execution model:
config.executionModelFor auditor model:
config.auditorModelconfig.executionModel<!-- forge-plan:start --> / <!-- forge-plan:end --> markers; the capture hook only stores plans wrapped in those markers.logging.enabled to true, and optionally logging.debug for verbose output.The loop is an iterative development system that alternates between coding and auditing phases:
Each iteration runs in a fresh session to keep context small and prioritize speed. After each phase completes, the current session is destroyed and a new one is created. The original task prompt and any audit findings are re-injected into the new session as a continuation prompt, so no context is lost while keeping the window clean.
Audit findings survive session rotation via the review store. The auditor stores each bug and warning using review-write with file, line, severity, and description. At the start of each audit:
review-readreview-deleteLoop sessions rotate between code and auditor work, so Forge persists per-session usage rows in loop_session_usage and merges them for loop-status. Detailed status includes cumulative cost, input/output/reasoning/cache token totals, per-model breakdowns, and live active-session output when available.
Loops always run in an isolated git worktree. Sandbox is optional: when Docker is available and sandbox.mode = 'docker' is configured, a sandbox container is provisioned automatically; otherwise the loop runs in worktree-only mode. Changes are auto-committed and the worktree is removed on completion (branch preserved for later merge).
After each coding iteration, the auditor agent reviews changes against project conventions and stored review findings. Findings are persisted via review-write scoped to the current loop. Outstanding severity: 'bug' findings block completion — the loop terminates only when the auditor has run at least once and zero bug-severity findings remain.
A watchdog monitors loop activity. If no progress is detected within stallTimeoutMs (default: 60s), the current phase is re-triggered. After maxConsecutiveStalls consecutive stalls (default: 5), the loop terminates with reason stall_timeout. Use loop-status with restart to resume from the persisted section/iteration.
Loops use the following priority order for model selection:
executionModel — Global execution model fallbackThe auditor model follows a similar chain: dialog selection → auditorModel → executionModel → platform default.
When launching from the TUI dialog, your selection is remembered and pre-filled on subsequent launches. The dialog also allows selecting a separate model for the auditor phase.
On model errors during execution, automatic fallback to the default model kicks in.
git push is denied inside active loop sessionsquestion and loop are blocked to prevent recursive loops and keep execution autonomous/loop to start, /loop-cancel to cancelloop to start with parameters, loop-status for checking progress (with restart capability), loop-cancel to cancelThe loop terminates when any of these conditions is met:
maxIterations cap is exceeded (0 = unlimited).maxConsecutiveStalls consecutive stalls (default: 5). Use loop-status with restart to resume from the persisted section and iteration.Loops always run in an isolated git worktree. Sandbox is optional: when Docker is available and sandbox.mode = 'docker' is configured, a sandbox container is provisioned automatically; otherwise the loop runs in worktree-only mode.
Worktree loops can optionally register as OpenCode workspaces, letting you switch between them (and your main project) from the same TUI session without restarting or re-opening anything.
Workspace integration requires the experimental workspace runtime to be enabled in OpenCode itself. The plugin API surface (experimental_workspace.register) is always present, but the underlying sync, session-scoping, and TUI dialogs are gated behind an environment variable. Without it, Forge's adapter registers fine but workspace.create silently no-ops and the TUI never shows worktree workspaces.
Set one of these in the environment that launches opencode:
export OPENCODE_EXPERIMENTAL_WORKSPACES=true
# or, to enable every experimental opencode feature at once:
export OPENCODE_EXPERIMENTAL=true
Accepted values are true or 1 (case-insensitive). Requires OpenCode ≥ 1.15.0.
The
OPENCODE_EXPERIMENTAL_WORKSPACESflag is not currently documented on opencode.ai. The authoritative source ispackages/core/src/flag/flag.tsandpackages/opencode/src/effect/runtime-flags.tsin the OpenCode repo.
No forge config option enables or disables this — the toggle is purely on the OpenCode side.
workspace.create no-ops and the loop runs as a plain worktree loop with no workspace switching. Everything else (iteration, auditing, sandbox, status, cancel, restart) is unaffected.When a worktree loop starts with OPENCODE_EXPERIMENTAL_WORKSPACES=true, forge:
experimental.workspace.create with type: "forge", branch: null, and extra: { loopName, projectDirectory, workspaceCreatedAt } to register the workspace through the forge adaptercreate hook creates the git worktree (reusing an orphaned branch when possible) and, when configured, provisions the Docker sandbox containerexperimental.workspace.warp to bind the session to that workspaceloops.workspace_id) so the TUI can route clicks on a loop into the correct workspaceThe adapter's remove hook commits in-flight changes (when teardown context allows), stops the sandbox container if any, and removes the worktree directory unless the loop is restartable. Branches are preserved for later restart or merge.
If workspace creation or session binding fails at runtime — env var unset, OpenCode version too old, network error, API mismatch — the loop does not abort. Forge logs the failure, clears the workspace ID, and the loop continues as a regular (non-workspace) worktree loop. You lose workspace-based switching for that loop, but iteration, auditing, sandbox, and restart all run to completion.
Run loop iterations inside an isolated Docker container. Three tools (bash, glob, grep) execute inside the container via docker exec, while read/write/edit operate on the host filesystem. Your project directory is bind-mounted at /workspace for instant file sharing.
1. Build the sandbox image:
docker build -t oc-forge-sandbox:latest container/
The image includes Node.js 24, pnpm, Bun, Python 3 + uv, ripgrep, git, and jq.
2. Configure the sandbox (~/.config/opencode/forge-config.jsonc):
{
"sandbox": {
"mode": "docker",
"image": "oc-forge-sandbox:latest"
}
}
3. Restart OpenCode.
Start a sandbox loop via the architect plan approval flow (select "Loop") or directly with the loop tool:
loop
Sandbox is optional. When Docker is available and configured, a sandbox container is provisioned automatically; otherwise the loop runs in worktree-only mode. The loop:
/workspacebash, glob, and grep tool calls into the container/workspace. No sync daemon, no file copying. Changes are visible instantly on both sides.bash, glob, and grep route through docker exec when a session belongs to a sandbox loop. The read/write/edit tools operate on the host filesystem directly (compatible with host LSP).forge-<worktreeName>.| Option | Default | Description |
|---|---|---|
sandbox.enabled | true | Enable sandboxed execution. Set to false to force worktree-only mode even when Docker is available. |
sandbox.mode | "docker" | Sandbox mode (optional; Docker used when available) |
sandbox.image | "oc-forge-sandbox:latest" | Docker image to use for sandbox containers |
The container/Dockerfile is included in the project. To add project-specific tools (e.g., Go, Rust, additional language servers), edit the Dockerfile and rebuild:
docker build -t oc-forge-sandbox:latest container/
pnpm build # Compile TypeScript to dist/
pnpm test # Run tests
pnpm typecheck # Type check without emitting
The diagram below shows the overall flow of the Forge loop system — from plan capture through iterative coding/auditing phases with section advancement and session rotation.

MIT
FAQs
OpenCode Forge - autonomous dev loops, plan storage, and sandboxing for OpenCode
The npm package opencode-forge receives a total of 136 weekly downloads. As such, opencode-forge popularity was classified as not popular.
We found that opencode-forge demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.