Claude Code's (and Copilot's) native plugin installer has zero awareness of .apm/ nesting -- it convention-scans only flat skills/, agents/, commands/, hooks.json at each plugin's root. Confirmed via strings on the installed claude binary and live installs of git@holocron/gitea@holocron/kyberforge@ holocron, all reporting Skills(0) Agents(0) Hooks(0) post ADR-0015's apm conversion. Root cause (apm_cli/core/plugin_manifest.py): apm's plugin.json compiler deliberately strips skills/agents/commands keys, assuming the host already auto-discovers those convention directories -- it has no model of .apm/ being host-visible at all. Separately, apm's own bundle exporter (apm_cli/bundle/plugin_exporter.py, behind `apm pack --format plugin`) implements the correct .apm/ -> flat mapping, but only ever targeted build/<name>-<version>/, a path nothing in marketplace.json's source: points at. scripts/sync-plugin-content.sh wraps that bundle exporter and copies its agents/, skills/, commands/, instructions/, extensions/, and merged hooks.json back into each plugin's own root as a second tracked compiled-output category -- same governance status as .claude-plugin/plugin.json: generated from .apm/, never hand-edited. tests/ subdirectories are excluded from the mirror (dev fixtures, not host-visible runtime content; several hardcode a relative repo-root walk-up sized for the .apm/-nested depth, which breaks when duplicated one level shallower). Applied for real across all 6 plugins and verified two ways: `claude plugin validate --strict` passes on every real plugin directory, and a live `claude --plugin-dir <path> -p "list skills/agents"` behavioral test confirms content is now actually discovered. Also, from the same issue #90 review round: - scripts/check-manifests.sh pointed at each plugin's root-level plugin.json (checking skills/hooks/mcpServers/agents pointer fields) -- that file was a stale near-duplicate of .claude-plugin/plugin.json nothing else read or wrote, now deleted across all 6 plugins. check-manifests.sh is rewritten to validate .claude-plugin/plugin.json instead, and drops the pointer-field checks entirely (nothing to check -- those fields are correctly absent by design). Content-presence drift is now check-plugin-content-sync's job, a new pre-push hook wired in .pre-commit-config.yaml. docs/adr/0017 records the root cause and decision in full, including two rejected alternatives (patching plugin.json's path fields directly -- apm's compiler strips them on every run; pointing marketplace.json at apm pack's build/ output -- a version-suffixed non-source directory nothing can install from without an extra build step). ADR-0015 and CONTEXT.md are updated to point at it. Refs: #90
124 lines
5.6 KiB
Markdown
124 lines
5.6 KiB
Markdown
---
|
|
name: pc-run
|
|
description: >
|
|
Use when the user wants to run pre-commit hooks, install git hooks, update
|
|
hook versions, or maintain the pre-commit cache. Triggers on: "run
|
|
pre-commit", "run all hooks", "check everything passes", "install hooks",
|
|
"wire hooks into git", "update hook versions", "autoupdate", "bump revs",
|
|
"clean the cache", "rebuild environments", "gc", "why is my hook failing",
|
|
"hooks aren't running". Do not use for creating or editing
|
|
`.pre-commit-config.yaml` — use `pc-author` for that.
|
|
|
|
compatibility: Requires pre-commit installed and available on PATH.
|
|
|
|
metadata:
|
|
category: devtools
|
|
source_keys:
|
|
- context7-pre-commit-com
|
|
- pre-commit-com
|
|
|
|
allowed-tools: Bash Read
|
|
---
|
|
|
|
## Gotchas
|
|
|
|
- Hooks not running on `git commit` almost always means `pre-commit install` was never run in this clone. Git hooks are per-clone — they are not committed to the repo.
|
|
- When a hook modifies files (e.g. `trailing-whitespace`, `end-of-file-fixer`), the commit is blocked intentionally — the staged version is stale. The fix is `git add -u && git commit`. Do NOT call `pre-commit install -f` here; that is for overwriting existing hooks, not re-staging.
|
|
- `pre-commit autoupdate` modifies `.pre-commit-config.yaml` in-place. Re-read the file after calling it to show the user the updated `rev` values.
|
|
- The `SKIP` env var requires exact hook `id` values, comma-separated, no spaces: `SKIP=check-yaml,gitleaks git commit -m "msg"`. A space after the comma silently skips nothing.
|
|
- Never use `git commit --no-verify` (or `-n`) to bypass a failing hook. Hooks are the automated QA gate; bypassing them breaks the pipeline. Diagnose and fix the failure instead — see the hook-specific guidance below and in `references/failure-patterns.md`.
|
|
- A stages mismatch — hook stage not installed — means the hook was added to the config but `pre-commit install` was not re-run with the correct `-t` flags. Hooks in stages not listed under `default_install_hook_types` will never fire.
|
|
|
|
## Route
|
|
|
|
Determine intent from the user's request, then execute the matching operation:
|
|
|
|
| User intent | Operation |
|
|
|---|---|
|
|
| "run", "check", "verify", "test hooks" | `pre-commit run --all-files` (default) |
|
|
| "staged", "simulate commit" | `pre-commit run` (staged files only) |
|
|
| "CI", "changed files only", "diff range" | `pre-commit run --from-ref <base> --to-ref <head>` — prefer this over `--all-files` on large repos |
|
|
| "install", "set up hooks", "wire into git" | `pre-commit install` — see Install |
|
|
| "pre-create environments", "install-hooks", "warm cache" | `pre-commit install-hooks` — see Install |
|
|
| "remove hooks", "uninstall", "tear down pre-commit" | `pre-commit uninstall` |
|
|
| "autoupdate", "update versions", "bump revs" | `pre-commit autoupdate` |
|
|
| "gc", "garbage collect" | `pre-commit gc` |
|
|
| "clean", "wipe cache", "rebuild from scratch" | `pre-commit clean` — see Clean |
|
|
|
|
If the intent is ambiguous, default to `pre-commit run --all-files`.
|
|
|
|
## Run
|
|
|
|
Default: `pre-commit run --all-files`. Never silently run staged-only.
|
|
|
|
```bash
|
|
pre-commit run --all-files
|
|
```
|
|
|
|
**When hooks fail**, read the output and:
|
|
1. Identify which hook failed and the specific cause. Be concrete: "gitleaks blocked `config.json` (high-entropy string on line 12)", not just "gitleaks failed".
|
|
2. Suggest a concrete next step. Common patterns are in `references/failure-patterns.md`.
|
|
3. Do NOT auto-fix code files. Do NOT modify `.pre-commit-config.yaml`. Those are the user's or `pc-author`'s responsibility.
|
|
|
|
If the user asks to run only staged files: `pre-commit run` (no `--all-files`).
|
|
If the user names a specific hook: `pre-commit run <hook-id>`.
|
|
|
|
## Install
|
|
|
|
Only run when the user explicitly asks to install or set up hooks.
|
|
|
|
Before running, check for existing hook files:
|
|
|
|
```bash
|
|
ls .git/hooks/
|
|
```
|
|
|
|
If any hook files exist (e.g. a hand-written `pre-commit`), `pre-commit install` does NOT refuse or error — it defaults to migration mode, which runs the existing hook and pre-commit's hooks both. Only `-f` replaces the existing hook file outright, and that replacement is not reversible via `pre-commit uninstall` — uninstall only removes pre-commit from `.git/hooks/`, it does not restore whatever hand-written hook `-f` overwrote. If files are present, tell the user: "Existing hook files found at `.git/hooks/<names>`. Plain `pre-commit install` will run both; `pre-commit install -f` will overwrite them permanently instead. Proceed with plain install, or overwrite?" Wait for confirmation before using `-f`.
|
|
|
|
```bash
|
|
pre-commit install
|
|
```
|
|
|
|
Re-run with `-t` flags when `default_install_hook_types` was changed or when hooks in non-default stages aren't firing:
|
|
|
|
```bash
|
|
pre-commit install -t pre-commit -t pre-push -t commit-msg
|
|
```
|
|
|
|
To pre-create all hook environments without running hooks (useful for CI warm-up or first-time setup):
|
|
|
|
```bash
|
|
pre-commit install-hooks
|
|
```
|
|
|
|
To remove pre-commit from `.git/hooks/` entirely:
|
|
|
|
```bash
|
|
pre-commit uninstall
|
|
```
|
|
|
|
## Autoupdate
|
|
|
|
```bash
|
|
pre-commit autoupdate
|
|
```
|
|
|
|
After it completes, read `.pre-commit-config.yaml` and report which `rev` values changed. If the user wants to pin to exact SHAs (for reproducibility): `pre-commit autoupdate --freeze`.
|
|
|
|
## Clean and GC
|
|
|
|
**`gc`** — removes only unused cached environments. Safe to run at any time:
|
|
```bash
|
|
pre-commit gc
|
|
```
|
|
|
|
**`clean`** — wipes the entire cache at `~/.cache/pre-commit`. All hook environments will be re-downloaded on next run. Require explicit confirmation before running:
|
|
|
|
> "This will wipe the entire pre-commit cache. All hook environments will be re-downloaded on next run. Proceed?"
|
|
|
|
Wait for the user to say yes before executing:
|
|
|
|
```bash
|
|
pre-commit clean
|
|
```
|