mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
fix(docker): set CLAUDE_CODE_TMPDIR + document hook reachability limit
Found in live testing: claude refuses its default /tmp/claude-<uid> temp dir when that path pre-exists root-owned (happens when the workspace bind-mount traverses it, e.g. a workspace under /tmp/claude-<uid>). Set CLAUDE_CODE_TMPDIR to a nonexistent HOME subpath the running uid creates+owns, so docker claude sessions are robust to any workspace location. Also document the hook-reachability constraint: in-container hooks POST to host.docker.internal (the bridge gateway), so they only fire when Codeman is reachable from the container (bind 0.0.0.0 + password); on a loopback-only bind they don't fire and idle detection falls back to output-based (which works). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -60,6 +60,15 @@ The container is paused across the capture so the image and workspace are consis
|
||||
|
||||
`GET /api/docker-exports` lists bundles; `GET /api/docker-exports/:filename` downloads one; `DELETE` removes one.
|
||||
|
||||
## Hooks require the server to be reachable from the container
|
||||
|
||||
In-container hooks (permission events, hook-based idle/stop/task notifications) POST to `CODEMAN_API_URL`, which is derived as `https://host.docker.internal:<port>` (`host.docker.internal` → the docker bridge gateway, e.g. `172.17.0.1`, via `--add-host …:host-gateway`). For that callback to succeed, the Codeman server must be **listening on an interface the container can reach**.
|
||||
|
||||
- If Codeman binds **loopback-only** (`127.0.0.1`, the default and the production systemd config), a container reaching `172.17.0.1:<port>` cannot connect, so **in-container hooks do not fire**. The session still works fully: idle/stop detection falls back to **output-based** detection through the `docker exec` PTY (which always works), and claude runs with `--dangerously-skip-permissions` so there are no permission prompts to forward anyway.
|
||||
- To enable in-container hooks, run Codeman where the container can reach it: bind `0.0.0.0` **with `CODEMAN_PASSWORD` set** (`CODEMAN_HOST=0.0.0.0`), or otherwise make `172.17.0.1:<port>` reachable. The host guard already allowlists `host.docker.internal` / `host.containers.internal`, and the hook secret is mounted, so hooks work as soon as the callback is reachable.
|
||||
|
||||
This is an environmental constraint, not a code limitation: the host-gateway mapping, `CODEMAN_API_URL` derivation, host-guard allowlist, and hook-secret mount are all wired correctly.
|
||||
|
||||
## Notes & limits
|
||||
|
||||
- Requires Docker (or Podman) with a reachable daemon; tmux must be present in the base image (a hard prerequisite, probed at link time).
|
||||
|
||||
@@ -997,6 +997,12 @@ export function resolveDockerLaunchOptions(
|
||||
HOME: CONTAINER_HOME,
|
||||
TERM: 'xterm-256color',
|
||||
COLORTERM: 'truecolor',
|
||||
// Give claude a temp dir it will own inside HOME. Its default `/tmp/claude-<uid>`
|
||||
// is refused when that path pre-exists root-owned — which happens when the
|
||||
// workspace bind-mount path traverses it (e.g. a workspace under /tmp/claude-<uid>).
|
||||
// A nonexistent HOME subpath is created+owned by the running uid, so this is robust
|
||||
// to any workspace location. Non-secret path, safe to be committed on export.
|
||||
CLAUDE_CODE_TMPDIR: `${CONTAINER_HOME}/.cache/codeman-claude-tmp`,
|
||||
};
|
||||
if (docker.hooksEnabled) {
|
||||
// Derive a container-reachable API url (scheme + port preserved; host swapped
|
||||
|
||||
Reference in New Issue
Block a user