feat: smart tree truncation and subtree extraction#36
Conversation
🦋 Changeset detectedLatest commit: fa2b1c1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
There was a problem hiding this comment.
💡 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".
| resolvedRoot = this.tree.resolveId(cmd.root); | ||
| if (resolvedRoot === undefined) { | ||
| return { ok: false, error: `Component ${cmd.root} not found` }; |
There was a problem hiding this comment.
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 👍 / 👎.
| if (truncated) { | ||
| lines.push(`... output truncated at ${maxLines} lines`); | ||
| } |
There was a problem hiding this comment.
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 👍 / 👎.
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>
ab4d5da to
fa2b1c1
Compare
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 👍 / 👎.
| const response: IpcResponse = { | ||
| ok: true, | ||
| data: { nodes: treeData, totalCount }, | ||
| }; |
There was a problem hiding this comment.
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 👍 / 👎.
Summary
Closes #20
Smart tree truncation and subtree extraction for the
get treecommand, making output practical for large React apps (500-2000+ components).Tree truncation (commits c1d483c..367eb3e)
<div>,<span>, etc. are hidden (use--allto show). Keyed hosts and custom elements are always shown.... +N more ComponentName.N components shown (M total)at the end of output.--max-lines Nflag: Hard cap on output lines for context budgets.Subtree extraction (commit 047d198)
get tree @c5shows only the subtree rooted at a specific component.@c1within the subtree.--depth,--all, and--max-linesflags.rootIdtoGetTreeOptionsinterface androotto IPC command type.maxLines response fix (commit ab4d5da)
maxLinesfrom IPC response data — it's a formatting concern, not data.maxLinesdirectly toformatTreefrom local command flags.Commits
c1d483cfeat: smart tree truncation for large component trees67ac35ftest: add tests for tree truncation and host filtering8f3319ddocs: update README with tree truncation flags367eb3echore: add changeset for smart tree truncation047d198feat: support subtree extraction in get-tree commandab4d5dafix: remove maxLines from IPC response dataTest plan
vitest run)tsc --noEmit)tsup)get treeon a large app shows truncated output with summaryget tree @c5shows correct subtree with re-labeled componentsget tree --allincludes host componentsget tree --max-lines 20caps output🤖 Generated with Claude Code