# NanoClaw Codex Agent Container # Runs Codex CLI in isolated Linux VM FROM node:22-slim # Install system dependencies RUN apt-get update && apt-get install -y \ curl \ git \ && rm -rf /var/lib/apt/lists/* # Install Codex CLI globally RUN npm install -g @openai/codex # Create app directory WORKDIR /app # Copy package files first for better caching COPY codex-runner/package*.json ./ # Install dependencies RUN npm install # Copy source code COPY codex-runner/ ./ # Build TypeScript RUN npm run build # Create workspace directories RUN mkdir -p /workspace/group /workspace/global /workspace/extra /workspace/ipc/messages /workspace/ipc/tasks /workspace/ipc/input # Create entrypoint script — use pre-built dist/ from image, # but if /app/src is mounted with newer source, recompile on the fly. RUN printf '#!/bin/bash\nset -e\n\n# Use pre-built dist if available, recompile only if source was mounted\nif [ -f /app/dist/index.js ]; then\n RUNNER_DIR=/app/dist\nelse\n cd /app && npx tsc --outDir /tmp/dist 2>&1 >&2\n ln -s /app/node_modules /tmp/dist/node_modules\n RUNNER_DIR=/tmp/dist\nfi\n\n# Capture stdin to temp file\ncat > /tmp/input.json\n\n# Drop privileges if running as root\nif [ "$(id -u)" = "0" ] && [ -n "$RUN_UID" ]; then\n chown "$RUN_UID:$RUN_GID" /tmp/input.json\n exec setpriv --reuid="$RUN_UID" --regid="$RUN_GID" --clear-groups -- node "$RUNNER_DIR/index.js" < /tmp/input.json\nfi\n\nexec node "$RUNNER_DIR/index.js" < /tmp/input.json\n' > /app/entrypoint.sh && chmod +x /app/entrypoint.sh # Set ownership to node user RUN chown -R node:node /workspace && chmod 777 /home/node # Set working directory to group workspace WORKDIR /workspace/group ENTRYPOINT ["/app/entrypoint.sh"]