Sessiontree
Session Tree Navigation
The /tree command provides tree-based navigation of the session history.
Overview
Sessions are stored as trees where each entry has an id and parentId. The "leaf" pointer tracks the current position. /tree lets you navigate to any point and optionally summarize the branch you're leaving.
Comparison with `/fork`
| Feature | /fork |
/tree |
|---|---|---|
| View | Flat list of user messages | Full tree structure |
| Action | Extracts path to new session file | Changes leaf in same session |
| Summary | Never | Optional (user prompted) |
| Events | session_before_fork / session_fork |
session_before_tree / session_tree |
Tree UI
├─ user: "Hello, can you help..."
│ └─ assistant: "Of course! I can..."
│ ├─ user: "Let's try approach A..."
│ │ └─ assistant: "For approach A..."
│ │ └─ [compaction: 12k tokens]
│ │ └─ user: "That worked..." ← active
│ └─ user: "Actually, approach B..."
│ └─ assistant: "For approach B..."
Controls
| Key | Action |
|---|---|
| ↑/↓ | Navigate (depth-first order) |
| Enter | Select node |
| Escape/Ctrl+C | Cancel |
| Ctrl+U | Toggle: user messages only |
| Ctrl+O | Toggle: show all (including custom/label entries) |
Display
- Height: half terminal height
- Current leaf marked with
← active - Labels shown inline:
[label-name] - Default filter hides
labelandcustomentries (shown in Ctrl+O mode) - Children sorted by timestamp (oldest first)
Selection Behavior
User Message or Custom Message
- Leaf set to parent of selected node (or
nullif root) - Message text placed in editor for re-submission
- User edits and submits, creating a new branch
Non-User Message (assistant, compaction, etc.)
- Leaf set to selected node
- Editor stays empty
- User continues from that point
Selecting Root User Message
If user selects the very first message (has no parent):
- Leaf reset to
null(empty conversation) - Message text placed in editor
- User effectively restarts from scratch
Branch Summarization
When switching branches, user is presented with three options:
- No summary - Switch immediately without summarizing
- Summarize - Generate a summary using the default prompt
- Summarize with custom prompt - Opens an editor to enter additional focus instructions that are appended to the default summarization prompt
What Gets Summarized
Path from old leaf back to common ancestor with target:
A → B → C → D → E → F ← old leaf
↘ G → H ← target
Abandoned path: D → E → F (summarized)
Summarization stops at:
- Common ancestor (always)
- Compaction node (if encountered first)
Summary Storage
Stored as BranchSummaryEntry:
interface BranchSummaryEntry {
type: "branch_summary";
id: string;
parentId: string; // New leaf position
timestamp: string;
fromId: string; // Old leaf we abandoned
summary: string; // LLM-generated summary
details?: unknown; // Optional hook data
}
Implementation
AgentSession.navigateTree()
async navigateTree(
targetId: string,
options?: {
summarize?: boolean;
customInstructions?: string;
replaceInstructions?: boolean;
label?: string;
}
): Promise<{ editorText?: string; cancelled: boolean }>
Options:
summarize: Whether to generate a summary of the abandoned branchcustomInstructions: Custom instructions for the summarizerreplaceInstructions: If true,customInstructionsreplaces the default prompt instead of being appendedlabel: Label to attach to the branch summary entry (or target entry if not summarizing)
Flow:
- Validate target, check no-op (target === current leaf)
- Find common ancestor between old leaf and target
- Collect entries to summarize (if requested)
- Fire
session_before_treeevent (hook can cancel or provide summary) - Run default summarizer if needed
- Switch leaf via
branch()orbranchWithSummary() - Update agent:
agent.replaceMessages(sessionManager.buildSessionContext().messages) - Fire
session_treeevent - Notify custom tools via session event
- Return result with
editorTextif user message was selected
SessionManager
getLeafUuid(): string | null- Current leaf (null if empty)resetLeaf(): void- Set leaf to null (for root user message navigation)getTree(): SessionTreeNode[]- Full tree with children sorted by timestampbranch(id)- Change leaf pointerbranchWithSummary(id, summary)- Change leaf and create summary entry
InteractiveMode
/tree command shows TreeSelectorComponent, then:
- Prompt for summarization
- Call
session.navigateTree() - Clear and re-render chat
- Set editor text if applicable
Hook Events
`session_before_tree`
interface TreePreparation {
targetId: string;
oldLeafId: string | null;
commonAncestorId: string | null;
entriesToSummarize: SessionEntry[];
userWantsSummary: boolean;
customInstructions?: string;
replaceInstructions?: boolean;
label?: string;
}
interface SessionBeforeTreeEvent {
type: "session_before_tree";
preparation: TreePreparation;
signal: AbortSignal;
}
interface SessionBeforeTreeResult {
cancel?: boolean;
summary?: { summary: string; details?: unknown };
customInstructions?: string; // Override custom instructions
replaceInstructions?: boolean; // Override replace mode
label?: string; // Override label
}
Extensions can override customInstructions, replaceInstructions, and label by returning them from the session_before_tree handler.
`session_tree`
interface SessionTreeEvent {
type: "session_tree";
newLeafId: string | null;
oldLeafId: string | null;
summaryEntry?: BranchSummaryEntry;
fromHook?: boolean;
}
Example: Custom Summarizer
export default function(indusagi: HookAPI) {
indusagi.on("session_before_tree", async (event, ctx) => {
if (!event.preparation.userWantsSummary) return;
if (event.preparation.entriesToSummarize.length === 0) return;
const summary = await myCustomSummarizer(event.preparation.entriesToSummarize);
return { summary: { summary, details: { custom: true } } };
});
}
Error Handling
- Summarization failure: cancels navigation, shows error
- User abort (Escape): cancels navigation
- Hook returns
cancel: true: cancels navigation silently
On This Page
OverviewComparison with `/fork`Tree UIControlsDisplaySelection BehaviorUser Message or Custom MessageNon-User Message (assistant, compaction, etc.)Selecting Root User MessageBranch SummarizationWhat Gets SummarizedSummary StorageImplementationAgentSession.navigateTree()SessionManagerInteractiveModeHook Events`session_before_tree``session_tree`Example: Custom SummarizerError Handling
