port: fix the container exiting instead of starting the agent
`loose` exited 126 with "File name too long": the entrypoint ended in `exec "$@"`, so the whole loop-task.md prompt was handed to exec as a command and the markdown was tried as a filename. The launcher was modelled on the RE container's but the entrypoint was written fresh and simpler, and it left out the half that matters -- the block that turns a `/loop ...` argument into a Claude Code invocation. Ported it over, with the two gates that make an unattended run possible: seeding ~/.claude.json so the first-run wizard does not stop on the theme picker, and claude-autonomous, which answers the Bypass Permissions disclaimer that has no config key to skip it. Also mounts the host's Claude credentials, which the container had no way to reach, and passes SYLPH_AUTONOMOUS=1 from `loose`. Verified: container stays up, display :97 ready, /reborn mounted read-only, Remote Control registered, Claude Code started in /work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1217
Cargo.lock
generated
Normal file
1217
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,4 +24,41 @@ if [ -d /reborn ]; then
|
|||||||
echo "[entrypoint] /reborn mounted read-only — HANDOFF.md is the contract"
|
echo "[entrypoint] /reborn mounted read-only — HANDOFF.md is the contract"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Seed ~/.claude.json from the host's read-only copy, then stamp onboarding as
|
||||||
|
# complete. Claude Code re-runs its first-run wizard whenever
|
||||||
|
# lastOnboardingVersion differs from the installed version, so a container with a
|
||||||
|
# newer Claude than the host stops on the theme picker -- no error, no log line,
|
||||||
|
# and an unattended agent sits there forever.
|
||||||
|
if [ -f "$HOME/.claude.host.json" ] && [ ! -s "$HOME/.claude.json" ]; then
|
||||||
|
cp "$HOME/.claude.host.json" "$HOME/.claude.json" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
CLAUDE_VER=$(claude --version 2>/dev/null | grep -oE '^[0-9][0-9.]*' || echo 0.0.0)
|
||||||
|
python3 /usr/local/bin/seed-claude-config.py "$HOME/.claude.json" "$CLAUDE_VER" \
|
||||||
|
"$PWD" "${PROJECT_DIR:-/work}" "$HOME" || true
|
||||||
|
chmod 600 "$HOME/.claude.json" 2>/dev/null || true
|
||||||
|
|
||||||
|
# ── Claude Code ──────────────────────────────────────────────────────────────
|
||||||
|
# Without this the loop prompt is handed to `exec` as a command, and the whole
|
||||||
|
# markdown file is tried as a filename: exit 126, "File name too long".
|
||||||
|
if [ "${SYLPH_AUTONOMOUS:-0}" = "1" ]; then
|
||||||
|
# Drop the image's default CMD first, or `claude` is handed the literal string
|
||||||
|
# "bash" as its prompt and answers a question nobody asked.
|
||||||
|
if [ "$#" -eq 1 ] && [ "$1" = "bash" ]; then
|
||||||
|
set --
|
||||||
|
fi
|
||||||
|
# Remote Control registers the session with the account so the agent can be
|
||||||
|
# reached from claude.ai -- the point of a detached run being that nobody is
|
||||||
|
# sitting in front of it. The name is passed EXPLICITLY: the flag's value is
|
||||||
|
# optional, so a bare --remote-control swallows the /loop prompt after it.
|
||||||
|
if [ "${SYLPH_REMOTE:-1}" != "0" ]; then
|
||||||
|
set -- --remote-control "${SYLPH_REMOTE_NAME:-sylpheed-port}" "$@"
|
||||||
|
echo "[entrypoint] Remote Control as '${SYLPH_REMOTE_NAME:-sylpheed-port}'"
|
||||||
|
fi
|
||||||
|
# claude-autonomous wraps `claude --dangerously-skip-permissions` in a pty and
|
||||||
|
# answers the one-time first-run gates. The Bypass Permissions disclaimer has
|
||||||
|
# no config key that skips it, so unattended it hangs forever.
|
||||||
|
set -- claude-autonomous "$@"
|
||||||
|
echo "[entrypoint] starting Claude Code in $(pwd)"
|
||||||
|
fi
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ docker_args() {
|
|||||||
--pids-limit 2048
|
--pids-limit 2048
|
||||||
-v "$REPO:/work"
|
-v "$REPO:/work"
|
||||||
-v "sylpheed-port-target:/sylph-home/port/target-container"
|
-v "sylpheed-port-target:/sylph-home/port/target-container"
|
||||||
-v "sylpheed-port-claude:/sylph-home/port/.claude"
|
-v "${SYLPH_CLAUDE_HOME:-$HOME/.claude}:/sylph-home/port/.claude"
|
||||||
|
-v "${SYLPH_CLAUDE_JSON:-$HOME/.claude.json}:/sylph-home/port/.claude.host.json:ro"
|
||||||
-e "PROJECT_DIR=/work"
|
-e "PROJECT_DIR=/work"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ case "${1:-}" in
|
|||||||
echo "==> loose | cpus=$CPUS mem=${MEM_GB}g pacing=${INTERVAL:-self}"
|
echo "==> loose | cpus=$CPUS mem=${MEM_GB}g pacing=${INTERVAL:-self}"
|
||||||
echo "==> repo: $REPO"
|
echo "==> repo: $REPO"
|
||||||
echo "==> reborn: ${REBORN:-<none>} (read-only)"
|
echo "==> reborn: ${REBORN:-<none>} (read-only)"
|
||||||
docker run -d -i -t "${ARGS[@]}" "$IMAGE" \
|
docker run -d -i -t "${ARGS[@]}" -e SYLPH_AUTONOMOUS=1 -w /work "$IMAGE" \
|
||||||
"/loop ${INTERVAL:+$INTERVAL }$TASK" >/dev/null
|
"/loop ${INTERVAL:+$INTERVAL }$TASK" >/dev/null
|
||||||
echo
|
echo
|
||||||
echo " running detached as '$NAME'."
|
echo " running detached as '$NAME'."
|
||||||
|
|||||||
Reference in New Issue
Block a user