From 7df4f06ae0e3ae80bd967bf53cbec36e58b4a3bd Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Wed, 18 Mar 2026 23:56:20 +0000 Subject: 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 --- internal/executor/container_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'internal/executor/container_test.go') diff --git a/internal/executor/container_test.go b/internal/executor/container_test.go index d4d591e..f97f2b5 100644 --- a/internal/executor/container_test.go +++ b/internal/executor/container_test.go @@ -23,14 +23,19 @@ func TestContainerRunner_BuildDockerArgs(t *testing.T) { workspace := "/tmp/ws" taskID := "task-123" - args := runner.buildDockerArgs(workspace, taskID) + agentHome := "/tmp/ws/.agent-home" + args := runner.buildDockerArgs(workspace, agentHome, taskID) expected := []string{ "run", "--rm", + "--add-host=host.docker.internal:host-gateway", + fmt.Sprintf("--user=%d:%d", os.Getuid(), os.Getgid()), "-v", "/tmp/ws:/workspace", + "-v", "/tmp/ws/.agent-home:/home/agent", "-w", "/workspace", "--env-file", "/tmp/ws/.claudomator-env", - "-e", "CLAUDOMATOR_API_URL=http://localhost:8484", + "-e", "HOME=/home/agent", + "-e", "CLAUDOMATOR_API_URL=http://host.docker.internal:8484", "-e", "CLAUDOMATOR_TASK_ID=task-123", "-e", "CLAUDOMATOR_DROP_DIR=/data/drops", "-v", "/tmp/ssh.sock:/tmp/ssh-auth.sock", -- cgit v1.2.3