Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ To check your configured providers:

- `/opencode:review` -- Normal OpenCode code review (read-only). Supports `--base <ref>`, `--pr <number>`, `--model <provider/model>`, `--free`, `--wait`, and `--background`.
- `/opencode:adversarial-review` -- Steerable review that challenges implementation and design decisions. Supports `--base <ref>`, `--pr <number>`, `--model <provider/model>`, `--free`, `--wait`, `--background`, and custom focus text.
- `/opencode:rescue` -- Delegates a task to OpenCode via the `opencode:opencode-rescue` subagent. Supports `--model`, `--free`, `--agent`, `--resume`, `--fresh`, `--worktree`, `--wait`, and `--background`.
- `/opencode:rescue` -- Delegates a task to OpenCode via the `safe-command.mjs` bridge, which validates flags and feeds the task text through a shell-insulated heredoc. Supports `--model`, `--free`, `--agent`, `--resume`, `--fresh`, `--worktree`, `--wait`, and `--background`. Foreground is the default; `--wait` is an explicit no-op alias for foreground; `--background` detaches a worker and returns a job id you can poll with `/opencode:status`.
- `/opencode:status` -- Shows running/recent OpenCode jobs for the current repo.
- `/opencode:result` -- Shows final output for a finished job, including OpenCode session ID for resuming.
- `/opencode:cancel` -- Cancels an active OpenCode job.
Expand Down Expand Up @@ -185,7 +185,6 @@ opencode-plugin-cc/
├── .github/workflows/ci.yml # GitHub Actions CI
├── plugins/opencode/
│ ├── .claude-plugin/plugin.json # Plugin metadata
│ ├── agents/opencode-rescue.md # Rescue subagent definition
│ ├── commands/ # 7 slash commands
│ │ ├── review.md
│ │ ├── adversarial-review.md
Expand Down
45 changes: 0 additions & 45 deletions plugins/opencode/agents/opencode-rescue.md

This file was deleted.

98 changes: 58 additions & 40 deletions plugins/opencode/commands/rescue.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,87 @@
---
description: Delegate investigation, an explicit fix request, or follow-up rescue work to the OpenCode rescue subagent
description: Delegate investigation, an explicit fix request, or follow-up rescue work to OpenCode
argument-hint: "[--background|--wait] [--worktree] [--resume|--fresh] [--model <provider/model> | --free] [--agent <build|plan>] [what OpenCode should investigate, solve, or continue]"
context: fork
allowed-tools: Bash(node:*), AskUserQuestion
---

Route this request to the `opencode:opencode-rescue` subagent.
The final user-visible response must be OpenCode's output verbatim.
Forward this request to the OpenCode companion's `task` runtime through the `safe-command.mjs` bridge.
The final user-visible response must be the bridge's stdout verbatim — no commentary, summary, or paraphrase before or after it.

Raw user request:
$ARGUMENTS

Helper calls the command may make BEFORE the final bridged `task` invocation:

- `node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" task-resume-candidate --json` — resume-detection helper
- `node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" last-review` — last-review presence check
- `node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" last-review --content` — last-review full text

Each of these is a separate Bash call that runs in the foreground and returns quickly. They are NOT the final task invocation — they are just information probes that inform how you build the final bridged call. Do not background them, and do not forward their output to the user.

Execution mode:

