Skip to content
Merged
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: 1 addition & 1 deletion .claude/skills/devtools-commit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The rules are in `docs/contributing/commit-message-guidelines.md`. Summary:
## Pull requests

- Pull requests are squash merged; the title becomes the commit on `main`, so it must follow the header format.
- A `commit-msg` hook (`scripts/commit-message.mjs`, enabled by `pnpm install`) warns about a bad message as you commit; CI checks the title and every commit in the pull request and, for now, reports problems as warnings. Run `pnpm commit:check` before pushing, and fix flagged messages with `git commit --amend` or a reword rebase.
- A `commit-msg` hook (`scripts/commit-message.mjs`, enabled by `pnpm install`) warns about a bad message as you commit; CI checks the title and every commit in the pull request: a bad title fails the check, and problems in the commits show as warnings. Run `pnpm commit:check` before pushing, and fix flagged messages with `git commit --amend` or a reword rebase.
- Address review feedback with fixup commits (`docs/contributing/using-fixup-commits.md`).
- One feature per pull request, with its tests (including agent tool tests when tools change).
- Rebuild and commit `extension/ui` when `app/` changed.
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ jobs:
- name: Smoke-test the CLI
run: node bin.mjs --help

node-22:
name: Package tests on Node.js 22
# `engines.node` allows 22, while the build job runs the `.nvmrc` version.
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: ./.github/actions/setup
with:
node-version: 22

- name: Test devtools package
run: pnpm test:devtools

axe:
runs-on: ubuntu-latest
timeout-minutes: 15
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/commit-message.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Pull request title
env:
TITLE: ${{ github.event.pull_request.title }}
run: node scripts/commit-message.mjs --title "$TITLE" --warn
run: node scripts/commit-message.mjs --title "$TITLE"

- name: Commit messages
env:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ jobs:
name: Angular ${{ matrix.angular }} on Node.js 22
runs-on: ubuntu-latest
timeout-minutes: 15
# The prerelease entry reports a private API rename early without failing the run.
continue-on-error: ${{ matrix.prerelease == true }}
strategy:
fail-fast: false
matrix:
Expand All @@ -29,6 +31,9 @@ jobs:
range: '^21.0.0'
- angular: '22'
range: '^22.0.0'
- angular: 'next'
range: 'next'
prerelease: true
steps:
- uses: actions/checkout@v7
with:
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ The unified Angular devtools. Inspect Angular component trees, signals, dependen
The package is published on npm as [`@pangular-inspector/devtools`](https://www.npmjs.com/package/@pangular-inspector/devtools).

```sh
npm install @pangular-inspector/devtools devframe
npm install -D @pangular-inspector/devtools
```

An Angular SSR server imports the hub when it starts, so install the package as a dependency there (`npm install @pangular-inspector/devtools`).

Then follow the [installation guide](./apps/docs/src/content/getting-started/installation.md) for your setup: Angular CLI with Express, Vite and Analog, the standalone CLI, [Angular Native](./apps/docs/src/content/guides/angular-native.md), or [Capacitor](./apps/docs/src/content/guides/capacitor.md). For a coding agent, run `npx @pangular-inspector/devtools mcp`.

## Documentation
Expand Down
8 changes: 4 additions & 4 deletions apps/docs/src/app/pages/index.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -865,22 +865,22 @@ claude mcp add pangular -- \\
readonly installCommands = [
{
pm: 'npm',
cmd: 'npm install @pangular-inspector/devtools devframe',
cmd: 'npm install @pangular-inspector/devtools',
logo: 'https://cdn.simpleicons.org/npm/CB3837',
},
{
pm: 'pnpm',
cmd: 'pnpm add @pangular-inspector/devtools devframe',
cmd: 'pnpm add @pangular-inspector/devtools',
logo: 'https://cdn.simpleicons.org/pnpm/F69220',
},
{
pm: 'yarn',
cmd: 'yarn add @pangular-inspector/devtools devframe',
cmd: 'yarn add @pangular-inspector/devtools',
logo: 'https://cdn.simpleicons.org/yarn/2C8EBB',
},
{
pm: 'bun',
cmd: 'bun add @pangular-inspector/devtools devframe',
cmd: 'bun add @pangular-inspector/devtools',
logo: 'https://bun.sh/logo.svg',
},
];
Expand Down
8 changes: 7 additions & 1 deletion apps/docs/src/content/agents/resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ Clients see each resource at a `devframe://resource/` URI with the id encoded. F
devframe://resource/pangular%3Acomponent-tree
```

Each one returns JSON.
Each one returns compact JSON.

### Page data and size

The `component-tree`, `signal-graph`, `injector-tree`, `ngrx-store`, `forms` and `router` resources start with an `_untrusted` field. The names, values and messages in them come from the running page. Treat them as data, not instructions.

When one of the first four runs past 100,000 characters, it returns a summary instead: `truncated: true`, up to 50 connected page ids in `pages`, and a `note` that names the tools to read the data with.

## Available resources

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/content/agents/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ These tools cover *Analog apps. Most read your source. Some also read what the V

### Call a server route <ngmd-badge variant="alpha">Action</ngmd-badge>

`analog-call-api` sends a request to a route on the running dev server, like `GET /api/v1/hello`, and returns the status, time and body. Secret keys, tokens and `Bearer` values in the body are masked. Reads: Vite plugin.
`analog-call-api` sends a request to a route on the running dev server, like `GET /api/v1/hello`, and returns the status, time and body. `path` is a path on the dev server that starts with a single `/`, not a full URL. `POST`, `PUT`, `PATCH` and `DELETE` need `confirm: true`. Secret keys, tokens and `Bearer` values in the body are masked. Reads: Vite plugin.

| Argument | Required | Value |
| --------- | -------- | ------------------------------------------------------------- |
Expand Down
13 changes: 8 additions & 5 deletions apps/docs/src/content/contributing/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,29 +174,32 @@ pnpm commit:check # Commit messages on your branch
</ngmd-step>
</ngmd-workflow>

A separate `axe` job in the same workflow installs Chromium and runs `pnpm test:axe`.
A separate `axe` job in the same workflow installs Chromium and runs `pnpm test:axe`. A `node-22` job runs `pnpm test:devtools` on Node.js 22, the oldest version `engines.node` allows.

### Angular compatibility

`.github/workflows/compat.yml` runs the page-side tests on the oldest and newest Angular versions the peer range allows. It runs on pushes to `main`, every Monday at 06:00 UTC, and on demand from the **Actions** tab. It doesn't run on pull requests.
`.github/workflows/compat.yml` runs the page-side tests on the oldest and newest Angular versions the peer range allows, and on the `next` prerelease. It runs on pushes to `main`, every Monday at 06:00 UTC, and on demand from the **Actions** tab. It doesn't run on pull requests.

| Job | Angular range | Node.js |
| ------------ | ------------- | ------- |
| Angular 20.0 | `~20.0.0` | 22 |
| Angular 21 | `^21.0.0` | 22 |
| Angular 22 | `^22.0.0` | 22 |
| Angular next | `next` | 22 |

Each job appends `overrides` for the `@angular/*` runtime packages to `pnpm-workspace.yaml`, reinstalls, and runs `vitest` with `packages/devtools/vitest.compat.config.ts`. That config picks the tests that render a real Angular app and leaves out the panel and server tests. It adds the Signal Forms tests on Angular 22 and later, and loads `zone.js` before Angular 21, where `TestBed` still expects it. A test that needs a feature from a later release checks the version with `angularAtLeast()` from `src/__tests__/angular-version.ts` and skips on older ones.
The `next` job installs the `next` dist-tag, so a renamed `ɵ` API shows up before the next major ships. It runs with `continue-on-error`: a failure marks the job red but not the workflow.

Each job appends `overrides` for the `@angular/*` runtime packages to `pnpm-workspace.yaml`, reinstalls, and runs `vitest` with `packages/devtools/vitest.compat.config.ts`. That config picks the tests that render a real Angular app or read Angular's private debug APIs, including the `*-real` tests that boot a real app where the main tests use fakes, and leaves out the panel tests and most server tests. It adds the Signal Forms tests on Angular 22 and later, and loads `zone.js` before Angular 21, where `TestBed` still expects it. A test that needs a feature from a later release checks the version with `angularAtLeast()` from `src/__tests__/angular-version.ts` and skips on older ones.

To reproduce a job, add the same `overrides` block to `pnpm-workspace.yaml`, run `pnpm install --no-frozen-lockfile`, then `pnpm exec vitest run --root packages/devtools --config vitest.compat.config.ts`. Don't commit the changed lockfile.

### Pull request checks

Two more workflows run on pull requests. Both only warn. They never fail the pull request.
Two more workflows run on pull requests. Only a pull request title that breaks the commit format fails one; everything else they find is a warning.

| Workflow | File | What it checks |
| ---------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Commit message` | `.github/workflows/commit-message.yml` | The pull request title and every commit message. The title becomes the commit on `main` when the pull request is squash merged. |
| `Commit message` | `.github/workflows/commit-message.yml` | The pull request title and every commit message. The title becomes the commit on `main` when the pull request is squash merged, so a bad title fails the check. |
| `Docs check` | `.github/workflows/docs-check.yml` | That a change to `packages/devtools/src/`, `app/src/` or the top-level files in `extension/` also changes a page in `apps/docs/src/content`. Tests don't count. |

If a code change needs no docs change, add the `no-docs` label to the pull request and say why in the description. The `Docs check` workflow then skips the warning.
Expand Down
10 changes: 5 additions & 5 deletions apps/docs/src/content/contributing/kitchen-sink.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,19 @@ bootstrapApplication(App, appConfig).then(() => {
### Code group

```bash group="install" name="pnpm" image="https://cdn.simpleicons.org/pnpm/F69220" active
pnpm add @pangular-inspector/devtools devframe
pnpm add @pangular-inspector/devtools
```

```bash group="install" name="npm" image="https://cdn.simpleicons.org/npm/CB3837"
npm install @pangular-inspector/devtools devframe
npm install @pangular-inspector/devtools
```

```bash group="install" name="yarn" image="https://cdn.simpleicons.org/yarn/2C8EBB"
yarn add @pangular-inspector/devtools devframe
yarn add @pangular-inspector/devtools
```

```bash group="install" name="bun" image="https://bun.sh/logo.svg"
bun add @pangular-inspector/devtools devframe
bun add @pangular-inspector/devtools
```

### File import
Expand Down Expand Up @@ -241,7 +241,7 @@ Text between alerts.

<ngmd-workflow>
<ngmd-step title="Install the package">
Run <code>pnpm add &#64;pangular-inspector/devtools devframe</code>.
Run <code>pnpm add &#64;pangular-inspector/devtools</code>.
</ngmd-step>
<ngmd-step title="Mount the hub">
Add the hub to your server.
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/src/content/contributing/writing-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,11 @@ For install commands, use a code group so readers pick their package manager. Li

````md
```bash group="install" name="pnpm" active
pnpm add @pangular-inspector/devtools devframe
pnpm add @pangular-inspector/devtools
```

```bash group="install" name="npm"
npm install @pangular-inspector/devtools devframe
npm install @pangular-inspector/devtools
```
````

Expand Down
21 changes: 11 additions & 10 deletions apps/docs/src/content/getting-started/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,22 @@ When the server is ready, it prints the version, the panel URL, the panel URL fo
MCP: http://localhost:9999/__mcp
```

If you pass no `--port` and port 9999 is taken, it also prints the port it uses instead. It also lists the extra allowed origins and a short hash of each pairing token, never the token.
With `--proxy-origin`, it also prints **Panel on your app**, the panel URL on your app's origin. If you pass no `--port` and port 9999 is taken, it also prints the port it uses instead. It also lists the extra allowed origins and a short hash of each pairing token, never the token.

When the server listens on your network (`--host 0.0.0.0` or a network address), it also prints the network URLs and an `initOverlay()` call to paste into an app on a device, with the server's whole connection info, its config included. See [Set up Capacitor](../guides/capacitor.md).

### Dev server flags

| Flag | What it does |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--port <port>` | Port to listen on. The default is 9999. If it is taken, a random free port is used. |
| `--host <host>` | Host to bind to. The default is `localhost`. |
| `--open`, `--no-open` | Open the browser on start, or not. |
| `--no-auth` | Turn off the one-time code the server asks for. |
| `--mcp`, `--no-mcp` | Mount the MCP endpoint at `/__mcp`, or not. It is on by default. |
| `--allowed-origin <origin>` | An extra origin allowed to reach the server, such as `http://192.168.1.20:8100`. Repeat it for more. |
| `--auth-token <token>` | A [pairing token](../security.md#pairing-tokens) a client may send instead of the one-time code. Repeat it for more. Prefer the `PANGULAR_AUTH_TOKEN` environment variable. |
| Flag | What it does |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--port <port>` | Port to listen on. The default is 9999. If it is taken, a random free port is used. |
| `--host <host>` | Host to bind to. The default is `localhost`. |
| `--open`, `--no-open` | Open the browser on start, or not. |
| `--no-auth` | Turn off the one-time code the server asks for. |
| `--mcp`, `--no-mcp` | Mount the MCP endpoint at `/__mcp`, or not. It is on by default. |
| `--allowed-origin <origin>` | An extra origin allowed to reach the server, such as `http://192.168.1.20:8100`. Repeat it for more. |
| `--proxy-origin <origin>` | The origin of your app's dev server when it proxies `/__pangular/` to this server, such as `http://localhost:4200`. The panel URL on that origin and the one-time code link point there. See [Client-only Angular CLI app](./installation.md#client-only-angular-cli-app). |
| `--auth-token <token>` | A [pairing token](../security.md#pairing-tokens) a client may send instead of the one-time code. Repeat it for more. Prefer the `PANGULAR_AUTH_TOKEN` environment variable. |

<ngmd-callout type="warning" title="Keep it on localhost">
The server binds to <code>localhost</code> by default and asks for a one-time code. Changing <code>--host</code> or passing <code>--no-auth</code> widens who can reach it. See <a href="../security.md">Access and redaction</a>.
Expand Down
5 changes: 2 additions & 3 deletions apps/docs/src/content/getting-started/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,10 @@ export default defineConfig({

The default export of `@pangular-inspector/devtools/devframe` uses the defaults. Call `createPangular()` to pass options:

```ts {7-9}
```ts {6-8}
// src/server.ts
import express from 'express';
import {initDevframe} from 'devframe/initiate';
import {createPangular} from '@pangular-inspector/devtools/devframe';
import {createPangular, initDevframe} from '@pangular-inspector/devtools/devframe';

const app = express();
const devtools = initDevframe(createPangular({agent: {readOnly: true}}), {
Expand Down
Loading
Loading