From 9dd5285508f124b8122586638b5fbe5c9bc81a8f Mon Sep 17 00:00:00 2001 From: adamw Date: Thu, 17 Sep 2026 10:54:01 +0200 Subject: [PATCH] fix(cli): close stdin for rtk init so first-run prompts can't hang container start rtk 0.45 asks for telemetry consent on first init. The init scripts send rtk's output to /dev/null but left stdin on the container TTY, so the question was invisible and startup blocked forever. Applies to the claude, cursor and codex variants. --- cli/lib/agents.bash | 5 +++-- cli/lib/rtk.bash | 18 +++++++++++------- cli/test/agents/agents.bats | 2 +- cli/test/rtk/rtk.bats | 5 ++++- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/cli/lib/agents.bash b/cli/lib/agents.bash index ceba0496..342ce4f4 100644 --- a/cli/lib/agents.bash +++ b/cli/lib/agents.bash @@ -529,11 +529,12 @@ fi # Auto-init rtk for codex: writes ~/.codex/RTK.md and appends an # @RTK.md reference to ~/.codex/AGENTS.md. Idempotent — skipped once -# the reference is already present. +# the reference is already present. stdin is closed so rtk's first-run +# prompts (telemetry consent) can't block container start. if command -v rtk >/dev/null 2>&1 \ && [ "${SANDCAT_RTK:-true}" != "false" ] \ && ! grep -q '@RTK.md\|RTK\.md' "$HOME/.codex/AGENTS.md" 2>/dev/null; then - rtk init -g --codex >/dev/null 2>&1 \ + rtk init -g --codex /dev/null 2>&1 \ || echo "sandcat: rtk init failed (non-fatal)" >&2 fi EOF diff --git a/cli/lib/rtk.bash b/cli/lib/rtk.bash index 56918dc9..f4c8cbd3 100644 --- a/cli/lib/rtk.bash +++ b/cli/lib/rtk.bash @@ -40,11 +40,15 @@ EOF } # Emits the app-user-init.sh fragment that runs `rtk init` for the given -# agent, guarded to a one-time execution. Currently wires `claude` and -# `cursor`; unknown/future agents (including codex — rtk 0.44 does not -# support `--agent codex`, and `--codex` cannot combine with `--hook-only` -# or `--auto-patch`) get a safe no-op so the binary is still available on -# PATH but rtk stays uninitialized until the case is added. +# agent, guarded to a one-time execution. Every invocation gets stdin +# from /dev/null: rtk init asks interactive questions on first run +# (telemetry consent since 0.45) and would otherwise block forever on +# the container's TTY while its output is discarded. +# Currently wires `claude` and `cursor`; unknown/future agents +# (including codex — rtk 0.44 does not support `--agent codex`, and +# `--codex` cannot combine with `--hook-only` or `--auto-patch`) get a +# safe no-op so the binary is still available on PATH but rtk stays +# uninitialized until the case is added. # # Emits an empty output when the feature is disabled OR when the agent # has no rtk profile. @@ -64,7 +68,7 @@ sct_rtk_user_init_block() { # CLAUDE.md injection would EROFS). # Idempotency: skipped once the hook string is already present. if command -v rtk >/dev/null 2>&1 && ! grep -q '"command": "rtk hook' "$HOME/.claude/settings.json" 2>/dev/null; then - rtk init -g --hook-only --auto-patch >/dev/null 2>&1 \ + rtk init -g --hook-only --auto-patch /dev/null 2>&1 \ || echo "sandcat: rtk init failed (non-fatal)" >&2 fi EOF @@ -80,7 +84,7 @@ EOF # still try inside the container so the warning nudges the user to # initialize rtk on the host. if command -v rtk >/dev/null 2>&1 && ! grep -q '"rtk hook cursor' "$HOME/.cursor/hooks.json" 2>/dev/null; then - rtk init -g --hook-only --auto-patch --agent cursor >/dev/null 2>&1 \ + rtk init -g --hook-only --auto-patch --agent cursor /dev/null 2>&1 \ || echo "sandcat: rtk hook not found for cursor. Install rtk on your host and run once: rtk init -g --hook-only --auto-patch --agent cursor (see README RTK section)" >&2 fi EOF diff --git a/cli/test/agents/agents.bats b/cli/test/agents/agents.bats index 3b2c7b2c..b3f84c3b 100755 --- a/cli/test/agents/agents.bats +++ b/cli/test/agents/agents.bats @@ -471,7 +471,7 @@ setup() { unset SANDCAT_RTK run sct_agent_user_init_block codex assert_output --partial "codex --version" - assert_output --partial "rtk init -g --codex" + assert_output --partial "rtk init -g --codex