- start.sh: auto-register project in ~/.config/context-studio/projects/ before launching Electron — without this acquireProjectLock() silently skips writing the lock file, waitForServers() never finds the registry port, all agent ports stay null (localhost:null errors) - start.sh: mount all known Claude Code credential locations into container (~/.claude/.credentials.json, ~/.claude.json, $CLAUDE_CONFIG_DIR variants) not just ~/.anthropic which was empty on this system - bin/claude: create /tmp/cs-ready-<agentId> on host after 3s delay so CS Core's CLI ready marker poll resolves instead of timing out after 10s - workflow.sh: add hasTrustDialogAccepted:true to all agent settings.json so claude goes straight to priming without the folder trust dialog - prereqs.sh: add ensure_api_key() — checks all credential locations, prompts with masked input if none found, offers to save to shell profile - wizard.sh: trap SIGINT for graceful abort — gum confirm popup, reverts created project dir and cloned core dir, leaves installed packages untouched - core.sh: set _WIZARD_CORE_CLONED=true before clone for cleanup tracking - electron-config.js: increase serverStartupTimeout 30s→90s (config file in core/config/, not source — safe to edit) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
170 lines
5.6 KiB
Bash
170 lines
5.6 KiB
Bash
#!/usr/bin/env bash
|
||
# prereqs.sh — detect distro, install missing prerequisites
|
||
|
||
detect_distro() {
|
||
if command -v pacman &>/dev/null; then echo "arch";
|
||
elif command -v apt-get &>/dev/null; then echo "debian";
|
||
elif command -v dnf &>/dev/null; then echo "rhel";
|
||
elif command -v yum &>/dev/null; then echo "rhel-yum";
|
||
elif command -v zypper &>/dev/null; then echo "suse";
|
||
else echo "unknown";
|
||
fi
|
||
}
|
||
|
||
install_pkg() {
|
||
local pkg="$1"
|
||
local distro
|
||
distro="$(detect_distro)"
|
||
case "$distro" in
|
||
arch) sudo pacman -Sy --noconfirm "$pkg" ;;
|
||
debian) sudo apt-get update -qq && sudo apt-get install -y "$pkg" ;;
|
||
rhel) sudo dnf install -y "$pkg" ;;
|
||
rhel-yum) sudo yum install -y "$pkg" ;;
|
||
suse) sudo zypper install -y "$pkg" ;;
|
||
*) die "Unsupported distro — please install $pkg manually." ;;
|
||
esac
|
||
}
|
||
|
||
ensure_git() {
|
||
if command -v git &>/dev/null; then
|
||
success "git $(git --version | awk '{print $3}')"
|
||
return
|
||
fi
|
||
warn "git not found."
|
||
ask_yn _install "Install git now?" "y"
|
||
if [[ "$_install" != "y" ]]; then die "git is required."; fi
|
||
gum spin --spinner dot --spinner.foreground "$C_MAUVE" \
|
||
--title " Installing git..." --title.foreground "$C_SKY" \
|
||
-- bash -c "$(declare -f install_pkg detect_distro); install_pkg git"
|
||
command -v git &>/dev/null || die "git installation failed."
|
||
success "git $(git --version | awk '{print $3}')"
|
||
}
|
||
|
||
ensure_container_runtime() {
|
||
if command -v podman &>/dev/null; then
|
||
CONTAINER_CMD="podman"
|
||
success "podman $(podman --version | awk '{print $3}')"
|
||
return
|
||
fi
|
||
if command -v docker &>/dev/null; then
|
||
CONTAINER_CMD="docker"
|
||
success "docker $(docker --version | awk '{print $3}' | tr -d ',')"
|
||
return
|
||
fi
|
||
|
||
warn "No container runtime found."
|
||
echo ""
|
||
gum style --foreground "$C_SKY" --margin "0 4" \
|
||
"podman — recommended (rootless, no daemon)" \
|
||
"docker — alternative"
|
||
echo ""
|
||
|
||
ask_choice _runtime "Which would you like to install?" \
|
||
"podman (recommended)" \
|
||
"docker"
|
||
|
||
local runtime_choice="$_runtime"
|
||
case "$runtime_choice" in
|
||
podman*) _install_podman; CONTAINER_CMD="podman" ;;
|
||
docker*) _install_docker; CONTAINER_CMD="docker" ;;
|
||
esac
|
||
|
||
command -v "$CONTAINER_CMD" &>/dev/null \
|
||
|| die "$CONTAINER_CMD installation failed. Please install manually."
|
||
success "$CONTAINER_CMD installed"
|
||
}
|
||
|
||
_install_podman() {
|
||
local distro
|
||
distro="$(detect_distro)"
|
||
gum spin --spinner dot --spinner.foreground "$C_MAUVE" \
|
||
--title " Installing podman..." --title.foreground "$C_SKY" \
|
||
-- bash -c "$(declare -f install_pkg detect_distro); install_pkg podman"
|
||
}
|
||
|
||
_install_docker() {
|
||
local distro
|
||
distro="$(detect_distro)"
|
||
case "$distro" in
|
||
arch) install_pkg docker ;;
|
||
debian) install_pkg docker.io ;;
|
||
rhel) install_pkg docker ;;
|
||
rhel-yum) install_pkg docker ;;
|
||
suse) install_pkg docker ;;
|
||
*) die "Unsupported distro — install docker manually." ;;
|
||
esac
|
||
sudo systemctl enable --now docker 2>/dev/null || true
|
||
sudo usermod -aG docker "$USER" 2>/dev/null || true
|
||
warn "Added $USER to docker group — log out and back in for it to take effect."
|
||
}
|
||
|
||
ensure_api_key() {
|
||
if [[ -n "${ANTHROPIC_API_KEY:-}" ]]; then
|
||
success "ANTHROPIC_API_KEY is set"
|
||
return
|
||
fi
|
||
|
||
# Resolve config dir — CLAUDE_CONFIG_DIR overrides default ~/.claude
|
||
local claude_dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
|
||
|
||
local creds_file=""
|
||
if [[ -f "$claude_dir/.credentials.json" ]]; then creds_file="$claude_dir/.credentials.json"
|
||
elif [[ -f "$HOME/.claude.json" ]]; then creds_file="$HOME/.claude.json"
|
||
elif [[ -f "$claude_dir/.claude.json" ]]; then creds_file="$claude_dir/.claude.json"
|
||
elif [[ -f "$HOME/.anthropic/.credentials.json" ]]; then creds_file="$HOME/.anthropic/.credentials.json"
|
||
fi
|
||
|
||
if [[ -n "$creds_file" ]]; then
|
||
success "Anthropic credentials found ($creds_file)"
|
||
return
|
||
fi
|
||
|
||
warn "ANTHROPIC_API_KEY is not set."
|
||
echo ""
|
||
gum style --foreground "$C_SKY" --margin "0 4" \
|
||
"Claude Code needs an Anthropic API key to run inside the container." \
|
||
"Get one at: https://console.anthropic.com/settings/api-keys"
|
||
echo ""
|
||
|
||
local key
|
||
key=$(gum input \
|
||
--password \
|
||
--placeholder "sk-ant-..." \
|
||
--prompt " › " \
|
||
--prompt.foreground "$C_MAUVE" \
|
||
--cursor.foreground "$C_MAUVE" \
|
||
--header " Anthropic API key" \
|
||
--header.foreground "$C_SKY" \
|
||
--width 70) || true
|
||
|
||
if [[ -z "$key" ]]; then
|
||
warn "No API key entered — set ANTHROPIC_API_KEY before running ./start.sh"
|
||
return
|
||
fi
|
||
|
||
export ANTHROPIC_API_KEY="$key"
|
||
success "ANTHROPIC_API_KEY set for this session"
|
||
|
||
ask_yn _save "Save to shell profile (~/.zshrc / ~/.bashrc)?" "y"
|
||
if [[ "$_save" == "y" ]]; then
|
||
local profile
|
||
if [[ "$SHELL" == */zsh ]]; then
|
||
profile="$HOME/.zshrc"
|
||
else
|
||
profile="$HOME/.bashrc"
|
||
fi
|
||
if grep -q "ANTHROPIC_API_KEY" "$profile" 2>/dev/null; then
|
||
warn "ANTHROPIC_API_KEY already in $profile — not adding again."
|
||
else
|
||
printf '\nexport ANTHROPIC_API_KEY="%s"\n' "$key" >> "$profile"
|
||
success "Saved to $profile"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
check_prerequisites() {
|
||
header "Prerequisites"
|
||
ensure_git
|
||
ensure_container_runtime
|
||
ensure_api_key
|
||
}
|