agentleFS
oneafrikanoneafrikan/the-grid/CLAUDE.md

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

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
  1. Very specific:

    Before acting (editing, committing, opening a PR): read GUARDRAILS.md.

    line 5
  2. Very specific:

    Before building a new capability or adding a dependency: read RELATED.md if it exists.

    line 7
  3. Very specific:

    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 …

    line 39
  4. Very specific:

    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 …

    line 45
  5. Very specific:

    When skills/ and a submodule both provide the same skill name, the skills/ copy wins (wire.sh wires repos first, skills/ last).

    line 47
  6. Distinctive:

    If it shows changes:

    line 192
  7. Distinctive:

    If it shows nothing: skip this step.

    line 198
  8. Distinctive:

    Always safe to run, always run it last.

    line 211
  9. Very specific:

    Read-only drift detectors (exit 1 on drift, write nothing): catalog.sh --check, wire.sh --check, agent-factory/compose.py <cfg> --target …

    line 233
  10. Very specific:

    Create skills/<name>/SKILL.md (a skill dir at the repo root is not wired).

    line 257
  11. Very specific:

    Before merging, the QA agent or session runs git diff --name-only origin/main...HEAD -- knowledge/canon (the same command as the PR …

    line 323
  12. Very specific:

    Remove what you created before finishing, once its PR is merged or abandoned: git worktree remove <path>.

    line 330
  13. Very specific:

    Delete the branch with git branch -D <branch> only after confirming the PR is MERGED or the branch is fully contained in origin/main.

    line 331
  14. Very specific:

    Never leave scratch worktrees under .claude/worktrees or /tmp registered in git worktree list.

    line 332
  15. Very specific:

    Only manages symlinks that point into GRID_DIR — never touches foreign symlinks.

    line 342
  16. Very specific:

    Only submodules in the manifest (baseline-submodules.txt + machines/<host>.txt overlay) are wired.

    line 355
  17. Very specific:

    Audit before wiring (step 0): before any teardown wire.sh runs audit.sh --wired --quiet.

    line 360
  18. Very specific:

    Never replaces an existing entry in those dirs.

    line 428
  19. Very specific:

    When writing role/SKILL.md instructions for a rule that must never be violated (e.g.

    line 572
  20. Very specific:

    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 …

    line 576
  21. Very specific:

    Before pointing a role at a wired skill for some capability, check whether another wired skill already covers the same ground — …

    line 600
  22. Distinctive:

    After an upstream history rewrite, git cherry/patch-id reports false unmerged commits.

    line 613

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

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md
<!-- charter-trailhead -->

Start here

  • 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 — 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 shared baseline-submodules.txt (wired on every machine) plus an optional per-machine overlay at machines/<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 from baseline-submodules.example.txt / machines/example.txt.
  • Library — everything else: indexed in SKILLS.md and searchable by skill-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 into skills/ 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 the skills/ dir and let the submodule own the slot.
  • When skills/ and a submodule both provide the same skill name, the skills/ 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 via project:<name> entries. Delete the file to wire everything (legacy). Gitignored, not tracked (#24) — personal curation. A fresh machine seeds its own from the tracked baseline-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 from machines/example.txt on a new machine.
  • LOGS/ — dev journal (handoffs/context from the handoff skill). 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. The handoff skill and the SessionEnd auto-handoff worker always write handoffs to the project's own LOGS folder (<repo root>/LOGS when the session ran inside a git repo, else <cwd>/LOGS; an existing logs/Logs/LOGS is 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 then git push the branch, which also publishes any other unpushed commit on it; with no repo the files are only written. See hooks/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: --check runs in gate.sh against a committed ratchet (owned skills + roles always; the baseline scope against the tracked baseline-submodules.example.txt once submodules are initialised, else exit 3 = skipped). A target missing per_entry_max_chars, owned.skill_body_max_bytes or schema: 1 fails. --report shows the numbers. Lowering a number is normal (--update-target); raising one needs --allow-raise and review.
  • scripts/usage/weekly.sh + scripts/usage/install-schedule.sh — the weekly usage job (extract, then commit usage/<host>.json to the private repo) and the installer that renders its launchd/systemd/cron schedule via scripts/lib/render-schedule.sh. The installer only writes files and PRINTS the activation commands; activating is a human step. See docs/usage.md.
  • scripts/prune-report.sh (wraps scripts/usage/prune_report.py; scripts/usage/aggregate.py is 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-only a skill, unused agents); docs/prune-keep.txt lists names never proposed. Never reads tokens/hooks. See docs/usage.md.
  • scripts/catalog.sh — regenerates SKILLS.md: wired skills in full detail, library repos as counts, reference (no-skill) repos in a footer. Deterministic output. The committed SKILLS.md is rendered from the tracked example baseline (GRID_BASELINE=baseline-submodules.example.txt bash scripts/catalog.sh; wire.sh and 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.json from plugins/bundles.json. plugins/ is generated output: regenerate with python3 scripts/build-plugins.py (needs agent-factory/.venv), never hand-edit. gate.sh runs --check and claude plugin validate --strict; audit.sh --owned scans plugins/.
  • scripts/translate-readme.sh + scripts/check-translations.sh — README translations (README.<locale>.md, locales in scripts/lib/readme-locales.txt, prompt in docs/translation-prompt.md). After README prose changes: bash scripts/translate-readme.sh --all; opt-in, costs tokens (one claude -p --model sonnet call per stale locale; --dry-run calls nothing, --switcher-only rewrites the language switchers with no model call). check-translations.sh [--strict] prints STALE <locale> (and MISSING <locale> with --strict); gate.sh runs it non-strict and only WARNs. The source hash ignores the switcher and count values (scripts/lib/readme-hash.sh). Tests stub the translator via GRID_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 (never repos/, .git*, absolute or .. paths). A new site asset must be added to site-files.txt.
  • scripts/sources.sh — regenerates docs/SOURCES.md (one upstream URL per submodule, tier from the baseline). --check HEADs every URL as a rot detector, non-zero exit on failure. Deterministic; never edit SOURCES.md by hand.
  • rules/ + scripts/rules.py — path-scoped rule packs (rules/<pack>/<topic>.md, frontmatter paths: only). Opt-in via rules:<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): lint runs in the gate, list is the pack inventory, emit renders Cursor .mdc or an AGENTS.md/GEMINI.md block. 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, or GRID_PRIVATE_DENYLIST; findings print only [private:N], never the term), and scripts/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=1 makes 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 its VERIFY_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 the core-researcher subagent 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 its README.md; issue #274.
  • evals/ + agent-factory/run_evals.py — golden cases for roles (opt-in, capped, tool-less runs; --validate runs in the gate). See evals/README.md.
  • scripts/instantiate.sh + automation-factory/patterns/issue-loop/ — the issue-loop. bash scripts/instantiate.sh issue-loop <repo> --profile work cuts a tracked loop/ (verbatim copies, loop.conf rendered once, labels created) into a repo; the cut repo's loop/run-issue.sh (started by hand) works ONE labelled issue headlessly: the runner runs VERIFY_CMD itself (--fast-verify selects the changed-files loop/verify.sh), then, by MODE: pr pushes issue-<N> and opens a draft PR for a human to merge; direct rebases onto the base (re-verifying if it moved), pushes to BASE_BRANCH with no PR and closes the issue (headless direct needs the runner, which a --mode direct cut does not ship: cut pr, then set MODE=direct in loop/loop.conf). It never classifies; only direct lands code without a human merge. MAX_ISSUES_PER_DAY=0 (default) is unlimited; a stale lock (dead pid) is taken over; infra failures (logged-out claude/gh, unreachable origin, rate limit) exit 1, keep the label and back off 15 min doubling to 6 h. --cron-every N (pr cut) 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 is loop/loop.conf (ISSUE_REPO lets issues live in a separate tracker). See the pattern README; the live instance's operating runbook (run, watch, feed, sync) is docs/issue-loop-runbook.md. Uplift is built by worktree agents and PRs to main. scripts/lib/render-schedule.sh is 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 with learning: on): capture, weekly analysis, injection, clusters for tank evolve. Data stays in ${GRID_STATE_DIR:-~/.grid} and the private repo. See docs/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.md is the review loop that starts from it.
  • policy.yaml — vetting policy read by scripts/audit.py: rule regexes with severities (high blocks, low warns), file classes, owned_roots, and sources.allowed_repos (the single source allowlist; no other file carries one). Restricted-YAML subset read by scripts/lib/miniyaml.py (it rejects any bare scalar PyYAML would type differently, such as True, 010, 1:30 or 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 ## Exclusions table, and the fenced audit-allow block (rule + path glob + contains + mandatory reason) that audit.py reads 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.py scans; audit.sh chooses what). The D3 interface other changes build on: python3 scripts/audit.py --format json --root <root> DIR... and bash scripts/audit.sh --owned|--wired|--gate [TARGET...]. wire.sh runs --wired before touching any link; gate.sh runs --gate as the audit check. SKILL.md / agent frontmatter is vetted by shape (scripts/lib/fmshape.py: anything outside a tiny plain-YAML whitelist is a frontmatter-complex finding that an allowlist line must pin) and its hooks block by scripts/lib/fmyaml.py (deny by default). See openspec/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.yaml also takes tools: (subagent allowlist) and unattended:. See agent-factory/README.md.
  • hooks/ + agent-factory/deploy_hooks.py — Claude Code guard hooks (launcher hooks/run.sh, hooks/catalogue.json as 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 the hooks: key of .grid/project.yaml) into its .claude/settings.local.json (or settings.json with target: shared) without touching hand-written hooks. --list shows costs, --check reports drift. See hooks/README.md and agent-factory/README.md.
  • scripts/compose-goldens.sh — golden-output check for compose.py over a fixture project, every compose target (the TARGETS list in the script; --check default, --update to regenerate tests/fixtures/compose/golden/; run --update in any PR that changes compose output). See agent-factory/README.md.
  • agent-factory/user.public.yaml — tracked neutral identity (machine: "your-machine"); use via GRID_USER_CONFIG for anything composed into a tracked or shipped file.
  • contexts/ — opt-in working-mode prompts (dev.md, research.md, review.md, each <=1200 bytes) and aliases.sh, a snippet a human sources from ~/.zshrc/~/.bashrc to get claude-dev/claude-research/claude-review (claude --append-system-prompt-file). Not wired by wire.sh; Claude Code only.
  • tests/ — bats test suite. Run with tests/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 in docs/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, audit passthrough). One stdlib Python 3.8+ file; python3 scripts/grid --help. The install path for users is BOOTSTRAP.md "Install without submodules".
  • grid.yaml — where wired skills come from: one url per source (key = dir under repos/) plus the tracked baseline file that selects the default set. Read with scripts/lib/miniyaml.py.
  • grid.lock — generated by python3 scripts/grid lock from the submodule checkouts: per skill, the source commit, tree and content hash that grid install fetches and verifies. Never edit by hand. A change that edits baseline-submodules.example.txt or a repos/* pointer re-runs python3 scripts/grid lock in the same PR; gate.sh fails the lock check (grid lock --check) otherwise.
  • ~/.grid/installed.manifest — machine-local ledger of the directories grid install placed (${GRID_STATE_DIR:-~/.grid}). Not in the repo. No ledger means maintainer mode: grid repair has nothing to repair; grid doctor still checks the links.
  • scripts/map.py + MAP.md — MAP.md is the generated session-start map (files with a "Read when" column, roles, delegation, canon one-liners, memory rules); never hand-edit it, run python3 scripts/map.py. --check runs in gate.sh as map: it reports MAP.md drift and also lints signals/ and knowledge/ through scripts/knowledge.py (stage enum and layout, signal grammar, edits after commit, ledger consistency, warrant against the stage ceiling, address resolution), printing E_<CODE> path: message lines, and exits 0 clean, 1 on drift or a finding, 2 when a file cannot be read; python3 scripts/map.py status prints stage and pending-signal counts and is not checked. The copy under project-factory/templates/_common/scripts/ must stay byte-identical (bats cmp).
  • scripts/knowledge.py — the signal/knowledge helper: hash, file, check, plan, apply. Mirrored byte-identically to project-factory/templates/_common/scripts/knowledge.py.
  • scripts/stamp-counts.py — counts in README*.md / index.html (<!--count:NAME-->N<!--/count--> markers) come from the SKILLS.md headline and the - role: lines in agent-factory/examples/*.yaml; catalog.sh restamps them after writing the default SKILLS.md, gate.sh checks them as counts. Never type those numbers.
  • PURPOSE.md — what the-grid is for (problem, intended solution, outcome). GUARDRAILS.md — must-nots, one G<n> line each with its check. BEHAVIOUR.md — this repo's additions to the agent defaults in agent-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>.md handoffs share the directory. The trailhead block at the top of this file is project-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)

  1. Clone the-grid to ~/.the-grid.
  2. Pull in submodules: git submodule update --init --recursive.
  3. 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.
  4. Wire skills: bash scripts/wire.sh — skills are live now.
  5. Set up install identity — only if agent-factory/user.yaml doesn't already exist (once per install, not once per session): copy it from agent-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 into agent-factory/user.yaml. This is install-level config: it lands on every composed agent's IDENTITY nameplate (see agent-factory section below). machine alone can be left blank — it falls back to the local hostname.
  6. 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 with GRID_PRIVATE_ROLES_DIR set; see the agent-factory section below.)
  7. 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)

  1. Pull the-grid itself — done (that's what triggered this).
  2. Refresh submodules to match what the pull moved the pointers to: git submodule update --init --recursive.
  3. 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/ or compose.py affects all projects, but only the four public configs are listed above. compose.py overwrites projects/<name>/ wholesale — so recomposing the public set while a private project's roles are unreachable (repo not cloned, GRID_PRIVATE_ROLES_DIR unset) silently destroys that project's composed output, and the next wire.sh tears down its symlinks. This has already happened once. Check ls agent-factory/projects/ against machines/<host>.local.txt before recomposing; if a project: gate there has no matching config you can reach, stop and fix that first.

  4. 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 --strict in CI) is the heavy merge-time gate; .githooks/pre-commit runs only gate.sh --pre-commit, a FAST check of staged files (shellcheck on staged .sh/.bash, python syntax on staged .py, bats for staged tests/*.bats only; it aborts only if a staged .bats file also has unstaged edits). The script self-installs core.hooksPath on first run. Run bash scripts/gate.sh before readying a branch. GRID_SKIP_HOOK=1 / --no-verify bypass it. Merges/rebases skip it. --strict (CI) fails on any skip not named in GRID_GATE_EXPECT_SKIPPED (see .github/workflows/tests.yml). CI splits the gate: a checks job (gate.sh --strict --no-bats) and a bats matrix of four shards (gate.sh --strict --shard <name>, files listed in tests/shards.txt), aggregated by the one job named gate, which passes only if every needed job is success (cancelled and skipped fail). A docs-only change (markdown outside skills/, agents/, agent-factory/, rules/, plugins/, project-factory/, automation-factory/, hooks/, evals/, tests/, .github/) runs the light docs job (personal, map, counts, front-door bats) instead of checks/bats, and gate passes on it. A new tests/test_*.bats file must be added to tests/shards.txt; tests/test_gate.bats fails otherwise. catalog, sources (sources.sh --check-drift) and budget run against the TRACKED baseline-submodules.example.txt (GRID_BASELINE pin; wire.sh pins it for SKILLS.md too), so SKILLS.md, docs/SOURCES.md and the ratchet are machine-independent; a personal baseline is never gated. It runs check-personal.sh as the personal check; with no private denylist on the machine (CI, forks) it passes and prints gate: PASS (skipped: personal-denylist). It runs audit.sh --gate --quiet as the audit check (owned assets + the baseline's wired set; skipped loudly if python3 or scripts/audit.sh is absent). If a baseline submodule is uninitialised, audit.sh --gate exits 2 ("wired set NOT scanned") unless --allow-partial is given; gate.sh passes it only when CI is unset and then lists audit-wired as 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; stable E_* 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 in agent-factory/authored-roles.txt are held to it by compose.py --lint-roles (required AGENTS.md sections, ranked list, hard rules, SOUL.md headings, ≤4KB). Enrol a role there once it has been through the pass.
  • Private roles: compose.py reads GRID_PRIVATE_ROLES_DIR, else falls back to ~/.the-grid-private/roles if that directory exists (set the var to empty to disable). A private role of the same name wins over a public one.
  • wire.sh writes .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] writes grid-<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>.md and 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.lock records roles/profile/hashes; --check reports 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 frontmatter

scripts/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.sh

A 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-wire

Idempotent: 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 in origin/main.
  • Never leave scratch worktrees under .claude/worktrees or /tmp registered in git worktree list; run git 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 inits tests/lib/bats-core itself; any other submodule a test needs (for example repos/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 plain bats run but fail under the gate (GRID_REQUIRE_VENV=1). To commit without either, use GRID_SKIP_HOOK=1 and run the gate before readying the branch.

wire.sh contract

  • GRID_DIR env var overrides the repo root (default: script's own directory).
  • SKILLS_DIR env var overrides the skills target (default: ~/.claude/skills/).
  • AGENTS_DIR env 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 via find (flat, skills/, skills/<category>/, etc.) — wire.sh symlinks each dir containing a SKILL.md, skipping a SKILL.md sitting at a repo root. Discovery goes through scripts/lib/find-skill-mds.sh (shared with catalog.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 plain find.
  • Exclusion rule (same helper): even tracked paths are dropped when they are translations (docs/, i18n/, translations/, locales/ + a locale dir such as ja-JP), live under a root-level dot-dir (.kiro, .agents, ... — per-harness copies or upstream maintainer skills), or match a repo | prefix/ row in scripts/lib/skill-excludes.txt (currently ecc | pi/).
  • Only submodules in the manifest (baseline-submodules.txt + machines/<host>.txt overlay) are wired; the rest are library-only. If no manifest exists, all repos are wired (legacy fallback). catalog.sh reads the baseline only (machine-agnostic, deterministic SKILLS.md).
  • Machine key: GRID_HOST env var overrides the overlay host (default hostname -s).
  • Audit before wiring (step 0): before any teardown wire.sh runs audit.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 missing policy.yaml or python3 blocks the same way (fail closed). GRID_AUDIT=warn prints a warning and wires anyway. GRID_SKIP_AUDIT=1 is 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_CATALOG alone no longer skips the audit. A mock grid without a policy.yaml must set GRID_SKIP_AUDIT=1 (the bats common_setup does). The audit is point-in-time (runs at wire time and in the gate, not between; --check does not re-audit) and covers skill and agent link targets only: runtime-root bin/ helpers are not scanned (accepted, see CURATION.md).
  • Manifest problems are announced: a missing baseline file (default path, or GRID_BASELINE set and absent) and a repo, repo/skill, -repo or -repo/skill entry that names no dir under repos/ print a stderr warning and add a manifest row (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 with runtime root occupied if a real dir or foreign link is there, and prints runtime 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 final wire.sh was blocked by the audit of the build output; it then prints the next command. A missing bun and the post-run notes are OS-aware wording only: macOS, Arch, Ubuntu/Debian).
  • Baseline override: GRID_BASELINE env 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 from baseline-submodules.example.txt when 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}-private and $GRID_DIR/../x are never matched). GRID_DIR itself 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 --check paths. 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-handoff SessionEnd entry in ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json via agent-factory/deploy_hooks.py --user (stdlib only; hand-written hooks and keys are never touched). On by default; -hook:auto-handoff in the baseline or a machine overlay turns it off and removes the entry (hook:auto-handoff re-enables; the last file wins; an unknown hook:<x> warns and is ignored). Skipped in every dry run and when the emitter is absent; python3 missing or an emitter failure is a warning, not a failed wire. --check also reports drift in that file (exit 1) and writes nothing. Records a hook row 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 the SKILLS.md / .wired.manifest writes. Every dry-run caller must use it (and nothing else); --check and tests/helpers/wired.bash do.
  • Rule packs: rules:<pack> / -rules:<pack> manifest entries (baseline or overlay) symlink each rules/<pack>/*.md (never README.md) to $RULES_DIR/grid/<pack>/ (RULES_DIR, default ~/.claude/rules; only grid/ is grid-owned). Opt-in: no rules: entry means nothing is wired. An unknown or unsafe pack name warns and is skipped (rule row in .wired.manifest); --check also reports rules drift.
  • Harnesses: harness:<name> / -harness:<name> manifest entries (or GRID_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 registry scripts/lib/harnesses.txt (codex, opencode, gemini, antigravity, pi, openclaw; ~/.agents/skills is 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 via rules.py emit, but only if the operator created that file (never created, never written through a symlink). See docs/harnesses.md.
  • Composed agents: wire.sh also wires agent-factory/projects/*/_claude-code/ output — orchestrator skills into SKILLS_DIR, specialist subagents into AGENTS_DIR. Gated per machine by project:<name> manifest entries; with no project: entry anywhere, every composed project wires (legacy). The example baseline pins project:core, project:grid, project:finance-desk and project:learning-desk (see agent-factory/ and issue #1) — a task-specific machine can subtract -project:grid, -project:finance-desk or -project:learning-desk via its overlay to trim clutter, but project:core (gh-triage, librarian, researcher, platform-engineer, context-engineer, tron) is meant to stay on every machine.
  • Root-owned agents: agents/*.md at the repo root wires directly into AGENTS_DIR, same ownership model as root-level skills/ — for hand-authored subagents that aren't a compose.py role (no delegates_to, not a team position; e.g. a ported persona/behavior-modifier like grid-ponytail). Wired last, so a root-owned agent overrides a same-named composed one.
  • No-catalog mode: GRID_NO_CATALOG=1 skips only the SKILLS.md refresh (.wired.manifest is still written). grid install sets it for its own wire.sh runs so a partial, submodule-free machine never rewrites the tracked catalogue; use GRID_NO_CATALOG=1 bash scripts/wire.sh to re-wire such a machine by hand.
  • Typed entries: scripts/grid ignores typed manifest entries (project:, rules:, harness:, any kind:); only wire.sh acts on them. grid install reads untyped repo / repo/skill / -repo / -repo/skill lines 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 after git pull then re-running compose.py (BOOTSTRAP step 6, or step 3 of "Updating an existing machine") and wire.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 (greenfield openspec 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 the openspec/ tree it creates.
  • agent-factory/_core/AGENTS_base.md — a boot-sequence check for SPECS.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 raw find/wc sweep — 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 --remote update noisy library repos — see LEARNINGS.md ("Library submodules can churn...").
  • When writing role/SKILL.md instructions 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-$var word-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 shared core project 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-engineer and tron all 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 in grid.yaml made it look like a dev-team role. Moving it to core cost one delegates_to edit 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's delegates_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. the security-reviewer role's procedure vs. jeffallan's wired security-reviewer skill) — that's a naming coincidence, not a relationship, and reads as one in prose ("lives in its security-reviewer skill") 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-wizard and superpowers/systematic-debugging both do hypothesis-driven root-cause debugging, but they're not duplicates: debugging-wizard explicitly credits and incorporates systematic-debugging's phase methodology as one of its own reference docs, adding stack-trace/log-correlation tooling and per-language debugger commands on top, while systematic-debugging is already the universal default everywhere via superpowers' using-superpowers skill — 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...") and INSTALL.md.
  • After an upstream history rewrite, git cherry/patch-id reports false unmerged commits; count git rev-list <old-main>..<branch> from the reflog, match subjects against the new main, then git 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.

Download now (ZIP)

Does it work?

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

No reviews yet

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

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

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

Your trail

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

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

Now do this for your own.

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