agentleFS
EJRyan89EJRyan89/coding-agent-skills/CLAUDE.md

coding-agent-skills

CLAUDE.md2 starsChanged 18 days agoMITView on GitHub

This project packages portable Claude Code skills and a guarded deployer. Each rule below is stated once; the section it points at holds how validation, a hook, or CI enforces it. The deployer is a standard-library Python 3.11.4+ package and supports Windows. On Linux the deployer and the whole validation suite run and deployable.yml deploys onto a fresh Ubuntu runner, but Linux support is not claimed until the maintainer's runtime canary runs the skills there; macOS is refused. Configured paths…

  • Commits and pushes

The file

Show its rules and text

We split this CLAUDE.md into the rules it gives an agent

13 rules. About 0 are common, 4 are distinctive, and 9 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Every entry point, a module whose __main__ block calls run_main, states its codes in an Exit status: docstring table, and each command has …

    line 19
  2. Very specific:

    Do not modify installed skills under ~/.claude/skills, installed agents under ~/.claude/agents, generated adapters under ~/.agents/skills, …

    line 46
  3. Very specific:

    Use an isolated temporary home for deployment fixtures and canaries: --canary-home, or Paths built on a temporary directory.

    line 47
  4. Very specific:

    Never source or execute configuration files.

    line 49
  5. Distinctive:

    Treat tokens used in Bash, PowerShell, JSON, YAML, or other executable/structured contexts according to that context.

    line 50
  6. Distinctive:

    Do not add personal paths, internal organization names, credentials, or generated deployer state.

    line 53
  7. Distinctive:

    Do not change the source ID without an explicit ownership-migration plan.

    line 54
  8. Very specific:

    Start a task with python tools/worktrees.py new <kind> <name>, which creates .claude/worktrees/<kind>-<name> (gitignored) on branch …

    line 61
  9. Very specific:

    When one session orchestrates several task sessions, a session in the hub keeps their pull requests merging with the shepherd-pull-requests …

    line 64
  10. Distinctive:

    Never pop or drop a stash you did not create: the stash stack is shared by every worktree.

    line 65
  11. Very specific:

    Every .ps1 and Markdown PowerShell fence validation reads passes Invoke-ScriptAnalyzer -Severity Warning,Error, and every Markdown Bash …

    line 83
  12. Very specific:

    Every skill with executable files must include an executable regression suite under its scripts/ directory.

    line 91
  13. Very specific:

    Keep DOCUMENTATION_FILES and DOCUMENTATION_DIRECTORIES in tests/run_validation.py to files no suite executes.

    line 93

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

Coding Agent Skills Development

This project packages portable Claude Code skills and a guarded deployer. Each rule below is stated once; the section it points at holds how validation, a hook, or CI enforces it.

The deployer is a standard-library Python 3.11.4+ package and supports Windows. On Linux the deployer and the whole validation suite run and deployable.yml deploys onto a fresh Ubuntu runner, but Linux support is not claimed until the maintainer's runtime canary runs the skills there; macOS is refused. Configured paths are absolute drive-letter paths on Windows and absolute POSIX paths on Linux, and rendered Bash and PowerShell are validated with Git Bash on Windows or the system Bash on Linux, ShellCheck, and PowerShell. Keep every operating-system-specific behavior in deployer/platform_support.py so Unix support is added there without touching the pipeline. The exceptions are what ejryan89-skill-core holds because a skill's script needs it too, and the deployer reads from there: the program lookup and PYTHON (which every skill renders as {{PYTHON}}) in executable_locator.py, the process tree in job_tree.py, the process probe in process_identity.py, is_reserved_device_name in device_names.py, is_link_or_junction in link_probe.py, path_key in path_keys.py, the form a path is compared in, and INSTALL_HINT in pdf_tool.py. A module states a sanctioned exception beside the code it excuses, as a module-level PLATFORM_ALLOWED = {token: reason}; "One platform seam" in docs/design.md says what each exception holds and what validation refuses outside the seam.

