Updates three things: 1. Context Studio Core — git pull on ~/.context-studio/core 2. Claude Code — npm install -g @anthropic-ai/claude-code in container 3. OS packages — apt-get update + upgrade in container If container is not running, in-container steps are skipped with a warning. Offers optional full image rebuild (--pull --no-cache) for a clean slate. Warns that in-container updates are ephemeral without a rebuild. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
172 lines
7.8 KiB
Bash
Executable file
172 lines
7.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
# ╔══════════════════════════════════════════════════════════════════╗
|
||
# ║ Context Studio Wizard — Project Setup ║
|
||
# ╚══════════════════════════════════════════════════════════════════╝
|
||
set -uo pipefail
|
||
|
||
WIZARD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
source "$WIZARD_DIR/lib/utils.sh"
|
||
source "$WIZARD_DIR/lib/prereqs.sh"
|
||
source "$WIZARD_DIR/lib/core.sh"
|
||
source "$WIZARD_DIR/lib/project.sh"
|
||
source "$WIZARD_DIR/lib/workflow.sh"
|
||
source "$WIZARD_DIR/lib/container.sh"
|
||
|
||
# ── Find existing projects base dir ───────────────────────────────────────
|
||
find_projects_dir() {
|
||
local candidates=("Projects" "projects" "Project" "project" "Dev" "dev" "Workspace" "workspace" "Code" "code" "src" "Src")
|
||
for candidate in "${candidates[@]}"; do
|
||
if [[ -d "$HOME/$candidate" ]]; then
|
||
echo "$HOME/$candidate"
|
||
return
|
||
fi
|
||
done
|
||
echo "$HOME/Projects"
|
||
}
|
||
|
||
# ── Project info ───────────────────────────────────────────────────────────
|
||
collect_project_info() {
|
||
header "Project Details"
|
||
|
||
ask PROJECT_NAME "Project name" ""
|
||
if [[ -z "$PROJECT_NAME" ]]; then die "Project name is required."; fi
|
||
|
||
local projects_base
|
||
projects_base="$(find_projects_dir)"
|
||
local default_dir="$projects_base/$(slugify "$PROJECT_NAME")"
|
||
ask PROJECT_DIR "Project location" "$default_dir"
|
||
if [[ -z "$PROJECT_DIR" ]]; then die "Project location is required."; fi
|
||
PROJECT_DIR="${PROJECT_DIR/#\~/$HOME}"
|
||
|
||
if [[ -e "$PROJECT_DIR" ]]; then
|
||
warn "Directory already exists: $PROJECT_DIR"
|
||
ask_yn _continue "Continue anyway?" "n"
|
||
if [[ "$_continue" != "y" ]]; then die "Aborted."; fi
|
||
fi
|
||
}
|
||
|
||
# ── Workflow source ────────────────────────────────────────────────────────
|
||
collect_workflow_info() {
|
||
header "Workflow Configuration"
|
||
|
||
ask_choice WORKFLOW_SOURCE "How do you want to configure your workflow?" \
|
||
"Generate from scratch" \
|
||
"Clone from existing repo"
|
||
|
||
if [[ "$WORKFLOW_SOURCE" == "Clone from existing repo" ]]; then
|
||
ask WORKFLOW_REPO "Workflow repo URL" ""
|
||
if [[ -z "$WORKFLOW_REPO" ]]; then die "Repo URL is required."; fi
|
||
else
|
||
ask PROJECT_DESC "Project description" "A software project"
|
||
ask TECH_STACK "Tech stack (e.g. Node.js, Rust, Python)" "Node.js"
|
||
ask_choice AGENT_PRESET "Agent preset" \
|
||
"minimal (5 agents: coordinator, 2 coders, researcher, tester)" \
|
||
"standard (9 agents: 2 coordinators, 3 coders, 2 researchers, tester, reviewer)"
|
||
case "$AGENT_PRESET" in
|
||
minimal*) AGENT_PRESET="minimal" ;;
|
||
*) AGENT_PRESET="standard" ;;
|
||
esac
|
||
fi
|
||
}
|
||
|
||
# ── Summary & confirm ──────────────────────────────────────────────────────
|
||
confirm_summary() {
|
||
header "Summary"
|
||
echo -e " ${BOLD}Project name${RESET} : $PROJECT_NAME"
|
||
echo -e " ${BOLD}Location${RESET} : $PROJECT_DIR"
|
||
echo -e " ${BOLD}Core${RESET} : $CS_CORE_DIR"
|
||
if [[ "${WORKFLOW_SOURCE:-}" == "Clone from existing repo" ]]; then
|
||
echo -e " ${BOLD}Workflow${RESET} : clone ${WORKFLOW_REPO:-}"
|
||
else
|
||
echo -e " ${BOLD}Workflow${RESET} : generate (${AGENT_PRESET:-minimal} preset)"
|
||
echo -e " ${BOLD}Description${RESET} : ${PROJECT_DESC:-}"
|
||
echo -e " ${BOLD}Tech stack${RESET} : ${TECH_STACK:-}"
|
||
fi
|
||
echo ""
|
||
ask_yn _ok "Create project?" "y"
|
||
if [[ "$_ok" != "y" ]]; then die "Aborted."; fi
|
||
}
|
||
|
||
# ── Build ──────────────────────────────────────────────────────────────────
|
||
build_project() {
|
||
header "Building Project"
|
||
|
||
local slug
|
||
slug="$(slugify "$PROJECT_NAME")"
|
||
|
||
create_project_structure "$PROJECT_DIR" "$PROJECT_NAME"
|
||
create_devcontainer "$PROJECT_DIR" "$PROJECT_NAME"
|
||
generate_container_scripts "$PROJECT_DIR" "$PROJECT_NAME" "$slug"
|
||
|
||
if [[ "${WORKFLOW_SOURCE:-}" == "Clone from existing repo" ]]; then
|
||
clone_workflow "$PROJECT_DIR" "${WORKFLOW_REPO:-}"
|
||
else
|
||
generate_workflow "$PROJECT_DIR" "$PROJECT_NAME" \
|
||
"${PROJECT_DESC:-A software project}" \
|
||
"${TECH_STACK:-Node.js}" \
|
||
"${AGENT_PRESET:-minimal}"
|
||
fi
|
||
|
||
git -C "$PROJECT_DIR" init -q
|
||
git -C "$PROJECT_DIR" add .
|
||
git -C "$PROJECT_DIR" commit -q -m "Initial project setup via Context Studio Wizard"
|
||
success "Git repo initialized"
|
||
}
|
||
|
||
# ── Done ───────────────────────────────────────────────────────────────────
|
||
print_next_steps() {
|
||
local slug
|
||
slug="$(slugify "$PROJECT_NAME")"
|
||
|
||
header "Done!"
|
||
success "Project created at: $PROJECT_DIR"
|
||
echo ""
|
||
echo -e "${BOLD}${GREEN} ➜ Enter your project now:${RESET}"
|
||
echo -e "${BOLD}${CYAN} cd \"$PROJECT_DIR\"${RESET}"
|
||
echo ""
|
||
echo -e "${BOLD}Start everything:${RESET}"
|
||
echo -e " ${CYAN}./start.sh${RESET}"
|
||
echo -e " Starts the agents container, then launches Context Studio Core on your host."
|
||
echo ""
|
||
echo -e " ${YELLOW}⚠ First run only:${RESET} the container image needs to be built."
|
||
echo -e " This downloads Node.js, Rust, Claude Code and all build tools."
|
||
echo -e " ${BOLD}Expect 5–15 minutes depending on your connection.${RESET}"
|
||
echo -e " Subsequent starts are instant — the image is cached."
|
||
echo ""
|
||
echo -e "${BOLD}Stop the container:${RESET}"
|
||
echo -e " ${CYAN}./stop.sh${RESET}"
|
||
echo ""
|
||
echo -e "${BOLD}Update everything:${RESET}"
|
||
echo -e " ${CYAN}./update.sh${RESET}"
|
||
echo -e " Updates Context Studio Core, Claude Code, and OS packages."
|
||
echo -e " Optionally rebuilds the image from scratch."
|
||
echo ""
|
||
echo -e "${BOLD}How it works:${RESET}"
|
||
echo -e " • Context Studio Core runs on your host (Electron UI, no display issues)"
|
||
echo -e " • Claude Code agents run inside container ${CYAN}cs-${slug}${RESET}"
|
||
echo -e " • ${CYAN}bin/claude${RESET} intercepts every agent call and routes it into the container"
|
||
echo -e " • Project files are mounted at the same path on host and in container"
|
||
echo ""
|
||
echo -e "${BOLD}VS Code (for editing):${RESET}"
|
||
echo -e " ${CYAN}code \"$PROJECT_DIR\"${RESET} → \"Reopen in Container\""
|
||
echo ""
|
||
}
|
||
|
||
# ── Main ───────────────────────────────────────────────────────────────────
|
||
main() {
|
||
echo ""
|
||
echo -e "${BOLD}${CYAN}╔══════════════════════════════════════╗${RESET}"
|
||
echo -e "${BOLD}${CYAN}║ Context Studio Wizard v1.0 ║${RESET}"
|
||
echo -e "${BOLD}${CYAN}╚══════════════════════════════════════╝${RESET}"
|
||
|
||
check_prerequisites
|
||
setup_core
|
||
collect_project_info
|
||
collect_workflow_info
|
||
confirm_summary
|
||
build_project
|
||
print_next_steps
|
||
}
|
||
|
||
main "$@"
|