Give a repo its own rules at both layers, and put each rule at the cheapest layer that holds it. The told layer is what a project's workspace tells a model before it writes, so it establishes where a session starts, which repo each kind of file belongs in, how the gate is run, the facts nobody can infer, what this repo does not have, the enforced rules as an index rather than a copy, and the handful no script can count. The caught layer is what turns the build red afterwards, as a linter sett...
Scanned 8/31/2026
Install via CLI
openskills install smk-labs/claude-plugins---
name: workspace-rules
description: Give a repo its own rules at both layers, and put each rule at the cheapest layer that holds it. The told layer is what a project's workspace tells a model before it writes, so it establishes where a session starts, which repo each kind of file belongs in, how the gate is run, the facts nobody can infer, what this repo does not have, the enforced rules as an index rather than a copy, and the handful no script can count. The caught layer is what turns the build red afterwards, as a linter setting, an architecture test or a hook, derived from this repo's own evidence, proved red by name and green on an untouched tree, with the cap, the displacement clause and the dated judged-out list inside the check file. Runs after a cleanup, spring-clean or otherwise. Use when the user asks to set house rules or project conventions, write or fix a CLAUDE.md, set up a project's .claude layer, tell the next session how this project works, onboard an agent to a codebase, stop a bug class from coming back, make the linter enforce the style guide, turn a written rule into a test, add architecture tests or guardrails, prune a rule set that has sprawled, wants a codebase standard that holds, or says "house rules", "workspace rules", "قانون بذار", "قوانین پروژه", "استاندارد کد", "این قانون رو تست کن", or complains that a rule everyone agreed on keeps getting broken.
---
A repo's rules sit at two layers: what its workspace tells a model before a line exists, and what its build catches after one is written. Telling costs a line in a file the model already reads; catching costs a red build, a turn, and a check somebody maintains forever. A rule belongs at the cheapest layer that holds it, and getting that call right is most of this pass. One test governs both: **if you could have written the rule without opening this repo, the model already knows it and the line is a tax.**
## Which layer, and this is the judgment the rest hangs on
**Take the capability away before writing any rule.** Delete the export, narrow the visibility, drop the dependency, remove the tool. A reviewer shipped without an edit tool cannot fix the code it reviews, which no instruction achieves and no compacted context forgets. Then read the default posture, because omission from an allow list is not removal.
**Sort what is left by what it hands the model.** Information it could not infer costs nothing to obey and holds with no gate, no judge and no repetition: what this repo does not have, which of two sources wins, where the local default is wrong and how widely. A cost it must pay against its own task is not held by prose at any volume. Loudness and frequency buy nothing, and the loudest rule in this evidence sits beside a settings file granting the very access it forbids.
**If a script could count compliance, something must count it.** Best-evidenced claim here, and it runs one way only: every countable rule nobody counted was found violated, most often by the file stating it. A file carrying a two hundred line target ran five hundred and fifty three, and a field no downstream reader consumed was blank in thirty-seven of thirty-nine notes.
**Where a cost remains and the capability cannot go, put the result in front of somebody who did not produce it, reading primary evidence rather than the producer's account.** The one controlled comparison here is exactly that: reviews handed a summary found none of the blockers, reviews handed the diff found twelve. A self-reported pass is worse than no check, because it launders trust downstream.
**What is left is a cost no script can count, and that is the handful worth writing down.** No script reads degree or intent, so none tells a surgical cut from a rewrite. None reaches a truth living outside the repo, like what someone else's binary does with your flags after their next release. None sees how you checked, only what you wrote, so *render it and look at it* is out of reach. And none gets any signal when the violation still works, which covers every judgment about where a thing belongs. Write those. Write almost nothing else twice.
## What the told layer establishes
One `CLAUDE.md` at the repo root, because that path is the loading mechanism. A second harness wanting a second filename gets a generated copy under byte comparison, never a second author.
It carries: where a session starts, said from both ends, since a model opens wherever the shell happened to be. Which repo each kind of file belongs in, as a test rather than an inventory: if the code changes and this file must change in the same branch it belongs with the code, and everything else belongs in the workspace repo beside it, or in a named directory here that no build reads when there is no second repo. That test places the rules themselves. How the gate is run, as the literal commands from the named root, including the flag whose absence is a silent defect.
Then the gated rules as an index, one clause and a location each, saying outright that this page cannot fail and the check is the authority. The facts nobody could infer, each carrying the version and date it was measured against, because this class fails by going stale rather than by being ignored. **What this repo does not have, and what nobody is to build here**, the cheapest thing on either layer: every entry is a confident invention somebody actually committed, and the second half stops the helpful addition nothing warned against. Any entry naming a path or a package is one line of the check away from being counted, which is where the halves meet. The handful no script can count. And the principles, tests among them: this project writes tests that would fail if the thing broke, a standard to hold rather than a coverage number to check. A rule the gate holds is described once, in the index, and where the inventory names the same absence it states the fact rather than the rule, or the page becomes the second copy it warns about.
## Prose is the default, and format is never the mechanism
**A pointer is not telling.** An agent handed the path to its rules and told they were authoritative produced twenty-two high findings in one review, every one a violation of a rule it had been pointed at. Their answer was to concatenate every rule file into every task file. Right finding, wrong end of it: inline what must be obeyed where the writer is already looking, cite what only has to be findable, and treat a rule set needing thousands of embedded lines as the defect.
Moving a rule into a rules file, a skill, an agent or a hook changes its container, not its force, and here the container almost never earned itself. What earned was removing a capability, or a second reader on primary evidence, and both work in any container. So spend the choice on reach: a rules file scoped to the paths it governs, a skill for a workflow somebody invokes by name, an agent for a job worth delegating, which almost always means that second reader, a hook only for what must physically happen every session and that prose demonstrably failed to make happen. An instruction nobody can satisfy where it is read is worse than none, because it teaches the model to discount its neighbours.
## Derive from this repo, never from a list
- **The headers of the gates that already run**, richest source in any repo with machinery: the script carries the rule and its comment carries the why, including the scope somebody deleted and the reason.
- **The `fix:` and revert log**, deduped because a rebase leaves the same subject twice, and **the decision log**, where a decision that changed a count becomes an assertion on that count.
- **Prose in the tree**, every comment carrying never or always; the **suppressions**, each a rule somebody started and abandoned; **your own transcripts**, where a class of defect costs real time and never appears in a diff.
- **What already runs**, so you subtract rather than re-encode, and **what nothing reaches**: the directory that is production for one rule and invisible to another is where violations live, and the rules file nothing loads is where told rules die.
Each rule carries the incident that bought it, dated, priced in this repo's own units. **No incident, no slot.** Having no mechanism disqualifies nothing, since the largest expensive cluster with nothing a check could catch is what the told layer is for. Neither does being generic: run the generic sweep if you like, and let the tree win every tie.
## Encode it, prove it, cap it
A linter setting, a linter rule pinned to what exists, an architecture test, a hook that refuses the edit, a CI job. A detector written into a document is on neither layer: a comment until something runs it, and it looks exactly like enforcement. Run each over the whole tree with the code you will ship and read the count, because a handful is a ledger and hundreds means you aimed at the wrong files. **Prove the search path exists, and that the tool ran at all, before believing an empty result**: a scan of a directory that is not there exits clean and reads exactly like no hits, a tool that refused on a locale or a missing flag reads the same, and the second reviewer inherits the same bad measurement.
**A rule the tree already satisfies just ships. One it breaks takes one of three shapes**: pin the number of occurrences, never a filename and never a count of files, or a second violation inside a listed file keeps the number and ships green; or set the limit at the target and warn until the slack closes; or scope the detector to added lines only, which needs no ledger. What it never does is ship as a block bypassed on day one. Pin only where the repair is a project, because a pinned typo is a certified lie and a pass that ledgers everything it finds ships rules that catch nothing the day they land. Block only near zero false positives on this tree, otherwise warn, and name in its header which layer does block.
**Seen red by name, and green on an untouched tree.** Break it on purpose and watch it fail by name in the real gate, once per file class it covers and once per trigger that runs it, then assert the other half on unmodified HEAD, and where that tree is already red, as a delta against a baseline measured before you touched anything, or the pass books somebody else's failures as its own. Keep the probe and date it. Every detector needs outcomes past pass and fail: could-not-run, and out-of-scope, neither of which is green.
**Reachable means executed, not mentioned.** Rules land in the command that already runs, and a container build or a release script is a gate too, often the only one whose failure stops a deploy. Then assert the reverse: every gate is reached by the command a person actually types, since a name added to a manifest satisfies the letter and runs nothing. Prove it by what the command counted, never by its exit code, because a runner whose glob matched no files exits 0 and reports a pass it never got. Every rules file is reached by something that parses it. The file the harness loads by its path is the one exception, where presence is all anyone can assert. At both layers the dominant failure is a correct rule nothing invokes.
**Say it once, and re-derive it.** Twenty duplications were counted here and not one stayed in sync; the copy reads as authoritative and is the one that drifts. So the told layer gets exactly one gate: every path and command it names resolves, and correspondence beats presence or a rename passes green. Anything the filesystem or the config already knows is derived or deleted, never hand-maintained beside a staleness warning.
Count the whole roster and not just what this pass added, the unit being the name printed when one fails. Assert that number last, after the sweep, or the cap becomes the reason a countable rule stayed in prose. Add the displacement clause, a rule that wants in pushes one out, starting with this pass, so the number you assert is under the one you found. Cap the told layer the same way, on the bytes reaching the context rather than the lines, because one file here grew its lines by two thirds and its weight fourfold and a line cap never saw it. Set that cap under whatever the page replaced, or it fences in today's file and costs nothing. If the page does not hold in one head, the admission test was never applied to it. Retire a rule when its surface is gone, when another covers it, when its scope matches zero files, or when it never caught anything, and say which rules you deliberately do not check beside the ones you do. A rule found wrong is retracted where it sits, with the date.
## Red flags
- A pointer standing in for a rule: *see `rules/`* in an agent's brief, or a rules file nothing path-scopes and nothing links.
- The same rule in two files. Not redundancy, but the drift you will read and believe. A document announcing its own staleness is the same defect wearing a warning label.
- A rule whose own examples break it. Demonstrated beats stated every time, so the example teaches the violation.
- A detector whose coverage is set by an optional field, measuring its own opt-in rate and printing green, or a gate whose exit code dies in a pipe and reports a pass it never got.
No comments yet. Be the first to comment!