Architecture

  • skills/<name>/ contains immutable skill templates. Never render configuration into this source tree.
  • agents/<name>.md holds Claude Code subagent definitions that skills declare in agent_deps; the deployer installs them to ~/.claude/agents.
  • skills/<name>/scripts/ is the only permitted location for a skill's executable files. Keep substantial executable logic out of Markdown.
  • deploy-meta/<name>.json declares each skill's required variables, shared dependencies, same-source skill dependencies, selection visibility, opt-in status, the external tools it runs, required or optional, and its runtime support (full, partial, or none for each of Claude Code, Codex, and Copilot CLI, naming the capability a runtime lacks), in the one layout "Metadata" in docs/adding-a-skill.md gives. skills/ejryan89-skill-core/scripts/runtime_support.py catalogues the runtimes, the capabilities each offers, and the reader of that declaration; validation holds each declaration to what the skill's frontmatter needs.
  • Skills may run only standard commands or declared tools. A Python script names the program of every command it starts where validation can read it, or states why beside the code as a module-level COMMANDS_ALLOWED = {scope: reason}; see "Commands skills may run" in docs/adding-a-skill.md. deployer/tools.py is the single catalogue of those tools, the deployment prerequisites, and the runtimes python deploy.py verify lists, with their version floors; python deploy.py check (deployer/check.py) reports them, and deployer/source_commit.py records the source commit in the manifest's source entry at each deployment.
  • source.json may group selectable skills into atomic bundles, and its renamed records each renamed skill's old name, whose owned copy the next deployment moves to the new one ("Renaming a skill" in docs/adding-a-skill.md); the manifest records requested roots separately from their expanded dependency closure and each skill's deployed skill_deps. A skipped or preserved skill keeps its recorded transitive skill dependencies and their shared assets and agents.
  • skills/<asset> contains shared assets declared in source.json as either owner or dependency.
  • skills/ejryan89-skill-core/ is a hidden skill and the one home of the repository's shared Python: skill scripts, the deployer, and tools/ all import its modules from skills/ejryan89-skill-core/scripts, and nothing copies them. It holds one module per concern, among them console.py, whose run_main(main) is the one call in every entry point's __main__ block and ends an unhandled exception with a FAILED <type>: <message> line and exit 1, never a traceback unless the entry point asks, as deploy.py's --debug does; frontmatter.py; github_client.py and git_client.py, whose GitHubClient and GitClient every gh call and every git call from a skill's Python go through; bounded_process.py, under both, which runs a command with no stdin but given bytes, no prompt, none of git's repository-selecting variables but the GIT_INDEX_FILE that run_bounded's index_file keyword alone sets, which neither client takes, and a time limit, and, when its caller asks, a bound on the output it keeps and an end, through a process tree the caller supplies, to every process the command started that has not left its process group; skill_roots.py, the skills directories a script must not write inside, and sibling_scripts, the one lookup of a sibling skill's scripts; executable_locator.py; flat_text.py, the one whitespace flattener for text a script prints on one line; and xml_reader.py, the one reader of untrusted XML, which refuses a DOCTYPE or ENTITY declaration. "Script results" in docs/adding-a-skill.md states the runner's and the clients' contracts.
  • A dependent declares ejryan89-skill-core in skill_deps, puts ../ejryan89-skill-core/scripts on sys.path, and reaches every other sibling it declares through sibling_scripts, as the suites under tests/ and the modules under tools/ do after their own statement. deployer/__init__.py holds the deployer's one statement putting skills/ejryan89-skill-core/scripts first on sys.path, located from its own file and never through the configured source path; a tools/ module writes the same statement above its ejryan89-skill-core imports. The deployer and ejryan89-skill-core import nothing outside the standard library, the deployer, and ejryan89-skill-core, and ejryan89-skill-core nothing from the deployer or tools/; "Validation" in docs/adding-a-skill.md states every import rule validation holds.
  • deploy.py is the single command-line entry point. deployer/cli.py routes it, and deployer/arguments.py declares its argparse parsers.
  • Every entry point, a module whose __main__ block calls run_main, states its codes in an Exit status: docstring table, and each command has a fault driver in tests/malformed_input/faults_*.py or a NOT_RUN reason; see "Script results" in docs/adding-a-skill.md.
  • python deploy.py configure runs deployer/configure.py, which writes a strictly parsed, source-specific configuration under ~/.claude/deployer/config/. deployer/config.py is the single declaration of configured and derived variables.
  • Any other deploy.py invocation runs deployer/pipeline.py: it renders selected skills in memory, validates the result, applies journaled multi-root changes, and records source-scoped ownership in ~/.claude/skills/.deploy-manifest.json. pipeline.py orchestrates a run (the lock, recovery, the journal, and the manifest commit) over deployer/selection.py (the menu, --all, and the checks a selection must pass), deployer/plan.py (the per-item plan the dry run prints and the deployment carries out, and the ownership checks before rendering), deployer/report.py (report lines and their labels, shared with check and verify), and deployer/migrate.py (--migrate-from). deployer/kinds.py describes each kind of item (skills, shared assets, runtime adapters, agents) once, and every pass over them iterates it, except where a kind differs, which its module states beside the code as a module-level KINDS_ALLOWED = {pass: reason}; "One table of item kinds" in docs/design.md names the exceptions and what validation refuses. deployer/context.py holds a run's options, selection, and manifest state. Authoritative skills live under ~/.claude/skills; thin generated runtime adapters live under ~/.agents/skills.
  • Every mutating filesystem operation of deploy.py and the deployer goes through deployer/fsops.py, whose fsops.extract_archive is the one extraction; tests inject failures by replacing those functions. A sanctioned exception, for throwaway files and directories under the system temporary directory only, is stated beside the code as a module-level FSOPS_ALLOWED = {token: reason}; "One write point" in docs/design.md says what validation counts as a write.
  • Never copy a module-level definition or constant between non-test Python files under skills/, deployer/, tools/, .claude/skills/, or tests/validation/: import one copy, and move a module more than one part of the repository needs to ejryan89-skill-core. A copy that must stay is sanctioned beside the code in every module that holds it, as a module-level DUPLICATION_ALLOWED = {name: reason} whose reason names every other file that holds the copy; "Validation" in docs/adding-a-skill.md says what counts as a copy.
  • skills/ejryan89-skill-core/scripts/frontmatter.py is the one reader for skill and agent frontmatter, imported as frontmatter by skill scripts, the deployer, tools/, and the tests.
  • python deploy.py verify (deployer/verify.py) checks, without starting a model, that Codex and Copilot CLI each find every manifest-owned runtime adapter, enabled and not shadowed. deployer/discovery.py reads each runtime's skill listing (Copilot's copilot skill list --json, Codex's app-server skills/list request) and is shared with tools/runtime_canary.py.
  • tests/deployer/test_*.py are the deployer suites; their isolated fixture repositories and homes live in tests/deployer/harness.py, which fails a test whose deployment changes anything under its source, and one whose expected refusal changes the home, unless the test states why with changes_home. tests/deployer/test_invariants.py shows both comparisons failing and passing, and holds that a permanent backup survives later deployments and the uninstall.
  • docs/skills.md is the skill reference. tools/skill_reference.py generates its summary table and the first block of each skill's section, and the "Runtime support" table, from SKILL.md frontmatter and metadata; the explanation after each block is hand-written. After changing a skill's frontmatter or metadata, run python tools/skill_reference.py --write; validation fails while the reference is stale.
  • tools/runtime_prompts.py renders, from fixtures and with no model, each prompt a skill's or a repository skill's script writes for a subagent at runtime, one sample per role, into docs/runtime-prompts/<skill>/<role>.txt, with the throwaway folder as <temp> and the checkout as <source>, where audit-skill measures it. After changing such a prompt, run python tools/runtime_prompts.py --write; validation fails while a sample is stale.
  • tools/plugin_build.py assembles the Claude Code plugins from skills/, agents/, and their metadata, each described by its entry in .claude-plugin/marketplace.json, into a folder under the temporary directory or reproducible archives, and never into the source tree: a plugin is a build output, never committed, and validation holds each plugin's files to their sources ("Validation" in docs/adding-a-skill.md). tools/plugin_release.py builds a release's archives from its tag and pins their checksums in the marketplace ("After tagging" in docs/releasing.md). tools/plugin_canary.py installs them into a throwaway Claude Code configuration and checks that Claude Code lists and runs them and that the reviewer guard holds in the plugin; like the runtime canary it calls a model, so it is a manual gate, never part of validation.
  • tools/runtime_canary.py deploys this checkout and the fixture source in tests/fixtures/runtime-canary/ into a throwaway home with deploy.py --canary-home, checks that Claude Code, Codex, and Copilot CLI find and run the named skills, and fails where a run disagrees with the skill's declared runtime support. It calls models, so it is a manual pull request gate run through the runtime-canary repository skill, never part of validation. Nothing under tests/fixtures/ ships, which validation enforces.
  • tools/skill_evals.py runs a skill's fixed scenarios under tests/fixtures/skill-evals/<skill>/<scenario>/ model by model, from throwaway homes deployed with deploy.py --canary-home, and judges each run by script, never from the report; --write replaces the skill's rows in docs/skill-evaluations.md. It calls models, so it is a manual pull request gate run through the evaluate-skill repository skill, never part of validation; "Skill evaluations" in docs/skill-evaluations.md describes the scenarios, the runs, and what is recorded.
  • .github/workflows/deployable.yml deploys onto a fresh windows-latest runner and, in its deployable-linux job, a fresh ubuntu-latest one, on dispatch and weekly, on the README's versions and on the latest release of every runtime: it installs the prerequisites and the runtimes, deploys into the runner's real profile, runs deploy.py verify, uninstalls, and deploys again. It starts no model and is never a required check, and the README's fresh-runner column records its last dispatched release run; "Before tagging" in docs/releasing.md says what tools/deployable_report.py judges and what validation pins.
  • .github/workflows/runtime-command-lines.yml runs tools/runtime_command_lines.py on dispatch and weekly, on the latest release of every runtime on fresh Windows and Linux runners: it builds each runtime command line the repository starts from the function that builds it for real runs, never a copy, and starts it signed out, so a release that drops or renames a flag fails the job. It starts no model and is never a required check; "Before tagging" in docs/releasing.md says how it starts them.
  • .github/workflows/runtime-changelogs.yml runs tools/runtime_changelogs.py on dispatch and weekly: it lists each runtime's changelog entries since the release the guidance record names that mention a term the code uses, read from the code at each run, never typed, and each guidance page that moved or is gone. It is advisory, fails only when the watch cannot run, starts no model, and is never a required check; "After tagging" in docs/releasing.md says how the guidance audit uses it.
  • tools/release_notes.py writes a release's section of docs/upgrade-notes.md from the upgrade notes of the commits since the previous tag, and tests/validation/upgrade_notes.py reads the same entries; "Before tagging" in docs/releasing.md runs it.
  • tools/worktrees.py coordinates parallel sessions (creating task worktrees and surveying them), tools/hub_guard.py is the hub guard hook declared in .claude/settings.json, tools/new_skill.py scaffolds a new skill's frontmatter, metadata, and reference section, or, with --repository, a repository skill and its shim, and tools/skill_shims.py writes and checks the shims; tests/tools/test_*.py are the suites for tools/.
  • .claude/skills/<name>/ holds this repository's own skills, for working on it rather than for deployment. Each has a shim in .agents/skills/<name>/ with the same frontmatter for Codex and Copilot, which tools/skill_shims.py writes and validation compares with what the tool writes; an adapter is what the deployer generates under ~/.agents/skills for a deployed skill. Keep the two words distinct. Repository skills meet the shipped-skill standard, and a change to one runs audit-skill on it ("Validation" in docs/adding-a-skill.md). review-repository is this repository's own pull request reviewer: its specialists manifest routes the deployer, the skills and their metadata, the validation policies, the trust-boundary files, and the documents to reviewers briefed on docs/design.md, and review-prs runs it once a machine's code-review configuration names it.
  • docs/design.md owns why the repository is built this way (the trust model, the invariants, and each decision with its reason and date), and a change that bends an invariant or revisits a decision updates it in the same pull request.

A document names what the repository holds or does and never counts it, and states no date or version in guidance; a reader who needs the number takes it from the generated reference or a command, and a "checked on" or "as of" date is replaced by the thing checked. The exceptions are the places that own a date or version as the record: a decision's date in docs/design.md, a release's section in docs/upgrade-notes.md and its notes, and the README's supported-runtimes table and the date of its fresh-runner run, which "Before tagging" in docs/releasing.md maintains.

To add or change a skill, follow the change-skill repository skill. It applies docs/adding-a-skill.md, the skill contract, one section at a time: read the section each step names before acting on it.

Safety requirements

  • Do not modify installed skills under ~/.claude/skills, installed agents under ~/.claude/agents, generated adapters under ~/.agents/skills, or user-managed Copilot skills under ~/.copilot/skills while developing or testing this project.
  • Use an isolated temporary home for deployment fixtures and canaries: --canary-home, or Paths built on a temporary directory. deployer/platform_support.py takes the home from the Windows profile folder on Windows, so setting HOME alone does not isolate a run there.
  • Preserve immutable template sources and verify source hashes when testing rendering.
  • Never source or execute configuration files; keep parsing restricted to validated KEY=VALUE entries.
  • Treat tokens used in Bash, PowerShell, JSON, YAML, or other executable/structured contexts according to that context. Universal raw substitution is not sufficient.
  • Reject unresolved tokens, unsafe names and paths, ownership collisions, and invalid shared dependencies before mutation.
  • Preserve journaled rollback, recovery, locking, manifest ownership, and permanent backup behavior.
  • Do not add personal paths, internal organization names, credentials, or generated deployer state.
  • Do not change the source ID without an explicit ownership-migration plan.

