You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Today /fork is just an alias of /branch — it copies the transcript into a new session that the user switches into (the classic session-fork delivered in #4158). Meanwhile the engine for a background fork agent already exists in the codebase but has no user-facing slash command.
I'd like a dedicated /fork <directive> command that spawns a background agent inheriting the full current conversation (system prompt, complete history, exact tool set, model, and prompt-cache parity) to work the directive, while the main conversation keeps going. When it finishes, its result is reported back into the current session.
This mirrors the behavior Claude Code shipped: /fork = background agent inheriting the conversation, /branch = copy-to-new-session. In our code that split would be:
branchCommand (packages/cli/src/ui/commands/branchCommand.ts) keeps the "copy into a new session" behavior, and drops altNames: ['fork'] so /fork is freed up.
A new forkCommand takes a <directive> and launches a full-tool background fork, parallel to how /btw already fires runForkedAgent in the background today.
Why is this needed?
The hard part is already built and tested — only the user-facing entry point is missing:
packages/core/src/tools/agent/fork-subagent.ts — FORK_AGENT (tools: ['*'], session-level, "inherits full conversation context"), buildForkedMessages(), FORK_PLACEHOLDER_RESULT, and the isInForkExecution() recursive-fork guard.
packages/core/src/utils/forkedAgent.ts — runForkedAgent with a dual path: cache path (GeminiChat, single-turn, no tools — used by /btw) and full-tool path (AgentHeadless, multi-turn), plus CacheSafeParams for prompt-cache reuse.
packages/core/src/agents/background-tasks.ts — BackgroundTaskRegistry (concurrency cap, lifecycle, task-notification reporting) and background-agent-resume.ts for re-attach across restarts.
packages/cli/src/ui/commands/btwCommand.ts — an existing precedent of a slash command that fires a background fork (fire-and-forget, non-blocking) and reuses CacheSafeParams so the fork sees the full system prompt + history.
So /fork would not introduce a new engine — it would expose the existing background-fork engine through a dedicated command, complementing the session-copy /branch (#4158) and the fork-subagent work (#3016).
Concretely it lets a user, mid-conversation, hand an independent task to a background worker (refactor, batch edit, investigate a bug) without interrupting the main thread or losing accumulated context.
Additional context
Suggested UX: /fork <directive> → returns immediately with a short fork name + id; the worker runs in the background and reports its result/summary back into the session on completion.
Suggested guards (mostly already present in the engine): refuse to fork before the first conversation turn; refuse while a response/tool call is in flight; bubble permission prompts back to the parent; recursive-fork rejection via isInForkExecution().
Suggested rollout: gate the new command behind a feature flag while it stabilizes.
What would you like to be added?
Today
/forkis just an alias of/branch— it copies the transcript into a new session that the user switches into (the classic session-fork delivered in #4158). Meanwhile the engine for a background fork agent already exists in the codebase but has no user-facing slash command.I'd like a dedicated
/fork <directive>command that spawns a background agent inheriting the full current conversation (system prompt, complete history, exact tool set, model, and prompt-cache parity) to work the directive, while the main conversation keeps going. When it finishes, its result is reported back into the current session.This mirrors the behavior Claude Code shipped:
/fork= background agent inheriting the conversation,/branch= copy-to-new-session. In our code that split would be:branchCommand(packages/cli/src/ui/commands/branchCommand.ts) keeps the "copy into a new session" behavior, and dropsaltNames: ['fork']so/forkis freed up.forkCommandtakes a<directive>and launches a full-tool background fork, parallel to how/btwalready firesrunForkedAgentin the background today.Why is this needed?
The hard part is already built and tested — only the user-facing entry point is missing:
packages/core/src/tools/agent/fork-subagent.ts—FORK_AGENT(tools: ['*'], session-level, "inherits full conversation context"),buildForkedMessages(),FORK_PLACEHOLDER_RESULT, and theisInForkExecution()recursive-fork guard.packages/core/src/utils/forkedAgent.ts—runForkedAgentwith a dual path: cache path (GeminiChat, single-turn, no tools — used by/btw) and full-tool path (AgentHeadless, multi-turn), plusCacheSafeParamsfor prompt-cache reuse.packages/core/src/agents/background-tasks.ts—BackgroundTaskRegistry(concurrency cap, lifecycle,task-notificationreporting) andbackground-agent-resume.tsfor re-attach across restarts.packages/cli/src/ui/commands/btwCommand.ts— an existing precedent of a slash command that fires a background fork (fire-and-forget, non-blocking) and reusesCacheSafeParamsso the fork sees the full system prompt + history.So
/forkwould not introduce a new engine — it would expose the existing background-fork engine through a dedicated command, complementing the session-copy/branch(#4158) and the fork-subagent work (#3016).Concretely it lets a user, mid-conversation, hand an independent task to a background worker (refactor, batch edit, investigate a bug) without interrupting the main thread or losing accumulated context.
Additional context
/fork <directive>→ returns immediately with a short fork name + id; the worker runs in the background and reports its result/summary back into the session on completion.isInForkExecution()./branch).