Skip to content

Add bb thread --plan for CLI/SDK parity with the composer's plan action - #2156

Merged
SawyerHood merged 1 commit into
mainfrom
bb/fix-2019-plan-mode-loaded-sessions
Aug 21, 2026
Merged

SawyerHood merged 1 commit into
mainfrom
bb/fix-2019-plan-mode-loaded-sessions

Conversation

@SawyerHood

@SawyerHood SawyerHood commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

What was wrong

Issue #2019 (report: https://get-bb.github.io/reports/issues/2019.html) had two parts.

  1. /plan was ignored on an already-loaded Claude Code session. This half landed in Enter Plan mode when a later Claude turn carries /plan #2157 (eec134dc6): buildClaudeTurnParams forwards claudeCodePermissionMode, the bridge turn schemas accept it, and enterPlanModeIfRequested switches the live SDK session into Plan mode before the prompt is pushed on both turn/start and turn/steer. This PR no longer touches that code.
  2. No CLI/SDK way into plan mode. Plan mode is keyed on the structured /plan command mention the composer sends (promptInputHasCommandMention), and bb thread tell/spawn always sent mentions: [], so a literal /plan ... reached the Claude CLI, which answered "/plan isn't available in this environment." Agents driving bb through the CLI or SDK had no parity path. This PR fixes that.

What changed

  • packages/domain/src/shared-types.ts: createBuiltinPlanCommandTextInput(text) builds the same /plan command mention the composer's plan action produces. @bb/sdk re-exports it (core/node/browser) so SDK callers pass it as input to threads.spawn/threads.send.
  • apps/cli: --plan on bb thread tell and bb thread spawn uses that helper. Plain /plan ... text is deliberately not parsed (the report's recommendation): that would silently change meaning for providers where /plan is a real slash command.
  • Docs: packages/templates/src/templates/bb-guide-threads.md and the bb-cli SKILL.md document --plan and the SDK helper.
  • Bridge tests only, covering what Enter Plan mode when a later Claude turn carries /plan #2157 left untested (its verifier noted "only turn/start is unit-tested"): bridge.test.ts gains a turn/steer case (which is what bb thread tell --plan on a busy thread becomes): entering Plan mode from a steer, a plain follow-up turn and a repeated /plan steer not re-requesting it, re-entry after an approved plan restored the preset; and a case where a refused setPermissionMode("plan") fails the turn instead of running it in the old mode. session-params.test.ts asserts buildClaudeTurnParams forwards the flag and omits it otherwise. No bridge source changes.

No wire change between server and host daemon, no HOST_DAEMON_PROTOCOL_VERSION or PROVIDER_BRIDGE_PROTOCOL_VERSION bump, no new plugin API members.

How you verified

Fail-before / pass-after on top of current origin/main (git checkout origin/main -- <the 7 non-test source files>, run, restore):

  • apps/cli/src/__tests__/command-output/thread-tell.test.ts "bb thread tell --plan sends the composer's /plan command mention" and thread-spawn.test.ts "bb thread spawn --plan opens the thread with the composer's /plan command mention": on main error: unknown option '--plan' (Tests 2 failed | 35 skipped); restored 37 passed (37).
  • packages/domain/test/shared-types.test.ts "builds plan command input the plan selector recognizes and strips": on main TypeError: createBuiltinPlanCommandTextInput is not a function; restored 11 passed (11).
  • plugins/provider-claude-code: bridge + session-params 84 passed (84) (the new bridge cases exercise code that is already on main via Enter Plan mode when a later Claude turn carries /plan #2157, so they pass on main too; they are coverage, not the proof).

From the committed tree (git status --porcelain empty):

  • pnpm exec turbo run typecheck --filter=@bb/domain --filter=@bb/sdk --filter=@bb/cli --filter=@bb/templates --filter=bb-plugin-provider-claude-code --filter=@bb/server --filter=@bb/agent-runtime -> Tasks: 11 successful, 11 total
  • pnpm exec turbo run test --filter=@bb/domain --filter=@bb/sdk --filter=@bb/cli --filter=@bb/templates --filter=bb-plugin-provider-claude-code -> Tasks: 11 successful, 11 total (domain 151, sdk 96, cli 455, templates 41, claude plugin 326)
  • pnpm exec turbo run test --filter=@bb/provider-parity --force -> Tasks: 2 successful, 2 total (43 passed)
  • apps/server skill tests (builtin-skills-copy, injected-skills, install-cli-skills): 22 passed.

Manual (earlier revision of this branch, before #2157 merged; the CLI path is unchanged): against my own dev instance with a real Claude Code session (claude-haiku-4-5), spawned a claude-code thread in accept-edits, let Reply only with ok. finish, then bb thread tell <thr> --plan "Create a file named hello.txt ..." on the loaded session. The DB client/turn/requested event carried the structured /plan command mention, Claude entered Plan mode, ExitPlanMode produced a pending plan interaction, no file was written; bb thread interactions approve restored accept-edits and created the file.

Fixes #2019

AGENT GENERATED: by Claude Opus 5

Rebase

Rebased onto origin/main at 75d6fc4d4 (was 33 commits behind; conflicted in bridge.ts and bridge.test.ts). #2157 (eec134dc6) landed the same bridge fix this PR originally carried (enterRequestedPlanMode here, enterPlanModeIfRequested there; identical body, same call sites, same schema and buildClaudeTurnParams hunks). Dropped every bridge source hunk (bridge.ts, commands.ts, session-params.ts) and this PR's copy of the turn/start regression test in favour of main's. Kept: the CLI --plan flag, the domain helper and SDK export, guide/skill text, and the bridge test cases #2157 lacks (steer path, plan re-entry, refused switch, turn-params forwarding). Title, commit message, and this body were rewritten for the reduced scope; the fail-before/pass-after proof is now the CLI flag and domain helper.

Independent verification (post-rebase)

Verified at 69f036642 (PR head) against origin/main 85eec4da6 (one unrelated mobile-workflow commit past the rebase base 75d6fc4d4; gh reports MERGEABLE).

Root cause check: plan mode is keyed on a /plan command mention (resolvePromptMode -> promptInputHasCommandMention in apps/server/src/services/threads/thread-commands.ts); the plan composer action's command is always {trigger: "/", name: "plan"} (plugin-provider-registration.ts), so the hardcoded mention the helper builds matches both Claude Code and Codex. The loaded-session half is on main via #2157 (enterPlanModeIfRequested in bridge.ts); this PR adds no bridge source.

Fail-before / pass-after (git checkout origin/main -- <9 non-test source files>, run, git checkout HEAD -- ...):

  • apps/cli thread-tell/thread-spawn --plan tests on main sources: error: unknown option '--plan', Tests 2 failed | 35 skipped (37); restored: pass.
  • packages/domain/test/shared-types.test.ts: TypeError: createBuiltinPlanCommandTextInput is not a function, 1 failed | 10 passed; restored: pass.

From the committed tree (git status --porcelain empty), all with --force (no turbo cache):

  • turbo run typecheck --filter=@bb/domain,@bb/sdk,@bb/cli,@bb/templates,bb-plugin-provider-claude-code,@bb/server,@bb/agent-runtime -> Tasks: 11 successful, 11 total
  • turbo run test for domain/sdk/cli/templates/claude plugin -> Tasks: 11 successful, 11 total (domain 151, sdk 96, cli 455, templates 41, claude plugin 326)
  • turbo run test --filter=@bb/provider-parity --force -> Tasks: 2 successful, 2 total (43 passed)
  • apps/server skill tests (builtin-skills-copy, injected-skills, install-cli-skills): 22 passed.

Live repro on the PR branch (own dev instance, real Claude Code, BB_CLI unset so the worktree CLI runs instead of re-execing the installed binary):

  1. bb thread spawn --provider claude-code --permission-mode accept-edits --plan --prompt ...: the client/turn/requested event carries the structured /plan mention, the Claude session started in Plan mode (its reasoning quotes the "Plan mode is active" reminder), the literal /plan was stripped, and there was no "/plan isn't available in this environment".
  2. bb thread stop, a plain bb thread tell ... "Reply only with ok." (session reloaded in accept-edits), then bb thread tell <thr> "Add a LICENSE file (MIT)..." --plan on that loaded session: bb thread interactions list shows plan | pending | Plan ready for review, no file written. bb thread tell --plan and --help both show and accept the flag.

CI: all checks green on 69f036642 (Checks, Package Smoke x2, Tests app-1..3/integration/packages/server).

Residual notes (minor, not blocking): --plan on a provider that declares no plan composer action (pi, ACP agents) is not rejected by the server; the /plan ... text reaches the provider verbatim, same as typing it in the composer. The helper tags the mention origin: "builtin" while the composer's plan action uses origin: "user"; nothing keys plan mode on origin.

AGENT GENERATED: by Claude Opus 5

@SawyerHood
SawyerHood marked this pull request as ready for review August 21, 2026 06:14
Plan mode is keyed on the structured `/plan` command mention the composer
sends, which `bb thread tell`/`spawn` never produced, so the literal
`/plan` text reached the Claude CLI ("/plan isn't available in this
environment"). Add `--plan` to both commands, a shared
`createBuiltinPlanCommandTextInput` helper (exported from @bb/sdk), and
document the surfaces in the guide and bb-cli skill.

The Claude bridge half of #2019 (switching an already-loaded session
into Plan mode when a later turn carries `/plan`) landed in #2157. This
change adds the bridge coverage #2157 left out: the `turn/steer` path
(`--plan` on a busy thread), re-entry after an approved plan, a refused
`setPermissionMode` failing the turn, and `buildClaudeTurnParams`
forwarding the flag.

Co-Authored-By: Claude <noreply@anthropic.com>
@SawyerHood
SawyerHood force-pushed the bb/fix-2019-plan-mode-loaded-sessions branch from 88f2ed8 to 69f0366 Compare August 21, 2026 16:42
@SawyerHood SawyerHood changed the title Enter Plan mode on loaded Claude sessions; add bb thread --plan Add bb thread --plan for CLI/SDK parity with the composer's plan action Aug 21, 2026
@SawyerHood
SawyerHood merged commit b64ab2b into main Aug 21, 2026
13 checks passed
@SawyerHood
SawyerHood deleted the bb/fix-2019-plan-mode-loaded-sessions branch August 21, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plan mode: ignored on already-loaded claude sessions; /plan has no CLI-parity path

1 participant