Parallel sessions

Several sessions may work in this repository at once, and sessions that share a checkout share a HEAD and a working tree, so one session's branch switch or commit carries another's uncommitted edits. Each task therefore gets its own worktree; see docs/parallel-sessions.md.

  • The main checkout is the hub. It stays on main, stays clean, and is never edited. It is used only to pull main, create and retire worktrees, survey, and deploy.
  • Start a task with python tools/worktrees.py new <kind> <name>, which creates .claude/worktrees/<kind>-<name> (gitignored) on branch <kind>/<name>. Then move the session into it (in Claude Code, EnterWorktree with that path) before editing. python tools/worktrees.py list surveys every worktree.
  • Integrate through a pull request pushed from the worktree, never through a merge in the hub. After it merges, retire the worktree from a session outside it with repo-cleanup on the hub, which also fast-forwards main; see "Retiring a worktree" in docs/parallel-sessions.md. By hand, run git worktree remove <path> and git branch -D <kind>/<name>. A squash merge leaves the branch looking unmerged, so -d refuses.
  • Deploy only from the hub on main. A deployment records its source path, so deploy.py refuses to deploy from a linked worktree, and --dry-run there refuses too once the home records the hub as the source, as it refuses any other checkout; --canary-home (a throwaway home under the temporary directory) still works there.
  • When one session orchestrates several task sessions, a session in the hub keeps their pull requests merging with the shepherd-pull-requests repository skill, one tick at a time; see "An orchestrator and a shepherd" in docs/parallel-sessions.md.
  • Never pop or drop a stash you did not create: the stash stack is shared by every worktree.
  • In a clone that opts in with git config coding-agent-skills.hubGuard true, the Claude Code hook in .claude/settings.json refuses edits to the hub, git commands that would move its HEAD or write its tree, and, while a hub is guarded, every part of a command it does not understand; "The guard's contract" in docs/parallel-sessions.md names what it reads, refuses, and does not see. For Codex and Copilot CLI these rules are the guard: Codex does not run the hook, and Copilot CLI runs it only in a folder it trusts, where on Windows the command exits under PowerShell before the guard starts; "Other runtimes" in docs/parallel-sessions.md says exactly what each does.
  • .claude/settings.json is tracked and may hold $schema, hooks, and attribution only. Its attribution turns off Claude Code's commit trailers, pull request footer, and session links, so commits and pull requests made here carry none. Permissions and every other setting belong in each developer's user or settings.local.json settings, and a settings.local.json is never committed; "The guard" in docs/parallel-sessions.md says what validation refuses.

Required validation

The validation command, which CI runs in full on every push and on every pull request that is not documentation-only (a documentation-only pull request runs the subset the runner selects):

python -B tests/run_validation.py
  • Validation is CI's job: the validate workflow's required Validation check, which needs every Windows leg, every Linux leg, and the job that asks whether each known failure's issue is open, is the gate, and a pull request merges only when it passes. Locally, before the pull request, run the suites the change touches one at a time, each new regression test with the fix reverted, ruff and mypy on the changed files, and the title and body checks; --changed is optional, never required. Run the full suite locally only when the change's reach warrants it, such as a validation policy or the runner, and reproduce a failed CI leg with --shard <index>/<count>, adding --full for a push, schedule, or dispatch leg. A reach no file name or import shows goes in CHANGE_REACHES in tests/validation/job_selection.py, never in a list a contributor keeps. "Validation" in docs/implementing-changes.md is the procedure and says what each run selects.
  • The gates that call a model (audit-skill on a changed skill, the runtime-canary lines, and the evaluate-skill citation) never run in CI and stay with the author. The Mutation workflow's Mutation gate job is not a required check: its step summary is the record, so read it, kill or name as equivalent each surviving mutant on a changed line that alters behavior a caller relies on, and copy no result into the pull request.
  • tests/run_validation.py is the single entry point used locally and in CI. Its policies live in tests/validation/, one module per policy family, each beside a fixture suite, tests/validation/test_<module>.py, that shows a violating input failing and a conforming one passing; a new policy goes in its family's module with a fixture test in that suite. A policy that reads Python reads it through ast and resolves each name through the module's imports. A policy check swaps no standard stream and changes neither os.environ nor the working directory, since the pool's jobs run meanwhile; "The runner" in CONTRIBUTING.md describes the pool, the legs and shards, and how a failure or a termination is reported.
  • Suites run in parallel and in shards, so every suite isolates its own temporary home and fixtures, and no test depends on another test's order or state. The root conftest.py isolates every Python suite's git: a test reads its home as self.git_home or through the git_home fixture, a test class or suite module adds settings as its git_config, and no conftest.py sits below the root.
  • Validation requires Python 3.11.4 or newer, Git Bash, ShellCheck, PowerShell 7 (pwsh), the PSScriptAnalyzer module, and the development dependencies requirements-dev.in pins (ruff, mypy, and pytest only, for contributors and CI), installed from its hash lock requirements-dev.txt, while the deployer and shipped skills stay standard-library. "Development environment" in CONTRIBUTING.md installs them, and docs/dependency-updates.md owns the pins.
  • Python is formatted and linted with ruff at a line length of 120 and type-checked with mypy, with no file or rule exempt; run python -m ruff format to fix formatting. A finding that must stay is suppressed on its line as # noqa: <code> - <reason>, and a type error as # type: ignore[<code>] # <reason>. Function complexity (C901) and length (PLR0915) take no noqa: split the function, and lower a ceiling, which only goes down, when the split leaves the maximum below it. mypy_path lists each skills/<name>/scripts directory a module or suite puts on sys.path, and each test directory whose suites import a module beside them by its bare name. "Python checks" in CONTRIBUTING.md is the full account.
  • Every .ps1 and Markdown PowerShell fence validation reads passes Invoke-ScriptAnalyzer -Severity Warning,Error, and every Markdown Bash fence outside skills/ and tests/ passes ShellCheck; write a placeholder in a Bash fence quoted, as in '<file>'.

