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>
107 lines
3.7 KiB
Bash
Executable File
107 lines
3.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Register a Claude subscription OAuth token with OneCLI — the *only* auth
|
|
# path that needs a TTY break in the flow. Paste-based paths (existing
|
|
# OAuth token / API key) are handled in-process by setup/auto.ts using
|
|
# clack prompts, then onecli secrets create is invoked directly from TS.
|
|
#
|
|
# Flow:
|
|
# 1. Run `claude setup-token` under a PTY (via script(1)) so the browser
|
|
# OAuth dance works and its token is captured into a tempfile.
|
|
# 2. Regex the sk-ant-oat…AA token out of the ANSI-stripped capture.
|
|
# 3. Register it with OneCLI.
|
|
#
|
|
# Env overrides:
|
|
# SECRET_NAME OneCLI secret name (default: Anthropic)
|
|
# HOST_PATTERN OneCLI host pattern (default: api.anthropic.com)
|
|
|
|
# Prefer bash 4+ (for `read -e -i` readline preload). macOS ships 3.2 in
|
|
# /bin/bash, but Homebrew users usually have 5.x first on PATH. The
|
|
# readline preload is optional — on 3.x we fall back to a plain prompt.
|
|
|
|
SECRET_NAME="${SECRET_NAME:-Anthropic}"
|
|
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; }
|
|
|
|
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; }
|
|
|
|
tmpfile=$(mktemp -t claude-setup-token.XXXXXX)
|
|
trap 'rm -f "$tmpfile"' EXIT
|
|
|
|
cat <<'EOF'
|
|
A browser window will open for you to sign in with your Claude account.
|
|
When you finish, we'll save the token to your OneCLI vault automatically.
|
|
|
|
Press Enter to continue, or edit the command first.
|
|
|
|
EOF
|
|
|
|
cmd="claude setup-token"
|
|
if [ "${BASH_VERSINFO[0]:-0}" -ge 4 ]; then
|
|
# bash 4+: pre-fill the readline buffer so Enter literally submits.
|
|
read -r -e -i "$cmd" -p "$ " cmd </dev/tty
|
|
else
|
|
# bash 3.x (macOS default /bin/bash): no readline preload. Fall back.
|
|
echo "$ $cmd"
|
|
read -r -p "Press Enter to run, Ctrl-C to abort. " _ </dev/tty
|
|
fi
|
|
|
|
# `script` arg order differs between BSD (macOS) and util-linux.
|
|
if script --version 2>/dev/null | grep -q util-linux; then
|
|
script -q -c "$cmd" "$tmpfile"
|
|
else
|
|
# BSD script: command is argv after the file, so let it word-split.
|
|
# shellcheck disable=SC2086
|
|
script -q "$tmpfile" $cmd
|
|
fi
|
|
|
|
# Strip ANSI codes + newlines (TTY wraps the token mid-string), then match
|
|
# the sk-ant-oat…AA token. perl because BSD grep caps {n,m} at 255.
|
|
token=$(sed $'s/\x1b\\[[0-9;]*[a-zA-Z]//g' "$tmpfile" \
|
|
| tr -d '\n\r' \
|
|
| perl -ne 'print "$1\n" while /(sk-ant-oat[A-Za-z0-9_-]{80,500}AA)/g' \
|
|
| tail -1 || true)
|
|
|
|
if [ -z "$token" ]; then
|
|
keep=$(mktemp -t claude-setup-token-log.XXXXXX)
|
|
cp "$tmpfile" "$keep"
|
|
echo >&2
|
|
echo "No sk-ant-oat…AA token found. Raw log: $keep" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo
|
|
echo "Got token: ${token:0:16}…${token: -4}"
|
|
echo "Saving it to your OneCLI vault as '${SECRET_NAME}' (host: ${HOST_PATTERN})…"
|
|
|
|
onecli secrets create \
|
|
--name "$SECRET_NAME" \
|
|
--type anthropic \
|
|
--value "$token" \
|
|
--host-pattern "$HOST_PATTERN"
|
|
|
|
echo "Done."
|