Fork vs In-Session Branch (Continue) in pi-web: Key Differences Explained
In pi-web, Fork creates a brand-new .jsonl session file with full history independence, while Continue (in-session branch) keeps the same file and only moves the cursor to a different leaf.
The pi-web conversational AI interface offers two distinct ways to branch from an existing conversation. Understanding when to use each can prevent data duplication and unexpected behavior in your agent sessions. This guide breaks down the architectural differences, implementation details, and practical use cases based on the actual source code.
What Fork Does in pi-web
Fork creates a completely independent session file.
When you click the Fork button on any user message, the UI sends a fork command to the server. In lib/rpc-manager.ts (lines 48-84), this command triggers one of two outcomes:
- Empty fork: Creates a fresh session linked to the original (used when forking before any messages)
- History fork: Copies all conversation history up to the selected entry via
createBranchedSession
// lib/rpc-manager.ts – fork command handling (L48-L84)
case "fork": {
const { entryId } = payload;
// Creates new .jsonl file, either empty or with copied history
const newSession = await createBranchedSession(sessionId, entryId);
// Current wrapper shuts down, UI switches to new session
return { sessionId: newSession.id };
}
The original session remains untouched. You get:
- A new file at
~/.pi/agent/sessions/[UUID].jsonl - A
parentSessionheader pointing to the original - Sidebar visualization as a child node under the parent
Use Fork when: you want to preserve the original conversation exactly as-is while exploring a completely different direction with full isolation.
What In-Session Branch (Continue) Does
Continue — also called in-session branch — navigates within the existing file without duplication.
Triggered by the Continue button or BranchNavigator component, this sends a navigate_tree command. The rpc-manager.ts (lines 85-92) forwards this to AgentSession.navigateTree, which updates the leafId pointer:
// lib/rpc-manager.ts – navigate_tree handling (L85-L92)
case "navigate_tree": {
const { targetId } = payload;
// Moves cursor within SAME file; no new file created
await this.inner.navigateTree(targetId);
return { leafId: targetId };
}
Key characteristics:
- The same
.jsonlfile is reused - Only the
leafId(current message pointer) changes - All conversation history remains in one place
- UI updates to show the selected branch as active
Use Continue when: you want to revisit or extend an earlier point in the same conversation without fragmenting your session history across multiple files.
Fork vs In-Session Branch: Side-by-Side Comparison
| Aspect | Fork | In-Session Branch (Continue) |
|---|---|---|
| Command type | fork |
navigate_tree |
| File outcome | New .jsonl created |
Same file reused |
| Storage impact | Duplicates history (up to fork point) | Zero duplication |
| Original session | Unchanged, preserved | Continues from new leaf |
| Sidebar display | Child node under parent | Same session, different branch |
| Implementation | createBranchedSession in rpc-manager.ts |
AgentSession.navigateTree |
UI Implementation Details
The interface wires these differently:
Fork button — components/MessageView.tsx (lines 249-258):
// components/MessageView.tsx – Fork button rendering
<MessageView
entryId={entry.id}
forking={isForking}
onFork={(entryId) => {
// Dispatches fork command to rpc-manager
sendAgentCommand(sessionId, { type: "fork", entryId });
}}
/>
Continue navigation — hooks/useAgentSession.ts (lines 1443-1455):
// hooks/useAgentSession.ts – Branch navigation
const handleNavigate = (leafId: string) => {
sendAgentCommand(sessionId, {
type: "navigate_tree",
targetId: leafId
});
};
Architectural Rationale
The AGENTS.md documentation explicitly warns against confusing these two modes under "Two kinds of branching — don't confuse them":
A fork creates a new independent session file, while an in-session branch (
navigate_tree) rewrites the view within the same file.
This distinction exists because:
- Fork enables true parallel experimentation where branches never interfere
- In-session branch keeps related exploration contained, reducing file sprawl and preserving context
Choose based on whether you need isolation (Fork) or continuity (Continue).
Summary
- Fork generates an independent
.jsonlsession file viacreateBranchedSession— best for divergent experiments requiring full isolation - In-session branch (Continue) updates the
leafIdcursor within the same file vianavigate_tree— best for exploring alternatives without fragmentation - Both commands route through
lib/rpc-manager.tsbut invoke fundamentally different session management paths - The UI surfaces Fork on individual messages and Continue through the branch navigator
Frequently Asked Questions
Can I convert a Continue branch into a Fork later?
No direct conversion exists in the current pi-web implementation. If you need file independence after using Continue, you must manually Fork from your desired point, which will create the new .jsonl file at that moment.
Does Forking preserve the full conversation history?
Partially. When you Fork at a specific message, pi-web copies history up to that entry point into the new file. Messages after the fork point are not included. This is implemented in createBranchedSession called from rpc-manager.ts.
Will in-session branches affect other users or shared sessions?
In-session branches (navigate_tree) only affect your current session view. Since no new file is created, other concurrent access to the same session file would see the same underlying data — though leafId is typically session-specific.
Which branching method should I use for A/B testing prompts?
Use Fork. Creating independent .jsonl files ensures your prompt variants remain cleanly separated with no risk of cross-contamination, and you can compare results across fully isolated session histories.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →