Skip to content

Docker cases fail to start unless the agent CLI is also installed on the host #332

Description

@thomas-negele

Summary

Starting a session for a Docker-linked case fails with Claude CLI not found when the corresponding agent CLI is not installed on the host. For a Docker case the CLI runs inside the container, so the host copy is never executed — the guard is a precondition for a value that the docker branch discards a few lines later.

shell mode works, every agent mode fails.

Environment

  • Codeman v1.21.0, installed with npm install -g aicodeman
  • Host: Debian 13 (trixie), Node 22.23.2, tmux 3.5a, Docker 29.6.2
  • Codeman runs as a systemd user service
  • Agent image built locally from docker/agent.Dockerfile — contains claude 2.1.240, codex 0.149.0, gemini 0.56.0, opencode 1.18.21, agy 1.1.18, pi 0.84.2
  • No agent CLIs installed on the host

Steps to reproduce

  1. Install Codeman on a host that has no agent CLI: npm install -g aicodeman
  2. Build the agent image from docker/agent.Dockerfile
  3. Create a Docker case (New case → Docker) pointing at an existing repo directory
  4. Start a Shell session → works, runs inside the container
  5. Start a Claude session → fails

Expected

The Claude session starts inside the container, exactly like the Shell session does. docker/agent.Dockerfile ships claude, so nothing is missing where the CLI actually runs.

Actual

[Session] Starting interactive Claude session (with tmux)
[Session] Failed to create mux session, falling back to direct PTY: Error: Claude CLI not found. Install it with: curl -fsSL https://claude.ai/install.sh | bash
Server PATH: /home/USER/.npm-global/bin:/usr/local/bin:/usr/bin:/bin
Login shell: /bin/bash -i -l
Checked directories: /home/USER/.local/bin, /home/USER/.claude/local, /usr/local/bin, /home/USER/.npm-global/bin, /home/USER/bin
    at TmuxManager.createSession (.../dist/tmux-manager.js:1625:19)
[Session] Interactive PTY spawned with PID: 3086948
[Session] Interactive PTY exited with code: 1

The pane in the web UI shows:

execvp(3) failed.: No such file or directory

docker exec <container> tmux -L codeman-docker ls shows only the Shell session — no container-side tmux session was ever created.

Root cause

Line references against 88bb98de (master).

TmuxManager.createSession resolves the host CLI and throws before the docker branch is reached — src/tmux-manager.ts#L1890-L1892:

const { pathExport, dir: cliDir } = this.buildPathExport(mode);
if (mode === 'claude' && !cliDir) {
  throw new Error(getClaudeNotFoundMessage());
}

Forty lines later the docker branch discards pathExport (and the whole localFullCmd it feeds) — src/tmux-manager.ts#L1934-L1938:

const fullCmd = docker
  ? buildDockerLaunchCommand(resolveDockerLaunchOptions(mode, docker, sessionId, resumeSessionId))
  : remote
    ? buildRemoteSessionCommand({ mode, remote, sessionId, claudeMode, allowedTools })
    : localFullCmd;

buildDockerLaunchCommand uses defaultDockerCommandForMode, which is a bare binary name resolved inside the container — src/docker-hosts.ts#L142:

claude: 'exec claude --dangerously-skip-permissions',

So the host path is never used on the docker path. The same guards exist for opencode, codex, gemini, antigravity and pi, so every mode except shell is affected.

This also contradicts the intent already stated for the remote/docker branches in src/web/routes/session-routes.ts#L2700-L2702:

the LOCAL availability gates below (isCodexAvailable() etc.) don't apply and would wrongly reject a machine that hasn't got the CLI installed locally.

That reasoning holds inside quick-start, but TmuxManager.createSession applies the gate regardless.

Note that _setupOrAttachMuxSession (src/tmux-manager.ts#L2161) calls the same buildPathExport without the throw, so only the create path is affected — which is why an already-created session can be re-attached but never started.

Suggested fix

Skip the not-found guards when the session is docker- or remote-backed. Either wrap the block:

if (!docker && !remote) {
  if (mode === 'claude' && !cliDir) throw new Error(getClaudeNotFoundMessage());
  // ... the other five
}

or move the guards below the fullCmd branch and apply them only on the local path.

Workaround

Install the agent CLIs on the host so the resolver finds them. They are never executed for docker cases:

npm install -g @anthropic-ai/claude-code @openai/codex

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions