feat: smart tree truncation and subtree extraction#45
Conversation
🦋 Changeset detectedLatest commit: 753a0bf 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: 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".
fa2b1c1 to
d36e4bc
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d36e4bc5db
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1468ea65fc
ℹ️ 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".
| if (truncated) { | ||
| // Replace last tree line with truncation notice to stay within budget | ||
| lines[lines.length - 1] = `... output truncated at ${maxLines} lines`; |
There was a problem hiding this comment.
Guard truncation replacement when no lines were emitted
The truncation path assumes at least one rendered tree line and overwrites lines[lines.length - 1], but lineLimit can be 0 (or negative) when maxLines is very small and a footer is reserved. In that case no tree line is ever pushed, so this write targets index -1 and the truncation notice disappears; e.g. --max-lines 1 currently prints only the summary footer and misrepresents that output was truncated.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed (same fix as the other formatters.ts comment — combined truncation+footer line resolves both issues at once).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aea5467abe
ℹ️ 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".
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>
Replace O(n²) nodes.find() with O(1) nodeMap.get() by building a Map<number, TreeNode> alongside the existing childrenMap. Also remove dead isLastChild variable in collapsed-sibling path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Hoist label assignment before the skip/emit branch in getTree walk - Precompute lineLimit once instead of recalculating reserve on every addLine call Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Only reserve truncation line when tree actually exceeds max-lines, replacing the last tree line instead of always reserving space - Return not-found error for stale subtree roots (labels that resolve but point to removed nodes) - Emit filtered children IDs when noHost skips host components, so children arrays stay consistent with parentId references Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Never skip the explicitly requested rootId even when noHost filtering is active, so `get tree @c5` works for host components - Guard against index -1 when truncation fires with zero lines emitted (e.g. --max-lines 1 with summary footer) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When --max-lines is set and the tree is truncated, the truncation notice now uses the pre-reserved footer slot (combined line) instead of replacing the last content line. This shows one additional component line within the same budget. Also fixes the --max-lines 1 edge case where the footer was emitted after the truncation notice, producing 2 lines instead of 1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
aea5467 to
753a0bf
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 753a0bf836
ℹ️ 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".
| const noHost = flags['all'] !== true; | ||
| // Parse optional root: `get tree @c5` or `get tree 5` | ||
| const rawRoot = command[2]; |
There was a problem hiding this comment.
Parse
--all as a boolean before consuming tree root
With the new optional subtree argument, get tree --all @c5 is parsed incorrectly: the generic arg parser stores flags.all = "@c5", so this branch treats --all as unset (noHost stays true) and rawRoot becomes undefined. That silently drops the requested subtree root and still filters host nodes, which makes a common flag ordering produce the wrong tree without any error.
Useful? React with 👍 / 👎.
PR #45 changed the get-tree IPC response from a flat array to { nodes, totalCount }, but browser.test.ts was not updated to match, causing the release workflow to fail on every push to main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
<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
get tree @c5shows only the subtree rooted at a specific component.@c1within the subtree.--depth,--all, and--max-linesflags.Fixes on top of original implementation
resolveId(stale/typo'd IDs now return not-found)--max-linesbudget including truncation and summary footer lines{ nodes, totalCount }response shapeTest plan
get treeon a large app shows truncated output with summaryget tree @c5shows correct subtreeget tree --allincludes host componentsget tree --max-lines 20caps outputSupersedes #36
🤖 Generated with Claude Code