Skip to content

feat(installer): set up a Claude Code cloud environment with --cloud - #72

Merged
ExtraToast merged 1 commit into
mainfrom
feat/cloud-environment
Sep 26, 2026
Merged

ExtraToast merged 1 commit into
mainfrom
feat/cloud-environment

Conversation

@ExtraToast

Copy link
Copy Markdown
Contributor

Why

A Claude Code cloud session starts from a fresh Ubuntu VM, so none of the laptop's agent setup reaches it: no Codex, no Hermes, no plugins, no language servers, no MCP fleet, no memory. This adds a cloud mode to setup-workstation.sh, plus the two files you paste into a cloud environment. cloud/setup-script.sh fetches the latest release's script from assets.jorisjonkers.dev and runs it with --cloud. cloud/environment.env lists the variables to fill in. Everything else stays in the registry, so the environment never needs editing again. The setup guide is docs/CLOUD.md.

What changes

  • --cloud: one profile. Claude Code is left to the host; a config-only CLI goes under /opt/agent-kit/claude-cli when none is on PATH. MCP tokens are registered as ${VAR} references, so the cached snapshot holds none. Codex is logged in from OPENAI_API_KEY, and Hermes gets an OpenRouter model when it has none.
  • cloud: false in the registry keeps an entry off the cloud. That covers Claude Code's own install, the kubernetes server (no kube context), the github plugin (the host's GitHub proxy covers it) and every LSP the estate does not use. Skipping them keeps setup inside the environment's ~5-minute cache budget.
  • install_linux: for brew-only language servers: Kotlin (pinned, sha256-checked) and jdtls.
  • Kit bundle re-exec. A copy run outside a checkout now fetches the release's bundle and re-runs the copy inside it. The bundle keeps its asset name, so fleet-infra's asset sync needs no change. It now also carries the registry, port-forward-agent.sh, cloud-session.sh and hermes-merge-mcp.py. Before this, a curl | bash run could not source port-forward-agent.sh or merge Hermes' MCP servers.
  • Fix: the primary profile wrote its MCP servers to a file claude never reads. Since feat(installer): second Claude Code profile and claude-<profile> launcher #58, every registration ran with CLAUDE_CONFIG_DIR=~/.claude. That moves .claude.json inside the directory, but a bare claude reads ~/.claude.json. The primary profile now runs without CLAUDE_CONFIG_DIR unless you set one yourself.
  • hermes-agent installs with --python '>=3.11,<3.14'. The cloud's GitHub proxy blocks uv's managed-Python download, and the VM's system Python 3.12 satisfies the range.
  • The unknown-server check no longer reads the Location: line of claude mcp list's diagnostics as a server name.

Verification done

  • render_registry.py --check, ruff and mypy are clean. pytest: 185 passed, 27 of them new. They cover tests/test_cloud_setup.py, the primary-profile and diagnostics cases in test_registry_render.py, and the bundle contents in test_publish_installer_artifacts.py.

  • shellcheck is clean on the new scripts, and -S warning is clean on the generated one.

  • End to end in ubuntu:24.04 as root: staged the bundle with publish-installer-artifacts.sh stage, served it locally, and ran cloud/setup-script.sh against it. It took 72 s with 0 failures. Read back:

    • /root/.claude.json holds the five servers with Bearer ${HINDSIGHT_API_TOKEN} and Bearer ${MEMORY_MCP_TOKEN}.
    • 11 plugins are enabled.
    • codex, hermes, olcli, drawio-mcp and the TypeScript, Pyright, Kotlin and jdtls servers are all in /usr/local/bin.
    • Hermes' config has the model and no kubernetes entry.

    The container was arm64, not the cloud's x86_64.

  • The profile bug shows on a real laptop: ~/.claude/.claude.json holds the servers setup registered on 2026-09-15, where a bare claude never looks.

After merge

  1. Merge the release PR. The asset host picks up the release within ~15 minutes. Check with curl -fsSL https://assets.jorisjonkers.dev/setup-workstation.sh | sed -n 2p. Until then, the published script rejects --cloud.
  2. Create the environment per docs/CLOUD.md: mint two claude-cloud tokens, add the custom network list, and paste the two files.
  3. Still unverified: whether the hosted Claude Code reads the VM's /root/.claude.json. claude mcp list in the first session answers it.
  4. On a laptop that ran setup since feat(installer): second Claude Code profile and claude-<profile> launcher #58, ~/.claude/.claude.json is stale once this lands and can be deleted.

Adds setup-workstation.sh --cloud and the two files pasted into a cloud
environment (cloud/setup-script.sh, cloud/environment.env). A copy run
outside a checkout now re-runs the one in the release's kit bundle, which
also carries the helpers it sources. Registry gains cloud: false and
install_linux. Fixes primary-profile MCP registrations landing in
~/.claude/.claude.json instead of ~/.claude.json.
@ExtraToast ExtraToast added type: feature New user-facing or operator-facing capability. area: tooling Reusable workflows, Gradle, templates, Renovate, and API tooling. component: config Configuration schema, defaults, or repo settings. priority: P2 Medium; normal planned work. labels Sep 26, 2026
@ExtraToast ExtraToast self-assigned this Sep 26, 2026
@ExtraToast
ExtraToast enabled auto-merge (squash) September 26, 2026 09:13
@ExtraToast
ExtraToast merged commit 7ce49b8 into main Sep 26, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: tooling Reusable workflows, Gradle, templates, Renovate, and API tooling. component: config Configuration schema, defaults, or repo settings. priority: P2 Medium; normal planned work. type: feature New user-facing or operator-facing capability.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant