feat(cloud-environment): bake the repo's cloud-bootstrap at cache build - #391
Conversation
Run the checked-out repo's committed .claude/cloud-bootstrap.sh as the setup script's final step, best-effort, with CLAUDE_CODE_REMOTE=true and CLAUDE_PROJECT_DIR set to the checkout root. One canonical name, no fallback paths: every fleet repo commits its generic repository setup — dependencies and plugin installs — at exactly that path, and a repo without the file is a logged no-op. Running the bootstrap at cache build is load-bearing for plugins: the session's plugin registry is built at process start and never re-read, so plugin installs must already be in the snapshot a session boots from. Document the handoff in the component README and restate that a merged component change reaches an environment only on its next cache rebuild. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHbdXDm8B4yj81uQBy8M3M
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 24abdab84f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if [[ -f .claude/cloud-bootstrap.sh ]]; then | ||
| if CLAUDE_CODE_REMOTE=true CLAUDE_PROJECT_DIR="$PWD" \ | ||
| bash .claude/cloud-bootstrap.sh >>"$LOG" 2>&1; then |
There was a problem hiding this comment.
Avoid baking plugins for only the cache-building repository
In the shared repo-agnostic environment described in README.md lines 10–15, a snapshot built while repo A is checked out can later warm a session for repo B. This block runs only A's bootstrap, so B's plugins are absent when its session starts; running B's bootstrap later cannot repair that state because the plugin registry has already been constructed, as lines 115–117 note. The cache must preload the fleet-wide plugin union, be keyed per repository, or otherwise execute each repository's plugin setup before that repository's process starts.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The cross-repo observation is correct, but it's a design premise rather than a gap: the snapshot is a warm cache, never the correctness path. That division is now documented as the frozen calling contract in the component README (7471a3d) — repos must not assume the component installed anything.
For the specific plugin concern: a repo-B session booting from a snapshot built on repo A still gets B's plugins, because cloud sessions install the plugins declared in the checked-out repo's project settings during session provisioning, before the session process constructs its registry — for any marketplace source the platform can resolve. The fleet's consumer repos declare github-source marketplaces, which resolve fine. The documented failure mode that motivates doing installs at cache build at all was checkout-relative directory sources (claude-code-plugins' own dogfooding, see the Plugins section of its .claude/hooks/session-start.sh), not the github sources this component serves.
Preloading a fleet-wide union here would invert the design: this repo-agnostic component would need to enumerate every consumer's plugin declarations — repo-specific knowledge the contract forbids — and the union would drift chronically, since snapshots rebuild only on script-field edits or ~7-day expiry. 7471a3d instead makes the stage data-driven from whatever checkout builds the cache, deliberately scoped as warm-up for the common case (the environment's most-used repo is typically the one it was built from).
Generated by Claude Code
|
Claude finished @kyle-sexton's task in 3m 26s —— View job Code review complete ✅
No blocking findings. What I checked
Not independently verifiedSandbox tool permissions in this run didn't allow executing |
…ing contract Add a generic plugin-install stage after the repo bootstrap: read the checkout's .claude/settings.json, register each extraKnownMarketplaces entry not already registered, and install each enabledPlugins entry not already installed (--scope user). Every step is best-effort with a WARN log line, and the stage skips cleanly when the claude CLI or jq is missing or the file declares no plugin keys — a repo that declares nothing gets nothing. The timing is load-bearing: Claude Code builds its plugin registry at process start and never re-reads it, so only snapshot-baked installs are loaded at a session's first turn. The commit-drift refresh in claude-code-plugins' own hook is deliberately not replicated; consumer repos use github-source marketplaces. Document the frozen calling contract in the README: the exact entry-point path and env vars, best-effort/exit-0 semantics, the warm-cache vs correctness-guarantee division of responsibility, and the rule that future changes may add to the component but never rename the entry point, drop the env vars, or fail closed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHbdXDm8B4yj81uQBy8M3M
|
Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
add10e4
into
feat/cloud-environment-component
…#388) Admit the shared Claude Code cloud-environment baseline as a component: parallel install tracks for gh + PowerShell (apt), the fleet's exact .NET SDK pins into /opt/dotnet, and Node 24.18.0 via nvm; timestamped logging with a completion stamp written strictly last; always exits 0 inside the ~5-minute cache-build budget. The final step runs the checked-out repo's committed .claude/cloud-bootstrap.sh (CLAUDE_CODE_REMOTE=true, CLAUDE_PROJECT_DIR at the checkout root), then a data-driven plugin stage registers extraKnownMarketplaces entries and installs enabledPlugins entries from the checkout's .claude/settings.json — plugin installs must be snapshot-baked because Claude Code builds its plugin registry at process start and never re-reads it. The README documents the paste-once account bootstrap, the network prerequisite, the verification stamp, the update lifecycle, and the frozen calling contract (includes #391). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHbdXDm8B4yj81uQBy8M3M
Stacked on #388 (the component addition); targets
feat/cloud-environment-componentso that PR stays reviewable as the baseline.What
Two changes to the cloud-environment component:
1. Bake the repo's cloud-bootstrap at cache build (
24abdab).claude/cloud-bootstrap.sh— best-effort, withCLAUDE_CODE_REMOTE=trueandCLAUDE_PROJECT_DIRset to the checkout root. One name, no fallback paths: the fleet migration is wholesale, so a repo carrying only the old.claude/hooks/session-start.shis deliberately a logged no-op, not a compatibility branch.2. Data-driven plugin install + frozen calling contract (
7471a3d).claude/settings.json, registers eachextraKnownMarketplacesentry not already registered, installs eachenabledPlugins: trueentry not already installed (--scope user). Best-effort withWARNlog lines; skips cleanly whenclaude/jqis missing or no plugin keys are declared. A repo that declares nothing gets nothing. Timing rationale: Claude Code builds its plugin registry at process start and never re-reads it, so only snapshot-baked installs are loaded at a session's first turn.SCRIPT_VERSIONbumped to2026-08-15.3.Verification
shellcheckclean;components/cloud-environment/setup.test.shpasses (6/6);markdownlint-cli2clean..claude/cloud-bootstrap.shgets it baked with both env vars set; a legacy-hook-only fixture logs the diagnostic no-op line. Plugin stage verified against this repo's 65 declared plugins: fresh install path installs a missing plugin, second run is a fast all-skip no-op (~1s), and both skip paths (no settings file, no plugin keys) log cleanly. Every run exits 0 in ~25s, well inside the ~5-minute cache-build budget, and writes the stamp strictly last.Related
cloud-environmentcomponent this stacks on.claude/cloud-bootstrap.shdocs/CLOUD-FLEET-SETUP.md— fleet plan this component implementsNo linked issue.