[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-apache-magpie-setup-isolated-setup-install":3,"mdc-qjlitj-key":42,"related-repo-apache-magpie-setup-isolated-setup-install":3273,"related-org-apache-magpie-setup-isolated-setup-install":3375},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":25,"repoUrl":26,"updatedAt":27,"license":28,"forks":29,"topics":30,"repo":37,"sourceUrl":40,"mdContent":41},"magpie-setup-isolated-setup-install","install secure Magpie agent environments","Guide an adopter through the first-time install of the\nframework's secure agent setup (bubblewrap + socat +\nclaude-code, sandbox\u002Fpermissions\u002Fclean-env layers). Walks\nevery step interactively; never auto-runs sudo, shell-rc\nedits, or settings overwrites.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"apache","Apache Software Foundation","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fapache.png",[12,16,19,22],{"name":13,"slug":14,"type":15},"Security","security","tag",{"name":17,"slug":18,"type":15},"Onboarding","onboarding",{"name":20,"slug":21,"type":15},"Sandboxing","sandboxing",{"name":23,"slug":24,"type":15},"Engineering","engineering",61,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fmagpie","2026-07-29T05:38:34.789277","Apache-2.0",42,[31,8,32,33,34,14,35,36],"agent-skills","automation","claude-code","cve","vulnerability-disclosure","vulnerability-management",{"repoUrl":26,"stars":25,"forks":29,"topics":38,"description":39},[31,8,32,33,34,14,35,36],"Agent-assisted maintainership and development framework for Apache projects — Triage, Mentoring, Drafting (agent-authored fixes with human review), and Pairing (developer-side dev-cycle) skills shipping; Agentic Autonomous (auto-merge) on the roadmap.","https:\u002F\u002Fgithub.com\u002Fapache\u002Fmagpie\u002Ftree\u002FHEAD\u002Fskills\u002Fsetup-isolated-setup-install","---\n# SPDX-License-Identifier: Apache-2.0\n# https:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0\nname: magpie-setup-isolated-setup-install\nfamily: setup\nmode: Meta\ndescription: |\n  Guide an adopter through the first-time install of the\n  framework's secure agent setup (bubblewrap + socat +\n  claude-code, sandbox\u002Fpermissions\u002Fclean-env layers). Walks\n  every step interactively; never auto-runs sudo, shell-rc\n  edits, or settings overwrites.\nwhen_to_use: |\n  Invoke when the user says \"set up the secure agent setup\",\n  \"first-time install of the secure config\", \"install the\n  secure setup in this tracker\", \"walk me through the\n  secure-agent-setup install\", or starts working on a fresh\n  adopter clone without secure-config wiring. Also appropriate\n  after a fresh OS install \u002F new dev machine where\n  `~\u002F.claude\u002Fscripts\u002F` is empty. Skip when the secure setup is\n  already in place — use `setup-isolated-setup-verify` (to\n  confirm completeness) or `setup-isolated-setup-update` (to\n  refresh against the framework's latest) instead.\ncapability: capability:platform\nlicense: Apache-2.0\n---\n\n\u003C!-- Placeholder convention (see AGENTS.md#placeholder-convention-used-in-skill-files):\n     \u003Cproject-config> → adopting project's `.apache-magpie\u002F` directory\n     \u003Ctracker>        → value of `tracker_repo:` in \u003Cproject-config>\u002Fproject.md\n     \u003Cupstream>       → value of `upstream_repo:` in \u003Cproject-config>\u002Fproject.md -->\n\n# setup-isolated-setup-install\n\n## Runtime routing (run before the Claude-specific procedure)\n\nDetermine the active harness from the session metadata and executable. When it\nis Codex, follow the install lifecycle in\n[docs\u002Fadapters\u002Fcodex.md](..\u002F..\u002Fdocs\u002Fadapters\u002Fcodex.md#install), including the\nproject profile merge, static lint, project trust, and `agent-iso codex`\nsteps. Do not write Claude settings or report a missing `.claude` file as a\nCodex failure. After completing the Codex branch, stop; the remainder of this\nskill is the Claude Code branch.\n\nWhen the harness is Claude Code, continue below. If the harness cannot be\ndetermined, ask once rather than applying one runtime's policy to another.\n\nThis skill is the **on-ramp** for adopters who do not yet have the\nsecure setup running. It is a thin walkthrough wrapper around the\ncanonical install path documented in\n[`docs\u002Fsetup\u002Fsecure-agent-setup.md`](..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md). The\nauthoritative content lives there; this skill exists so an adopter\ncan say *\"set up the secure agent setup\"* in a fresh session and\nland in the right step-by-step flow without first reading the\ndocument.\n\n## Adopter overrides\n\nBefore running the default behaviour documented\nbelow, this skill consults\n[`.apache-magpie-local\u002Fsetup-isolated-setup-install.md`](..\u002F..\u002Fdocs\u002Fsetup\u002Fagentic-overrides.md) (personal, gitignored) and [`.apache-magpie-overrides\u002Fsetup-isolated-setup-install.md`](..\u002F..\u002Fdocs\u002Fsetup\u002Fagentic-overrides.md) (committed, project-wide)\nin the adopter repo if it exists, and applies any\nagent-readable overrides it finds. See\n[`docs\u002Fsetup\u002Fagentic-overrides.md`](..\u002F..\u002Fdocs\u002Fsetup\u002Fagentic-overrides.md)\nfor the contract — what overrides may contain, hard\nrules, the reconciliation flow on framework upgrade,\nupstreaming guidance.\n\n**Hard rule**: agents NEVER modify the snapshot under\n`\u003Cadopter-repo>\u002F.apache-magpie\u002F`. Local modifications\ngo in the override file. Framework changes go via PR\nto `apache\u002Fmagpie`.\n\n---\n\n## Snapshot drift\n\nAlso at the top of every run, this skill compares the\ngitignored `.apache-magpie.local.lock` (per-machine\nfetch) against the committed `.apache-magpie.lock`\n(the project pin). On mismatch the skill surfaces the\ngap and proposes\n[`\u002Fmagpie-setup upgrade`](..\u002Fsetup\u002Fupgrade.md).\nThe proposal is non-blocking — the user may defer if\nthey want to run with the local snapshot for now. See\n[`docs\u002Fsetup\u002Finstall-recipes.md` § Subsequent runs and drift detection](..\u002F..\u002Fdocs\u002Fsetup\u002Finstall-recipes.md#subsequent-runs-and-drift-detection)\nfor the full flow.\n\nDrift severity:\n\n- **method or URL differ** → ✗ full re-install needed.\n- **ref differs** (project bumped tag, or `git-branch`\n  local is behind upstream tip) → ⚠ sync needed.\n- **`svn-zip` SHA-512 mismatches the committed\n  anchor** → ✗ security-flagged; investigate before\n  upgrading.\n\n---\n## Golden rules\n\n- **Do not auto-run privilege-elevating commands.** Anything that\n  needs `sudo` (apt \u002F dnf installs, system-wide writes) is *printed*\n  for the user to copy-paste into their own terminal. The skill\n  never invokes `sudo` itself.\n- **Do not edit shell rc files without approval.** `~\u002F.bashrc` \u002F\n  `~\u002F.zshrc` modifications (sourcing `agent-iso.sh`, the optional\n  `alias claude='claude-iso'`) are surfaced as the exact line to\n  add; the user pastes it themselves. The skill confirms the rc\n  file path with the user first; it does not assume.\n- **Do not overwrite an existing settings file silently.** If the\n  user already has a project `.claude\u002Fsettings.json` or a\n  user-scope `~\u002F.claude\u002Fsettings.json`, the skill *diffs* the\n  desired merge against the existing file and asks for explicit\n  approval before writing. Re-installs \u002F partial-state recoveries\n  are common — the skill must not blow away an unrelated\n  pre-existing hook or `permissions.ask` rule. The desired merge\n  **includes the agent-guard `hooks.PreToolUse` entry** (matcher\n  `Bash`, command running the user-scope `~\u002F.claude\u002Fscripts\u002Fagent-guard.py`)\n  — the deterministic guard from\n  [`tools\u002Fagent-guard`](..\u002F..\u002Ftools\u002Fagent-guard\u002FREADME.md). Install\n  the script as `~\u002F.claude\u002Fscripts\u002Fagent-guard.py` and populate\n  `~\u002F.claude\u002Fscripts\u002Fguards.d\u002F` from both the engine's bundled\n  `guards.d\u002F*.py` and every skill-owned `skills\u002F*\u002Fguards\u002F*.py`\n  (so skill-owned guards like `mention` \u002F `mark-ready` are active),\n  alongside the other user-scope scripts (Step P); wire the\n  `PreToolUse` entry once, and preserve any pre-existing `hooks`\n  entries.\n- **Stop on the first failure.** If a step fails (manifest read\n  fails, framework path wrong, an existing file conflicts in a way\n  the user has not yet decided about), stop and report. Do not\n  push past a failure to the next step.\n\n## Up-front confirmations\n\nBefore walking any install step, confirm with the user:\n\n1. **OS \u002F distro.** macOS, Ubuntu \u002F Debian (apt), Fedora \u002F RHEL\n   (dnf), or Arch \u002F NixOS \u002F other. macOS skips bubblewrap +\n   socat (Seatbelt is built-in); Linux installs both per the\n   distro shortcut.\n2. **Framework checkout path.** The path to the user's local\n   `magpie` clone. Required to read\n   `tools\u002Fagent-isolation\u002Fpinned-versions.toml`,\n   `.claude\u002Fsettings.json`, and the\n   `tools\u002Fagent-isolation\u002F*.sh` scripts. If the user does not\n   have a clone, walk them through `git clone` first.\n3. **Fresh install or re-install.** For a re-install on a partial\n   existing state, the skill must enumerate the existing wiring\n   (project settings.json, user settings.json, hooks dir, the\n   agent-guard `hooks.PreToolUse` entry + `~\u002F.claude\u002Fscripts\u002Fagent-guard.py`,\n   shell rc) before any merge so the user knows what is being\n   preserved vs replaced.\n4. **Sync repo (optional).** Whether the user maintains a\n   private dotfile-style `~\u002F.claude-config` repo per\n   [Syncing user-scope config across machines](..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#syncing-user-scope-config-across-machines).\n   If yes, the skill installs user-scope scripts as **symlinks**\n   into `~\u002F.claude-config\u002Fscripts\u002F` rather than `cp`-ing into\n   `~\u002F.claude\u002Fscripts\u002F` — the symlink approach is what makes\n   sync push the upgrades to other machines automatically.\n\n## Walk-through\n\nFollow the canonical step list at\n[docs\u002Fsetup\u002Fsecure-agent-setup.md → Adopter setup → Via a Claude Code prompt](..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#via-a-claude-code-prompt).\nEach step in that list maps 1:1 to a step in this skill. Do not\nre-write the list here — read the doc, follow it, and surface each\nsub-step with the user. The doc names are the source of truth; the\nskill is the runner.\n\nFor the verification step at the end, hand off to the\n`setup-isolated-setup-verify` skill rather than re-walking the checklist\ninline.\n\n### Agent runtime — install `@latest`, enforce the floor\n\n`claude-code` is **not** pinned to an exact version. Install it with\n`npm install -g --no-save @anthropic-ai\u002Fclaude-code@latest` (the\ncommand in the doc's install list) — latest always carries the newest\npermission-rule \u002F sandbox \u002F prompt-injection fixes. The manifest's\n`[tools.claude-code]` table in\n[`pinned-versions.toml`](..\u002F..\u002Ftools\u002Fagent-isolation\u002Fpinned-versions.toml)\ndeclares a `min_version` **floor**, not a pin. Because this install is\ndriven from Claude Code, apply the same hard gate\n`setup-isolated-setup-verify` check 5 applies: read the running\nversion (`claude --version`) and, if it is **below** `min_version`,\n**hard-fail** — stop the install, tell the operator to upgrade to\n`@latest`, and have them re-run. The secure setup must not be stood up\non a below-floor runtime.\n\n### Step P — Project-root coverage in the sandbox allowlists\n\nPer\n[`docs\u002Fsetup\u002Fsecure-agent-setup.md` → *Project-root coverage in the sandbox allowlists*](..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#project-root-coverage-in-the-sandbox-allowlists)\nand [issue #197](https:\u002F\u002Fgithub.com\u002Fapache\u002Fmagpie\u002Fissues\u002F197),\nthe harness pre-resolves `sandbox.filesystem.allowRead: [\".\"]` at\nsession start in a way that silently drops the literal `.` from the\nresolved set, so a session in a freshly-cloned adopter repo can\nwrite to CWD but cannot **read** from it under the sandbox.\n\nThe defensive measure is to add the project root as an explicit\n**absolute path** to `sandbox.filesystem.allowRead` and `allowWrite`\nin the adopter's **project-local** settings file\n(`\u003Crepo>\u002F.claude\u002Fsettings.local.json`) — gitignored, per-machine,\nper-project, merged on top of the committed project-scope and\nuser-scope by the harness. Worktrees handle themselves: each\nworktree has its own `\u003Cworktree>\u002F.claude\u002Fsettings.local.json`,\nand each gets its own root added.\n\n#### Step P.0 — Ask the user: per-project or whole-user scope?\n\nBefore installing anything, ask the operator which scope they\nwant — see\n[`docs\u002Fsetup\u002Fsecure-agent-setup.md` → *Per-project vs whole-user scope*](..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#per-project-vs-whole-user-scope)\nfor the full rationale + trade-offs:\n\n- **Per-project.** The skill runs the helper for the\n  current project only. Future projects on this host need the\n  skill re-run in each, OR the operator can pick whole-user later.\n  No global git config changes.\n- **Whole-user (global).** The skill walks the operator's existing\n  local git checkouts and populates their `settings.local.json`\n  files, then sets `git config --global core.hooksPath` so every\n  future `git checkout` \u002F `git clone` \u002F `git worktree add` on the\n  host picks up the framework's universal post-checkout hook.\n\n**Detect whether whole-user (global) scope is already active first.**\nRead `git config --global --get core.hooksPath`:\n\n- If it is **unset** (or does not point at the framework's shared\n  hook dir), whole-user isolation is **not yet set up on this host**.\n  In that case **propose whole-user (global) as the default** — it\n  is the recommended baseline because it covers every current and\n  future repo on the host in one pass, so the operator does not have\n  to re-run this skill per project. Present per-project as the\n  narrower alternative for operators who deliberately want to keep\n  their per-repo git hooks (see the Step P.0a caveats).\n- If it is **already set** to the framework's shared hook dir,\n  whole-user isolation is already in place; default to **per-project**\n  for this specific project (the global hook already covers the host,\n  so only this project's `settings.local.json` needs the local pass).\n\n**Prefer structured Q&A.** When the agent harness offers a\nstructured-question tool (e.g. Claude Code's `AskUserQuestion`),\nuse a single-select prompt whose default is chosen by the detection\nabove — `Whole-user (global, recommended)` when whole-user is not\nyet set up, otherwise `Per-project`. Free-form chat is the fallback.\n\nIf the user picks **per-project**, skip to *Step P.1 — Install\nthe helper script* and *Step P.2 — Run the helper for this project*,\nthen move on to the next step in the canonical install list.\n\nIf the user picks **whole-user**, follow Step P.0a's loud\ndisclosure first, then Step P.0b (pick the whole-user *flavour* —\nsimple vs dispatcher), then Step P.1, then Steps P.2-whole-user\n(walk existing checkouts) and P.3-whole-user (install the global\nhook + set `core.hooksPath`). If they chose the dispatcher flavour,\nalso run Step P.3b-whole-user (install the dispatcher + prek shim).\n\n##### Step P.0a — Loud disclosure before setting whole-user scope\n\nIf the operator picked whole-user, surface this disclosure\n**before** any global config write. The operator must\nacknowledge it explicitly; no silent proceed:\n\n> **!!! WHOLE-USER SCOPE — `core.hooksPath` GLOBAL OVERRIDE !!!**\n>\n> Setting `git config --global core.hooksPath` makes git look up\n> hooks in **one shared directory** for every repo on this host.\n> Every `.git\u002Fhooks\u002F*` in every existing repo on this machine\n> becomes **inert** — git will no longer fire your per-repo\n> `pre-commit`, `commit-msg`, `pre-push`, or any other hook\n> unless the shared dir chains back to them.\n>\n> There are two whole-user flavours (you choose next, Step P.0b):\n>\n> - **Simple** — the framework installs **only** the\n>   `post-checkout` hook in the shared dir. Every other per-repo\n>   hook stays inert until you migrate it into `~\u002F.claude\u002Fgit-hooks\u002F`\n>   yourself. Pick this only if you don't rely on per-repo hooks.\n> - **With per-repo dispatcher (recommended if you use prek \u002F\n>   pre-commit \u002F husky \u002F any per-repo hook)** — the framework\n>   installs a **dispatcher** for each hook type. Each dispatcher\n>   runs the framework's own logic (the `post-checkout`\n>   sandbox-allowlist sync) **and then chains through to that\n>   repo's own `.git\u002Fhooks\u002F\u003Cname>`**. Your per-repo hooks keep\n>   firing, and a repo with no hook is a clean no-op. A bundled\n>   `prek` PATH shim makes `prek install` write its shim into the\n>   repo-local `.git\u002Fhooks\u002F` (via `--git-dir`) so the dispatcher\n>   can find it.\n>\n> Either way, whole-user scope is reversible:\n> `git config --global --unset core.hooksPath` restores per-repo\n> hook lookup, and (dispatcher flavour) removing\n> `~\u002F.claude\u002Fbin` from PATH restores the stock `prek`.\n\nConfirm the operator wants to proceed with whole-user scope after\nreading the disclosure. If they hesitate or pick per-project,\nfall back to the per-project path.\n\n##### Step P.0b — Choose the whole-user flavour: simple or dispatcher\n\nIf the operator confirmed whole-user, ask which flavour (see the\ndisclosure above for the trade-off). **Default to the dispatcher\nflavour** — it is a strict superset of simple (it still runs the\n`post-checkout` sync everywhere) and it avoids silently shadowing\nper-repo hooks, which is the most common whole-user surprise.\nPick simple only if the operator explicitly wants the minimal\nfootprint and confirms they run no per-repo hooks.\n\n**Prefer structured Q&A** here too: a single-select with\n`With per-repo dispatcher (recommended)` as the default and\n`Simple (post-checkout only)` as the alternative.\n\n- **Simple** → Step P.3-whole-user installs `git-global-post-checkout.sh`\n  only.\n- **Dispatcher** → Step P.3-whole-user still runs, and Step\n  P.3b-whole-user additionally installs `git-hook-dispatcher.sh`\n  (symlinked to each hook name, including `post-checkout` — which\n  in this flavour supersedes the standalone `git-global-post-checkout.sh`)\n  and the `prek` PATH shim.\n\n#### Step P.1 — Install the helper script\n\n(Both scopes.)\n\nCopy `tools\u002Fagent-isolation\u002Fsandbox-add-project-root.sh` into\n`~\u002F.claude\u002Fscripts\u002Fsandbox-add-project-root.sh` (or symlink it\nfrom `~\u002F.claude-config\u002Fscripts\u002F` if the operator uses the\nprivate sync repo), mode `0755`. The script file lives\nuser-scope so a single install covers every adopter project on\nthe host; what it **writes** is project-local. The same install\nmechanism the `sandbox-bypass-warn.sh` and `sandbox-status-line.sh`\nhelpers use (see the *Sandbox-bypass visibility hook* and\n*Sandbox-state status line* sections of the doc).\n#### Step P.2 — Run the helper for this project (per-project scope)\n\nSkip if the operator picked whole-user scope (Step P.2-whole-user\nbelow covers the equivalent).\n\nRun the helper once with `--all-worktrees` in the adopter\nrepo's main checkout. The helper enumerates\n`git worktree list --porcelain` and, for each worktree, writes\nthat worktree's absolute path into that worktree's own\n`\u003Cworktree>\u002F.claude\u002Fsettings.local.json` (creating the file if\nit does not yet exist). Idempotent, atomic, tolerant of missing\nprereqs (see the script's header comment for the full\nfailure-mode list). On success, surface the diff so the operator\nsees which entries landed; on no-op (paths already present),\nsurface a one-line \"already covered\" confirmation.\n\n**Sandbox-bypass requirement when invoked from inside an agent\nsession.** `.claude\u002Fsettings.local.json` is in Claude Code's\nbuilt-in sandbox `denyWithinAllow` set (verified empirically —\nsee\n[`docs\u002Fsetup\u002Fsecure-agent-setup.md` → *Security rationale*](..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#security-rationale--why-project-local-is-safe-to-write-to)),\nso the helper's Bash write is blocked when invoked through the\nagent's `Bash` tool. If this skill is being walked from inside\na sandboxed session, invoke the helper with\n`dangerouslyDisableSandbox: true` and the reason\n*\"writing project-local sandbox-allowlist entries (issue #197 fix)\"*.\nThe bypass triggers `sandbox-bypass-warn.sh`'s loud-red banner\nso the operator sees and approves the single write. When the\noperator runs `setup-isolated-setup-install` directly from a\nterminal (the typical first-time-install path), no bypass is\nneeded — the script runs outside the agent sandbox.\n\n#### Step P.2-whole-user — Walk existing checkouts (whole-user scope)\n\nSkip if the operator picked per-project scope.\n\nWalk the operator's existing git checkouts and populate each\none's `.claude\u002Fsettings.local.json`. This pass is **settings-only**\nby default — it does NOT install per-repo `post-checkout` hooks\n(the global hook installed in Step P.3-whole-user covers that\nfor both existing and future repos via `core.hooksPath`).\n\n1. **Prompt the operator for root directories to scan.**\n   Default suggestions: `~\u002Fcode\u002F`, `~\u002Fprojects\u002F`, `~\u002Fdev\u002F`,\n   `~\u002Fwork\u002F`. Show the operator the list, let them edit it.\n   Empty list → skip the walk; the operator can re-run this\n   skill later when they want existing repos covered.\n\n2. **Walk each root dir.** Use a depth-limited `find` with\n   reasonable exclusions:\n\n   ```bash\n   find \"\u003Croot>\" -maxdepth 5 -type d -name .git \\\n       -not -path '*\u002Fnode_modules\u002F*' \\\n       -not -path '*\u002F.venv\u002F*' \\\n       -not -path '*\u002F__pycache__\u002F*' \\\n       -not -path '*\u002Fbuild\u002F*' \\\n       -not -path '*\u002Fdist\u002F*' \\\n       -not -path '*\u002F.cache\u002F*' \\\n       -prune\n   ```\n\n   For each `.git\u002F` found, the parent dir is a working tree.\n   De-duplicate by canonical path.\n\n3. **For each working tree found, run the helper with\n   `--all-worktrees`.** Same invocation as the per-project\n   variant — the helper itself handles `git worktree list` so\n   linked worktrees of the same repo get processed. The helper's\n   built-in `git check-ignore` guard skips repos whose\n   `.claude\u002Fsettings.local.json` is not gitignored (defense in\n   depth — the operator should fix the `.gitignore` first).\n\n4. **Tabulate the result** for the operator: how many checkouts\n   were scanned, how many had `.claude\u002F` (so the helper wrote),\n   how many were skipped (no `.claude\u002F` directory, or\n   `.claude\u002Fsettings.local.json` not gitignored).\n\n5. **Do not install per-repo `post-checkout` hooks** during this\n   pass. The next sub-step covers future and existing repos\n   uniformly via the global hook.\n\n#### Step P.3-whole-user — Install the global post-checkout hook (whole-user scope)\n\nSkip if the operator picked per-project scope. **Dispatcher\nflavour (Step P.0b):** skip step 1 below — Step P.3b-whole-user\ninstalls the dispatcher as `post-checkout` instead, superseding the\nstandalone `git-global-post-checkout.sh`. Still run step 2 (set\n`core.hooksPath`) here.\n\n1. **(Simple flavour only) Install the universal `post-checkout`\n   hook.** Copy\n   `tools\u002Fagent-isolation\u002Fgit-global-post-checkout.sh` into\n   `~\u002F.claude\u002Fgit-hooks\u002Fpost-checkout` (or symlink it from\n   `~\u002F.claude-config\u002Fgit-hooks\u002Fpost-checkout` if the operator\n   uses the private sync repo), mode `0755`. The hook content is\n   in\n   [`tools\u002Fagent-isolation\u002Fgit-global-post-checkout.sh`](..\u002F..\u002Ftools\u002Fagent-isolation\u002Fgit-global-post-checkout.sh) —\n   it calls the sandbox-allowlist helper for Claude-Code-aware\n   worktrees.\n\n2. **Set `core.hooksPath` globally** so every git operation across\n   every repo on the host uses the shared hook dir:\n\n   ```bash\n   git config --global core.hooksPath \"$HOME\u002F.claude\u002Fgit-hooks\"\n   ```\n\n   Surface the resulting `git config --global --get core.hooksPath`\n   value to the operator to confirm the write.\n\n3. **Reiterate the implication** from Step P.0a's disclosure:\n   per-repo `.git\u002Fhooks\u002F*` are now inert across the entire host.\n   The operator must migrate any per-repo hooks they want to keep.\n   `git config --global --unset core.hooksPath` is the reversal.\n\nAfter this step, future `git clone`, `git worktree add`, and\n`git checkout` operations anywhere on the host invoke the\nframework's universal post-checkout, which keeps each\nClaude-Code-aware project's `.claude\u002Fsettings.local.json` in\nsync without any further operator action.\n\n#### Step P.3b-whole-user — Install the per-repo dispatcher + prek shim (dispatcher flavour only)\n\nSkip unless the operator picked the **dispatcher** flavour in\nStep P.0b. This is what keeps the operator's per-repo hooks (prek,\npre-commit, husky, hand-written) firing under global\n`core.hooksPath` — the shared dir runs the framework's logic **and\nthen chains through to each repo's own `.git\u002Fhooks\u002F\u003Cname>`**. See\n[`docs\u002Fsetup\u002Fsecure-agent-setup.md` → *Whole-user with the per-repo dispatcher*](..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#whole-user-with-the-per-repo-dispatcher)\nfor the full rationale + the validated behaviour matrix.\n\n1. **Install the dispatcher for each hook type.** Copy\n   [`tools\u002Fagent-isolation\u002Fgit-hook-dispatcher.sh`](..\u002F..\u002Ftools\u002Fagent-isolation\u002Fgit-hook-dispatcher.sh)\n   into `~\u002F.claude\u002Fgit-hooks\u002Fgit-hook-dispatcher.sh` (or symlink\n   from `~\u002F.claude-config\u002Fgit-hooks\u002F` under the private sync repo),\n   mode `0755`, then create one symlink per hook name pointing at\n   it — including `post-checkout`, which replaces the standalone\n   file from Step P.3 (the dispatcher runs the same sandbox sync,\n   then chains to any repo-local `post-checkout`):\n\n   ```bash\n   cd ~\u002F.claude\u002Fgit-hooks\n   for h in post-checkout pre-commit prepare-commit-msg commit-msg \\\n            post-commit pre-push post-merge post-rewrite \\\n            pre-rebase pre-merge-commit; do\n     ln -sf git-hook-dispatcher.sh \"$h\"\n   done\n   ```\n\n   The dispatcher is basename-keyed, so one file serves every hook\n   type. It resolves the repo-local hook via\n   `git rev-parse --git-common-dir` (worktree-safe) and `exec`s it\n   with the original argv + inherited stdin, so a failing local\n   `pre-commit` \u002F `pre-push` still aborts the git operation.\n\n2. **Install the `prek` PATH shim** so `prek install` writes its\n   shim into the repo-local `.git\u002Fhooks\u002F` (where the dispatcher\n   chains) instead of the shared dir. Copy\n   [`tools\u002Fagent-isolation\u002Fprek-shim.sh`](..\u002F..\u002Ftools\u002Fagent-isolation\u002Fprek-shim.sh)\n   into `~\u002F.claude\u002Fbin\u002Fprek` (or symlink from\n   `~\u002F.claude-config\u002Fbin\u002Fprek`), mode `0755`. The shim rewrites\n   only `prek install` (injecting\n   `--git-dir \"$(git rev-parse --git-common-dir)\"` unless the caller\n   already passed `--git-dir`, asked for `--help`, or is outside a\n   git work tree); **every other `prek` invocation passes through\n   unchanged**. It is a no-op on hosts with no global\n   `core.hooksPath`.\n\n3. **Surface the PATH line for the operator to add** to their\n   `~\u002F.bashrc` \u002F `~\u002F.zshrc` (per the golden rules — never edit the\n   rc file directly):\n\n   ```bash\n   export PATH=\"$HOME\u002F.claude\u002Fbin:$PATH\"\n   ```\n\n   Confirm the rc path with the operator; print the line for them\n   to paste. Until it is on PATH ahead of the real `prek`, the\n   shim is inert and `prek install` reverts to writing into the\n   shared dir.\n\n4. **Tell the operator how their existing prek repos are picked up.**\n   Repos that already ran `prek install` before this setup have\n   their shim in `.git\u002Fhooks\u002Fpre-commit` already (that is where a\n   pre-`core.hooksPath` `prek install` put it), so the dispatcher\n   finds them with no further action. Repos where they run\n   `prek install` *after* the global switch will now install\n   locally via the shim. Only repos where the shim already landed\n   in the shared dir (from a `prek install` run *while*\n   `core.hooksPath` was set but *before* this dispatcher setup)\n   need a one-time `prek install` re-run through the shim.\n\nThe `.` entry stays in the committed project-scope `allowRead`\nregardless — the explicit absolute path in\n`settings.local.json` is belt-and-braces, not a replacement. If\nthe harness ever stops resolving `.`, the explicit path still\ncovers the project; if `.` works correctly, the explicit entry is\nredundant but harmless. The committed project-scope file is\n**never** modified by the helper (machine-specific absolute paths\nhave no business in a file shared across contributors).\n\nThe helper is also invoked by `\u002Fmagpie-setup adopt`,\n`\u002Fmagpie-setup upgrade`, and `\u002Fmagpie-setup worktree-init` for\nthe same reason. The `post-checkout` git hook installed by\n`\u002Fmagpie-setup adopt` chains into the helper too, so new\nworktrees added via `git worktree add` after this install pass\ninherit access automatically — no operator action needed.\n\n## After the install lands\n\nSuggest two follow-up routines the user can wire later:\n\n- `setup-isolated-setup-verify` — re-run after every Claude Code upgrade\n  or settings-file edit, to confirm denials still fire as\n  expected. The \"did a denial silently turn into an allow?\"\n  signal is exactly what this skill exists for.\n- `setup-isolated-setup-update` — periodic check for framework\n  updates, pinned-tool upgrade candidates, and drift between the\n  installed user-scope copies and the framework's\n  source-of-truth. Recommend a per-Claude-Code-upgrade or\n  monthly cadence, whichever comes first.\n\n**Always propose shared-config sync once the install lands.**\nRegardless of whether the operator already maintains the\n`~\u002F.claude-config` sync repo, proactively offer to run\n`setup-shared-config-sync` as a follow-up:\n\n- If the `~\u002F.claude-config` sync repo is already in place, the\n  skill commits + pushes the local modifications (the user-scope\n  scripts, hooks, and settings this install just wired up) so the\n  other machines pick them up.\n- If the operator does **not** yet have `~\u002F.claude-config`, the\n  `setup-shared-config-sync` skill bootstraps it (clones the\n  default private remote if it exists, or creates a fresh private\n  remote and scaffolds the layout). Mention this so a first-time\n  operator knows the follow-up will set sync up from scratch — the\n  point of proposing it is precisely so the just-installed config\n  does not stay machine-local.\n\nSurface it as an offer for the operator to accept, not an\nauto-run — the sync skill has its own confirmation gates before it\ncommits or pushes anything.\n",{"data":43,"body":48},{"name":4,"family":44,"mode":45,"description":6,"when_to_use":46,"capability":47,"license":28},"setup","Meta","Invoke when the user says \"set up the secure agent setup\",\n\"first-time install of the secure config\", \"install the\nsecure setup in this tracker\", \"walk me through the\nsecure-agent-setup install\", or starts working on a fresh\nadopter clone without secure-config wiring. Also appropriate\nafter a fresh OS install \u002F new dev machine where\n`~\u002F.claude\u002Fscripts\u002F` is empty. Skip when the secure setup is\nalready in place — use `setup-isolated-setup-verify` (to\nconfirm completeness) or `setup-isolated-setup-update` (to\nrefresh against the framework's latest) instead.\n","capability:platform",{"type":49,"children":50},"root",[51,59,66,98,103,136,142,181,207,211,217,264,269,318,321,327,561,567,572,716,722,735,748,763,863,869,924,975,982,1004,1064,1082,1136,1170,1194,1220,1227,1239,1452,1457,1463,1482,1508,1567,1573,1578,1650,1656,1661,1689,1767,1773,1778,1811,2244,2250,2283,2446,2478,2484,2531,3066,3114,3162,3168,3173,3197,3222,3262,3267],{"type":52,"tag":53,"props":54,"children":56},"element","h1",{"id":55},"setup-isolated-setup-install",[57],{"type":58,"value":55},"text",{"type":52,"tag":60,"props":61,"children":63},"h2",{"id":62},"runtime-routing-run-before-the-claude-specific-procedure",[64],{"type":58,"value":65},"Runtime routing (run before the Claude-specific procedure)",{"type":52,"tag":67,"props":68,"children":69},"p",{},[70,72,79,81,88,90,96],{"type":58,"value":71},"Determine the active harness from the session metadata and executable. When it\nis Codex, follow the install lifecycle in\n",{"type":52,"tag":73,"props":74,"children":76},"a",{"href":75},"..\u002F..\u002Fdocs\u002Fadapters\u002Fcodex.md#install",[77],{"type":58,"value":78},"docs\u002Fadapters\u002Fcodex.md",{"type":58,"value":80},", including the\nproject profile merge, static lint, project trust, and ",{"type":52,"tag":82,"props":83,"children":85},"code",{"className":84},[],[86],{"type":58,"value":87},"agent-iso codex",{"type":58,"value":89},"\nsteps. Do not write Claude settings or report a missing ",{"type":52,"tag":82,"props":91,"children":93},{"className":92},[],[94],{"type":58,"value":95},".claude",{"type":58,"value":97}," file as a\nCodex failure. After completing the Codex branch, stop; the remainder of this\nskill is the Claude Code branch.",{"type":52,"tag":67,"props":99,"children":100},{},[101],{"type":58,"value":102},"When the harness is Claude Code, continue below. If the harness cannot be\ndetermined, ask once rather than applying one runtime's policy to another.",{"type":52,"tag":67,"props":104,"children":105},{},[106,108,114,116,126,128,134],{"type":58,"value":107},"This skill is the ",{"type":52,"tag":109,"props":110,"children":111},"strong",{},[112],{"type":58,"value":113},"on-ramp",{"type":58,"value":115}," for adopters who do not yet have the\nsecure setup running. It is a thin walkthrough wrapper around the\ncanonical install path documented in\n",{"type":52,"tag":73,"props":117,"children":119},{"href":118},"..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md",[120],{"type":52,"tag":82,"props":121,"children":123},{"className":122},[],[124],{"type":58,"value":125},"docs\u002Fsetup\u002Fsecure-agent-setup.md",{"type":58,"value":127},". The\nauthoritative content lives there; this skill exists so an adopter\ncan say ",{"type":52,"tag":129,"props":130,"children":131},"em",{},[132],{"type":58,"value":133},"\"set up the secure agent setup\"",{"type":58,"value":135}," in a fresh session and\nland in the right step-by-step flow without first reading the\ndocument.",{"type":52,"tag":60,"props":137,"children":139},{"id":138},"adopter-overrides",[140],{"type":58,"value":141},"Adopter overrides",{"type":52,"tag":67,"props":143,"children":144},{},[145,147,157,159,168,170,179],{"type":58,"value":146},"Before running the default behaviour documented\nbelow, this skill consults\n",{"type":52,"tag":73,"props":148,"children":150},{"href":149},"..\u002F..\u002Fdocs\u002Fsetup\u002Fagentic-overrides.md",[151],{"type":52,"tag":82,"props":152,"children":154},{"className":153},[],[155],{"type":58,"value":156},".apache-magpie-local\u002Fsetup-isolated-setup-install.md",{"type":58,"value":158}," (personal, gitignored) and ",{"type":52,"tag":73,"props":160,"children":161},{"href":149},[162],{"type":52,"tag":82,"props":163,"children":165},{"className":164},[],[166],{"type":58,"value":167},".apache-magpie-overrides\u002Fsetup-isolated-setup-install.md",{"type":58,"value":169}," (committed, project-wide)\nin the adopter repo if it exists, and applies any\nagent-readable overrides it finds. See\n",{"type":52,"tag":73,"props":171,"children":172},{"href":149},[173],{"type":52,"tag":82,"props":174,"children":176},{"className":175},[],[177],{"type":58,"value":178},"docs\u002Fsetup\u002Fagentic-overrides.md",{"type":58,"value":180},"\nfor the contract — what overrides may contain, hard\nrules, the reconciliation flow on framework upgrade,\nupstreaming guidance.",{"type":52,"tag":67,"props":182,"children":183},{},[184,189,191,197,199,205],{"type":52,"tag":109,"props":185,"children":186},{},[187],{"type":58,"value":188},"Hard rule",{"type":58,"value":190},": agents NEVER modify the snapshot under\n",{"type":52,"tag":82,"props":192,"children":194},{"className":193},[],[195],{"type":58,"value":196},"\u003Cadopter-repo>\u002F.apache-magpie\u002F",{"type":58,"value":198},". Local modifications\ngo in the override file. Framework changes go via PR\nto ",{"type":52,"tag":82,"props":200,"children":202},{"className":201},[],[203],{"type":58,"value":204},"apache\u002Fmagpie",{"type":58,"value":206},".",{"type":52,"tag":208,"props":209,"children":210},"hr",{},[],{"type":52,"tag":60,"props":212,"children":214},{"id":213},"snapshot-drift",[215],{"type":58,"value":216},"Snapshot drift",{"type":52,"tag":67,"props":218,"children":219},{},[220,222,228,230,236,238,248,250,262],{"type":58,"value":221},"Also at the top of every run, this skill compares the\ngitignored ",{"type":52,"tag":82,"props":223,"children":225},{"className":224},[],[226],{"type":58,"value":227},".apache-magpie.local.lock",{"type":58,"value":229}," (per-machine\nfetch) against the committed ",{"type":52,"tag":82,"props":231,"children":233},{"className":232},[],[234],{"type":58,"value":235},".apache-magpie.lock",{"type":58,"value":237},"\n(the project pin). On mismatch the skill surfaces the\ngap and proposes\n",{"type":52,"tag":73,"props":239,"children":241},{"href":240},"..\u002Fsetup\u002Fupgrade.md",[242],{"type":52,"tag":82,"props":243,"children":245},{"className":244},[],[246],{"type":58,"value":247},"\u002Fmagpie-setup upgrade",{"type":58,"value":249},".\nThe proposal is non-blocking — the user may defer if\nthey want to run with the local snapshot for now. See\n",{"type":52,"tag":73,"props":251,"children":253},{"href":252},"..\u002F..\u002Fdocs\u002Fsetup\u002Finstall-recipes.md#subsequent-runs-and-drift-detection",[254,260],{"type":52,"tag":82,"props":255,"children":257},{"className":256},[],[258],{"type":58,"value":259},"docs\u002Fsetup\u002Finstall-recipes.md",{"type":58,"value":261}," § Subsequent runs and drift detection",{"type":58,"value":263},"\nfor the full flow.",{"type":52,"tag":67,"props":265,"children":266},{},[267],{"type":58,"value":268},"Drift severity:",{"type":52,"tag":270,"props":271,"children":272},"ul",{},[273,284,302],{"type":52,"tag":274,"props":275,"children":276},"li",{},[277,282],{"type":52,"tag":109,"props":278,"children":279},{},[280],{"type":58,"value":281},"method or URL differ",{"type":58,"value":283}," → ✗ full re-install needed.",{"type":52,"tag":274,"props":285,"children":286},{},[287,292,294,300],{"type":52,"tag":109,"props":288,"children":289},{},[290],{"type":58,"value":291},"ref differs",{"type":58,"value":293}," (project bumped tag, or ",{"type":52,"tag":82,"props":295,"children":297},{"className":296},[],[298],{"type":58,"value":299},"git-branch",{"type":58,"value":301},"\nlocal is behind upstream tip) → ⚠ sync needed.",{"type":52,"tag":274,"props":303,"children":304},{},[305,316],{"type":52,"tag":109,"props":306,"children":307},{},[308,314],{"type":52,"tag":82,"props":309,"children":311},{"className":310},[],[312],{"type":58,"value":313},"svn-zip",{"type":58,"value":315}," SHA-512 mismatches the committed\nanchor",{"type":58,"value":317}," → ✗ security-flagged; investigate before\nupgrading.",{"type":52,"tag":208,"props":319,"children":320},{},[],{"type":52,"tag":60,"props":322,"children":324},{"id":323},"golden-rules",[325],{"type":58,"value":326},"Golden rules",{"type":52,"tag":270,"props":328,"children":329},{},[330,362,404,551],{"type":52,"tag":274,"props":331,"children":332},{},[333,338,340,346,348,353,355,360],{"type":52,"tag":109,"props":334,"children":335},{},[336],{"type":58,"value":337},"Do not auto-run privilege-elevating commands.",{"type":58,"value":339}," Anything that\nneeds ",{"type":52,"tag":82,"props":341,"children":343},{"className":342},[],[344],{"type":58,"value":345},"sudo",{"type":58,"value":347}," (apt \u002F dnf installs, system-wide writes) is ",{"type":52,"tag":129,"props":349,"children":350},{},[351],{"type":58,"value":352},"printed",{"type":58,"value":354},"\nfor the user to copy-paste into their own terminal. The skill\nnever invokes ",{"type":52,"tag":82,"props":356,"children":358},{"className":357},[],[359],{"type":58,"value":345},{"type":58,"value":361}," itself.",{"type":52,"tag":274,"props":363,"children":364},{},[365,370,372,378,380,386,388,394,396,402],{"type":52,"tag":109,"props":366,"children":367},{},[368],{"type":58,"value":369},"Do not edit shell rc files without approval.",{"type":58,"value":371}," ",{"type":52,"tag":82,"props":373,"children":375},{"className":374},[],[376],{"type":58,"value":377},"~\u002F.bashrc",{"type":58,"value":379}," \u002F\n",{"type":52,"tag":82,"props":381,"children":383},{"className":382},[],[384],{"type":58,"value":385},"~\u002F.zshrc",{"type":58,"value":387}," modifications (sourcing ",{"type":52,"tag":82,"props":389,"children":391},{"className":390},[],[392],{"type":58,"value":393},"agent-iso.sh",{"type":58,"value":395},", the optional\n",{"type":52,"tag":82,"props":397,"children":399},{"className":398},[],[400],{"type":58,"value":401},"alias claude='claude-iso'",{"type":58,"value":403},") are surfaced as the exact line to\nadd; the user pastes it themselves. The skill confirms the rc\nfile path with the user first; it does not assume.",{"type":52,"tag":274,"props":405,"children":406},{},[407,412,414,420,422,428,430,435,437,443,445,458,460,466,468,474,476,486,488,493,495,501,503,509,511,517,519,525,527,533,535,541,543,549],{"type":52,"tag":109,"props":408,"children":409},{},[410],{"type":58,"value":411},"Do not overwrite an existing settings file silently.",{"type":58,"value":413}," If the\nuser already has a project ",{"type":52,"tag":82,"props":415,"children":417},{"className":416},[],[418],{"type":58,"value":419},".claude\u002Fsettings.json",{"type":58,"value":421}," or a\nuser-scope ",{"type":52,"tag":82,"props":423,"children":425},{"className":424},[],[426],{"type":58,"value":427},"~\u002F.claude\u002Fsettings.json",{"type":58,"value":429},", the skill ",{"type":52,"tag":129,"props":431,"children":432},{},[433],{"type":58,"value":434},"diffs",{"type":58,"value":436}," the\ndesired merge against the existing file and asks for explicit\napproval before writing. Re-installs \u002F partial-state recoveries\nare common — the skill must not blow away an unrelated\npre-existing hook or ",{"type":52,"tag":82,"props":438,"children":440},{"className":439},[],[441],{"type":58,"value":442},"permissions.ask",{"type":58,"value":444}," rule. The desired merge\n",{"type":52,"tag":109,"props":446,"children":447},{},[448,450,456],{"type":58,"value":449},"includes the agent-guard ",{"type":52,"tag":82,"props":451,"children":453},{"className":452},[],[454],{"type":58,"value":455},"hooks.PreToolUse",{"type":58,"value":457}," entry",{"type":58,"value":459}," (matcher\n",{"type":52,"tag":82,"props":461,"children":463},{"className":462},[],[464],{"type":58,"value":465},"Bash",{"type":58,"value":467},", command running the user-scope ",{"type":52,"tag":82,"props":469,"children":471},{"className":470},[],[472],{"type":58,"value":473},"~\u002F.claude\u002Fscripts\u002Fagent-guard.py",{"type":58,"value":475},")\n— the deterministic guard from\n",{"type":52,"tag":73,"props":477,"children":479},{"href":478},"..\u002F..\u002Ftools\u002Fagent-guard\u002FREADME.md",[480],{"type":52,"tag":82,"props":481,"children":483},{"className":482},[],[484],{"type":58,"value":485},"tools\u002Fagent-guard",{"type":58,"value":487},". Install\nthe script as ",{"type":52,"tag":82,"props":489,"children":491},{"className":490},[],[492],{"type":58,"value":473},{"type":58,"value":494}," and populate\n",{"type":52,"tag":82,"props":496,"children":498},{"className":497},[],[499],{"type":58,"value":500},"~\u002F.claude\u002Fscripts\u002Fguards.d\u002F",{"type":58,"value":502}," from both the engine's bundled\n",{"type":52,"tag":82,"props":504,"children":506},{"className":505},[],[507],{"type":58,"value":508},"guards.d\u002F*.py",{"type":58,"value":510}," and every skill-owned ",{"type":52,"tag":82,"props":512,"children":514},{"className":513},[],[515],{"type":58,"value":516},"skills\u002F*\u002Fguards\u002F*.py",{"type":58,"value":518},"\n(so skill-owned guards like ",{"type":52,"tag":82,"props":520,"children":522},{"className":521},[],[523],{"type":58,"value":524},"mention",{"type":58,"value":526}," \u002F ",{"type":52,"tag":82,"props":528,"children":530},{"className":529},[],[531],{"type":58,"value":532},"mark-ready",{"type":58,"value":534}," are active),\nalongside the other user-scope scripts (Step P); wire the\n",{"type":52,"tag":82,"props":536,"children":538},{"className":537},[],[539],{"type":58,"value":540},"PreToolUse",{"type":58,"value":542}," entry once, and preserve any pre-existing ",{"type":52,"tag":82,"props":544,"children":546},{"className":545},[],[547],{"type":58,"value":548},"hooks",{"type":58,"value":550},"\nentries.",{"type":52,"tag":274,"props":552,"children":553},{},[554,559],{"type":52,"tag":109,"props":555,"children":556},{},[557],{"type":58,"value":558},"Stop on the first failure.",{"type":58,"value":560}," If a step fails (manifest read\nfails, framework path wrong, an existing file conflicts in a way\nthe user has not yet decided about), stop and report. Do not\npush past a failure to the next step.",{"type":52,"tag":60,"props":562,"children":564},{"id":563},"up-front-confirmations",[565],{"type":58,"value":566},"Up-front confirmations",{"type":52,"tag":67,"props":568,"children":569},{},[570],{"type":58,"value":571},"Before walking any install step, confirm with the user:",{"type":52,"tag":573,"props":574,"children":575},"ol",{},[576,586,635,659],{"type":52,"tag":274,"props":577,"children":578},{},[579,584],{"type":52,"tag":109,"props":580,"children":581},{},[582],{"type":58,"value":583},"OS \u002F distro.",{"type":58,"value":585}," macOS, Ubuntu \u002F Debian (apt), Fedora \u002F RHEL\n(dnf), or Arch \u002F NixOS \u002F other. macOS skips bubblewrap +\nsocat (Seatbelt is built-in); Linux installs both per the\ndistro shortcut.",{"type":52,"tag":274,"props":587,"children":588},{},[589,594,596,602,604,610,612,617,619,625,627,633],{"type":52,"tag":109,"props":590,"children":591},{},[592],{"type":58,"value":593},"Framework checkout path.",{"type":58,"value":595}," The path to the user's local\n",{"type":52,"tag":82,"props":597,"children":599},{"className":598},[],[600],{"type":58,"value":601},"magpie",{"type":58,"value":603}," clone. Required to read\n",{"type":52,"tag":82,"props":605,"children":607},{"className":606},[],[608],{"type":58,"value":609},"tools\u002Fagent-isolation\u002Fpinned-versions.toml",{"type":58,"value":611},",\n",{"type":52,"tag":82,"props":613,"children":615},{"className":614},[],[616],{"type":58,"value":419},{"type":58,"value":618},", and the\n",{"type":52,"tag":82,"props":620,"children":622},{"className":621},[],[623],{"type":58,"value":624},"tools\u002Fagent-isolation\u002F*.sh",{"type":58,"value":626}," scripts. If the user does not\nhave a clone, walk them through ",{"type":52,"tag":82,"props":628,"children":630},{"className":629},[],[631],{"type":58,"value":632},"git clone",{"type":58,"value":634}," first.",{"type":52,"tag":274,"props":636,"children":637},{},[638,643,645,650,652,657],{"type":52,"tag":109,"props":639,"children":640},{},[641],{"type":58,"value":642},"Fresh install or re-install.",{"type":58,"value":644}," For a re-install on a partial\nexisting state, the skill must enumerate the existing wiring\n(project settings.json, user settings.json, hooks dir, the\nagent-guard ",{"type":52,"tag":82,"props":646,"children":648},{"className":647},[],[649],{"type":58,"value":455},{"type":58,"value":651}," entry + ",{"type":52,"tag":82,"props":653,"children":655},{"className":654},[],[656],{"type":58,"value":473},{"type":58,"value":658},",\nshell rc) before any merge so the user knows what is being\npreserved vs replaced.",{"type":52,"tag":274,"props":660,"children":661},{},[662,667,669,675,677,683,685,690,692,698,700,706,708,714],{"type":52,"tag":109,"props":663,"children":664},{},[665],{"type":58,"value":666},"Sync repo (optional).",{"type":58,"value":668}," Whether the user maintains a\nprivate dotfile-style ",{"type":52,"tag":82,"props":670,"children":672},{"className":671},[],[673],{"type":58,"value":674},"~\u002F.claude-config",{"type":58,"value":676}," repo per\n",{"type":52,"tag":73,"props":678,"children":680},{"href":679},"..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#syncing-user-scope-config-across-machines",[681],{"type":58,"value":682},"Syncing user-scope config across machines",{"type":58,"value":684},".\nIf yes, the skill installs user-scope scripts as ",{"type":52,"tag":109,"props":686,"children":687},{},[688],{"type":58,"value":689},"symlinks",{"type":58,"value":691},"\ninto ",{"type":52,"tag":82,"props":693,"children":695},{"className":694},[],[696],{"type":58,"value":697},"~\u002F.claude-config\u002Fscripts\u002F",{"type":58,"value":699}," rather than ",{"type":52,"tag":82,"props":701,"children":703},{"className":702},[],[704],{"type":58,"value":705},"cp",{"type":58,"value":707},"-ing into\n",{"type":52,"tag":82,"props":709,"children":711},{"className":710},[],[712],{"type":58,"value":713},"~\u002F.claude\u002Fscripts\u002F",{"type":58,"value":715}," — the symlink approach is what makes\nsync push the upgrades to other machines automatically.",{"type":52,"tag":60,"props":717,"children":719},{"id":718},"walk-through",[720],{"type":58,"value":721},"Walk-through",{"type":52,"tag":67,"props":723,"children":724},{},[725,727,733],{"type":58,"value":726},"Follow the canonical step list at\n",{"type":52,"tag":73,"props":728,"children":730},{"href":729},"..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#via-a-claude-code-prompt",[731],{"type":58,"value":732},"docs\u002Fsetup\u002Fsecure-agent-setup.md → Adopter setup → Via a Claude Code prompt",{"type":58,"value":734},".\nEach step in that list maps 1:1 to a step in this skill. Do not\nre-write the list here — read the doc, follow it, and surface each\nsub-step with the user. The doc names are the source of truth; the\nskill is the runner.",{"type":52,"tag":67,"props":736,"children":737},{},[738,740,746],{"type":58,"value":739},"For the verification step at the end, hand off to the\n",{"type":52,"tag":82,"props":741,"children":743},{"className":742},[],[744],{"type":58,"value":745},"setup-isolated-setup-verify",{"type":58,"value":747}," skill rather than re-walking the checklist\ninline.",{"type":52,"tag":749,"props":750,"children":752},"h3",{"id":751},"agent-runtime-install-latest-enforce-the-floor",[753,755,761],{"type":58,"value":754},"Agent runtime — install ",{"type":52,"tag":82,"props":756,"children":758},{"className":757},[],[759],{"type":58,"value":760},"@latest",{"type":58,"value":762},", enforce the floor",{"type":52,"tag":67,"props":764,"children":765},{},[766,771,773,778,780,786,788,794,796,806,808,814,815,820,822,827,829,835,837,842,843,848,849,854,856,861],{"type":52,"tag":82,"props":767,"children":769},{"className":768},[],[770],{"type":58,"value":33},{"type":58,"value":772}," is ",{"type":52,"tag":109,"props":774,"children":775},{},[776],{"type":58,"value":777},"not",{"type":58,"value":779}," pinned to an exact version. Install it with\n",{"type":52,"tag":82,"props":781,"children":783},{"className":782},[],[784],{"type":58,"value":785},"npm install -g --no-save @anthropic-ai\u002Fclaude-code@latest",{"type":58,"value":787}," (the\ncommand in the doc's install list) — latest always carries the newest\npermission-rule \u002F sandbox \u002F prompt-injection fixes. The manifest's\n",{"type":52,"tag":82,"props":789,"children":791},{"className":790},[],[792],{"type":58,"value":793},"[tools.claude-code]",{"type":58,"value":795}," table in\n",{"type":52,"tag":73,"props":797,"children":799},{"href":798},"..\u002F..\u002Ftools\u002Fagent-isolation\u002Fpinned-versions.toml",[800],{"type":52,"tag":82,"props":801,"children":803},{"className":802},[],[804],{"type":58,"value":805},"pinned-versions.toml",{"type":58,"value":807},"\ndeclares a ",{"type":52,"tag":82,"props":809,"children":811},{"className":810},[],[812],{"type":58,"value":813},"min_version",{"type":58,"value":371},{"type":52,"tag":109,"props":816,"children":817},{},[818],{"type":58,"value":819},"floor",{"type":58,"value":821},", not a pin. Because this install is\ndriven from Claude Code, apply the same hard gate\n",{"type":52,"tag":82,"props":823,"children":825},{"className":824},[],[826],{"type":58,"value":745},{"type":58,"value":828}," check 5 applies: read the running\nversion (",{"type":52,"tag":82,"props":830,"children":832},{"className":831},[],[833],{"type":58,"value":834},"claude --version",{"type":58,"value":836},") and, if it is ",{"type":52,"tag":109,"props":838,"children":839},{},[840],{"type":58,"value":841},"below",{"type":58,"value":371},{"type":52,"tag":82,"props":844,"children":846},{"className":845},[],[847],{"type":58,"value":813},{"type":58,"value":611},{"type":52,"tag":109,"props":850,"children":851},{},[852],{"type":58,"value":853},"hard-fail",{"type":58,"value":855}," — stop the install, tell the operator to upgrade to\n",{"type":52,"tag":82,"props":857,"children":859},{"className":858},[],[860],{"type":58,"value":760},{"type":58,"value":862},", and have them re-run. The secure setup must not be stood up\non a below-floor runtime.",{"type":52,"tag":749,"props":864,"children":866},{"id":865},"step-p-project-root-coverage-in-the-sandbox-allowlists",[867],{"type":58,"value":868},"Step P — Project-root coverage in the sandbox allowlists",{"type":52,"tag":67,"props":870,"children":871},{},[872,874,890,892,900,902,908,910,915,917,922],{"type":58,"value":873},"Per\n",{"type":52,"tag":73,"props":875,"children":877},{"href":876},"..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#project-root-coverage-in-the-sandbox-allowlists",[878,883,885],{"type":52,"tag":82,"props":879,"children":881},{"className":880},[],[882],{"type":58,"value":125},{"type":58,"value":884}," → ",{"type":52,"tag":129,"props":886,"children":887},{},[888],{"type":58,"value":889},"Project-root coverage in the sandbox allowlists",{"type":58,"value":891},"\nand ",{"type":52,"tag":73,"props":893,"children":897},{"href":894,"rel":895},"https:\u002F\u002Fgithub.com\u002Fapache\u002Fmagpie\u002Fissues\u002F197",[896],"nofollow",[898],{"type":58,"value":899},"issue #197",{"type":58,"value":901},",\nthe harness pre-resolves ",{"type":52,"tag":82,"props":903,"children":905},{"className":904},[],[906],{"type":58,"value":907},"sandbox.filesystem.allowRead: [\".\"]",{"type":58,"value":909}," at\nsession start in a way that silently drops the literal ",{"type":52,"tag":82,"props":911,"children":913},{"className":912},[],[914],{"type":58,"value":206},{"type":58,"value":916}," from the\nresolved set, so a session in a freshly-cloned adopter repo can\nwrite to CWD but cannot ",{"type":52,"tag":109,"props":918,"children":919},{},[920],{"type":58,"value":921},"read",{"type":58,"value":923}," from it under the sandbox.",{"type":52,"tag":67,"props":925,"children":926},{},[927,929,934,936,942,944,950,952,957,959,965,967,973],{"type":58,"value":928},"The defensive measure is to add the project root as an explicit\n",{"type":52,"tag":109,"props":930,"children":931},{},[932],{"type":58,"value":933},"absolute path",{"type":58,"value":935}," to ",{"type":52,"tag":82,"props":937,"children":939},{"className":938},[],[940],{"type":58,"value":941},"sandbox.filesystem.allowRead",{"type":58,"value":943}," and ",{"type":52,"tag":82,"props":945,"children":947},{"className":946},[],[948],{"type":58,"value":949},"allowWrite",{"type":58,"value":951},"\nin the adopter's ",{"type":52,"tag":109,"props":953,"children":954},{},[955],{"type":58,"value":956},"project-local",{"type":58,"value":958}," settings file\n(",{"type":52,"tag":82,"props":960,"children":962},{"className":961},[],[963],{"type":58,"value":964},"\u003Crepo>\u002F.claude\u002Fsettings.local.json",{"type":58,"value":966},") — gitignored, per-machine,\nper-project, merged on top of the committed project-scope and\nuser-scope by the harness. Worktrees handle themselves: each\nworktree has its own ",{"type":52,"tag":82,"props":968,"children":970},{"className":969},[],[971],{"type":58,"value":972},"\u003Cworktree>\u002F.claude\u002Fsettings.local.json",{"type":58,"value":974},",\nand each gets its own root added.",{"type":52,"tag":976,"props":977,"children":979},"h4",{"id":978},"step-p0-ask-the-user-per-project-or-whole-user-scope",[980],{"type":58,"value":981},"Step P.0 — Ask the user: per-project or whole-user scope?",{"type":52,"tag":67,"props":983,"children":984},{},[985,987,1002],{"type":58,"value":986},"Before installing anything, ask the operator which scope they\nwant — see\n",{"type":52,"tag":73,"props":988,"children":990},{"href":989},"..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#per-project-vs-whole-user-scope",[991,996,997],{"type":52,"tag":82,"props":992,"children":994},{"className":993},[],[995],{"type":58,"value":125},{"type":58,"value":884},{"type":52,"tag":129,"props":998,"children":999},{},[1000],{"type":58,"value":1001},"Per-project vs whole-user scope",{"type":58,"value":1003},"\nfor the full rationale + trade-offs:",{"type":52,"tag":270,"props":1005,"children":1006},{},[1007,1017],{"type":52,"tag":274,"props":1008,"children":1009},{},[1010,1015],{"type":52,"tag":109,"props":1011,"children":1012},{},[1013],{"type":58,"value":1014},"Per-project.",{"type":58,"value":1016}," The skill runs the helper for the\ncurrent project only. Future projects on this host need the\nskill re-run in each, OR the operator can pick whole-user later.\nNo global git config changes.",{"type":52,"tag":274,"props":1018,"children":1019},{},[1020,1025,1027,1033,1035,1041,1043,1049,1050,1055,1056,1062],{"type":52,"tag":109,"props":1021,"children":1022},{},[1023],{"type":58,"value":1024},"Whole-user (global).",{"type":58,"value":1026}," The skill walks the operator's existing\nlocal git checkouts and populates their ",{"type":52,"tag":82,"props":1028,"children":1030},{"className":1029},[],[1031],{"type":58,"value":1032},"settings.local.json",{"type":58,"value":1034},"\nfiles, then sets ",{"type":52,"tag":82,"props":1036,"children":1038},{"className":1037},[],[1039],{"type":58,"value":1040},"git config --global core.hooksPath",{"type":58,"value":1042}," so every\nfuture ",{"type":52,"tag":82,"props":1044,"children":1046},{"className":1045},[],[1047],{"type":58,"value":1048},"git checkout",{"type":58,"value":526},{"type":52,"tag":82,"props":1051,"children":1053},{"className":1052},[],[1054],{"type":58,"value":632},{"type":58,"value":526},{"type":52,"tag":82,"props":1057,"children":1059},{"className":1058},[],[1060],{"type":58,"value":1061},"git worktree add",{"type":58,"value":1063}," on the\nhost picks up the framework's universal post-checkout hook.",{"type":52,"tag":67,"props":1065,"children":1066},{},[1067,1072,1074,1080],{"type":52,"tag":109,"props":1068,"children":1069},{},[1070],{"type":58,"value":1071},"Detect whether whole-user (global) scope is already active first.",{"type":58,"value":1073},"\nRead ",{"type":52,"tag":82,"props":1075,"children":1077},{"className":1076},[],[1078],{"type":58,"value":1079},"git config --global --get core.hooksPath",{"type":58,"value":1081},":",{"type":52,"tag":270,"props":1083,"children":1084},{},[1085,1111],{"type":52,"tag":274,"props":1086,"children":1087},{},[1088,1090,1095,1097,1102,1104,1109],{"type":58,"value":1089},"If it is ",{"type":52,"tag":109,"props":1091,"children":1092},{},[1093],{"type":58,"value":1094},"unset",{"type":58,"value":1096}," (or does not point at the framework's shared\nhook dir), whole-user isolation is ",{"type":52,"tag":109,"props":1098,"children":1099},{},[1100],{"type":58,"value":1101},"not yet set up on this host",{"type":58,"value":1103},".\nIn that case ",{"type":52,"tag":109,"props":1105,"children":1106},{},[1107],{"type":58,"value":1108},"propose whole-user (global) as the default",{"type":58,"value":1110}," — it\nis the recommended baseline because it covers every current and\nfuture repo on the host in one pass, so the operator does not have\nto re-run this skill per project. Present per-project as the\nnarrower alternative for operators who deliberately want to keep\ntheir per-repo git hooks (see the Step P.0a caveats).",{"type":52,"tag":274,"props":1112,"children":1113},{},[1114,1115,1120,1122,1127,1129,1134],{"type":58,"value":1089},{"type":52,"tag":109,"props":1116,"children":1117},{},[1118],{"type":58,"value":1119},"already set",{"type":58,"value":1121}," to the framework's shared hook dir,\nwhole-user isolation is already in place; default to ",{"type":52,"tag":109,"props":1123,"children":1124},{},[1125],{"type":58,"value":1126},"per-project",{"type":58,"value":1128},"\nfor this specific project (the global hook already covers the host,\nso only this project's ",{"type":52,"tag":82,"props":1130,"children":1132},{"className":1131},[],[1133],{"type":58,"value":1032},{"type":58,"value":1135}," needs the local pass).",{"type":52,"tag":67,"props":1137,"children":1138},{},[1139,1144,1146,1152,1154,1160,1162,1168],{"type":52,"tag":109,"props":1140,"children":1141},{},[1142],{"type":58,"value":1143},"Prefer structured Q&A.",{"type":58,"value":1145}," When the agent harness offers a\nstructured-question tool (e.g. Claude Code's ",{"type":52,"tag":82,"props":1147,"children":1149},{"className":1148},[],[1150],{"type":58,"value":1151},"AskUserQuestion",{"type":58,"value":1153},"),\nuse a single-select prompt whose default is chosen by the detection\nabove — ",{"type":52,"tag":82,"props":1155,"children":1157},{"className":1156},[],[1158],{"type":58,"value":1159},"Whole-user (global, recommended)",{"type":58,"value":1161}," when whole-user is not\nyet set up, otherwise ",{"type":52,"tag":82,"props":1163,"children":1165},{"className":1164},[],[1166],{"type":58,"value":1167},"Per-project",{"type":58,"value":1169},". Free-form chat is the fallback.",{"type":52,"tag":67,"props":1171,"children":1172},{},[1173,1175,1179,1181,1186,1187,1192],{"type":58,"value":1174},"If the user picks ",{"type":52,"tag":109,"props":1176,"children":1177},{},[1178],{"type":58,"value":1126},{"type":58,"value":1180},", skip to ",{"type":52,"tag":129,"props":1182,"children":1183},{},[1184],{"type":58,"value":1185},"Step P.1 — Install\nthe helper script",{"type":58,"value":943},{"type":52,"tag":129,"props":1188,"children":1189},{},[1190],{"type":58,"value":1191},"Step P.2 — Run the helper for this project",{"type":58,"value":1193},",\nthen move on to the next step in the canonical install list.",{"type":52,"tag":67,"props":1195,"children":1196},{},[1197,1198,1203,1205,1210,1212,1218],{"type":58,"value":1174},{"type":52,"tag":109,"props":1199,"children":1200},{},[1201],{"type":58,"value":1202},"whole-user",{"type":58,"value":1204},", follow Step P.0a's loud\ndisclosure first, then Step P.0b (pick the whole-user ",{"type":52,"tag":129,"props":1206,"children":1207},{},[1208],{"type":58,"value":1209},"flavour",{"type":58,"value":1211}," —\nsimple vs dispatcher), then Step P.1, then Steps P.2-whole-user\n(walk existing checkouts) and P.3-whole-user (install the global\nhook + set ",{"type":52,"tag":82,"props":1213,"children":1215},{"className":1214},[],[1216],{"type":58,"value":1217},"core.hooksPath",{"type":58,"value":1219},"). If they chose the dispatcher flavour,\nalso run Step P.3b-whole-user (install the dispatcher + prek shim).",{"type":52,"tag":1221,"props":1222,"children":1224},"h5",{"id":1223},"step-p0a-loud-disclosure-before-setting-whole-user-scope",[1225],{"type":58,"value":1226},"Step P.0a — Loud disclosure before setting whole-user scope",{"type":52,"tag":67,"props":1228,"children":1229},{},[1230,1232,1237],{"type":58,"value":1231},"If the operator picked whole-user, surface this disclosure\n",{"type":52,"tag":109,"props":1233,"children":1234},{},[1235],{"type":58,"value":1236},"before",{"type":58,"value":1238}," any global config write. The operator must\nacknowledge it explicitly; no silent proceed:",{"type":52,"tag":1240,"props":1241,"children":1242},"blockquote",{},[1243,1258,1315,1320,1425],{"type":52,"tag":67,"props":1244,"children":1245},{},[1246],{"type":52,"tag":109,"props":1247,"children":1248},{},[1249,1251,1256],{"type":58,"value":1250},"!!! WHOLE-USER SCOPE — ",{"type":52,"tag":82,"props":1252,"children":1254},{"className":1253},[],[1255],{"type":58,"value":1217},{"type":58,"value":1257}," GLOBAL OVERRIDE !!!",{"type":52,"tag":67,"props":1259,"children":1260},{},[1261,1263,1268,1270,1275,1277,1283,1285,1290,1292,1298,1300,1306,1307,1313],{"type":58,"value":1262},"Setting ",{"type":52,"tag":82,"props":1264,"children":1266},{"className":1265},[],[1267],{"type":58,"value":1040},{"type":58,"value":1269}," makes git look up\nhooks in ",{"type":52,"tag":109,"props":1271,"children":1272},{},[1273],{"type":58,"value":1274},"one shared directory",{"type":58,"value":1276}," for every repo on this host.\nEvery ",{"type":52,"tag":82,"props":1278,"children":1280},{"className":1279},[],[1281],{"type":58,"value":1282},".git\u002Fhooks\u002F*",{"type":58,"value":1284}," in every existing repo on this machine\nbecomes ",{"type":52,"tag":109,"props":1286,"children":1287},{},[1288],{"type":58,"value":1289},"inert",{"type":58,"value":1291}," — git will no longer fire your per-repo\n",{"type":52,"tag":82,"props":1293,"children":1295},{"className":1294},[],[1296],{"type":58,"value":1297},"pre-commit",{"type":58,"value":1299},", ",{"type":52,"tag":82,"props":1301,"children":1303},{"className":1302},[],[1304],{"type":58,"value":1305},"commit-msg",{"type":58,"value":1299},{"type":52,"tag":82,"props":1308,"children":1310},{"className":1309},[],[1311],{"type":58,"value":1312},"pre-push",{"type":58,"value":1314},", or any other hook\nunless the shared dir chains back to them.",{"type":52,"tag":67,"props":1316,"children":1317},{},[1318],{"type":58,"value":1319},"There are two whole-user flavours (you choose next, Step P.0b):",{"type":52,"tag":270,"props":1321,"children":1322},{},[1323,1356],{"type":52,"tag":274,"props":1324,"children":1325},{},[1326,1331,1333,1338,1340,1346,1348,1354],{"type":52,"tag":109,"props":1327,"children":1328},{},[1329],{"type":58,"value":1330},"Simple",{"type":58,"value":1332}," — the framework installs ",{"type":52,"tag":109,"props":1334,"children":1335},{},[1336],{"type":58,"value":1337},"only",{"type":58,"value":1339}," the\n",{"type":52,"tag":82,"props":1341,"children":1343},{"className":1342},[],[1344],{"type":58,"value":1345},"post-checkout",{"type":58,"value":1347}," hook in the shared dir. Every other per-repo\nhook stays inert until you migrate it into ",{"type":52,"tag":82,"props":1349,"children":1351},{"className":1350},[],[1352],{"type":58,"value":1353},"~\u002F.claude\u002Fgit-hooks\u002F",{"type":58,"value":1355},"\nyourself. Pick this only if you don't rely on per-repo hooks.",{"type":52,"tag":274,"props":1357,"children":1358},{},[1359,1364,1366,1371,1373,1378,1380,1391,1393,1399,1401,1407,1409,1415,1417,1423],{"type":52,"tag":109,"props":1360,"children":1361},{},[1362],{"type":58,"value":1363},"With per-repo dispatcher (recommended if you use prek \u002F\npre-commit \u002F husky \u002F any per-repo hook)",{"type":58,"value":1365}," — the framework\ninstalls a ",{"type":52,"tag":109,"props":1367,"children":1368},{},[1369],{"type":58,"value":1370},"dispatcher",{"type":58,"value":1372}," for each hook type. Each dispatcher\nruns the framework's own logic (the ",{"type":52,"tag":82,"props":1374,"children":1376},{"className":1375},[],[1377],{"type":58,"value":1345},{"type":58,"value":1379},"\nsandbox-allowlist sync) ",{"type":52,"tag":109,"props":1381,"children":1382},{},[1383,1385],{"type":58,"value":1384},"and then chains through to that\nrepo's own ",{"type":52,"tag":82,"props":1386,"children":1388},{"className":1387},[],[1389],{"type":58,"value":1390},".git\u002Fhooks\u002F\u003Cname>",{"type":58,"value":1392},". Your per-repo hooks keep\nfiring, and a repo with no hook is a clean no-op. A bundled\n",{"type":52,"tag":82,"props":1394,"children":1396},{"className":1395},[],[1397],{"type":58,"value":1398},"prek",{"type":58,"value":1400}," PATH shim makes ",{"type":52,"tag":82,"props":1402,"children":1404},{"className":1403},[],[1405],{"type":58,"value":1406},"prek install",{"type":58,"value":1408}," write its shim into the\nrepo-local ",{"type":52,"tag":82,"props":1410,"children":1412},{"className":1411},[],[1413],{"type":58,"value":1414},".git\u002Fhooks\u002F",{"type":58,"value":1416}," (via ",{"type":52,"tag":82,"props":1418,"children":1420},{"className":1419},[],[1421],{"type":58,"value":1422},"--git-dir",{"type":58,"value":1424},") so the dispatcher\ncan find it.",{"type":52,"tag":67,"props":1426,"children":1427},{},[1428,1430,1436,1438,1444,1446,1451],{"type":58,"value":1429},"Either way, whole-user scope is reversible:\n",{"type":52,"tag":82,"props":1431,"children":1433},{"className":1432},[],[1434],{"type":58,"value":1435},"git config --global --unset core.hooksPath",{"type":58,"value":1437}," restores per-repo\nhook lookup, and (dispatcher flavour) removing\n",{"type":52,"tag":82,"props":1439,"children":1441},{"className":1440},[],[1442],{"type":58,"value":1443},"~\u002F.claude\u002Fbin",{"type":58,"value":1445}," from PATH restores the stock ",{"type":52,"tag":82,"props":1447,"children":1449},{"className":1448},[],[1450],{"type":58,"value":1398},{"type":58,"value":206},{"type":52,"tag":67,"props":1453,"children":1454},{},[1455],{"type":58,"value":1456},"Confirm the operator wants to proceed with whole-user scope after\nreading the disclosure. If they hesitate or pick per-project,\nfall back to the per-project path.",{"type":52,"tag":1221,"props":1458,"children":1460},{"id":1459},"step-p0b-choose-the-whole-user-flavour-simple-or-dispatcher",[1461],{"type":58,"value":1462},"Step P.0b — Choose the whole-user flavour: simple or dispatcher",{"type":52,"tag":67,"props":1464,"children":1465},{},[1466,1468,1473,1475,1480],{"type":58,"value":1467},"If the operator confirmed whole-user, ask which flavour (see the\ndisclosure above for the trade-off). ",{"type":52,"tag":109,"props":1469,"children":1470},{},[1471],{"type":58,"value":1472},"Default to the dispatcher\nflavour",{"type":58,"value":1474}," — it is a strict superset of simple (it still runs the\n",{"type":52,"tag":82,"props":1476,"children":1478},{"className":1477},[],[1479],{"type":58,"value":1345},{"type":58,"value":1481}," sync everywhere) and it avoids silently shadowing\nper-repo hooks, which is the most common whole-user surprise.\nPick simple only if the operator explicitly wants the minimal\nfootprint and confirms they run no per-repo hooks.",{"type":52,"tag":67,"props":1483,"children":1484},{},[1485,1490,1492,1498,1500,1506],{"type":52,"tag":109,"props":1486,"children":1487},{},[1488],{"type":58,"value":1489},"Prefer structured Q&A",{"type":58,"value":1491}," here too: a single-select with\n",{"type":52,"tag":82,"props":1493,"children":1495},{"className":1494},[],[1496],{"type":58,"value":1497},"With per-repo dispatcher (recommended)",{"type":58,"value":1499}," as the default and\n",{"type":52,"tag":82,"props":1501,"children":1503},{"className":1502},[],[1504],{"type":58,"value":1505},"Simple (post-checkout only)",{"type":58,"value":1507}," as the alternative.",{"type":52,"tag":270,"props":1509,"children":1510},{},[1511,1528],{"type":52,"tag":274,"props":1512,"children":1513},{},[1514,1518,1520,1526],{"type":52,"tag":109,"props":1515,"children":1516},{},[1517],{"type":58,"value":1330},{"type":58,"value":1519}," → Step P.3-whole-user installs ",{"type":52,"tag":82,"props":1521,"children":1523},{"className":1522},[],[1524],{"type":58,"value":1525},"git-global-post-checkout.sh",{"type":58,"value":1527},"\nonly.",{"type":52,"tag":274,"props":1529,"children":1530},{},[1531,1536,1538,1544,1546,1551,1553,1558,1560,1565],{"type":52,"tag":109,"props":1532,"children":1533},{},[1534],{"type":58,"value":1535},"Dispatcher",{"type":58,"value":1537}," → Step P.3-whole-user still runs, and Step\nP.3b-whole-user additionally installs ",{"type":52,"tag":82,"props":1539,"children":1541},{"className":1540},[],[1542],{"type":58,"value":1543},"git-hook-dispatcher.sh",{"type":58,"value":1545},"\n(symlinked to each hook name, including ",{"type":52,"tag":82,"props":1547,"children":1549},{"className":1548},[],[1550],{"type":58,"value":1345},{"type":58,"value":1552}," — which\nin this flavour supersedes the standalone ",{"type":52,"tag":82,"props":1554,"children":1556},{"className":1555},[],[1557],{"type":58,"value":1525},{"type":58,"value":1559},")\nand the ",{"type":52,"tag":82,"props":1561,"children":1563},{"className":1562},[],[1564],{"type":58,"value":1398},{"type":58,"value":1566}," PATH shim.",{"type":52,"tag":976,"props":1568,"children":1570},{"id":1569},"step-p1-install-the-helper-script",[1571],{"type":58,"value":1572},"Step P.1 — Install the helper script",{"type":52,"tag":67,"props":1574,"children":1575},{},[1576],{"type":58,"value":1577},"(Both scopes.)",{"type":52,"tag":67,"props":1579,"children":1580},{},[1581,1583,1589,1591,1597,1599,1604,1606,1612,1614,1619,1621,1627,1628,1634,1636,1641,1643,1648],{"type":58,"value":1582},"Copy ",{"type":52,"tag":82,"props":1584,"children":1586},{"className":1585},[],[1587],{"type":58,"value":1588},"tools\u002Fagent-isolation\u002Fsandbox-add-project-root.sh",{"type":58,"value":1590}," into\n",{"type":52,"tag":82,"props":1592,"children":1594},{"className":1593},[],[1595],{"type":58,"value":1596},"~\u002F.claude\u002Fscripts\u002Fsandbox-add-project-root.sh",{"type":58,"value":1598}," (or symlink it\nfrom ",{"type":52,"tag":82,"props":1600,"children":1602},{"className":1601},[],[1603],{"type":58,"value":697},{"type":58,"value":1605}," if the operator uses the\nprivate sync repo), mode ",{"type":52,"tag":82,"props":1607,"children":1609},{"className":1608},[],[1610],{"type":58,"value":1611},"0755",{"type":58,"value":1613},". The script file lives\nuser-scope so a single install covers every adopter project on\nthe host; what it ",{"type":52,"tag":109,"props":1615,"children":1616},{},[1617],{"type":58,"value":1618},"writes",{"type":58,"value":1620}," is project-local. The same install\nmechanism the ",{"type":52,"tag":82,"props":1622,"children":1624},{"className":1623},[],[1625],{"type":58,"value":1626},"sandbox-bypass-warn.sh",{"type":58,"value":943},{"type":52,"tag":82,"props":1629,"children":1631},{"className":1630},[],[1632],{"type":58,"value":1633},"sandbox-status-line.sh",{"type":58,"value":1635},"\nhelpers use (see the ",{"type":52,"tag":129,"props":1637,"children":1638},{},[1639],{"type":58,"value":1640},"Sandbox-bypass visibility hook",{"type":58,"value":1642}," and\n",{"type":52,"tag":129,"props":1644,"children":1645},{},[1646],{"type":58,"value":1647},"Sandbox-state status line",{"type":58,"value":1649}," sections of the doc).",{"type":52,"tag":976,"props":1651,"children":1653},{"id":1652},"step-p2-run-the-helper-for-this-project-per-project-scope",[1654],{"type":58,"value":1655},"Step P.2 — Run the helper for this project (per-project scope)",{"type":52,"tag":67,"props":1657,"children":1658},{},[1659],{"type":58,"value":1660},"Skip if the operator picked whole-user scope (Step P.2-whole-user\nbelow covers the equivalent).",{"type":52,"tag":67,"props":1662,"children":1663},{},[1664,1666,1672,1674,1680,1682,1687],{"type":58,"value":1665},"Run the helper once with ",{"type":52,"tag":82,"props":1667,"children":1669},{"className":1668},[],[1670],{"type":58,"value":1671},"--all-worktrees",{"type":58,"value":1673}," in the adopter\nrepo's main checkout. The helper enumerates\n",{"type":52,"tag":82,"props":1675,"children":1677},{"className":1676},[],[1678],{"type":58,"value":1679},"git worktree list --porcelain",{"type":58,"value":1681}," and, for each worktree, writes\nthat worktree's absolute path into that worktree's own\n",{"type":52,"tag":82,"props":1683,"children":1685},{"className":1684},[],[1686],{"type":58,"value":972},{"type":58,"value":1688}," (creating the file if\nit does not yet exist). Idempotent, atomic, tolerant of missing\nprereqs (see the script's header comment for the full\nfailure-mode list). On success, surface the diff so the operator\nsees which entries landed; on no-op (paths already present),\nsurface a one-line \"already covered\" confirmation.",{"type":52,"tag":67,"props":1690,"children":1691},{},[1692,1697,1698,1704,1706,1712,1714,1729,1731,1736,1738,1744,1746,1751,1753,1758,1760,1765],{"type":52,"tag":109,"props":1693,"children":1694},{},[1695],{"type":58,"value":1696},"Sandbox-bypass requirement when invoked from inside an agent\nsession.",{"type":58,"value":371},{"type":52,"tag":82,"props":1699,"children":1701},{"className":1700},[],[1702],{"type":58,"value":1703},".claude\u002Fsettings.local.json",{"type":58,"value":1705}," is in Claude Code's\nbuilt-in sandbox ",{"type":52,"tag":82,"props":1707,"children":1709},{"className":1708},[],[1710],{"type":58,"value":1711},"denyWithinAllow",{"type":58,"value":1713}," set (verified empirically —\nsee\n",{"type":52,"tag":73,"props":1715,"children":1717},{"href":1716},"..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#security-rationale--why-project-local-is-safe-to-write-to",[1718,1723,1724],{"type":52,"tag":82,"props":1719,"children":1721},{"className":1720},[],[1722],{"type":58,"value":125},{"type":58,"value":884},{"type":52,"tag":129,"props":1725,"children":1726},{},[1727],{"type":58,"value":1728},"Security rationale",{"type":58,"value":1730},"),\nso the helper's Bash write is blocked when invoked through the\nagent's ",{"type":52,"tag":82,"props":1732,"children":1734},{"className":1733},[],[1735],{"type":58,"value":465},{"type":58,"value":1737}," tool. If this skill is being walked from inside\na sandboxed session, invoke the helper with\n",{"type":52,"tag":82,"props":1739,"children":1741},{"className":1740},[],[1742],{"type":58,"value":1743},"dangerouslyDisableSandbox: true",{"type":58,"value":1745}," and the reason\n",{"type":52,"tag":129,"props":1747,"children":1748},{},[1749],{"type":58,"value":1750},"\"writing project-local sandbox-allowlist entries (issue #197 fix)\"",{"type":58,"value":1752},".\nThe bypass triggers ",{"type":52,"tag":82,"props":1754,"children":1756},{"className":1755},[],[1757],{"type":58,"value":1626},{"type":58,"value":1759},"'s loud-red banner\nso the operator sees and approves the single write. When the\noperator runs ",{"type":52,"tag":82,"props":1761,"children":1763},{"className":1762},[],[1764],{"type":58,"value":55},{"type":58,"value":1766}," directly from a\nterminal (the typical first-time-install path), no bypass is\nneeded — the script runs outside the agent sandbox.",{"type":52,"tag":976,"props":1768,"children":1770},{"id":1769},"step-p2-whole-user-walk-existing-checkouts-whole-user-scope",[1771],{"type":58,"value":1772},"Step P.2-whole-user — Walk existing checkouts (whole-user scope)",{"type":52,"tag":67,"props":1774,"children":1775},{},[1776],{"type":58,"value":1777},"Skip if the operator picked per-project scope.",{"type":52,"tag":67,"props":1779,"children":1780},{},[1781,1783,1788,1790,1795,1797,1802,1804,1809],{"type":58,"value":1782},"Walk the operator's existing git checkouts and populate each\none's ",{"type":52,"tag":82,"props":1784,"children":1786},{"className":1785},[],[1787],{"type":58,"value":1703},{"type":58,"value":1789},". This pass is ",{"type":52,"tag":109,"props":1791,"children":1792},{},[1793],{"type":58,"value":1794},"settings-only",{"type":58,"value":1796},"\nby default — it does NOT install per-repo ",{"type":52,"tag":82,"props":1798,"children":1800},{"className":1799},[],[1801],{"type":58,"value":1345},{"type":58,"value":1803}," hooks\n(the global hook installed in Step P.3-whole-user covers that\nfor both existing and future repos via ",{"type":52,"tag":82,"props":1805,"children":1807},{"className":1806},[],[1808],{"type":58,"value":1217},{"type":58,"value":1810},").",{"type":52,"tag":573,"props":1812,"children":1813},{},[1814,1853,2148,2195,2227],{"type":52,"tag":274,"props":1815,"children":1816},{},[1817,1822,1824,1830,1831,1837,1838,1844,1845,1851],{"type":52,"tag":109,"props":1818,"children":1819},{},[1820],{"type":58,"value":1821},"Prompt the operator for root directories to scan.",{"type":58,"value":1823},"\nDefault suggestions: ",{"type":52,"tag":82,"props":1825,"children":1827},{"className":1826},[],[1828],{"type":58,"value":1829},"~\u002Fcode\u002F",{"type":58,"value":1299},{"type":52,"tag":82,"props":1832,"children":1834},{"className":1833},[],[1835],{"type":58,"value":1836},"~\u002Fprojects\u002F",{"type":58,"value":1299},{"type":52,"tag":82,"props":1839,"children":1841},{"className":1840},[],[1842],{"type":58,"value":1843},"~\u002Fdev\u002F",{"type":58,"value":611},{"type":52,"tag":82,"props":1846,"children":1848},{"className":1847},[],[1849],{"type":58,"value":1850},"~\u002Fwork\u002F",{"type":58,"value":1852},". Show the operator the list, let them edit it.\nEmpty list → skip the walk; the operator can re-run this\nskill later when they want existing repos covered.",{"type":52,"tag":274,"props":1854,"children":1855},{},[1856,1861,1863,1869,1871,2134,2138,2140,2146],{"type":52,"tag":109,"props":1857,"children":1858},{},[1859],{"type":58,"value":1860},"Walk each root dir.",{"type":58,"value":1862}," Use a depth-limited ",{"type":52,"tag":82,"props":1864,"children":1866},{"className":1865},[],[1867],{"type":58,"value":1868},"find",{"type":58,"value":1870}," with\nreasonable exclusions:",{"type":52,"tag":1872,"props":1873,"children":1878},"pre",{"className":1874,"code":1875,"language":1876,"meta":1877,"style":1877},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","find \"\u003Croot>\" -maxdepth 5 -type d -name .git \\\n    -not -path '*\u002Fnode_modules\u002F*' \\\n    -not -path '*\u002F.venv\u002F*' \\\n    -not -path '*\u002F__pycache__\u002F*' \\\n    -not -path '*\u002Fbuild\u002F*' \\\n    -not -path '*\u002Fdist\u002F*' \\\n    -not -path '*\u002F.cache\u002F*' \\\n    -prune\n","bash","",[1879],{"type":52,"tag":82,"props":1880,"children":1881},{"__ignoreMap":1877},[1882,1947,1980,2009,2038,2067,2096,2125],{"type":52,"tag":1883,"props":1884,"children":1887},"span",{"class":1885,"line":1886},"line",1,[1888,1893,1899,1905,1910,1915,1921,1926,1931,1936,1941],{"type":52,"tag":1883,"props":1889,"children":1891},{"style":1890},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1892],{"type":58,"value":1868},{"type":52,"tag":1883,"props":1894,"children":1896},{"style":1895},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1897],{"type":58,"value":1898}," \"",{"type":52,"tag":1883,"props":1900,"children":1902},{"style":1901},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1903],{"type":58,"value":1904},"\u003Croot>",{"type":52,"tag":1883,"props":1906,"children":1907},{"style":1895},[1908],{"type":58,"value":1909},"\"",{"type":52,"tag":1883,"props":1911,"children":1912},{"style":1901},[1913],{"type":58,"value":1914}," -maxdepth",{"type":52,"tag":1883,"props":1916,"children":1918},{"style":1917},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1919],{"type":58,"value":1920}," 5",{"type":52,"tag":1883,"props":1922,"children":1923},{"style":1901},[1924],{"type":58,"value":1925}," -type",{"type":52,"tag":1883,"props":1927,"children":1928},{"style":1901},[1929],{"type":58,"value":1930}," d",{"type":52,"tag":1883,"props":1932,"children":1933},{"style":1901},[1934],{"type":58,"value":1935}," -name",{"type":52,"tag":1883,"props":1937,"children":1938},{"style":1901},[1939],{"type":58,"value":1940}," .git",{"type":52,"tag":1883,"props":1942,"children":1944},{"style":1943},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1945],{"type":58,"value":1946}," \\\n",{"type":52,"tag":1883,"props":1948,"children":1950},{"class":1885,"line":1949},2,[1951,1956,1961,1966,1971,1976],{"type":52,"tag":1883,"props":1952,"children":1953},{"style":1901},[1954],{"type":58,"value":1955},"    -not",{"type":52,"tag":1883,"props":1957,"children":1958},{"style":1901},[1959],{"type":58,"value":1960}," -path",{"type":52,"tag":1883,"props":1962,"children":1963},{"style":1895},[1964],{"type":58,"value":1965}," '",{"type":52,"tag":1883,"props":1967,"children":1968},{"style":1901},[1969],{"type":58,"value":1970},"*\u002Fnode_modules\u002F*",{"type":52,"tag":1883,"props":1972,"children":1973},{"style":1895},[1974],{"type":58,"value":1975},"'",{"type":52,"tag":1883,"props":1977,"children":1978},{"style":1943},[1979],{"type":58,"value":1946},{"type":52,"tag":1883,"props":1981,"children":1983},{"class":1885,"line":1982},3,[1984,1988,1992,1996,2001,2005],{"type":52,"tag":1883,"props":1985,"children":1986},{"style":1901},[1987],{"type":58,"value":1955},{"type":52,"tag":1883,"props":1989,"children":1990},{"style":1901},[1991],{"type":58,"value":1960},{"type":52,"tag":1883,"props":1993,"children":1994},{"style":1895},[1995],{"type":58,"value":1965},{"type":52,"tag":1883,"props":1997,"children":1998},{"style":1901},[1999],{"type":58,"value":2000},"*\u002F.venv\u002F*",{"type":52,"tag":1883,"props":2002,"children":2003},{"style":1895},[2004],{"type":58,"value":1975},{"type":52,"tag":1883,"props":2006,"children":2007},{"style":1943},[2008],{"type":58,"value":1946},{"type":52,"tag":1883,"props":2010,"children":2012},{"class":1885,"line":2011},4,[2013,2017,2021,2025,2030,2034],{"type":52,"tag":1883,"props":2014,"children":2015},{"style":1901},[2016],{"type":58,"value":1955},{"type":52,"tag":1883,"props":2018,"children":2019},{"style":1901},[2020],{"type":58,"value":1960},{"type":52,"tag":1883,"props":2022,"children":2023},{"style":1895},[2024],{"type":58,"value":1965},{"type":52,"tag":1883,"props":2026,"children":2027},{"style":1901},[2028],{"type":58,"value":2029},"*\u002F__pycache__\u002F*",{"type":52,"tag":1883,"props":2031,"children":2032},{"style":1895},[2033],{"type":58,"value":1975},{"type":52,"tag":1883,"props":2035,"children":2036},{"style":1943},[2037],{"type":58,"value":1946},{"type":52,"tag":1883,"props":2039,"children":2041},{"class":1885,"line":2040},5,[2042,2046,2050,2054,2059,2063],{"type":52,"tag":1883,"props":2043,"children":2044},{"style":1901},[2045],{"type":58,"value":1955},{"type":52,"tag":1883,"props":2047,"children":2048},{"style":1901},[2049],{"type":58,"value":1960},{"type":52,"tag":1883,"props":2051,"children":2052},{"style":1895},[2053],{"type":58,"value":1965},{"type":52,"tag":1883,"props":2055,"children":2056},{"style":1901},[2057],{"type":58,"value":2058},"*\u002Fbuild\u002F*",{"type":52,"tag":1883,"props":2060,"children":2061},{"style":1895},[2062],{"type":58,"value":1975},{"type":52,"tag":1883,"props":2064,"children":2065},{"style":1943},[2066],{"type":58,"value":1946},{"type":52,"tag":1883,"props":2068,"children":2070},{"class":1885,"line":2069},6,[2071,2075,2079,2083,2088,2092],{"type":52,"tag":1883,"props":2072,"children":2073},{"style":1901},[2074],{"type":58,"value":1955},{"type":52,"tag":1883,"props":2076,"children":2077},{"style":1901},[2078],{"type":58,"value":1960},{"type":52,"tag":1883,"props":2080,"children":2081},{"style":1895},[2082],{"type":58,"value":1965},{"type":52,"tag":1883,"props":2084,"children":2085},{"style":1901},[2086],{"type":58,"value":2087},"*\u002Fdist\u002F*",{"type":52,"tag":1883,"props":2089,"children":2090},{"style":1895},[2091],{"type":58,"value":1975},{"type":52,"tag":1883,"props":2093,"children":2094},{"style":1943},[2095],{"type":58,"value":1946},{"type":52,"tag":1883,"props":2097,"children":2099},{"class":1885,"line":2098},7,[2100,2104,2108,2112,2117,2121],{"type":52,"tag":1883,"props":2101,"children":2102},{"style":1901},[2103],{"type":58,"value":1955},{"type":52,"tag":1883,"props":2105,"children":2106},{"style":1901},[2107],{"type":58,"value":1960},{"type":52,"tag":1883,"props":2109,"children":2110},{"style":1895},[2111],{"type":58,"value":1965},{"type":52,"tag":1883,"props":2113,"children":2114},{"style":1901},[2115],{"type":58,"value":2116},"*\u002F.cache\u002F*",{"type":52,"tag":1883,"props":2118,"children":2119},{"style":1895},[2120],{"type":58,"value":1975},{"type":52,"tag":1883,"props":2122,"children":2123},{"style":1943},[2124],{"type":58,"value":1946},{"type":52,"tag":1883,"props":2126,"children":2128},{"class":1885,"line":2127},8,[2129],{"type":52,"tag":1883,"props":2130,"children":2131},{"style":1901},[2132],{"type":58,"value":2133},"    -prune\n",{"type":52,"tag":2135,"props":2136,"children":2137},"br",{},[],{"type":58,"value":2139},"For each ",{"type":52,"tag":82,"props":2141,"children":2143},{"className":2142},[],[2144],{"type":58,"value":2145},".git\u002F",{"type":58,"value":2147}," found, the parent dir is a working tree.\nDe-duplicate by canonical path.",{"type":52,"tag":274,"props":2149,"children":2150},{},[2151,2162,2164,2170,2172,2178,2180,2185,2187,2193],{"type":52,"tag":109,"props":2152,"children":2153},{},[2154,2156,2161],{"type":58,"value":2155},"For each working tree found, run the helper with\n",{"type":52,"tag":82,"props":2157,"children":2159},{"className":2158},[],[2160],{"type":58,"value":1671},{"type":58,"value":206},{"type":58,"value":2163}," Same invocation as the per-project\nvariant — the helper itself handles ",{"type":52,"tag":82,"props":2165,"children":2167},{"className":2166},[],[2168],{"type":58,"value":2169},"git worktree list",{"type":58,"value":2171}," so\nlinked worktrees of the same repo get processed. The helper's\nbuilt-in ",{"type":52,"tag":82,"props":2173,"children":2175},{"className":2174},[],[2176],{"type":58,"value":2177},"git check-ignore",{"type":58,"value":2179}," guard skips repos whose\n",{"type":52,"tag":82,"props":2181,"children":2183},{"className":2182},[],[2184],{"type":58,"value":1703},{"type":58,"value":2186}," is not gitignored (defense in\ndepth — the operator should fix the ",{"type":52,"tag":82,"props":2188,"children":2190},{"className":2189},[],[2191],{"type":58,"value":2192},".gitignore",{"type":58,"value":2194}," first).",{"type":52,"tag":274,"props":2196,"children":2197},{},[2198,2203,2205,2211,2213,2218,2220,2225],{"type":52,"tag":109,"props":2199,"children":2200},{},[2201],{"type":58,"value":2202},"Tabulate the result",{"type":58,"value":2204}," for the operator: how many checkouts\nwere scanned, how many had ",{"type":52,"tag":82,"props":2206,"children":2208},{"className":2207},[],[2209],{"type":58,"value":2210},".claude\u002F",{"type":58,"value":2212}," (so the helper wrote),\nhow many were skipped (no ",{"type":52,"tag":82,"props":2214,"children":2216},{"className":2215},[],[2217],{"type":58,"value":2210},{"type":58,"value":2219}," directory, or\n",{"type":52,"tag":82,"props":2221,"children":2223},{"className":2222},[],[2224],{"type":58,"value":1703},{"type":58,"value":2226}," not gitignored).",{"type":52,"tag":274,"props":2228,"children":2229},{},[2230,2242],{"type":52,"tag":109,"props":2231,"children":2232},{},[2233,2235,2240],{"type":58,"value":2234},"Do not install per-repo ",{"type":52,"tag":82,"props":2236,"children":2238},{"className":2237},[],[2239],{"type":58,"value":1345},{"type":58,"value":2241}," hooks",{"type":58,"value":2243}," during this\npass. The next sub-step covers future and existing repos\nuniformly via the global hook.",{"type":52,"tag":976,"props":2245,"children":2247},{"id":2246},"step-p3-whole-user-install-the-global-post-checkout-hook-whole-user-scope",[2248],{"type":58,"value":2249},"Step P.3-whole-user — Install the global post-checkout hook (whole-user scope)",{"type":52,"tag":67,"props":2251,"children":2252},{},[2253,2255,2260,2262,2267,2269,2274,2276,2281],{"type":58,"value":2254},"Skip if the operator picked per-project scope. ",{"type":52,"tag":109,"props":2256,"children":2257},{},[2258],{"type":58,"value":2259},"Dispatcher\nflavour (Step P.0b):",{"type":58,"value":2261}," skip step 1 below — Step P.3b-whole-user\ninstalls the dispatcher as ",{"type":52,"tag":82,"props":2263,"children":2265},{"className":2264},[],[2266],{"type":58,"value":1345},{"type":58,"value":2268}," instead, superseding the\nstandalone ",{"type":52,"tag":82,"props":2270,"children":2272},{"className":2271},[],[2273],{"type":58,"value":1525},{"type":58,"value":2275},". Still run step 2 (set\n",{"type":52,"tag":82,"props":2277,"children":2279},{"className":2278},[],[2280],{"type":58,"value":1217},{"type":58,"value":2282},") here.",{"type":52,"tag":573,"props":2284,"children":2285},{},[2286,2344,2422],{"type":52,"tag":274,"props":2287,"children":2288},{},[2289,2301,2303,2309,2310,2316,2318,2324,2326,2331,2333,2342],{"type":52,"tag":109,"props":2290,"children":2291},{},[2292,2294,2299],{"type":58,"value":2293},"(Simple flavour only) Install the universal ",{"type":52,"tag":82,"props":2295,"children":2297},{"className":2296},[],[2298],{"type":58,"value":1345},{"type":58,"value":2300},"\nhook.",{"type":58,"value":2302}," Copy\n",{"type":52,"tag":82,"props":2304,"children":2306},{"className":2305},[],[2307],{"type":58,"value":2308},"tools\u002Fagent-isolation\u002Fgit-global-post-checkout.sh",{"type":58,"value":1590},{"type":52,"tag":82,"props":2311,"children":2313},{"className":2312},[],[2314],{"type":58,"value":2315},"~\u002F.claude\u002Fgit-hooks\u002Fpost-checkout",{"type":58,"value":2317}," (or symlink it from\n",{"type":52,"tag":82,"props":2319,"children":2321},{"className":2320},[],[2322],{"type":58,"value":2323},"~\u002F.claude-config\u002Fgit-hooks\u002Fpost-checkout",{"type":58,"value":2325}," if the operator\nuses the private sync repo), mode ",{"type":52,"tag":82,"props":2327,"children":2329},{"className":2328},[],[2330],{"type":58,"value":1611},{"type":58,"value":2332},". The hook content is\nin\n",{"type":52,"tag":73,"props":2334,"children":2336},{"href":2335},"..\u002F..\u002Ftools\u002Fagent-isolation\u002Fgit-global-post-checkout.sh",[2337],{"type":52,"tag":82,"props":2338,"children":2340},{"className":2339},[],[2341],{"type":58,"value":2308},{"type":58,"value":2343}," —\nit calls the sandbox-allowlist helper for Claude-Code-aware\nworktrees.",{"type":52,"tag":274,"props":2345,"children":2346},{},[2347,2359,2361,2410,2413,2415,2420],{"type":52,"tag":109,"props":2348,"children":2349},{},[2350,2352,2357],{"type":58,"value":2351},"Set ",{"type":52,"tag":82,"props":2353,"children":2355},{"className":2354},[],[2356],{"type":58,"value":1217},{"type":58,"value":2358}," globally",{"type":58,"value":2360}," so every git operation across\nevery repo on the host uses the shared hook dir:",{"type":52,"tag":1872,"props":2362,"children":2364},{"className":1874,"code":2363,"language":1876,"meta":1877,"style":1877},"git config --global core.hooksPath \"$HOME\u002F.claude\u002Fgit-hooks\"\n",[2365],{"type":52,"tag":82,"props":2366,"children":2367},{"__ignoreMap":1877},[2368],{"type":52,"tag":1883,"props":2369,"children":2370},{"class":1885,"line":1886},[2371,2376,2381,2386,2391,2395,2400,2405],{"type":52,"tag":1883,"props":2372,"children":2373},{"style":1890},[2374],{"type":58,"value":2375},"git",{"type":52,"tag":1883,"props":2377,"children":2378},{"style":1901},[2379],{"type":58,"value":2380}," config",{"type":52,"tag":1883,"props":2382,"children":2383},{"style":1901},[2384],{"type":58,"value":2385}," --global",{"type":52,"tag":1883,"props":2387,"children":2388},{"style":1901},[2389],{"type":58,"value":2390}," core.hooksPath",{"type":52,"tag":1883,"props":2392,"children":2393},{"style":1895},[2394],{"type":58,"value":1898},{"type":52,"tag":1883,"props":2396,"children":2397},{"style":1943},[2398],{"type":58,"value":2399},"$HOME",{"type":52,"tag":1883,"props":2401,"children":2402},{"style":1901},[2403],{"type":58,"value":2404},"\u002F.claude\u002Fgit-hooks",{"type":52,"tag":1883,"props":2406,"children":2407},{"style":1895},[2408],{"type":58,"value":2409},"\"\n",{"type":52,"tag":2135,"props":2411,"children":2412},{},[],{"type":58,"value":2414},"Surface the resulting ",{"type":52,"tag":82,"props":2416,"children":2418},{"className":2417},[],[2419],{"type":58,"value":1079},{"type":58,"value":2421},"\nvalue to the operator to confirm the write.",{"type":52,"tag":274,"props":2423,"children":2424},{},[2425,2430,2432,2437,2439,2444],{"type":52,"tag":109,"props":2426,"children":2427},{},[2428],{"type":58,"value":2429},"Reiterate the implication",{"type":58,"value":2431}," from Step P.0a's disclosure:\nper-repo ",{"type":52,"tag":82,"props":2433,"children":2435},{"className":2434},[],[2436],{"type":58,"value":1282},{"type":58,"value":2438}," are now inert across the entire host.\nThe operator must migrate any per-repo hooks they want to keep.\n",{"type":52,"tag":82,"props":2440,"children":2442},{"className":2441},[],[2443],{"type":58,"value":1435},{"type":58,"value":2445}," is the reversal.",{"type":52,"tag":67,"props":2447,"children":2448},{},[2449,2451,2456,2457,2462,2464,2469,2471,2476],{"type":58,"value":2450},"After this step, future ",{"type":52,"tag":82,"props":2452,"children":2454},{"className":2453},[],[2455],{"type":58,"value":632},{"type":58,"value":1299},{"type":52,"tag":82,"props":2458,"children":2460},{"className":2459},[],[2461],{"type":58,"value":1061},{"type":58,"value":2463},", and\n",{"type":52,"tag":82,"props":2465,"children":2467},{"className":2466},[],[2468],{"type":58,"value":1048},{"type":58,"value":2470}," operations anywhere on the host invoke the\nframework's universal post-checkout, which keeps each\nClaude-Code-aware project's ",{"type":52,"tag":82,"props":2472,"children":2474},{"className":2473},[],[2475],{"type":58,"value":1703},{"type":58,"value":2477}," in\nsync without any further operator action.",{"type":52,"tag":976,"props":2479,"children":2481},{"id":2480},"step-p3b-whole-user-install-the-per-repo-dispatcher-prek-shim-dispatcher-flavour-only",[2482],{"type":58,"value":2483},"Step P.3b-whole-user — Install the per-repo dispatcher + prek shim (dispatcher flavour only)",{"type":52,"tag":67,"props":2485,"children":2486},{},[2487,2489,2493,2495,2500,2502,2512,2514,2529],{"type":58,"value":2488},"Skip unless the operator picked the ",{"type":52,"tag":109,"props":2490,"children":2491},{},[2492],{"type":58,"value":1370},{"type":58,"value":2494}," flavour in\nStep P.0b. This is what keeps the operator's per-repo hooks (prek,\npre-commit, husky, hand-written) firing under global\n",{"type":52,"tag":82,"props":2496,"children":2498},{"className":2497},[],[2499],{"type":58,"value":1217},{"type":58,"value":2501}," — the shared dir runs the framework's logic ",{"type":52,"tag":109,"props":2503,"children":2504},{},[2505,2507],{"type":58,"value":2506},"and\nthen chains through to each repo's own ",{"type":52,"tag":82,"props":2508,"children":2510},{"className":2509},[],[2511],{"type":58,"value":1390},{"type":58,"value":2513},". See\n",{"type":52,"tag":73,"props":2515,"children":2517},{"href":2516},"..\u002F..\u002Fdocs\u002Fsetup\u002Fsecure-agent-setup.md#whole-user-with-the-per-repo-dispatcher",[2518,2523,2524],{"type":52,"tag":82,"props":2519,"children":2521},{"className":2520},[],[2522],{"type":58,"value":125},{"type":58,"value":884},{"type":52,"tag":129,"props":2525,"children":2526},{},[2527],{"type":58,"value":2528},"Whole-user with the per-repo dispatcher",{"type":58,"value":2530},"\nfor the full rationale + the validated behaviour matrix.",{"type":52,"tag":573,"props":2532,"children":2533},{},[2534,2778,2893,2983],{"type":52,"tag":274,"props":2535,"children":2536},{},[2537,2542,2543,2553,2554,2560,2562,2568,2570,2575,2577,2582,2584,2589,2591,2744,2747,2749,2755,2757,2763,2765,2770,2771,2776],{"type":52,"tag":109,"props":2538,"children":2539},{},[2540],{"type":58,"value":2541},"Install the dispatcher for each hook type.",{"type":58,"value":2302},{"type":52,"tag":73,"props":2544,"children":2546},{"href":2545},"..\u002F..\u002Ftools\u002Fagent-isolation\u002Fgit-hook-dispatcher.sh",[2547],{"type":52,"tag":82,"props":2548,"children":2550},{"className":2549},[],[2551],{"type":58,"value":2552},"tools\u002Fagent-isolation\u002Fgit-hook-dispatcher.sh",{"type":58,"value":691},{"type":52,"tag":82,"props":2555,"children":2557},{"className":2556},[],[2558],{"type":58,"value":2559},"~\u002F.claude\u002Fgit-hooks\u002Fgit-hook-dispatcher.sh",{"type":58,"value":2561}," (or symlink\nfrom ",{"type":52,"tag":82,"props":2563,"children":2565},{"className":2564},[],[2566],{"type":58,"value":2567},"~\u002F.claude-config\u002Fgit-hooks\u002F",{"type":58,"value":2569}," under the private sync repo),\nmode ",{"type":52,"tag":82,"props":2571,"children":2573},{"className":2572},[],[2574],{"type":58,"value":1611},{"type":58,"value":2576},", then create one symlink per hook name pointing at\nit — including ",{"type":52,"tag":82,"props":2578,"children":2580},{"className":2579},[],[2581],{"type":58,"value":1345},{"type":58,"value":2583},", which replaces the standalone\nfile from Step P.3 (the dispatcher runs the same sandbox sync,\nthen chains to any repo-local ",{"type":52,"tag":82,"props":2585,"children":2587},{"className":2586},[],[2588],{"type":58,"value":1345},{"type":58,"value":2590},"):",{"type":52,"tag":1872,"props":2592,"children":2594},{"className":1874,"code":2593,"language":1876,"meta":1877,"style":1877},"cd ~\u002F.claude\u002Fgit-hooks\nfor h in post-checkout pre-commit prepare-commit-msg commit-msg \\\n         post-commit pre-push post-merge post-rewrite \\\n         pre-rebase pre-merge-commit; do\n  ln -sf git-hook-dispatcher.sh \"$h\"\ndone\n",[2595],{"type":52,"tag":82,"props":2596,"children":2597},{"__ignoreMap":1877},[2598,2612,2655,2682,2705,2736],{"type":52,"tag":1883,"props":2599,"children":2600},{"class":1885,"line":1886},[2601,2607],{"type":52,"tag":1883,"props":2602,"children":2604},{"style":2603},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[2605],{"type":58,"value":2606},"cd",{"type":52,"tag":1883,"props":2608,"children":2609},{"style":1901},[2610],{"type":58,"value":2611}," ~\u002F.claude\u002Fgit-hooks\n",{"type":52,"tag":1883,"props":2613,"children":2614},{"class":1885,"line":1949},[2615,2621,2626,2631,2636,2641,2646,2651],{"type":52,"tag":1883,"props":2616,"children":2618},{"style":2617},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[2619],{"type":58,"value":2620},"for",{"type":52,"tag":1883,"props":2622,"children":2623},{"style":1943},[2624],{"type":58,"value":2625}," h ",{"type":52,"tag":1883,"props":2627,"children":2628},{"style":2617},[2629],{"type":58,"value":2630},"in",{"type":52,"tag":1883,"props":2632,"children":2633},{"style":1901},[2634],{"type":58,"value":2635}," post-checkout",{"type":52,"tag":1883,"props":2637,"children":2638},{"style":1901},[2639],{"type":58,"value":2640}," pre-commit",{"type":52,"tag":1883,"props":2642,"children":2643},{"style":1901},[2644],{"type":58,"value":2645}," prepare-commit-msg",{"type":52,"tag":1883,"props":2647,"children":2648},{"style":1901},[2649],{"type":58,"value":2650}," commit-msg",{"type":52,"tag":1883,"props":2652,"children":2653},{"style":1943},[2654],{"type":58,"value":1946},{"type":52,"tag":1883,"props":2656,"children":2657},{"class":1885,"line":1982},[2658,2663,2668,2673,2678],{"type":52,"tag":1883,"props":2659,"children":2660},{"style":1901},[2661],{"type":58,"value":2662},"         post-commit",{"type":52,"tag":1883,"props":2664,"children":2665},{"style":1901},[2666],{"type":58,"value":2667}," pre-push",{"type":52,"tag":1883,"props":2669,"children":2670},{"style":1901},[2671],{"type":58,"value":2672}," post-merge",{"type":52,"tag":1883,"props":2674,"children":2675},{"style":1901},[2676],{"type":58,"value":2677}," post-rewrite",{"type":52,"tag":1883,"props":2679,"children":2680},{"style":1943},[2681],{"type":58,"value":1946},{"type":52,"tag":1883,"props":2683,"children":2684},{"class":1885,"line":2011},[2685,2690,2695,2700],{"type":52,"tag":1883,"props":2686,"children":2687},{"style":1901},[2688],{"type":58,"value":2689},"         pre-rebase",{"type":52,"tag":1883,"props":2691,"children":2692},{"style":1901},[2693],{"type":58,"value":2694}," pre-merge-commit",{"type":52,"tag":1883,"props":2696,"children":2697},{"style":1895},[2698],{"type":58,"value":2699},";",{"type":52,"tag":1883,"props":2701,"children":2702},{"style":2617},[2703],{"type":58,"value":2704}," do\n",{"type":52,"tag":1883,"props":2706,"children":2707},{"class":1885,"line":2040},[2708,2713,2718,2723,2727,2732],{"type":52,"tag":1883,"props":2709,"children":2710},{"style":1890},[2711],{"type":58,"value":2712},"  ln",{"type":52,"tag":1883,"props":2714,"children":2715},{"style":1901},[2716],{"type":58,"value":2717}," -sf",{"type":52,"tag":1883,"props":2719,"children":2720},{"style":1901},[2721],{"type":58,"value":2722}," git-hook-dispatcher.sh",{"type":52,"tag":1883,"props":2724,"children":2725},{"style":1895},[2726],{"type":58,"value":1898},{"type":52,"tag":1883,"props":2728,"children":2729},{"style":1943},[2730],{"type":58,"value":2731},"$h",{"type":52,"tag":1883,"props":2733,"children":2734},{"style":1895},[2735],{"type":58,"value":2409},{"type":52,"tag":1883,"props":2737,"children":2738},{"class":1885,"line":2069},[2739],{"type":52,"tag":1883,"props":2740,"children":2741},{"style":2617},[2742],{"type":58,"value":2743},"done\n",{"type":52,"tag":2135,"props":2745,"children":2746},{},[],{"type":58,"value":2748},"The dispatcher is basename-keyed, so one file serves every hook\ntype. It resolves the repo-local hook via\n",{"type":52,"tag":82,"props":2750,"children":2752},{"className":2751},[],[2753],{"type":58,"value":2754},"git rev-parse --git-common-dir",{"type":58,"value":2756}," (worktree-safe) and ",{"type":52,"tag":82,"props":2758,"children":2760},{"className":2759},[],[2761],{"type":58,"value":2762},"exec",{"type":58,"value":2764},"s it\nwith the original argv + inherited stdin, so a failing local\n",{"type":52,"tag":82,"props":2766,"children":2768},{"className":2767},[],[2769],{"type":58,"value":1297},{"type":58,"value":526},{"type":52,"tag":82,"props":2772,"children":2774},{"className":2773},[],[2775],{"type":58,"value":1312},{"type":58,"value":2777}," still aborts the git operation.",{"type":52,"tag":274,"props":2779,"children":2780},{},[2781,2793,2795,2800,2802,2807,2809,2819,2820,2826,2828,2834,2836,2841,2843,2848,2850,2856,2858,2863,2865,2871,2873,2885,2887,2892],{"type":52,"tag":109,"props":2782,"children":2783},{},[2784,2786,2791],{"type":58,"value":2785},"Install the ",{"type":52,"tag":82,"props":2787,"children":2789},{"className":2788},[],[2790],{"type":58,"value":1398},{"type":58,"value":2792}," PATH shim",{"type":58,"value":2794}," so ",{"type":52,"tag":82,"props":2796,"children":2798},{"className":2797},[],[2799],{"type":58,"value":1406},{"type":58,"value":2801}," writes its\nshim into the repo-local ",{"type":52,"tag":82,"props":2803,"children":2805},{"className":2804},[],[2806],{"type":58,"value":1414},{"type":58,"value":2808}," (where the dispatcher\nchains) instead of the shared dir. Copy\n",{"type":52,"tag":73,"props":2810,"children":2812},{"href":2811},"..\u002F..\u002Ftools\u002Fagent-isolation\u002Fprek-shim.sh",[2813],{"type":52,"tag":82,"props":2814,"children":2816},{"className":2815},[],[2817],{"type":58,"value":2818},"tools\u002Fagent-isolation\u002Fprek-shim.sh",{"type":58,"value":691},{"type":52,"tag":82,"props":2821,"children":2823},{"className":2822},[],[2824],{"type":58,"value":2825},"~\u002F.claude\u002Fbin\u002Fprek",{"type":58,"value":2827}," (or symlink from\n",{"type":52,"tag":82,"props":2829,"children":2831},{"className":2830},[],[2832],{"type":58,"value":2833},"~\u002F.claude-config\u002Fbin\u002Fprek",{"type":58,"value":2835},"), mode ",{"type":52,"tag":82,"props":2837,"children":2839},{"className":2838},[],[2840],{"type":58,"value":1611},{"type":58,"value":2842},". The shim rewrites\nonly ",{"type":52,"tag":82,"props":2844,"children":2846},{"className":2845},[],[2847],{"type":58,"value":1406},{"type":58,"value":2849}," (injecting\n",{"type":52,"tag":82,"props":2851,"children":2853},{"className":2852},[],[2854],{"type":58,"value":2855},"--git-dir \"$(git rev-parse --git-common-dir)\"",{"type":58,"value":2857}," unless the caller\nalready passed ",{"type":52,"tag":82,"props":2859,"children":2861},{"className":2860},[],[2862],{"type":58,"value":1422},{"type":58,"value":2864},", asked for ",{"type":52,"tag":82,"props":2866,"children":2868},{"className":2867},[],[2869],{"type":58,"value":2870},"--help",{"type":58,"value":2872},", or is outside a\ngit work tree); ",{"type":52,"tag":109,"props":2874,"children":2875},{},[2876,2878,2883],{"type":58,"value":2877},"every other ",{"type":52,"tag":82,"props":2879,"children":2881},{"className":2880},[],[2882],{"type":58,"value":1398},{"type":58,"value":2884}," invocation passes through\nunchanged",{"type":58,"value":2886},". It is a no-op on hosts with no global\n",{"type":52,"tag":82,"props":2888,"children":2890},{"className":2889},[],[2891],{"type":58,"value":1217},{"type":58,"value":206},{"type":52,"tag":274,"props":2894,"children":2895},{},[2896,2901,2903,2908,2909,2914,2916,2964,2967,2969,2974,2976,2981],{"type":52,"tag":109,"props":2897,"children":2898},{},[2899],{"type":58,"value":2900},"Surface the PATH line for the operator to add",{"type":58,"value":2902}," to their\n",{"type":52,"tag":82,"props":2904,"children":2906},{"className":2905},[],[2907],{"type":58,"value":377},{"type":58,"value":526},{"type":52,"tag":82,"props":2910,"children":2912},{"className":2911},[],[2913],{"type":58,"value":385},{"type":58,"value":2915}," (per the golden rules — never edit the\nrc file directly):",{"type":52,"tag":1872,"props":2917,"children":2919},{"className":1874,"code":2918,"language":1876,"meta":1877,"style":1877},"export PATH=\"$HOME\u002F.claude\u002Fbin:$PATH\"\n",[2920],{"type":52,"tag":82,"props":2921,"children":2922},{"__ignoreMap":1877},[2923],{"type":52,"tag":1883,"props":2924,"children":2925},{"class":1885,"line":1886},[2926,2932,2937,2942,2946,2950,2955,2960],{"type":52,"tag":1883,"props":2927,"children":2929},{"style":2928},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[2930],{"type":58,"value":2931},"export",{"type":52,"tag":1883,"props":2933,"children":2934},{"style":1943},[2935],{"type":58,"value":2936}," PATH",{"type":52,"tag":1883,"props":2938,"children":2939},{"style":1895},[2940],{"type":58,"value":2941},"=",{"type":52,"tag":1883,"props":2943,"children":2944},{"style":1895},[2945],{"type":58,"value":1909},{"type":52,"tag":1883,"props":2947,"children":2948},{"style":1943},[2949],{"type":58,"value":2399},{"type":52,"tag":1883,"props":2951,"children":2952},{"style":1901},[2953],{"type":58,"value":2954},"\u002F.claude\u002Fbin:",{"type":52,"tag":1883,"props":2956,"children":2957},{"style":1943},[2958],{"type":58,"value":2959},"$PATH",{"type":52,"tag":1883,"props":2961,"children":2962},{"style":1895},[2963],{"type":58,"value":2409},{"type":52,"tag":2135,"props":2965,"children":2966},{},[],{"type":58,"value":2968},"Confirm the rc path with the operator; print the line for them\nto paste. Until it is on PATH ahead of the real ",{"type":52,"tag":82,"props":2970,"children":2972},{"className":2971},[],[2973],{"type":58,"value":1398},{"type":58,"value":2975},", the\nshim is inert and ",{"type":52,"tag":82,"props":2977,"children":2979},{"className":2978},[],[2980],{"type":58,"value":1406},{"type":58,"value":2982}," reverts to writing into the\nshared dir.",{"type":52,"tag":274,"props":2984,"children":2985},{},[2986,2991,2993,2998,3000,3006,3008,3013,3014,3019,3021,3026,3027,3032,3034,3039,3041,3046,3051,3053,3057,3059,3064],{"type":52,"tag":109,"props":2987,"children":2988},{},[2989],{"type":58,"value":2990},"Tell the operator how their existing prek repos are picked up.",{"type":58,"value":2992},"\nRepos that already ran ",{"type":52,"tag":82,"props":2994,"children":2996},{"className":2995},[],[2997],{"type":58,"value":1406},{"type":58,"value":2999}," before this setup have\ntheir shim in ",{"type":52,"tag":82,"props":3001,"children":3003},{"className":3002},[],[3004],{"type":58,"value":3005},".git\u002Fhooks\u002Fpre-commit",{"type":58,"value":3007}," already (that is where a\npre-",{"type":52,"tag":82,"props":3009,"children":3011},{"className":3010},[],[3012],{"type":58,"value":1217},{"type":58,"value":371},{"type":52,"tag":82,"props":3015,"children":3017},{"className":3016},[],[3018],{"type":58,"value":1406},{"type":58,"value":3020}," put it), so the dispatcher\nfinds them with no further action. Repos where they run\n",{"type":52,"tag":82,"props":3022,"children":3024},{"className":3023},[],[3025],{"type":58,"value":1406},{"type":58,"value":371},{"type":52,"tag":129,"props":3028,"children":3029},{},[3030],{"type":58,"value":3031},"after",{"type":58,"value":3033}," the global switch will now install\nlocally via the shim. Only repos where the shim already landed\nin the shared dir (from a ",{"type":52,"tag":82,"props":3035,"children":3037},{"className":3036},[],[3038],{"type":58,"value":1406},{"type":58,"value":3040}," run ",{"type":52,"tag":129,"props":3042,"children":3043},{},[3044],{"type":58,"value":3045},"while",{"type":52,"tag":82,"props":3047,"children":3049},{"className":3048},[],[3050],{"type":58,"value":1217},{"type":58,"value":3052}," was set but ",{"type":52,"tag":129,"props":3054,"children":3055},{},[3056],{"type":58,"value":1236},{"type":58,"value":3058}," this dispatcher setup)\nneed a one-time ",{"type":52,"tag":82,"props":3060,"children":3062},{"className":3061},[],[3063],{"type":58,"value":1406},{"type":58,"value":3065}," re-run through the shim.",{"type":52,"tag":67,"props":3067,"children":3068},{},[3069,3071,3076,3078,3084,3086,3091,3093,3098,3100,3105,3107,3112],{"type":58,"value":3070},"The ",{"type":52,"tag":82,"props":3072,"children":3074},{"className":3073},[],[3075],{"type":58,"value":206},{"type":58,"value":3077}," entry stays in the committed project-scope ",{"type":52,"tag":82,"props":3079,"children":3081},{"className":3080},[],[3082],{"type":58,"value":3083},"allowRead",{"type":58,"value":3085},"\nregardless — the explicit absolute path in\n",{"type":52,"tag":82,"props":3087,"children":3089},{"className":3088},[],[3090],{"type":58,"value":1032},{"type":58,"value":3092}," is belt-and-braces, not a replacement. If\nthe harness ever stops resolving ",{"type":52,"tag":82,"props":3094,"children":3096},{"className":3095},[],[3097],{"type":58,"value":206},{"type":58,"value":3099},", the explicit path still\ncovers the project; if ",{"type":52,"tag":82,"props":3101,"children":3103},{"className":3102},[],[3104],{"type":58,"value":206},{"type":58,"value":3106}," works correctly, the explicit entry is\nredundant but harmless. The committed project-scope file is\n",{"type":52,"tag":109,"props":3108,"children":3109},{},[3110],{"type":58,"value":3111},"never",{"type":58,"value":3113}," modified by the helper (machine-specific absolute paths\nhave no business in a file shared across contributors).",{"type":52,"tag":67,"props":3115,"children":3116},{},[3117,3119,3125,3126,3131,3133,3139,3141,3146,3148,3153,3155,3160],{"type":58,"value":3118},"The helper is also invoked by ",{"type":52,"tag":82,"props":3120,"children":3122},{"className":3121},[],[3123],{"type":58,"value":3124},"\u002Fmagpie-setup adopt",{"type":58,"value":611},{"type":52,"tag":82,"props":3127,"children":3129},{"className":3128},[],[3130],{"type":58,"value":247},{"type":58,"value":3132},", and ",{"type":52,"tag":82,"props":3134,"children":3136},{"className":3135},[],[3137],{"type":58,"value":3138},"\u002Fmagpie-setup worktree-init",{"type":58,"value":3140}," for\nthe same reason. The ",{"type":52,"tag":82,"props":3142,"children":3144},{"className":3143},[],[3145],{"type":58,"value":1345},{"type":58,"value":3147}," git hook installed by\n",{"type":52,"tag":82,"props":3149,"children":3151},{"className":3150},[],[3152],{"type":58,"value":3124},{"type":58,"value":3154}," chains into the helper too, so new\nworktrees added via ",{"type":52,"tag":82,"props":3156,"children":3158},{"className":3157},[],[3159],{"type":58,"value":1061},{"type":58,"value":3161}," after this install pass\ninherit access automatically — no operator action needed.",{"type":52,"tag":60,"props":3163,"children":3165},{"id":3164},"after-the-install-lands",[3166],{"type":58,"value":3167},"After the install lands",{"type":52,"tag":67,"props":3169,"children":3170},{},[3171],{"type":58,"value":3172},"Suggest two follow-up routines the user can wire later:",{"type":52,"tag":270,"props":3174,"children":3175},{},[3176,3186],{"type":52,"tag":274,"props":3177,"children":3178},{},[3179,3184],{"type":52,"tag":82,"props":3180,"children":3182},{"className":3181},[],[3183],{"type":58,"value":745},{"type":58,"value":3185}," — re-run after every Claude Code upgrade\nor settings-file edit, to confirm denials still fire as\nexpected. The \"did a denial silently turn into an allow?\"\nsignal is exactly what this skill exists for.",{"type":52,"tag":274,"props":3187,"children":3188},{},[3189,3195],{"type":52,"tag":82,"props":3190,"children":3192},{"className":3191},[],[3193],{"type":58,"value":3194},"setup-isolated-setup-update",{"type":58,"value":3196}," — periodic check for framework\nupdates, pinned-tool upgrade candidates, and drift between the\ninstalled user-scope copies and the framework's\nsource-of-truth. Recommend a per-Claude-Code-upgrade or\nmonthly cadence, whichever comes first.",{"type":52,"tag":67,"props":3198,"children":3199},{},[3200,3205,3207,3212,3214,3220],{"type":52,"tag":109,"props":3201,"children":3202},{},[3203],{"type":58,"value":3204},"Always propose shared-config sync once the install lands.",{"type":58,"value":3206},"\nRegardless of whether the operator already maintains the\n",{"type":52,"tag":82,"props":3208,"children":3210},{"className":3209},[],[3211],{"type":58,"value":674},{"type":58,"value":3213}," sync repo, proactively offer to run\n",{"type":52,"tag":82,"props":3215,"children":3217},{"className":3216},[],[3218],{"type":58,"value":3219},"setup-shared-config-sync",{"type":58,"value":3221}," as a follow-up:",{"type":52,"tag":270,"props":3223,"children":3224},{},[3225,3237],{"type":52,"tag":274,"props":3226,"children":3227},{},[3228,3230,3235],{"type":58,"value":3229},"If the ",{"type":52,"tag":82,"props":3231,"children":3233},{"className":3232},[],[3234],{"type":58,"value":674},{"type":58,"value":3236}," sync repo is already in place, the\nskill commits + pushes the local modifications (the user-scope\nscripts, hooks, and settings this install just wired up) so the\nother machines pick them up.",{"type":52,"tag":274,"props":3238,"children":3239},{},[3240,3242,3246,3248,3253,3255,3260],{"type":58,"value":3241},"If the operator does ",{"type":52,"tag":109,"props":3243,"children":3244},{},[3245],{"type":58,"value":777},{"type":58,"value":3247}," yet have ",{"type":52,"tag":82,"props":3249,"children":3251},{"className":3250},[],[3252],{"type":58,"value":674},{"type":58,"value":3254},", the\n",{"type":52,"tag":82,"props":3256,"children":3258},{"className":3257},[],[3259],{"type":58,"value":3219},{"type":58,"value":3261}," skill bootstraps it (clones the\ndefault private remote if it exists, or creates a fresh private\nremote and scaffolds the layout). Mention this so a first-time\noperator knows the follow-up will set sync up from scratch — the\npoint of proposing it is precisely so the just-installed config\ndoes not stay machine-local.",{"type":52,"tag":67,"props":3263,"children":3264},{},[3265],{"type":58,"value":3266},"Surface it as an offer for the operator to accept, not an\nauto-run — the sync skill has its own confirmation gates before it\ncommits or pushes anything.",{"type":52,"tag":3268,"props":3269,"children":3270},"style",{},[3271],{"type":58,"value":3272},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":3274,"total":3374},[3275,3289,3305,3319,3335,3351,3361],{"slug":3276,"name":3276,"fn":3277,"description":3278,"org":3279,"tags":3280,"stars":25,"repoUrl":26,"updatedAt":3288},"generate-cve-json","generate CVE JSON documents","Generate a CVE 5.x JSON document from an \u003Ctracker> tracking\nissue, ready to paste into the Vulnogram `#source` tab of the ASF CVE tool\nat https:\u002F\u002Fcveprocess.apache.org\u002Fcve5\u002F\u003CCVE-ID>#source. The conversion is\ndeterministic: same issue in, same JSON bytes out. Handles multiple\ncredits (one per line) and multiple references (URLs extracted from the\nissue's \"Public advisory URL\" and \"PR with the fix\" fields; the\n\"Security mailing list thread\" field is treated as internal-only and\nnever exported).\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3281,3284,3285],{"name":3282,"slug":3283,"type":15},"Compliance","compliance",{"name":13,"slug":14,"type":15},{"name":3286,"slug":3287,"type":15},"Technical Writing","technical-writing","2026-07-12T08:35:41.218722",{"slug":3290,"name":3290,"fn":3291,"description":3292,"org":3293,"tags":3294,"stars":25,"repoUrl":26,"updatedAt":3304},"magpie-audit-finding-fix","fix findings from code audit tools","For a batch of findings from a non-security audit tool\n(`\u003Caudit-tool>` — ruff \u002F flake8 \u002F mypy \u002F pylint \u002F CodeQL \u002F\nApache Verum \u002F Apache Caer \u002F equivalent; full list in the body)\nagainst `\u003Cupstream>`, draft the smallest fix for each finding.\nRe-runs the tool after each batch to confirm the findings are\ncleared. Produces a commit and a hand-back artefact; never opens\na PR on autopilot or merges.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3295,3298,3301],{"name":3296,"slug":3297,"type":15},"Audit","audit",{"name":3299,"slug":3300,"type":15},"Code Analysis","code-analysis",{"name":3302,"slug":3303,"type":15},"Debugging","debugging","2026-07-12T08:35:13.930479",{"slug":3306,"name":3306,"fn":3307,"description":3308,"org":3309,"tags":3310,"stars":25,"repoUrl":26,"updatedAt":3318},"magpie-ci-runner-audit","audit GitHub Actions workflow runner compatibility","Read-only audit of GitHub Actions workflow runner compatibility\nfor one repository, an explicit repository set, one Apache project\nwith multiple repositories, or the full Apache GitHub org. Finds\nobsolete GitHub-hosted runner labels and macOS runner\u002Ftool\narchitecture mismatches. Produces TSV evidence files; never edits\nworkflows, opens PRs, or posts comments.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3311,3312,3315],{"name":3296,"slug":3297,"type":15},{"name":3313,"slug":3314,"type":15},"CI\u002FCD","ci-cd",{"name":3316,"slug":3317,"type":15},"GitHub Actions","github-actions","2026-07-12T08:34:30.320965",{"slug":3320,"name":3320,"fn":3321,"description":3322,"org":3323,"tags":3324,"stars":25,"repoUrl":26,"updatedAt":3334},"magpie-committer-onboarding","onboard Apache project committers","Post-vote committer and PMC onboarding for Apache projects.\nWalks the nominator through every step from ICLA check to\nwelcome announcement for both incubating podlings and\ngraduated top-level projects.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3325,3328,3331],{"name":3326,"slug":3327,"type":15},"Management","management",{"name":3329,"slug":3330,"type":15},"Operations","operations",{"name":3332,"slug":3333,"type":15},"Process Documentation","process-documentation","2026-07-12T08:33:35.628029",{"slug":3336,"name":3336,"fn":3337,"description":3338,"org":3339,"tags":3340,"stars":25,"repoUrl":26,"updatedAt":3350},"magpie-contributor-activity-sweep","generate contributor activity reports","Read-only GitHub activity card for a named contributor on \u003Cupstream>.\nFetches PR authorship, code-review activity, issues, and PR\u002Fissue\ncomments over a configurable window. Limited to GitHub-visible\nactivity — the body documents the off-GitHub tracks the nominator\nmust supply separately. No readiness verdict is produced; use\ncontributor-nomination for a full nomination brief.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3341,3344,3347],{"name":3342,"slug":3343,"type":15},"Analytics","analytics",{"name":3345,"slug":3346,"type":15},"GitHub","github",{"name":3348,"slug":3349,"type":15},"Reporting","reporting","2026-07-12T08:33:41.715859",{"slug":3352,"name":3352,"fn":3353,"description":3354,"org":3355,"tags":3356,"stars":25,"repoUrl":26,"updatedAt":3360},"magpie-contributor-nomination","generate contributor nomination briefs","Read-only nomination brief for a named GitHub contributor on\n\u003Cupstream>. Aggregates GitHub activity across all contribution\ntracks plus maintainer-supplied off-GitHub signal, and flags\nvendor-neutrality context — the evidence a PMC needs to open\na committer or PMC nomination thread.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3357,3358,3359],{"name":23,"slug":24,"type":15},{"name":3345,"slug":3346,"type":15},{"name":3348,"slug":3349,"type":15},"2026-07-12T08:33:39.211745",{"slug":3362,"name":3362,"fn":3363,"description":3364,"org":3365,"tags":3366,"stars":25,"repoUrl":26,"updatedAt":3373},"magpie-contributor-sentiment","measure contributor sentiment on GitHub repositories","Measures contributor-sentiment signals on \u003Cupstream> over a\nconfigurable window: thread tone (first-response classification),\ntime-to-first-reply (median hours), first-PR retention\n(second-PR rate), and reviewer load (Gini coefficient). Compares\neach signal against a pre-adoption baseline and produces a\nstructured gate report used to decide whether a skill family is\nready to advance from experimental to stable.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3367,3368,3371,3372],{"name":3342,"slug":3343,"type":15},{"name":3369,"slug":3370,"type":15},"Communications","communications",{"name":23,"slug":24,"type":15},{"name":3345,"slug":3346,"type":15},"2026-07-12T08:34:09.204167",71,{"items":3376,"total":3525},[3377,3395,3409,3420,3431,3444,3462,3473,3483,3494,3504,3514],{"slug":3378,"name":3378,"fn":3379,"description":3380,"org":3381,"tags":3382,"stars":3392,"repoUrl":3393,"updatedAt":3394},"datafusion-python","write Apache DataFusion Python code","Use when the user is writing datafusion-python (Apache DataFusion Python bindings) DataFrame or SQL code. Covers imports, data loading, DataFrame operations, expression building, SQL-to-DataFrame mappings, idiomatic patterns, and common pitfalls.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3383,3386,3389],{"name":3384,"slug":3385,"type":15},"Data Analysis","data-analysis",{"name":3387,"slug":3388,"type":15},"Python","python",{"name":3390,"slug":3391,"type":15},"SQL","sql",593,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fdatafusion-python","2026-07-12T08:36:04.957626",{"slug":3396,"name":3396,"fn":3397,"description":3398,"org":3399,"tags":3400,"stars":3406,"repoUrl":3407,"updatedAt":3408},"bydbql","generate and execute BanyanDB BydbQL queries","Generate, validate, and optionally execute read-only BanyanDB BydbQL for STREAM, MEASURE, TRACE, and PROPERTY resources. Use when the user asks to query BanyanDB, translate natural language to BydbQL, inspect BanyanDB schema or data, validate BydbQL, or fetch raw BanyanDB records.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3401,3402,3405],{"name":3342,"slug":3343,"type":15},{"name":3403,"slug":3404,"type":15},"Database","database",{"name":3390,"slug":3391,"type":15},344,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fskywalking-banyandb","2026-07-12T08:31:01.294423",{"slug":3410,"name":3410,"fn":3411,"description":3412,"org":3413,"tags":3414,"stars":3406,"repoUrl":3407,"updatedAt":3419},"compiling","compile and build BanyanDB projects","Compile and build the SkyWalking BanyanDB project. Use when the user asks to compile, build, or generate code for this project.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3415,3418],{"name":3416,"slug":3417,"type":15},"Build","build",{"name":23,"slug":24,"type":15},"2026-07-12T08:31:06.373309",{"slug":3421,"name":3421,"fn":3422,"description":3423,"org":3424,"tags":3425,"stars":3406,"repoUrl":3407,"updatedAt":3430},"gh-pull-request","create GitHub pull requests for BanyanDB","Create a GitHub pull request for SkyWalking BanyanDB. Use when the user asks to create a PR, submit changes, or open a pull request.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3426,3427],{"name":3345,"slug":3346,"type":15},{"name":3428,"slug":3429,"type":15},"Pull Requests","pull-requests","2026-07-12T08:31:03.792415",{"slug":3432,"name":3432,"fn":3433,"description":3434,"org":3435,"tags":3436,"stars":3406,"repoUrl":3407,"updatedAt":3443},"vendor-update","update Go and Node.js vendor dependencies","Upgrade Go\u002FNode.js vendor dependencies and sync tool versions. Use whenever the user says \"upgrade dependencies\", \"update vendors\", \"vendor update\", \"run vendor-upgrade\", \"bump dependencies\", \"update packages\", or asks to run the `vendor-update` Make target. This skill also checks `scripts\u002Fbuild\u002Fversion.mk` after upgrading to see if any tracked tool versions need updating too, and removes stale binaries from `bin\u002F` when versions change.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3437,3440],{"name":3438,"slug":3439,"type":15},"Go","go",{"name":3441,"slug":3442,"type":15},"Node.js","node-js","2026-07-12T08:31:02.555555",{"slug":3445,"name":3445,"fn":3446,"description":3447,"org":3448,"tags":3449,"stars":3459,"repoUrl":3460,"updatedAt":3461},"cayenne-cgen","generate Cayenne entity Java classes","Use this skill whenever the user wants to (re)generate Cayenne entity Java classes from a DataMap. Trigger on phrases like 'generate Java classes', 'regenerate entities', 'run cgen', 'create the entity classes', 'why is the Artist class missing fields', 'where did the `_Abstract*` classes come from', 'sync the entity classes with the model', or any request to materialize Java from the DataMap. Also trigger as a follow-up after modeling changes (someone added an entity, attribute, or relationship and now the Java side is stale). This skill exclusively uses the `mcp__cayenne__cgen_run` MCP tool — it does NOT use `mvn cayenne:cgen` or the Gradle cgen task.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3450,3453,3456],{"name":3451,"slug":3452,"type":15},"Data Modeling","data-modeling",{"name":3454,"slug":3455,"type":15},"Java","java",{"name":3457,"slug":3458,"type":15},"ORM","orm",343,"https:\u002F\u002Fgithub.com\u002Fapache\u002Fcayenne","2026-07-12T08:32:33.575211",{"slug":3463,"name":3463,"fn":3464,"description":3465,"org":3466,"tags":3467,"stars":3459,"repoUrl":3460,"updatedAt":3472},"cayenne-db-import","import database schema into Cayenne DataMaps","Use this skill when the user wants to import database schema metadata into a Cayenne DataMap — the *model\u002Fmapping only*, not names or Java classes. Trigger on phrases like 'reverse engineer the database', 'import the schema', 'generate a DataMap from my DB', 'add the new tables from the DB into the model', 'import the customer table', 'create entities from these tables', or any request to read database metadata to populate or update a DataMap's XML. This is for *full schema* or *bulk table* import; one-off a-la-carte entity additions belong in the cayenne-modeling skill. IMPORTANT — scope: this imports the mapping ONLY; it does not clean up the Object-layer names or (re)generate Java classes. When the user wants their whole project brought in line with the DB ('sync my project with the database', 'my schema changed, update everything', 'update my entities\u002Fclasses from the DB'), that is the end-to-end `cayenne-full-db-sync` skill, which runs this import and then name cleanup and class generation. To regenerate classes alone use `cayenne-cgen`. The skill runs reverse engineering directly via the `mcp__cayenne__dbimport_run` MCP tool when a DBConnector is already configured; otherwise it opens the CayenneModeler GUI via `mcp__cayenne__open_project` to configure the connection first.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3468,3469,3470,3471],{"name":3403,"slug":3404,"type":15},{"name":3454,"slug":3455,"type":15},{"name":3457,"slug":3458,"type":15},{"name":3390,"slug":3391,"type":15},"2026-07-19T05:40:33.655062",{"slug":3474,"name":3474,"fn":3475,"description":3476,"org":3477,"tags":3478,"stars":3459,"repoUrl":3460,"updatedAt":3482},"cayenne-full-db-sync","synchronize Cayenne projects with database","Use this skill when the user wants to bring their WHOLE Cayenne project in line with the database in one shot — the mapping, the Object-layer names, and the generated Java classes together. This is the end-to-end 'sync with the DB' workflow, and it orchestrates three skills in order: `cayenne-db-import` (import schema metadata into the DataMap) → `cayenne-model-naming` (polish the just-imported names) → `cayenne-cgen` (regenerate Java classes). Trigger on holistic phrases like 'sync my project with the database', 'sync with the DB', 'my schema changed, update everything', 'update my entities\u002Fclasses from the database', 'reverse engineer and regenerate the classes', 'import the new tables and rebuild the entities', 'full DB sync', 'bring the model and classes up to date with the DB'. The distinguishing signal is scope: the user wants the whole project (mapping + names + Java code), not just one stage. For the *model\u002Fmapping only* (no name cleanup, no class generation) use `cayenne-db-import`; to (re)generate classes alone use `cayenne-cgen`; to clean names alone use `cayenne-model-naming`. Uses the `mcp__cayenne__dbimport_run` and `mcp__cayenne__cgen_run` MCP tools via the sub-skills; does NOT use Maven or Gradle goals.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3479,3480,3481],{"name":3403,"slug":3404,"type":15},{"name":3454,"slug":3455,"type":15},{"name":3457,"slug":3458,"type":15},"2026-07-19T06:03:49.112969",{"slug":3484,"name":3484,"fn":3485,"description":3486,"org":3487,"tags":3488,"stars":3459,"repoUrl":3460,"updatedAt":3493},"cayenne-model-naming","clean up Cayenne object-layer names","Use this skill to clean up Object-layer names in a Cayenne DataMap — ObjEntity, ObjAttribute, and ObjRelationship names, plus DbRelationship names (the first-class unit of relationship cleanup — every FK has one whether or not an ObjRelationship was generated; the ObjRelationship name is synced to it when one exists) — so they read as descriptive, consistent Java. Trigger on phrases like 'clean up the model names', 'fix the entity names', 'these names look ugly', 'make the names descriptive', 'normalize the ObjEntity\u002Fattribute\u002Frelationship names', 'why is this relationship called team1', 'rename entities to be consistent', 'the import produced Gametype instead of GameType'. Invoke it on an explicit user request, or as a manual follow-up after a `cayenne-db-import` to polish the just-imported additions — it is never triggered automatically. IMPORTANT: this is a LIGHT polish pass — CayenneModeler's reverse-engineering already produces good names for the common case; only improve the specific things its deterministic algorithm cannot (run-together names with no separators like `gametype`, meaningless numbered names like `team1` from multiple relationships between two tables, and a common entity prefix that leaks into relationship names like `aaOrders`). Do NOT rewrite names that are already correct. This is Obj-layer naming polish; for structural model edits use `cayenne-modeling`, and for regenerating classes afterward use `cayenne-cgen`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3489,3490,3491,3492],{"name":3451,"slug":3452,"type":15},{"name":3403,"slug":3404,"type":15},{"name":3454,"slug":3455,"type":15},{"name":3457,"slug":3458,"type":15},"2026-07-22T05:35:32.342548",{"slug":3495,"name":3495,"fn":3496,"description":3497,"org":3498,"tags":3499,"stars":3459,"repoUrl":3460,"updatedAt":3503},"cayenne-modeler","manage Cayenne projects with CayenneModeler","Use this skill when the user explicitly wants to open CayenneModeler (the GUI) on a Cayenne project, or when the modeling task is inherently visual — reverse engineering (delegated to cayenne-db-import), bulk relationship layout, multi-entity visual refactoring. Trigger on phrases like 'open the Modeler', 'open in CayenneModeler', 'launch the GUI', 'edit visually', 'show me the project in the Modeler'. Do NOT trigger as a fallback for ordinary a-la-carte XML edits — those belong in the cayenne-modeling skill, which is faster and doesn't require the user to context-switch.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3500,3501,3502],{"name":3451,"slug":3452,"type":15},{"name":3454,"slug":3455,"type":15},{"name":3457,"slug":3458,"type":15},"2026-07-12T08:32:37.199428",{"slug":3505,"name":3505,"fn":3506,"description":3507,"org":3508,"tags":3509,"stars":3459,"repoUrl":3460,"updatedAt":3513},"cayenne-modeling","edit and extend Cayenne ORM models","Use this skill whenever the user wants to edit, inspect, or extend the Cayenne ORM model in a project — adding or modifying entities, attributes, relationships, embeddables, named queries, stored procedures, or DataNodes. Trigger on phrases like 'add an ObjEntity', 'add a DbEntity', 'add a relationship', 'expose this column as an attribute', 'create a new DataMap', 'add a named query', 'create an embeddable', 'add a stored procedure', 'change the attribute type', 'mark this column as nullable', 'rename this entity', or any mention of a Cayenne `*.map.xml` or `cayenne-*.xml` file. Also trigger when the user references modeling concepts (ObjEntity, DbEntity, ObjAttribute, DbAttribute, ObjRelationship, DbRelationship, Embeddable, dbEntityName, deleteRule, db-attribute-path, db-relationship-path, defaultPackage) in the context of a Cayenne-using app. This is the *primary* skill for a-la-carte ORM model manipulation — direct XML edits, not the Modeler GUI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3510,3511,3512],{"name":3403,"slug":3404,"type":15},{"name":3454,"slug":3455,"type":15},{"name":3457,"slug":3458,"type":15},"2026-07-19T05:40:32.6889",{"slug":3515,"name":3515,"fn":3516,"description":3517,"org":3518,"tags":3519,"stars":3459,"repoUrl":3460,"updatedAt":3524},"cayenne-query","write and modify Cayenne database queries","Use this skill whenever the user wants to write or modify a Cayenne query — fetching entities by criteria, joining, prefetching to avoid N+1, ordering, paginating, aggregating, or running raw SQL through Cayenne. Trigger on phrases like 'query for X', 'fetch all artists where ...', 'write an ObjectSelect', 'use SQLSelect', 'use SelectById', 'add a prefetch', 'get distinct values', 'count rows', 'find by ID', 'load by primary key', 'build a Cayenne expression', 'why am I getting N+1', 'how do I paginate', 'select a single column', 'select columns into a DTO', 'named query in the DataMap'. Do NOT trigger for modeling changes (use cayenne-modeling) or runtime bootstrap (use cayenne-runtime).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3520,3521,3522,3523],{"name":3403,"slug":3404,"type":15},{"name":3454,"slug":3455,"type":15},{"name":3457,"slug":3458,"type":15},{"name":3390,"slug":3391,"type":15},"2026-07-12T08:32:35.072322",108]