#!/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 "$@"