Skip to content
Draft
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
63 changes: 63 additions & 0 deletions .claude/rules/angular.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Angular rules

You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.

These apply to every Angular and TypeScript file in the repository: the panel (`app`), the package (`packages/ng-devtools`), the demo apps and the docs site. `AGENTS.md` points here so agents other than Claude Code find them too.

## TypeScript Best Practices

- Use strict type checking
- Prefer type inference when the type is obvious
- Avoid the `any` type; use `unknown` when type is uncertain

## Angular Best Practices

- Always use standalone components over NgModules
- Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
- Do NOT set `changeDetection: ChangeDetectionStrategy.OnPush` explicitly. `OnPush` is the default in Angular v22+.
- Use signals for state management
- Implement lazy loading for feature routes
- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
- Use `NgOptimizedImage` for all static images.
- `NgOptimizedImage` does not work for inline base64 images.

## Accessibility Requirements

- It MUST pass all AXE checks.
- It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.

### Components

- Keep components small and focused on a single responsibility
- Use `input()` and `output()` functions instead of decorators
- Use `model()` for two-way bound properties with `[(prop)]` syntax instead of pairing `input()` with `output()`
- Use `computed()` for derived state
- Use `linkedSignal()` for state derived from multiple reactive sources that must stay synchronized
- Prefer inline templates for small components
- Prefer Signal Forms (`@angular/forms/signals`) for new forms. They are stable in Angular v22+ and provide signal-based state, type-safe field access, and schema-based validation
- When not using Signal Forms, prefer Reactive forms instead of Template-driven ones
- Do NOT use `ngClass`, use `class` bindings instead
- Do NOT use `ngStyle`, use `style` bindings instead
- Do NOT import `CommonModule`, import only the directives and pipes the template uses, such as `AsyncPipe` or `DatePipe`
- When using external templates/styles, use paths relative to the component TS file.

## State Management

- Use signals for local component state
- Use `computed()` for derived state
- Keep state transformations pure and predictable
- Do NOT use `mutate` on signals, use `update` or `set` instead

## Templates

- Keep templates simple and avoid complex logic
- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
- Use the async pipe to handle observables
- Do not assume globals like (`new Date()`) are available.

## Services

- Design services around a single responsibility
- Use the `providedIn: 'root'` option for singleton services
- Prefer the `@Service` decorator over `@Injectable({providedIn: 'root'})` for new singleton services (Angular v22+)
- Use the `inject()` function instead of constructor injection
40 changes: 40 additions & 0 deletions .claude/skills/devtools-fix-issue/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: devtools-fix-issue
description: Take one GitHub issue in this repository to a pull request, from checking the report against the code to answering review comments. Use when asked to fix, investigate or close a specific issue, or to address review comments on a fix.
---

# Fix one issue

Treat the issue as a claim. The report, its evidence and its proposed fix can all be wrong or out of date.

## 1. Check the report

- Read it with `gh issue view <n> --repo santoshyadavdev/angular-devtools`, then read the code it names on `main`.
- Check the claim against the reference the code follows: Angular's own source in `node_modules/@angular/*` for debug APIs and forms or router behaviour, the NgRx or Analog packages for their internals, devframe for transport and auth.
- If the report is wrong, already fixed, or needs a product or design decision, stop and say so with evidence. Don't guess a design. The `grilling` skill settles the decision with the maintainer.
- If it can only be confirmed by a manual test the maintainer has to do (the Chrome extension in real Chrome, for example), stop and say what the test is.

## 2. Reproduce, then fix

1. Write a test that fails for the reported reason, not for some side effect. Package code goes in `packages/ng-devtools/src/__tests__`, panel code in `app/src/__tests__` (`pnpm test:panel`).
2. Make the smallest fix that covers the cause. Follow `docs/contributing/coding-standards.md` and the `devtools-inspector` or `devtools-ui` skill for the area.
3. Undo the fix and run the test again. It must fail. Put the fix back.
4. Update the docs page for the area when behaviour, options, labels or tools change (`devtools-docs` skill).

## 3. Check it

Run the checks in the `devtools-verify` skill. When `app/` changed, run `pnpm extension:build` and commit `extension/ui`, or CI fails.

Then review your own diff as a skeptic: data that now leaks without redaction, a new tool missing from the config lists in `packages/ng-devtools/src/config.ts`, a listener or wrapper that is never removed, a docs claim the code doesn't back.

## 4. Open the pull request

Follow the `devtools-commit` skill. Put `Fixes #<n>` in the body. When only part of the issue is fixed, write `Refs #<n>` and say what is left.

Issue titles follow `area: what is wrong`, in lowercase, with a commit scope as the area: `router: a failed lazy navigation is only logged`. Use it for any follow-up issue you open, and use the issue's area as the scope of the fix's commit.

## Review comments

- Check each comment against the code before changing anything. Bots (CodeRabbit) are often right and sometimes wrong.
- Fix the valid ones with a test. For the rest, reply with the evidence: the file and line, a command and its output, or the case the reviewer missed.
- A CI failure your change caused reproduces locally. A flake passes on a rerun and fails on `main` too. Say which it was.
51 changes: 51 additions & 0 deletions .claude/skills/devtools-work-issues/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: devtools-work-issues
description: Work through a batch of GitHub issues in this repository with parallel agents, then combine, verify and ship them as one pull request per batch. Use when asked to fix all issues of a priority or label, or several issues at once.
---

# Work a batch of issues

Each issue still goes through the `devtools-fix-issue` skill. This skill is about running many of them at once without agents getting in each other's way.

## 1. Plan the batch

- List the issues: `gh issue list --repo santoshyadavdev/angular-devtools --label P2 --state open --limit 200`.
- Leave out issues that need a product or design decision, or a manual test the maintainer has to do. List them in the report as "for later", and settle the decisions afterwards with the `grilling` skill. If only part of an issue is clear, do that part and use `Refs #<n>` for it.
- Titles follow `area: what is wrong` (`router: a failed lazy navigation is only logged`), and the area is a commit scope, so it usually names the group. Title any follow-up issue the same way.
- Group the rest by the files they touch (inspector or area: forms, router, http, analog, signals, overlay and popup, cli and config, extension), so no two groups edit the same code. Aim for three to eight issues per group.

## 2. One worktree per group

- Create a detached worktree per group, plus one for combining, in a folder git ignores:
`git worktree add --detach <path> <base>`, then `pnpm install --frozen-lockfile --prefer-offline` in each.
- Agents only edit files in their own worktree. They don't commit, stage, branch, stash or push. A reviewer can read each group's work with `git diff`.
- Each agent returns, per issue: fixed, partly fixed or skipped, the cause and fix in a line, the test it added, and its check results.
- With many worktrees inside the repository folder, Nx finds duplicate projects. Run it as `NX_WORKSPACE_ROOT_PATH=$PWD NX_DAEMON=false pnpm exec nx test angular-devtools`.

## 3. Combine

- Copy each group's changed and new files into the combine worktree. For a file that another group changed too, use `git merge-file` against the base version (`git show <base>:<path>`) and keep every fix.
- Run the full `devtools-verify` checks there once, and fix breakage between groups.
- Run `pnpm extension:build` once at the end, not in every group, and commit `extension/ui` in its own commit.

## 4. Verify before the pull request

Run read-only agents against the combined branch, each in its own worktree and port range:

- a code review per pull request (`devtools-reviewer` role);
- the panel in a real browser, every inspector tab, with axe (`a11y-reviewer` role);
- every agent tool through a real MCP client;
- every setup: Express hub, Vite plugin, CLI, static report, the Analog example;
- regressions: tests deleted or weakened since `main`, and removed tools, config keys or flags.

Then have a second agent try to refute each finding, and fix only what survives.

## 5. Ship

- One pull request per batch, with `Closes #<n>` per fixed issue, a "Left open" section, and the checks.
- Stacked batches (P2 built on P1, and so on): after the first is squash merged, merge `main` into the next one. Its conflicts are the same changes on both sides, so keep the branch's side, then check that the diff against the old branch head only adds what landed on `main` since. Watch for paragraphs the merge duplicates in docs.
- Conflicts in `extension/ui/assets` are build output. Drop both sides and run `pnpm extension:build` again.

## 6. Clean up

Remove the worktrees (`git worktree remove -f -f <path>`, then `git worktree prune`) and delete the merged local branches.
28 changes: 28 additions & 0 deletions .claude/skills/grilling/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: grilling
description: Stress-test a plan, design or open decision by asking the user one question at a time, each with a recommended answer, until both sides agree, and only then act. Use before a non-trivial design, for issues left open as "needs a decision", or whenever the user asks to be grilled or to have their thinking challenged.
---

# Grilling

Interview the user about every part of the plan until you reach a shared understanding. Walk down each branch of the decision tree and settle the decisions one by one, in the order they depend on each other.

## How to ask

- Ask one question at a time, and wait for the answer before the next. Several questions at once are hard to answer well.
- Give your recommended answer with every question, and say why in a sentence or two. Name the alternatives you considered and what each would cost.
- Keep a running list of what is decided. Restate it when a later answer changes an earlier one.

## Facts versus decisions

- Look up facts yourself instead of asking. Read the code, the docs, the issue and its comments (`gh issue view <n> --repo santoshyadavdev/angular-devtools --comments`), `git log`, and Angular's own source in `node_modules/@angular/*`. Quote what you found when it shapes a question.
- Put every decision to the user and wait. A decision is anything about behaviour, scope, naming, defaults, security or what the project supports. Don't settle one because it looks obvious.
- Use the words in `docs/CONTEXT.md`. If a question needs a word that isn't there, say so; the answer may belong in the glossary.

## Don't act yet

Don't edit files, open pull requests, or comment on issues until the user confirms you have reached a shared understanding. Then summarise the decisions, and hand the work to the matching skill: `devtools-fix-issue` for one issue, `devtools-work-issues` for a batch.

## Issues that need a decision

This is the tool for issues that `devtools-fix-issue` and `devtools-work-issues` leave open as "needs a decision" or "for later", such as #69, #100, #128, #157, #166 and #181. Read the issue and the code it names first, then grill the user on the open choice. Once it is settled, the issue can go through `devtools-fix-issue` like any other. If the user wants the decision recorded on the issue, draft the comment and let them post it.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @santoshyadavdev
* @santoshyadavdev @erkamyaman
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
name: Bug report
description: Something in the devtools shows wrong data, breaks, or looks wrong
title: '<area>: '
labels: [bug, needs triage]
body:
- type: markdown
attributes:
value: |
Title the issue `area: what is wrong`, in lowercase, for example `router: a failed lazy navigation is only logged`. The area is one of the [commit scopes](https://github.com/santoshyadavdev/angular-devtools/blob/main/docs/contributing/commit-message-guidelines.md#scope), such as `components`, `router`, `forms`, `http`, `mcp`, `extension` or `docs`.
- type: dropdown
id: area
attributes:
Expand Down
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
name: Feature request
description: Suggest an inspector, a view or an agent tool
title: '<area>: '
labels: [feature, needs triage]
body:
- type: markdown
attributes:
value: |
Title the issue `area: what is missing`, in lowercase, for example `signals: the detail panel can't jump to a dependency or consumer`. The area is one of the [commit scopes](https://github.com/santoshyadavdev/angular-devtools/blob/main/docs/contributing/commit-message-guidelines.md#scope), such as `components`, `router`, `forms`, `http`, `mcp`, `extension` or `docs`.
- type: textarea
id: problem
attributes:
Expand Down
26 changes: 26 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Set up the workspace
description: pnpm, Node and a frozen install. Shared by every workflow so they resolve the same tree.

inputs:
registry-url:
description: Passed to setup-node, which writes an .npmrc for it. Only the release sets it.
required: false
default: ''

runs:
using: composite
steps:
# Reads the version from the root `packageManager` field, so CI and a laptop resolve the
# same tree.
- uses: pnpm/action-setup@v5

- uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
cache: pnpm
registry-url: ${{ inputs.registry-url }}

# Frozen: a lockfile that does not match the manifests fails the run rather than quietly
# resolving something newer.
- run: pnpm install --frozen-lockfile
shell: bash
20 changes: 4 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
branches: [main]
pull_request:
branches: [main]
# The release runs this same gate on the commit it releases.
workflow_call:

permissions:
contents: read
Expand All @@ -25,14 +27,7 @@ jobs:
fetch-depth: 0
persist-credentials: false

- uses: pnpm/action-setup@v5

- uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
cache: pnpm

- run: pnpm install --frozen-lockfile
- uses: ./.github/actions/setup

- uses: nrwl/nx-set-shas@v4

Expand Down Expand Up @@ -77,14 +72,7 @@ jobs:
with:
persist-credentials: false

- uses: pnpm/action-setup@v5

- uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
cache: pnpm

- run: pnpm install --frozen-lockfile
- uses: ./.github/actions/setup

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium
Expand Down
63 changes: 63 additions & 0 deletions .github/workflows/latest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Latest versions

# The package declares `@angular/core >=20` and `vite >=5`, and this repository pins the versions
# it tests on, so a new Angular, Analog or Vite release can break users between our releases
# without CI noticing (#100). Each week this makes fresh apps the way users do, on whatever those
# ranges resolve to that day, installs the package from a local registry, wires the documented
# setup, builds it and checks the hub answers. See apps/docs/src/content/contributing/publishing.md.
on:
schedule:
# Mondays at 06:00 UTC.
- cron: '0 6 * * 1'
workflow_dispatch:

permissions:
contents: read
# A failing scheduled run opens, or comments on, one issue per scenario.
issues: write

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

jobs:
scenario:
name: ${{ matrix.scenario }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
# Every scenario reports, so one week's failures are all visible at once.
fail-fast: false
matrix:
scenario:
- angular-cli
- analog
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: ./.github/actions/setup

# Starts its own Verdaccio, publishes the package there, and writes the Angular, Analog,
# Vite and devframe versions it resolved to the job summary, pass or fail.
- run: pnpm verify:publish --scenario=${{ matrix.scenario }}

# One open issue per scenario, found by its title: a new one the first week it fails, and a
# comment on that one every week after until someone closes it.
- name: Report the failure
if: failure() && github.event_name == 'schedule'
env:
GH_TOKEN: ${{ github.token }}
SCENARIO: ${{ matrix.scenario }}
RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
title="ci: the $SCENARIO setup fails on the latest versions"
body="The $SCENARIO scenario of \`pnpm verify:publish\` failed on the newest versions the peer ranges allow: $RUN. The run's summary lists the versions it resolved. See #100."
number=$(gh issue list --state open --search "\"$title\" in:title" --json number,title \
| jq -r --arg title "$title" 'map(select(.title == $title)) | .[0].number // empty')
if [ -n "$number" ]; then
gh issue comment "$number" --body "Still failing: $RUN"
else
gh issue create --title "$title" --body "$body" --label bug --label 'area: ci'
fi
Loading
Loading