claude-dev-env 2.13.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +61 -0
- package/CLAUDE.md +1 -57
- package/_shared/AGENTS.md +15 -0
- package/_shared/CLAUDE.md +1 -15
- package/_shared/advisor/AGENTS.md +22 -0
- package/_shared/advisor/CLAUDE.md +1 -22
- package/_shared/pr-loop/AGENTS.md +27 -0
- package/_shared/pr-loop/CLAUDE.md +1 -27
- package/_shared/pr-loop/scripts/AGENTS.md +35 -0
- package/_shared/pr-loop/scripts/CLAUDE.md +1 -35
- package/_shared/pr-loop/scripts/code_rules_gate_parts/AGENTS.md +42 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +1 -42
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/AGENTS.md +26 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -26
- package/_shared/pr-loop/scripts/tests/AGENTS.md +44 -0
- package/_shared/pr-loop/scripts/tests/CLAUDE.md +1 -44
- package/_shared/process-tree/AGENTS.md +41 -0
- package/_shared/process-tree/CLAUDE.md +1 -41
- package/agents/AGENTS.md +31 -0
- package/agents/CLAUDE.md +1 -31
- package/agents/clean-coder.md +6 -6
- package/agents/test_agent_frontmatter.py +4 -4
- package/audit-rubrics/AGENTS.md +43 -0
- package/audit-rubrics/CLAUDE.md +1 -43
- package/audit-rubrics/category_rubrics/AGENTS.md +37 -0
- package/audit-rubrics/category_rubrics/CLAUDE.md +1 -37
- package/audit-rubrics/prompts/AGENTS.md +37 -0
- package/audit-rubrics/prompts/CLAUDE.md +1 -37
- package/bin/AGENTS.md +112 -0
- package/bin/CLAUDE.md +1 -112
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/install-constants.mjs +6 -7
- package/bin/install.mjs +24 -5
- package/bin/install.test.mjs +34 -0
- package/commands/AGENTS.md +23 -0
- package/commands/CLAUDE.md +1 -23
- package/commands/hook-log-extract.md +3 -3
- package/docs/AGENTS.md +32 -0
- package/docs/CLAUDE.md +1 -32
- package/docs/CODE_RULES.md +1 -1
- package/docs/imagegen.md +22 -0
- package/docs/references/AGENTS.md +17 -0
- package/docs/references/CLAUDE.md +1 -17
- package/hooks/AGENTS.md +31 -0
- package/hooks/CLAUDE.md +1 -31
- package/hooks/_gh_pr_author_swap_utils.py +14 -0
- package/hooks/advisory/AGENTS.md +16 -0
- package/hooks/advisory/CLAUDE.md +1 -16
- package/hooks/blocking/AGENTS.md +123 -0
- package/hooks/blocking/CLAUDE.md +1 -123
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/AGENTS.md +28 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/CLAUDE.md +1 -28
- package/hooks/blocking/code_rules_banned_identifiers.py +1 -1
- package/hooks/blocking/code_rules_dead_module_constant.py +149 -37
- package/hooks/blocking/code_rules_probe_chains.py +6 -2
- package/hooks/blocking/config/AGENTS.md +10 -0
- package/hooks/blocking/config/CLAUDE.md +1 -10
- package/hooks/blocking/gh_pr_author_restore.py +7 -2
- package/hooks/blocking/intent_only_ending_blocker.py +11 -16
- package/hooks/blocking/inventory_intent_records/AGENTS.md +26 -0
- package/hooks/blocking/inventory_intent_records/CLAUDE.md +1 -26
- package/hooks/blocking/package_inventory_stale_blocker_parts/AGENTS.md +26 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/CLAUDE.md +1 -26
- package/hooks/blocking/pii_prevention_blocker_parts/AGENTS.md +24 -0
- package/hooks/blocking/pii_prevention_blocker_parts/CLAUDE.md +1 -24
- package/hooks/blocking/tdd_enforcer_parts/AGENTS.md +30 -0
- package/hooks/blocking/tdd_enforcer_parts/CLAUDE.md +1 -30
- package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +171 -0
- package/hooks/blocking/test_code_rules_enforcer_magic_allowlist.py +1 -1
- package/hooks/blocking/test_gh_pr_author_restore.py +2 -1
- package/hooks/blocking/test_intent_only_ending_blocker.py +4 -0
- package/hooks/diagnostic/AGENTS.md +43 -0
- package/hooks/diagnostic/CLAUDE.md +1 -43
- package/hooks/diagnostic/hook_log_extractor.py +2 -2
- package/hooks/diagnostic/migrations/AGENTS.md +16 -0
- package/hooks/diagnostic/migrations/CLAUDE.md +1 -16
- package/hooks/diagnostic/queries/AGENTS.md +19 -0
- package/hooks/diagnostic/queries/CLAUDE.md +1 -19
- package/hooks/diagnostic/test_hook_log_extractor.py +2 -2
- package/hooks/git-hooks/AGENTS.md +31 -0
- package/hooks/git-hooks/CLAUDE.md +1 -31
- package/hooks/git-hooks/git_hooks_constants/AGENTS.md +21 -0
- package/hooks/git-hooks/git_hooks_constants/CLAUDE.md +1 -21
- package/hooks/git-hooks/git_hooks_constants/__init__.py +4 -6
- package/hooks/git-hooks/pre_push.py +47 -34
- package/hooks/git-hooks/test_pre_push.py +111 -7
- package/hooks/hooks_constants/AGENTS.md +104 -0
- package/hooks/hooks_constants/CLAUDE.md +1 -104
- package/hooks/hooks_constants/hook_log_extractor_constants.py +1 -2
- package/hooks/hooks_constants/task_list_loop_starter_constants.py +4 -3
- package/hooks/hooks_constants/working_style_prompt_constants.py +29 -20
- package/hooks/lifecycle/AGENTS.md +18 -0
- package/hooks/lifecycle/CLAUDE.md +1 -18
- package/hooks/observability/AGENTS.md +20 -0
- package/hooks/observability/CLAUDE.md +1 -20
- package/hooks/session/AGENTS.md +33 -0
- package/hooks/session/CLAUDE.md +1 -33
- package/hooks/session/gh_pr_author_session_cleanup.py +7 -2
- package/hooks/session/task_list_loop_starter.py +3 -3
- package/hooks/session/test_gh_pr_author_session_cleanup.py +2 -1
- package/hooks/session/test_task_list_loop_starter.py +10 -2
- package/hooks/session/test_working_style_prompt.py +9 -4
- package/hooks/validation/AGENTS.md +20 -0
- package/hooks/validation/CLAUDE.md +1 -20
- package/hooks/validators/AGENTS.md +51 -0
- package/hooks/validators/CLAUDE.md +1 -51
- package/hooks/validators/health_check.py +52 -19
- package/hooks/validators/python_style_checks.py +1 -1
- package/hooks/validators/test_health_check.py +112 -27
- package/hooks/workflow/AGENTS.md +16 -0
- package/hooks/workflow/CLAUDE.md +1 -16
- package/installable-surfaces.manifest.json +1 -0
- package/output-styles/AGENTS.md +15 -0
- package/output-styles/CLAUDE.md +1 -15
- package/package.json +2 -1
- package/rules/AGENTS.md +61 -0
- package/rules/CLAUDE.md +1 -61
- package/rules/code-standards.md +5 -9
- package/rules/doc-prose-cuts.md +1 -1
- package/scripts/AGENTS.md +62 -0
- package/scripts/CLAUDE.md +1 -62
- package/scripts/codex_compat_materializer.py +4 -0
- package/scripts/dev_env_scripts_constants/AGENTS.md +21 -0
- package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -21
- package/scripts/sync_to_cursor/AGENTS.md +23 -0
- package/scripts/sync_to_cursor/CLAUDE.md +1 -23
- package/scripts/test_validate_instruction_pairs.py +90 -0
- package/scripts/test_verify_installable_package.py +5 -1
- package/scripts/tests/AGENTS.md +33 -0
- package/scripts/tests/CLAUDE.md +1 -33
- package/scripts/tests/test_codex_compat_materializer.py +36 -1
- package/scripts/validate_instruction_pairs.py +183 -0
- package/skills/AGENTS.md +72 -0
- package/skills/CLAUDE.md +1 -72
- package/skills/_shared/AGENTS.md +44 -0
- package/skills/_shared/CLAUDE.md +1 -44
- package/skills/_shared/advisor/AGENTS.md +9 -0
- package/skills/_shared/advisor/CLAUDE.md +1 -9
- package/skills/_shared/pr-loop/AGENTS.md +50 -0
- package/skills/_shared/pr-loop/CLAUDE.md +1 -50
- package/skills/_shared/pr-loop/prompts/AGENTS.md +9 -0
- package/skills/_shared/pr-loop/prompts/CLAUDE.md +1 -9
- package/skills/_shared/pr-loop/scripts/AGENTS.md +35 -0
- package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -35
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +24 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -24
- package/skills/anthropic-plan/AGENTS.md +34 -0
- package/skills/anthropic-plan/CLAUDE.md +1 -34
- package/skills/anthropic-plan/scripts/AGENTS.md +11 -0
- package/skills/anthropic-plan/scripts/CLAUDE.md +1 -11
- package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +16 -0
- package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/CLAUDE.md +1 -16
- package/skills/anthropic-plan/templates/AGENTS.md +13 -0
- package/skills/anthropic-plan/templates/CLAUDE.md +1 -13
- package/skills/anthropic-plan/workflow/AGENTS.md +14 -0
- package/skills/anthropic-plan/workflow/CLAUDE.md +1 -14
- package/skills/auditing-claude-config/AGENTS.md +21 -0
- package/skills/auditing-claude-config/CLAUDE.md +1 -21
- package/skills/autoconverge/AGENTS.md +36 -0
- package/skills/autoconverge/CLAUDE.md +1 -36
- package/skills/autoconverge/reference/AGENTS.md +16 -0
- package/skills/autoconverge/reference/CLAUDE.md +1 -16
- package/skills/autoconverge/workflow/AGENTS.md +26 -0
- package/skills/autoconverge/workflow/CLAUDE.md +1 -26
- package/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +16 -0
- package/skills/autoconverge/workflow/autoconverge_report_constants/CLAUDE.md +1 -16
- package/skills/bugteam/AGENTS.md +30 -0
- package/skills/bugteam/CLAUDE.md +1 -30
- package/skills/bugteam/reference/AGENTS.md +20 -0
- package/skills/bugteam/reference/CLAUDE.md +1 -20
- package/skills/bugteam/reference/obstacles/AGENTS.md +24 -0
- package/skills/bugteam/reference/obstacles/CLAUDE.md +1 -24
- package/skills/bugteam/scripts/AGENTS.md +30 -0
- package/skills/bugteam/scripts/CLAUDE.md +1 -30
- package/skills/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +18 -0
- package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +1 -18
- package/skills/closeout/reference/handoff-prompt-template.md +1 -1
- package/skills/codex-review/AGENTS.md +46 -0
- package/skills/codex-review/CLAUDE.md +1 -46
- package/skills/codex-review/reference/AGENTS.md +15 -0
- package/skills/codex-review/reference/CLAUDE.md +1 -15
- package/skills/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/CLAUDE.md +1 -18
- package/skills/codex-review/test_skill_scaffold.py +3 -3
- package/skills/copilot-review/AGENTS.md +18 -0
- package/skills/copilot-review/CLAUDE.md +1 -18
- package/skills/everything-search/AGENTS.md +17 -0
- package/skills/everything-search/CLAUDE.md +1 -17
- package/skills/fresh-branch/AGENTS.md +14 -0
- package/skills/fresh-branch/CLAUDE.md +1 -14
- package/skills/grok-spawn/AGENTS.md +28 -0
- package/skills/grok-spawn/CLAUDE.md +1 -28
- package/skills/pr-converge/AGENTS.md +32 -0
- package/skills/pr-converge/CLAUDE.md +1 -32
- package/skills/pr-converge/pr_converge_skill_constants/AGENTS.md +26 -0
- package/skills/pr-converge/pr_converge_skill_constants/CLAUDE.md +1 -26
- package/skills/pr-converge/reference/AGENTS.md +28 -0
- package/skills/pr-converge/reference/CLAUDE.md +1 -28
- package/skills/pr-converge/reference/obstacles/AGENTS.md +23 -0
- package/skills/pr-converge/reference/obstacles/CLAUDE.md +1 -23
- package/skills/pr-converge/scripts/AGENTS.md +46 -0
- package/skills/pr-converge/scripts/CLAUDE.md +1 -46
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +1 -18
- package/skills/pr-converge/workflows/AGENTS.md +16 -0
- package/skills/pr-converge/workflows/CLAUDE.md +1 -16
- package/skills/prototype/reference/honest-limitations.md +1 -1
- package/skills/rebase/AGENTS.md +32 -0
- package/skills/rebase/CLAUDE.md +1 -32
- package/skills/recall/AGENTS.md +30 -0
- package/skills/recall/CLAUDE.md +1 -30
- package/skills/remember/AGENTS.md +31 -0
- package/skills/remember/CLAUDE.md +1 -31
- package/skills/reviews/SKILL.md +1 -1
- package/skills/session-log/AGENTS.md +32 -0
- package/skills/session-log/CLAUDE.md +1 -32
- package/skills/session-tidy/AGENTS.md +36 -0
- package/skills/session-tidy/CLAUDE.md +1 -36
- package/skills/skill-builder/AGENTS.md +49 -0
- package/skills/skill-builder/CLAUDE.md +1 -49
- package/skills/skill-builder/references/AGENTS.md +25 -0
- package/skills/skill-builder/references/CLAUDE.md +1 -25
- package/skills/skill-builder/references/deterministic-elements.md +1 -1
- package/skills/skill-builder/templates/AGENTS.md +14 -0
- package/skills/skill-builder/templates/CLAUDE.md +1 -14
- package/skills/skill-builder/workflows/AGENTS.md +19 -0
- package/skills/skill-builder/workflows/CLAUDE.md +1 -19
- package/skills/task-build/AGENTS.md +29 -0
- package/skills/task-build/CLAUDE.md +1 -29
- package/skills/update/AGENTS.md +38 -0
- package/skills/update/CLAUDE.md +1 -38
- package/system-prompts/AGENTS.md +17 -0
- package/system-prompts/CLAUDE.md +1 -17
- package/system-prompts/software-engineer.xml +3 -3
- package/skills/imagegen/SKILL.md +0 -21
- package/skills/imagegen/scripts/config/__init__.py +0 -1
- package/skills/imagegen/scripts/config/constants.py +0 -28
- package/skills/imagegen/scripts/imagegen.py +0 -45
- package/skills/imagegen/scripts/imagegen_core.py +0 -528
- package/skills/imagegen/scripts/test_imagegen.py +0 -204
|
@@ -1,41 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
One home for ending a spawned process together with every descendant it
|
|
4
|
-
started. Callers that capture a CLI's output import it so a grandchild can
|
|
5
|
-
never outlive the run and hold the capture pipe open.
|
|
6
|
-
|
|
7
|
-
## Consumers
|
|
8
|
-
|
|
9
|
-
| Caller | Use |
|
|
10
|
-
|---|---|
|
|
11
|
-
| `scripts/grok_headless_runner.py` | Kills a timed-out worker's tree between drain attempts |
|
|
12
|
-
| `skills/codex-review/scripts/run_codex_review.py` | Kills the review tree on timeout, then drains |
|
|
13
|
-
| `skills/codex-review/scripts/codex_usage_probe.py` | Tears the app-server tree down after the rate-limits exchange |
|
|
14
|
-
|
|
15
|
-
A skill script reaches this home the way the bugteam scripts reach
|
|
16
|
-
`_shared/pr-loop/scripts`: it puts the directory on `sys.path` and imports by
|
|
17
|
-
module name. `bin/install.mjs` copies `_shared` and `scripts` together, and
|
|
18
|
-
every install group that carries a consumer carries `_shared`, so the import
|
|
19
|
-
resolves in the repository and under `~/.claude` alike.
|
|
20
|
-
|
|
21
|
-
## Key files
|
|
22
|
-
|
|
23
|
-
| File | Purpose |
|
|
24
|
-
|---|---|
|
|
25
|
-
| `scripts/process_tree_kill.py` | `terminate_process_tree` (poll, platform tree kill, re-poll, `Popen.kill()` fallback), `kill_process_tree_by_identifier`, and `should_start_new_session` for the matching `Popen` flag |
|
|
26
|
-
| `scripts/test_process_tree_kill.py` | Behavioral tests for every public entry point here, each platform branch, each failure the helper swallows, and the `Popen.kill()` fallback |
|
|
27
|
-
| `scripts/config/process_tree_scripts_constants/process_tree_kill_constants.py` | The taskkill command, its `/T`, `/F`, and `/PID` flags, and the bound on the kill command |
|
|
28
|
-
| `scripts/pyproject.toml` | mypy configuration; `check.ps1` runs it under the `mypy-process-tree` label |
|
|
29
|
-
|
|
30
|
-
## Platform guard
|
|
31
|
-
|
|
32
|
-
Both the branch selector and the POSIX helper compare `sys.platform` against
|
|
33
|
-
the literal `"win32"`. That literal is what mypy narrows on: behind a named
|
|
34
|
-
constant, `os.getpgid`, `os.killpg`, and `signal.SIGKILL` fail type checking on
|
|
35
|
-
Windows.
|
|
36
|
-
|
|
37
|
-
## Pairing rule
|
|
38
|
-
|
|
39
|
-
`os.killpg` signals a whole process group, so a child sharing the caller's
|
|
40
|
-
group takes the caller down with it. Every `Popen` whose tree this module ends
|
|
41
|
-
passes `start_new_session=should_start_new_session()`.
|
|
1
|
+
@AGENTS.md
|
package/agents/AGENTS.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# agents
|
|
2
|
+
|
|
3
|
+
Agent definition files installed into `~/.claude/agents/` by `bin/install.mjs`. Each `.md` file defines a named subagent: its description (shown in the Claude Code UI), allowed tools, and behavioral instructions.
|
|
4
|
+
|
|
5
|
+
## Agent files
|
|
6
|
+
|
|
7
|
+
| File | Agent name | Role |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `caveman.md` | Caveman Agent | Terse voice and smallest-possible artifacts; questions premise before building |
|
|
10
|
+
| `clasp-deployment-orchestrator.md` | Clasp Deployment Orchestrator | Creates and deploys Google Apps Script projects with multiple files |
|
|
11
|
+
| `clean-coder.md` | Clean Coder | Primary code-writing agent; links the review contract, CODE_RULES, and enforcer; task-local discovery and gate-clean first writes |
|
|
12
|
+
| `code-advisor.md` | Code Advisor | Single-executor mid-run advisor (PLAN/CORRECTION/STOP as final text); distinct from session-advisor |
|
|
13
|
+
| `code-quality-agent.md` | Code Quality Agent | Multi-file code quality review across an entire diff or set of files |
|
|
14
|
+
| `deep-research.md` | Deep Research | Citation-grounded research with web search |
|
|
15
|
+
| `docs-agent.md` | Docs Agent | Documentation authoring and maintenance |
|
|
16
|
+
| `git-commit-crafter.md` | Git Commit Crafter | Stages changes, writes conventional commit messages, creates commits |
|
|
17
|
+
| `issue-tracker.md` | Issue Tracker | Primary handler for one GitHub issue action per spawn; loads the issue-tracker skill (plain-brief); returns issue numbers and URLs |
|
|
18
|
+
| `plan-packet-validator.md` | Plan Packet Validator | Fresh-context validator for workflow-generated plan packets under `docs/plans/` |
|
|
19
|
+
| `pr-description-writer.md` | PR Description Writer | Drafts PR descriptions and comments from the current diff using the canonical description and comment guides |
|
|
20
|
+
| `session-advisor.md` | Session Advisor | Standing multi-consumer reviewer; SendMessage only; returns endorse/correction/plan/stop |
|
|
21
|
+
| `skill-writer-agent.md` | Skill Writer Agent | Authors SKILL.md and companion files to skill-builder conventions; caller-agnostic authoring specialist |
|
|
22
|
+
|
|
23
|
+
## Format
|
|
24
|
+
|
|
25
|
+
Each file uses YAML frontmatter (`name`, `description`, `tools`, optional `color`) followed by a Markdown body with the agent's behavioral instructions. The `description` field appears in the Claude Code agent picker. An agent definition carries no `model` key — the caller supplies the model on each spawn.
|
|
26
|
+
|
|
27
|
+
## Adding an agent
|
|
28
|
+
|
|
29
|
+
1. Create a new `.md` file in this directory with valid frontmatter.
|
|
30
|
+
2. Run `bin/install.mjs` to copy it to `~/.claude/agents/`.
|
|
31
|
+
3. Restart Claude Code to pick up the new agent.
|
package/agents/CLAUDE.md
CHANGED
|
@@ -1,31 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Agent definition files installed into `~/.claude/agents/` by `bin/install.mjs`. Each `.md` file defines a named subagent: its description (shown in the Claude Code UI), allowed tools, and behavioral instructions.
|
|
4
|
-
|
|
5
|
-
## Agent files
|
|
6
|
-
|
|
7
|
-
| File | Agent name | Role |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| `caveman.md` | Caveman Agent | Terse voice and smallest-possible artifacts; questions premise before building |
|
|
10
|
-
| `clasp-deployment-orchestrator.md` | Clasp Deployment Orchestrator | Creates and deploys Google Apps Script projects with multiple files |
|
|
11
|
-
| `clean-coder.md` | Clean Coder | Primary code-writing agent; links AGENTS.md / CODE_RULES / enforcer; task-local discovery and gate-clean first writes |
|
|
12
|
-
| `code-advisor.md` | Code Advisor | Single-executor mid-run advisor (PLAN/CORRECTION/STOP as final text); distinct from session-advisor |
|
|
13
|
-
| `code-quality-agent.md` | Code Quality Agent | Multi-file code quality review across an entire diff or set of files |
|
|
14
|
-
| `deep-research.md` | Deep Research | Citation-grounded research with web search |
|
|
15
|
-
| `docs-agent.md` | Docs Agent | Documentation authoring and maintenance |
|
|
16
|
-
| `git-commit-crafter.md` | Git Commit Crafter | Stages changes, writes conventional commit messages, creates commits |
|
|
17
|
-
| `issue-tracker.md` | Issue Tracker | Primary handler for one GitHub issue action per spawn; loads the issue-tracker skill (plain-brief); returns issue numbers and URLs |
|
|
18
|
-
| `plan-packet-validator.md` | Plan Packet Validator | Fresh-context validator for workflow-generated plan packets under `docs/plans/` |
|
|
19
|
-
| `pr-description-writer.md` | PR Description Writer | Drafts PR descriptions and comments from the current diff using the canonical description and comment guides |
|
|
20
|
-
| `session-advisor.md` | Session Advisor | Standing multi-consumer reviewer; SendMessage only; returns endorse/correction/plan/stop |
|
|
21
|
-
| `skill-writer-agent.md` | Skill Writer Agent | Authors SKILL.md and companion files to skill-builder conventions; caller-agnostic authoring specialist |
|
|
22
|
-
|
|
23
|
-
## Format
|
|
24
|
-
|
|
25
|
-
Each file uses YAML frontmatter (`name`, `description`, `tools`, optional `color`) followed by a Markdown body with the agent's behavioral instructions. The `description` field appears in the Claude Code agent picker. An agent definition carries no `model` key — the caller supplies the model on each spawn.
|
|
26
|
-
|
|
27
|
-
## Adding an agent
|
|
28
|
-
|
|
29
|
-
1. Create a new `.md` file in this directory with valid frontmatter.
|
|
30
|
-
2. Run `bin/install.mjs` to copy it to `~/.claude/agents/`.
|
|
31
|
-
3. Restart Claude Code to pick up the new agent.
|
|
1
|
+
@AGENTS.md
|
package/agents/clean-coder.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clean-coder
|
|
3
|
-
description: "Use PROACTIVELY for ALL code generation — features, fixes, refactors, hooks, automation, and any task that produces code. Links
|
|
3
|
+
description: "Use PROACTIVELY for ALL code generation — features, fixes, refactors, hooks, automation, and any task that produces code. Links the project review contract and the CODE_RULES / enforcer / rules map; task-local discovery; high-signal gotchas so write gates pass on the first attempt."
|
|
4
4
|
tools: Read, Write, Edit, Bash, Grep, Glob, Task, Skill, SendMessage
|
|
5
5
|
color: green
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Clean Coder — Zero-Defect Code Generation
|
|
9
9
|
|
|
10
|
-
You are the definitive code-writing agent. You produce code so clean that reviewers find nothing. **
|
|
10
|
+
You are the definitive code-writing agent. You produce code so clean that reviewers find nothing. **Use the repository's checked-in review contract when present.** `../docs/CODE_RULES.md` is its compact projection; `../hooks/blocking/code_rules_enforcer.py` is hand-maintained write-time enforcement. Link these references and keep their wording authoritative.
|
|
11
11
|
|
|
12
|
-
**Announce at start:** "Using clean-coder agent —
|
|
12
|
+
**Announce at start:** "Using clean-coder agent — review contract / CODE_RULES via canonical refs."
|
|
13
13
|
|
|
14
14
|
## First Action (MANDATORY)
|
|
15
15
|
|
|
@@ -39,7 +39,7 @@ Paths are relative to this agent file (`agents/`).
|
|
|
39
39
|
|
|
40
40
|
| Concern | Canonical source |
|
|
41
41
|
|---|---|
|
|
42
|
-
| Full review criteria |
|
|
42
|
+
| Full review criteria | Project review contract (when the target repo provides one) |
|
|
43
43
|
| Compact generation checklist | `../docs/CODE_RULES.md` |
|
|
44
44
|
| Write-time gates | `../hooks/blocking/code_rules_enforcer.py` |
|
|
45
45
|
| Policy surface map | `../rules/code-standards.md` |
|
|
@@ -47,7 +47,7 @@ Paths are relative to this agent file (`agents/`).
|
|
|
47
47
|
| Windows rmtree / mkdir | `../rules/windows-filesystem-safe.md` |
|
|
48
48
|
| `gh` body files | `../rules/gh-cli-conventions.md` |
|
|
49
49
|
| Plain illustrative docstrings | `../rules/plain-illustrative-docstrings.md` |
|
|
50
|
-
| TDD / right-size |
|
|
50
|
+
| TDD / right-size | Review contract Tests + Design; `CODE_RULES.md` §7–§8 |
|
|
51
51
|
|
|
52
52
|
Type-ignore rule (AGENTS Types): a `# type: ignore` needs a second trailing `#` justification of at least five characters. Prefer a real type when available.
|
|
53
53
|
|
|
@@ -88,7 +88,7 @@ def fetch_with_retries(url: str) -> str:
|
|
|
88
88
|
## Scope, TDD, and outcomes
|
|
89
89
|
|
|
90
90
|
- **Scope:** only lines the task needs. Surface out-of-scope CODE_RULES drift after the task, do not expand silently.
|
|
91
|
-
- **TDD:** when tests are in scope, red → green → refactor (
|
|
91
|
+
- **TDD:** when tests are in scope, red → green → refactor (review contract Tests / `CODE_RULES` §8).
|
|
92
92
|
- **Outcome:** code that passes `/check` and the write gates on the first write; self-documenting names; paired tests for new production paths.
|
|
93
93
|
|
|
94
94
|
## When to use this agent
|
|
@@ -79,7 +79,7 @@ import pytest
|
|
|
79
79
|
import yaml
|
|
80
80
|
|
|
81
81
|
ACCEPTED_FRONTMATTER_KEYS = frozenset({"name", "description", "tools", "color"})
|
|
82
|
-
|
|
82
|
+
INSTRUCTION_ALIAS_FILENAMES = frozenset({"AGENTS.md", "CLAUDE.md"})
|
|
83
83
|
FRONTMATTER_FENCE_LINE = "---"
|
|
84
84
|
MATERIALIZER_MODULE_NAME = "codex_compat_materializer"
|
|
85
85
|
MATERIALIZER_MODULE_PATH = (
|
|
@@ -113,20 +113,20 @@ def _extract_frontmatter_block(markdown_text: str) -> str | None:
|
|
|
113
113
|
|
|
114
114
|
@cache
|
|
115
115
|
def _agent_definition_candidate_paths() -> tuple[Path, ...]:
|
|
116
|
-
"""Return every markdown file in this directory that
|
|
116
|
+
"""Return every markdown file in this directory that is an agent definition.
|
|
117
117
|
|
|
118
118
|
This is the floor the parametrized checks are measured against: each of
|
|
119
119
|
these files is expected to yield a frontmatter block, so one that does not
|
|
120
120
|
is a broken definition rather than a file to pass over.
|
|
121
121
|
|
|
122
122
|
Returns:
|
|
123
|
-
Every `*.md` path in this directory
|
|
123
|
+
Every agent-definition `*.md` path in this directory, sorted.
|
|
124
124
|
"""
|
|
125
125
|
agents_directory = Path(__file__).parent
|
|
126
126
|
return tuple(
|
|
127
127
|
each_markdown_file
|
|
128
128
|
for each_markdown_file in sorted(agents_directory.glob("*.md"))
|
|
129
|
-
if each_markdown_file.name
|
|
129
|
+
if each_markdown_file.name not in INSTRUCTION_ALIAS_FILENAMES
|
|
130
130
|
)
|
|
131
131
|
|
|
132
132
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# audit-rubrics
|
|
2
|
+
|
|
3
|
+
Audit rubrics for the PR-loop code-review suite. The rubrics define the 17 bug categories (A–Q), their sub-bucket decompositions, and the prompt templates agents use during an audit pass. Installed into `~/.claude/audit-rubrics/` by `bin/install.mjs`.
|
|
4
|
+
|
|
5
|
+
## Key file
|
|
6
|
+
|
|
7
|
+
| File | Purpose |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `audit-categories.json` | Machine-readable A-Q schema: id, title, slug, and sub-bucket id/axis pairs; single source for rubric and prompt skeleton parity |
|
|
10
|
+
| `source-material-section-types.md` | Lookup table for how to chunk an artifact into sections for an audit prompt; covers code PRs, docs, SQL schemas, config files, and more |
|
|
11
|
+
|
|
12
|
+
## Subdirectories
|
|
13
|
+
|
|
14
|
+
| Entry | Description |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `category_rubrics/` | One `.md` per category (A–Q): defines what the category audits, example findings, and a sub-bucket decomposition table |
|
|
17
|
+
| `prompts/` | One `.md` per category: the ready-to-use audit prompt template an agent inlines the artifact into |
|
|
18
|
+
|
|
19
|
+
## Categories
|
|
20
|
+
|
|
21
|
+
| ID | Name |
|
|
22
|
+
|---|---|
|
|
23
|
+
| A | API contract verification |
|
|
24
|
+
| B | Selector engine compatibility |
|
|
25
|
+
| C | Resource cleanup |
|
|
26
|
+
| D | Scoping and ordering |
|
|
27
|
+
| E | Dead code |
|
|
28
|
+
| F | Silent failures |
|
|
29
|
+
| G | Bounds and overflow |
|
|
30
|
+
| H | Security boundaries |
|
|
31
|
+
| I | Concurrency |
|
|
32
|
+
| J | Code-rules compliance |
|
|
33
|
+
| K | Codebase conflicts |
|
|
34
|
+
| L | Behavior equivalence |
|
|
35
|
+
| M | Producer-consumer cardinality |
|
|
36
|
+
| N | Test name / scenario verifier |
|
|
37
|
+
| O | Docstring vs implementation drift |
|
|
38
|
+
| P | Name vs behavior contract |
|
|
39
|
+
| Q | Cross-surface claim consistency |
|
|
40
|
+
|
|
41
|
+
## Breaking-change rule
|
|
42
|
+
|
|
43
|
+
Adding a sub-bucket to a category rubric requires updating `audit-categories.json` and the matching prompt template in `prompts/` in the same commit, then running `audit_category_schema.py --validate`. Skills that reference category IDs (`bugteam`, `findbugs`) rely on stable sub-bucket IDs (A1, A2, … Q-n). Worked examples stay in the rubric markdown only; they are outside the schema.
|
package/audit-rubrics/CLAUDE.md
CHANGED
|
@@ -1,43 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Audit rubrics for the PR-loop code-review suite. The rubrics define the 17 bug categories (A–Q), their sub-bucket decompositions, and the prompt templates agents use during an audit pass. Installed into `~/.claude/audit-rubrics/` by `bin/install.mjs`.
|
|
4
|
-
|
|
5
|
-
## Key file
|
|
6
|
-
|
|
7
|
-
| File | Purpose |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `audit-categories.json` | Machine-readable A-Q schema: id, title, slug, and sub-bucket id/axis pairs; single source for rubric and prompt skeleton parity |
|
|
10
|
-
| `source-material-section-types.md` | Lookup table for how to chunk an artifact into sections for an audit prompt; covers code PRs, docs, SQL schemas, config files, and more |
|
|
11
|
-
|
|
12
|
-
## Subdirectories
|
|
13
|
-
|
|
14
|
-
| Entry | Description |
|
|
15
|
-
|---|---|
|
|
16
|
-
| `category_rubrics/` | One `.md` per category (A–Q): defines what the category audits, example findings, and a sub-bucket decomposition table |
|
|
17
|
-
| `prompts/` | One `.md` per category: the ready-to-use audit prompt template an agent inlines the artifact into |
|
|
18
|
-
|
|
19
|
-
## Categories
|
|
20
|
-
|
|
21
|
-
| ID | Name |
|
|
22
|
-
|---|---|
|
|
23
|
-
| A | API contract verification |
|
|
24
|
-
| B | Selector engine compatibility |
|
|
25
|
-
| C | Resource cleanup |
|
|
26
|
-
| D | Scoping and ordering |
|
|
27
|
-
| E | Dead code |
|
|
28
|
-
| F | Silent failures |
|
|
29
|
-
| G | Bounds and overflow |
|
|
30
|
-
| H | Security boundaries |
|
|
31
|
-
| I | Concurrency |
|
|
32
|
-
| J | Code-rules compliance |
|
|
33
|
-
| K | Codebase conflicts |
|
|
34
|
-
| L | Behavior equivalence |
|
|
35
|
-
| M | Producer-consumer cardinality |
|
|
36
|
-
| N | Test name / scenario verifier |
|
|
37
|
-
| O | Docstring vs implementation drift |
|
|
38
|
-
| P | Name vs behavior contract |
|
|
39
|
-
| Q | Cross-surface claim consistency |
|
|
40
|
-
|
|
41
|
-
## Breaking-change rule
|
|
42
|
-
|
|
43
|
-
Adding a sub-bucket to a category rubric requires updating `audit-categories.json` and the matching prompt template in `prompts/` in the same commit, then running `audit_category_schema.py --validate`. Skills that reference category IDs (`bugteam`, `findbugs`) rely on stable sub-bucket IDs (A1, A2, … Q-n). Worked examples stay in the rubric markdown only; they are outside the schema.
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# audit-rubrics/category_rubrics
|
|
2
|
+
|
|
3
|
+
One rubric file per audit category (A–Q). Each file defines what the category covers, gives concrete examples of findings, and provides the sub-bucket decomposition an audit agent uses to structure its pass.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
| File | Category |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `category-a-api-contracts.md` | A — API contract verification |
|
|
10
|
+
| `category-b-selector-engine-compat.md` | B — Selector engine compatibility |
|
|
11
|
+
| `category-c-resource-cleanup.md` | C — Resource cleanup |
|
|
12
|
+
| `category-d-scoping-and-ordering.md` | D — Scoping and ordering |
|
|
13
|
+
| `category-e-dead-code.md` | E — Dead code |
|
|
14
|
+
| `category-f-silent-failures.md` | F — Silent failures |
|
|
15
|
+
| `category-g-bounds-and-overflow.md` | G — Bounds and overflow |
|
|
16
|
+
| `category-h-security-boundaries.md` | H — Security boundaries |
|
|
17
|
+
| `category-i-concurrency.md` | I — Concurrency |
|
|
18
|
+
| `category-j-code-rules-compliance.md` | J — Code-rules compliance |
|
|
19
|
+
| `category-k-codebase-conflicts.md` | K — Codebase conflicts |
|
|
20
|
+
| `category-l-behavior-equivalence.md` | L — Behavior equivalence |
|
|
21
|
+
| `category-m-producer-consumer-cardinality.md` | M — Producer-consumer cardinality |
|
|
22
|
+
| `category-n-test-name-scenario-verifier.md` | N — Test name / scenario verifier |
|
|
23
|
+
| `category-o-docstring-vs-impl-drift.md` | O — Docstring vs implementation drift |
|
|
24
|
+
| `category-p-name-vs-behavior-contract.md` | P — Name vs behavior contract |
|
|
25
|
+
| `category-q-cross-surface-claims.md` | Q — Cross-surface claim consistency |
|
|
26
|
+
|
|
27
|
+
## Rubric structure
|
|
28
|
+
|
|
29
|
+
Each file has:
|
|
30
|
+
- A plain-language description of what the category audits
|
|
31
|
+
- Concrete finding examples
|
|
32
|
+
- A companion-reference pointer to `../source-material-section-types.md`
|
|
33
|
+
- A sub-bucket decomposition table with stable IDs (A1, A2, …) and the concrete checks each bucket requires
|
|
34
|
+
|
|
35
|
+
## Relationship to prompts/
|
|
36
|
+
|
|
37
|
+
`category_rubrics/` is the human-readable reference. `prompts/` holds the agent-ready prompt templates that inline the same sub-bucket list in a structured prompt format. Keep both in sync when sub-buckets change.
|
|
@@ -1,37 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
One rubric file per audit category (A–Q). Each file defines what the category covers, gives concrete examples of findings, and provides the sub-bucket decomposition an audit agent uses to structure its pass.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
| File | Category |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `category-a-api-contracts.md` | A — API contract verification |
|
|
10
|
-
| `category-b-selector-engine-compat.md` | B — Selector engine compatibility |
|
|
11
|
-
| `category-c-resource-cleanup.md` | C — Resource cleanup |
|
|
12
|
-
| `category-d-scoping-and-ordering.md` | D — Scoping and ordering |
|
|
13
|
-
| `category-e-dead-code.md` | E — Dead code |
|
|
14
|
-
| `category-f-silent-failures.md` | F — Silent failures |
|
|
15
|
-
| `category-g-bounds-and-overflow.md` | G — Bounds and overflow |
|
|
16
|
-
| `category-h-security-boundaries.md` | H — Security boundaries |
|
|
17
|
-
| `category-i-concurrency.md` | I — Concurrency |
|
|
18
|
-
| `category-j-code-rules-compliance.md` | J — Code-rules compliance |
|
|
19
|
-
| `category-k-codebase-conflicts.md` | K — Codebase conflicts |
|
|
20
|
-
| `category-l-behavior-equivalence.md` | L — Behavior equivalence |
|
|
21
|
-
| `category-m-producer-consumer-cardinality.md` | M — Producer-consumer cardinality |
|
|
22
|
-
| `category-n-test-name-scenario-verifier.md` | N — Test name / scenario verifier |
|
|
23
|
-
| `category-o-docstring-vs-impl-drift.md` | O — Docstring vs implementation drift |
|
|
24
|
-
| `category-p-name-vs-behavior-contract.md` | P — Name vs behavior contract |
|
|
25
|
-
| `category-q-cross-surface-claims.md` | Q — Cross-surface claim consistency |
|
|
26
|
-
|
|
27
|
-
## Rubric structure
|
|
28
|
-
|
|
29
|
-
Each file has:
|
|
30
|
-
- A plain-language description of what the category audits
|
|
31
|
-
- Concrete finding examples
|
|
32
|
-
- A companion-reference pointer to `../source-material-section-types.md`
|
|
33
|
-
- A sub-bucket decomposition table with stable IDs (A1, A2, …) and the concrete checks each bucket requires
|
|
34
|
-
|
|
35
|
-
## Relationship to prompts/
|
|
36
|
-
|
|
37
|
-
`category_rubrics/` is the human-readable reference. `prompts/` holds the agent-ready prompt templates that inline the same sub-bucket list in a structured prompt format. Keep both in sync when sub-buckets change.
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# audit-rubrics/prompts
|
|
2
|
+
|
|
3
|
+
Agent-ready audit prompt templates, one per category (A–Q). An agent inlines the artifact under review into the `[INLINE THE FULL ARTIFACT HERE]` placeholder and runs the prompt as-is.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
| File | Category |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `category-a-api-contracts.md` | A — API contract verification |
|
|
10
|
+
| `category-b-selector-engine-compat.md` | B — Selector engine compatibility |
|
|
11
|
+
| `category-c-resource-cleanup.md` | C — Resource cleanup |
|
|
12
|
+
| `category-d-scoping-and-ordering.md` | D — Scoping and ordering |
|
|
13
|
+
| `category-e-dead-code.md` | E — Dead code |
|
|
14
|
+
| `category-f-silent-failures.md` | F — Silent failures |
|
|
15
|
+
| `category-g-bounds-and-overflow.md` | G — Bounds and overflow |
|
|
16
|
+
| `category-h-security-boundaries.md` | H — Security boundaries |
|
|
17
|
+
| `category-i-concurrency.md` | I — Concurrency |
|
|
18
|
+
| `category-j-code-rules-compliance.md` | J — Code-rules compliance |
|
|
19
|
+
| `category-k-codebase-conflicts.md` | K — Codebase conflicts |
|
|
20
|
+
| `category-l-behavior-equivalence.md` | L — Behavior equivalence |
|
|
21
|
+
| `category-m-producer-consumer-cardinality.md` | M — Producer-consumer cardinality |
|
|
22
|
+
| `category-n-test-name-scenario-verifier.md` | N — Test name / scenario verifier |
|
|
23
|
+
| `category-o-docstring-vs-impl-drift.md` | O — Docstring vs implementation drift |
|
|
24
|
+
| `category-p-name-vs-behavior-contract.md` | P — Name vs behavior contract |
|
|
25
|
+
| `category-q-cross-surface-claims.md` | Q — Cross-surface claim consistency |
|
|
26
|
+
|
|
27
|
+
## Prompt structure
|
|
28
|
+
|
|
29
|
+
Each template:
|
|
30
|
+
- Scopes the audit to one category only (skip the others)
|
|
31
|
+
- Lists all sub-buckets from the matching `category_rubrics/` file
|
|
32
|
+
- Requires each sub-bucket to produce at least one Shape A finding OR one Shape B proof-of-absence with three or more adversarial probes
|
|
33
|
+
- Uses `find` as the finding ID prefix (single-pass audits) rather than `loop<N>-<K>`
|
|
34
|
+
|
|
35
|
+
## Relationship to category_rubrics/
|
|
36
|
+
|
|
37
|
+
`prompts/` is the executable form; `category_rubrics/` is the reference form. When a sub-bucket decomposition changes in a rubric, update the matching prompt in the same commit.
|
|
@@ -1,37 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Agent-ready audit prompt templates, one per category (A–Q). An agent inlines the artifact under review into the `[INLINE THE FULL ARTIFACT HERE]` placeholder and runs the prompt as-is.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
| File | Category |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `category-a-api-contracts.md` | A — API contract verification |
|
|
10
|
-
| `category-b-selector-engine-compat.md` | B — Selector engine compatibility |
|
|
11
|
-
| `category-c-resource-cleanup.md` | C — Resource cleanup |
|
|
12
|
-
| `category-d-scoping-and-ordering.md` | D — Scoping and ordering |
|
|
13
|
-
| `category-e-dead-code.md` | E — Dead code |
|
|
14
|
-
| `category-f-silent-failures.md` | F — Silent failures |
|
|
15
|
-
| `category-g-bounds-and-overflow.md` | G — Bounds and overflow |
|
|
16
|
-
| `category-h-security-boundaries.md` | H — Security boundaries |
|
|
17
|
-
| `category-i-concurrency.md` | I — Concurrency |
|
|
18
|
-
| `category-j-code-rules-compliance.md` | J — Code-rules compliance |
|
|
19
|
-
| `category-k-codebase-conflicts.md` | K — Codebase conflicts |
|
|
20
|
-
| `category-l-behavior-equivalence.md` | L — Behavior equivalence |
|
|
21
|
-
| `category-m-producer-consumer-cardinality.md` | M — Producer-consumer cardinality |
|
|
22
|
-
| `category-n-test-name-scenario-verifier.md` | N — Test name / scenario verifier |
|
|
23
|
-
| `category-o-docstring-vs-impl-drift.md` | O — Docstring vs implementation drift |
|
|
24
|
-
| `category-p-name-vs-behavior-contract.md` | P — Name vs behavior contract |
|
|
25
|
-
| `category-q-cross-surface-claims.md` | Q — Cross-surface claim consistency |
|
|
26
|
-
|
|
27
|
-
## Prompt structure
|
|
28
|
-
|
|
29
|
-
Each template:
|
|
30
|
-
- Scopes the audit to one category only (skip the others)
|
|
31
|
-
- Lists all sub-buckets from the matching `category_rubrics/` file
|
|
32
|
-
- Requires each sub-bucket to produce at least one Shape A finding OR one Shape B proof-of-absence with three or more adversarial probes
|
|
33
|
-
- Uses `find` as the finding ID prefix (single-pass audits) rather than `loop<N>-<K>`
|
|
34
|
-
|
|
35
|
-
## Relationship to category_rubrics/
|
|
36
|
-
|
|
37
|
-
`prompts/` is the executable form; `category_rubrics/` is the reference form. When a sub-bucket decomposition changes in a rubric, update the matching prompt in the same commit.
|
|
1
|
+
@AGENTS.md
|
package/bin/AGENTS.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# bin
|
|
2
|
+
|
|
3
|
+
The installer and its companion modules. Running `npx claude-dev-env` (or `node bin/install.mjs`) copies package files into the managed root (`~/.claude/` by default; `CLAUDE_CONFIG_DIR` or `--target` selects another), merges hook entries into that root's `settings.json`, installs Git hooks, and writes `~/.mypy.ini` under the process home.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
| File | Purpose |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `install.mjs` | Main installer: builds a read-only plan via `install-plan.mjs`, then runs mutations inside `install-transaction.mjs` recovery (copy content directories, merge hooks, install skills, prune, git hooks, mypy.ini); routes `CLAUDE_HOME`, the manifest path, and `~/.mypy.ini` through `resolve-install-root.mjs`; resolves single or multi-profile targets before mutation and writes one ownership manifest per target |
|
|
10
|
+
| `resolve-install-root.mjs` | Pure install-root resolver: precedence `--target` > `CLAUDE_CONFIG_DIR` > `~/.claude`, separator-boundary containment, and the declared external allowlist for `~/.mypy.ini` |
|
|
11
|
+
| `select-install-targets.mjs` | Pure target selection for main-default, explicit `--target`, and `--profile`/`--profiles`; rejects ambiguous or duplicate targets; builds per-target manifest records with `targetIdentity` and `managedRoot` |
|
|
12
|
+
| `install-plan.mjs` | Read-only install and uninstall plans: install preflight (managed root, source conflicts, Python, settings when hooks install) and uninstall preflight (settings JSON before removal, removable vs skipped manifest records), freezes plans E2/F execute |
|
|
13
|
+
| `install-transaction.mjs` | Install, update, and uninstall transaction journal: captures prior settings, manifest, managed files, and `core.hooksPath`, restores them on failure, and supports fault injection phases for recovery tests |
|
|
14
|
+
| `install.transaction.test.mjs` | Unit and sandbox installer tests for snapshot/restore and fault phases (`after_file_staging`, `after_settings_write`, `after_git_config`, `after_manifest_write`) |
|
|
15
|
+
| `install.uninstall-transaction.test.mjs` | Uninstall plan preflight and recovery: malformed/non-object settings fail before removal, each fault phase restores files/settings/manifest/`core.hooksPath`, retry succeeds, selected-root containment |
|
|
16
|
+
| `install.profile-root.test.mjs` | Contract tests for the install-root resolver: precedence, containment boundary, external allowlist, and the install.mjs import smoke check |
|
|
17
|
+
| `install-constants.mjs` | The named values `install.mjs` reads: `SKIPPED_SOURCE_ENTRY_NAMES` and `SKIPPED_SOURCE_FILE_EXTENSIONS` for the build artifacts the source walk leaves behind, `RUN_BACKUP_DIRECTORY_NAME_PATTERN` for the timestamp shape a run backup directory carries, `MANAGED_SKILLS_DIRECTORY_NAME` and `MANAGED_HOOKS_DIRECTORY_NAME` for the directory name each of those trees carries in a package source and under `~/.claude` — read by the copy loops, the hooks.json reads, the git-hook shims, the mypy configuration, and the prunes alike — `SETTINGS_FILE_NAME` for the settings file the merge, the retired-hook prune, and the uninstall purge share, and `MYPY_INI_FILE_NAME` for the home-directory file `install_mypy_ini.mjs` writes (also imported by `resolve-install-root.mjs`) |
|
|
18
|
+
| `ever-shipped-skills.mjs` | Static `EVER_SHIPPED_SKILL_NAMES` set of every top-level skill directory name the package has shipped; the installer subtracts the current skill set from it to prune retired skills left under `~/.claude/skills` |
|
|
19
|
+
| `expand_home_directory_tokens.mjs` | Expands residual `$HOME` / `${HOME}` / `~/` tokens in settings.json hook and statusLine commands to absolute home paths at install time (literal-safe for homes that contain `$`) |
|
|
20
|
+
| `git_hooks_installer.mjs` | Installs or updates the `pre-commit`, `pre-push`, and `post-commit` Git hooks in the user's git config; writes hook scripts that delegate to the installed Python hooks |
|
|
21
|
+
| `install_mypy_ini.mjs` | Writes `~/.mypy.ini` with settings that make mypy find the hooks package and enforce strict type checking |
|
|
22
|
+
| `install.test.mjs` | Unit tests for `install.mjs` — covers conflict detection, interpreter detection, settings merging, the settings shapes the installer never wrote — those every hook walk hands back untouched, and the shipped-event value the merge replaces with a warning — the source-artifact skip in `collectFiles`, the case-only rename decision and the `copyTree` copy that acts on it, the retired-hook diff and settings prune, the stale-file prune: the manifest diff, path-key case folding, emptied-parent cleanup, and the warn-and-keep paths, and backup retention: the sweep a moved-content run drives, the empty root a run whose moves failed gives up, and the populated root retention keeps |
|
|
23
|
+
| `install.profiles.test.mjs` | Profile target-selection and per-target ownership manifest contract tests (main-default, multi-profile, ambiguity/duplicate rejection, help text) |
|
|
24
|
+
| `install.plan.test.mjs` | Read-only plan and preflight tests: zero-write plan construction, source-conflict and missing-Python fail-closed, settings check only when hooks install, tolerant broken-manifest, invalid managed root, mutation-kind list for E2 |
|
|
25
|
+
| `install.prune.test.mjs` | End-to-end prune tests that run the real installer against a sandbox `HOME` — retired-skill, retired-hook, and stale-file moves into one timestamped backup, the settings entry a retired hook loses, the top-level paths every root's diff leaves alone, the manifest record a failed move keeps, the full-install and resolved-dependency gates, backup retention, and the uninstall: the `~/.mypy.ini` removal, the containment guard, and nested-directory cleanup |
|
|
26
|
+
| `git_hooks_installer.test.mjs` | Tests for `git_hooks_installer.mjs` |
|
|
27
|
+
| `install_mypy_ini.test.mjs` | Tests for `install_mypy_ini.mjs` |
|
|
28
|
+
|
|
29
|
+
## Source build artifacts
|
|
30
|
+
|
|
31
|
+
`collectFiles` walks the package source and skips the artifacts a contributor's tooling writes beside it: the entry names `__pycache__`, `.ruff_cache`, `.pytest_cache`, `.mypy_cache`, `node_modules`, `.DS_Store`, and any file ending `.pyc` or `.pyo`. A skipped directory takes everything under it out of the walk. The `files` negations in `package.json` (`!**/__pycache__/**`, `!**/*.py[cod]`, the cache directories, `!**/*.log`, `!**/*.egg-info/**`) keep the same artifacts out of the published tarball, and `.npmignore` carries those patterns for tooling that reads it — keep the two in step. An `npx` install reads a clean tree; the walk covers a local `node bin/install.mjs` run against a working tree that holds the artifacts.
|
|
32
|
+
|
|
33
|
+
The skip and the cleanup of artifacts an earlier install copied are one code path. A `.pyc` a prior manifest records under any managed root sits outside the set the walk returns, so the next full install reads it as stale, moves it into that run's backup root, and drops it from the manifest the run writes.
|
|
34
|
+
|
|
35
|
+
## Copying a file whose name changed letter case
|
|
36
|
+
|
|
37
|
+
`copyTree` renames a destination entry that differs from the shipped file name only in letter case to the shipped name, then copies. On a case-insensitive volume `copyFileSync` writes its bytes through whichever entry the filesystem resolves the path to, so a package shipping `README.md` over an installed `Readme.md` would fill the installed entry and leave the earlier spelling standing. The rename runs first because `renameSync` inside one directory is atomic: a run interrupted between the rename and the copy leaves the file present under the shipped name holding the earlier content, which the next install overwrites.
|
|
38
|
+
|
|
39
|
+
The decision reads the destination directory's entry names, cached one listing per directory for the whole copy run. On a case-sensitive volume the two names are two files, so the rename is skipped and each name keeps its own content. `caseOnlyRenameSourceName(shippedName, existingNames, options)` holds the decision, and `options.isCaseInsensitive` carries the platform answer as a value so a test drives either branch on a host of either kind.
|
|
40
|
+
|
|
41
|
+
## Retired-skill prune
|
|
42
|
+
|
|
43
|
+
The full-install prune renames a retired skill directory into a timestamped backup rather than deleting it. Each pruned directory is renamed to `~/.claude/.claude-dev-env-pruned/<timestamp>/skills/<skill-name>/`, a backup root outside `~/.claude/skills` so a backed-up directory is never re-discovered as a skill. The `skills/` segment mirrors `~/.claude`, matching the layout the stale-file prune writes, so one recovery point reads as a copy of the tree it came from. One run shares one timestamped root, so a run leaves one recovery point. A rename that fails leaves the directory in place with a logged warning and never falls back to deletion, so a prune failure costs at most a cosmetic leftover.
|
|
44
|
+
|
|
45
|
+
Matching is by directory name alone, so a user-authored directory whose name collides with a retired skill is backed up as if it were that skill. A directory is pruned when the prior install's manifest recorded it or the ever-shipped set names it, and the current install did not just write it. A name absent from all three of those sets, together with `~/.claude/skills/_shared`, is left in place. Recovery of a wrongly-matched directory runs until the next pruning install, which keeps its own backup and retires the rest.
|
|
46
|
+
|
|
47
|
+
## Stale-file prune
|
|
48
|
+
|
|
49
|
+
A full install also moves aside a file under a managed root that the run leaves unwritten. `copyTree` adds and overwrites but never removes, so every root the installer writes carries the same drift, and the prune covers all of them: `rules`, `docs`, `commands`, `agents`, `system-prompts`, `scripts`, `_shared`, `audit-rubrics`, `skills`, and `hooks` — the names in `MANAGED_TOP_LEVEL_DIRECTORY_NAMES`.
|
|
50
|
+
|
|
51
|
+
Nothing moves unless a prior install recorded it. That single rule is what makes covering ten roots as safe as covering one: the installer reads the file list from `~/.claude/.claude-dev-env-manifest.json`, subtracts every file the run copied across all source roots, and moves what remains.
|
|
52
|
+
|
|
53
|
+
The prune runs once per root, each call confined to its own root. Per-root iteration gives the containment guard and the emptied-parent walk the root that owns each file, and it settles `_shared`: `~/.claude/_shared` and `~/.claude/skills/_shared` are distinct absolute paths, so the `_shared` call and the `skills` call each see their own files and no path enters two diffs. Each root's content lands under `~/.claude/.claude-dev-env-pruned/<timestamp>/<root-name>/<relative>`, so the backup mirrors `~/.claude`. Every prune in a run shares that one timestamped root. A recorded path under no managed root — `~/.claude/CLAUDE.md`, `settings.json`, the manifest itself, and the `~/.mypy.ini` that sits in the home directory beside `~/.claude` — reaches no root's diff and stays where it is. The install summary reports the skills root's own count on the `skills:` line and the sum across roots on its own line.
|
|
54
|
+
|
|
55
|
+
The manifest diff limits the move to files the installer itself wrote. Runtime-generated content — a Python `__pycache__` entry, a ruff cache, a log — and any file a user authored under a managed root stay in place, because no install recorded them. Path comparison ignores letter case on Windows and macOS, so a package shipping `README.md` over an installed `Readme.md` keeps the bytes the run just wrote. A directory or a link standing where the manifest records a file is skipped with a warning, so the mover never renames a whole tree and never follows a link out of `~/.claude`. A directory emptied by a move is removed, walking up to the root the file sat under. A move that fails logs a warning and leaves the file in place, so a prune failure costs at most a stale file. The installer records each such path in the fresh manifest when the file is still on disk, so the file stays inside the next full install's diff and gets another attempt.
|
|
56
|
+
|
|
57
|
+
A missing or unreadable manifest, or one carrying no file list, holds the stale-file prune for that run: with no record of what an install wrote, the run has nothing to diff against.
|
|
58
|
+
|
|
59
|
+
A run writes both manifest keys — the file list and the skill-name list — wholesale from what it just installed only when the prunes ran that run and read the prior record all the way through, so the next diff reads as "the package stopped shipping this". Every other run unions what it wrote onto the prior lists: a scoped `--only` install, a full install holding its prunes behind an unresolved dependency group, and a run whose prune step ends early with a logged warning. The union keeps every entry a later prune needs to spot a stale file or a retired skill, and keeps `--uninstall` able to name the whole tree. The prune itself bounds the lists: a stale path leaves the record on the first full install that moves it aside.
|
|
60
|
+
|
|
61
|
+
## Retired-hook entries in settings.json
|
|
62
|
+
|
|
63
|
+
A hook script under `~/.claude/hooks` carries a second reference: the `settings.json` entry that runs it. A full install removes that entry in the same run that moves the script aside, and removes it first — a `settings.json` naming a script that has left the hooks directory makes every session start invoke a missing file.
|
|
64
|
+
|
|
65
|
+
The retired set comes from the manifest diff alone: the hook files a prior install recorded that this run leaves unwritten, each taken relative to `~/.claude/hooks`. A script the run still writes stays out of the set, and a path no install of ours recorded never enters it, so a user-authored hook is out of reach of the prune. Each command is matched on the anchored `/.claude/hooks/<relative>` tail the merge uses to tell this installer's entries from a user's, so a command whose path is a retired tail plus a suffix (`retired_gate.py.bak`) names another file and stays.
|
|
66
|
+
|
|
67
|
+
The walk covers every event type the settings file holds rather than the ones the current `hooks.json` names, so an entry under an event type the package stopped shipping is reached too. A matcher group left empty is dropped, and an event type left empty goes with it. The file is written once, and only when an entry left it, so a run that retires no hook leaves `settings.json` byte-identical.
|
|
68
|
+
|
|
69
|
+
Every settings walk recognizes the shapes the installer writes and steps around the rest, so a hand-edited or third-party `settings.json` carries an install through rather than ending it. A matcher group carrying no `hooks` array and a hook entry whose `command` is not a string survive every walk untouched. An event type whose value is not an array of groups survives this prune and the uninstall purge; the merge replaces that value with the group list it ships for that event type, warning with the event type named so the user can recover the value from their own history. An event type the package ships no groups for keeps whatever value the file holds.
|
|
70
|
+
|
|
71
|
+
## Backup retention
|
|
72
|
+
|
|
73
|
+
A run that moves content into `~/.claude/.claude-dev-env-pruned/<timestamp>/` then retires the other run backups, so the directory holds the one recovery point closest to what sits on disk. The retired-skill prune and the stale-file prune each report how many moves succeeded, and their sum is the signal the sweep answers to. The sweep removes a direct child whose name matches the installer's timestamp shape (`2026-07-25T18-04-11-923Z`), which leaves anything else under the pruned-backup directory in place, along with the directory itself. A removal that fails logs a warning and the sweep carries on, so retention never ends an install. The install output names the count when the sweep removes anything.
|
|
74
|
+
|
|
75
|
+
A run that moves nothing sweeps nothing, so every recovery point the user holds stays where it is. `moveIntoRunBackup` creates the directories leading to a backup path before it renames, so a run whose every move fails — the antivirus scanner or open editor case — leaves that timestamped root standing empty. Retention clears it with `rmdirSync` alone, depth first, so a directory holding anything survives every step.
|
|
76
|
+
|
|
77
|
+
## Uninstall
|
|
78
|
+
|
|
79
|
+
`--uninstall` builds a read-only uninstall plan, captures a recovery snapshot, then removes each file the plan lists.
|
|
80
|
+
|
|
81
|
+
Settings JSON is validated before any removal. A malformed or non-object `settings.json` fails closed with the managed files still on disk. Each manifest record passes a containment guard: the path resolves under `~/.claude`, or it names the `~/.mypy.ini` the install writes in the home directory. Every other record is skipped with a warning and counted. Skipping keeps one malformed record — hand-edited, or written by an installer that ran against a different home — from stranding the user with a half-removed install. The purge removes every legitimate record, clears the manifest, and reports the skipped count.
|
|
82
|
+
|
|
83
|
+
The uninstall runs inside the same snapshot/restore journal as install: prior settings, manifest, managed files, and `core.hooksPath` restore when a later phase fails, so a retry starts from a complete ownership record. The journal is discarded only after a successful commit.
|
|
84
|
+
|
|
85
|
+
Removing a file leaves its directory a candidate for cleanup. Once the file loop ends, the purge walks up from each such directory to the managed top-level directory the file sits under (`MANAGED_TOP_LEVEL_DIRECTORY_NAMES`), removing each directory it finds empty. That reaches a nested tree such as `skills/<name>/scripts/`. A record under no managed root gets no walk, so `~/.claude` itself is never a stop root and a directory the installer never wrote stays. A separate pass drops each managed top-level directory the purge empties.
|
|
86
|
+
|
|
87
|
+
## Prune gates
|
|
88
|
+
|
|
89
|
+
Every prune runs behind the same two gates: a full install, and every declared dependency group resolved. When any dependency group fails to resolve, all of them are skipped for the whole run with a logged notice naming the unresolved group. An unresolved dependency contributes no skills to the installed set, so a live skill that a dependency package supplies would look retired and its files would look stale; holding every prune until each dependency resolves keeps that skill's files in place and keeps their manifest records, so a run with every dependency resolved can still prune them.
|
|
90
|
+
|
|
91
|
+
## Key exports from install.mjs
|
|
92
|
+
|
|
93
|
+
| Export | Description |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `CONTENT_DIRECTORIES` | Array of package subdirectory names copied verbatim to `~/.claude/` |
|
|
96
|
+
| `MANAGED_TOP_LEVEL_DIRECTORY_NAMES` | The content directories plus `skills` and `hooks`; the stale-file prune walks it to give each root its own diff, and the uninstall purge reads it to find the root a recorded file belongs to |
|
|
97
|
+
| `collectFiles(directory)` | Lists every file under a source directory, skipping the build-artifact names and extensions in `install-constants.mjs` |
|
|
98
|
+
| `pythonCandidatesForPlatform(platform)` | Returns ordered Python interpreter candidates to probe; `py -3` first on Windows to avoid Microsoft Store alias issues |
|
|
99
|
+
| `isWindowsStorePythonStub(path)` | Returns true when the path resolves to the non-spawnable WindowsApps stub |
|
|
100
|
+
| `interpreterCommandFromPath(path)` | Formats an absolute interpreter path as a settings.json hook command prefix |
|
|
101
|
+
| `collectPackageSourceConflicts(dir)` | Returns any unmerged git conflicts in the package source; installer aborts when any exist |
|
|
102
|
+
| `pruneStaleInstalledFiles(priorFiles, currentFiles, destinationRoot, backupRoot, options)` | Moves each manifest-recorded file under the destination root that the run leaves unwritten into the run's backup root; returns `{ prunedCount, failedPaths }`. `options.isCaseInsensitive` drives path-key case folding, defaulting to this host's filesystem; `options.managedHomeDirectory` sets the home the containment guard tests against, defaulting to `~/.claude` |
|
|
103
|
+
| `copyTree(sourceBase, destBase, options)` | Copies every file under a source directory, renaming a destination entry that differs from the shipped name only in letter case to the shipped name first; returns `{ created, updated, paths }`. `options.isCaseInsensitive` drives that rename, defaulting to this host's filesystem |
|
|
104
|
+
| `caseOnlyRenameSourceName(shippedName, existingNames, options)` | Returns the existing directory entry a shipped file name would overwrite through a case-only spelling difference, or null; `options.isCaseInsensitive` defaults to this host's filesystem |
|
|
105
|
+
| `retiredManagedHookRelativePaths(priorFiles, currentFiles, hooksRoot)` | Returns the hook script paths a prior install recorded under the hooks root that this run leaves unwritten, each relative to that root |
|
|
106
|
+
| `pruneRetiredHookEntriesFromSettings(settingsPath, retiredPaths)` | Removes each settings.json entry running a retired managed hook script, writing the file only when an entry left it; returns the removed count |
|
|
107
|
+
| `retainNewestRunBackupOnly(runBackupRoot, didRunMoveContent)` | Retires every run backup sitting beside the run's own when `didRunMoveContent` holds; clears the run's empty root with `rmdirSync` when it does not |
|
|
108
|
+
| `comparisonKeyForPath(path, options)` | Builds the key two paths are compared through: resolved, forward-slashed, and lowercased when `options.isCaseInsensitive` holds — which defaults to true on Windows and macOS |
|
|
109
|
+
|
|
110
|
+
## Install groups
|
|
111
|
+
|
|
112
|
+
`install.mjs` defines install groups (`core`, `journal`) plus any dependency groups discovered from `package.json` `dependencies`. The `core` group installs skills, all hooks, and the content directories. `journal` installs only its skill set.
|