Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .claude/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
## Plugins (v0.5.0+)

- [ ] **Antigravity + superpowers**: confirm whether `antigravity extensions install <url>` is a real command. Replace manual hint with headless install if confirmed.
- [ ] gstack `./setup` — confirm non-interactive behaviour on fresh box (`--yes`-style flag?). Currently we assume it runs cleanly without prompts.
- [ ] GSD: legacy npm package conflict check (`get-shit-done-cc`, `get-shit-done-redux`) — auto-uninstall in 09-plugins.sh if found.
- [ ] Superpowers OpenCode install is "fetch instructions" — investigate whether OpenCode has a headless prompt API to drive it programmatically.
- [ ] Plugin verification: after install, run a sanity check (e.g. `claude -p "/plugin list"` and grep for the installed names).

Expand Down
21 changes: 10 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fully configured, in a single command:

| Profile | What you get |
|--------------|-------------------------------------------------------------------------------------------------------|
| `cli-bundle` | Claude Code + OpenAI Codex + Google Antigravity + Cursor + **OpenCode** CLIs (any combination) |
| `cli-bundle` | Claude Code + OpenAI Codex + Google Antigravity + Cursor + **OpenCode** + **OpenViking** CLIs (any combination) |
| `openclaw` | [OpenClaw](https://github.com/openclaw/openclaw) — local agent gateway on port `18789` |
| `hermes` | [Hermes Agent](https://github.com/NousResearch/hermes-agent) (Nous Research, Python+uv) |
| `paperclip` | [Paperclip](https://github.com/paperclipai/paperclip) — Node API + embedded Postgres :3100 |
Expand All @@ -34,7 +34,7 @@ Plus, on every profile:
`cli-bundle` additionally bundles:

- **MCP servers** for Claude (Context7, Linear, Slack, GitHub, Supabase, Sentry, Notion, Playwright, Filesystem, Obsidian)
- **Plugins** — GSD, gstack, superpowers, OpenSpec, plus the official Anthropic marketplace (Linear/Slack/GitHub/Notion/Atlassian/Asana/Figma/Sentry/Supabase/Vercel)
- **Plugins** — superpowers, OpenSpec, plus the official Anthropic marketplace (Linear/Slack/GitHub/Notion/Atlassian/Asana/Figma/Sentry/Supabase/Vercel)
- **Obsidian vault** — shared workspace at `$OBSIDIAN_VAULT_DIR`, all CLIs read/write, optional git auto-sync
- **Dream mode** — cron-driven memory consolidation for Claude

Expand All @@ -47,14 +47,14 @@ harness/
│ ├── common.sh # mutex_check, mutex_set, load_env, banner
│ ├── base-packages.sh # install_base_packages, install_db_clients,
│ │ # install_headless_browser, install_node,
│ │ # install_pnpm, install_bun, install_uv
│ │ # install_pnpm, install_uv
│ ├── obsidian.sh # setup_vault, sync_vault_now/install/uninstall
│ └── plugins.sh # claude_headless, install_official_claude_plugin,
│ # install_claude_plugin, install_openspec,
│ # install_gstack_for, print_manual_install_hint
│ # print_manual_install_hint
└── profiles/
├── cli-bundle/ # 01-system → 02-claude → 03-codex → 04-antigravity
│ # → 05-cursor → 05b-opencode → 08-obsidian
│ # → 05-cursor → 05b-opencode → 05c-openviking → 08-obsidian
│ # → 06-mcp → 07-dream → 09-plugins
├── openclaw/ # 01-system → 02-openclaw
├── hermes/ # 01-system → 02-hermes
Expand Down Expand Up @@ -121,9 +121,9 @@ Why: these stacks compete for PATH entries, ports, systemd unit names, and
memory on small VPSes. Coexistence isn't supported. If you *really* know
better, `--force` bypasses the check.

The `cli-bundle` profile is the exception: it intentionally stacks **five**
thin CLI clients (Claude, Codex, Antigravity, Cursor, OpenCode) which have
disjoint config dirs and no port binds.
The `cli-bundle` profile is the exception: it intentionally stacks **six**
thin CLI clients (Claude, Codex, Antigravity, Cursor, OpenCode, OpenViking)
which have disjoint config dirs and no port binds.

## Pre-requisites

Expand All @@ -140,7 +140,7 @@ disjoint config dirs and no port binds.

### `cli-bundle`

Five CLIs — toggle each in `.env`. Defaults: Claude `true`, others `false`.
Six CLIs — toggle each in `.env`. Defaults: Claude `true`, others `false`.

| Toggle | CLI | Install path |
|------------------------|----------------------|-------------------------------------------------------|
Expand All @@ -149,6 +149,7 @@ Five CLIs — toggle each in `.env`. Defaults: Claude `true`, others `false`.
| `INSTALL_ANTIGRAVITY` | Google Antigravity | upstream installer (`curl … \| bash`) |
| `INSTALL_CURSOR` | Cursor agent | upstream installer (`curl … \| bash`) |
| `INSTALL_OPENCODE` | OpenCode | upstream installer (`curl -fsSL https://opencode.ai/install \| bash`) |
| `INSTALL_OPENVIKING` | OpenViking (`ov`) | `npm i -g @openviking/cli` |

Plus:

Expand Down Expand Up @@ -183,8 +184,6 @@ supports it; printed manual hint otherwise.

| Plugin | Claude | Codex | Antigravity | Cursor | OpenCode |
|------------------|----------|-------------------|----------------------------|----------------------|----------------------|
| GSD | headless | — | — | — | — |
| gstack | headless | — | — | — | headless |
| superpowers | headless | manual `/plugins` | manual (not documented) | manual `/add-plugin` | manual fetch URL |
| **OpenSpec** | universal (npm global, `/opsx:*` slash commands from any CLI) — invoked via `openspec init` per project |

Expand Down
19 changes: 0 additions & 19 deletions lib/base-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,6 @@ install_pnpm() {
pnpm -v
}

# Install Bun (JS runtime; required by gstack plugin).
install_bun() {
if command -v bun >/dev/null 2>&1; then
echo "==> bun $(bun --version) already installed"
return 0
fi
echo "==> Installing bun (bun.sh)"
curl -fsSL https://bun.sh/install | bash
export PATH="$HOME/.bun/bin:$PATH"
if ! grep -q 'BUN_INSTALL' "$HOME/.bashrc" 2>/dev/null; then
cat >> "$HOME/.bashrc" <<'EOF'

# Bun
export BUN_INSTALL="$HOME/.bun"
case ":$PATH:" in *":$BUN_INSTALL/bin:"*) ;; *) export PATH="$BUN_INSTALL/bin:$PATH";; esac
EOF
fi
}

# Install uv (Python package manager used by Hermes).
install_uv() {
if command -v uv >/dev/null 2>&1; then
Expand Down
32 changes: 2 additions & 30 deletions lib/plugins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ install_official_claude_plugin() {
}

# Install a Claude Code plugin from a marketplace.
# $1 = marketplace spec (e.g. "jnuyens/gsd-plugin" or "obra/superpowers-marketplace")
# $2 = plugin spec (e.g. "gsd@gsd-plugin" or "superpowers@claude-plugins-official")
# $1 = marketplace spec (e.g. "obra/superpowers-marketplace")
# $2 = plugin spec (e.g. "superpowers@superpowers-marketplace")
install_claude_plugin() {
local marketplace="$1"
local plugin="$2"
Expand All @@ -56,34 +56,6 @@ install_openspec() {
openspec --version 2>/dev/null || true
}

# Install gstack into a target CLI's skills dir.
# $1 = host name (claude, opencode, etc.)
install_gstack_for() {
local host="$1"
local target_dir="$HOME/.${host}/skills/gstack"
echo "==> Installing gstack for $host → $target_dir"

if [[ -d "$target_dir/.git" ]]; then
git -C "$target_dir" fetch --depth 1 origin
git -C "$target_dir" reset --hard origin/HEAD
else
git clone --single-branch --depth 1 \
https://github.com/garrytan/gstack.git "$target_dir"
fi

pushd "$target_dir" >/dev/null || return 1
if [[ -x ./setup ]]; then
if [[ "$host" == "claude" ]]; then
./setup
else
./setup --host "$host"
fi
else
echo "WARN: gstack/setup not found or not executable"
fi
popd >/dev/null || return 1
}

# Tell the operator exactly what to type into a non-headless CLI.
print_manual_install_hint() {
local cli="$1"
Expand Down
15 changes: 5 additions & 10 deletions profiles/cli-bundle/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ INSTALL_CODEX=false
INSTALL_ANTIGRAVITY=false
INSTALL_CURSOR=false
INSTALL_OPENCODE=false
INSTALL_OPENVIKING=false

# --- Claude Code Auth ---
# Optional. Leave empty to use OAuth via `claude login`. console.anthropic.com
Expand All @@ -24,6 +25,10 @@ OPENAI_API_KEY=
# --- Cursor CLI ---
# Auth via `cursor-agent login`. No key needed here.

# --- OpenViking CLI (`ov`) ---
# No CLI auth needed. Configure your server with `ov config` (interactive).
# Defaults to http://localhost:1933. https://github.com/volcengine/OpenViking

# --- Context7 (Upstash) ---
# Optional. Free without key, higher rate limit with key from context7.com
CONTEXT7_API_KEY=
Expand Down Expand Up @@ -102,19 +107,9 @@ OBSIDIAN_AUTOSYNC_SCHEDULE=*/15 * * * *
# ============================================================
# Plugins (09-plugins.sh)
# Coverage:
# GSD → Claude only
# gstack → any host listed in GSTACK_TARGETS (Claude + OpenCode supported)
# superpowers → per-CLI toggles below
# ============================================================

# Get Shit Done (Claude-only plugin marketplace)
INSTALL_GSD=false

# gstack — virtual engineering team (slash commands + skills)
INSTALL_GSTACK=false
# Space-separated list. Valid: claude opencode
GSTACK_TARGETS=claude

# OpenSpec — spec-driven development. Universal (works in any AI CLI via
# /opsx:* slash commands once invoked from a project that ran `openspec init`).
# Upstream: https://github.com/Fission-AI/OpenSpec
Expand Down
36 changes: 36 additions & 0 deletions profiles/cli-bundle/05c-openviking.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# ============================================================
# 05c-openviking.sh — Installs OpenViking CLI (`ov`).
# Package: @openviking/cli (npm). Connects to an OpenViking
# server (default http://localhost:1933).
# Upstream: https://github.com/volcengine/OpenViking
# Setup: `ov config` (interactive) to point at your server.
# ============================================================
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/.env"

if [[ ! -f "$ENV_FILE" ]]; then
echo "ERROR: $ENV_FILE not found."
exit 1
fi

# shellcheck disable=SC1090
set -a; source "$ENV_FILE"; set +a

if [[ "${INSTALL_OPENVIKING:-false}" != "true" ]]; then
echo "==> OpenViking install disabled (INSTALL_OPENVIKING != true). Skipping."
exit 0
fi

export PATH="$HOME/.npm-global/bin:$PATH"

echo "==> Installing @openviking/cli"
npm install -g @openviking/cli

ov --version 2>/dev/null || ov status 2>/dev/null || true

echo "==> OpenViking CLI installed."
echo " Configure your server with: ov config"
echo " (defaults to http://localhost:1933; override via OPENVIKING_CLI_CONFIG_FILE)"
40 changes: 2 additions & 38 deletions profiles/cli-bundle/09-plugins.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
#!/usr/bin/env bash
# ============================================================
# 09-plugins.sh — install GSD, gstack, superpowers across the CLIs.
# 09-plugins.sh — install superpowers + OpenSpec + official plugins.
#
# Coverage matrix:
# GSD → Claude only
# gstack → Claude, OpenCode (and any host listed in GSTACK_TARGETS)
# superpowers → Claude (headless), Codex/Cursor/OpenCode (manual hints),
# Antigravity (option (b) per RECOMMENDATIONS: no attempt,
# just print hint with the warning that it is not officially
Expand All @@ -26,42 +24,8 @@ set -a; source "$ENV_FILE"; set +a

# shellcheck source=../../lib/plugins.sh
source "$REPO_ROOT/lib/plugins.sh"
# shellcheck source=../../lib/base-packages.sh
source "$REPO_ROOT/lib/base-packages.sh"

export PATH="$HOME/.npm-global/bin:$HOME/.local/bin:$HOME/.opencode/bin:$HOME/.bun/bin:$PATH"

# --- GSD (Claude only) ----------------------------------------------------
if [[ "${INSTALL_GSD:-false}" == "true" ]]; then
if [[ "${INSTALL_CLAUDE:-true}" != "true" ]]; then
echo "WARN: INSTALL_GSD=true but Claude not installed — skipping."
else
install_claude_plugin "jnuyens/gsd-plugin" "gsd@gsd-plugin"
fi
fi

# --- gstack (Claude + any host in GSTACK_TARGETS) -------------------------
if [[ "${INSTALL_GSTACK:-false}" == "true" ]]; then
install_bun
TARGETS="${GSTACK_TARGETS:-claude}"
for host in $TARGETS; do
case "$host" in
claude)
if [[ "${INSTALL_CLAUDE:-true}" != "true" ]]; then
echo "WARN: gstack target 'claude' requested but INSTALL_CLAUDE != true. Skipping."
continue
fi
;;
opencode)
if [[ "${INSTALL_OPENCODE:-false}" != "true" ]]; then
echo "WARN: gstack target 'opencode' requested but INSTALL_OPENCODE != true. Skipping."
continue
fi
;;
esac
install_gstack_for "$host"
done
fi
export PATH="$HOME/.npm-global/bin:$HOME/.local/bin:$HOME/.opencode/bin:$PATH"

# --- superpowers (multi-CLI) ----------------------------------------------
if [[ "${INSTALL_SUPERPOWERS:-false}" == "true" ]]; then
Expand Down
10 changes: 1 addition & 9 deletions profiles/cli-bundle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,22 +166,17 @@ crontab -l | grep -v obsidian-vault-sync | crontab -
rm ~/.local/bin/obsidian-vault-sync
```

## Plugins (GSD, gstack, superpowers)
## Plugins (superpowers, OpenSpec)

Opt-in plugin install handled by `09-plugins.sh`. Headless onde possível;
hint manual onde não.

| Plugin | Claude | Codex | Antigravity | Cursor | OpenCode |
|--------------|-------------------|-------------------|-----------------------------|-------------------|-------------------|
| GSD | headless | — | — | — | — |
| gstack | headless (`./setup`) | — | — | — | headless (`./setup --host opencode`) |
| superpowers | headless | manual `/plugins` | manual (não documentado) | manual `/add-plugin` | manual fetch URL |

Toggles no `.env`:
```env
INSTALL_GSD=true # Claude only
INSTALL_GSTACK=true
GSTACK_TARGETS="claude opencode" # ou só "claude"
INSTALL_SUPERPOWERS=true
SUPERPOWERS_CLAUDE=true
SUPERPOWERS_CODEX=true
Expand All @@ -195,9 +190,6 @@ Rodar isolado:
bash 09-plugins.sh
```

**Bun**: gstack precisa de Bun. `09-plugins.sh` instala via `install_bun()` se
`INSTALL_GSTACK=true`.

**Antigravity superpowers**: docs upstream não cobrem. Toggle imprime hint
manual com palpite (padrão Gemini CLI). Sem tentativa automática.

Expand Down
5 changes: 3 additions & 2 deletions profiles/cli-bundle/install.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# ============================================================
# cli-bundle/install.sh
# Installs Claude Code + Codex + Antigravity + Cursor CLIs.
# All four coexist on one host. Toggle individually in .env.
# Installs Claude Code + Codex + Antigravity + Cursor + OpenCode + OpenViking CLIs.
# All coexist on one host. Toggle individually in .env.
# ============================================================
set -euo pipefail

Expand All @@ -29,6 +29,7 @@ bash "$SCRIPT_DIR/03-codex.sh"
bash "$SCRIPT_DIR/04-antigravity.sh"
bash "$SCRIPT_DIR/05-cursor.sh"
bash "$SCRIPT_DIR/05b-opencode.sh"
bash "$SCRIPT_DIR/05c-openviking.sh"
bash "$SCRIPT_DIR/08-obsidian.sh" # vault skeleton first; MCP step below registers it
bash "$SCRIPT_DIR/06-mcp.sh"
bash "$SCRIPT_DIR/07-dream.sh"
Expand Down
Loading