Files
holocron/plugins/git/skills/pc-author/SKILL.md
Defame1297 38f1ba4e03 fix(kyberforge): bridge apm content to Claude Code's flat plugin discovery
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
2026-08-13 16:59:03 +00:00

5.1 KiB

name, description, allowed-tools, metadata
name description allowed-tools metadata
pc-author Use when the user wants to create, add hooks to, remove hooks from, update, or configure .pre-commit-config.yaml. Triggers on: "set up pre-commit", "add a hook", "remove this hook", "configure pre-commit", "create a pre-commit config", "disable trailing whitespace hook", "add shellcheck", "update my pre-commit config", even if the user does not name pre-commit explicitly. Do not use for running hooks, installing git hooks, or bumping revision pins — use pc-run for those. Bash Read Write Edit
category source_keys
devtools
context7-pre-commit-com
pre-commit-com
context7-pre-commit-hooks
pre-commit-hooks-github

Gotchas

  • rev must be an immutable tag or commit SHA — never a branch name. pre-commit autoupdate breaks silently on branches.
  • Fixers (trailing-whitespace, end-of-file-fixer, pretty-format-json) modify files but do NOT auto-stage them. The commit is blocked; the user must re-stage and recommit. Warn when adding fixers.
  • pre-commit validate-config catches YAML structure errors but does NOT check whether hook ids exist in the target repo's manifest, and does NOT download or run hooks. It is fast; run it after every write.
  • When removing a hook leaves its repo block with zero hooks, delete the entire repo block — an empty hooks: [] causes validate-config to fail.
  • language: system and language: script are deprecated names. Use language: unsupported and language: unsupported_script for new local hooks.

Route

Check before acting:

  • .pre-commit-config.yaml does not exist → Create from scratch
  • File exists → Modify existing

Create from scratch

  1. Run a shallow extension scan:
    git ls-files | grep -oE '\.[a-z]+$' | sort | uniq -c | sort -rn
    
  2. Read references/hooks-by-language.md to map detected extensions to recommended hooks. For a minimal starting point instead of a full recommendation set, pre-commit sample-config > .pre-commit-config.yaml prints a small starter config to build on.
  3. State the proposed config in full before writing. Wait for user confirmation.
  4. Write .pre-commit-config.yaml.
  5. Run pre-commit validate-config. If non-zero: show the error, fix it, re-validate. Never leave a broken config.

Modify existing

Read .pre-commit-config.yaml first. Note any stale rev values (see Rev staleness below) but do not change them.

Adding a hook

  1. Run a shallow extension scan to detect languages in the repo:
    git ls-files | grep -oE '\.[a-z]+$' | sort | uniq -c | sort -rn
    
  2. Read references/hooks-by-language.md for the correct repo URL, rev, and recommended args for any hook before writing.
  3. Check for duplicates — if the same hook ID or equivalent tool already exists in the config, say so and stop.
  4. To sanity-check a hook against the repo's actual files before committing to it in config, smoke-test it with pre-commit try-repo <repo-url> <hook-id> --verbose (or a local path for hooks under development). This runs the hook without writing anything.
  5. If the hook's source repo already exists in the config, add the hook under that repo block. Otherwise append a new repo block.
  6. State the proposed addition. Wait for confirmation.
  7. Write. Run pre-commit validate-config. If non-zero: show error, fix, re-validate.

Removing a hook

  1. Identify the hook entry and its repo block.
  2. State what will be removed: hook ID, and whether the parent repo block will also be deleted (if it would have zero hooks remaining). Wait for confirmation.
  3. Remove the hook entry. If the repo block now has zero hooks remaining, remove the entire repo block.
  4. Write. Run pre-commit validate-config. If non-zero: revert the edit, show the error, and stop — do not leave a broken config (removal edits are not safely auto-fixable, unlike a bad new hook block, which can usually be corrected in place).

Configuring top-level keys

Only when the user explicitly asks. Valid keys: fail_fast, default_stages, default_language_version, minimum_pre_commit_version, exclude, files, default_install_hook_types.

State the proposed change and wait for confirmation before writing.

Rev staleness

When reading the config, for each repo listed in references/hooks-by-language.md, compare its rev in the user's config against the rev in that file. Flag any mismatch as potentially outdated and tell the user to run pc-run to autoupdate. Repos not in the reference cannot be checked — skip them silently. Do not modify rev values yourself.

The reference table's pins can themselves go stale between updates — treat a mismatch as a prompt to check, not a certainty. pre-commit autoupdate (via pc-run) is the authoritative source for what the current rev actually is.

Scope boundary

This skill manages .pre-commit-config.yaml only. It does not:

  • Author .pre-commit-hooks.yaml (publishing hooks for external consumers)
  • Run pre-commit install
  • Execute hooks or run the test suite
  • Bump rev values

For those operations, use pc-run.