- If the request includes `--background`, run the `opencode:opencode-rescue` subagent in the background.
- If the request includes `--wait`, run the `opencode:opencode-rescue` subagent in the foreground.
- If neither flag is present, default to foreground.
- `--background` and `--wait` are execution flags for Claude Code. Do not forward them to `task`, and do not treat them as part of the natural-language task text.
- `--model`, `--free`, and `--agent` are runtime-selection flags. Preserve them for the forwarded `task` call, but do not treat them as part of the natural-language task text. `--free` tells the companion to pick a random first-party `opencode/*` free-tier model from `opencode models`; it is restricted to `opencode/*` because OpenRouter free models have inconsistent tool-use support. `--free` is mutually exclusive with `--model`.
- `--worktree` is an isolation flag. Preserve it for the forwarded `task` call, but do not treat it as part of the natural-language task text. When present, OpenCode runs in an isolated git worktree instead of editing the working directory in-place.
- If the request includes `--resume`, do not ask whether to continue. The user already chose.
- If the request includes `--fresh`, do not ask whether to continue. The user already chose.
- Otherwise, before starting OpenCode, check for a resumable rescue session from this Claude session by running:
- Default is foreground: the bridged Bash call runs synchronously and the user sees the companion's full output when the task finishes.
- If the request includes `--background`, the companion detaches a worker and the bridge returns a job id immediately (`OpenCode task started in background: <id>` plus a `Check /opencode:status for progress.` line). Return that stdout verbatim.
- The Bash call that runs the bridge must always run in the foreground — never set `run_in_background: true` on the Bash tool, even when the user passes `--background`. Companion-level backgrounding is what `--background` forwards to.
- `--wait` is accepted as a documented no-op alias for the default foreground mode. The bridge strips it.
- `--background` and `--wait` are the only execution-mode flags. Every other flag is forwarded to the companion.

```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" task-resume-candidate --json
```
Flag handling (all of these are recognized, validated, and forwarded by `safe-command.mjs`):

- `--background` — companion detaches a worker and returns a job id.
- `--wait` — no-op alias for foreground; bridge strips it.
- `--worktree` — run OpenCode in an isolated git worktree instead of editing the working directory in-place.
- `--resume` (or `--resume-last`) — continue the most recent OpenCode session from this Claude session. The bridge translates `--resume` into the companion-native `--resume-last`.
- `--fresh` — explicit marker that the task must NOT resume. The bridge strips it (the absence of `--resume-last` already conveys "fresh").
- `--model <provider/model-id>` — override OpenCode's default model for this single task. Value must match `[A-Za-z0-9._/:-]+`.
- `--free` — tells the companion to pick a random first-party `opencode/*` free-tier model from `opencode models`. Restricted to `opencode/*` because OpenRouter free models have inconsistent tool-use support.
- `--agent <build|plan>` — override the OpenCode agent. Value must be `build` or `plan`.
- `--free` and `--model` are mutually exclusive — the bridge rejects payloads that include both. If the user supplies both, return the bridge's error verbatim and stop.

Resume detection (runs before the final bridged call, only when neither `--resume` nor `--fresh` is in the raw user request):

- Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" task-resume-candidate --json` in the foreground.
- If that helper reports `available: true`, use `AskUserQuestion` exactly once to ask whether to continue the current OpenCode session or start a new one.
- The two choices must be:
- `Continue current OpenCode session`
- `Start a new OpenCode session`
- If the user is clearly giving a follow-up instruction such as "continue", "keep going", "resume", "apply the top fix", or "dig deeper", put `Continue current OpenCode session (Recommended)` first.
- Otherwise put `Start a new OpenCode session (Recommended)` first.
- If the user chooses continue, add `--resume` before routing to the subagent.
- If the user chooses a new session, add `--fresh` before routing to the subagent.
- If the helper reports `available: false`, do not ask. Route normally.

Operating rules:
- If the user chooses continue, add `--resume` at the start of the payload you feed to the bridge heredoc.
- If the user chooses a new session, do not add `--resume`.
- If the helper reports `available: false`, do not ask. Proceed without `--resume`.
- If the user is clearly asking to continue prior OpenCode work (such as "continue", "keep going", "resume", "apply the top fix", or "dig deeper") and `--fresh` is not in the raw request, add `--resume` to the payload even when the resume-detection helper was skipped.

