Add Context Studio Wizard — project scaffolding CLI
- wizard.sh: interactive bash wizard that scaffolds new CS projects - lib/: utils, core install, project structure, workflow generation - templates/: Dockerfile, devcontainer.json, agent presets (minimal/standard), system.json, roles, hook rules - README: setup, usage, mobility workflow Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cd5b28919c
commit
09ff27be92
19 changed files with 1132 additions and 1 deletions
114
README.md
114
README.md
|
|
@ -1,2 +1,114 @@
|
||||||
# ContextStudioWizard
|
# Context Studio Wizard
|
||||||
|
|
||||||
|
> Scaffold a fully configured multi-agent AI development environment in seconds.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
One command. One conversation. A complete project drops out:
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.context-studio/core/ ← installed once, shared globally
|
||||||
|
|
||||||
|
~/projects/my-project/
|
||||||
|
├── .devcontainer/ ← Node 22 · Rust · Claude Code · Electron deps
|
||||||
|
├── workflow/ ← agents, roles, A2A config, project docs
|
||||||
|
└── src/ ← your code
|
||||||
|
```
|
||||||
|
|
||||||
|
Open in devcontainer → start Context Studio → talk to your agent team.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `git` | Clone repos |
|
||||||
|
| `docker` or `podman` | Run devcontainer |
|
||||||
|
| SSH key → `github.com` | Access context-studio-core |
|
||||||
|
| `ANTHROPIC_API_KEY` | Claude agents |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./wizard.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The wizard guides you through:
|
||||||
|
|
||||||
|
1. **Core setup** — clones `context-studio-core` to `~/.context-studio/core/` (once)
|
||||||
|
2. **Project name & location**
|
||||||
|
3. **Workflow** — generate from scratch _or_ clone an existing repo
|
||||||
|
4. **Agent preset** _(if generating)_
|
||||||
|
|
||||||
|
| Preset | Agents |
|
||||||
|
|--------|--------|
|
||||||
|
| `minimal` | coordinator · 2× coder · researcher · tester |
|
||||||
|
| `standard` | 2× coordinator · 3× coder · 2× researcher · tester · reviewer |
|
||||||
|
|
||||||
|
5. **Done** — git repo initialized, devcontainer ready
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Open the project
|
||||||
|
|
||||||
|
**VS Code**
|
||||||
|
```bash
|
||||||
|
code ~/projects/my-project # → "Reopen in Container"
|
||||||
|
```
|
||||||
|
|
||||||
|
**CLI**
|
||||||
|
```bash
|
||||||
|
cd ~/projects/my-project
|
||||||
|
docker build -t my-project .devcontainer/
|
||||||
|
docker run -it --rm \
|
||||||
|
-v "$(pwd)":/workspace \
|
||||||
|
-v "$HOME/.context-studio/core":/opt/context-studio/core \
|
||||||
|
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
|
||||||
|
my-project bash
|
||||||
|
```
|
||||||
|
|
||||||
|
**Start Context Studio** _(inside container)_
|
||||||
|
```bash
|
||||||
|
node $CS_CORE_DIR/core/start.js # Electron UI
|
||||||
|
node $CS_CORE_DIR/core/start.js --ui-mode=headless # servers only
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mobility
|
||||||
|
|
||||||
|
Commit your project. On any machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <your-project-repo>
|
||||||
|
cd my-project
|
||||||
|
code . # done
|
||||||
|
```
|
||||||
|
|
||||||
|
Core is re-cloned automatically on first run. Only `ANTHROPIC_API_KEY` is needed on the host.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Repository layout
|
||||||
|
|
||||||
|
```
|
||||||
|
wizard.sh ← entry point
|
||||||
|
lib/
|
||||||
|
utils.sh ← prompts, colors, helpers
|
||||||
|
core.sh ← global core install/update
|
||||||
|
project.sh ← devcontainer + project scaffold
|
||||||
|
workflow.sh ← generate or clone workflow config
|
||||||
|
templates/
|
||||||
|
Dockerfile ← Node 22 + Rust + build tools + Claude Code
|
||||||
|
devcontainer.json ← mounts, env vars, VS Code extensions
|
||||||
|
agents-minimal.json ← 5-agent preset
|
||||||
|
agents-standard.json ← 9-agent preset
|
||||||
|
system.json ← A2A server defaults
|
||||||
|
roles/ ← coordinator, coder, researcher, tester, reviewer
|
||||||
|
hooks/rules/ ← per-role tool restrictions
|
||||||
|
```
|
||||||
|
|
|
||||||
28
lib/core.sh
Normal file
28
lib/core.sh
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# core.sh — manage the global context-studio-core installation
|
||||||
|
|
||||||
|
CS_CORE_REPO="git@github.com:KlausUllrich/context-studio-core.git"
|
||||||
|
CS_HOME="${CS_HOME:-$HOME/.context-studio}"
|
||||||
|
CS_CORE_DIR="$CS_HOME/core"
|
||||||
|
|
||||||
|
setup_core() {
|
||||||
|
header "Context Studio Core"
|
||||||
|
|
||||||
|
if [[ -d "$CS_CORE_DIR/.git" ]]; then
|
||||||
|
success "Core already installed at $CS_CORE_DIR"
|
||||||
|
ask_yn _update "Update core to latest?" "n"
|
||||||
|
if [[ "$_update" == "y" ]]; then
|
||||||
|
info "Pulling latest core..."
|
||||||
|
git -C "$CS_CORE_DIR" pull --ff-only \
|
||||||
|
|| warn "Pull failed — continuing with existing version"
|
||||||
|
success "Core updated"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Cloning context-studio-core → $CS_CORE_DIR"
|
||||||
|
mkdir -p "$CS_HOME"
|
||||||
|
git clone "$CS_CORE_REPO" "$CS_CORE_DIR" \
|
||||||
|
|| die "Failed to clone context-studio-core. Check your SSH key and network."
|
||||||
|
success "Core installed at $CS_CORE_DIR"
|
||||||
|
}
|
||||||
101
lib/project.sh
Normal file
101
lib/project.sh
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# project.sh — create project directory and devcontainer
|
||||||
|
|
||||||
|
WIZARD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
create_project_structure() {
|
||||||
|
local project_dir="$1"
|
||||||
|
local project_name="$2"
|
||||||
|
|
||||||
|
info "Creating project structure at $project_dir..."
|
||||||
|
|
||||||
|
mkdir -p "$project_dir/src"
|
||||||
|
mkdir -p "$project_dir/.devcontainer"
|
||||||
|
|
||||||
|
# .gitignore
|
||||||
|
cat > "$project_dir/.gitignore" <<'EOF'
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
.pnp/
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
*.AppImage
|
||||||
|
*.dmg
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
workflow/data/registry.db
|
||||||
|
workflow/users/*/session-history/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# README
|
||||||
|
cat > "$project_dir/README.md" <<EOF
|
||||||
|
# $project_name
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### First time setup
|
||||||
|
\`\`\`bash
|
||||||
|
# Open in devcontainer (VS Code)
|
||||||
|
code .
|
||||||
|
# → Reopen in Container
|
||||||
|
|
||||||
|
# Or via CLI
|
||||||
|
docker build -t $( slugify "$project_name" ) .devcontainer/
|
||||||
|
docker run -it --rm \\
|
||||||
|
-v "\$(pwd)":/workspace \\
|
||||||
|
-v "\$HOME/.context-studio/core":/opt/context-studio/core \\
|
||||||
|
-e ANTHROPIC_API_KEY="\$ANTHROPIC_API_KEY" \\
|
||||||
|
$( slugify "$project_name" ) bash
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Start Context Studio
|
||||||
|
\`\`\`bash
|
||||||
|
CS_WORKFLOW_DIR=/workspace/workflow node /opt/context-studio/core/core/start.js
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Start headless (no Electron UI)
|
||||||
|
\`\`\`bash
|
||||||
|
CS_WORKFLOW_DIR=/workspace/workflow node /opt/context-studio/core/core/start.js --ui-mode=headless
|
||||||
|
\`\`\`
|
||||||
|
EOF
|
||||||
|
|
||||||
|
success "Project structure created"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_devcontainer() {
|
||||||
|
local project_dir="$1"
|
||||||
|
local project_name="$2"
|
||||||
|
local slug
|
||||||
|
slug="$(slugify "$project_name")"
|
||||||
|
|
||||||
|
info "Generating devcontainer config..."
|
||||||
|
|
||||||
|
# Dockerfile
|
||||||
|
sed "s/{{PROJECT_SLUG}}/$slug/g" \
|
||||||
|
"$WIZARD_DIR/templates/Dockerfile" \
|
||||||
|
> "$project_dir/.devcontainer/Dockerfile"
|
||||||
|
|
||||||
|
# devcontainer.json
|
||||||
|
sed "s/{{PROJECT_NAME}}/$project_name/g; s/{{PROJECT_SLUG}}/$slug/g" \
|
||||||
|
"$WIZARD_DIR/templates/devcontainer.json" \
|
||||||
|
> "$project_dir/.devcontainer/devcontainer.json"
|
||||||
|
|
||||||
|
success "Devcontainer config written to $project_dir/.devcontainer/"
|
||||||
|
}
|
||||||
73
lib/utils.sh
Normal file
73
lib/utils.sh
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# utils.sh — colors, prompts, helpers
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
RESET='\033[0m'
|
||||||
|
|
||||||
|
info() { echo -e "${CYAN}${BOLD}[info]${RESET} $*"; }
|
||||||
|
success() { echo -e "${GREEN}${BOLD}[ok]${RESET} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}${BOLD}[warn]${RESET} $*"; }
|
||||||
|
error() { echo -e "${RED}${BOLD}[error]${RESET} $*" >&2; }
|
||||||
|
die() { error "$*"; exit 1; }
|
||||||
|
header() { echo -e "\n${BOLD}${CYAN}━━━ $* ━━━${RESET}\n"; }
|
||||||
|
|
||||||
|
# ask VAR "prompt" "default"
|
||||||
|
ask() {
|
||||||
|
local var="$1" prompt="$2" default="$3"
|
||||||
|
if [[ -n "$default" ]]; then
|
||||||
|
echo -ne "${BOLD}${prompt}${RESET} ${CYAN}[${default}]${RESET}: "
|
||||||
|
else
|
||||||
|
echo -ne "${BOLD}${prompt}${RESET}: "
|
||||||
|
fi
|
||||||
|
read -r input
|
||||||
|
if [[ -z "$input" && -n "$default" ]]; then
|
||||||
|
eval "$var=\"$default\""
|
||||||
|
else
|
||||||
|
eval "$var=\"$input\""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ask_yn VAR "prompt" "y|n"
|
||||||
|
ask_yn() {
|
||||||
|
local var="$1" prompt="$2" default="$3"
|
||||||
|
local options
|
||||||
|
if [[ "$default" == "y" ]]; then options="Y/n"; else options="y/N"; fi
|
||||||
|
echo -ne "${BOLD}${prompt}${RESET} ${CYAN}[${options}]${RESET}: "
|
||||||
|
read -r input
|
||||||
|
input="${input:-$default}"
|
||||||
|
if [[ "$input" =~ ^[Yy]$ ]]; then
|
||||||
|
eval "$var=y"
|
||||||
|
else
|
||||||
|
eval "$var=n"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ask_choice VAR "prompt" option1 option2 ...
|
||||||
|
ask_choice() {
|
||||||
|
local var="$1" prompt="$2"; shift 2
|
||||||
|
local options=("$@")
|
||||||
|
echo -e "${BOLD}${prompt}${RESET}"
|
||||||
|
for i in "${!options[@]}"; do
|
||||||
|
echo -e " ${CYAN}$((i+1))${RESET}) ${options[$i]}"
|
||||||
|
done
|
||||||
|
echo -ne "Choice ${CYAN}[1]${RESET}: "
|
||||||
|
read -r input
|
||||||
|
input="${input:-1}"
|
||||||
|
if [[ "$input" =~ ^[0-9]+$ ]] && (( input >= 1 && input <= ${#options[@]} )); then
|
||||||
|
eval "$var=\"${options[$((input-1))]}\""
|
||||||
|
else
|
||||||
|
eval "$var=\"${options[0]}\""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
require_cmd() {
|
||||||
|
command -v "$1" &>/dev/null || die "Required command not found: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
slugify() {
|
||||||
|
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//;s/-$//'
|
||||||
|
}
|
||||||
166
lib/workflow.sh
Normal file
166
lib/workflow.sh
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# workflow.sh — generate or clone workflow config
|
||||||
|
|
||||||
|
WIZARD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
# generate_workflow PROJECT_DIR PROJECT_NAME PROJECT_DESC TECH_STACK PRESET
|
||||||
|
generate_workflow() {
|
||||||
|
local project_dir="$1"
|
||||||
|
local project_name="$2"
|
||||||
|
local project_desc="$3"
|
||||||
|
local tech_stack="$4"
|
||||||
|
local preset="$5"
|
||||||
|
local workflow_dir="$project_dir/workflow"
|
||||||
|
|
||||||
|
info "Generating workflow config ($preset preset)..."
|
||||||
|
|
||||||
|
mkdir -p "$workflow_dir/agents"
|
||||||
|
mkdir -p "$workflow_dir/roles"
|
||||||
|
mkdir -p "$workflow_dir/hooks/rules"
|
||||||
|
mkdir -p "$workflow_dir/project-docs/tasks"
|
||||||
|
mkdir -p "$workflow_dir/users/default/tasks"
|
||||||
|
mkdir -p "$workflow_dir/data"
|
||||||
|
|
||||||
|
# workflow.json
|
||||||
|
cat > "$workflow_dir/workflow.json" <<EOF
|
||||||
|
{
|
||||||
|
"name": "$(slugify "$project_name")",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "$project_desc",
|
||||||
|
"techStack": "$tech_stack",
|
||||||
|
"requirements": {
|
||||||
|
"tools": [],
|
||||||
|
"cliProviders": [
|
||||||
|
{
|
||||||
|
"name": "claude-code",
|
||||||
|
"command": "claude",
|
||||||
|
"versionFlag": "--version",
|
||||||
|
"installHint": "npm install -g @anthropic-ai/claude-code"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# system.json
|
||||||
|
cp "$WIZARD_DIR/templates/system.json" "$workflow_dir/system.json"
|
||||||
|
|
||||||
|
# agents.json — based on preset
|
||||||
|
local agents_template
|
||||||
|
case "$preset" in
|
||||||
|
standard) agents_template="$WIZARD_DIR/templates/agents-standard.json" ;;
|
||||||
|
*) agents_template="$WIZARD_DIR/templates/agents-minimal.json" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sed "s/{{PROJECT_NAME}}/$project_name/g; s/{{PROJECT_DESC}}/$project_desc/g" \
|
||||||
|
"$agents_template" > "$workflow_dir/agents.json"
|
||||||
|
|
||||||
|
# Create agent directories from agents.json
|
||||||
|
local agent_ids
|
||||||
|
agent_ids=$(grep '"id"' "$workflow_dir/agents.json" | sed 's/.*"id": *"\([^"]*\)".*/\1/')
|
||||||
|
for agent_id in $agent_ids; do
|
||||||
|
_create_agent_dir "$workflow_dir" "$agent_id"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy role files
|
||||||
|
cp "$WIZARD_DIR/templates/roles/"*.md "$workflow_dir/roles/" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Copy hook rules
|
||||||
|
cp "$WIZARD_DIR/templates/hooks/rules/"*.json "$workflow_dir/hooks/rules/" 2>/dev/null || true
|
||||||
|
|
||||||
|
# project-docs/project-vision.md
|
||||||
|
cat > "$workflow_dir/project-docs/project-vision.md" <<EOF
|
||||||
|
# $project_name — Project Vision
|
||||||
|
|
||||||
|
## Description
|
||||||
|
$project_desc
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
$tech_stack
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
- [ ] Define requirements
|
||||||
|
- [ ] Implement core features
|
||||||
|
- [ ] Test and review
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
- Phase 1: Project setup and scaffolding
|
||||||
|
- Phase 2: Core implementation
|
||||||
|
- Phase 3: Testing and hardening
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# CLAUDE.md
|
||||||
|
cat > "$workflow_dir/CLAUDE.md" <<EOF
|
||||||
|
# $project_name
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
$project_desc
|
||||||
|
|
||||||
|
**Tech Stack**: $tech_stack
|
||||||
|
|
||||||
|
## Context Studio Setup
|
||||||
|
- Workflow directory: \`CS_WORKFLOW_DIR\`
|
||||||
|
- Core directory: \`CS_CORE_DIR\`
|
||||||
|
- Start system: \`node \$CS_CORE_DIR/core/start.js\`
|
||||||
|
|
||||||
|
## Agent Roles
|
||||||
|
See \`roles/\` directory for agent role definitions.
|
||||||
|
Read \`project-docs/project-vision.md\` for project goals.
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
Use \`/sm <agent> "message"\` to send messages between agents.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
success "Workflow generated at $workflow_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
_create_agent_dir() {
|
||||||
|
local workflow_dir="$1"
|
||||||
|
local agent_id="$2"
|
||||||
|
local agent_dir="$workflow_dir/agents/$agent_id/.claude"
|
||||||
|
|
||||||
|
mkdir -p "$agent_dir/hooks"
|
||||||
|
mkdir -p "$agent_dir/commands"
|
||||||
|
|
||||||
|
# settings.json
|
||||||
|
cat > "$agent_dir/settings.json" <<EOF
|
||||||
|
{
|
||||||
|
"model": "sonnet",
|
||||||
|
"spinnerTipsEnabled": false,
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(*)",
|
||||||
|
"Read(*)",
|
||||||
|
"Write(*)",
|
||||||
|
"Edit(*)",
|
||||||
|
"Glob(*)",
|
||||||
|
"Grep(*)",
|
||||||
|
"Task",
|
||||||
|
"SlashCommand:/prime:*",
|
||||||
|
"SlashCommand:/sm:*"
|
||||||
|
],
|
||||||
|
"deny": [
|
||||||
|
"Bash(node \$CS_CORE_DIR/core/stop.js:*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# CLAUDE.md per agent
|
||||||
|
cat > "$workflow_dir/agents/$agent_id/CLAUDE.md" <<EOF
|
||||||
|
# Agent: $agent_id
|
||||||
|
|
||||||
|
Load your role with \`/prime\` at session start.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_workflow() {
|
||||||
|
local project_dir="$1"
|
||||||
|
local repo_url="$2"
|
||||||
|
local workflow_dir="$project_dir/workflow"
|
||||||
|
|
||||||
|
info "Cloning workflow from $repo_url..."
|
||||||
|
git clone "$repo_url" "$workflow_dir" \
|
||||||
|
|| die "Failed to clone workflow repo: $repo_url"
|
||||||
|
success "Workflow cloned to $workflow_dir"
|
||||||
|
}
|
||||||
40
templates/Dockerfile
Normal file
40
templates/Dockerfile
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
FROM node:22-bookworm-slim
|
||||||
|
|
||||||
|
# ── System dependencies ──────────────────────────────────────────────────────
|
||||||
|
# Build tools: needed for node-pty (native module) and Electron
|
||||||
|
# xvfb + libgtk: needed if running Electron inside container with virtual display
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
ca-certificates \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
libx11-dev \
|
||||||
|
libxkbfile-dev \
|
||||||
|
libsecret-1-dev \
|
||||||
|
libfontconfig1 \
|
||||||
|
libgbm1 \
|
||||||
|
libasound2 \
|
||||||
|
xvfb \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# ── Rust toolchain ───────────────────────────────────────────────────────────
|
||||||
|
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||||
|
CARGO_HOME=/usr/local/cargo \
|
||||||
|
PATH=/usr/local/cargo/bin:$PATH
|
||||||
|
|
||||||
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
|
||||||
|
| sh -s -- -y --no-modify-path --default-toolchain stable \
|
||||||
|
&& rustup component add clippy rustfmt \
|
||||||
|
&& chmod -R a+w /usr/local/rustup /usr/local/cargo
|
||||||
|
|
||||||
|
# ── Claude Code CLI ──────────────────────────────────────────────────────────
|
||||||
|
RUN npm install -g @anthropic-ai/claude-code
|
||||||
|
|
||||||
|
# ── Workspace ────────────────────────────────────────────────────────────────
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
# Context Studio Core is mounted at /opt/context-studio/core (read-only from host)
|
||||||
|
# Workflow lives at /workspace/workflow (per-project, writable)
|
||||||
92
templates/agents-minimal.json
Normal file
92
templates/agents-minimal.json
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
{
|
||||||
|
"version": "2.2",
|
||||||
|
"projectName": "{{PROJECT_NAME}}",
|
||||||
|
"projectDescription": "{{PROJECT_DESC}}",
|
||||||
|
"features": {
|
||||||
|
"use_database_tracking": true
|
||||||
|
},
|
||||||
|
"agentGroups": [
|
||||||
|
{
|
||||||
|
"name": "Coordination",
|
||||||
|
"agents": ["kai"],
|
||||||
|
"color": "#a6e3a1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Development",
|
||||||
|
"agents": ["dev", "ace"],
|
||||||
|
"color": "#89b4fa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Quality",
|
||||||
|
"agents": ["rex", "kit"],
|
||||||
|
"color": "#f9e2af"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"agents": [
|
||||||
|
{
|
||||||
|
"id": "kai",
|
||||||
|
"name": "Lead Coordinator",
|
||||||
|
"workingDirectory": "agents/kai",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "coordinator",
|
||||||
|
"description": "Central coordination — receives tasks from user, plans work, delegates to agents",
|
||||||
|
"capabilities": ["coordination", "documentation", "monitoring", "delegation"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dev",
|
||||||
|
"name": "Developer",
|
||||||
|
"workingDirectory": "agents/dev",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "coder",
|
||||||
|
"description": "Primary developer — implements features, writes code, fixes bugs",
|
||||||
|
"capabilities": ["coding", "debugging", "refactoring"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ace",
|
||||||
|
"name": "Developer 2",
|
||||||
|
"workingDirectory": "agents/ace",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "coder",
|
||||||
|
"description": "Secondary developer — parallel implementation, code reviews",
|
||||||
|
"capabilities": ["coding", "debugging", "refactoring"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rex",
|
||||||
|
"name": "Researcher",
|
||||||
|
"workingDirectory": "agents/rex",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "researcher",
|
||||||
|
"description": "Research and discovery — investigates APIs, patterns, documentation",
|
||||||
|
"capabilities": ["research", "documentation", "analysis"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "kit",
|
||||||
|
"name": "Tester",
|
||||||
|
"workingDirectory": "agents/kit",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "tester",
|
||||||
|
"description": "Testing and quality assurance — writes tests, validates behavior",
|
||||||
|
"capabilities": ["testing", "validation", "bug-reporting"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
149
templates/agents-standard.json
Normal file
149
templates/agents-standard.json
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
{
|
||||||
|
"version": "2.2",
|
||||||
|
"projectName": "{{PROJECT_NAME}}",
|
||||||
|
"projectDescription": "{{PROJECT_DESC}}",
|
||||||
|
"features": {
|
||||||
|
"use_database_tracking": true
|
||||||
|
},
|
||||||
|
"agentGroups": [
|
||||||
|
{
|
||||||
|
"name": "Coordination",
|
||||||
|
"agents": ["kai", "sam"],
|
||||||
|
"color": "#a6e3a1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Development",
|
||||||
|
"agents": ["dev", "ace", "bolt"],
|
||||||
|
"color": "#89b4fa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Research",
|
||||||
|
"agents": ["rex", "doc"],
|
||||||
|
"color": "#cba6f7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Quality",
|
||||||
|
"agents": ["kit", "lens"],
|
||||||
|
"color": "#f9e2af"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"agents": [
|
||||||
|
{
|
||||||
|
"id": "kai",
|
||||||
|
"name": "Lead Coordinator",
|
||||||
|
"workingDirectory": "agents/kai",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "coordinator",
|
||||||
|
"description": "Central coordination — receives tasks from user, plans work, delegates to sub-coordinators and agents",
|
||||||
|
"capabilities": ["coordination", "documentation", "monitoring", "delegation"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sam",
|
||||||
|
"name": "Sub-coordinator",
|
||||||
|
"workingDirectory": "agents/sam",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "subcoordinator",
|
||||||
|
"description": "Sub-coordination — manages a group of agents for a specific workstream",
|
||||||
|
"capabilities": ["coordination", "delegation", "tracking"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dev",
|
||||||
|
"name": "Developer",
|
||||||
|
"workingDirectory": "agents/dev",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "coder",
|
||||||
|
"description": "Primary developer — implements features, writes code, fixes bugs",
|
||||||
|
"capabilities": ["coding", "debugging", "refactoring"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ace",
|
||||||
|
"name": "Developer 2",
|
||||||
|
"workingDirectory": "agents/ace",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "coder",
|
||||||
|
"description": "Secondary developer — parallel implementation",
|
||||||
|
"capabilities": ["coding", "debugging", "refactoring"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bolt",
|
||||||
|
"name": "Developer 3",
|
||||||
|
"workingDirectory": "agents/bolt",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "coder",
|
||||||
|
"description": "Tertiary developer — specialised tasks and overflow",
|
||||||
|
"capabilities": ["coding", "debugging"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rex",
|
||||||
|
"name": "Researcher",
|
||||||
|
"workingDirectory": "agents/rex",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "researcher",
|
||||||
|
"description": "Lead researcher — investigates APIs, patterns, architecture",
|
||||||
|
"capabilities": ["research", "documentation", "analysis"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "doc",
|
||||||
|
"name": "Documentation",
|
||||||
|
"workingDirectory": "agents/doc",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "researcher",
|
||||||
|
"description": "Documentation specialist — writes docs, technical writing",
|
||||||
|
"capabilities": ["documentation", "research", "writing"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "kit",
|
||||||
|
"name": "Tester",
|
||||||
|
"workingDirectory": "agents/kit",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "tester",
|
||||||
|
"description": "Testing and quality assurance — writes tests, validates behavior",
|
||||||
|
"capabilities": ["testing", "validation", "bug-reporting"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "lens",
|
||||||
|
"name": "Code Reviewer",
|
||||||
|
"workingDirectory": "agents/lens",
|
||||||
|
"hooks": ".claude/hooks/",
|
||||||
|
"settings": ".claude/settings.json",
|
||||||
|
"role": "reviewer",
|
||||||
|
"description": "Code review — reviews PRs, enforces standards, flags issues",
|
||||||
|
"capabilities": ["code-review", "standards", "security"],
|
||||||
|
"cli": "claude code",
|
||||||
|
"provider": "claude",
|
||||||
|
"cliParams": ["--dangerously-skip-permissions"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
36
templates/devcontainer.json
Normal file
36
templates/devcontainer.json
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"name": "{{PROJECT_NAME}}",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
},
|
||||||
|
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
|
||||||
|
"workspaceFolder": "/workspace",
|
||||||
|
"mounts": [
|
||||||
|
"source=${localEnv:HOME}/.context-studio/core,target=/opt/context-studio/core,type=bind,consistency=cached",
|
||||||
|
"source=${localEnv:HOME}/.anthropic,target=/root/.anthropic,type=bind,consistency=cached"
|
||||||
|
],
|
||||||
|
"remoteEnv": {
|
||||||
|
"ANTHROPIC_API_KEY": "${localEnv:ANTHROPIC_API_KEY}",
|
||||||
|
"CS_CORE_DIR": "/opt/context-studio/core",
|
||||||
|
"CS_WORKFLOW_DIR": "/workspace/workflow",
|
||||||
|
"PROJECT_ROOT_DIR": "/workspace",
|
||||||
|
"DISPLAY": "${localEnv:DISPLAY}"
|
||||||
|
},
|
||||||
|
"postCreateCommand": "cd /opt/context-studio/core && npm install && git config --global --add safe.directory /workspace && git config --global --add safe.directory /opt/context-studio/core",
|
||||||
|
"runArgs": [
|
||||||
|
"--init",
|
||||||
|
"--cap-add=SYS_PTRACE",
|
||||||
|
"--security-opt", "seccomp=unconfined"
|
||||||
|
],
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"rust-lang.rust-analyzer",
|
||||||
|
"ms-vscode.cpptools"
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"terminal.integrated.defaultProfile.linux": "bash"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
templates/hooks/rules/coordinator.json
Normal file
17
templates/hooks/rules/coordinator.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"role": "coordinator",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"tool": "Bash",
|
||||||
|
"pattern": ".*",
|
||||||
|
"action": "warn",
|
||||||
|
"message": "Coordinators should delegate implementation to coders. Are you sure you want to run this command directly?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tool": "Edit",
|
||||||
|
"pattern": ".*",
|
||||||
|
"action": "warn",
|
||||||
|
"message": "Coordinators should delegate code changes to coders via /sm."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
4
templates/hooks/rules/default.json
Normal file
4
templates/hooks/rules/default.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"role": "default",
|
||||||
|
"rules": []
|
||||||
|
}
|
||||||
19
templates/roles/coder-role.md
Normal file
19
templates/roles/coder-role.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Coder Role
|
||||||
|
|
||||||
|
You are a Developer in a multi-agent development team managed by Context Studio.
|
||||||
|
|
||||||
|
## Responsibilities
|
||||||
|
- Implement features and fix bugs as delegated by the coordinator
|
||||||
|
- Write clean, maintainable code
|
||||||
|
- Follow project conventions and tech stack
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
- Receive tasks via A2A messages
|
||||||
|
- Report completion or blockers back to coordinator via `/sm kai "status"`
|
||||||
|
- Ask for clarification when requirements are ambiguous
|
||||||
|
|
||||||
|
## Principles
|
||||||
|
- Read existing code before modifying it
|
||||||
|
- Prefer editing existing files over creating new ones
|
||||||
|
- Write tests for non-trivial logic
|
||||||
|
- Keep changes focused on the task
|
||||||
20
templates/roles/coordinator-role.md
Normal file
20
templates/roles/coordinator-role.md
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Coordinator Role
|
||||||
|
|
||||||
|
You are a Lead Coordinator in a multi-agent development team managed by Context Studio.
|
||||||
|
|
||||||
|
## Responsibilities
|
||||||
|
- Receive tasks from the user
|
||||||
|
- Break down tasks into subtasks and delegate to appropriate agents
|
||||||
|
- Track progress and consolidate results
|
||||||
|
- Report status back to the user
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
- Send messages to agents via `/sm <agent-id> "message"`
|
||||||
|
- Monitor agent status
|
||||||
|
- Escalate blockers to the user
|
||||||
|
|
||||||
|
## Principles
|
||||||
|
- Delegate implementation to coders — do not write code yourself
|
||||||
|
- Delegate research to researchers
|
||||||
|
- Delegate testing to testers
|
||||||
|
- Keep the user informed of progress
|
||||||
18
templates/roles/researcher-role.md
Normal file
18
templates/roles/researcher-role.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Researcher Role
|
||||||
|
|
||||||
|
You are a Researcher in a multi-agent development team managed by Context Studio.
|
||||||
|
|
||||||
|
## Responsibilities
|
||||||
|
- Investigate APIs, libraries, patterns, and documentation
|
||||||
|
- Produce concise research reports for the coordinator and coders
|
||||||
|
- Answer technical questions with evidence
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
- Receive research tasks via A2A messages
|
||||||
|
- Report findings back via `/sm kai "findings"` or the requesting agent
|
||||||
|
- Store research results in `project-docs/` when relevant
|
||||||
|
|
||||||
|
## Principles
|
||||||
|
- Prefer official documentation over Stack Overflow
|
||||||
|
- Summarize findings — do not dump raw docs
|
||||||
|
- Flag uncertainties and alternatives
|
||||||
17
templates/roles/reviewer-role.md
Normal file
17
templates/roles/reviewer-role.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Reviewer Role
|
||||||
|
|
||||||
|
You are a Code Reviewer in a multi-agent development team managed by Context Studio.
|
||||||
|
|
||||||
|
## Responsibilities
|
||||||
|
- Review code written by developers
|
||||||
|
- Enforce coding standards and best practices
|
||||||
|
- Flag security issues, performance problems, and design smells
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
- Receive review tasks via A2A messages
|
||||||
|
- Report review results back to coordinator via `/sm kai "review complete"`
|
||||||
|
|
||||||
|
## Principles
|
||||||
|
- Be constructive — suggest improvements, not just problems
|
||||||
|
- Distinguish must-fix from nice-to-have
|
||||||
|
- Check for security vulnerabilities (injection, XSS, auth bypass, etc.)
|
||||||
19
templates/roles/subcoordinator-role.md
Normal file
19
templates/roles/subcoordinator-role.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Sub-coordinator Role
|
||||||
|
|
||||||
|
You are a Sub-coordinator in a multi-agent development team managed by Context Studio.
|
||||||
|
|
||||||
|
## Responsibilities
|
||||||
|
- Manage a group of agents for a specific workstream (e.g. backend, frontend)
|
||||||
|
- Receive delegated work from the Lead Coordinator
|
||||||
|
- Break it down further and delegate to specialists in your group
|
||||||
|
- Report consolidated progress back to the Lead Coordinator
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
- Receive tasks from Lead Coordinator (`kai`) via A2A messages
|
||||||
|
- Delegate to agents in your group via `/sm <agent> "task"`
|
||||||
|
- Report back to kai via `/sm kai "status"`
|
||||||
|
|
||||||
|
## Principles
|
||||||
|
- Do not implement code yourself — delegate to coders
|
||||||
|
- Track all delegated tasks and follow up on completion
|
||||||
|
- Escalate blockers to the Lead Coordinator
|
||||||
17
templates/roles/tester-role.md
Normal file
17
templates/roles/tester-role.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Tester Role
|
||||||
|
|
||||||
|
You are a Tester in a multi-agent development team managed by Context Studio.
|
||||||
|
|
||||||
|
## Responsibilities
|
||||||
|
- Write and run tests for features implemented by coders
|
||||||
|
- Report bugs with reproduction steps
|
||||||
|
- Validate acceptance criteria
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
- Receive testing tasks via A2A messages
|
||||||
|
- Report test results and bugs back to coordinator via `/sm kai "results"`
|
||||||
|
|
||||||
|
## Principles
|
||||||
|
- Test edge cases, not just happy paths
|
||||||
|
- Write automated tests where possible
|
||||||
|
- Keep bug reports actionable: what failed, what was expected, how to reproduce
|
||||||
43
templates/system.json
Normal file
43
templates/system.json
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"version": "1.0",
|
||||||
|
"registry": {
|
||||||
|
"database": "./data/registry.db",
|
||||||
|
"port": 8000
|
||||||
|
},
|
||||||
|
"system": {
|
||||||
|
"startup_delay": 1500,
|
||||||
|
"message_timeout": 30000,
|
||||||
|
"max_message_size": 1048576,
|
||||||
|
"heartbeat_interval": 30000,
|
||||||
|
"heartbeat_timeout": 5000,
|
||||||
|
"heartbeat_failure_threshold": 3,
|
||||||
|
"log_level": "info",
|
||||||
|
"debug_mode": false
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"max_queue_size_per_agent": 1000,
|
||||||
|
"max_messages_per_agent": 5000,
|
||||||
|
"max_sse_connections_per_agent": 5,
|
||||||
|
"rate_limit_enabled": true,
|
||||||
|
"max_requests_per_minute_per_agent": 100,
|
||||||
|
"sanitize_input": true,
|
||||||
|
"bypass_localhost": true
|
||||||
|
},
|
||||||
|
"monitor": {
|
||||||
|
"pane_detection_max_retries": 5,
|
||||||
|
"pane_cache_duration": 300000,
|
||||||
|
"auto_recovery_interval": 60000,
|
||||||
|
"sse_reconnect_initial_delay": 200,
|
||||||
|
"sse_reconnect_max_delay": 5000
|
||||||
|
},
|
||||||
|
"a2aInjection": {
|
||||||
|
"chunkSize": 8192,
|
||||||
|
"chunkDelayMs": 5,
|
||||||
|
"scaledDelayBaseMs": 50,
|
||||||
|
"scaledDelayPerChunkMs": 40,
|
||||||
|
"scaledDelayMinMs": 100,
|
||||||
|
"busyFlagTimeoutMs": 30000,
|
||||||
|
"injectionTimeoutMs": 600000,
|
||||||
|
"debugMode": false
|
||||||
|
}
|
||||||
|
}
|
||||||
160
wizard.sh
Executable file
160
wizard.sh
Executable file
|
|
@ -0,0 +1,160 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# ╔══════════════════════════════════════════════════════════════════╗
|
||||||
|
# ║ Context Studio Wizard — Project Setup ║
|
||||||
|
# ╚══════════════════════════════════════════════════════════════════╝
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
WIZARD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
source "$WIZARD_DIR/lib/utils.sh"
|
||||||
|
source "$WIZARD_DIR/lib/core.sh"
|
||||||
|
source "$WIZARD_DIR/lib/project.sh"
|
||||||
|
source "$WIZARD_DIR/lib/workflow.sh"
|
||||||
|
|
||||||
|
# ── Prerequisites ──────────────────────────────────────────────────────────
|
||||||
|
check_prerequisites() {
|
||||||
|
header "Checking Prerequisites"
|
||||||
|
require_cmd git
|
||||||
|
if command -v docker &>/dev/null; then
|
||||||
|
CONTAINER_CMD="docker"
|
||||||
|
elif command -v podman &>/dev/null; then
|
||||||
|
CONTAINER_CMD="podman"
|
||||||
|
else
|
||||||
|
die "Neither docker nor podman found. Install one to use devcontainers."
|
||||||
|
fi
|
||||||
|
success "git: $(git --version)"
|
||||||
|
success "$CONTAINER_CMD: $($CONTAINER_CMD --version | head -1)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Project info ───────────────────────────────────────────────────────────
|
||||||
|
collect_project_info() {
|
||||||
|
header "Project Details"
|
||||||
|
|
||||||
|
ask PROJECT_NAME "Project name" ""
|
||||||
|
[[ -z "$PROJECT_NAME" ]] && die "Project name is required."
|
||||||
|
|
||||||
|
local default_dir="$HOME/projects/$(slugify "$PROJECT_NAME")"
|
||||||
|
ask PROJECT_DIR "Project location" "$default_dir"
|
||||||
|
[[ -z "$PROJECT_DIR" ]] && die "Project location is required."
|
||||||
|
PROJECT_DIR="${PROJECT_DIR/#\~/$HOME}"
|
||||||
|
|
||||||
|
if [[ -e "$PROJECT_DIR" ]]; then
|
||||||
|
warn "Directory already exists: $PROJECT_DIR"
|
||||||
|
ask_yn _continue "Continue anyway?" "n"
|
||||||
|
[[ "$_continue" != "y" ]] && die "Aborted."
|
||||||
|
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" ""
|
||||||
|
[[ -z "$WORKFLOW_REPO" ]] && die "Repo URL is required."
|
||||||
|
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)"
|
||||||
|
# Normalize to short key
|
||||||
|
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 preset)"
|
||||||
|
echo -e " ${BOLD}Description${RESET} : ${PROJECT_DESC:-}"
|
||||||
|
echo -e " ${BOLD}Tech stack${RESET} : ${TECH_STACK:-}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
ask_yn _ok "Create project?" "y"
|
||||||
|
[[ "$_ok" != "y" ]] && die "Aborted."
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Build ──────────────────────────────────────────────────────────────────
|
||||||
|
build_project() {
|
||||||
|
header "Building Project"
|
||||||
|
|
||||||
|
create_project_structure "$PROJECT_DIR" "$PROJECT_NAME"
|
||||||
|
create_devcontainer "$PROJECT_DIR" "$PROJECT_NAME"
|
||||||
|
|
||||||
|
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"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Init git repo
|
||||||
|
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}Next steps:${RESET}"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}Option A — VS Code devcontainer:${RESET}"
|
||||||
|
echo -e " code \"$PROJECT_DIR\""
|
||||||
|
echo -e " → \"Reopen in Container\""
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}Option B — CLI:${RESET}"
|
||||||
|
echo -e " cd \"$PROJECT_DIR\""
|
||||||
|
echo -e " $CONTAINER_CMD build -t $slug .devcontainer/"
|
||||||
|
echo -e " $CONTAINER_CMD run -it --rm \\"
|
||||||
|
echo -e " -v \"\$(pwd)\":/workspace \\"
|
||||||
|
echo -e " -v \"\$HOME/.context-studio/core\":/opt/context-studio/core \\"
|
||||||
|
echo -e " -e ANTHROPIC_API_KEY=\"\$ANTHROPIC_API_KEY\" \\"
|
||||||
|
echo -e " $slug bash"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${CYAN}Inside container — start Context Studio:${RESET}"
|
||||||
|
echo -e " node \$CS_CORE_DIR/core/start.js"
|
||||||
|
echo -e " # or headless (no Electron):"
|
||||||
|
echo -e " node \$CS_CORE_DIR/core/start.js --ui-mode=headless"
|
||||||
|
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 "$@"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue