diff --git a/apps/opencode-plugin/commands/plannotator-annotate.md b/apps/opencode-plugin/commands/plannotator-annotate.md
index f2c7d2208..6a9c58fb2 100644
--- a/apps/opencode-plugin/commands/plannotator-annotate.md
+++ b/apps/opencode-plugin/commands/plannotator-annotate.md
@@ -1,6 +1,3 @@
---
description: Open interactive annotation UI for a markdown file, HTML file, or URL
---
-
-The Plannotator Annotate UI has been triggered. Opening the annotation UI...
-Acknowledge "Opening annotation UI..." and wait for the user's feedback.
diff --git a/apps/opencode-plugin/commands/plannotator-archive.md b/apps/opencode-plugin/commands/plannotator-archive.md
index b9899be8a..2dfff75cc 100644
--- a/apps/opencode-plugin/commands/plannotator-archive.md
+++ b/apps/opencode-plugin/commands/plannotator-archive.md
@@ -1,6 +1,3 @@
---
description: Browse saved plan decisions in the archive
---
-
-The Plannotator Archive has been triggered. Opening the archive browser...
-Acknowledge "Opening plan archive..." and wait for the user to finish browsing.
diff --git a/apps/opencode-plugin/commands/plannotator-review.md b/apps/opencode-plugin/commands/plannotator-review.md
index 172904be4..bd150d01d 100644
--- a/apps/opencode-plugin/commands/plannotator-review.md
+++ b/apps/opencode-plugin/commands/plannotator-review.md
@@ -1,6 +1,3 @@
---
description: Open interactive code review for current changes or a PR URL; pass --git to force Git in JJ workspaces
---
-
-The Plannotator Code Review has been triggered. Opening the review UI...
-Acknowledge "Opening code review..." and wait for the user's feedback.
diff --git a/apps/opencode-plugin/index.ts b/apps/opencode-plugin/index.ts
index 5e576853a..b9ebb9fb8 100644
--- a/apps/opencode-plugin/index.ts
+++ b/apps/opencode-plugin/index.ts
@@ -383,11 +383,26 @@ The user will review your plan in a visual UI where they can annotate, approve,
Do NOT proceed with implementation until your plan is approved.`);
},
- // Intercept plannotator-last before the agent sees the command
+ // Intercept plannotator commands before the agent sees them.
+ // Clearing output.parts in place suppresses the .md body + appended
+ // args so the agent never receives the command — without this, OpenCode
+ // calls resolvePromptParts() on "
", which auto-attaches
+ // any file path it finds as a FilePart. On a large file that blows the
+ // context before the annotation UI even opens (#713).
+ //
+ // Must mutate in place (length = 0), not reassign (= []). The caller
+ // holds a reference to the parts array directly and ignores any new
+ // array assigned to output.parts.
"command.execute.before": async (input, output) => {
- if (input.command !== "plannotator-last") return;
+ const cmd = input.command;
+ if (
+ cmd !== "plannotator-last" &&
+ cmd !== "plannotator-annotate" &&
+ cmd !== "plannotator-review" &&
+ cmd !== "plannotator-archive"
+ ) return;
- output.parts = [];
+ output.parts.length = 0;
const deps: CommandDeps = {
client: ctx.client,
@@ -398,58 +413,35 @@ Do NOT proceed with implementation until your plan is approved.`);
getPasteApiUrl,
directory: ctx.directory,
};
+ // input.arguments is the raw tail string from OpenCode's command dispatcher —
+ // needed so --gate / --json reach the handlers' parseAnnotateArgs (#570).
+ const event = {
+ properties: { sessionID: input.sessionID, arguments: input.arguments },
+ };
- const feedback = await handleAnnotateLastCommand(
- // input.arguments is the raw tail string from OpenCode's command dispatcher —
- // needed so --gate / --json reach handleAnnotateLastCommand's parseAnnotateArgs (#570).
- { properties: { sessionID: input.sessionID, arguments: input.arguments } },
- deps
- );
-
- if (feedback) {
- try {
- await ctx.client.session.prompt({
- path: { id: input.sessionID },
- body: {
- parts: [{
- type: "text",
- text: getAnnotateMessageFeedbackPrompt("opencode", undefined, { feedback }),
- }],
- },
- });
- } catch {
- // Session may not be available
+ if (cmd === "plannotator-last") {
+ const feedback = await handleAnnotateLastCommand(event, deps);
+ if (feedback) {
+ try {
+ await ctx.client.session.prompt({
+ path: { id: input.sessionID },
+ body: {
+ parts: [{
+ type: "text",
+ text: getAnnotateMessageFeedbackPrompt("opencode", undefined, { feedback }),
+ }],
+ },
+ });
+ } catch {
+ // Session may not be available
+ }
}
+ return;
}
- },
-
- // Listen for slash commands (review + annotate)
- event: async ({ event }) => {
- const isCommandEvent =
- event.type === "command.executed" ||
- event.type === "tui.command.execute";
-
- if (!isCommandEvent) return;
-
- // @ts-ignore - Event structure varies
- const commandName = event.properties?.name || event.command || event.payload?.name;
-
- const deps: CommandDeps = {
- client: ctx.client,
- htmlContent: getPlanHtml(),
- reviewHtmlContent: getReviewHtml(),
- getSharingEnabled,
- getShareBaseUrl,
- getPasteApiUrl,
- directory: ctx.directory,
- };
- if (commandName === "plannotator-review")
- return handleReviewCommand(event, deps);
- if (commandName === "plannotator-annotate")
- return handleAnnotateCommand(event, deps);
- if (commandName === "plannotator-archive")
- return handleArchiveCommand(event, deps);
+ if (cmd === "plannotator-annotate") return handleAnnotateCommand(event, deps);
+ if (cmd === "plannotator-review") return handleReviewCommand(event, deps);
+ if (cmd === "plannotator-archive") return handleArchiveCommand(event, deps);
},
};