| name | edit-spec |
| description | Edit a vigiles .spec.ts to change a compiled instruction file (CLAUDE.md / AGENTS.md) — add, modify, or remove a rule, section, command, or key file. Use whenever you need to change a CLAUDE.md/AGENTS.md that carries a vigiles hash (edit the spec, never the artifact), including adding a new enforce()/check()/guidance() rule. |
| argument-hint | <what to change — e.g., "add a rule about error handling" or "update the testing section"> |
Edit a .spec.ts file to update the project's instruction files. The spec is the source of truth — CLAUDE.md and AGENTS.md are compiled build artifacts that must not be edited directly.
Arguments
$ARGUMENTS — What the user wants to change. Examples:
- "add a rule about always using the custom logger"
- "update the architecture section"
- "add src/services/auth.ts to key files"
- "add npm run lint to commands"
- "change the testing guidance"
Instructions
Step 1: Find the Spec
Look for spec files in the repo root:
CLAUDE.md.spec.ts — source for CLAUDE.md
AGENTS.md.spec.ts — source for AGENTS.md
- Any
*.spec.ts matching instruction files
If no spec exists: if there's a hand-written CLAUDE.md, suggest the
adopt-spec skill; otherwise suggest npx vigiles init to scaffold one.
Step 2: Read and Understand the Spec
Read the spec file. It's a TypeScript file that exports a claude() call with these fields:
import { claude, enforce, guidance, check, every } from "vigiles/spec";
export default claude({
target: "CLAUDE.md",
sections: {
positioning: "What this project does...",
architecture: "How the codebase is structured...",
},
keyFiles: {
"src/index.ts": "Main entry point",
},
commands: {
"npm run build": "Compile the project",
"npm test": "Run all tests",
},
rules: {
"no-any": enforce(
"@typescript-eslint/no-explicit-any",
"Use unknown and narrow with type guards.",
),
"test-pairing": check(
every("src/**/*.service.ts").has("{name}.test.ts"),
"Every service must have tests.",
),
"research-first": guidance("Google unfamiliar APIs before implementing."),
},
});
Step 3: Make the Changes
Based on what the user asked for:
Adding a rule (this absorbs the old generate-rule skill):
- Classify the rule from the request:
enforce() — a linter rule can back it. Check the project's linter configs
(ESLint, Ruff, Clippy, Pylint, RuboCop, Stylelint) for a matching rule; also
consider an architectural tool (ast-grep, Dependency Cruiser, Steiger). If
uncertain whether a rule exists, ask the user rather than guessing.
check() — a filesystem structural convention ("every X needs a Y"). Only
for file-pairing; never for code content.
guidance() — can't be mechanically enforced (subjective conventions,
process rules, migration context).
- For
enforce(): use the real linter rule name (e.g. eslint/no-console,
@typescript-eslint/no-explicit-any, ruff/T201).
- Add to the
rules object with a kebab-case key derived from the intent,
preserving alphabetical order if the existing rules are alphabetical. Import
any new builders needed (e.g. check and every for the first check()).
Updating a section:
- Edit the string in
sections. Sections are plain strings or tagged template literals with file(), cmd(), ref() for verified references
- Do NOT add
# or ## headers inside sections — they break the document structure
Adding a key file or command:
- Add to
keyFiles or commands. The compiler verifies these exist at compile time
- For commands: must match a script in
package.json
- For key files: must exist on disk
Step 4: Compile
After editing the spec, run:
npx vigiles compile
This regenerates the compiled instruction file(s). Review the output for any errors:
stale-file — a key file path doesn't exist
stale-command — a command isn't in package.json
invalid-rule — a linter rule doesn't exist or is disabled
section-has-header — a section contains # headers (break into separate named sections)
Step 5: Verify
npx vigiles lint
If the vigiles plugin is installed (/plugin marketplace add zernie/vigiles then /plugin install vigiles@vigiles, or npx vigiles init), the PostToolUse hook recompiles automatically after you save the spec.
Important
- Do what's asked; don't silently escalate enforcement. Add the rule the user asked for. If making it an
enforce() would need a linter-config edit or a plugin install (a cost), or if it could fail a clean CI, say so and let the user choose — don't change linter config or flip on strict / workflow gating on your own. A pure win (a rule that's already enabled) you can just apply. The strengthen skill owns guidance() → enforce() upgrades.
- Never edit CLAUDE.md or AGENTS.md directly — they have a vigiles hash comment and are build artifacts
- The spec is TypeScript — you get type checking, autocomplete, and verified references
enforce() rules are verified — the compiler checks the rule exists AND is enabled in your linter config
- Sections must not contain
# or ## headers — use separate named sections instead