Angular Linters & Git Hooks
This skill standardizes code quality and commit message consistency using industry-standard tools.
Fundamental Principles
- References as Source of Truth: The files within the
references/ directory are the absolute source of truth for configuration patterns. Always read the relevant reference file BEFORE performing any configuration step or proposing changes.
- Strict
defineConfig Standard: For Angular v19+ and v21+, defineConfig from eslint/config is the mandatory wrapper for eslint.config.js. Do NOT replace it with tseslint.config or other wrappers, as it is the official default generated by Angular schematics.
Recommended Workflow
IMPORTANT: Steps 1–8 form a continuous pipeline. Execute them sequentially without pausing for user confirmation between steps. Only stop and try to fix if a MUST pass check fails.
Package Manager Convention: Throughout this skill, [pkg-manager] refers to the package manager confirmed during project setup (pnpm, npm, or yarn). The [exec] command maps to pnpm exec / yarn exec / npx respectively. All commands MUST use the confirmed manager — never default to a specific one.
Pre-Condition (MANDATORY):
Before starting, run git status --porcelain. If the output is NOT empty, STOP. Tell the user: "Your working directory has uncommitted changes. Please commit or stash them before running this skill to protect your work."
Failure Recovery:
If any step fails:
- Run
git diff --name-only to identify files changed by this skill.
- Revert ONLY those files:
git checkout -- <file1> <file2> ...
- Remove ONLY untracked files created by this skill (config files generated by the script), not all untracked files.
- Do NOT use
git reset --hard or git clean -fd — these destroy unrelated user work.
Step 0: Read Project Manifest
- Read
PROJECT_MANIFEST.json from the project root.
- Extract
packageManager, style, angularMajorVersion, and rxjsLinting.
- If the file is missing, ask the user for these values before proceeding. Do NOT assume defaults.
- Use
packageManager as [pkg-manager] throughout this skill.
Step 1: Preparation & Installation
- Read References: Read all files in the
references/ directory to understand the project's quality standards.
- Install Tools: Run
scripts/configure_linters.sh --style [css|scss] --package-manager [pkg-manager] --rxjs [auto|enabled|disabled] to install all quality tools and perform initial configuration. Pass the project's style format, package manager, and RxJS linting mode so the correct dependencies are installed:
- CSS: Installs
stylelint-config-standard
- SCSS: Installs
stylelint-config-standard-scss (includes SCSS syntax + plugin)
IMPORTANT: Before running the script, verify the file content with a quick read to confirm it contains the expected --style parsing logic. This prevents stale file versions from running.
Note: The globals package is installed as part of this setup.
Step 2: Verify Installation Output
After running configure_linters.sh, verify what it creates:
Packages:
- Required devDependencies exist (e.g.,
@angular-eslint/*, husky, lint-staged, @commitlint/cli, etc.)
Config Files (auto-generated by script):
eslint.config.js (from ng add @angular-eslint/schematics)
.prettierignore
.stylelintignore
stylelint.config.mjs (CSS or SCSS variant based on --style)
commitlint.config.js
.husky/commit-msg (commitlint hook)
.husky/pre-commit (lint-staged hook)
Note: eslint.config.js is the base Angular config — it will be enhanced with plugins in Step 3. The package.json scripts, prettier config, and lint-staged config are added by the Agent in Step 3.
Step 3: Iterative ESLint Configuration & Verification
This phase adds ESLint plugins incrementally, verifying stability after each addition.
3.0: Add Development Scripts
Add quality scripts to package.json. Adjust the glob pattern to match the project's style format (*.css, *.scss, or *.{css,scss}):
{
"lint": "ng lint",
"lint:fix": "ng lint --fix",
"lint:styles": "stylelint \"src/**/*.css\"",
"lint:styles:fix": "stylelint \"src/**/*.css\" --fix",
"format": "prettier --check \"src/**/*.{ts,html,css,json,md}\"",
"format:fix": "prettier --write \"src/**/*.{ts,html,css,json,md}\""
}
Verify Scripts: Run [pkg-manager] run to list available scripts and confirm they were added.
CI Usage: Use check-only scripts (lint, lint:styles, format) to fail builds on issues.
Development: Use auto-fix scripts (lint:fix, lint:styles:fix, format:fix) to fix issues locally.
3.1: Verify Base Configuration
- Run
[pkg-manager] run lint immediately after installation.
- MUST pass before proceeding.
- Note: The base configuration from
ng add @angular-eslint/schematics automatically includes tsRecommended, templateRecommended, and templateAccessibility. Verification involves ensuring these presets are present in eslint.config.js.
3.2: Add Prettier Integration
- Add both Prettier packages to
eslint.config.js as the last two entries in the defineConfig array:
eslint-config-prettier — Disables ESLint formatting rules that conflict with Prettier.
eslint-plugin-prettier/recommended — Runs Prettier as an ESLint rule (so ng lint --fix formats too).
- Add global ignores and globals configuration (see
references/eslint-config-template.md).
- Prettier Config: Modern Angular CLI may auto-generate a
"prettier" key in package.json. Do NOT create a .prettierrc file. Instead:
- Verify the
"prettier" key exists in package.json.
- Verify the Angular HTML parser override is in
package.json (see references/prettier.md).
- Create
.prettierignore (consult references/prettier.md).
- Run
[pkg-manager] run lint.
- MUST pass before proceeding.
3.3: Add Organizational Plugins
- Add
eslint-plugin-import-x and eslint-plugin-unused-imports to eslint.config.js (consult references/import-x-and-unused-imports.md).
- Use the official
defineConfig pattern: register importX as a plugin and use extends: ['import-x/flat/recommended', 'import-x/flat/typescript'] string references.
- Add
// @ts-expect-error -- known type incompatibility between import-x and ESLint Plugin types above the 'import-x': importX line.
- Run
[pkg-manager] run lint.
- MUST pass before proceeding.
3.4: Add RxJS Plugin (CONDITIONAL)
- Read
rxjsLinting from PROJECT_MANIFEST.json (or ask the user if no manifest):
"auto" (default): Check if rxjs is listed in package.json dependencies or devDependencies. If present, proceed. If absent, skip.
"enabled": Always install and configure the plugin.
"disabled": Skip entirely.
- If installing: Add
eslint-plugin-rxjs-x to eslint.config.js using the shared config rxjsX.configs.recommended (consult references/rxjs.md). Ensure parserOptions.projectService: true is set in the TypeScript block for type-aware rules.
- Run
[pkg-manager] run lint.
- If type-checker errors occur, consult references and troubleshoot parser configuration.
- MUST pass before proceeding.
- If skipping: Inform the user: "RxJS linting is disabled for this project. If you add RxJS later, re-run Step 3.4 or set
rxjsLinting: enabled in the manifest."
Step 4: Stylelint Verification
- Verify:
stylelint.config.mjs and .stylelintignore exist (auto-generated by script in Step 1).
- Run
[pkg-manager] run lint:styles to verify configuration.
- MUST pass before proceeding.
Step 5: Git Hooks Validation
- Verify:
.husky/pre-commit and .husky/commit-msg exist (auto-generated by script in Step 1).
- Add a
"lint-staged" key to package.json (consistent with Prettier — both inline):{
"lint-staged": {
"*.ts": ["eslint --fix"],
"*.html": ["eslint --fix", "prettier --write"],
"*.css": ["stylelint --fix", "prettier --write"],
"*.{json,md}": ["prettier --write"]
}
}
Note: Do NOT create a .lintstagedrc file. Keep it inline in package.json for consistency.
- Verify:
commitlint.config.js, .husky/commit-msg, .husky/pre-commit, and "lint-staged" key in package.json all exist.
- Perform a test commit to verify:
- Husky pre-commit hook triggers lint-staged.
- Commitlint validates conventional commit messages.
- MUST succeed before proceeding.
Step 6: Final Verification
- Run
[pkg-manager] run lint (check-only) to verify all ESLint rules pass.
- Run
[pkg-manager] run lint:styles to verify all Stylelint rules pass (if applicable).
- Run
[pkg-manager] run format (check-only) to verify all files are properly formatted.
- All checks MUST pass before proceeding.
Step 7: Validation Testing (REQUIRED)
Confirm all quality rules are actively working by creating intentional violations and verifying detection, auto-fix, and cleanup.
Follow the complete test strategy in references/validation-testing.md. It covers:
- ESLint TypeScript (unused imports, wrong import order, naming)
- ESLint HTML/Accessibility (missing alt text, click without keyup, non-focusable elements)
- ESLint RxJS-x (nested subscribe, unsafe takeUntil)
- Prettier (formatting violations)
- Stylelint (CSS violations)
- Commitlint (bad vs good commit messages)
- Lint-staged (pre-commit hook execution)
MUST complete the validation checklist in references/validation-testing.md before proceeding to Step 8.
Step 8: Cleanup
- Do not leave intermediate files, backups, or temporary artifacts in the user workspace.
Resources
- scripts/configure_linters.sh: Deterministic orchestrator for installation and initial setup.
- references/: Configuration examples and troubleshooting guides for each tool.
eslint-config-template.md — ESLint flat config structural skeleton — defines WHERE each plugin integrates. Read alongside the individual plugin reference files.
rxjs.md — eslint-plugin-rxjs-x shared configs and integration guide.
prettier.md — Prettier + ESLint integration.
stylelint.md — Stylelint config for CSS/SCSS Angular projects.
import-x-and-unused-imports.md — Import organization and unused import detection.
parser-config.md — TypeScript parser troubleshooting (projectService, tsconfigRootDir).
validation-testing.md — Complete test patterns for validating all quality tools.
1---2name: angular-linters3description: Workflow for setting up and managing ESLint, Stylelint, Husky, and Commitlint in Angular projects.4---56# Angular Linters & Git Hooks78This skill standardizes code quality and commit message consistency using industry-standard tools.910## Fundamental Principles1112- **References as Source of Truth**: The files within the `references/` directory are the absolute source of truth for configuration patterns. Always read the relevant reference file **BEFORE** performing any configuration step or proposing changes.13- **Strict `defineConfig` Standard**: For Angular v19+ and v21+, `defineConfig` from `eslint/config` is the mandatory wrapper for `eslint.config.js`. Do **NOT** replace it with `tseslint.config` or other wrappers, as it is the official default generated by Angular schematics.1415## Recommended Workflow1617> **IMPORTANT:** Steps 1–8 form a **continuous pipeline**. Execute them sequentially without pausing for user confirmation between steps. Only stop and try to fix if a **MUST pass** check fails.1819> **Package Manager Convention:** Throughout this skill, `[pkg-manager]` refers to the package manager confirmed during project setup (pnpm, npm, or yarn). The `[exec]` command maps to `pnpm exec` / `yarn exec` / `npx` respectively. All commands **MUST** use the confirmed manager — never default to a specific one.2021**Pre-Condition (MANDATORY):**2223> Before starting, run `git status --porcelain`. If the output is **NOT empty**, **STOP**. Tell the user: _"Your working directory has uncommitted changes. Please commit or stash them before running this skill to protect your work."_2425**Failure Recovery:**2627> If any step fails:28> 1. Run `git diff --name-only` to identify files changed by this skill.29> 2. Revert **ONLY** those files: `git checkout -- <file1> <file2> ...`30> 3. Remove **ONLY** untracked files created by this skill (config files generated by the script), not all untracked files.31> 4. **Do NOT** use `git reset --hard` or `git clean -fd` — these destroy unrelated user work.3233### Step 0: Read Project Manifest34351. Read `PROJECT_MANIFEST.json` from the project root.362. Extract `packageManager`, `style`, `angularMajorVersion`, and `rxjsLinting`.373. If the file is missing, ask the user for these values before proceeding. Do NOT assume defaults.384. Use `packageManager` as `[pkg-manager]` throughout this skill.3940### Step 1: Preparation & Installation41421. **Read References**: Read all files in the `references/` directory to understand the project's quality standards.432. **Install Tools**: Run `scripts/configure_linters.sh --style [css|scss] --package-manager [pkg-manager] --rxjs [auto|enabled|disabled]` to install all quality tools and perform initial configuration. Pass the project's style format, package manager, and RxJS linting mode so the correct dependencies are installed:4445- **CSS**: Installs `stylelint-config-standard`46- **SCSS**: Installs `stylelint-config-standard-scss` (includes SCSS syntax + plugin)4748> **IMPORTANT:** Before running the script, **verify the file content** with a quick read to confirm it contains the expected `--style` parsing logic. This prevents stale file versions from running.4950> **Note:** The `globals` package is installed as part of this setup.5152### Step 2: Verify Installation Output5354After running `configure_linters.sh`, verify what it creates:5556**Packages:**5758- Required devDependencies exist (e.g., `@angular-eslint/*`, `husky`, `lint-staged`, `@commitlint/cli`, etc.)5960**Config Files (auto-generated by script):**6162- `eslint.config.js` (from `ng add @angular-eslint/schematics`)63- `.prettierignore`64- `.stylelintignore`65- `stylelint.config.mjs` (CSS or SCSS variant based on `--style`)66- `commitlint.config.js`67- `.husky/commit-msg` (commitlint hook)68- `.husky/pre-commit` (lint-staged hook)6970> **Note:** `eslint.config.js` is the base Angular config — it will be enhanced with plugins in Step 3. The `package.json` scripts, prettier config, and lint-staged config are added by the Agent in Step 3.7172### Step 3: Iterative ESLint Configuration & Verification7374This phase adds ESLint plugins incrementally, verifying stability after each addition.7576**3.0: Add Development Scripts**7778- Add quality scripts to `package.json`. Adjust the glob pattern to match the project's style format (`*.css`, `*.scss`, or `*.{css,scss}`):7980 ```json81 {82 "lint": "ng lint",83 "lint:fix": "ng lint --fix",84 "lint:styles": "stylelint \"src/**/*.css\"",85 "lint:styles:fix": "stylelint \"src/**/*.css\" --fix",86 "format": "prettier --check \"src/**/*.{ts,html,css,json,md}\"",87 "format:fix": "prettier --write \"src/**/*.{ts,html,css,json,md}\""88 }89 ```9091- **Verify Scripts:** Run `[pkg-manager] run` to list available scripts and confirm they were added.92- **CI Usage:** Use check-only scripts (`lint`, `lint:styles`, `format`) to fail builds on issues.93- **Development:** Use auto-fix scripts (`lint:fix`, `lint:styles:fix`, `format:fix`) to fix issues locally.9495**3.1: Verify Base Configuration**9697- Run `[pkg-manager] run lint` immediately after installation.98- **MUST pass** before proceeding.99- **Note:** The base configuration from `ng add @angular-eslint/schematics` automatically includes `tsRecommended`, `templateRecommended`, and `templateAccessibility`. Verification involves ensuring these presets are present in `eslint.config.js`.100101**3.2: Add Prettier Integration**102103- Add **both** Prettier packages to `eslint.config.js` as the **last two entries** in the `defineConfig` array:104 1. `eslint-config-prettier` — Disables ESLint formatting rules that conflict with Prettier.105 2. `eslint-plugin-prettier/recommended` — Runs Prettier as an ESLint rule (so `ng lint --fix` formats too).106- Add global ignores and globals configuration (see `references/eslint-config-template.md`).107- **Prettier Config:** Modern Angular CLI may auto-generate a `"prettier"` key in `package.json`. **Do NOT create a `.prettierrc` file.** Instead:108 1. Verify the `"prettier"` key exists in `package.json`.109 2. Verify the Angular HTML parser override is in `package.json` (see `references/prettier.md`).110- Create `.prettierignore` (consult `references/prettier.md`).111- Run `[pkg-manager] run lint`.112- **MUST pass** before proceeding.113114**3.3: Add Organizational Plugins**115- Add `eslint-plugin-import-x` and `eslint-plugin-unused-imports` to `eslint.config.js` (consult `references/import-x-and-unused-imports.md`).116- Use the official `defineConfig` pattern: register `importX` as a plugin and use `extends: ['import-x/flat/recommended', 'import-x/flat/typescript']` string references.117- Add `// @ts-expect-error -- known type incompatibility between import-x and ESLint Plugin types` above the `'import-x': importX` line.118- Run `[pkg-manager] run lint`.119- **MUST pass** before proceeding.120121**3.4: Add RxJS Plugin (CONDITIONAL)**1221231. Read `rxjsLinting` from `PROJECT_MANIFEST.json` (or ask the user if no manifest):124 - `"auto"` (default): Check if `rxjs` is listed in `package.json` dependencies or devDependencies. If present, proceed. If absent, skip.125 - `"enabled"`: Always install and configure the plugin.126 - `"disabled"`: Skip entirely.1272. **If installing:** Add `eslint-plugin-rxjs-x` to `eslint.config.js` using the shared config `rxjsX.configs.recommended` (consult `references/rxjs.md`). Ensure `parserOptions.projectService: true` is set in the TypeScript block for type-aware rules.128 - Run `[pkg-manager] run lint`.129 - If type-checker errors occur, consult references and troubleshoot parser configuration.130 - **MUST pass** before proceeding.1313. **If skipping:** Inform the user: _"RxJS linting is disabled for this project. If you add RxJS later, re-run Step 3.4 or set `rxjsLinting: enabled` in the manifest."_132133### Step 4: Stylelint Verification134135- **Verify:** `stylelint.config.mjs` and `.stylelintignore` exist (auto-generated by script in Step 1).136- Run `[pkg-manager] run lint:styles` to verify configuration.137- **MUST pass** before proceeding.138139### Step 5: Git Hooks Validation140141- **Verify:** `.husky/pre-commit` and `.husky/commit-msg` exist (auto-generated by script in Step 1).142- Add a `"lint-staged"` key to `package.json` (consistent with Prettier — both inline):143 ```json144 {145 "lint-staged": {146 "*.ts": ["eslint --fix"],147 "*.html": ["eslint --fix", "prettier --write"],148 "*.css": ["stylelint --fix", "prettier --write"],149 "*.{json,md}": ["prettier --write"]150 }151 }152 ```153 > **Note:** Do NOT create a `.lintstagedrc` file. Keep it inline in `package.json` for consistency.154- **Verify:** `commitlint.config.js`, `.husky/commit-msg`, `.husky/pre-commit`, and `"lint-staged"` key in `package.json` all exist.155- Perform a test commit to verify:156 - Husky pre-commit hook triggers lint-staged.157 - Commitlint validates conventional commit messages.158- **MUST succeed** before proceeding.159160### Step 6: Final Verification161162- Run `[pkg-manager] run lint` (check-only) to verify all ESLint rules pass.163- Run `[pkg-manager] run lint:styles` to verify all Stylelint rules pass (if applicable).164- Run `[pkg-manager] run format` (check-only) to verify all files are properly formatted.165- All checks **MUST pass** before proceeding.166167### Step 7: Validation Testing (REQUIRED)168169Confirm all quality rules are actively working by creating intentional violations and verifying detection, auto-fix, and cleanup.170171Follow the complete test strategy in `references/validation-testing.md`. It covers:172173- **ESLint TypeScript** (unused imports, wrong import order, naming)174- **ESLint HTML/Accessibility** (missing alt text, click without keyup, non-focusable elements)175- **ESLint RxJS-x** (nested subscribe, unsafe takeUntil)176- **Prettier** (formatting violations)177- **Stylelint** (CSS violations)178- **Commitlint** (bad vs good commit messages)179- **Lint-staged** (pre-commit hook execution)180181**MUST complete** the validation checklist in `references/validation-testing.md` before proceeding to Step 8.182183### Step 8: Cleanup184185- Do not leave intermediate files, backups, or temporary artifacts in the user workspace.186187## Resources188189- **scripts/configure_linters.sh**: Deterministic orchestrator for installation and initial setup.190- **references/**: Configuration examples and troubleshooting guides for each tool.191 - `eslint-config-template.md` — ESLint flat config structural skeleton — defines WHERE each plugin integrates. Read alongside the individual plugin reference files.192 - `rxjs.md` — `eslint-plugin-rxjs-x` shared configs and integration guide.193 - `prettier.md` — Prettier + ESLint integration.194 - `stylelint.md` — Stylelint config for CSS/SCSS Angular projects.195 - `import-x-and-unused-imports.md` — Import organization and unused import detection.196 - `parser-config.md` — TypeScript parser troubleshooting (projectService, tsconfigRootDir).197 - `validation-testing.md` — Complete test patterns for validating all quality tools.