the-grid
CLAUDE.md4 starsChanged 8 days agoMITView on GitHub
- Session start: read PURPOSE.md and MAP.md. - Before acting (editing, committing, opening a PR): read GUARDRAILS.md. - Recording a claim or filing a signal: read signals/README.md (stages, warrant rule, file format). - Before building a new capability or adding a dependency: read RELATED.md if it exists. - Everything else: find it through MAP.md ("Read when" column); do not read what it does not point you to. <!-- /charter-trailhead --> the-grid is Gareth's wiring hub for the AI-agent ecosystem —…
- Deletes or force-pushes
- Installs packages
- Commits and pushes
In this repository15 other files it gives its agents.
- cavemanSkill
- gh-issues-by-severitySkill
- grid-helpSkill
- grill-meSkill
- growth-psychSkill
- handoffSkill
- mine-learningsSkill
- openspec-helpSkill
- rubber-duckSkill
- setup-repo-skillsSkill
- skill-scoutSkill
- spec-scoutSkill
- standupSkill
- tightenSkill
- un-claudishSkill
The file
Show its rules and text
We split this CLAUDE.md into the rules it gives an agent
22 rules. About 0 are common, 4 are distinctive, and 18 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.
18
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 5
Before acting (editing, committing, opening a PR): read GUARDRAILS.md.
- Very specific: line 7
Before building a new capability or adding a dependency: read RELATED.md if it exists.
- Very specific: line 39
Only put a skill there if it's original to the-grid, or if it's an upstream skill that's been deliberately forked/edited and must not track …
- Very specific: line 45
If a skills/ copy is byte-identical to (or merely an older snapshot of) a submodule copy, it's redundant: delete the skills/ dir and let …
- Very specific: line 47
When skills/ and a submodule both provide the same skill name, the skills/ copy wins (wire.sh wires repos first, skills/ last).
- Distinctive: line 192
If it shows changes:
- Distinctive: line 198
If it shows nothing: skip this step.
- Distinctive: line 211
Always safe to run, always run it last.
- Very specific: line 233
Read-only drift detectors (exit 1 on drift, write nothing): catalog.sh --check, wire.sh --check, agent-factory/compose.py <cfg> --target …
- Very specific: line 257
Create skills/<name>/SKILL.md (a skill dir at the repo root is not wired).
- Very specific: line 323
Before merging, the QA agent or session runs git diff --name-only origin/main...HEAD -- knowledge/canon (the same command as the PR …
- Very specific: line 330
Remove what you created before finishing, once its PR is merged or abandoned: git worktree remove <path>.
- Very specific: line 331
Delete the branch with git branch -D <branch> only after confirming the PR is MERGED or the branch is fully contained in origin/main.
- Very specific: line 332
Never leave scratch worktrees under .claude/worktrees or /tmp registered in git worktree list.
- Very specific: line 342
Only manages symlinks that point into GRID_DIR — never touches foreign symlinks.
- Very specific: line 355
Only submodules in the manifest (baseline-submodules.txt + machines/<host>.txt overlay) are wired.
- Very specific: line 360
Audit before wiring (step 0): before any teardown wire.sh runs audit.sh --wired --quiet.
- Very specific: line 428
Never replaces an existing entry in those dirs.
- Very specific: line 572
When writing role/SKILL.md instructions for a rule that must never be violated (e.g.
- Very specific: line 576
Don't write bash-style unquoted-$var word-splitting in ad-hoc shell commands — Gareth's machines may run zsh, which doesn't word-split by …
- Very specific: line 600
Before pointing a role at a wired skill for some capability, check whether another wired skill already covers the same ground — …
- Distinctive: line 613
After an upstream history rewrite, git cherry/patch-id reports false unmerged commits.
≈ “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
<!-- charter-trailhead -->Start here
- Session start: read
PURPOSE.mdandMAP.md. - Before acting (editing, committing, opening a PR): read
GUARDRAILS.md. - Recording a claim or filing a signal: read
signals/README.md(stages, warrant rule, file format). - Before building a new capability or adding a dependency: read
RELATED.mdif it exists. - Everything else: find it through
MAP.md("Read when" column); do not read what it does not point you to.
<!-- /charter-trailhead -->the-grid — Claude context
the-grid is Gareth's wiring hub for the AI-agent ecosystem — Claude / OpenClaw / Paperclip / Hermes / opencode and friends. It is not skills-only: skills are the first asset type it wires, but the remit is broader (commands, agents, MCP servers, plugins, configs may follow). It owns some assets directly and pulls many more from sibling repos via git submodules.
wire.sh symlinks skills into ~/.claude/skills/ so Claude picks them up. It
also wires composed agents from agent-factory/ (see below): orchestrator
skills into ~/.claude/skills/, specialist subagents into ~/.claude/agents/. To
keep the active set sane while still indexing the whole ecosystem, the-grid splits
submodules into two tiers:
- Wired — a small curated allowlist whose skills are symlinked live into
~/.claude/skills/. The allowlist is layered: a sharedbaseline-submodules.txt(wired on every machine) plus an optional per-machine overlay atmachines/<hostname>.txt(host =hostname -s) that adds or subtracts entries. wire.sh unions baseline + overlay. Both are personal curation, not tracked in this repo (see #24) — each machine keeps its own, seeded frombaseline-submodules.example.txt/machines/example.txt. - Library — everything else: indexed in
SKILLS.mdand searchable byskill-scout, but not wired (so a session isn't drowned in thousands of skills). Promote a library repo to wired by adding its name to the baseline.
What lives where (ownership principle)
skills/<name>/is for skills Gareth owns or has edited for his own purposes. Only put a skill there if it's original to the-grid, or if it's an upstream skill that's been deliberately forked/edited and must not track upstream. (A skill dir at the repo root is not wired.)- Everything else is managed upstream in
repos/*submodules and wired on demand. Don't copy an upstream skill intoskills/just to use it — the submodule copy gets wired automatically. - If a
skills/copy is byte-identical to (or merely an older snapshot of) a submodule copy, it's redundant: delete theskills/dir and let the submodule own the slot. - When
skills/and a submodule both provide the same skill name, theskills/copy wins (wire.sh wires repos first,skills/last). That's the escape hatch for an edited fork.
Key files
BOOTSTRAP.md— full machine boot sequence: clone → submodules → wire skills → compose agents → wire agents. Start here on a new machine.scripts/wire.sh— the wiring script. Idempotent. Tears down all grid-owned symlinks and rebuilds the wired set each run (so un-wiring a repo actually removes it).baseline-submodules.txt— the baseline allowlist of submodules whose skills are wired live on every machine. Anything not listed is library-only. Also gates composed projects viaproject:<name>entries. Delete the file to wire everything (legacy). Gitignored, not tracked (#24) — personal curation. A fresh machine seeds its own from the trackedbaseline-submodules.example.txt; edit the local copy, not the example, for day-to-day changes.machines/<hostname>.txt— per-machine overlay layered on the baseline (hostname -s). Adds (repo,repo/skill,project:<name>) or subtracts (-repo,-repo/skill,-project:<name>) for that host only. Absent overlay → baseline as-is. Gitignored, not tracked (#24) — seed frommachines/example.txton a new machine.LOGS/— dev journal (handoffs/context from thehandoffskill). Gitignored, not tracked (#24/#39) — personal and not useful to a fork. On machines that want it, it's a symlink into a separate private repo; nothing in the-grid requires it to exist. Thehandoffskill and the SessionEnd auto-handoff worker always write handoffs to the project's ownLOGSfolder (<repo root>/LOGSwhen the session ran inside a git repo, else<cwd>/LOGS; an existinglogs/Logs/LOGSis reused, a missing one is created), with no fallback directory and no location table. In a git repo they commit the two files by explicit path in the repo that holds them (here: the private repo behind the symlink) and thengit pushthe branch, which also publishes any other unpushed commit on it; with no repo the files are only written. Seehooks/README.md"Auto-handoff".scripts/budget.py+docs/budget-target.json— measures the skill/role description listing (Claude Code shares one small description budget across all skills and drops the overflow silently) and gates it:--checkruns ingate.shagainst a committed ratchet (owned skills + roles always; the baseline scope against the trackedbaseline-submodules.example.txtonce submodules are initialised, else exit 3 = skipped). A target missingper_entry_max_chars,owned.skill_body_max_bytesorschema: 1fails.--reportshows the numbers. Lowering a number is normal (--update-target); raising one needs--allow-raiseand review.scripts/usage/weekly.sh+scripts/usage/install-schedule.sh— the weekly usage job (extract, then commitusage/<host>.jsonto the private repo) and the installer that renders its launchd/systemd/cron schedule viascripts/lib/render-schedule.sh. The installer only writes files and PRINTS the activation commands; activating is a human step. Seedocs/usage.md.scripts/prune-report.sh(wrapsscripts/usage/prune_report.py;scripts/usage/aggregate.pyis the importable per-host summer, no CLI) — read-only report that proposes what to drop from the baseline from the per-host usage files (demote a repo,name-onlya skill, unused agents);docs/prune-keep.txtlists names never proposed. Never readstokens/hooks. Seedocs/usage.md.scripts/catalog.sh— regeneratesSKILLS.md: wired skills in full detail, library repos as counts, reference (no-skill) repos in a footer. Deterministic output. The committedSKILLS.mdis rendered from the tracked example baseline (GRID_BASELINE=baseline-submodules.example.txt bash scripts/catalog.sh;wire.shand the gate pin it), not a machine's personal one.SKILLS.md— generated index of the whole ecosystem. Never edit by hand.scripts/build-plugins.py+plugins/+docs/PLUGINS.md— generates the two Claude Code plugin bundles (grid-core,grid-agents) and.claude-plugin/marketplace.jsonfromplugins/bundles.json.plugins/is generated output: regenerate withpython3 scripts/build-plugins.py(needsagent-factory/.venv), never hand-edit.gate.shruns--checkandclaude plugin validate --strict;audit.sh --ownedscansplugins/.scripts/translate-readme.sh+scripts/check-translations.sh— README translations (README.<locale>.md, locales inscripts/lib/readme-locales.txt, prompt indocs/translation-prompt.md). After README prose changes:bash scripts/translate-readme.sh --all; opt-in, costs tokens (oneclaude -p --model sonnetcall per stale locale;--dry-runcalls nothing,--switcher-onlyrewrites the language switchers with no model call).check-translations.sh [--strict]printsSTALE <locale>(andMISSING <locale>with--strict);gate.shruns it non-strict and only WARNs. The source hash ignores the switcher and count values (scripts/lib/readme-hash.sh). Tests stub the translator viaGRID_CLAUDE.site-files.txt+scripts/stage-site.sh— define what GitHub Pages publishes: the list names repo-relative paths (index.html, assets), the script copies exactly those into_site/for.github/workflows/pages.yml(neverrepos/,.git*, absolute or..paths). A new site asset must be added tosite-files.txt.scripts/sources.sh— regeneratesdocs/SOURCES.md(one upstream URL per submodule, tier from the baseline).--checkHEADs every URL as a rot detector, non-zero exit on failure. Deterministic; never editSOURCES.mdby hand.rules/+scripts/rules.py— path-scoped rule packs (rules/<pack>/<topic>.md, frontmatterpaths:only). Opt-in viarules:<pack>/-rules:<pack>manifest entries (symlinked to$RULES_DIR/grid/<pack>/by wire.sh, see the wire.sh contract).rules.py lint|list|emit(stdlib only):lintruns in the gate,listis the pack inventory,emitrenders Cursor.mdcor anAGENTS.md/GEMINI.mdblock. Authoring:rules/README.md; user docs:docs/rules.md.scripts/check-personal.sh— scans the tracked tree for personal data (emails, home paths, tokens, private IPs, tailnet hosts, blocked file types, oversized files). Three rule sources, merged:scripts/personal-patterns.txt(public generic rules), the private denylist (~/.the-grid-private/denylist.txt, orGRID_PRIVATE_DENYLIST; findings print only[private:N], never the term), andscripts/personal-allow-paths.txt(paths skipped entirely: add one only with a# reason; prefer rewording the line). Voice rule: text rendered into other people's agents, skills, hooks or rules says "the operator", never the author's name; prose docs may name the author.GRID_REQUIRE_DENYLIST=1makes a missing denylist a failure; set it for any unattended build so it cannot pass on the generic half alone (a cut of the issue-loop into this repo should set it in itsVERIFY_CMD). CI has no denylist, so it runs the generic half only (GRID_PRIVATE_DENYLIST=disables the private half on purpose).docs/model-selection.md— which model for which job, with prices, independent benchmarks, worked cost maths, and a dated expiry watchlist. Refreshed on demand via thecore-researchersubagent using the brief at the bottom of the file.docs/business-tier/— design for giving non-terminal colleagues the grid through a business repo (the-grid-<business>). v0 built as a plain repo with a plugin marketplace for git users and a skill zip upload for everyone else (ADR-009); the delegation gate is answered (ADR-008). Start at itsREADME.md; issue #274.evals/+agent-factory/run_evals.py— golden cases for roles (opt-in, capped, tool-less runs;--validateruns in the gate). Seeevals/README.md.scripts/instantiate.sh+automation-factory/patterns/issue-loop/— the issue-loop.bash scripts/instantiate.sh issue-loop <repo> --profile workcuts a trackedloop/(verbatim copies,loop.confrendered once, labels created) into a repo; the cut repo'sloop/run-issue.sh(started by hand) works ONE labelled issue headlessly: the runner runsVERIFY_CMDitself (--fast-verifyselects the changed-filesloop/verify.sh), then, byMODE:prpushesissue-<N>and opens a draft PR for a human to merge;directrebases onto the base (re-verifying if it moved), pushes toBASE_BRANCHwith no PR and closes the issue (headless direct needs the runner, which a--mode directcut does not ship: cutpr, then setMODE=directinloop/loop.conf). It never classifies; onlydirectlands code without a human merge.MAX_ISSUES_PER_DAY=0(default) is unlimited; a stale lock (dead pid) is taken over; infra failures (logged-outclaude/gh, unreachable origin, rate limit) exit 1, keep the label and back off 15 min doubling to 6 h.--cron-every N(prcut) prints one crontab line per repo, never installs it. The push/merge guard reaches only the worker, through the runner's per-run--settings; it is never wired into the-grid's own.claude/settings.json(so merge-on-green sessions here are not blocked). Config isloop/loop.conf(ISSUE_REPOlets issues live in a separate tracker). See the pattern README; the live instance's operating runbook (run, watch, feed, sync) isdocs/issue-loop-runbook.md. Uplift is built by worktree agents and PRs tomain.scripts/lib/render-schedule.shis shared by the usage and instincts schedulers._retired/— archive, not gated, linted or deployed; removal waits for the operator's GitHub-side cleanup.scripts/instincts.sh— habit learning from your own sessions (opt-in per project withlearning: on): capture, weekly analysis, injection,clustersfor tankevolve. Data stays in${GRID_STATE_DIR:-~/.grid}and the private repo. Seedocs/instincts.md.scripts/run-record.sh— appends one JSON line per agent run to a local private log (${GRID_RUN_LOG:-~/.the-grid-private/runs.jsonl});docs/agent-retro.mdis the review loop that starts from it.policy.yaml— vetting policy read byscripts/audit.py: rule regexes with severities (highblocks,lowwarns), file classes,owned_roots, andsources.allowed_repos(the single source allowlist; no other file carries one). Restricted-YAML subset read byscripts/lib/miniyaml.py(it rejects any bare scalar PyYAML would type differently, such asTrue,010,1:30or a date: quote it; an unknown top-level key is exit 2); every regex is a single-quoted scalar.CURATION.md— the human-readable trust record: a### repos/<name>section per trusted wired repo, an## Exclusionstable, and the fencedaudit-allowblock (rule + path glob +contains+ mandatoryreason) thataudit.pyreads as its allowlist. Only the headings and the allowlist block are machine-checked.scripts/audit.sh/scripts/audit.py— the offline, deterministic scanner for wired content (audit.pyscans;audit.shchooses what). The D3 interface other changes build on:python3 scripts/audit.py --format json --root <root> DIR...andbash scripts/audit.sh --owned|--wired|--gate [TARGET...].wire.shruns--wiredbefore touching any link;gate.shruns--gateas theauditcheck. SKILL.md / agent frontmatter is vetted by shape (scripts/lib/fmshape.py: anything outside a tiny plain-YAML whitelist is afrontmatter-complexfinding that an allowlist line must pin) and itshooksblock byscripts/lib/fmyaml.py(deny by default). Seeopenspec/changes/vetting/design.md.agent-factory/models.yaml— the one tier-to-model map for generated Claude Code agents (default: tier maps to itself);role.yamlalso takestools:(subagent allowlist) andunattended:. Seeagent-factory/README.md.hooks/+agent-factory/deploy_hooks.py— Claude Code guard hooks (launcherhooks/run.sh,hooks/catalogue.jsonas the one place scope, profile and token cost are defined) and the emitter that writes a project's chosen profile (off|minimal|standard|strict, from thehooks:key of.grid/project.yaml) into its.claude/settings.local.json(orsettings.jsonwithtarget: shared) without touching hand-written hooks.--listshows costs,--checkreports drift. Seehooks/README.mdandagent-factory/README.md.scripts/compose-goldens.sh— golden-output check forcompose.pyover a fixture project, every compose target (theTARGETSlist in the script;--checkdefault,--updateto regeneratetests/fixtures/compose/golden/; run--updatein any PR that changes compose output). Seeagent-factory/README.md.agent-factory/user.public.yaml— tracked neutral identity (machine: "your-machine"); use viaGRID_USER_CONFIGfor anything composed into a tracked or shipped file.contexts/— opt-in working-mode prompts (dev.md,research.md,review.md, each <=1200 bytes) andaliases.sh, a snippet a human sources from~/.zshrc/~/.bashrcto getclaude-dev/claude-research/claude-review(claude --append-system-prompt-file). Not wired bywire.sh; Claude Code only.tests/— bats test suite. Run withtests/lib/bats-core/bin/bats tests/. Tests and scripts must run on Linux (authoritative) and macOS (BSD userland, the 3.2 system bash): rules and helpers indocs/portability.md.repos/— sibling skill repos as git submodules. Each submodule may contain multiple skill dirs.scripts/grid— the submodule-free install CLI (install,lock,drift,schedule,doctor,repair,uninstall,auditpassthrough). One stdlib Python 3.8+ file;python3 scripts/grid --help. The install path for users isBOOTSTRAP.md"Install without submodules".grid.yaml— where wired skills come from: oneurlper source (key = dir underrepos/) plus the tracked baseline file that selects the default set. Read withscripts/lib/miniyaml.py.grid.lock— generated bypython3 scripts/grid lockfrom the submodule checkouts: per skill, the source commit, tree and content hash thatgrid installfetches and verifies. Never edit by hand. A change that editsbaseline-submodules.example.txtor arepos/*pointer re-runspython3 scripts/grid lockin the same PR;gate.shfails thelockcheck (grid lock --check) otherwise.~/.grid/installed.manifest— machine-local ledger of the directoriesgrid installplaced (${GRID_STATE_DIR:-~/.grid}). Not in the repo. No ledger means maintainer mode:grid repairhas nothing to repair;grid doctorstill checks the links.scripts/map.py+MAP.md—MAP.mdis the generated session-start map (files with a "Read when" column, roles, delegation, canon one-liners, memory rules); never hand-edit it, runpython3 scripts/map.py.--checkruns ingate.shasmap: it reportsMAP.mddrift and also lintssignals/andknowledge/throughscripts/knowledge.py(stage enum and layout, signal grammar, edits after commit, ledger consistency, warrant against the stage ceiling, address resolution), printingE_<CODE> path: messagelines, and exits 0 clean, 1 on drift or a finding, 2 when a file cannot be read;python3 scripts/map.py statusprints stage and pending-signal counts and is not checked. The copy underproject-factory/templates/_common/scripts/must stay byte-identical (batscmp).scripts/knowledge.py— the signal/knowledge helper:hash,file,check,plan,apply. Mirrored byte-identically toproject-factory/templates/_common/scripts/knowledge.py.scripts/stamp-counts.py— counts inREADME*.md/index.html(<!--count:NAME-->N<!--/count-->markers) come from theSKILLS.mdheadline and the- role:lines inagent-factory/examples/*.yaml;catalog.shrestamps them after writing the defaultSKILLS.md,gate.shchecks them ascounts. Never type those numbers.PURPOSE.md— what the-grid is for (problem, intended solution, outcome).GUARDRAILS.md— must-nots, oneG<n>line each with its check.BEHAVIOUR.md— this repo's additions to the agent defaults inagent-factory/_core/AGENTS_base.md. Both PURPOSE and GUARDRAILS are operator-approved (commit 3ef0287).signals/+knowledge/— the per-repo conventions for filing a claim (signals/README.md) and keeping entries by stage (knowledge/README.md,knowledge/canon/human-approved). No sweep runs yet;signals/→<agent>.mdhandoffs share the directory. The trailhead block at the top of this file isproject-factory/trailhead.md.TODO.md— current outstanding work.
Getting a machine up to date
Plain-English sequence for the three things a machine needs: current
submodules (the sibling skill repos), current skills (symlinked into
~/.claude/skills/), current agents (composed subagents + orchestrator
skills, symlinked into ~/.claude/agents/).
New machine (never had the-grid before)
- Clone the-grid to
~/.the-grid. - Pull in submodules:
git submodule update --init --recursive. - Seed your wiring manifest (gitignored, personal — see #24):
cp baseline-submodules.example.txt baseline-submodules.txt && cp machines/example.txt machines/"$(hostname -s)".txt, then edit both to taste. Skip a file that already exists. - Wire skills:
bash scripts/wire.sh— skills are live now. - Set up install identity — only if
agent-factory/user.yamldoesn't already exist (once per install, not once per session): copy it fromagent-factory/user.yaml.example, then ask the human who the operator is (name + contact), what channels they're reachable on, and any other field the template asks for — don't guess, don't leave it silently blank, and don't skip asking just because every field is technically optional. Write their answers intoagent-factory/user.yaml. This is install-level config: it lands on every composed agent's IDENTITY nameplate (see agent-factory section below).machinealone can be left blank — it falls back to the local hostname. - Build the agent teams:
cd agent-factory && python3 -m venv .venv && .venv/bin/pip install -r requirements.txt && .venv/bin/python compose.py examples/core.yaml --target claude-code && .venv/bin/python compose.py examples/grid.yaml --target claude-code && .venv/bin/python compose.py examples/finance-desk.yaml --target claude-code && .venv/bin/python compose.py examples/learning-desk.yaml --target claude-code. (Four public projects, composed independently — a private desk, if you have one, composes the same way withGRID_PRIVATE_ROLES_DIRset; see the agent-factory section below.) - Wire again from the repo root:
bash scripts/wire.sh— agents are live now.
(Steps 2, 3, 4, 6, and 7 — everything except the optional identity config in
step 5, which needs a human to fill it in — are exactly what scripts/bootstrap.sh
--with-agents does in one shot.)
Existing machine (already set up, just did git fetch && git pull)
- Pull the-grid itself — done (that's what triggered this).
- Refresh submodules to match what the pull moved the pointers to:
git submodule update --init --recursive. Refresh agents — but only if the pull touched anything under
agent-factory/(composed output there is git-ignored, so a pull alone never updates it). Check with:git diff --stat HEAD@{1} HEAD -- agent-factory/. If it shows changes:cd agent-factory && .venv/bin/python compose.py examples/core.yaml --target claude-code && .venv/bin/python compose.py examples/grid.yaml --target claude-code && .venv/bin/python compose.py examples/finance-desk.yaml --target claude-code && .venv/bin/python compose.py examples/learning-desk.yaml --target claude-code && cd ..(recompose all four public projects — cheap even if only one actually changed). If it shows nothing: skip this step.⚠ Recompose every private project too, in the same pass. A change to
agent-factory/_core/orcompose.pyaffects all projects, but only the four public configs are listed above.compose.pyoverwritesprojects/<name>/wholesale — so recomposing the public set while a private project's roles are unreachable (repo not cloned,GRID_PRIVATE_ROLES_DIRunset) silently destroys that project's composed output, and the nextwire.shtears down its symlinks. This has already happened once. Checkls agent-factory/projects/againstmachines/<host>.local.txtbefore recomposing; if aproject:gate there has no matching config you can reach, stop and fix that first.- Refresh skills (and agents, and
SKILLS.md) in one go:bash scripts/wire.sh. Always safe to run, always run it last.
Drift checks, the commit gate, and per-project agents
scripts/gate.sh— the gate. A plain run (and--strictin CI) is the heavy merge-time gate;.githooks/pre-commitruns onlygate.sh --pre-commit, a FAST check of staged files (shellcheck on staged.sh/.bash, python syntax on staged.py, bats for stagedtests/*.batsonly; it aborts only if a staged.batsfile also has unstaged edits). The script self-installscore.hooksPathon first run. Runbash scripts/gate.shbefore readying a branch.GRID_SKIP_HOOK=1/--no-verifybypass it. Merges/rebases skip it.--strict(CI) fails on any skip not named inGRID_GATE_EXPECT_SKIPPED(see.github/workflows/tests.yml). CI splits the gate: achecksjob (gate.sh --strict --no-bats) and abatsmatrix of four shards (gate.sh --strict --shard <name>, files listed intests/shards.txt), aggregated by the one job namedgate, which passes only if every needed job issuccess(cancelled and skipped fail). A docs-only change (markdown outsideskills/,agents/,agent-factory/,rules/,plugins/,project-factory/,automation-factory/,hooks/,evals/,tests/,.github/) runs the lightdocsjob (personal, map, counts, front-door bats) instead ofchecks/bats, andgatepasses on it. A newtests/test_*.batsfile must be added totests/shards.txt;tests/test_gate.batsfails otherwise.catalog,sources(sources.sh --check-drift) andbudgetrun against the TRACKEDbaseline-submodules.example.txt(GRID_BASELINEpin;wire.shpins it for SKILLS.md too), so SKILLS.md, docs/SOURCES.md and the ratchet are machine-independent; a personal baseline is never gated. It runscheck-personal.shas thepersonalcheck; with no private denylist on the machine (CI, forks) it passes and printsgate: PASS (skipped: personal-denylist). It runsaudit.sh --gate --quietas theauditcheck (owned assets + the baseline's wired set; skipped loudly ifpython3orscripts/audit.shis absent). If a baseline submodule is uninitialised,audit.sh --gateexits 2 ("wired set NOT scanned") unless--allow-partialis given;gate.shpasses it only whenCIis unset and then listsaudit-wiredas skipped, so CI stays strict.- Read-only drift detectors (exit 1 on drift, write nothing):
catalog.sh --check,wire.sh --check,agent-factory/compose.py <cfg> --target claude-code --check,compose.py --lint-roles(every role; stableE_*codes;roles/_retired/is an archive that is never linted/composed/deployed). - Role authoring contract:
agent-factory/docs/role-authoring.md("facts, not persona"). Roles listed inagent-factory/authored-roles.txtare held to it bycompose.py --lint-roles(requiredAGENTS.mdsections, ranked list, hard rules,SOUL.mdheadings, ≤4KB). Enrol a role there once it has been through the pass. - Private roles:
compose.pyreadsGRID_PRIVATE_ROLES_DIR, else falls back to~/.the-grid-private/rolesif that directory exists (set the var to empty to disable). A private role of the same name wins over a public one. wire.shwrites.wired.manifest(gitignored; kind/name/target/status/reason) — rewritten only when it changes.- Per-project agents:
agent-factory/deploy.py <project> --roles a,b [--profile lean|full]writesgrid-<role>agents/skills into<project>/.claude/from the same role sources (lean = role judgement + scope + procedure, no persona/memory/boot sequence; the SKILL's template/checklist sections are written to.claude/grid-reference/grid-<role>.mdand read on demand, not inlined). Project facts come from<project>/.grid/project.yaml, never from the grid. Generated files carry a marker; hand-written files are never overwritten;.claude/grid-agents.lockrecords roles/profile/hashes;--checkreports drift. Seeded into new projects by project-factory (AGENTS-SETUP.md,.grid/project.yaml).
Adding a skill
Create skills/<name>/SKILL.md (a skill dir at the repo root is not wired). Frontmatter requires name: and description:. Then run bash scripts/wire.sh.
A SKILL.md over 4,000 bytes is split: keep the purpose and step skeleton, move reference detail into sections/<topic>.md (plain markdown, no frontmatter, <= 6,000 bytes, kebab-case).
Index each file in a ## Sections block of SKILL.md, one - sections/<file>: read when ... line per file; wire.sh symlinks the whole skill dir, so sections/ travels with it.
python3 scripts/budget.py --check (part of the gate) fails on an unindexed or missing section, a section over 6,000 bytes, or a SKILL.md over skill_body_max_bytes.
Regenerating the skill catalogue
bash scripts/catalog.sh # rewrites SKILLS.md from every SKILL.md's frontmatterscripts/wire.sh calls scripts/catalog.sh automatically as its final step, so wiring and
SKILLS.md never drift — you rarely need to run it by hand. Output is sorted and
timestamp-free, so an unchanged skill set yields an identical file (clean diffs).
A repo-root SKILL.md (gstack marker) is excluded, matching wire.sh.
Adding a sibling repo
git submodule add <repo-url> repos/<name>
git submodule update --init
bash scripts/wire.shA newly added submodule is library by default (indexed, not wired). To wire its
skills live everywhere, add its repos/<name> dir name to baseline-submodules.txt
(or to a single machine's machines/<host>.txt overlay) and re-run
bash scripts/wire.sh. This keeps ~/.claude/skills/ small even as the-grid indexes
thousands of ecosystem skills.
Reference submodules (indexes, not skill collections)
Some submodules are awesome-lists / indexes with no SKILL.md files (e.g.
repos/voltagent — VoltAgent's awesome-openclaw-skills, a categorised index of
OpenClaw-ecosystem skills). These are kept for browsing and as a source for
skill-scout, not for wiring. They need no special config: wire.sh wires nothing
from them (no skills to find), and catalog.sh auto-detects the empty case and lists
them under "Reference submodules" in SKILLS.md instead of an empty skill section.
Refresh one with git submodule update --remote repos/<name>.
Reconciling a machine (removing stale shadows)
wire.sh won't clobber a real directory that shadows a grid skill (safety).
On a fresh machine those shadows are often stale, root-owned copies. reconcile.sh
moves them aside so the-grid owns the slot, then re-wires. It learns the names from
a dry wire into a throwaway home (GRID_DRY_HOME), so it never hardcodes names.
bash scripts/reconcile.sh # dry run — list shadowing dirs
bash scripts/reconcile.sh --force # move them to a dated backup dir (audit gate first, sudo only where needed) + re-wireIdempotent: a fully-wired machine reports "Nothing to reconcile".
Running tests
tests/lib/bats-core/bin/bats tests/Write portable shell and tests: read docs/portability.md first (helpers file_mode, sed_i, mktemp_canon; avoid coproc, grep -P, stat -c, bare mktemp). All tests must stay green (run bash scripts/gate.sh for the full commit gate: shellcheck, catalog.sh --check, role lint (compose.py --lint-roles), compose.py --check per composed project (local only: composed output is gitignored, so CI runs the lint and lists the uncomposed projects as compose-<name> skips), check-personal.sh, bats). Tests use temp dirs — they never touch the real ~/.claude/skills/ or ~/.claude/agents/. Venv-gated tests (agent-factory/.venv with PyYAML) skip on a plain bats run, but FAIL when GRID_REQUIRE_VENV=1 or CI=true (the gate sets the former). In a @test, write ! cmd || false and one [ ] per line: a bare mid-test ! cmd or [ A ] && [ B ] can never fail (test_repo_health.bats lints this).
Canon is never merged on green
A PR that changes any path under knowledge/canon/ is never merged under the standing approval to merge on green CI plus independent QA; a human merges it (GUARDRAILS#G7).
Before merging, the QA agent or session runs git diff --name-only origin/main...HEAD -- knowledge/canon (the same command as the PR template checkbox).
Non-empty output means a human merges: stop and leave the PR open.
Worktree hygiene
Agents and sessions must not leave stale worktrees or local branches behind.
- Remove what you created before finishing, once its PR is merged or abandoned:
git worktree remove <path>. - Delete the branch with
git branch -D <branch>only after confirming the PR is MERGED or the branch is fully contained inorigin/main. - Never leave scratch worktrees under
.claude/worktreesor/tmpregistered ingit worktree list; rungit worktree prune. - Session start: run
git worktree list, report and prune stale entries. Session end: list any worktree left open and why. - Untracked
__pycache__is not a reason to keep a worktree. - A fresh worktree has empty submodule dirs and no
agent-factory/.venv. The pre-commit hook initstests/lib/bats-coreitself; any other submodule a test needs (for examplerepos/ecc) and the venv (cd agent-factory && python3 -m venv .venv && .venv/bin/pip install -r requirements.txt) are yours to set up. Venv-gated tests skip on a plainbatsrun but fail under the gate (GRID_REQUIRE_VENV=1). To commit without either, useGRID_SKIP_HOOK=1and run the gate before readying the branch.
wire.sh contract
GRID_DIRenv var overrides the repo root (default: script's own directory).SKILLS_DIRenv var overrides the skills target (default:~/.claude/skills/).AGENTS_DIRenv var overrides the subagents target (default:~/.claude/agents/).- Only manages symlinks that point into
GRID_DIR— never touches foreign symlinks. - Skills in
repos/*/are discovered at any depth viafind(flat,skills/,skills/<category>/, etc.) — wire.sh symlinks each dir containing aSKILL.md, skipping aSKILL.mdsitting at a repo root. Discovery goes throughscripts/lib/find-skill-mds.sh(shared withcatalog.sh): in a submodule that is its own git checkout it lists tracked files only, so gitignored generated copies (gstack writes ~54 per host into.slate/,.kiro/, ...) are never wired or counted; a non-git dir falls back to plainfind. - Exclusion rule (same helper): even tracked paths are dropped when they are
translations (
docs/,i18n/,translations/,locales/+ a locale dir such asja-JP), live under a root-level dot-dir (.kiro,.agents, ... — per-harness copies or upstream maintainer skills), or match arepo | prefix/row inscripts/lib/skill-excludes.txt(currentlyecc | pi/). - Only submodules in the manifest (
baseline-submodules.txt+machines/<host>.txtoverlay) are wired; the rest are library-only. If no manifest exists, all repos are wired (legacy fallback).catalog.shreads the baseline only (machine-agnostic, deterministicSKILLS.md). - Machine key:
GRID_HOSTenv var overrides the overlay host (defaulthostname -s). - Audit before wiring (step 0): before any teardown
wire.shrunsaudit.sh --wired --quiet. A high-severity finding (or a broken policy) blocks with exit 3 and changes nothing, so existing links survive a bad upstream bump. A missingpolicy.yamlorpython3blocks the same way (fail closed).GRID_AUDIT=warnprints a warning and wires anyway.GRID_SKIP_AUDIT=1is the only bypass (it prints a stderr notice; audit.sh's own dry run sets it to avoid recursion), plus every dry run (GRID_DRY_HOME, so--check's child never audits).GRID_SKIP_CATALOGalone no longer skips the audit. A mock grid without apolicy.yamlmust setGRID_SKIP_AUDIT=1(the batscommon_setupdoes). The audit is point-in-time (runs at wire time and in the gate, not between;--checkdoes not re-audit) and covers skill and agent link targets only: runtime-rootbin/helpers are not scanned (accepted, seeCURATION.md). - Manifest problems are announced: a missing baseline file (default path, or
GRID_BASELINEset and absent) and arepo,repo/skill,-repoor-repo/skillentry that names no dir underrepos/print a stderr warning and add amanifestrow (missing/unknown) to.wired.manifest; the wire still runs. An absent per-host overlay is normal and silent. - Runtime map:
scripts/lib/runtimes.txt(repo | link | marker | needs | setup) lists wired repos whose skills need more than files on disk (gstack: its browse daemon). wire.sh keeps the runtime-root link$SKILLS_DIR/<link> -> $GRID_DIR/repos/<repo>(rebuilt each run, since teardown removes every grid link), skips it withruntime root occupiedif a real dir or foreign link is there, and printsruntime MISSING: <repo>(exit status unaffected) when the marker is absent. The setup itself is human-run:bash scripts/runtime-setup.sh <repo> [--dry-run](exit 2 prerequisite/occupied link, 3 if the Claude settings file changed or the finalwire.shwas blocked by the audit of the build output; it then prints the next command. A missingbunand the post-run notes are OS-aware wording only: macOS, Arch, Ubuntu/Debian). - Baseline override:
GRID_BASELINEenv var replaces the path of the first manifest layer (default$GRID_DIR/baseline-submodules.txt); machine overlays still load from$GRID_DIR/machines/. Tests and CI use it to wire frombaseline-submodules.example.txtwhen there is no personal baseline. - Teardown scope: teardown removes only links whose target RESOLVES to a path under
$GRID_DIR/(target_is_ours: the target's parent is resolved physically, a missing parent is normalised lexically; trailing slash, so a sibling dir like${GRID_DIR}-privateand$GRID_DIR/../xare never matched).GRID_DIRitself is canonicalised (pwd -P) at start, so every link carries one spelling. It follows a skills/agents dir that is itself a symlink (find -H) and tolerates newline names, in both the wire and--checkpaths. The link steps never replace a real file, a dangling link or a foreign link that shares a grid name (skip (not managed)). - Failure safety (no lock): registry dirs are resolved and every written dir is
checked writable BEFORE the first
rm; an unresolvable dir of an active harness or an unwritable dir is exit 2, nothing changed. Removed links are logged and an EXIT/INT/TERM/HUP trap restores any that are still absent unless the run completed (SIGKILL cannot be trapped: re-run wire). There is deliberately no lock: one wire at a time is the supported use (cron plus a manual run can race, so don't). - Machine hooks: wire.sh keeps one generated
auto-handoffSessionEnd entry in${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.jsonviaagent-factory/deploy_hooks.py --user(stdlib only; hand-written hooks and keys are never touched). On by default;-hook:auto-handoffin the baseline or a machine overlay turns it off and removes the entry (hook:auto-handoffre-enables; the last file wins; an unknownhook:<x>warns and is ignored). Skipped in every dry run and when the emitter is absent;python3missing or an emitter failure is a warning, not a failed wire.--checkalso reports drift in that file (exit 1) and writes nothing. Records ahookrow in.wired.manifest. - Dry home:
GRID_DRY_HOME=<dir>forces every home-derived target under it (HOME,SKILLS_DIR,AGENTS_DIR,CLAUDE_CONFIG_DIR,RULES_DIR,GRID_HARNESS_HOME; inherited values are ignored) and skips theSKILLS.md/.wired.manifestwrites. Every dry-run caller must use it (and nothing else);--checkandtests/helpers/wired.bashdo. - Rule packs:
rules:<pack>/-rules:<pack>manifest entries (baseline or overlay) symlink eachrules/<pack>/*.md(neverREADME.md) to$RULES_DIR/grid/<pack>/(RULES_DIR, default~/.claude/rules; onlygrid/is grid-owned). Opt-in: norules:entry means nothing is wired. An unknown or unsafe pack name warns and is skipped (rulerow in.wired.manifest);--checkalso reports rules drift. - Harnesses:
harness:<name>/-harness:<name>manifest entries (orGRID_HARNESS=a,b, which replaces the manifest set for one run) also link the wired skills, and composed_<compose_target>/agents/*, into other harnesses' dirs from the registryscripts/lib/harnesses.txt(codex, opencode, gemini, antigravity, pi, openclaw;~/.agents/skillsis shared by five). Opt-in; an unknown name exits 2. Never replaces an existing entry in those dirs; skip reasons land in.wired.manifest.rules:packs are also delivered into an active harness's global instruction file viarules.py emit, but only if the operator created that file (never created, never written through a symlink). Seedocs/harnesses.md. - Composed agents: wire.sh also wires
agent-factory/projects/*/_claude-code/output — orchestrator skills intoSKILLS_DIR, specialist subagents intoAGENTS_DIR. Gated per machine byproject:<name>manifest entries; with noproject:entry anywhere, every composed project wires (legacy). The example baseline pinsproject:core,project:grid,project:finance-deskandproject:learning-desk(seeagent-factory/and issue #1) — a task-specific machine can subtract-project:grid,-project:finance-deskor-project:learning-deskvia its overlay to trim clutter, butproject:core(gh-triage, librarian, researcher, platform-engineer, context-engineer, tron) is meant to stay on every machine. - Root-owned agents:
agents/*.mdat the repo root wires directly intoAGENTS_DIR, same ownership model as root-levelskills/— for hand-authored subagents that aren't a compose.py role (nodelegates_to, not a team position; e.g. a ported persona/behavior-modifier likegrid-ponytail). Wired last, so a root-owned agent overrides a same-named composed one. - No-catalog mode:
GRID_NO_CATALOG=1skips only theSKILLS.mdrefresh (.wired.manifestis still written).grid installsets it for its ownwire.shruns so a partial, submodule-free machine never rewrites the tracked catalogue; useGRID_NO_CATALOG=1 bash scripts/wire.shto re-wire such a machine by hand. - Typed entries:
scripts/gridignores typed manifest entries (project:,rules:,harness:, anykind:); onlywire.shacts on them.grid installreads untypedrepo/repo/skill/-repo/-repo/skilllines only.
agent-factory (composed agents)
agent-factory/ composes AI dev-team agents from a single config
(role × stack × skills). compose.py is a multi-target compiler: one source (the
live OpenClaw 5-file identity model — SOUL/IDENTITY/AGENTS/USER/MEMORY + skills)
emits to different runtimes via --target. The Claude Code target is built and
wired live: orchestrator roles (role.yaml orchestrator: true) → CC skills
(invoke with /<role>); specialist roles → CC subagents (delegate to them, or
an orchestrator hands off). OpenClaw + Paperclip (autonomous) targets are the next
work. See agent-factory/README.md.
Orchestrator rosters are generated, not hand-written. Each orchestrator declares
its reports via delegates_to: in the compose config (the delegation topology lives
with the team, the single source of truth). compose.py renders a roster table from
that list and injects it at the {{ROSTER_TABLE}} token in the role's AGENTS.md
(owns text = role.yaml owns: override, else the summary's first sentence). Validation
is symmetric and loud: a token with no delegates_to (or vice-versa), or a delegate not
on the team, is a hard compose error — so a roster can never silently drift out of sync
with the team. grid topology: ceo → tech-lead, product-manager, growth-hacker;
tech-lead → eng + data; growth-hacker → the marketing arm (a player-coach
orchestrator). gsd is the light fan-out for small fixes (one specialist per
independent fix, merge, independent QA; /gsd, bare: true): standalone, not under
the CEO, and tech-lead keeps PRDs and the release gate. examples/grid.yaml is the
dev-team project — 25 roles: 4 orchestrators → CC skills, 21 specialists → CC subagents.
Four public projects (grid above; finance-desk, core and learning-desk below), same repo, composed and gated independently:
examples/finance-desk.yaml — finance-manager → the finance desk pipeline
(sentinel → analyst → strategist → risk-officer → scribe), a standalone
top-level orchestrator, deliberately never under the CEO's delegates_to — a
personal desk, not a dev-team initiative. examples/core.yaml — cross-desk
shared infra with no delegation chain (gh-triage, librarian,
researcher — the general-purpose investigator, domain-general on purpose
and gated here so it survives -project:grid; platform-engineer — personal
dev-environment portability across macOS/Ubuntu/Arch, likewise; context-engineer —
what loads into a session and its budget, likewise; tron — the
front door, /tron, likewise), gated
project:core and meant to stay wired on every machine regardless of which
desk-specific project (grid, finance-desk, learning-desk, or a private desk) that
machine actually runs — the projects split apart specifically so a
task-specific machine can subtract a whole desk via its overlay
(-project:grid, -project:finance-desk) without losing the others. A
private desk (e.g. a personal research vertical) can be composed the same
way, sourcing roles from GRID_PRIVATE_ROLES_DIR — never committed to this
repo; see compose.py's role_dir().
examples/learning-desk.yaml — the learning agents, all operator-triggered:
morpheus (Socratic tutor for any topic; /morpheus), oracle (learns about
the operator, who picks their own name/role/avatar; /oracle), tank
(agent-to-agent lessons from the run log; proposes diffs, never edits a role).
Roles are public; data is private and lives in ~/.the-grid-private/learning/
(morpheus/, operator/, tank/). /tron (in core) is the front door: it reads
what is wired and recommends a route; /grid-help stays the static reference.
Interactive roles (morpheus, oracle, tron) are orchestrator: true with no
delegates_to — that is the only way compose emits a skill (main session,
can hold a dialogue); specialists become subagents and cannot. Composed names are
<slug>-<role> by default; bare_names: true (project) or bare: true (one agent
entry) gives /<role> instead — keep bare role names unique across wired projects.
Rollout note:
agent-factory/projects/*is git-ignored (regenerable output). A machine picks up roster/topology changes only aftergit pullthen re-runningcompose.py(BOOTSTRAP step 6, or step 3 of "Updating an existing machine") andwire.sh— pulling alone is not enough.
Spec-driven development (OpenSpec)
the-grid wires OpenSpec (repos/openspec, MIT) on every
machine — 12 openspec-* workflow skills, gated as a whole-repo baseline entry
minus the maintainer-only release-openspec. They shell out to a CLI that is
not vendored: npm i -g @fission-ai/openspec@latest (Node >= 20.19.0). Without
it every one of those skills is inert.
There is deliberately no fifth "spec-factory". OpenSpec already is the spec factory; what the-grid adds is two thin layers:
project-factory/templates/_common/SPECS.md— the convention, both adoption paths (greenfieldopenspec init; brownfield = specs grow per-change, never big-bang back-filled), and agent instructions. In_common, so every cut project gets it, seed or retrofit — spec-driven is the default, not a per-project decision someone has to remember. It documents only; the CLI owns theopenspec/tree it creates.agent-factory/_core/AGENTS_base.md— a boot-sequence check forSPECS.md/openspec/. One edit reaches all 40 composed public roles across the four projects. Conditional: repos without the markers are untouched.
skills/spec-scout/ audits adoption and reports spec↔code drift (survey-only,
mirroring skill-scout — never runs openspec init, never writes specs).
project-factory (project bootstrapping)
project-factory/ scaffolds whole new projects from a template — a different job
from skills/ (wired), agent-factory/ (composes personas), and
automation-factory/ (cuts a pattern into an existing repo's .claude/-adjacent
loop/). A project-factory template is standalone: no logic of its own, doesn't
run, doesn't depend on the-grid once cut. project-factory/scripts/cut-project.sh <template>
<target-dir> either seeds a brand-new project (empty target) or retrofits
an existing one (non-empty target) — same script, same rule either way: never
overwrite a file that already exists and differs from the template; anything
skipped is reported for manual review. Composition (which agent-factory
persona, which skills, which automation-factory pattern) happens after
seeding, as a normal step in the resulting repo — project-factory itself stays
out of that decision. See project-factory/README.md.
Learnings
Durable lessons mined from project history — full context and sources in
LEARNINGS.md (generated/maintained by the mine-learnings skill).
- Scripts whose output is committed/diffed across machines (like
catalog.sh) must pin locale (LC_ALL=C) and compute counts from a controlled pre-pass, not a rawfind/wcsweep — see LEARNINGS.md ("Cross-machine scripts must pin locale..."). - Skills that write files from multiple machines (like
handoff) must scope filenames by hostname and verify target directory names rather than assume them — see LEARNINGS.md ("Handoff output paths..."). - Library-tier submodules churn independently and can inflate curated counts;
keep headline skill totals derived only from wired/root-owned skills, and
don't casually
--remoteupdate noisy library repos — see LEARNINGS.md ("Library submodules can churn..."). - When writing role/
SKILL.mdinstructions for a rule that must never be violated (e.g. gh-triage skip logic), state it as an explicit imperative block — don't rely on step ordering to imply it — see LEARNINGS.md ("Agent instructions that must never be skipped..."). - Don't write bash-style unquoted-
$varword-splitting in ad-hoc shell commands — Gareth's machines may run zsh, which doesn't word-split by default — see LEARNINGS.md ("zsh doesn't word-split..."). - A cron-driven, non-delegating role (e.g.
gh-triage) doesn't need a project of its own — but a sharedcoreproject for cross-desk infra (roles no single desk owns, meant to survive that desk being subtracted on a task-specific machine) is a real category, not project-proliferation for its own sake.gh-triage,librarian,researcher,platform-engineer,context-engineerandtronall live there now. - A role only looks team-owned until you ask what happens when that team is
gated off.
researcher's method was always domain-agnostic — only its membership ingrid.yamlmade it look like a dev-team role. Moving it tocorecost onedelegates_toedit and a routing note in the orphaned orchestrator; the role content didn't change at all. - Splitting a desk (e.g.
finance-desk) out of a larger composed project is free when that desk's orchestrator was already standalone (not in anyone'sdelegates_to) — the delegation topology doesn't change, only which compose config file it's read from. - A composed role's own bundled
SKILL.md("its operating procedure") can share a bare name with an unrelated wired ecosystem skill (e.g. thesecurity-reviewerrole's procedure vs. jeffallan's wiredsecurity-reviewerskill) — that's a naming coincidence, not a relationship, and reads as one in prose ("lives in itssecurity-reviewerskill") unless a role's AGENTS.md says explicitly which one it means. Check for this collision whenever a role name and a wired skill name match. - Before pointing a role at a wired skill for some capability, check whether
another wired skill already covers the same ground —
jeffallan/debugging-wizardandsuperpowers/systematic-debuggingboth do hypothesis-driven root-cause debugging, but they're not duplicates:debugging-wizardexplicitly credits and incorporatessystematic-debugging's phase methodology as one of its own reference docs, adding stack-trace/log-correlation tooling and per-language debugger commands on top, whilesystematic-debuggingis already the universal default everywhere viasuperpowers'using-superpowersskill — so neither needs a role-specific routing note on its own. - Claude Desktop's two surfaces wire differently: the Code tab reads the wired
~/.claude; Cowork reads only plugins installed in Cowork and runs subagents in a cloud container with staged copies (write-back replaces originals) — see LEARNINGS.md ("Claude Desktop surfaces differ...") andINSTALL.md. - After an upstream history rewrite,
git cherry/patch-id reports false unmerged commits; countgit rev-list <old-main>..<branch>from the reflog, match subjects against the new main, thengit reset --hard origin/main— see LEARNINGS.md ("Reconciling local branches after an upstream history rewrite").
About
the-grid is Gareth's brainchild — a personal, evolving system for organising and wiring up his Claude skills. Intended to eventually be a public repo. Treat it as an extension of how Gareth thinks and works, and keep it tidy as it grows.
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.

