Session Fork vs In-Session Branch Navigation in Pi Web: Key Differences Explained

Session fork creates a new .jsonl file that diverges from a specific entry while preserving the original session unchanged, whereas in-session branch navigation switches between logical branches within the same file using the navigate_tree command.

Pi Web (agegr/pi-web) provides two distinct mechanisms for managing conversation history divergence. Understanding the difference between session fork and in-session branch navigation is essential for building applications that handle complex conversational workflows or require isolated experimental paths.

What Is Session Fork in Pi Web?

According to AGENTS.md, a session fork creates a brand-new .jsonl file starting from a selected entry. This operation generates a unique session ID and writes a separate file to disk, leaving the original session file completely untouched. The forked session maintains a reference to its parent through the parentSession header, causing it to appear as a child node in the sidebar.

The RPC handler in [lib/rpc-manager.ts](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts#L393) processes the "fork" command by serializing the conversation history up to the specified entry into a new physical file.

// Create a new independent session from entry "abc123"
await sendAgentCommand(sessionId, {
  type: "fork",
  entryId: "abc123"
});

What Is In-Session Branch Navigation?

In-session branch navigation, documented in AGENTS.md, allows users to switch between multiple conversation branches while remaining within the same .jsonl file. Unlike forking, this operation does not create new files; instead, it updates the active pointer to reference a different leaf in the conversation tree by calling navigate_tree.

The implementation in [lib/rpc-manager.ts](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts#L430) handles the "navigate_tree" command to update the session's active branch context without file system duplication.

// Switch to branch leaf "leaf456" within the current session file
await sendAgentCommand(sessionId, {
  type: "navigate_tree",
  targetId: "leaf456"
});

Key Differences Between Fork and Branch Navigation

  • File Persistence: Session fork creates a separate <timestamp>_<uuid>.jsonl file on disk, while in-session branch navigation only modifies the existing file's internal tree structure.
  • Sidebar Representation: Forked sessions appear as distinct child nodes under the original session due to the parentSession header relationship. In-session branches maintain a single sidebar entry regardless of how many branches exist.
  • API Parameters: Forking requires the "fork" command with an entryId parameter, whereas navigation uses "navigate_tree" with a targetId parameter, both sent to the Agent RPC endpoint (/api/agent/[id]).
  • Deletion Scope: Deleting a forked session removes only the new .jsonl file, preserving the original. Deleting a session with branches removes all branches since they share the same underlying file.

Implementation Details

RPC Command Handling

The core logic resides in lib/rpc-manager.ts. The fork command handler (around line 393) instantiates a new session file containing the truncated history. The navigation handler (around line 430) updates the session state to point to a different leaf node without file system operations.

Frontend Integration

In [hooks/useAgentSession.ts](https://github.com/agegr/pi-web/blob/main/hooks/useAgentSession.ts), the application wraps these RPC calls for UI consumption. The fork operation typically sets a transient loading state before invoking the command, while the BranchNavigator component provides the interface for selecting alternate branches.

// hooks/useAgentSession.ts - fork handler pattern
const forkFromEntry = async (entryId: string) => {
  setForkingEntryId(entryId);
  await sendAgentCommand(sessionId, { 
    type: "fork", 
    entryId 
  });
};

// Branch navigation handler
const navigateToBranch = async (leafId: string) => {
  await sendAgentCommand(sessionId, { 
    type: "navigate_tree", 
    targetId: leafId 
  });
};

Summary

  • Session fork creates a new .jsonl file with a unique ID, preserving the original session while establishing a parent-child relationship visible in the sidebar.
  • In-session branch navigation switches between logical branches within the same file using the navigate_tree command, maintaining a single session entry in the UI.
  • Forking is handled in lib/rpc-manager.ts via the "fork" command (line 393), while navigation uses "navigate_tree" (line 430).
  • Use forking for permanent divergence that requires independent file management, and use branch navigation for temporary explorations within the same conversation context.

Frequently Asked Questions

When should I use a session fork instead of branch navigation?

Use a session fork when you need to create a permanent, independent copy of the conversation that can be deleted, renamed, or shared separately without affecting the original session. Use in-session branch navigation for temporary "what-if" scenarios or alternative response paths that should remain grouped under the same session file and sidebar entry.

Does forking a session affect the original conversation history?

No. According to the AGENTS.md specification, forking creates a completely new .jsonl file while leaving the original session file and its entire history intact. The original session continues to exist unchanged, and the forked version references it only through the parentSession metadata header.

How do I programmatically navigate between branches in Pi Web?

Invoke the sendAgentCommand function with type: "navigate_tree" and provide the targetId parameter specifying the leaf entry ID of the desired branch. This command is processed by the RPC manager in lib/rpc-manager.ts around line 430 to update the active branch context without creating new files or modifying session metadata beyond the active pointer.

Where are forked sessions stored compared to branched sessions?

Forked sessions are stored as separate .jsonl files in the sessions directory with unique timestamps and UUIDs, each containing a parentSession header linking back to the source. Branched sessions exist as multiple logical paths within a single .jsonl file, meaning all branches share the same physical storage location, session ID, and metadata.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →