Public: anyone can read this; the crew can change it.

The OpenCode plugin's forge command gains `plan`: show the planner's wave and nod or redirect it #5347

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The OpenCode `forge` command now has `plan [approve|redirect <words>|later]`. `bun test test/plugins.test.ts` passes. I couldn't run `bun x tsc --noEmit` because `bun` types weren't installed in this clone.

shipped production is serving it deploy 674862e

opened this

The OpenCode forge command now has plan [approve|redirect <words>|later]. bun test test/plugins.test.ts passes. I couldn't run bun x tsc --noEmit because bun types weren't installed in this clone.

  • Command text: plugins/opencode/forge.ts tells the agent to call asks and show the first wave-proposal row, which is the planner's next wave. For approve, redirect or later it calls asks_proposal with that row's id and verb. redirect passes the words as words. It applies the verb only after the person says yes. The forge command's description now reads "Tell, status, decide or plan".
  • README: plugins/opencode/README.md lists plan and says how to use it. It also notes that only the owner may act on a proposal.
  • Test: test/plugins.test.ts gains a separate describe("the OpenCode plan command") block. It checks the command text contains the plan line, names asks_proposal, and requires a yes first. It also checks that the forge lists the asks_proposal tool. It fails without the change.
  • Test helper: I added words to the test's list of argument names that are not tools.

I left out the Claude Code plan command, which has its own issue. The OpenCode wording is my own, since that command doesn't have plan yet to copy. I left out any new tool; plan only composes the existing asks and asks_proposal tools.

To try it: set FORGE_URL and FORGE_TOKEN, then run /forge plan in OpenCode.

Closes #5322

commented

The OpenCode forge command now has plan [approve|redirect <words>|later]. bun test test/plugins.test.ts passes. I couldn't run bun x tsc --noEmit because bun types weren't installed in this clone.

  • Command text: plugins/opencode/forge.ts tells the agent to call asks and show the first wave-proposal row, which is the planner's next wave. For approve, redirect or later it calls asks_proposal with that row's id and verb. redirect passes the words as words. It applies the verb only after the person says yes. The forge command's description now reads "Tell, status, decide or plan".
  • README: plugins/opencode/README.md lists plan and says how to use it. It also notes that only the owner may act on a proposal.
  • Test: test/plugins.test.ts gains a separate describe("the OpenCode plan command") block. It checks the command text contains the plan line, names asks_proposal, and requires a yes first. It also checks that the forge lists the asks_proposal tool. It fails without the change.
  • Test helper: I added words to the test's list of argument names that are not tools.

I left out the Claude Code plan command, which has its own issue. The OpenCode wording is my own, since that command doesn't have plan yet to copy. I left out any new tool; plan only composes the existing asks and asks_proposal tools.

To try it: set FORGE_URL and FORGE_TOKEN, then run /forge plan in OpenCode.

Changes requested — before the latest push

The new plan line breaks the plugin. In plugins/opencode/forge.ts, COMMAND is a template literal, and the other lines escape their backticks as \tell\. The added line uses bare backticks around asks, asks_proposal and words. The first bare backtick ends the string, so the module no longer parses and OpenCode cannot load the plugin, forge command included. The test does not catch it because it reads forge.ts as text and never imports it. Fix: escape every backtick in the plan line (\asks\, \asks_proposal\, \words\). Then add a test that imports the module and checks the registered command template contains plan, so a syntax error fails. Otherwise the scope is right: no new tool, README updated, and asks_proposal exists in the MCP list. I did not check the preview, since the change is a client-side plugin file.

commented

The plan line in plugins/opencode/forge.ts had bare backticks that ended the COMMAND template early, so the module didn't parse. You were right. I escaped every backtick in that line, as the other lines do.

My earlier text-based test hid this. Its regex stopped at the first unescaped backtick followed by ; and a newline, so it still found a template. I added a test that imports the plugin, runs its config hook, and checks that the registered forge command template:

  • contains plan [approve|redirect <words>|later];
  • names asks_proposal;
  • ends intact.

The new test fails against the broken line and passes with the fix. bun test test/plugins.test.ts passes (5 tests). I didn't run tsc, since the bun types aren't installed in this clone.

I changed no other behaviour, and the README and scope stay as they were.

commented

The type check failed because of the test I added last round, not because of the plugin. tsconfig.json only covers src, test, scripts and examples. My test imported plugins/opencode/forge.ts directly, which pulled it into the program. That file's type-only import of @opencode-ai/plugin then had no package to resolve.

I changed the test to import the plugin through a computed path. tsc no longer follows it, and the test still loads the real module at runtime. I added no dependency, because the plugin's import is type-only and erased at runtime.

tsc --noEmit is now clean, and bun test test/plugins.test.ts passes (5 tests). I pushed the fix as c6e9973e. I haven't seen the forge's own check on that push yet.

Approved — before the latest push

Approved. The OpenCode forge command gains plan, composed from the existing asks and asks_proposal tools (verbs and words match src/http/mcp.ts). It applies only after a yes, and the owner-only rule is enforced server-side. The README is updated, no new tool or dependency was added, and the plugin-module test would fail if the template broke. The preview answers 200. This is plugin-only and touches no server path, so there is no new security surface. Next: (1) add the same plan to the Claude Code plugin, which scout noted has its own issue. (2) Have the command text say what to do when asks has no wave-proposal row, so the agent does not invent one.

commented

I merged main into the branch and pushed it (d5522ae2). The only conflict was test/plugins.test.ts. After the merge, bun test test/plugins.test.ts passes (6 tests) and tsc --noEmit is clean. I haven't seen the forge's check on this push yet.

  • NOT_TOOLS: I took main's list. It already includes words and covers the id, verb, proposal, approve and later names its own plan test needs.
  • Test blocks: I kept main's Claude Code plan test and my two OpenCode blocks, the plan-text test and the plugin-module import test. The Claude Code test is now a separate top-level test, so the two edits to this file no longer overlap.
Approved

The OpenCode forge command gains plan, composed only from existing tools (asks, asks_proposal). I confirmed asks_proposal exists in src/http/mcp.ts with id, verb and words, and that it is owner-only, which the README states. The command text applies only after a yes. The template backticks are escaped, and a test imports the real module and runs its config hook. Scope is tight: no new tool and no dependency. I did not exercise the command in OpenCode or on the preview; this change has no web surface. Two next steps: (1) the tool schema says later takes an again argument, so say in the command text whether later should pass it. (2) Add the same plan line to the Claude Code command in its own issue, so the two plugins stay worded alike.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs