Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/test-cli-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
paths:
- 'npm_modules/cli/src/**'
- 'npm_modules/cli/test/**'
- 'npm_modules/cli/debugger/**'
- 'npm_modules/cli/package.json'
- '.github/workflows/test-cli-linux.yml'
push:
Expand All @@ -13,6 +14,7 @@ on:
paths:
- 'npm_modules/cli/src/**'
- 'npm_modules/cli/test/**'
- 'npm_modules/cli/debugger/**'
- 'npm_modules/cli/package.json'
- '.github/workflows/test-cli-linux.yml'
workflow_dispatch:
Expand Down
15 changes: 15 additions & 0 deletions docs/docs/command-line-references.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Commands:
valdi export <platform> Build and export a Valdi library
valdi hotreload [--module module_name] [--target Starts the hotreloader for the application
target_name]
valdi debugger Starts the Valdi debugger web interface
valdi test [--module module_name] [--target target_name] Runs tests for given module(s) or target(s). Runs all
tests if no module or target is specified.
valdi lint <command> Checks and formats the code
Expand Down Expand Up @@ -151,6 +152,20 @@ Starts the Valdi [hotreloader](./start-about.md#prototype-quickly-with-hot-reloa
- The `--target` option should be a valid Bazel target (ex: `//:hello_world_hotreload`).
- The `--module` option will query and run targets in the current workspace which match the module_name.<br></br>

`valdi debugger [--host host] [--port port] [--strict-port] [--json]`\
Starts a local browser-based Valdi debugger web interface. The debugger attaches
to running Valdi daemon targets and exposes live view hierarchy, preview,
inspector data, element snapshots, heap dumps, and runtime logs. CPU profiling
uses a separate Hermes debugger connection.

- The default host is `127.0.0.1`; the debugger rejects non-loopback bind
addresses because snapshots can contain application data.
- The preferred port is `8765`; if it is busy, the command selects the next
available port so multiple local debugger sessions can run at once.
- Use `--strict-port` to fail instead of auto-selecting another port.
- Use `--json` to print one machine-readable startup object with the selected
`url`, `port`, `requestedPort`, and `portWasAutoSelected` fields.<br></br>

`valdi test [--module module_name] [--target target_name]`\
Executes the test(s) for the provided targets. Note that multiple modules OR targets can be provided to execute all tests simultaneously. If no modules or targets are provided, ALL tests within the current workspace will be ran.<br></br>

Expand Down
8 changes: 7 additions & 1 deletion docs/docs/workflow-inspector.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ Valdi Inspector is a desktop application, written in Valdi itself, which can be
```
valdi hotreload
```
* To launch the browser-based debugger:
```
valdi debugger
```
Open the printed `VALDI_DEBUGGER_URL` to inspect running Valdi targets. The
command auto-selects a free local port when `8765` is already in use, and
`--json` prints startup details for automation.
* To just launch the inspector:
```
./scripts/start_inspector.sh
Expand Down Expand Up @@ -63,4 +70,3 @@ The hot reloader establishes a TCP connection between the device/simulator and t




8 changes: 8 additions & 0 deletions npm_modules/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ For complete documentation, see:
- Enables instant hot reload during development
- Watches for file changes and updates app in milliseconds

**`valdi debugger`** - Local debugger web interface
- Starts the browser-based Valdi debugger at `127.0.0.1`
- Uses live daemon data from running Valdi targets for view hierarchy, preview, inspector state, snapshots, heap, and runtime logs
- Captures CPU profiles through a separate Hermes debugger connection
- Restricts the server to loopback addresses because debugger snapshots can contain application data
- Prefers port `8765` and automatically selects the next available port so multiple local sessions can run at once
- Supports `--json` for automation-friendly startup output

**`valdi skills`** - AI assistant skills
- Installs Valdi context files into Claude Code, Cursor, or GitHub Copilot so AI tools generate correct Valdi code instead of React patterns
- `valdi skills install` — auto-detects installed AI tools and installs all skills
Expand Down
121 changes: 121 additions & 0 deletions npm_modules/cli/debugger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Valdi Debugger Frontend

This directory is the packaged browser UI served by `valdi debugger`.
It is intentionally local-only, dependency-free, and small enough to ship with
the CLI package.

## File Map

- `index.html`: static shell and DOM anchors for the debugger UI.
- `debugger.css`: themes, layout, controls, preview, inspector, and responsive styles.
- `debugger-state.js`: shared state, DOM references, constants, and action parameter helpers.
- `debugger-api.js`: fetch helpers, action stream, and development reload stream.
- `debugger-model.js`: snapshot normalization, tree traversal, bounds, issues, and selection helpers.
- `debugger-preview-html.js`: inert HTML projection of the hot-reloaded snapshot tree.
- `debugger-render.js`: header, target list, tree, preview overlay, inspector, and export rendering.
- `debugger-runtime.js`: target discovery, snapshots, runtime log streaming, heap, and copy/export helpers.
- `debugger-performance.js`: Hermes CPU profile controls.
- `debugger-actions.js`: UI actions, command prompt handling, auto-refresh, and externally driven debugger actions.
- `debugger-session.js`: `sessionStorage` restore/persist for reload-friendly debugger state.
- `debugger-bootstrap.js`: DOM event wiring and boot sequence.

Scripts are loaded as classic browser scripts in the order listed in
`index.html`. There is no module loader or bundler for this frontend; shared
functions and variables are intentionally global within the page.

## Server Contract

The local HTTP server lives in `../src/debugger/server.ts`. It serves these
assets and proxies debugger requests to Valdi daemon or Hermes endpoints.

Important routes:

- `/api/status`: probes daemon targets and hot reload proxy state.
- `/api/snapshot`: fetches the selected target's view tree and preview data.
- `/api/runtime-logs` and `/api/runtime-logs/stream`: read and stream target logs.
- `/api/debugger/state`, `/api/debugger/events`, and `/api/debugger/actions`: keep the browser UI and external agents in sync.
- `/api/performance/profile/*`: list Hermes contexts and capture CPU profiles.

Renderer tracing is intentionally not part of this foundation. It requires the
separate runtime and native renderer-instrumentation stack; land that stack
before adding renderer trace routes or controls to this debugger. Hermes CPU
profiling uses the existing inspector transport and has no such prerequisite.
Target input forwarding and data/network provider tabs should likewise land
with their runtime-side contracts and end-to-end tests rather than as inactive
browser-only surfaces.
Web-renderer inspection should land together with its first-party bridge rather
than expose an inert preview flag from this foundation.

Detailed debugger snapshots explicitly opt in to component ViewModel and state
serialization. That data can be sensitive, is bounded by a per-field and
whole-tree character budget, and is never included in ordinary `valdi inspect
tree` requests. Auto-refresh starts disabled so serialization remains a
deliberate local debugging action. The server rejects non-loopback Host,
Origin, and cross-site browser API requests. It also generates a fresh
high-entropy API token for every server instance and rejects every `/api/*`
GET, POST, and event stream that does not present it. Browser and DevTools
pages receive the token in the served HTML bootstrap, use the
`X-Valdi-Debugger-Token` header for fetches, and add it only to same-origin
EventSource URLs (whose document has `Referrer-Policy: no-referrer`). The
ordinary CLI log and `VALDI_DEBUGGER_URL` never contain the token. Agents must
start the command with `--json`, treat the returned `apiToken` as a secret, and
send it using the returned `apiTokenHeader` name.

The UI listener and CLI target discovery use separate environment variables:

- `VALDI_DEBUGGER_UI_PORT` selects the browser HTTP port (default `8765`).
- `VALDI_DEBUGGER_SERVICE_PORT` tells target discovery which Valdi runtime
debugger service port to probe. Without it, discovery probes
the standalone and mobile defaults (`13591` and `13592`).

Both values must be decimal integers in the range 1–65535. The legacy
`VALDI_DEBUGGER_PORT` name is intentionally not used by the UI or service.

## Development Loop

For an installed CLI:

```bash
valdi debugger
```

For local CLI development, build the CLI, then run the built entrypoint:

```bash
cd npm_modules/cli
npm run build
node dist/index.js debugger --host 127.0.0.1 --port 8765
```

The synthetic native-tree preview never auto-loads projected HTTP(S) image,
video, CSS background, or WebView resources. Only `data:` and `blob:` media are
assigned; WebView contents are represented by an inert placeholder.

The debugger server watches `.html`, `.css`, and `.js` files in this directory
and emits `/api/dev-events`; the browser reloads itself when these files change.
If you add a new static asset type, update the server MIME map and watcher.

Session state is persisted in `sessionStorage` under
`valdi.debugger.session.v1`, so normal debugger refreshes should preserve the
active section, selected target/node, filters, expanded tree nodes, and capture
settings.

## Validation

For frontend-only changes:

```bash
for file in npm_modules/cli/debugger/debugger*.js; do node -c "$file" || exit 1; done
git diff --check
```

For changes that touch the server or CLI TypeScript:

```bash
cd npm_modules/cli
npm run build
node_modules/.bin/tsc --noEmit --project tsconfig.dist.json
```

When validating the full ordered browser bundle, concatenate the scripts in the
same order as `index.html` and parse the result with `new Function(...)`.
Loading
Loading