feat(setup): ping agent before chat, detect stale service, auto-install Claude

Round-trip confirmation before first chat. After cli-agent wires up the
Terminal Agent, send `chat ping` through the CLI socket under a spinner
with 30s timeout (shared helper in setup/lib/agent-ping.ts, also used by
verify). Only after a real reply do we show "Your assistant is ready."
and enter the chat loop. Ping failures surface a targeted note
(socket_error vs no_reply) and skip the prompt — so users never type
into the void.

Checkout-mismatch detection. verify resolves the running service PID's
script path via `ps -p <pid> -o command=` and compares to projectRoot.
If the service is running from a sibling clone (common for developers
with multiple checkouts), SERVICE comes back as running_other_checkout
instead of running, AGENT_PING is skipped, and the failure note tells
the user exactly which bootout + bootstrap pair to run.

Native Claude Code install on demand. Only the subscription auth path
needs `claude`; the paste-token and paste-API-key paths don't. So
register-claude-token.sh now runs setup/install-claude.sh when `claude`
is missing (curl -fsSL https://claude.ai/install.sh | bash), then
prepends ~/.local/bin to PATH in-process so the rest of the script can
see the fresh binary.

Gutter-safe wrapping. wrapForGutter + dimWrap in lib/theme.ts hard-wrap
text to `process.stdout.columns - gutter` on word boundaries, measuring
visible length (ANSI-stripped). dimWrap applies the dim envelope per
line because clack resets styling at each line break when rendering
multi-line log content — a single outer dim() only colors the first
line. Applied to the long "why" notes before container + onecli, the
channel-skip info, the ping-failure note, and the checkout-mismatch
remediation.

Wordmark anchoring. printIntro always includes the NanoClaw wordmark in
the clack intro line, whether or not nanoclaw.sh already printed one in
bash. Worth ~1 line of redundancy so the brand stays visible at the top
of the clack session after bootstrap output scrolls out.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-04-22 11:06:15 +03:00
parent 9b6e5b24a1
commit 72b7a72cbb
6 changed files with 389 additions and 78 deletions

View File

@@ -25,8 +25,26 @@ HOST_PATTERN="${HOST_PATTERN:-api.anthropic.com}"
command -v onecli >/dev/null \
|| { echo "onecli not found. Install it first (see /setup §4)." >&2; exit 1; }
command -v claude >/dev/null \
|| { echo "claude CLI not found. Install from https://claude.ai/download" >&2; exit 1; }
if ! command -v claude >/dev/null 2>&1; then
echo "Claude Code CLI not found — installing it now (needed for subscription sign-in)…"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if ! bash "$SCRIPT_DIR/install-claude.sh"; then
echo >&2
echo "Couldn't install the Claude Code CLI automatically." >&2
echo "Install it manually with" >&2
echo " curl -fsSL https://claude.ai/install.sh | bash" >&2
echo "and re-run setup." >&2
exit 1
fi
# install-claude.sh PATH additions are scoped to its own subshell; redo
# them here so the rest of this script can see the fresh `claude` binary.
if [ -d "$HOME/.local/bin" ] && [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
export PATH="$HOME/.local/bin:$PATH"
fi
hash -r 2>/dev/null || true
fi
command -v script >/dev/null \
|| { echo "script(1) is required for PTY capture." >&2; exit 1; }