- The subagent is a thin forwarder only. It should use one `Bash` call to invoke `node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" task ...` and return that command's stdout as-is.
- Return the OpenCode companion stdout verbatim to the user.
- Do not paraphrase, summarize, rewrite, or add commentary before or after it.
- Do not ask the subagent to inspect files, monitor progress, poll `/opencode:status`, fetch `/opencode:result`, call `/opencode:cancel`, summarize output, or do follow-up work of its own.
- Leave `--agent` unset unless the user explicitly asks for a specific agent (build or plan).
- Leave the model unset unless the user explicitly asks for a specific model or `--free`.
- Leave `--resume` and `--fresh` in the forwarded request. The subagent handles that routing when it builds the `task` command.
- If the helper reports that OpenCode is missing or unauthenticated, stop and tell the user to run `/opencode:setup`.
- If the user did not supply a request, check for a saved review from `/opencode:review` or `/opencode:adversarial-review`:
Empty-request / last-review branch (runs when the raw user request contains no task text):

```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" last-review
```
- Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" last-review` in the foreground.
- If stdout is `LAST_REVIEW_AVAILABLE`, use `AskUserQuestion` exactly once with two options:
- `Fix issues from last review (Recommended)` — prepend the saved review content as context for the rescue task
- `Describe a new task` — ask what OpenCode should investigate or fix
- If the user chooses to fix from last review, read the saved review via `node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" last-review --content` and include its stdout verbatim inside the final bridged payload, prefixed with the literal line `The following issues were found in a prior OpenCode review. Please fix them:` followed by a blank line and then the review content.
- If stdout is `NO_LAST_REVIEW`, ask the user what OpenCode should investigate or fix and use their reply as the task text.

- If stdout is `LAST_REVIEW_AVAILABLE`, use `AskUserQuestion` exactly once with two options:
- `Fix issues from last review (Recommended)` — prepend the saved review content as context for the rescue task
- `Describe a new task` — ask what OpenCode should investigate or fix
- If the user chooses to fix from last review, read the saved review via:
Final bridged call (exactly one foreground Bash invocation of `safe-command.mjs`, after any helper calls and user questions above have settled):

```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/opencode-companion.mjs" last-review --content
node "${CLAUDE_PLUGIN_ROOT}/scripts/safe-command.mjs" task <<'OPENCODE_TASK'
$ARGUMENTS
OPENCODE_TASK
```

and include its stdout verbatim in the forwarded task text, prefixed with:
Payload rules:

- The body of the heredoc above is the bridge's stdin. Replace `$ARGUMENTS` with the adjusted payload you have decided on: any recognized flags first, then the natural-language task text. Preserve the user's task text byte-for-byte; do not paraphrase, re-quote, or escape it.
- If you added `--resume` via the resume-detection branch, the first token of the payload must be `--resume`.
- If the user chose "Fix issues from last review", prepend the literal header line and the review content before the task text, inside the same heredoc body.
- Rescue is always write-capable. The companion's `task` runtime defaults to write mode and has no read-only switch. If the user asks for read-only, point them at `/opencode:review` or `/opencode:adversarial-review` instead.
- The single-quoted heredoc delimiter (`<<'OPENCODE_TASK'`) prevents shell expansion of anything inside the body, so apostrophes, quotes, `$()`, backticks, `;`, `&`, `|`, `<`, `>`, and newlines in the task text are all safe. Do not try to escape them yourself.

`The following issues were found in a prior OpenCode review. Please fix them:\n\n`
Return rules:

- If stdout is `NO_LAST_REVIEW`, ask what OpenCode should investigate or fix.
- Return the bridge stdout exactly as-is.
- Do not paraphrase, summarize, rewrite, or add commentary before or after it.
- Do not inspect the repository, read files, grep, monitor progress, poll `/opencode:status`, fetch `/opencode:result`, call `/opencode:cancel`, summarize output, or do any follow-up work of your own.
- If the bridge rejects the payload (unknown flag, invalid `--model` value, `--free` + `--model`, etc.), return the bridge's stderr verbatim and stop.
- If the helper reports that OpenCode is missing or unauthenticated, stop and tell the user to run `/opencode:setup`.
Loading