Skip to content

Roll out global ~/.claude/CLAUDE.md safety rules to all machines #365

Open

Description

@ptr727

Summary

Get the agent write-safety kit installed and current on every machine that runs Claude Code with my gh credentials logged in.

One command per machine. It installs, and it prints one line to paste back here.

Do this on each machine

Clone fresh (or git pull an existing clone — the point is that it is current), then run one command.

Linux, macOS, WSL

git clone --depth 1 https://github.com/ptr727/ProjectTemplate.git /tmp/pt && cd /tmp/pt
./host-setup/agent-safety/install.sh

Windows (PowerShell)

git clone --depth 1 https://github.com/ptr727/ProjectTemplate.git $env:TEMP\pt; cd $env:TEMP\pt
.\host-setup\agent-safety\install.ps1

Both need Python 3 and nothing else. Both are idempotent, so re-running is always safe and is the fix for anything reported below.

Restart Claude Code sessions on that machine afterwards, so the hook and CLAUDE.md load.

What to paste back

The installer ends with one line. Paste it into the checklist below:

server-2 | Debian GNU/Linux 13 (trixie) | hub e2a99f1 | payload 2600d29d59ff247a | agent-safety v1, fleet-bootstrap v1 | 2026-08-11T02:12:07Z

Host name, host type, the hub commit it installed from, a digest of the bytes installed, the marker blocks actually found in CLAUDE.md, and when. That is the record — a tick is not.

Re-checking a machine later, without changing it

./host-setup/agent-safety/install.sh --report      # Linux / macOS / WSL
.\host-setup\agent-safety\install.ps1 --report     # Windows

Read-only. Run it from a fresh hub checkout and it compares that machine against that checkout:

Verdict Exit Meaning
CURRENT 0 Machine matches this checkout
STALE 1 Lists each reason; re-run the installer
NOT INSTALLED 2 No stamp on this machine

It creates nothing, so running it on a machine that has never been set up leaves it untouched.

Rollout

Every tick below was reset. They recorded that someone ran something once, the kit has changed several times since, and none of them carries a stamp — so none can be checked. Paste the stamp line as each machine is done.

  • Server-2 Proxmox (this host — the kit is installed but predates the stamp, so re-run it)
  • Windows workstation
  • WSL2 Debian
  • WSL2 Ubuntu
  • Macbook Air
  • Thinkpad Windows
  • Thinkpad Linux
  • Any CI / headless / cron environment that invokes Claude Code with the token

Why the ticks were not enough

The previous body said it outright: "a machine ticked below is not necessarily current." Three things were being conflated, and only the third matters:

  • Ran once — what a tick records.
  • Files present — what a grep for the markers records. A block edited between its own markers passes this.
  • Current and in force — what the stamp records.

--report checks the third. It compares the installed bytes rather than markers, so a hand-edited block is caught; it reads settings.json, so a kit whose hook is no longer registered is reported inactive rather than fine; and it reports a duplicated or half-written block, which a presence check reads as success.

What is checked

  • The deployed hook and both CLAUDE.md blocks, byte for byte against the checkout, line endings normalized so a CRLF machine is not falsely stale
  • The PreToolUse hook is registered in settings.json, exactly once
  • Every managed permission rule is present
  • Markers are neither duplicated nor half-written
  • The install was not made from a dirty checkout, which would mean the recorded commit does not identify the bytes

One thing the installer will not fix

On at least this host, the superseded safety section from #364 still sits above the canonical marker block, so the two overlap. The installer only rewrites what is between its own markers, so that older text survives every re-run and --report will call the machine CURRENT with it still there.

Removing it is a judgment call on a per-machine file rather than something to automate, so it is worth a look while visiting each box.

Relates to #364. The tooling matrix half is #483. Landed in #665.

Activity

  1. ptr727 commented on Jul 20, 2026

    @ptr727
    OwnerAuthor

    The rollout is now a portable kit, not a hand-placed file: host-setup/agent-safety/ shipped in #367 (on develop) with install.sh (Linux / WSL / macOS / Proxmox) and install.ps1 (Windows). One idempotent, self-testing installer deploys the PreToolUse hook, registers the settings.json entry, and appends the ## GitHub Write Safety (Any Project, Every Session) section to ~/.claude/CLAUDE.md in one step. Re-running updates in place.

    Deployed and verified on this WSL2 machine (the box running this session):

    • install.sh ran, hook self-test passed, settings.json PreToolUse/Bash entry registered (existing keys preserved), the three-rule section is in ~/.claude/CLAUDE.md (2 markers).
    • The hook is live in-session — a Bash command containing the incident pattern was blocked by the real PreToolUse gate, the incident payload denies through the installed entry point, and a read passes.

    Remaining boxes still run the kit themselves (the checklist stays yours to tick per box as each is done):

    • Windows workstation — you placed the CLAUDE.md rules on 2026-07-19; re-run install.ps1 to also install the technical hook (the new mechanical half).
    • Proxmox server (where the incident originated) — run install.sh.
    • Other workstations — run install.sh / install.ps1.
    • CI / headless — run install.sh.

    Verify per box: python3 ~/.claude/hooks/gh-write-guard.py --selftest and grep -c 'agent-safety v' ~/.claude/CLAUDE.md (expect 2). On Windows: py -3 "$env:USERPROFILE\.claude\hooks\gh-write-guard.py" --selftest.

    Relates to #364, #366.

  2. ptr727 commented on Jul 23, 2026

    @ptr727
    OwnerAuthor

    WSL2 Debian - verified current

    Re-ran host-setup/agent-safety/install.sh on WSL2 Debian (Debian on a Win11 workstation) against the current kit (hub 614a291, kit last changed 2026-07-21). Idempotent, no functional change - this box was already deployed, and the kit's later revisions are now confirmed in place.

    Verified:

    • Hook self-test: PASS (python3 ~/.claude/hooks/gh-write-guard.py --selftest).
    • ~/.claude/hooks/gh-write-guard.py is byte-identical to host-setup/agent-safety/gh-write-guard.py (current, not a stale copy).
    • ~/.claude/CLAUDE.md: 2 agent-safety v markers (the safety block is present and marker-delimited).
    • ~/.claude/settings.json: exactly one PreToolUse/Bash group carries the hook.
    • Live in-session: the hook actively blocked the incident patterns (suppressed-output writes, literal node-ids, cross-origin -R) throughout this session, so it is enforcing, not just installed. No restart needed on this box.

    Remaining boxes on the rollout checklist stay as before (Windows workstation install.ps1 for the hook, Proxmox install.sh, other workstations, CI/headless).

  3. ptr727 commented on Jul 23, 2026

    @ptr727
    OwnerAuthor

    Audit: Server-2 Proxmox — safeguard implemented and verified

    Machine: Server-2 Proxmox (Proxmox VE / Debian, PlexCleaner host — the machine where the incident originated)
    Date: 2026-07-23
    File: /home/pieter/.claude/CLAUDE.md

    What was done

    The file already existed with the incident-specific rules (repo-scope ban, no fabricated GitHub node IDs, no suppressed write output). Per this issue's instructions, the canonical ## Safety rules block from #364 (Repo scope / Writes are never probes / Outward-facing actions) was appended to it, with a note that where the two overlap the stricter reading applies.

    Verification

    $ grep -E 'Repo scope|Writes are never probes|Outward-facing actions' ~/.claude/CLAUDE.md
    **Repo scope.** Confine all git / GitHub / `gh` / API activity to this project's own
    **Writes are never probes.** Never fire a state-changing call (GraphQL mutation,
    **Outward-facing actions.** Confirm before anything externally visible or hard to

    All three rule headings present — verify check from the issue passes. Rollout checklist updated accordingly.


    Posted by Claude Code at the account owner's explicit request in-session.

  4. ptr727 commented on Jul 30, 2026

    @ptr727
    OwnerAuthor

    WSL2 Debian verified and refreshed today.

    This box is Debian GNU/Linux 13 (trixie) under WSL2, so it is the WSL2 Debian row, already checked for the CLAUDE.md rules.

    What was stale. The deployed ~/.claude/hooks/gh-write-guard.py was the 2026-07-25 copy, predating the AGENTS.md split, so its denial messages pointed at AGENTS.md "Repository Boundaries and Write Safety" for a section that now lives in GOVERNANCE.md. It denied correctly throughout, and it caught a real one this session (a git push ... 2>&1 | tail -2, which is output suppression on a mutation). Only the pointer it hands you was wrong.

    Re-ran host-setup/agent-safety/install.sh, and verified rather than assumed:

    hook self-test: PASS
    settings -> PreToolUse/Bash hook registered
    CLAUDE.md -> safety block updated
    
    $ python3 ~/.claude/hooks/gh-write-guard.py --selftest   # SELFTEST PASS
    $ grep -c "agent-safety v" ~/.claude/CLAUDE.md           # 2
    $ grep -c "AGENTS.md .Repository Boundaries" ~/.claude/hooks/gh-write-guard.py     # 0
    $ grep -c "GOVERNANCE.md .Repository Boundaries" ~/.claude/hooks/gh-write-guard.py # 2
    $ cmp ~/.claude/hooks/gh-write-guard.py host-setup/agent-safety/gh-write-guard.py  # identical

    settings.json still parses and still registers the hook.

    A note for the remaining hosts. A box that installed before the split carries the same stale citation, so re-running the installer is worth doing on each one as it is ticked rather than assuming the first install is current. The installer is idempotent and updates the CLAUDE.md block in place, so a re-run is cheap.

    Scope of this comment. Only WSL2 Debian is claimed. The other unchecked rows are untouched, and I have not inspected them.

  5. ptr727 commented on Jul 31, 2026

    @ptr727
    OwnerAuthor

    Server-2 Proxmox is now fully covered, and the checklist line is updated to say so.

    Development moved off the WSL2 Debian box onto this host on 2026-07-31. A verification pass found that only the documentary layer had ever been installed here: the ~/.claude/CLAUDE.md section from 2026-07-23 was the older #364 draft wording, there was no ~/.claude/hooks/ directory, and neither settings.json nor settings.local.json carried a hooks key. The gh-write-guard mechanical layer was therefore absent on the very machine where the incident originated.

    Re-running host-setup/agent-safety/install.sh fixed both halves:

    • ~/.claude/hooks/gh-write-guard.py installed, --selftest reports SELFTEST PASS (Rule 4 branch-rule-bypass cases included).
    • PreToolUse/Bash hook registered in ~/.claude/settings.json.
    • Canonical agent-safety v1 block appended to ~/.claude/CLAUDE.md, both markers present.

    One follow-up left for the account owner, not actioned here: the older #364 ## Safety rules section is still in that file above the new canonical block, so the two now overlap. Removing the superseded section is a judgment call on a per-machine file, so it is being surfaced rather than applied.

    Worth noting for the remaining boxes: the WSL2 Debian entry is ticked for the CLAUDE.md text, which does not imply the hook is installed there. The two layers roll out together only when install.sh is the thing that gets run.


    Posted by Claude Code at the account owner's explicit request.

  6. ptr727 commented on Aug 11, 2026

    @ptr727
    OwnerAuthor

    Body updated rather than re-filed, since the rollout it tracks is the same one. Three changes, all because the thing being rolled out grew after this was written.

    Scope. This tracked one block. install.py now manages two, agent-safety and fleet-bootstrap, plus the gh-write-guard hook. That matters for the checklist: every tick below predates the fleet-bootstrap block, so a machine marked done here can still be stale. Its content changed again today, so a machine carrying the older copy routes a stale repository to AUDIT.md, which measures, instead of RESYNC.md, which applies.

    The verify command was misleading and is replaced. It grepped the first draft's rule headings, which no longer appear verbatim and never covered the second block, so a current machine could fail it and a stale one could pass. It now uses the installer's own checks, counting two markers per block because a half-written block is exactly what a presence check misses:

    grep -c 'agent-safety v'    ~/.claude/CLAUDE.md   # expect 2
    grep -c 'fleet-bootstrap v' ~/.claude/CLAUDE.md   # expect 2
    python3 ~/.claude/hooks/gh-write-guard.py --selftest

    Server-2 refreshed today for the new routing, verified: both marker pairs present, settings.json still valid JSON, hook self-test passing.

    Two things this does not do. The checklist is untouched, 3 ticked and 5 unticked before and after, because which machines are done is yours to say and I can only reach this one. And it does not claim the ticked machines are current, only that they cannot be assumed to be.

    Worth recording how this surfaced. The issue had gone stale in the same way three documents did today, an enumeration that was accurate when written and silently outgrown by the thing it describes. #653, #660 and #662 were the others. Nothing reads an issue body for staleness, so this one only turned up because you asked which issue tracked it.

  7. ptr727 commented on Aug 21, 2026

    @ptr727
    OwnerAuthor

    Current audit against develop at 1832702: partial. The portable installer, stamp, read-only --report, and hook self-test exist. The issue's machine rollout is not verified complete, and the checklist carries no current stamp lines for the named hosts. Keep open until the host inventory itself provides current evidence or this rollout is moved to a machine-reporting system.

  8. added
    choreRegistry, labels, rollout, and other fleet housekeeping
    on Sep 5, 2026
  9. ptr727 commented on Oct 8, 2026

    @ptr727
    OwnerAuthor

    WSL2 Debian done, run at the maintainer's request from a fresh main checkout (4a0d9a0). The stamp line is shown with its host name field omitted:

    <host> | Debian GNU/Linux 13 (trixie) (WSL) | hub 4a0d9a0 | payload 281553bdf6d46fae | agent-safety v1, fleet-bootstrap v1 | 2026-10-08T21:28:29Z
    
    • --report before: STALE, for a stale payload, the containment prefix still set while its hook file was missing, no SessionEnd sweep registered, and a hand-edited CLAUDE.md.
    • --report after: CURRENT, exit 0, and all three hook self-tests pass.
    • The hand-written content above the markers was host notes rather than the superseded Add agent safety rules to shared AGENTS.md (repo-scope + no writes-as-probes) #364 section. It was moved into the host-local file first, so the render carries it under the host-local marker.

    The checklist tick is left for you.


    Posted by Claude Code at the account owner's explicit request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    choreRegistry, labels, rollout, and other fleet housekeeping

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions