https://github.com/wieslawsoltes/inspector
Inspector is a .NET CLI and runtime infrastructure for inspecting and manipulating Avalonia UI trees.
https://github.com/wieslawsoltes/inspector
avalonia avaloniaui cli coding-agents inspector logical-tree visual-tree
Last synced: about 2 months ago
JSON representation
Inspector is a .NET CLI and runtime infrastructure for inspecting and manipulating Avalonia UI trees.
- Host: GitHub
- URL: https://github.com/wieslawsoltes/inspector
- Owner: wieslawsoltes
- License: mit
- Created: 2026-03-01T10:43:53.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-12T10:52:10.000Z (3 months ago)
- Last Synced: 2026-03-12T16:00:21.530Z (3 months ago)
- Topics: avalonia, avaloniaui, cli, coding-agents, inspector, logical-tree, visual-tree
- Language: C#
- Homepage:
- Size: 64.5 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Inspector
[](https://github.com/wieslawsoltes/Inspector/actions/workflows/ci.yml)
[](https://github.com/wieslawsoltes/Inspector/actions/workflows/release.yml)
Inspector is a .NET CLI and runtime infrastructure for inspecting and manipulating Avalonia UI trees.
It is designed for both human use and coding-agent automation with deterministic, machine-readable output.
## What it does
- Enumerates **visual** and **logical** trees
- Reads node property metadata and values
- Applies node/property mutations (set property, insert/remove/move/reparent)
- Exposes capabilities and stable schema metadata for automation
- Supports:
- **Host mode** (instrumented runtime in app)
- **Process mode** (CLI-side no-host attach via `--pid` or `--name`)
## NuGet packages
| Package | Version | Downloads | Install |
| --- | --- | --- | --- |
| [`Inspector.Contracts`](https://www.nuget.org/packages/Inspector.Contracts) | [](https://www.nuget.org/packages/Inspector.Contracts) | [](https://www.nuget.org/packages/Inspector.Contracts) | `dotnet add package Inspector.Contracts` |
| [`Inspector.Transport`](https://www.nuget.org/packages/Inspector.Transport) | [](https://www.nuget.org/packages/Inspector.Transport) | [](https://www.nuget.org/packages/Inspector.Transport) | `dotnet add package Inspector.Transport` |
| [`Inspector.Host`](https://www.nuget.org/packages/Inspector.Host) | [](https://www.nuget.org/packages/Inspector.Host) | [](https://www.nuget.org/packages/Inspector.Host) | `dotnet add package Inspector.Host` |
| [`Inspector.AvaloniaAdapter`](https://www.nuget.org/packages/Inspector.AvaloniaAdapter) | [](https://www.nuget.org/packages/Inspector.AvaloniaAdapter) | [](https://www.nuget.org/packages/Inspector.AvaloniaAdapter) | `dotnet add package Inspector.AvaloniaAdapter` |
| [`Inspector.Cli.Tool`](https://www.nuget.org/packages/Inspector.Cli.Tool) | [](https://www.nuget.org/packages/Inspector.Cli.Tool) | [](https://www.nuget.org/packages/Inspector.Cli.Tool) | `dotnet tool install --global Inspector.Cli.Tool` |
## Installation
### Library packages
Install the package you need:
```bash
dotnet add package Inspector.Contracts
dotnet add package Inspector.Transport
dotnet add package Inspector.Host
dotnet add package Inspector.AvaloniaAdapter
```
### CLI as .NET tool
Global tool:
```bash
dotnet tool install --global Inspector.Cli.Tool
inspector --help
```
Local tool manifest:
```bash
dotnet new tool-manifest
dotnet tool install --local Inspector.Cli.Tool
dotnet tool run inspector --help
```
Update/uninstall:
```bash
dotnet tool update --global Inspector.Cli.Tool
dotnet tool uninstall --global Inspector.Cli.Tool
```
## Repository layout
```text
src/
Inspector.Contracts Shared DTOs/enums/schema contracts
Inspector.Transport Local transport/session/authorization model
Inspector.Host In-process host runtime abstractions
Inspector.AvaloniaAdapter Tree/property/mutation adapter implementations
Inspector.Cli Command-line interface and agent-friendly output
tests/
Inspector.Tests xUnit test suite
samples/
Inspector.SampleApp Minimal host runtime integration sample
```
## Requirements
- .NET SDK compatible with `net10.0`
## CI build and release scripts
- `scripts/ci-build.sh`: restore, build, test, and pack all publishable packages.
- `scripts/ci-release.sh`: runs `ci-build.sh` and pushes `.nupkg`/`.snupkg` to NuGet.
- `.github/workflows/ci.yml`: PR/push validation + package artifact upload.
- `.github/workflows/release.yml`: tag/manual release publishing to NuGet (`NUGET_API_KEY` secret required).
Run locally:
```bash
bash scripts/ci-build.sh
```
Release locally:
```bash
NUGET_API_KEY= VERSION=0.1.0 bash scripts/ci-release.sh
```
## CLI help (latest)
```text
Inspector.Cli command surface
Usage:
inspector capabilities
inspector connect [--mode ] [--address ] [--pid ] [--name ] [--client-id ] [--client-version ] [--secret ] [--scope ]...
inspector tree get --session-id [--kind visual|logical]
inspector node get-properties --session-id --node-id
inspector node set-property --session-id --node-id --property --value [--operation-id ]
inspector tree mutate --session-id --target-node-id --operation [--payload ] [--dry-run] [--operation-id ]
inspector tree batch-mutate --session-id --operations [--dry-run] [--operation-id ]
Global options:
--json Emit deterministic JSON output
--output Select output mode
--help, -h Show help
Exit codes: 0=success, 2=validation error, 3=execution error, 10=unexpected error
```
## CLI usage examples
```bash
# Capabilities
inspector capabilities --json
# Connect (host mode)
inspector connect --mode host --address local://inspector --client-id my-tool --json
# Connect (process mode by pid)
inspector connect --mode process --pid 12345 --json
# Connect (process mode by name)
inspector connect --mode process --name Inspector.SampleApp --json
# Visual tree
inspector tree get --session-id sess-123 --kind visual --json
# Node properties
inspector node get-properties --session-id sess-123 --node-id visual-button --json
# Set property
inspector node set-property --session-id sess-123 --node-id visual-button --property Width --value 320 --json
# Mutate tree (dry-run)
inspector tree mutate --session-id sess-123 --target-node-id visual-button --operation move --payload '{"index":0}' --dry-run --json
# Batch mutate (single call, multiple operations)
inspector tree batch-mutate --session-id sess-123 --operations '[{"targetNodeId":"visual-label","operation":"set-property","payload":{"property":"Text","value":"Welcome back"}},{"targetNodeId":"visual-root","operation":"insert","payload":{"typeName":"TextBox","name":"EmailInput","properties":{"Watermark":"Email"}}}]' --json
```
If you are developing from source, you can run the same commands with:
```bash
dotnet run --project src/Inspector.Cli -- [args]
```
### Host mode full tree mutability payloads
When connected with `--mode host`, `tree mutate` supports structural and property mutations with JSON payloads:
- `set-property`: `{"property":"","value":}`
- `insert`: `{"typeName":"","nodeId":"","name":"","classes":["..."],"properties":{"...":...},"index":0}`
- `move`: `{"index":1}`
- `reparent`: `{"parentNodeId":"","index":0}`
- `remove`: payload optional
The same operation payloads are also used by `tree batch-mutate` entries.
Examples:
```bash
# Create a new control node under visual-root (nodeId can be omitted for auto-generation)
inspector tree mutate --session-id --target-node-id visual-root --operation insert --payload '{"typeName":"Avalonia.Controls.TextBox","name":"EmailInput","properties":{"Text":"","Watermark":"Email"}}' --json
# Set any property via tree mutate payload
inspector tree mutate --session-id --target-node-id visual-label --operation set-property --payload '{"property":"Text","value":"Ready to login"}' --json
# Reparent and remove
inspector tree mutate --session-id --target-node-id child-node --operation reparent --payload '{"parentNodeId":"new-parent","index":0}' --json
inspector tree mutate --session-id --target-node-id old-node --operation remove --json
# Batch mutate using either raw array or { "operations": [...] }
inspector tree batch-mutate --session-id --operations '{"operations":[{"targetNodeId":"visual-label","operation":"set-property","payload":{"property":"Text","value":"Ready to login"}},{"targetNodeId":"visual-root","operation":"insert","payload":{"typeName":"Avalonia.Controls.TextBox","name":"EmailInput","properties":{"Watermark":"Email"}}}]}' --json
```
## Process mode guide (`--mode process`)
Use this mode to target an already-running process by PID or process name.
1) Connect and capture session id:
```bash
inspector connect --mode process --pid --json
# or
inspector connect --mode process --name --json
```
Check `data.processSnapshotAvailable` in connect output:
- `true`: live UI snapshot is available
- `false`: CLI will use fallback process metadata
2) Reuse returned `sessionId` in follow-up commands:
```bash
inspector tree get --session-id --kind visual --json
inspector node get-properties --session-id --node-id --json
inspector node set-property --session-id --node-id --property --value --json
```
For apps that include the sample snapshot publisher integration:
- `node set-property` queues live property mutation commands for the running process.
- `tree mutate` in process mode also queues live structural mutation commands (`insert`, `remove`, `move`, `reparent`, `set-property`) so runtime controls can be added/rearranged without restarting the app.
- `tree batch-mutate` applies multiple mutations in one CLI call and queues each live process mutation command in order for faster bulk updates.
3) Common process-mode errors:
- `cli.process.not_found`: PID/name not found
- `cli.process.ambiguous`: multiple processes match `--name` (retry with `--pid`)
- `cli.process.exited`: process ended before command execution
When the target app publishes live inspector snapshots (the included `Inspector.SampleApp` does), process mode returns live visual/logical nodes and node properties instead of fallback process metadata.
If no live snapshot is published by the target process, process mode falls back to process metadata nodes.
## Session model
- `connect` creates a session and returns `sessionId`.
- Session state is persisted across CLI invocations in a local temporary session store.
- `tree get`, `node get-properties`, `node set-property`, `tree mutate`, and `tree batch-mutate` require a valid `--session-id`.
## Output behavior
- Defaults to **JSON** when input/output is redirected (non-interactive)
- Supports explicit output selection via `--output text|json`
- `--json` forces deterministic JSON output
- Errors are returned with explicit non-zero exit codes
## Agent skill integration (Codex)
Repository includes a single Codex skill definition:
- `SKILL/inspector-avalonia-cli/SKILL.md`
Install it locally:
```bash
mkdir -p ~/.codex/skills/inspector-avalonia-cli
cp SKILL/inspector-avalonia-cli/SKILL.md ~/.codex/skills/inspector-avalonia-cli/SKILL.md
```
## Sample app
`samples/Inspector.SampleApp` is an Avalonia desktop app (`dotnet` Avalonia template) with inspector host wiring via `InspectorHostRuntime` and `DelegateInspectorRequestHandler`.
Run it with:
```bash
dotnet run --project samples/Inspector.SampleApp
```
Then connect from CLI in host mode:
```bash
inspector connect --mode host --address local://inspector --json
```
## Current implementation status
This repository includes a functioning foundation (contracts, transport model, host runtime, adapter services, CLI, tests, sample app), including process-mode connection via `--pid`/`--name` and session-aware CLI workflows.