Skip to content

feat: smart tree truncation and subtree extraction#36

Closed
piotrski wants to merge 9 commits intomainfrom
worktree-agent-af468d5e
Closed

feat: smart tree truncation and subtree extraction#36
piotrski wants to merge 9 commits intomainfrom
worktree-agent-af468d5e

Conversation

@piotrski
Copy link
Copy Markdown
Collaborator

@piotrski piotrski commented Mar 5, 2026

Summary

Closes #20

Smart tree truncation and subtree extraction for the get tree command, making output practical for large React apps (500-2000+ components).

Tree truncation (commits c1d483c..367eb3e)

  • Host filtering by default: <div>, <span>, etc. are hidden (use --all to show). Keyed hosts and custom elements are always shown.
  • Sibling collapsing: Repeated siblings with the same display name collapse after 3 items with ... +N more ComponentName.
  • Summary footer: N components shown (M total) at the end of output.
  • --max-lines N flag: Hard cap on output lines for context budgets.

Subtree extraction (commit 047d198)

  • get tree @c5 shows only the subtree rooted at a specific component.
  • Labels re-assigned starting from @c1 within the subtree.
  • Combines with --depth, --all, and --max-lines flags.
  • Added rootId to GetTreeOptions interface and root to IPC command type.

maxLines response fix (commit ab4d5da)

  • Removed maxLines from IPC response data — it's a formatting concern, not data.
  • The CLI now passes maxLines directly to formatTree from local command flags.

Commits

  • c1d483c feat: smart tree truncation for large component trees
  • 67ac35f test: add tests for tree truncation and host filtering
  • 8f3319d docs: update README with tree truncation flags
  • 367eb3e chore: add changeset for smart tree truncation
  • 047d198 feat: support subtree extraction in get-tree command
  • ab4d5da fix: remove maxLines from IPC response data

Test plan

  • All 87 existing tests pass (vitest run)
  • Type checking passes (tsc --noEmit)
  • Build succeeds (tsup)
  • Manual: get tree on a large app shows truncated output with summary
  • Manual: get tree @c5 shows correct subtree with re-labeled components
  • Manual: get tree --all includes host components
  • Manual: get tree --max-lines 20 caps output

🤖 Generated with Claude Code

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 5, 2026

🦋 Changeset detected

Latest commit: fa2b1c1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-react-devtools Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab4d5da411

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +158 to +160
resolvedRoot = this.tree.resolveId(cmd.root);
if (resolvedRoot === undefined) {
return { ok: false, error: `Component ${cmd.root} not found` };
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep get-tree root lookup consistent for numeric IDs

The new subtree path only rejects missing roots when resolveId returns undefined, but numeric roots never do that (resolveId(999) returns 999 even if absent), so get tree 999 succeeds with an empty tree instead of a not-found error. In practice this turns stale/typoed numeric IDs into the misleading No components (is a React app connected?) output instead of actionable feedback, unlike label-based lookups.

Useful? React with 👍 / 👎.

Comment on lines +144 to +146
if (truncated) {
lines.push(`... output truncated at ${maxLines} lines`);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce max-lines when adding truncation footer

The formatter stops tree traversal at maxLines, but then appends the truncation line unconditionally, so --max-lines N can emit N+1 lines (and with a summary footer, still exceed the hard cap). This breaks the documented line-budget guarantee for large trees and can overflow context budgets in the exact scenario this flag is meant to protect.

Useful? React with 👍 / 👎.

piotrski and others added 9 commits March 18, 2026 01:10
Add three complementary strategies to reduce tree output size:

1. Filter host components by default (--all flag to include them)
   - Host components with keys or custom element names are kept
   - Filtering happens at output level, not internal tree structure

2. Collapse repeated siblings with same display name
   - Shows first 3 items, then "... +N more ComponentName"
   - Detects runs of siblings with identical displayName

3. Summary footer showing component count
   - "N components shown (M total)" when filtered
   - "N components" when showing all

Also adds --max-lines N flag as a hard cap on output lines.

Closes #20

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Test host component filtering with noHost option
- Test custom element and keyed host preservation
- Test child promotion when host nodes are skipped
- Test noHost + maxDepth combination
- Test sibling collapsing (repeated display names)
- Test summary footer with totalCount
- Test maxLines truncation
- Test options object variant for formatTree

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document --all, --max-lines flags and smart tree behavior:
- Host filtering enabled by default
- Sibling collapsing for repeated component names
- Summary footer showing component counts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `get tree @c5` syntax to view only the subtree rooted at a specific
component. Labels are re-assigned starting from @c1 within the subtree.
Combines with --depth, --all, and --max-lines flags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
maxLines is a formatting concern, not data. The daemon now returns only
{ nodes, totalCount } in the get-tree response. The CLI passes maxLines
directly to formatTree from the local command flags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The get-tree response changed from an array to { nodes, totalCount }.
Update E2E tests to destructure the new format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously resolveId always returned numeric IDs without checking if
the node exists, making `get tree 999` return an empty tree instead
of a not-found error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reserve space for both the truncation message and summary footer when
computing the max-lines cutoff, so --max-lines N never emits more
than N lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@piotrski piotrski force-pushed the worktree-agent-af468d5e branch from ab4d5da to fa2b1c1 Compare March 18, 2026 00:13
@piotrski piotrski closed this Mar 18, 2026
@piotrski piotrski deleted the worktree-agent-af468d5e branch March 18, 2026 00:15
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa2b1c1ab8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

for (const childId of node.children) {
walk(childId, depth + 1);
// Check if this host node should be filtered out
const skipThis = noHost && node.type === 'host' && !isSignificantHost(node);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep explicit subtree root from being host-filtered

When get tree <root> is used, the selected root can still be dropped by host filtering because skipThis does not exempt the depth-0 node. With the CLI default (noHost: true), requesting a plain host root (for example one discovered via get tree --all or numeric ID) returns a subtree that starts at a different node or even an empty tree, which breaks the expected semantics of “rooted at this component.”

Useful? React with 👍 / 👎.

Comment on lines +176 to +179
const response: IpcResponse = {
ok: true,
data: { nodes: treeData, totalCount },
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid breaking get-tree IPC clients with response shape change

This switches get-tree IPC responses from a node array to { nodes, totalCount } without a compatibility path, so any direct IPC consumer that still reads resp.data as an array will break immediately. In this repo, packages/e2e-tests/src/browser.test.ts still treats the payload as Array<...>, so the release browser test flow will fail once it runs against this daemon response.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Smart tree truncation for large component trees

1 participant