Wire cloud session guards via environment setup script#4
Merged
Conversation
Cloud reads ~/.claude global memory (account-synced AGENTS.md/CLAUDE.md) and a setup-script-provisioned ~/.claude/skills/, but does not honor a setup-script ~/.claude/settings.json PreToolUse hook. Committed project .claude/ stays the universal same-session surface, so committed-vendor is accepted for the skill + Security hook and setup-script is a skills-only supplement. Refine the falsified M5.0 "never ~/.claude" premise and drop the brain/organs metaphor in the ADR; note the same correction in traveling-security.md and cloud-pull-trigger.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
Add docs/learnings/multi-repo-brain.md (fixes the dangling ADR-001 ref): consolidates which config surface each session reads and the 2026-07-06 cloud measurements -- memory + skills load from a setup-script ~/.claude/, the safety hooks do not (settings.json ignored; launcher-settings.json is the env surface). Records the recommended setup script and the two operator tests that close the milestone. Roadmap: add "cloud bootstrap parity" as an in-progress milestone with its success bar; queue a post-milestone revisit of the commit-skill wrapper (gates stay, wrapper is the open question); correct the stale "commits only after approval" line to the autonomous-commit reality.
A fresh Claude Code cloud session honors ~/.claude/launcher-settings.json
for hooks, not a setup-script ~/.claude/settings.json. merge-cloud-hooks.js
wires the Security PreToolUse deny-list into that surface so an environment
setup script can guard a fresh session the way bootstrap.sh guards a local
machine.
Reuses secure-repo.js's idempotent, non-clobbering merge -- refactored to
export mergePreToolUseHook(settingsPath, {matcher, command}) so the
committed-vendor route and the cloud route share one merge. Preserves infra
SessionStart/Stop hooks; command points at this clone's guard.
Tooling for the cloud-bootstrap hooks decider test. Adds
merge-cloud-hooks.test.js; secure-repo.test.js stays green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
Record the milestone-first, stack-then-run prompt pattern (from a Copilot CLI session) as a backlog note to evaluate later, plus a ROADMAP bullet. Frames the delta vs AGENTS.md workflow and the question of whether a minimal wording earns a place -- explicitly not a framework to build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
Cloud/headless runs should not trigger claude plugin install for external marketplaces -- those installs do not activate same-session there and are not agent-rules core. --no-plugins gates wire_claude_plugins so the cloud setup script (clone + bootstrap --no-plugins + merge-cloud-hooks) runs clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
The 2026-07-06 decider settled it: a setup script that merges the real security-pretooluse.js into ~/.claude/launcher-settings.json activates the guard in a fresh cloud session (rm -rf ~/testdir BLOCKED; both surfaces survived launch). The earlier "settings.json hook doesn't fire" was a malformed-probe confound, not an unread surface. ADR-002 records the per-environment guard route and amends ADR-001's alt (c) rejection; ADR-001 keeps its committed-vendor decision as the per-repo route. Corrects the learnings parity matrix, finalizes the production setup script, and advances ROADMAP #8 (cloud bootstrap parity essentially met). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
merge-cloud-hooks.js now DERIVES every PreToolUse hook from the canonical tools/claude/settings.json and remaps each command to the clone's path, so both guards -- security-pretooluse and guard-main -- ride ~/.claude/launcher-settings.json in a fresh cloud session (previously only security). Single source of truth: add a hook to settings.json once and it reaches local and cloud; a fitness test asserts the two hook sets stay equal. Generalizes secure-repo.js's merge to dedup by hook basename (was hardcoded to security-pretooluse); secure-repo.test.js unchanged and green. Extends merge-cloud-hooks.test.js with guard-main wiring, behavior, and the drift fitness check. Updates learnings + ROADMAP #8. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
A fresh cloud session on the production setup script confirmed full parity: AGENTS.md loaded (quoted its first Behavior bullet), agent-rules skills + the /status command listed, and rm -rf ~/testdir blocked by the guard. Marks ROADMAP #8 done and records the 2026-07-10 smoke in the learnings doc; the subagents leg is n/a (agents/ is empty). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
main (PR #1) generalized secure-repo.js to vendor both guards via a GUARDS array; this branch added the cloud route (merge-cloud-hooks.js). Reconciled by extracting one shared mergeGuards(settingsPath, commandFor) driven by GUARDS, used by BOTH routes: the committed-vendor route (repo .claude/ settings.json, $CLAUDE_PROJECT_DIR command) and the cloud route (~/.claude/launcher-settings.json, absolute clone-path command). GUARDS is now the single source of truth; the cloud test's fitness check cross-verifies it against tools/claude/settings.json. Also folds in main's new skills (teach, skill-scout, handoff) and pr-for-review update. All engine tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
Post-merge, merge-cloud-hooks.js reuses secure-repo.js's shared GUARDS + mergeGuards rather than parsing tools/claude/settings.json; the fitness test cross-checks GUARDS against settings.json. Fix the two docs that still said "derives from settings.json". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Enables the safety guards (
security-pretooluse.jsandguard-main.js) to activate in fresh cloud/phone Claude Code sessions via an environment setup script, complementing the committed-vendor route (ADR-001) with a per-environment alternative (ADR-002). A fresh cloud session now achieves full parity with local bootstrap — payload, skills, commands, and both PreToolUse guards all present and active same-session.Key Changes
hooks/merge-cloud-hooks.js(new) — derives all PreToolUse guards from the canonicaltools/claude/settings.json, remaps each hook's command to the clone's absolute path, and merges them idempotently into~/.claude/launcher-settings.json(the env's live hook surface). Fitness test asserts the wired hook set cannot drift from the source of truth.hooks/merge-cloud-hooks.test.js(new) — comprehensive zero-dep Node test suite validating:security-pretooluseblocksrm -rf ~/testdir;guard-mainblocks main-branch force-push but allows feature-branchhooks/secure-repo.js(refactored) — extractedmergePreToolUseHook(settingsPath, { matcher, command })as a generic hook-merge function (used by both committed-vendor and env-setup routes), keeping the committed-vendormergeSettings()as a thin wrapper. Dedup now works by hook basename, so any hook (security, guard-main, etc.) merges idempotently.bootstrap.sh— added--no-pluginsflag to skip external plugin provisioning (installs don't activate same-session in cloud and aren't agent-rules core). Enables the env setup script to runbootstrap.sh --no-pluginsfor payload without plugin overhead.ADR-002 (new) — documents the environment setup script route, corrects ADR-001's alternative-(c) rejection (a malformed-probe confound; the real guard fires same-session), and establishes the two routes as complementary: per-environment (ADR-002) vs. per-repo (ADR-001).
docs/learnings/multi-repo-brain.md(new) — consolidated finding on which config surfaces cloud sessions read: global memory (account-syncedAGENTS.md/CLAUDE.md) ✅, skills ✅, commands ✅, and a setup-script-merged PreToolUse guard ✅. Includes the production setup script and test evidence.docs/ROADMAP.md— marked milestone 8 (cloud bootstrap parity) complete; updated milestone 9 (commit skill) to reflect autonomous commits within a slice.docs/adr/cloud-brain-load.md(ADR-001) — updated status to accepted, refined context to reflect the empirical finding that cloud reads~/.claudeglobal memory (not operator's skills/hooks), and amended alternative-(c) to note the guard-via-setup-script correction.docs/plans/slice-stacking-workflow.md(new) — backlog note on a minimal prompt pattern for milestone-first slice-stacking (plan the stack, get approval, run to completion). Captured from a working session; flagged for later evaluation.docs/plans/cloud-pull-trigger.mdanddocs/plans/traveling-security.md— minor updates reflecting the 2026-07-06 empirical findings.Implementation Details
Single source of truth: The set of PreToolUse hooks is derived from
tools/claude/settings.json(the canonical local wiring). Add or remove a hook there once and it flows to both local (bootstrap) and cloud (merge-cloud-hooks) — the wiring cannot drift. A fitness test asserts the two hook sets stay equal.**Idempot
https://claude.ai/code/session_012NtohUoqyy2LWZYsYi2SWN