mirror of
https://github.com/JuliusBrussee/cavekit.git
synced 2026-09-14 16:32:40 +08:00
ad7aa4ebd7
Adds a preflight step that removes the deprecated ~/.claude/plugins/local/blueprint-marketplace and ~/.claude/plugins/cache/blueprint-local directories left behind by earlier "bp" installs, so the installer converges on a clean ck-only plugin layout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
202 lines
8.1 KiB
Bash
Executable File
202 lines
8.1 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Cavekit Installer
|
|
#
|
|
# Usage:
|
|
# git clone https://github.com/JuliusBrussee/cavekit.git ~/.cavekit && ~/.cavekit/install.sh
|
|
|
|
set -euo pipefail
|
|
|
|
INSTALL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
CLAUDE_DIR="$HOME/.claude"
|
|
SETTINGS_FILE="$CLAUDE_DIR/settings.json"
|
|
BIN_DIR="/usr/local/bin"
|
|
MARKETPLACE_NAME="cavekit-local"
|
|
MARKETPLACE_DIR="$CLAUDE_DIR/plugins/local/cavekit-marketplace"
|
|
|
|
# ─── Colors ─────────────────────────────────────────────────────────────────
|
|
|
|
R=$'\033[0m' B=$'\033[1m' GR=$'\033[32m' YL=$'\033[33m' BL=$'\033[34m' RD=$'\033[31m'
|
|
|
|
info() { printf "${BL}▸${R} %s\n" "$1"; }
|
|
ok() { printf "${GR}■${R} %s\n" "$1"; }
|
|
warn() { printf "${YL}!${R} %s\n" "$1"; }
|
|
fail() { printf "${RD}✗${R} %s\n" "$1" >&2; exit 1; }
|
|
|
|
# ─── Header ─────────────────────────────────────────────────────────────────
|
|
|
|
printf "\n${B}${BL} ┌──────────────────────────┐${R}\n"
|
|
printf "${B}${BL} │ C A V E K I T │${R}\n"
|
|
printf "${B}${BL} └──────────────────────────┘${R}\n"
|
|
printf "${B}Installer${R}\n\n"
|
|
|
|
# ─── Preflight ──────────────────────────────────────────────────────────────
|
|
|
|
command -v git &>/dev/null || fail "git not found."
|
|
command -v claude &>/dev/null || warn "claude CLI not found. Install Claude Code to use /ck:... commands."
|
|
command -v codex &>/dev/null || warn "codex CLI not found. Codex local plugin sync will still be configured."
|
|
command -v tmux &>/dev/null || warn "tmux not found. Install for the parallel launcher: brew install tmux"
|
|
|
|
# ─── Clean up legacy blueprint/bp install artifacts ────────────────────────
|
|
|
|
LEGACY_BP_MARKET="$CLAUDE_DIR/plugins/local/blueprint-marketplace"
|
|
LEGACY_BP_CACHE="$CLAUDE_DIR/plugins/cache/blueprint-local"
|
|
|
|
if [[ -d "$LEGACY_BP_MARKET" || -d "$LEGACY_BP_CACHE" ]]; then
|
|
info "Removing deprecated blueprint/bp install artifacts..."
|
|
rm -rf "$LEGACY_BP_MARKET" "$LEGACY_BP_CACHE"
|
|
ok "Removed legacy blueprint-marketplace and cache"
|
|
fi
|
|
|
|
# ─── Create marketplace with symlink to repo ─────────────────────────────
|
|
|
|
info "Setting up Cavekit marketplace..."
|
|
|
|
mkdir -p "$MARKETPLACE_DIR/.claude-plugin"
|
|
|
|
# Symlink the repo as the "ck" plugin
|
|
ln -sfn "$INSTALL_DIR" "$MARKETPLACE_DIR/ck"
|
|
|
|
# Remove any legacy bp alias symlink from earlier installs
|
|
rm -f "$MARKETPLACE_DIR/bp"
|
|
|
|
# Write marketplace metadata
|
|
cat > "$MARKETPLACE_DIR/.claude-plugin/marketplace.json" <<EOF
|
|
{
|
|
"name": "$MARKETPLACE_NAME",
|
|
"owner": { "name": "$(whoami)" },
|
|
"metadata": {
|
|
"description": "Local Cavekit plugin marketplace",
|
|
"version": "3.0.1"
|
|
},
|
|
"plugins": [
|
|
{
|
|
"name": "ck",
|
|
"description": "Cavekit framework with skills, commands, agents, and references",
|
|
"version": "3.0.1",
|
|
"source": "./ck",
|
|
"author": { "name": "$(whoami)" }
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
|
|
cat > "$MARKETPLACE_DIR/.claude-plugin/plugin.json" <<EOF
|
|
{
|
|
"name": "cavekit-marketplace",
|
|
"description": "Local Cavekit plugin marketplace",
|
|
"version": "3.0.1",
|
|
"plugins": ["ck"]
|
|
}
|
|
EOF
|
|
|
|
ok "Marketplace created at $MARKETPLACE_DIR"
|
|
|
|
# ─── Register Claude Code plugin ───────────────────────────────────────────
|
|
|
|
info "Configuring Claude Code settings..."
|
|
|
|
mkdir -p "$CLAUDE_DIR"
|
|
|
|
if [[ ! -f "$SETTINGS_FILE" ]]; then
|
|
cat > "$SETTINGS_FILE" <<EOF
|
|
{
|
|
"extraKnownMarketplaces": {
|
|
"${MARKETPLACE_NAME}": {
|
|
"source": { "source": "directory", "path": "${MARKETPLACE_DIR}" }
|
|
}
|
|
},
|
|
"enabledPlugins": {
|
|
"ck@${MARKETPLACE_NAME}": true
|
|
}
|
|
}
|
|
EOF
|
|
ok "Created $SETTINGS_FILE"
|
|
else
|
|
if command -v python3 &>/dev/null; then
|
|
python3 - "$SETTINGS_FILE" "$MARKETPLACE_NAME" "$MARKETPLACE_DIR" <<'PYEOF'
|
|
import json, sys
|
|
path, name, mpath = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
with open(path) as f:
|
|
d = json.load(f)
|
|
markets = d.setdefault("extraKnownMarketplaces", {})
|
|
markets[name] = {"source": {"source": "directory", "path": mpath}}
|
|
# Remove deprecated blueprint-local marketplace
|
|
markets.pop("blueprint-local", None)
|
|
enabled = d.setdefault("enabledPlugins", {})
|
|
enabled[f"ck@{name}"] = True
|
|
# Strip all deprecated bp/blueprint plugin registrations (any marketplace)
|
|
for key in list(enabled.keys()):
|
|
if key.startswith("bp@") or key.startswith("blueprint@"):
|
|
enabled.pop(key, None)
|
|
with open(path, "w") as f:
|
|
json.dump(d, f, indent=2)
|
|
PYEOF
|
|
ok "Updated $SETTINGS_FILE"
|
|
else
|
|
if grep -q "ck@${MARKETPLACE_NAME}" "$SETTINGS_FILE" 2>/dev/null; then
|
|
ok "Plugin already registered"
|
|
else
|
|
warn "Could not auto-update settings. Add manually to $SETTINGS_FILE:"
|
|
printf "\n"
|
|
printf ' "extraKnownMarketplaces": { "%s": { "source": { "source": "directory", "path": "%s" } } }\n' "$MARKETPLACE_NAME" "$MARKETPLACE_DIR"
|
|
printf ' "enabledPlugins": { "ck@%s": true }\n\n' "$MARKETPLACE_NAME"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ─── Sync Codex local plugin ────────────────────────────────────────────────
|
|
|
|
info "Configuring Codex local plugin..."
|
|
|
|
chmod +x "$INSTALL_DIR/scripts/sync-codex-plugin.sh"
|
|
"$INSTALL_DIR/scripts/sync-codex-plugin.sh"
|
|
|
|
# ─── Install cavekit CLI ─────────────────────────────────────────────────
|
|
|
|
info "Installing cavekit command..."
|
|
|
|
chmod +x "$INSTALL_DIR/scripts/cavekit"
|
|
chmod +x "$INSTALL_DIR/scripts/cavekit-launch-session.sh"
|
|
chmod +x "$INSTALL_DIR/scripts/cavekit-status-poller.sh"
|
|
chmod +x "$INSTALL_DIR/scripts/cavekit-analytics.sh"
|
|
chmod +x "$INSTALL_DIR/scripts/dashboard-progress.sh"
|
|
chmod +x "$INSTALL_DIR/scripts/dashboard-activity.sh"
|
|
chmod +x "$INSTALL_DIR/scripts/setup-build.sh"
|
|
|
|
if [[ -w "$BIN_DIR" ]]; then
|
|
ln -sf "$INSTALL_DIR/scripts/cavekit" "$BIN_DIR/cavekit"
|
|
ok "Installed cavekit to $BIN_DIR/cavekit"
|
|
else
|
|
info "Need sudo to install cavekit to $BIN_DIR"
|
|
sudo ln -sf "$INSTALL_DIR/scripts/cavekit" "$BIN_DIR/cavekit"
|
|
ok "Installed cavekit to $BIN_DIR/cavekit"
|
|
fi
|
|
|
|
# ─── Done ───────────────────────────────────────────────────────────────────
|
|
|
|
printf "\n${B}${GR}Installed!${R}\n\n"
|
|
|
|
printf " ${B}Terminal:${R}\n"
|
|
printf " cavekit --monitor Pick build sites and launch agents\n"
|
|
printf " cavekit --monitor --expanded One tmux window per build site\n"
|
|
printf " cavekit --status Show build site progress\n"
|
|
printf " cavekit --analytics Show loop trends\n"
|
|
printf " cavekit --kill Stop sessions\n"
|
|
printf "\n"
|
|
printf " ${B}Claude:${R}\n"
|
|
printf " /ck:sketch Draft kits\n"
|
|
printf " /ck:map Generate build site\n"
|
|
printf " /ck:make Build from kits (inline, sequential, safe default)\n"
|
|
printf " /ck:make-parallel Opt-in: parallel subagents in isolated worktrees\n"
|
|
printf " /ck:check Inspect the build\n"
|
|
printf " /ck:review Audit branch end-to-end\n"
|
|
printf " /ck:status Check build progress\n"
|
|
printf " /ck:ship <feature> One-shot sketch → map → make → check\n"
|
|
printf "\n"
|
|
printf " ${B}Codex:${R}\n"
|
|
printf " Synced local plugin via ~/plugins/ck and ~/.agents/plugins/marketplace.json\n"
|
|
printf " Linked prompts into ~/.codex/prompts (for /prompts:ck-... commands)\n"
|
|
printf "\n"
|
|
printf " Restart Claude Code and Codex to load the plugin changes.\n\n"
|