workstation: standardize on the native claude install (drop npm-global + npx)
All checks were successful
ci/woodpecker/push/default Pipeline was successful
All checks were successful
ci/woodpecker/push/default Pipeline was successful
Question from Viktor: should claude run via the binary or npx? Answer: the native install is the recommended runtime (self-contained, self-updating ~/.local/bin/claude; installMethod=native) — and every existing user had already auto-migrated to it, leaving the npm-global copy empty and the npx fallback dead. "Leave only the recommended setup": - setup-devvm.sh: node is now installed ONLY for the t3 CLI; dropped the machine-wide `npm install -g @anthropic-ai/claude-code` (npm/npx is not the recommended runtime and just shadowed the per-user native installs). - t3-provision-users.sh: new per-user `install_user_claude_native` (runs the official https://claude.ai/install.sh AS the user, idempotent/skip-if-present) — provisions native claude for BOTH the terminal launcher and each t3-serve instance, replacing the npm bootstrap. - skel/start-claude.sh: launcher runs the native `claude` only; if missing it bootstraps via the native installer (was an `npx @anthropic-ai/claude-code` fallback). - docs/architecture/multi-tenancy.md: documented the native-only runtime model. node stays (the pinned t3 CLI is npm-global). Verified: native installer reachable + produces ~/.local/bin/claude 2.1.177; all three scripts pass bash -n + shellcheck. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
4a48f065e9
commit
eecd78233b
4 changed files with 37 additions and 14 deletions
|
|
@ -288,6 +288,25 @@ deploy_user_launcher() {
|
|||
log "deployed start-claude.sh -> $user"
|
||||
}
|
||||
|
||||
# Ensure the per-user NATIVE claude install (the recommended runtime: ~user/.local/bin/claude,
|
||||
# self-updating) — used by BOTH the terminal launcher AND the user's t3-serve instance. We do
|
||||
# NOT npm-install claude system-wide (npm/npx isn't the recommended runtime); each user gets
|
||||
# their own native install. Idempotent: skip if already present. Runs the official native
|
||||
# installer AS the user (into their ~/.local). Best-effort: a failure WARNs and retries next
|
||||
# reconcile (start-claude.sh also self-bootstraps the terminal path).
|
||||
install_user_claude_native() {
|
||||
local user="$1" home
|
||||
home="$(getent passwd "$user" | cut -d: -f6)"
|
||||
[[ -n "$home" && -d "$home" ]] || return 0
|
||||
[[ -x "$home/.local/bin/claude" ]] && return 0 # already native -> done
|
||||
if [[ "$DRY_RUN" == 1 ]]; then echo "[dry-run] native claude install -> $user"; return 0; fi
|
||||
if runuser -u "$user" -- bash -lc 'curl -fsSL https://claude.ai/install.sh | bash' >/dev/null 2>&1; then
|
||||
log "installed native claude -> $user"
|
||||
else
|
||||
log "WARN: native claude install failed for $user (retries next reconcile)"
|
||||
fi
|
||||
}
|
||||
|
||||
[[ $EUID -eq 0 ]] || { echo "t3-provision-users: must run as root" >&2; exit 1; }
|
||||
for bin in python3 jq; do command -v "$bin" >/dev/null || { echo "missing $bin" >&2; exit 1; }; done
|
||||
[[ -f "$ROSTER" && -f "$ENGINE" ]] || { echo "roster/engine not under $WORKSTATION_DIR" >&2; exit 1; }
|
||||
|
|
@ -367,6 +386,7 @@ while IFS=$'\t' read -r os_user tier shell groups_csv code_layout repos_csv; do
|
|||
deploy_user_launcher "$os_user" # keep ~/start-claude.sh current (skel only seeds new accounts)
|
||||
fi
|
||||
refresh_codex_mirror "$os_user" # all tiers — mirror of the managed claudeMd
|
||||
install_user_claude_native "$os_user" # all tiers — per-user native claude (terminal + t3); no npm/npx
|
||||
done < <(jq -r '.accounts[] | [.os_user, .tier, .shell, (if (.groups|length)==0 then "-" else (.groups|join(",")) end), .code_layout, (if (.repos|length)==0 then "-" else (.repos|join(",")) end)] | @tsv' "$desired_file")
|
||||
|
||||
# 5) per-user .env (sticky port) + enable t3-serve@
|
||||
|
|
|
|||
|
|
@ -21,7 +21,13 @@ export DEBIAN_FRONTEND=noninteractive
|
|||
apt-get update -qq
|
||||
apt-get install -y "${PKGS[@]}" >/dev/null
|
||||
|
||||
# 2) node >= 18 + claude-code (claude-code requires node >= 18)
|
||||
# 2) node >= 18 — needed for the t3 CLI (npm-global, below). NOT for claude-code:
|
||||
# claude-code is the per-user NATIVE install (the recommended, self-updating
|
||||
# ~/.local/bin/claude), provisioned per user by t3-provision-users
|
||||
# (install_user_claude_native) and self-bootstrapped by start-claude.sh on first launch.
|
||||
# We deliberately do NOT `npm install -g @anthropic-ai/claude-code` — npm/npx is not the
|
||||
# recommended runtime, and a system-wide npm copy just shadows/duplicates the per-user
|
||||
# native installs everyone auto-migrates to anyway.
|
||||
need_node=1
|
||||
if command -v node >/dev/null; then
|
||||
[[ "$(node -v | sed 's/^v\([0-9]*\).*/\1/')" -ge 18 ]] && need_node=0
|
||||
|
|
@ -31,14 +37,6 @@ if [[ $need_node -eq 1 ]]; then
|
|||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash - >/dev/null
|
||||
apt-get install -y nodejs >/dev/null
|
||||
fi
|
||||
# Detect the GLOBAL npm package, NOT whatever `claude` resolves to on PATH: the admin's
|
||||
# personal ~/.local/bin/claude shadows it, so `command -v claude` silently skipped the
|
||||
# system-wide install — leaving /usr/lib/node_modules/@anthropic-ai empty and fresh
|
||||
# non-admins with no claude (they only worked because the admin's install was on PATH).
|
||||
if ! npm ls -g --depth=0 @anthropic-ai/claude-code >/dev/null 2>&1; then
|
||||
log "npm: installing @anthropic-ai/claude-code (system-wide)"
|
||||
npm install -g @anthropic-ai/claude-code >/dev/null
|
||||
fi
|
||||
|
||||
# 2b) t3 (the per-user coding surface) — PINNED, never nightly/latest. t3 is pre-1.0 and
|
||||
# ships breaking auth-schema + bootstrap-API changes our t3-dispatch can't follow blind
|
||||
|
|
|
|||
|
|
@ -42,13 +42,16 @@ else
|
|||
done
|
||||
fi
|
||||
|
||||
# Prefer the system-wide `claude` (installed by setup-devvm.sh); fall back to npx.
|
||||
# Run the NATIVE `claude` (the recommended install: ~/.local/bin/claude, self-updating).
|
||||
# No npm/npx. If the native binary is missing (a fresh account before the hourly reconcile
|
||||
# has provisioned it), bootstrap it with the official native installer, then run it.
|
||||
launch() {
|
||||
if command -v claude >/dev/null 2>&1; then
|
||||
claude "$@"
|
||||
else
|
||||
npx @anthropic-ai/claude-code "$@"
|
||||
if ! command -v claude >/dev/null 2>&1; then
|
||||
echo " Installing Claude Code (native) for $(id -un) …"
|
||||
curl -fsSL https://claude.ai/install.sh | bash || return 127
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
fi
|
||||
claude "$@"
|
||||
}
|
||||
|
||||
# Re-assert Claude Code's first-run onboarding flag before launch. ~/.claude.json is a
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue