From d2696ff5572c5ba89282fbf9991e6626271d5009 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 27 Oct 2026 14:31:26 +0000 Subject: [PATCH 1/7] feat: optional Claude Code self-hosted runner with a skill for sharing the workspace Add modules/claude-self-hosted-runner, vendored into all three templates. A switch (default off) starts `claude self-hosted-runner` in a restart loop in tmux session `claude-runner` on every workspace start, once the user has saved ~/.claude-runner/environment-secret; the secret never goes through Terraform. A second parameter sets the number of concurrent sessions (1-4). The runner rewrites ~/.gitconfig and ~/.config/git before every session, so the session git identity and ignore list go in /etc/gitconfig, reinstalled on each start, and the runner refuses to start alongside remote control. It also installs: - ~/.claude/skills/coder-shared-workspace, copied into every session, with rules for sessions sharing one Docker daemon and DDEV install: worktrees instead of shared checkouts, no workspace-wide Docker/DDEV commands, and a flock around test suites that power off DDEV. - claude-sessions, listing live sessions with checkout, branch and unpushed commits, and --push-outcome-on-release, so commits from repositories that forbid agents to push still reach the session's claude/ branch. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UrTUMvjLtFGNseL9fh5s4o --- CLAUDE.md | 2 +- Makefile | 11 ++- docs/user/using-workspaces.md | 22 +++++ .../claude-self-hosted-runner/files/SKILL.md | 87 +++++++++++++++++++ .../files/claude-runner-loop.sh.tftpl | 20 +++++ .../files/claude-sessions | 13 +++ .../claude-self-hosted-runner/files/gitconfig | 8 ++ .../claude-self-hosted-runner/files/gitignore | 4 + .../modules/claude-self-hosted-runner/main.tf | 44 ++++++++++ .../claude-self-hosted-runner/outputs.tf | 42 +++++++++ .../claude-self-hosted-runner/variables.tf | 17 ++++ .../claude-self-hosted-runner/versions.tf | 7 ++ drupal-contrib/template.tf | 7 ++ drupal-contrib/tests/validate.tftest.hcl | 56 ++++++++++++ .../claude-self-hosted-runner/files/SKILL.md | 87 +++++++++++++++++++ .../files/claude-runner-loop.sh.tftpl | 20 +++++ .../files/claude-sessions | 13 +++ .../claude-self-hosted-runner/files/gitconfig | 8 ++ .../claude-self-hosted-runner/files/gitignore | 4 + .../modules/claude-self-hosted-runner/main.tf | 44 ++++++++++ .../claude-self-hosted-runner/outputs.tf | 42 +++++++++ .../claude-self-hosted-runner/variables.tf | 17 ++++ .../claude-self-hosted-runner/versions.tf | 7 ++ drupal-core/template.tf | 7 ++ drupal-core/tests/validate.tftest.hcl | 65 ++++++++++++++ .../claude-self-hosted-runner/files/SKILL.md | 87 +++++++++++++++++++ .../files/claude-runner-loop.sh.tftpl | 20 +++++ .../files/claude-sessions | 13 +++ .../claude-self-hosted-runner/files/gitconfig | 8 ++ .../claude-self-hosted-runner/files/gitignore | 4 + .../modules/claude-self-hosted-runner/main.tf | 44 ++++++++++ .../claude-self-hosted-runner/outputs.tf | 42 +++++++++ .../claude-self-hosted-runner/variables.tf | 17 ++++ .../claude-self-hosted-runner/versions.tf | 7 ++ freeform/template.tf | 7 ++ freeform/tests/validate.tftest.hcl | 56 ++++++++++++ .../claude-self-hosted-runner/files/SKILL.md | 87 +++++++++++++++++++ .../files/claude-runner-loop.sh.tftpl | 20 +++++ .../files/claude-sessions | 13 +++ .../claude-self-hosted-runner/files/gitconfig | 8 ++ .../claude-self-hosted-runner/files/gitignore | 4 + modules/claude-self-hosted-runner/main.tf | 44 ++++++++++ modules/claude-self-hosted-runner/outputs.tf | 42 +++++++++ .../claude-self-hosted-runner/variables.tf | 17 ++++ modules/claude-self-hosted-runner/versions.tf | 7 ++ .../add-claude-self-hosted-runner/proposal.md | 18 ++++ .../specs/claude-self-hosted-runner/spec.md | 22 +++++ .../add-claude-self-hosted-runner/tasks.md | 10 +++ 48 files changed, 1249 insertions(+), 2 deletions(-) create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/files/SKILL.md create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/files/claude-runner-loop.sh.tftpl create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/files/claude-sessions create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/files/gitconfig create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/files/gitignore create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/main.tf create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/outputs.tf create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/variables.tf create mode 100644 drupal-contrib/modules/claude-self-hosted-runner/versions.tf create mode 100644 drupal-core/modules/claude-self-hosted-runner/files/SKILL.md create mode 100644 drupal-core/modules/claude-self-hosted-runner/files/claude-runner-loop.sh.tftpl create mode 100644 drupal-core/modules/claude-self-hosted-runner/files/claude-sessions create mode 100644 drupal-core/modules/claude-self-hosted-runner/files/gitconfig create mode 100644 drupal-core/modules/claude-self-hosted-runner/files/gitignore create mode 100644 drupal-core/modules/claude-self-hosted-runner/main.tf create mode 100644 drupal-core/modules/claude-self-hosted-runner/outputs.tf create mode 100644 drupal-core/modules/claude-self-hosted-runner/variables.tf create mode 100644 drupal-core/modules/claude-self-hosted-runner/versions.tf create mode 100644 freeform/modules/claude-self-hosted-runner/files/SKILL.md create mode 100644 freeform/modules/claude-self-hosted-runner/files/claude-runner-loop.sh.tftpl create mode 100644 freeform/modules/claude-self-hosted-runner/files/claude-sessions create mode 100644 freeform/modules/claude-self-hosted-runner/files/gitconfig create mode 100644 freeform/modules/claude-self-hosted-runner/files/gitignore create mode 100644 freeform/modules/claude-self-hosted-runner/main.tf create mode 100644 freeform/modules/claude-self-hosted-runner/outputs.tf create mode 100644 freeform/modules/claude-self-hosted-runner/variables.tf create mode 100644 freeform/modules/claude-self-hosted-runner/versions.tf create mode 100644 modules/claude-self-hosted-runner/files/SKILL.md create mode 100644 modules/claude-self-hosted-runner/files/claude-runner-loop.sh.tftpl create mode 100644 modules/claude-self-hosted-runner/files/claude-sessions create mode 100644 modules/claude-self-hosted-runner/files/gitconfig create mode 100644 modules/claude-self-hosted-runner/files/gitignore create mode 100644 modules/claude-self-hosted-runner/main.tf create mode 100644 modules/claude-self-hosted-runner/outputs.tf create mode 100644 modules/claude-self-hosted-runner/variables.tf create mode 100644 modules/claude-self-hosted-runner/versions.tf create mode 100644 openspec/changes/add-claude-self-hosted-runner/proposal.md create mode 100644 openspec/changes/add-claude-self-hosted-runner/specs/claude-self-hosted-runner/spec.md create mode 100644 openspec/changes/add-claude-self-hosted-runner/tasks.md diff --git a/CLAUDE.md b/CLAUDE.md index 4c3cff1..7aa34fb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -79,7 +79,7 @@ make test-templates ## Shared Terraform Assets -Some Terraform config (currently `modules/claude-remote-control`, `modules/docker-daemon`, `shared/vscode-extensions.tf`, `shared/bashrc-symlink-guard.sh` and `shared/ssh-agent-setup.sh`) is shared across all three templates but must exist as a **physical copy inside each template directory** — `coder templates push` and CI's `terraform validate`/`test` only ever operate on a single template directory, so a relative `../modules` or `../shared` reference would not survive the push and would not be visible to CI. +Some Terraform config (currently `modules/claude-remote-control`, `modules/claude-self-hosted-runner`, `modules/docker-daemon`, `shared/vscode-extensions.tf`, `shared/bashrc-symlink-guard.sh` and `shared/ssh-agent-setup.sh`) is shared across all three templates but must exist as a **physical copy inside each template directory** — `coder templates push` and CI's `terraform validate`/`test` only ever operate on a single template directory, so a relative `../modules` or `../shared` reference would not survive the push and would not be visible to CI. - **Edit only the canonical source**: `modules/claude-remote-control/` or `shared/vscode-extensions.tf` at the repo root. Never hand-edit the vendored copies (`