What Is `navigate_tree` for In-Session Branches in Pi Web?

The navigate_tree command switches the active in-session branch by updating the server-side leaf pointer without rewriting the session file, enabling read-only navigation within the existing conversation tree.

The navigate_tree command is a core mechanism in the agegr/pi-web repository that controls how users move between different conversation branches during an active AgentSession. When you interact with the Branch Navigator or click Continue in the UI, this command tells the server exactly which entry in the current session file should be displayed.

How navigate_tree Controls In-Session Navigation

According to the architecture documented in AGENTS.md, in-session branches (or tree branches) represent different paths within a single .jsonl session file. The navigate_tree command serves as the internal signaling mechanism that changes which branch is currently active in the UI.

Unlike a fork operation, which creates an entirely new session file, navigate_tree performs a read-only operation. It simply moves the cursor to a different leaf node while preserving the original parent/child relationships stored on disk. This distinction is critical for understanding the session lifecycle: navigation explores existing history, while forking creates new persistent branches.

Client-Side Implementation: Dispatching the Command

On the client, the navigate_tree command is dispatched through the hook responsible for agent session communication. When a user selects a leaf in the Branch Navigator, the UI captures the target entry ID and sends it to the server.

// hooks/useAgentSession.ts – triggering branch navigation
const leafId = entryId; // ID of the target message entry

sendAgentCommand(sessionId, { 
  type: "navigate_tree", 
  targetId: leafId 
})
  .catch(() => {});

This sendAgentCommand function transmits the command object to the server-side RPC manager, initiating the branch switch.

Server-Side Handling in lib/rpc-manager.ts

The server receives the command in lib/rpc-manager.ts, where a command dispatcher handles the navigate_tree case. The implementation extracts the targetId, updates the session's current leaf pointer, and returns the refreshed state to the client.

// lib/rpc-manager.ts – command dispatch logic
case "navigate_tree": {
  const { targetId } = cmd;
  
  // Update the AgentSession’s current leaf to the requested entry
  session.setCurrentLeaf(targetId);
  
  // Return the updated session state to the client
  return { 
    type: "session_state", 
    state: session.getState() 
  };
}

The session.setCurrentLeaf() method performs the actual pointer update. Because this only modifies the in-memory session state and not the underlying .jsonl file, the operation is lightweight and immediate.

It is essential to distinguish navigate_tree from session forking:

  • navigate_tree: Changes the active view within the same session file. No new files are created; the operation only affects which messages are rendered in the UI.
  • Forking: Creates a new .jsonl file with its own session ID, generating a distinct conversation branch that persists independently of the original session.

As implemented in agegr/pi-web, navigate_tree keeps you within the original conversation tree, allowing you to explore alternative response paths that already exist, while forking is used to spawn new, divergent conversation lines.

Summary

  • navigate_tree is the internal command that switches the active in-session branch without persisting changes to disk.
  • The server-side implementation in lib/rpc-manager.ts uses session.setCurrentLeaf(targetId) to update the current pointer.
  • Client-side code in hooks/useAgentSession.ts dispatches the command via sendAgentCommand() when users interact with the Branch Navigator.
  • This mechanism is read-only and distinct from forking, which creates new .jsonl session files.
  • The command enables efficient exploration of existing conversation trees by updating only the in-memory view state.

Frequently Asked Questions

What happens to the session file when navigate_tree is called?

Nothing is written to disk. The navigate_tree command only updates the in-memory pointer via session.setCurrentLeaf(), making it a read-only operation that affects only what is displayed in the UI.

How does navigate_tree differ from creating a new branch?

navigate_tree navigates existing branches within the current .jsonl file, while forking creates a brand new session file with a unique ID. Navigation preserves the original session history; forking spawns an independent conversation line.

Where is the navigate_tree command handled on the server?

The command is handled in lib/rpc-manager.ts within the command dispatcher switch statement. This file receives the targetId, updates the AgentSession state, and returns the updated session object to the client.

Can navigate_tree create new conversation branches?

No, navigate_tree cannot create new branches. It only allows navigation to existing leaf nodes that are already present in the session tree. Creating new branches requires different commands that modify the session structure or initiate a fork operation.

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 →