TypeScript cli & typescript repository by @angular. AI agent rules & system prompts with 27k stars.
---
trigger: always_on
---
This is the source code for the Angular CLI and related build tooling. This guide outlines standard practices for AI agents working in this repository.
## Environment
- Use `pnpm` for package management.
- Use `pnpm bazel test //target` to run tests.
## Key Documentation
- [Developer Guide](docs/DEVELOPER.md): definitive guide for building, debugging, and running test targets.
- [Contributing Guide](CONTRIBUTING.md): general contribution workflows and guidelines.
- [Commit Guidelines](CONTRIBUTING.md#commit): format for commit messages and PR titles.
## Building
- Make a local build of all packages:
```shell
pnpm build --local
```
## Coding Practices
- **Imports:**
- Always use the `node:` protocol for Node.js built-in imports (e.g., `node:fs`, `node:path`, `node:assert`).
- Prefer named imports (e.g., `import { mkdtemp } from 'node:fs'`) or default imports (`import fs from 'node:fs'`) instead of namespace imports (`import * as fs`).
- Use type-only imports (`import type { ... }`) when importing types to avoid runtime side-effects.
- **Classes:**
- Prefer ECMAScript private fields (`#field`) over TypeScript `private` keywords for encapsulated state.
## Testing
- **Temporary Directories (`TEST_TMPDIR`):**
- Tests in this repository only run in Bazel. **ALWAYS** use `process.env['TEST_TMPDIR']` and assert that it is set:
```ts
import assert from 'node:assert';
import { mkdtemp } from 'node:fs/promises';
import { join } from 'node:path';
describe('...', () => {
let tempRoot: string;
beforeAll(async () => {
const baseTmpDir = process.env['TEST_TMPDIR'];
assert(baseTmpDir, 'TEST_TMPDIR is not set');
tempRoot = await mkdtemp(join(baseTmpDir, 'angular-cli-test-'));
});
});
```
- **NEVER** use or fallback to `os.tmpdir()`. Bazel executes tests in hermetic sandboxes and sets `TEST_TMPDIR` to an isolated, sandboxed directory. Using `os.tmpdir()` can cause sandboxing failures, permission errors, or file leakage outside the Bazel sandbox.
- **Unit & Integration Tests:**
- Run all unit and integration tests: `pnpm bazel test //packages/...`
- Run a specific unit test target (e.g., `pnpm bazel test //packages/angular/build:test`). Note that package `:test` targets may exclude builder integration tests (such as specs under `**/builders/**/tests/**`).
- Run a specific builder integration test target (e.g., `pnpm bazel test //packages/angular/build:library_integration_tests` or `pnpm bazel test //packages/angular/build:application_integration_tests`).
- Query all test targets: `pnpm bazel query "tests(//packages/...)"`
- Find the exact test target for a specific spec file (using its workspace-relative path, which Bazel resolves as a source file target): `pnpm bazel query "kind(jasmine_test, rdeps(//packages/..., <relative/path/to/file_spec.ts>))"`
- Focus specific tests when debugging: use `fdescribe()` and `fit()`. NEVER commit focused tests to the repository.
- Run tests without sharding when isolating or debugging: use `--config=no-sharding` with a specific test target (e.g., `pnpm bazel test //packages/angular/build:library_integration_tests --config=no-sharding`).
This disables test sharding (`--test_sharding_strategy=disabled`) and flaky test retries (`--flaky_test_attempts=1`).
This is especially useful when isolating test runs or debugging with focused tests (`fit`/`fdescribe`) to avoid empty shard failures and unnecessary re-runs.
Do not use this flag when running broad test suites (such as `//packages/...`), as executing tests without sharding takes significantly longer.
- **End-to-End Tests:**
- Run subset of E2E tests: `pnpm bazel test //tests:e2e_node22 --config=e2e --test_filter="<filter>"`
## Pull Requests
- Use the `gh` CLI (GitHub CLI) for creating and managing pull requests.
- **Fixup Commits:**
- When addressing review feedback, **ALWAYS** use fixup commits (`git commit --fixup <commit>`) instead of amending existing commits. This preserves commit history during review and allows reviewers to easily see incremental changes.
- Only use fixup commits for changes that directly belong to the target commit. Unrelated changes must be made in a separate commit with their own commit message, not as a fixup commit.
- Fixup commits are automatically squashed when merging with `pnpm ng-dev pr merge` or optionally when rebasing with `pnpm ng-dev pr rebase <pr>`.
- Use `pnpm ng-dev pr` commands:
- `pnpm ng-dev pr rebase <pr>`: Rebase a PR branch on its target branch and optionally squash fixup commits.
- `pnpm ng-dev pr merge <pr>`: Merge an approved PR into its targeted branches.