Skip to content

Commit 12265ed

Browse files
fix(installer): use dev tty redirect so pai handoff works in piped install
Prior gate was [ -t 0 ] && [ -t 1 ], which fails when stdin is a pipe even if stdout is the user terminal. Result: post-install fell through to the osascript fallback, which on remote macOS opens a Terminal window the user cannot see — leaving them thinking nothing happened. Fix: gate on [ -r /dev/tty ] and exec zsh -i -c with stdin redirected from /dev/tty. The redirect rebinds stdin to the real terminal, so pai inherits a usable TTY and the REPL can read keystrokes. Removed the osascript branch — it was the silent-failure hazard. Headless case now just prints the explicit command.
1 parent 698b15f commit 12265ed

1 file changed

Lines changed: 17 additions & 18 deletions

File tree

Releases/v5.0.0/.claude/install.sh

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -251,29 +251,28 @@ export PAI_BUNDLE_DIR="$SCRIPT_DIR"
251251
bun run "$INSTALLER_DIR/main.ts" --mode "$INSTALL_MODE"
252252
INSTALL_EXIT=$?
253253

254-
# Post-wizard handoff. Three paths, in priority order:
254+
# Post-wizard handoff. Two paths, in priority order:
255255
#
256-
# 1. Interactive TTY available (user ran `bash install.sh` directly, or CLI
257-
# mode in a terminal): exec into zsh -i -c 'source ~/.zshrc && pai' so the
258-
# user lands directly in pai in the same window. exec replaces this
259-
# process — there's no return.
256+
# 1. Controlling terminal accessible (any path where the user can see/type:
257+
# direct `bash install.sh`, SSH session running `curl … | sh`, local
258+
# `curl … | sh` in Terminal): redirect stdin from /dev/tty and exec into
259+
# `zsh -i -c 'source ~/.zshrc && pai'`. The /dev/tty redirect is what
260+
# makes this work under `curl | sh` — stdin to the install.sh process is
261+
# the curl pipe (not a TTY), but /dev/tty still resolves to the user's
262+
# actual controlling terminal, so the new zsh + pai inherit a real TTY
263+
# and Claude Code can read keystrokes. Without the redirect, pai would
264+
# launch with a closed-pipe stdin and immediately fail or hang.
260265
#
261-
# 2. macOS without a TTY (the `curl https://ourpai.ai/install.sh | sh` path
262-
# pipes stdin from curl, so [ -t 0 ] is false even though stdout is a
263-
# terminal): use osascript to open a fresh Terminal window running pai.
264-
# The user keeps their original terminal AND gets a new one with pai live.
265-
#
266-
# 3. Headless / no TTY / no osascript (Linux SSH, CI harness): print the
267-
# explicit command so the user can run it themselves.
266+
# 2. No controlling terminal (true headless: CI harness, daemon spawn): print
267+
# the explicit one-liner. We deliberately do NOT fall through to
268+
# `osascript … Terminal` here — on a remote/headless macOS box that
269+
# silently opens a window the user can't see, leaving them thinking
270+
# nothing happened (the bug Daniel hit on server.baylander.lan).
268271
if [ "$INSTALL_EXIT" -eq 0 ]; then
269272
echo ""
270-
if [ -t 0 ] && [ -t 1 ]; then
273+
if [ -r /dev/tty ]; then
271274
info "Launching pai..."
272-
exec zsh -i -c 'source ~/.zshrc && pai'
273-
elif [ "$(uname)" = "Darwin" ] && command -v osascript >/dev/null 2>&1; then
274-
info "Opening a new Terminal window for pai..."
275-
osascript -e 'tell application "Terminal" to do script "source ~/.zshrc && pai"' >/dev/null 2>&1 || \
276-
info "Could not auto-launch — run: ${BOLD}source ~/.zshrc && pai${RESET}"
275+
exec zsh -i -c 'source ~/.zshrc && pai' < /dev/tty
277276
else
278277
info "Install complete. To start pai, run: ${BOLD}source ~/.zshrc && pai${RESET}"
279278
fi

0 commit comments

Comments
 (0)