summaryrefslogtreecommitdiff
path: root/internal/cli/serve.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-18 23:56:20 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-18 23:56:20 +0000
commit7df4f06ae0e3ae80bd967bf53cbec36e58b4a3bd (patch)
tree740c141c52764604fc8d4c036733e5f47368b26a /internal/cli/serve.go
parenta4795d68fc5381f1ff48d043fe7554355e5899fb (diff)
feat: containerized execution with agent tooling and deployment fixes
- ContainerRunner replaces ClaudeRunner/GeminiRunner; all agent types run in Docker containers via claudomator-agent:latest - Writable agentHome staging dir (/home/agent) satisfies home-dir requirements for both claude and gemini CLIs without exposing host creds - Copy .credentials.json and .claude.json into staging dir at run time; GEMINI_API_KEY passed via env file - Fix git clone: remove MkdirTemp-created dir before cloning (git rejects pre-existing dirs even when empty) - Replace localhost with host.docker.internal in APIURL so container can reach host API; add --add-host=host.docker.internal:host-gateway - Run container as --user=$(uid):$(gid) so host-owned workspace files are readable; chmod workspace 0755 and instructions file 0644 after clone - Pre-create .gemini/ in staging dir to avoid atomic-rename ENOENT on first gemini-cli run - Add ct CLI tool to container image: pre-built Bash wrapper for Claudomator API (ct task submit/create/run/wait/status/list) - Document ct tool in CLAUDE.md agent instructions section - Add drain-failed-tasks script: retries failed tasks on a 5-minute interval - Update Dockerfile: Node 22 via NodeSource, Go 1.24, gemini-cli, git safe.directory=*, default ~/.claude.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/cli/serve.go')
-rw-r--r--internal/cli/serve.go50
1 files changed, 26 insertions, 24 deletions
diff --git a/internal/cli/serve.go b/internal/cli/serve.go
index 2ee020d..98e7524 100644
--- a/internal/cli/serve.go
+++ b/internal/cli/serve.go
@@ -75,36 +75,38 @@ func serve(addr string) error {
apiURL = "http://" + addr
}
+ // Resolve the claude config dir from HOME so the container can mount credentials.
+ claudeConfigDir := filepath.Join(os.Getenv("HOME"), ".claude")
+
runners := map[string]executor.Runner{
+ // ContainerRunner: binaries are resolved via PATH inside the container image,
+ // so ClaudeBinary/GeminiBinary are left empty (host paths would not exist inside).
"claude": &executor.ContainerRunner{
- Image: cfg.ClaudeImage,
- Logger: logger,
- LogDir: cfg.LogDir,
- APIURL: apiURL,
- DropsDir: cfg.DropsDir,
- SSHAuthSock: cfg.SSHAuthSock,
- ClaudeBinary: cfg.ClaudeBinaryPath,
- GeminiBinary: cfg.GeminiBinaryPath,
+ Image: cfg.ClaudeImage,
+ Logger: logger,
+ LogDir: cfg.LogDir,
+ APIURL: apiURL,
+ DropsDir: cfg.DropsDir,
+ SSHAuthSock: cfg.SSHAuthSock,
+ ClaudeConfigDir: claudeConfigDir,
},
"gemini": &executor.ContainerRunner{
- Image: cfg.GeminiImage,
- Logger: logger,
- LogDir: cfg.LogDir,
- APIURL: apiURL,
- DropsDir: cfg.DropsDir,
- SSHAuthSock: cfg.SSHAuthSock,
- ClaudeBinary: cfg.ClaudeBinaryPath,
- GeminiBinary: cfg.GeminiBinaryPath,
+ Image: cfg.GeminiImage,
+ Logger: logger,
+ LogDir: cfg.LogDir,
+ APIURL: apiURL,
+ DropsDir: cfg.DropsDir,
+ SSHAuthSock: cfg.SSHAuthSock,
+ ClaudeConfigDir: claudeConfigDir,
},
"container": &executor.ContainerRunner{
- Image: "claudomator-agent:latest",
- Logger: logger,
- LogDir: cfg.LogDir,
- APIURL: apiURL,
- DropsDir: cfg.DropsDir,
- SSHAuthSock: cfg.SSHAuthSock,
- ClaudeBinary: cfg.ClaudeBinaryPath,
- GeminiBinary: cfg.GeminiBinaryPath,
+ Image: "claudomator-agent:latest",
+ Logger: logger,
+ LogDir: cfg.LogDir,
+ APIURL: apiURL,
+ DropsDir: cfg.DropsDir,
+ SSHAuthSock: cfg.SSHAuthSock,
+ ClaudeConfigDir: claudeConfigDir,
},
}