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
In this repository30 other files it gives its agents.
- AGENTS.mdAGENTS.md
- audit-repositorySkill
- change-skillSkill
- evaluate-skillSkill
- implement-changeSkill
- review-repositorySkill
- runtime-canarySkill
- shepherd-pull-requestsSkill
- audit-repositorySkill
- change-skillSkill
- evaluate-skillSkill
- implement-changeSkill
- review-repositorySkill
- runtime-canarySkill
- shepherd-pull-requestsSkill
- audit-ai-configSkill
- audit-skillSkill
- curate-agent-memorySkill
- dotnet-dependenciesSkill
- dotnet-formatSkill
- ejryan89-code-review-coreSkill
- ejryan89-skill-coreSkill
- flag-review-findingSkill
- github-activity-reportSkill
- repo-cleanupSkill
- review-documentSkill
- review-insightsSkill
- review-prsSkill
- update-coding-agent-skillsSkill
- update-pr-dashboardSkill
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
- Very specific: line 19
Every entry point, a module whose __main__ block calls run_main, states its codes in an Exit status: docstring table, and each command has …
- Very specific: line 46
Do not modify installed skills under ~/.claude/skills, installed agents under ~/.claude/agents, generated adapters under ~/.agents/skills, …
- Very specific: line 47
Use an isolated temporary home for deployment fixtures and canaries: --canary-home, or Paths built on a temporary directory.
- Very specific: line 49
Never source or execute configuration files.
- Distinctive: line 50
Treat tokens used in Bash, PowerShell, JSON, YAML, or other executable/structured contexts according to that context.
- Distinctive: line 53
Do not add personal paths, internal organization names, credentials, or generated deployer state.
- Distinctive: line 54
Do not change the source ID without an explicit ownership-migration plan.
- Very specific: line 61
Start a task with python tools/worktrees.py new <kind> <name>, which creates .claude/worktrees/<kind>-<name> (gitignored) on branch …
- Very specific: line 64
When one session orchestrates several task sessions, a session in the hub keeps their pull requests merging with the shepherd-pull-requests …
- Distinctive: line 65
Never pop or drop a stash you did not create: the stash stack is shared by every worktree.
- Very specific: line 83
Every .ps1 and Markdown PowerShell fence validation reads passes Invoke-ScriptAnalyzer -Severity Warning,Error, and every Markdown Bash …
- Very specific: line 91
Every skill with executable files must include an executable regression suite under its scripts/ directory.
- Very specific: line 93
Keep DOCUMENTATION_FILES and DOCUMENTATION_DIRECTORIES in tests/run_validation.py to files no suite executes.
≈ “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.
Files
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>.mdholds Claude Code subagent definitions that skills declare inagent_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>.jsondeclares 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, ornonefor each of Claude Code, Codex, and Copilot CLI, naming the capability a runtime lacks), in the one layout "Metadata" indocs/adding-a-skill.mdgives.skills/ejryan89-skill-core/scripts/runtime_support.pycatalogues 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" indocs/adding-a-skill.md.deployer/tools.pyis the single catalogue of those tools, the deployment prerequisites, and the runtimespython deploy.py verifylists, with their version floors;python deploy.py check(deployer/check.py) reports them, anddeployer/source_commit.pyrecords the source commit in the manifest's source entry at each deployment. source.jsonmay group selectable skills into atomic bundles, and itsrenamedrecords each renamed skill's old name, whose owned copy the next deployment moves to the new one ("Renaming a skill" indocs/adding-a-skill.md); the manifest records requested roots separately from their expanded dependency closure and each skill's deployedskill_deps. A skipped or preserved skill keeps its recorded transitive skill dependencies and their shared assets and agents.skills/<asset>contains shared assets declared insource.jsonas eitherownerordependency.skills/ejryan89-skill-core/is a hidden skill and the one home of the repository's shared Python: skill scripts, the deployer, andtools/all import its modules fromskills/ejryan89-skill-core/scripts, and nothing copies them. It holds one module per concern, among themconsole.py, whoserun_main(main)is the one call in every entry point's__main__block and ends an unhandled exception with aFAILED <type>: <message>line and exit 1, never a traceback unless the entry point asks, asdeploy.py's--debugdoes;frontmatter.py;github_client.pyandgit_client.py, whoseGitHubClientandGitClienteveryghcall 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 theGIT_INDEX_FILEthatrun_bounded'sindex_filekeyword 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, andsibling_scripts, the one lookup of a sibling skill'sscripts;executable_locator.py;flat_text.py, the one whitespace flattener for text a script prints on one line; andxml_reader.py, the one reader of untrusted XML, which refuses aDOCTYPEorENTITYdeclaration. "Script results" indocs/adding-a-skill.mdstates the runner's and the clients' contracts.- A dependent declares
ejryan89-skill-coreinskill_deps, puts../ejryan89-skill-core/scriptsonsys.path, and reaches every other sibling it declares throughsibling_scripts, as the suites undertests/and the modules undertools/do after their own statement.deployer/__init__.pyholds the deployer's one statement puttingskills/ejryan89-skill-core/scriptsfirst onsys.path, located from its own file and never through the configured source path; atools/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 ortools/; "Validation" indocs/adding-a-skill.mdstates every import rule validation holds. deploy.pyis the single command-line entry point.deployer/cli.pyroutes it, anddeployer/arguments.pydeclares itsargparseparsers.- Every entry point, a module whose
__main__block callsrun_main, states its codes in anExit status:docstring table, and each command has a fault driver intests/malformed_input/faults_*.pyor aNOT_RUNreason; see "Script results" indocs/adding-a-skill.md. python deploy.py configurerunsdeployer/configure.py, which writes a strictly parsed, source-specific configuration under~/.claude/deployer/config/.deployer/config.pyis the single declaration of configured and derived variables.- Any other
deploy.pyinvocation runsdeployer/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.pyorchestrates a run (the lock, recovery, the journal, and the manifest commit) overdeployer/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 withcheckandverify), anddeployer/migrate.py(--migrate-from).deployer/kinds.pydescribes 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-levelKINDS_ALLOWED = {pass: reason}; "One table of item kinds" indocs/design.mdnames the exceptions and what validation refuses.deployer/context.pyholds 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.pyand the deployer goes throughdeployer/fsops.py, whosefsops.extract_archiveis 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-levelFSOPS_ALLOWED = {token: reason}; "One write point" indocs/design.mdsays 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/, ortests/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-levelDUPLICATION_ALLOWED = {name: reason}whose reason names every other file that holds the copy; "Validation" indocs/adding-a-skill.mdsays what counts as a copy. skills/ejryan89-skill-core/scripts/frontmatter.pyis the one reader for skill and agent frontmatter, imported asfrontmatterby 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.pyreads each runtime's skill listing (Copilot'scopilot skill list --json, Codex's app-serverskills/listrequest) and is shared withtools/runtime_canary.py.tests/deployer/test_*.pyare the deployer suites; their isolated fixture repositories and homes live intests/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 withchanges_home.tests/deployer/test_invariants.pyshows both comparisons failing and passing, and holds that a permanent backup survives later deployments and the uninstall.docs/skills.mdis the skill reference.tools/skill_reference.pygenerates its summary table and the first block of each skill's section, and the "Runtime support" table, fromSKILL.mdfrontmatter and metadata; the explanation after each block is hand-written. After changing a skill's frontmatter or metadata, runpython tools/skill_reference.py --write; validation fails while the reference is stale.tools/runtime_prompts.pyrenders, 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, intodocs/runtime-prompts/<skill>/<role>.txt, with the throwaway folder as<temp>and the checkout as<source>, whereaudit-skillmeasures it. After changing such a prompt, runpython tools/runtime_prompts.py --write; validation fails while a sample is stale.tools/plugin_build.pyassembles the Claude Code plugins fromskills/,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" indocs/adding-a-skill.md).tools/plugin_release.pybuilds a release's archives from its tag and pins their checksums in the marketplace ("After tagging" indocs/releasing.md).tools/plugin_canary.pyinstalls 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.pydeploys this checkout and the fixture source intests/fixtures/runtime-canary/into a throwaway home withdeploy.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 theruntime-canaryrepository skill, never part of validation. Nothing undertests/fixtures/ships, which validation enforces.tools/skill_evals.pyruns a skill's fixed scenarios undertests/fixtures/skill-evals/<skill>/<scenario>/model by model, from throwaway homes deployed withdeploy.py --canary-home, and judges each run by script, never from the report;--writereplaces the skill's rows indocs/skill-evaluations.md. It calls models, so it is a manual pull request gate run through theevaluate-skillrepository skill, never part of validation; "Skill evaluations" indocs/skill-evaluations.mddescribes the scenarios, the runs, and what is recorded..github/workflows/deployable.ymldeploys onto a freshwindows-latestrunner and, in itsdeployable-linuxjob, a freshubuntu-latestone, 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, runsdeploy.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" indocs/releasing.mdsays whattools/deployable_report.pyjudges and what validation pins..github/workflows/runtime-command-lines.ymlrunstools/runtime_command_lines.pyon 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" indocs/releasing.mdsays how it starts them..github/workflows/runtime-changelogs.ymlrunstools/runtime_changelogs.pyon 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" indocs/releasing.mdsays how the guidance audit uses it.tools/release_notes.pywrites a release's section ofdocs/upgrade-notes.mdfrom the upgrade notes of the commits since the previous tag, andtests/validation/upgrade_notes.pyreads the same entries; "Before tagging" indocs/releasing.mdruns it.tools/worktrees.pycoordinates parallel sessions (creating task worktrees and surveying them),tools/hub_guard.pyis the hub guard hook declared in.claude/settings.json,tools/new_skill.pyscaffolds a new skill's frontmatter, metadata, and reference section, or, with--repository, a repository skill and its shim, andtools/skill_shims.pywrites and checks the shims;tests/tools/test_*.pyare the suites fortools/..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, whichtools/skill_shims.pywrites and validation compares with what the tool writes; an adapter is what the deployer generates under~/.agents/skillsfor a deployed skill. Keep the two words distinct. Repository skills meet the shipped-skill standard, and a change to one runsaudit-skillon it ("Validation" indocs/adding-a-skill.md).review-repositoryis 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 ondocs/design.md, andreview-prsruns it once a machine's code-review configuration names it.docs/design.mdowns 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/skillswhile developing or testing this project. - Use an isolated temporary home for deployment fixtures and canaries:
--canary-home, orPathsbuilt on a temporary directory.deployer/platform_support.pytakes the home from the Windows profile folder on Windows, so settingHOMEalone 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=VALUEentries. - 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 pullmain, 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,EnterWorktreewith that path) before editing.python tools/worktrees.py listsurveys 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-cleanupon the hub, which also fast-forwardsmain; see "Retiring a worktree" indocs/parallel-sessions.md. By hand, rungit worktree remove <path>andgit branch -D <kind>/<name>. A squash merge leaves the branch looking unmerged, so-drefuses. - Deploy only from the hub on
main. A deployment records its source path, sodeploy.pyrefuses to deploy from a linked worktree, and--dry-runthere 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-requestsrepository skill, one tick at a time; see "An orchestrator and a shepherd" indocs/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.jsonrefuses 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" indocs/parallel-sessions.mdnames 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" indocs/parallel-sessions.mdsays exactly what each does. .claude/settings.jsonis tracked and may hold$schema, hooks, andattributiononly. Itsattributionturns 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 orsettings.local.jsonsettings, and asettings.local.jsonis never committed; "The guard" indocs/parallel-sessions.mdsays 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
validateworkflow's requiredValidationcheck, 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;--changedis 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--fullfor a push, schedule, or dispatch leg. A reach no file name or import shows goes inCHANGE_REACHESintests/validation/job_selection.py, never in a list a contributor keeps. "Validation" indocs/implementing-changes.mdis the procedure and says what each run selects. - The gates that call a model (
audit-skillon a changed skill, theruntime-canarylines, and theevaluate-skillcitation) never run in CI and stay with the author. TheMutationworkflow'sMutation gatejob 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.pyis the single entry point used locally and in CI. Its policies live intests/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 throughastand resolves each name through the module's imports. A policy check swaps no standard stream and changes neitheros.environnor the working directory, since the pool's jobs run meanwhile; "The runner" inCONTRIBUTING.mddescribes 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.pyisolates every Python suite's git: a test reads its home asself.git_homeor through thegit_homefixture, a test class or suite module adds settings as itsgit_config, and noconftest.pysits below the root. - Validation requires Python 3.11.4 or newer, Git Bash, ShellCheck, PowerShell 7 (
pwsh), the PSScriptAnalyzer module, and the development dependenciesrequirements-dev.inpins (ruff,mypy, andpytestonly, for contributors and CI), installed from its hash lockrequirements-dev.txt, while the deployer and shipped skills stay standard-library. "Development environment" inCONTRIBUTING.mdinstalls them, anddocs/dependency-updates.mdowns 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 formatto 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 nonoqa: split the function, and lower a ceiling, which only goes down, when the split leaves the maximum below it.mypy_pathlists eachskills/<name>/scriptsdirectory a module or suite puts onsys.path, and each test directory whose suites import a module beside them by its bare name. "Python checks" inCONTRIBUTING.mdis the full account. - Every
.ps1and Markdown PowerShell fence validation reads passesInvoke-ScriptAnalyzer -Severity Warning,Error, and every Markdown Bash fence outsideskills/andtests/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 withgh issue create --body-fileorgh pr create --body-file;--bodybypasses the template. - Name each issue the change resolves in its own
Closes #Nline 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, orbuild), an optional scope in parentheses, a colon, and a space, as infix(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 notein the pull request body, in the shapedocs/upgrade-notes.mdgives, and never in that file; check it locally with--pr-body <file>. Given alone, without-k,--changed,--full, or--shard,--pr-titleand--pr-bodyrun 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 itsevaluate-skillrun and commits the result it wrote todocs/skill-evaluations.md, when the skill has scenarios. - Before
gh pr create, rungit fetch origin mainandgit rebase origin/main, not the localmain, in the worktree. While the pull request is open, mergeorigin/maininto 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.mdis 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 rootAGENTS.mdand 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.pyholds 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, orai-config-parityworkflow. Copilot code review on GitHub.com, the cloud agent, and Copilot CLI readCLAUDE.mdthemselves, code review taking it from the pull request's head branch. Reconsider a parity check only if a surface that reads only the redirect inAGENTS.mdor neither file (VS Code chat with itschat.useClaudeMdFilesetting off, when it reads onlyAGENTS.md, or code review in VS Code or JetBrains) becomes a supported way of working on this repository, and wire it intovalidate.ymlrather than adding an uncalled workflow. - The
init-ai-configskill that generated that layout was retired for the same reason;audit-ai-configindocs/skills.mdrecords 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.
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
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.

