/tree Command Reference
/tree opens the interactive Session Tree navigator. It lets you jump to any entry in the current session file and continue from that point.
This is an in-file leaf move, not a new session export.
What /tree does
- Builds a tree from current session entries (
SessionManager.getTree()) - Opens
TreeSelectorComponentwith keyboard navigation, filters, and search - On selection, calls
AgentSession.navigateTree(targetId, { summarize, customInstructions }) - Rebuilds visible chat from the new leaf path
- Optionally prefills editor text when selecting a user/custom message
Primary implementation:
src/modes/controllers/input-controller.ts(/tree, keybinding wiring, double-escape behavior)src/modes/controllers/selector-controller.ts(tree UI launch + summary prompt flow)src/modes/components/tree-selector.ts(navigation, filters, search, labels, rendering)src/session/agent-session.ts(navigateTreeleaf switching + optional summary)src/session/session-manager.ts(getTree,branch,branchWithSummary,resetLeaf, label persistence)
How to open it
Any of the following opens the same selector:
/tree- configured keybinding action
tree - double-escape on empty editor when
doubleEscapeAction = "tree"(default) /branchwhendoubleEscapeAction = "tree"(routes to tree selector instead of user-only branch picker)
Tree UI model
The tree is rendered from session entry parent pointers (id / parentId).
- Children are sorted by timestamp ascending (older first, newer lower)
- Active branch (path from root to current leaf) is marked with a bullet
- Labels (if present) render as
[label]before node text - If multiple roots exist (orphaned/broken parent chains), they are shown under a virtual branching root
Example tree view (active path marked with •):
├─ user: "Start task"
│ └─ assistant: "Plan"
│ ├─ • user: "Try approach A"
│ │ └─ • assistant: "A result"
│ │ └─ • [milestone] user: "Continue A"
│ └─ user: "Try approach B"
│ └─ assistant: "B result"The selector recenters around current selection and shows up to:
max(5, floor(terminalHeight / 2))rows
Keybindings inside tree selector
Up/Down: move selection (wraps)Left/Right: page up / page downEnter: select nodeEsc: clear search if active; otherwise close selectorCtrl+C: close selectorType: append to search queryBackspace: delete search characterShift+L: edit/clear label on selected entryCtrl+O: cycle filter forwardShift+Ctrl+O: cycle filter backwardAlt+D/T/U/L/A: jump directly to specific filter mode
Filters and search semantics
Filter modes (TreeList):
defaultno-toolsuser-onlylabeled-onlyall
default
Shows most conversational nodes, but hides bookkeeping entry types:
labelcustommodel_changethinking_level_change
no-tools
Same as default, plus hides toolResult messages.
user-only
Only message entries where role is user.
labeled-only
Only entries that currently resolve to a label.
all
Everything in the session tree, including bookkeeping/custom entries.
Tool-only assistant node behavior
Assistant messages that contain only tool calls (no text) are hidden by default in all filtered views unless:
- message is error/aborted (
stopReasonnotstop/toolUse), or - it is the current leaf (always kept visible)
Search behavior
- Query is tokenized by spaces
- Matching is case-insensitive
- All tokens must match (AND semantics)
- Searchable text includes label, role, and type-specific content (message text, branch summary text, custom type, tool command snippets, etc.)
Selection outcomes (important)
navigateTree computes new leaf behavior from selected entry type:
Selecting user message
- New leaf becomes selected entry’s
parentId - If parent is
null(root user message), leaf resets to root (resetLeaf()) - Selected message text is copied to editor for editing/resubmit
Selecting custom_message
- Same leaf rule as user messages (
parentId) - Text content is extracted and copied to editor
Selecting non-user node (assistant/tool/summary/compaction/custom bookkeeping/etc.)
- New leaf becomes selected node id
- Editor is not prefilled
Selecting current leaf
- No-op; selector closes with “Already at this point”
Selection decision (simplified):
selected node
│
├─ is current leaf? ── yes ──> close selector (no-op)
│
├─ is user/custom_message? ── yes ──> leaf := parentId (or resetLeaf for root)
│ + prefill editor text
│
└─ otherwise ──> leaf := selected node id
+ no editor prefillSummary-on-switch flow
Summary prompt is controlled by branchSummary.enabled (default: false).
When enabled, after picking a node the UI asks:
No summarySummarizeSummarize with custom prompt
Flow details:
- Escape in summary prompt reopens tree selector
- Custom prompt cancellation returns to summary choice loop
- During summarization, UI shows loader and binds
EsctoabortBranchSummary() - If summarization aborts, tree selector reopens and no move is applied
navigateTree internals:
- Collects abandoned-branch entries from old leaf to common ancestor
- Emits
session_before_tree(extensions can cancel or inject summary) - Uses default summarizer only if requested and needed
- Applies move with:
branchWithSummary(...)when summary existsbranch(newLeafId)for non-root move without summaryresetLeaf()for root move without summary
- Replaces agent conversation with rebuilt session context
- Emits
session_tree
Note: if user requests summary but there is nothing to summarize, navigation proceeds without creating a summary entry.
Labels
Label edits in tree UI call appendLabelChange(targetId, label).
- non-empty label sets/updates resolved label
- empty label clears it
- labels are stored as append-only
labelentries - tree nodes display resolved label state, not raw label-entry history
/tree vs adjacent operations
| Operation | Scope | Result |
|---|---|---|
/tree | Current session file | Moves leaf to selected point (same file) |
/branch | Usually current session file -> new session file | By default branches from selected user message into a new session file; if doubleEscapeAction = "tree", /branch opens tree navigation UI instead |
/fork | Whole current session | Duplicates session into a new persisted session file |
/resume | Session list | Switches to another session file |
Key distinction: /tree is a navigation/repositioning tool inside one session file. /branch, /fork, and /resume all change session-file context.
Operator workflows
Re-run from an earlier user prompt without losing current branch
/tree- search/select earlier user message
- choose
No summary(or summarize if needed) - edit prefilled text in editor
- submit
Effect: new branch grows from selected point within same session file.
Leave current branch with context breadcrumb
- enable
branchSummary.enabled /treeand select target node- choose
Summarize(or custom prompt)
Effect: a branch_summary entry is appended at the target position before continuing.
Investigate hidden bookkeeping entries
/tree- press
Alt+A(all) - search for
model,thinking,custom, or labels
Effect: inspect full internal timeline, not just conversational nodes.
Bookmark pivot points for later jumps
/tree- move to entry
Shift+Land set label- later use
Alt+L(labeled-only) to jump quickly
Effect: fast navigation among durable branch landmarks.