Skip to content

Comments

Implement a trace CLI - alloy-trace#368

Merged
bterlson merged 24 commits intoalloy-framework:mainfrom
bterlson:feat/trace-cli
Feb 18, 2026
Merged

Implement a trace CLI - alloy-trace#368
bterlson merged 24 commits intoalloy-framework:mainfrom
bterlson:feat/trace-cli

Conversation

@bterlson
Copy link
Contributor

This PR implements a CLI tool to help explore a trace file. Its primary purpose is to enable LLMs to help diagnose what went wrong when something fails. It exposes most of the information found in the devtools UI.

…ysis

New CLI tool for querying Alloy debug trace SQLite databases. Provides
commands for inspecting effects, refs, components, symbols, scopes,
output files, and aggregate statistics.

Commands:
  effect <list|show|chain|hotspots|ancestry|subtree>
  ref <list|show|chain|hotspots|fanout|ownership>
  component <list|show|tree|stats>
  symbol <list|show>
  scope <list|show>
  file <list|show>
  stats
  errors
  query <sql>

Features:
- Filter by source file, output file, component, name, type
- JSON output mode for scripting
- Pagination with --limit
- Reactive chain analysis (effect→ref→effect chains)
- Hotspot detection (most active effects/refs)
- Component tree visualization
- Per-component overhead statistics
- Raw SQL query support

Includes input validation, cycle detection in ref chains, and
graceful error handling for missing database files.
103 tests across 5 test files covering:
- component list/show/tree/stats with filters, json, limits
- effect list/show/chain/hotspots/ancestry/subtree
- ref list/show/chain/hotspots/fanout/ownership with cycle detection
- stats, errors, file, query, symbol, scope commands
- utility functions: requireId, shortPath, CTE helpers, pagination
- Add comprehensive README with usage, examples, and schema docs
- Add files field to limit published package to dist/
- Add engines constraint (node >= 22.5.0 for node:sqlite)
Add shared formatComponentStack() in types.ts that renders entries as:
    at ComponentName (file.tsx:10:5)
Uses shortPath to trim /packages/ prefix. Used by errors command.
Both now use shared formatComponentStack() which renders as:
    at ComponentName (short/path.tsx:line:col)
file search now searches the full output file content instead of
individual text node values. This finds text that spans multiple
render tree nodes (e.g. 'interface Foo' where 'interface' and 'Foo'
are separate text nodes). Maps matches back to text nodes by
token-based lookup and shows component stack from the most specific
matching node.
Match full search string first, then fall back to longest token.
Avoids flooding output with every node matching common words like
'interface'.
Search file content for the exact search string. Find the deepest
text node containing the search text (or its longest word as
fallback). Show only the component stack, no noisy text node lists.
Rewrote file search to use the same approach as the devtools: collect
text nodes in DFS tree order (not seq order), diff against file content
with diff-match-patch, and map file offsets back to text nodes through
equal segments. This fixes two bugs:

1. Cross-node text search (e.g. 'interface ChatMessageAudioUrl') now
   correctly maps to the declaration's text node, not a reference.

2. All matches now show component stacks, including type references
   that were previously unmapped due to seq vs output order mismatch.

Added diff-match-patch as a dependency and two new tests for DFS
ordering and ambiguous text node resolution.
- formatComponentStack now shows render node IDs (e.g. 'at Declaration alloy-framework#42')
- File search: removed 'Found N matches' header, 'Match N:' labels, and
  indentation. Shows 3 lines of context with blank line separator.
- Updated seed data and tests to include renderNodeId in component stacks.
- Added test for 3-line context and renderNodeId formatting.
Stack traces now hide library/framework frames by default, matching the
devtools filtering approach: frames are external if they have no source
location or their source is inside node_modules.

- Added --all-frames flag to show all stack frames
- When frames are hidden, shows hint: '... N framework frames hidden
  (use --all-frames to show)'
- shortPath now converts absolute paths to relative paths from cwd
  instead of stripping /packages/ prefix
- Updated isExternalFrame to use /node_modules/ check (matches devtools)
- Stack traces now use bold for component names, dim for node IDs,
  and cyan for file locations
- Sourceless frames are no longer hidden by default (fixes missing
  ModelDeclaration and other user components without source annotations)
- Only frames with source paths containing /node_modules/ are hidden
- Strip ANSI codes in test capture helper for clean assertions
…on re-render

- Babel plugin emits import.meta.url instead of hardcoded absolute paths
  so component source locations resolve to the installed location at runtime
- Source maps resolve .js paths back to original .tsx sources when
  --enable-source-maps is active
- Extract shared source-map utilities into debug/source-map.ts, used by
  both effect source capture and component source resolution
- Fix source info loss on For/memo re-render: nodeKinds now stores source
  alongside kind/name, and recordSubtreeAdded/recordCachedSubtreeChildren
  preserve it on INSERT OR REPLACE
@github-actions
Copy link
Contributor

github-actions bot commented Feb 18, 2026

All changed packages have been documented.

  • @alloy-js/babel-plugin-jsx-dom-expressions
  • @alloy-js/cli
  • @alloy-js/core
  • @alloy-js/create
  • @alloy-js/csharp
  • @alloy-js/go
  • @alloy-js/java
  • @alloy-js/json
  • @alloy-js/markdown
  • @alloy-js/msbuild
  • @alloy-js/python
  • @alloy-js/trace-cli
  • @alloy-js/typescript
Show changes

@alloy-js/cli - feature ✏️

Add --with-dev flag to produce both production (dist/) and development (dist/dev/) builds. Dev builds include source info from babel transforms for improved debugging. --dev produces only a dev build to dist/, and --watch now defaults to dev mode. Package exports use "development" condition so consumers can opt into dev builds via node --conditions=development.

@alloy-js/core - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/create - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/csharp - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/go - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/java - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/json - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/markdown - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/msbuild - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/python - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/typescript - feature ✏️

Ship dev sources in package for debugging. Use node's --condition="development" flag to use this build.

@alloy-js/babel-plugin-jsx-dom-expressions - feature ✏️

Pass import.meta.url to createComponent for dev builds.

@alloy-js/trace-cli - feature ✏️

Add @alloy-js/trace-cli for querying Alloy trace databases from the command line, enabling LLMs and developers to explore render trees, component stacks, effects, and output files to understand what happened during a render.

@bterlson bterlson merged commit b3c9982 into alloy-framework:main Feb 18, 2026
8 checks passed
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.

1 participant