Fork a Claude Code session into a new tmux pane. Mid-turn. Full tools. Persistent.
You must be running Claude Code inside tmux. This won't work in VS Code terminal, iTerm2 without tmux, Windows without WSL+tmux, or any non-tmux environment. tmux is the whole trick.
prefix+f → instant fork (even while Claude is mid-turn)
/forkoff → fork from prompt
It's /btw but instead of a disposable one-shot answer, you get a whole new Claude with your full conversation context, its own context window, and all tools available. Named after what you mutter when you need two of yourself.
git clone https://github.com/user/forkoff.git
cd forkoff && bash install.shNeeds tmux (obviously), claude in PATH, and python3 or jq.
bash install.sh --uninstall to clean up.
prefix+f — fork right. Works while Claude is busy. Doesn't interrupt anything. This is the one you want most of the time.
prefix+F — same but splits below.
/forkoff [text] — type at the prompt. A UserPromptSubmit hook catches it, forks, and blocks the prompt so Claude never sees it (zero API turns). If you type this mid-turn it'll interrupt the current work though — use the keybinding instead if you don't want that.
forkoff.sh — direct invocation for scripts: ~/.claude/scripts/forkoff.sh "$TMUX_PANE" "$(pwd)" right "go investigate auth"
Under the hood it reads session_id from .claude/context-state-$TMUX_PANE.json and runs claude --resume <id> --fork-session in a new split pane. The -d flag keeps focus on your current pane.
- Requires tmux. No tmux, no forkoff. VS Code terminal, Windows without WSL — won't work.
- Mid-turn via keybinding only. The keybinding runs outside Claude entirely (tmux does the work). The
/forkoffprompt path can't avoid interrupting a busy turn — that needs a privilegedimmediate+local-jsxcommand type that only built-ins get. - Forks from current state.
/btwtrimmed the unfinished assistant tail before forking.--fork-sessiontakes the session as-is. Usually fine.
We traced this from the v2.1.80 binary (cli.js, 12MB minified). The interesting part isn't that /btw existed — it's how it ran mid-turn without interrupting anything.
/btw was registered as type: "local-jsx" with immediate: true. That's a privileged command type. When you typed during a busy turn, the input handler hit an early-exit branch (offset 11561216) that checked for immediate local-jsx commands before the normal interrupt+queue path:
let e = _.find((q6) => q6.immediate && q6.isEnabled() && ...);
if (e && e.type === "local-jsx" && (K.isActive || Y)) {
o = await (await e.load()).call(H6, q6, t);
return // exits before the interrupt path ever runs
}The actual side question ran through kh8() → xf() (the fork kernel at offset 9258609) with querySource: "side_question", maxTurns: 1, skipCacheWrite: true, canUseTool: deny. In-process, same Node.js runtime, result displayed inline then thrown away.
That fork profile still lives in the RC control protocol's side_question handler — same identity, same kernel, just routed through the WebSocket bridge now instead of a local slash command.
The full call chain: BiY (registration, offset 9643268) → miY (handler, 9642907) → IiY (React component) → uiY (context assembly, trims unfinished tail via xiY) → kh8 (side-question fork, 9638640) → xf (fork kernel, 9258609).
/btw was purpose-built for quick side questions — fast, lightweight, zero disruption. It did exactly what it was designed to do. /forkoff solves a different problem: when you need a full independent session, not just a quick answer.
/btw |
/forkoff |
|
|---|---|---|
| Purpose | quick side question | full independent session |
| Tools | denied (by design — keeps it fast) | full access |
| Turns | 1 | unlimited |
| Persistence | ephemeral (by design — no clutter) | full session |
| Context window | shared with parent | independent |
| Mid-turn | yes (privileged built-in) | yes (tmux keybinding) |
They're complementary. /btw is a post-it note, /forkoff is a second desk.
Things that would make this better if they existed in Claude Code:
-
Plugin-level
immediatecommands — if plugins could registerimmediate: truecommands, the/forkoffhook could trigger mid-turn without interrupting, using the same privileged path/btwused. Currently only built-ins get that. -
Fork context in prompt commands — public prompt commands with
context: "fork"useHEY() → kk()which seeds the child with fresh messages, not the parent transcript. IfHEY()passed throughforkContextMessageslikeuiY()does, we wouldn't need--resume --fork-sessionat all. -
--trim-pendingflag on--fork-session—/btwtrimmed the unfinished assistant tail before forking viaxiY(). Would be nice to have that for external forks too. -
/btwwith tool access — a--toolsflag or configurable profile would cover the gap between "quick disposable question" and "full independent session."
MIT