Never work around a failing check. Do not mark tests as expected failures or skipped, weaken or disable a gate, or leave TODO or placeholder comments to land partial work; finish the change so every check passes, or keep it uncommitted. A test that cannot run on a platform is skipped by a condition that reads the platform alone, and any other skip that must stay is sanctioned beside the code as a module-level SKIP_ALLOWED = {scope: reason}. Never disable or suppress ShellCheck, PSScriptAnalyzer, ruff, or mypy beyond one finding on its line; fix the cause. The only sanctioned suppression of a shell check is the fragment-lint header deployer/render.py adds to Markdown command examples it extracts for validation; PowerShell has none, so rewrite a fence or script so the rule holds, keeping a command example the same command. "Validation" in docs/adding-a-skill.md and "Python checks" in CONTRIBUTING.md name each marker, comment, directive, and settings file validation refuses.

Add regression coverage for every behavior change. When a token appears in executable content, include a rendered execution fixture with representative values containing spaces and other allowed punctuation: a token in Bash or PowerShell sits inside quotes and is covered by a tests/deployer/ test named *with_spaces*, as "Template values" in docs/adding-a-skill.md describes.

A regression suite runs only if its name matches test_*, test-*, *_test, *-test, or *.test.* with a .py, .sh, or .ps1 extension. A Python suite defines at least one test, as unittest test cases, plain test functions, or both, and holds no if __name__ == "__main__": block, since the runner starts it through pytest. Run one suite, or one test, as the runner does, with python -B -m pytest <suite> or python -B -m pytest '<suite>::<Class>::<test>' from the repository root. "Validation" in docs/adding-a-skill.md states what a suite holds.

Every skill with executable files must include an executable regression suite under its scripts/ directory. Markdown may use executable-language fences only for command examples of five lines or fewer; extract longer programs into tested files under scripts/.

Keep DOCUMENTATION_FILES and DOCUMENTATION_DIRECTORIES in tests/run_validation.py to files no suite executes; Markdown under skills/, agents/, and .claude/ is skill and agent behavior, not documentation. "Validation" in docs/implementing-changes.md says what a documentation-only change runs.

Issues and pull requests

  • The backlog is this repository's GitHub issues. Write every issue body from the matching template in .github/ISSUE_TEMPLATE/ (enhancement, bug, documentation, or question) and every pull request body from .github/pull_request_template.md, keeping their section headings, to a file passed with gh issue create --body-file or gh pr create --body-file; --body bypasses the template.
  • Name each issue the change resolves in its own Closes #N line when the pull request is opened.
  • A pull request's title becomes its squash commit's title, so it opens with a type (feat, fix, docs, test, refactor, chore, ci, or build), an optional scope in parentheses, a colon, and a space, as in fix(deployer): ..., with no !; the type agrees with the worktree's branch kind when the kind is one of them. Check it locally with --pr-title <file>.
  • A change a user who updates meets, every contract change included, states it under ## Upgrade note in the pull request body, in the shape docs/upgrade-notes.md gives, and never in that file; check it locally with --pr-body <file>. Given alone, without -k, --changed, --full, or --shard, --pr-title and --pr-body run only the title, upgrade-note, forms-considered, silent-revert, and known-failure closing checks. A pull request that changes a skill's prompt, description, model guidance, or reviewer instructions cites its evaluate-skill run and commits the result it wrote to docs/skill-evaluations.md, when the skill has scenarios.
  • Before gh pr create, run git fetch origin main and git rebase origin/main, not the local main, in the worktree. While the pull request is open, merge origin/main into it before pushing more commits, and never rebase or force-push it. If a push is rejected, fetch and inspect the remote branch before anything else: the maintainer may have updated it.

"Pull requests" in docs/implementing-changes.md says what each title type covers and how the title, upgrade-note, forms-considered, silent-revert, and known-failure closing checks read a pull request.

Maintaining AI Agent Config

This CLAUDE.md is the single canonical, hand-authored instruction source for every agent runtime working in this repository.

  • AGENTS.md is a hand-maintained Codex wrapper that only redirects to this file. Keep it thin; never copy guidance into it or replace it with a generated adapter.
  • Keep this file under 32 KiB, Codex's default project_doc_max_bytes, as a budget: Codex loads the root AGENTS.md and reads this file through its redirect, which that limit does not govern. State each rule in a sentence or two and point, by its quoted heading and its document, at the section that holds how the rule is enforced, moving any enforcement detail there. tests/tools/test_claude_md.py holds the size and that each pointer names a section its document has.
  • Claude Code, Codex (through AGENTS.md), and Copilot CLI/app load these instructions directly, so the repository intentionally has no generated projections: no .github/copilot-instructions.md, .github/ai-config-manifest.json, .github/scripts/ai_config.py, or ai-config-parity workflow. Copilot code review on GitHub.com, the cloud agent, and Copilot CLI read CLAUDE.md themselves, code review taking it from the pull request's head branch. Reconsider a parity check only if a surface that reads only the redirect in AGENTS.md or neither file (VS Code chat with its chat.useClaudeMdFile setting off, when it reads only AGENTS.md, or code review in VS Code or JetBrains) becomes a supported way of working on this repository, and wire it into validate.yml rather than adding an uncalled workflow.
  • The init-ai-config skill that generated that layout was retired for the same reason; audit-ai-config in docs/skills.md records the history.

Source authority

This project directory is the authoritative source for templates, metadata, deployment logic, tests, and documentation. Installed files under ~/.claude/skills/ and any legacy copy under ~/.claude/skill-templates/ are not authoritative and must not be edited as the source of a change. Synchronizing or deploying to those locations must be an explicit operation, never an incidental validation step.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.