#!/usr/bin/env bash # register_project.sh — register a new project with the Custodian State Hub # # Usage: scripts/register_project.sh # domain: one of custodian|railiance|markitect|coulomb_social|personhood|foerster_capabilities # project_path: absolute path to the project directory # # Example: # scripts/register_project.sh railiance /home/worsch/railiance # # What it does: # 1. Verify the API is reachable # 2. Look up the topic ID for the domain # 3. Check that state-hub is in ~/.claude.json; warn if missing # 4. Write $project_path/CLAUDE.md from the template (skip if exists) # 5. POST a progress event recording the registration set -euo pipefail DOMAIN="${1:-}" PROJECT_PATH="${2:-}" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" STATE_HUB_DIR="$(dirname "$SCRIPT_DIR")" API_BASE="${API_BASE:-http://127.0.0.1:8000}" # ── Validate args ────────────────────────────────────────────────────────────── if [[ -z "$DOMAIN" || -z "$PROJECT_PATH" ]]; then echo "Usage: $0 " echo " domain: custodian|railiance|markitect|coulomb_social|personhood|foerster_capabilities" echo " project_path: absolute path to project directory" exit 1 fi if [[ ! -d "$PROJECT_PATH" ]]; then echo "ERROR: project_path does not exist: $PROJECT_PATH" exit 1 fi PROJECT_NAME="$(basename "$PROJECT_PATH")" # ── Step 1: API health check ─────────────────────────────────────────────────── echo "==> Checking API at $API_BASE ..." if ! curl -sf "$API_BASE/state/health" > /dev/null; then echo "ERROR: State Hub API is not reachable." echo " Start it: cd $STATE_HUB_DIR && make api" echo " (requires postgres: make db first)" exit 1 fi echo " API OK" # ── Step 2: Look up topic ID ─────────────────────────────────────────────────── echo "==> Looking up topic for domain '$DOMAIN' ..." TOPICS_JSON="$(curl -sf "$API_BASE/topics/?status=active")" TOPIC_ID="$(echo "$TOPICS_JSON" | python3 -c " import json, sys topics = json.load(sys.stdin) match = next((t for t in topics if t.get('domain') == sys.argv[1]), None) if not match: print('NOT_FOUND') else: print(match['id']) " "$DOMAIN")" if [[ "$TOPIC_ID" == "NOT_FOUND" ]]; then echo "ERROR: No active topic found for domain '$DOMAIN'." echo " Known domains: custodian railiance markitect coulomb_social personhood foerster_capabilities" exit 1 fi echo " topic_id: $TOPIC_ID" # ── Step 3: Check MCP registration ──────────────────────────────────────────── echo "==> Checking MCP server registration ..." MCP_OK="$(python3 -c " import json from pathlib import Path f = Path.home() / '.claude.json' if not f.exists(): print('MISSING_FILE') else: d = json.loads(f.read_text()) servers = d.get('mcpServers', {}) print('OK' if 'state-hub' in servers else 'NOT_REGISTERED') ")" if [[ "$MCP_OK" == "MISSING_FILE" ]]; then echo "WARNING: ~/.claude.json not found. MCP server is not registered." echo " To register:" echo " MСPCFG=\$(cat $STATE_HUB_DIR/../.mcp.json | python3 -c \"import json,sys; print(json.dumps(json.load(sys.stdin)['mcpServers']['state-hub']))\")" echo " claude mcp add-json -s user state-hub \"\$MCPCFG\"" echo " python3 $SCRIPT_DIR/patch_mcp_cwd.py" elif [[ "$MCP_OK" == "NOT_REGISTERED" ]]; then echo "WARNING: 'state-hub' not found in ~/.claude.json." echo " To register, see CLAUDE.md MCP Server Registration section." else echo " MCP OK" fi # ── Step 4: Write CLAUDE.md ──────────────────────────────────────────────────── CLAUDE_MD="$PROJECT_PATH/CLAUDE.md" TEMPLATE="$SCRIPT_DIR/project_claude_md.template" if [[ -f "$CLAUDE_MD" ]]; then echo "==> CLAUDE.md already exists at $CLAUDE_MD — skipping." else echo "==> Writing CLAUDE.md to $CLAUDE_MD ..." sed \ -e "s|{PROJECT_NAME}|$PROJECT_NAME|g" \ -e "s|{DOMAIN}|$DOMAIN|g" \ -e "s|{TOPIC_ID}|$TOPIC_ID|g" \ "$TEMPLATE" > "$CLAUDE_MD" echo " Written." fi # ── Step 5: Record progress event ───────────────────────────────────────────── echo "==> Recording registration event ..." EVENT_JSON="$(python3 -c " import json payload = { 'topic_id': '$TOPIC_ID', 'event_type': 'milestone', 'summary': 'Project registered with State Hub: $PROJECT_NAME ($DOMAIN)', 'author': 'custodian', 'detail': { 'project_path': '$PROJECT_PATH', 'claude_md': '$CLAUDE_MD', 'domain': '$DOMAIN', }, } print(json.dumps(payload)) ")" curl -sf -X POST "$API_BASE/progress/" \ -H "Content-Type: application/json" \ -d "$EVENT_JSON" > /dev/null echo " Event recorded." echo "" echo "Registration complete!" echo " Project: $PROJECT_NAME" echo " Domain: $DOMAIN" echo " Topic ID: $TOPIC_ID" echo " CLAUDE.md: $CLAUDE_MD" echo "" echo "Next: restart Claude Code for the MCP server to be available in this project."