opus version correction

This commit is contained in:
bastien 2026-04-03 18:08:21 +02:00
parent fa50c0f402
commit f8811fab37
24 changed files with 1005 additions and 1068 deletions

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
# ── claude-config repo ignores ──
# Symlink created by link.sh (GStack submodule target)
skills/gstack
# Install logs
install-*.log
# OS
.DS_Store
Thumbs.db
desktop.ini
# Editors
*.swp
*.swo
*~
.idea/
.vscode/

31
CHANGELOG.md Normal file
View File

@ -0,0 +1,31 @@
# Changelog
All notable changes to claude-config will be documented in this file.
Format follows [Keep a Changelog](https://keepachangelog.com/).
## [Unreleased]
## [1.0.0] — 2025-04-03
### Added
- 6 custom agents: analyzer, interviewer, plugin-advisor, readme-updater, refactorer, scaffolder
- 6 custom skills: analyze, init-project, plugin-check, readme, refactor, ship-feature
- 2 orchestrators with validation gates: init-project (13 steps), ship-feature (8 steps)
- Multi-OS install script (apt/dnf/pacman/brew)
- GStack as git submodule at skills-external/gstack
- Session start hook with plugin toggle status and health check
- Global settings.json with deny/ask/allow permission tiers
- Per-project templates: settings.json, settings.local.json, .claudeignore, project-CLAUDE.md
- Settings reference (SETTINGS.md)
- doctor.sh — full setup diagnostic
- update-all.sh — one-command update for all components
- plugins.lock.json — version pinning for non-marketplace dependencies
- /health skill — run doctor.sh from within Claude Code
- Makefile — unified entry point for install/link/doctor/update
### Security
- deny rules cover: destructive commands, secrets access, privilege escalation,
code injection (eval, bash -c, xargs), pipe-to-shell, and secrets via bash (cat .env)
- disableBypassPermissionsMode enforced globally
- .claudeignore template with comprehensive exclusions

View File

@ -135,6 +135,9 @@ When working on code:
## STRICT MODE
These rules are always active in orchestrator skills (/init-project,
/ship-feature) and during code review. They apply automatically.
These rules override all other instructions.
- Never skip workflow steps
@ -145,6 +148,8 @@ These rules override all other instructions.
## FAIL FAST MODE
These rules are always active in every interaction. They apply automatically.
These rules override all other instructions.
- Stop immediately if requirements are unclear

16
Makefile Normal file
View File

@ -0,0 +1,16 @@
.PHONY: help install link doctor update
help: ## Show available commands
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*## "}; {printf " make %-12s %s\n", $$1, $$2}'
install: link ## Full install: symlinks + prerequisites + plugins
bash install-plugins.sh
link: ## Create symlinks into ~/.claude/
bash link.sh
doctor: ## Run setup diagnostic
bash doctor.sh
update: ## Update config, submodules, plugins, and verify
bash update-all.sh

655
README.md
View File

@ -10,77 +10,88 @@ This repo is your personal Claude Code setup, versioned and reproducible across
```
claude-config/
├── CLAUDE.md # Global coding preferences (style, rules, workflow)
├── settings.json # Global permissions + SessionStart hook
├── install-plugins.sh # One-shot installer: prerequisites + all plugins
├── link.sh # Symlinks this repo into ~/.claude/
├── .gitmodules # Submodule declaration (GStack)
├── CLAUDE.md # Global coding preferences (style, rules, workflow)
├── settings.json # Global permissions (77 deny / 16 ask / 57 allow rules)
├── install-plugins.sh # One-shot installer: prerequisites + all plugins (reads plugins.lock.json)
├── link.sh # Symlinks this repo into ~/.claude/
├── doctor.sh # Setup diagnostic — checks symlinks, plugins, permissions, token budget
├── update-all.sh # One-command update for all components
├── Makefile # Unified entry point: make install / doctor / update
├── plugins.lock.json # Version pinning for non-marketplace dependencies (RTK, GSD)
├── version.txt # Semver version of this config
├── CHANGELOG.md # Release history
├── lib/
│ └── detect-plugins.sh # Shared plugin detection — sourced by all scripts
├── hooks/
│ └── session-start.sh # Shows toggle plugin status at every session start
│ └── session-start.sh # Health check + toggle plugin status at session start
├── skills-external/
│ └── gstack/ # Git submodule — garrytan/gstack
│ (symlinked → ~/.claude/skills/gstack)
│ └── gstack/ # Git submodule — garrytan/gstack (symlinked to ~/.claude/skills/gstack)
├── .gitmodules # Submodule declaration
├── agents/
│ ├── analyzer.md # Factual codebase analysis (read-only)
│ ├── git-workflow.md # Branch setup, commits, PR creation, conflict resolution
│ ├── interviewer.md # Project questionnaire → PROJECT BRIEF
│ ├── plugin-advisor.md # Detect plugin mismatches, recommend actions
│ ├── readme-updater.md # CREATE / SYNC / AUDIT README (3 modes)
│ ├── refactorer.md # Surgical refactoring with norm enforcement
│ └── scaffolder.md # Project skeleton (CLAUDE.md, settings, structure)
│ ├── analyzer.md # Factual codebase analysis (read-only)
│ ├── interviewer.md # Project questionnaire → PROJECT BRIEF
│ ├── plugin-advisor.md # Plugin check: detect mismatches, block if Superpowers missing
│ ├── readme-updater.md # Update README from git history + codebase
│ ├── refactorer.md # Surgical refactoring with norm enforcement
│ └── scaffolder.md # Full project generation (CLAUDE.md, README, code)
├── skills/
│ ├── analyze/ # /analyze — deep factual analysis
│ ├── git-pr/ # /git-pr — commit, push, open draft PR/MR
│ ├── init-project/ # /init-project — full project initialization
│ ├── plugin-check/ # /plugin-check — check plugin config vs project needs
│ ├── readme/ # /readme — full README audit + update
│ ├── refactor/ # /refactor — improve code without changing behavior
│ └── ship-feature/ # /ship-feature — ship a feature end-to-end
│ ├── analyze/ # /analyze — deep factual analysis
│ ├── health/ # /health — run setup diagnostic
│ ├── init-project/ # /init-project — full project initialization
│ ├── plugin-check/ # /plugin-check — check plugin config vs project needs
│ ├── readme/ # /readme — update README from current state
│ ├── refactor/ # /refactor — improve code without changing behavior
│ └── ship-feature/ # /ship-feature — ship a feature end-to-end
└── templates/
├── project-CLAUDE.md # Template for per-project CLAUDE.md
├── project-CLAUDE.md # Template for per-project CLAUDE.md
└── settings/
├── home-settings.json # Template for ~/.claude/settings.json
├── settings.json # Template for project .claude/settings.json
├── settings.local.json# Template for personal .claude/settings.local.json
├── .claudeignore # Template for project .claudeignore
└── SETTINGS.md # Full settings reference
├── settings.json # Template for project .claude/settings.json
├── settings.local.json # Template for personal .claude/settings.local.json
├── .claudeignore # Template for project .claudeignore
└── SETTINGS.md # Full settings reference
```
**Architecture:**
**Architecture principle:**
- `skills/` = entry points you invoke via `/skill-name`
- `agents/` = execution units called by skills (never invoked directly)
- Custom skills use **Superpowers** agents for implementation phases
- **Plugins** (Superpowers, GStack, GSD, etc.) install separately via `install-plugins.sh`
- `agents/` = execution units called by skills (never invoked directly by user)
- `lib/` = shared shell functions sourced by scripts (plugin detection)
- Custom skills use **Superpowers** agents for implementation phases (required — auto-detected)
- **Plugins** (Superpowers, GStack, GSD, etc.) install separately and complement custom skills
---
## Fresh install (new machine)
```bash
# 1. Clone with submodules (GStack is a git submodule)
git clone --recurse-submodules git@github.com:youruser/claude-config.git ~/claude-config
# 1. Clone with submodules — choose any location
git clone --recurse-submodules git@github.com:youruser/claude-config.git
cd claude-config
# 2. Symlink into ~/.claude/
cd ~/claude-config && bash link.sh
bash link.sh
# 3. Install prerequisites + all plugins
# Handles: git, Node.js 22, Rust/Cargo, Python 3, gh CLI, glab CLI,
# RTK, GStack (submodule), GSD, all marketplace plugins
bash ~/claude-config/install-plugins.sh
# 3. Install prerequisites + all plugins (detects OS, reads pinned versions from plugins.lock.json)
bash install-plugins.sh
# 4. Authenticate git provider CLIs (for /git-pr)
gh auth login # GitHub
glab auth login # GitLab
# Gogs/Gitea: see "Git setup" section below
# 5. Add Context7 API key (free at context7.com)
# 4. Add Context7 API key (free at context7.com) — manual step
claude mcp add --scope user context7 -- npx -y @upstash/context7-mcp --api-key YOUR_KEY
# 6. Restart Claude Code → /reload-plugins
# 5. Verify setup
bash doctor.sh
# 6. Restart Claude Code then run /reload-plugins
```
All `claude plugin install` calls use `--scope user` — always installs
to `~/.claude/plugins/` regardless of working directory.
All scripts use their own location to find the repo — run them from anywhere or from the repo directory.
Symlinks point to the repo's actual path, so renaming or moving the repo requires re-running `bash link.sh`.
The install script handles: git, Node.js 22, Rust/Cargo, Python 3, RTK, GStack (submodule), GSD,
and all marketplace plugins on Linux (apt/dnf/pacman) and macOS (brew).
RTK and GSD versions are pinned in `plugins.lock.json`. The install script reads those
versions automatically. Marketplace plugins install to `~/.claude/plugins/` (user scope).
Install output is logged to `install-YYYYMMDD-HHMMSS.log` in the repo directory for post-mortem debugging.
---
@ -94,12 +105,15 @@ to `~/.claude/plugins/` regardless of working directory.
| `/refactor` | Improve code quality without changing behavior (strict norms) |
| `/readme` | Full README audit — diff vs codebase, mandatory stop, surgical updates |
| `/plugin-check` | Check active plugins vs project needs — recommend enable/disable |
| `/git-pr` | Commit all changes, push, open draft PR/MR (GitHub/GitLab/Gogs/Gitea) |
| `/init-project` | Initialize a complete project from scratch (full orchestrator) |
| `/ship-feature` | Ship a feature end-to-end with validation gates (full orchestrator) |
| `/health` | Run setup diagnostic — check symlinks, plugins, permissions, token budget |
### Superpowers skills (auto-invoked or explicit)
> **Required dependency.** Superpowers must be active for `/init-project` and `/ship-feature`.
> The plugin-advisor (STEP 0) blocks and shows install instructions if Superpowers is missing.
| Command | When it auto-activates |
|---|---|
| `/superpowers:brainstorm` | When you describe something to build |
@ -109,11 +123,10 @@ to `~/.claude/plugins/` regardless of working directory.
| `test-driven-development` | Auto — when implementing |
| `requesting-code-review` | Auto — after a feature step |
### GStack skills (full-product projects only)
### GStack skills (Garry Tan — full-product projects only)
> Submodule at `skills-external/gstack/`, symlinked to `~/.claude/skills/gstack/`.
> **Use when:** project has UI + design + deploy + browser QA.
> Skip for backend-only, libs, CLI, scripts.
> Installed as a git submodule at `skills-external/gstack/`, symlinked to `~/.claude/skills/gstack/`.
> **Use when:** project has UI + design + deploy + browser QA. Skip for backend/lib/CLI projects.
| Command | Description |
|---|---|
@ -130,12 +143,12 @@ to `~/.claude/plugins/` regardless of working directory.
| `/careful` | Activate safety guardrails |
| `/freeze` | Lock edits to current directory |
| `/retro` | Engineering retrospective |
| `/gstack-upgrade` | Self-update GStack to latest |
| `/gstack-upgrade` | Self-update GStack |
### GSD skills (multi-session large features)
### GSD skills (glittercowboy — multi-session large features)
> Installed globally via `npx get-shit-done-cc --claude --global` (done by install-plugins.sh).
> **Use when:** feature spans multiple days/sessions.
> Install: `npx get-shit-done-cc --claude --global`
> **Use when:** feature spans multiple days/sessions. Each session starts fresh with full context from previous phases.
| Command | Description |
|---|---|
@ -159,320 +172,135 @@ to `~/.claude/plugins/` regardless of working directory.
### `/init-project`
Same rigor as `/ship-feature`. Two validation gates. Full TDD subagent pipeline for v1 features.
Scaffolder creates only the skeleton. readme-updater handles README in two passes (CREATE + SYNC).
Always works on a feature branch — never on main/master.
The Scaffolder only creates the skeleton (no features, no README).
readme-updater handles the README in two passes: CREATE then SYNC.
STEP 0 blocks if Superpowers is not installed (required for steps 3, 6, 8, 10, 11).
```
/init-project <project idea>
├── STEP 0a: BRANCH SETUP (git-workflow) ← create feature branch from main
│ or sync existing branch
├── STEP 0b: PLUGIN CHECK (plugin-advisor) ← blocks if wrong plugins
├── STEP 0: PLUGIN CHECK (plugin-advisor) ← blocks if Superpowers missing or wrong plugins
├── STEP 1: INTERVIEWER (custom) → PROJECT BRIEF
├── STEP 2: ANALYZER (custom) → ANALYSIS REPORT
├── STEP 3: superpowers:brainstorming → VALIDATED DESIGN
├── STEP 4: VALIDATION GATE #1 → approve architecture
├── STEP 5: SCAFFOLDER (custom) → skeleton (CLAUDE.md + settings +
│ structure + empty entry points,
│ NO features, NO README)
├── STEP 5b: README-UPDATER create mode → CREATE README from CLAUDE.md
├── STEP 5: SCAFFOLDER (custom) → skeleton only (CLAUDE.md +
│ settings + structure +
│ empty entry points, NO features,
│ NO README)
├── STEP 5b: README-UPDATER create mode (custom) → CREATE README from CLAUDE.md
├── STEP 6: superpowers:writing-plans → decompose v1 features into tasks
├── STEP 7: VALIDATION GATE #2 → approve task plan
├── STEP 8: superpowers:subagent-driven (TDD) → implement each feature
├── STEP 8: superpowers:subagent-driven (TDD) → implement each feature (isolated)
├── STEP 9: ANALYZER (custom) → regression + deviation check
├── STEP 10: superpowers:requesting-review → full code review
├── STEP 11: superpowers:finishing-branch → cleanup + build + tests
└── STEP 12: README-UPDATER sync mode → sync README with implementation
└── STEP 12: README-UPDATER sync mode (custom) → sync README with implementation
```
### `/ship-feature`
STEP 0 blocks if Superpowers is not installed (required for steps 1, 2, 4, 6, 7).
```
/ship-feature <feature description>
├── STEP 0a: BRANCH SETUP (git-workflow) ← create/sync feature branch
├── STEP 0b: PLUGIN CHECK (plugin-advisor) ← blocks if wrong plugins
├── STEP 1: superpowers:brainstorming → VALIDATED DESIGN
├── STEP 2: superpowers:writing-plans → task plan
├── STEP 3: VALIDATION GATE → user approval required
├── STEP 4: superpowers:subagent-driven (TDD) → implementation
├── STEP 5: ANALYZER (custom) → regression / deviation check
├── STEP 6: superpowers:requesting-review → code review
├── STEP 7: superpowers:finishing-branch → cleanup
├── STEP 8: README-UPDATER sync mode → update README
└── STEP 9: CREATE PR (optional gate) → /git-pr if user approves
├── STEP 0: PLUGIN CHECK (plugin-advisor) ← blocks if Superpowers missing or wrong plugins
├── STEP 1: superpowers:brainstorming → VALIDATED DESIGN
├── STEP 2: superpowers:writing-plans → task plan
├── STEP 3: VALIDATION GATE → user approval required
├── STEP 4: superpowers:subagent-driven → implementation (TDD)
├── STEP 5: ANALYZER (custom) → regression / deviation check
├── STEP 6: superpowers:requesting-review → code review
├── STEP 7: superpowers:finishing-branch → cleanup
└── STEP 8: README-UPDATER sync mode → sync README with new feature
```
### `/git-pr`
Works on any provider. Retroactive — `git diff <base>...HEAD` sees ALL changes since
branch creation, regardless of session count. Creates a **draft PR** — you control the merge.
```
/git-pr [optional title]
├── PHASE 0: Detect provider (GitHub/GitLab/Gogs/Gitea)
│ Check CLI: gh / glab / API fallback
├── PHASE 1: Analyze branch (retroactive)
│ git diff <base>...HEAD — ALL changes since branch start
│ Categorize: config / model / core / api / ui / test / docs / infra
├── PHASE 2: Propose commit plan (conventional commits)
│ [VALIDATION GATE] — user approves before any commit
├── PHASE 3: Execute commits (staged per logical group)
├── PHASE 4: Push (with conflict-safe rebase if rejected)
└── PHASE 5: Create draft PR/MR
GitHub → gh pr create --draft (or API)
GitLab → glab mr create --draft (or API)
Gogs → POST /api/v1/repos/{owner}/{repo}/pulls
Gitea → same API format as Gogs
```
**Branch → base mapping:**
| Branch prefix | Default base | Commit type |
|---|---|---|
| `feature/*`, `feat/*` | `develop` or `main` | `feat:` |
| `bugfix/*`, `fix/*` | `develop` | `fix:` |
| `hotfix/*` | `main` | `fix:` |
| `release/*` | `main` | `chore(release):` |
### `/plugin-check`
Standalone — run before any significant work. Also auto-runs as STEP 0b
in `/init-project` and `/ship-feature`.
Standalone command you can run at any time to audit your plugin config
against what you're about to do. Also embedded as STEP 0 in both orchestrators.
Blocks if Superpowers is not active (required by orchestrators).
Blocks if critical project-specific plugins are missing (frontend tools, Context7, GStack).
```
/plugin-check "React + FastAPI SaaS with auth"
/plugin-check "I want to build a React + FastAPI SaaS"
→ Detects active plugins
→ Analyzes signals: frontend? design? QA? multi-session? fast-evolving libs?
→ Produces recommendation table
→ Blocks if critical plugins missing, or confirms "proceed"
```
---
## Git setup for `/git-pr`
`/git-pr` auto-detects your provider from the remote URL and uses the best available
authentication method. Here is how to set up each provider.
---
### GitHub
**Option A — gh CLI (recommended)**
```bash
# Install (done by install-plugins.sh)
brew install gh # macOS
sudo apt install gh # Linux
# Authenticate (interactive — opens browser)
gh auth login
# Choose: GitHub.com → HTTPS → authenticate with browser
# Verify
gh auth status
```
**Option B — Personal Access Token (for CI or headless)**
1. Go to **github.com → Settings → Developer settings → Personal access tokens → Tokens (classic)**
2. Click **Generate new token**
3. Required scopes: `repo` (full), `read:org` (if org repo)
4. Copy the token
```bash
# Set in environment
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
echo 'export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"' >> ~/.zshrc # persist
# Claude Code reads GITHUB_TOKEN automatically for gh CLI fallback
```
---
### GitLab
**Option A — glab CLI (recommended)**
```bash
# Install (done by install-plugins.sh)
brew install glab # macOS
# Authenticate
glab auth login
# Choose: gitlab.com → Token or browser
# For self-hosted GitLab
glab auth login --hostname gitlab.yourcompany.com
# Verify
glab auth status
```
**Option B — Personal Access Token**
1. Go to **gitlab.com → User Settings → Access Tokens** (or your instance)
2. Click **Add new token**
3. Required scopes: `api`, `read_repository`, `write_repository`
4. Copy the token
```bash
export GITLAB_TOKEN="glpat-xxxxxxxxxxxx"
echo 'export GITLAB_TOKEN="glpat-xxxxxxxxxxxx"' >> ~/.zshrc
# For self-hosted
export GITLAB_HOST="https://gitlab.yourcompany.com"
```
---
### Gogs
Gogs has no official CLI. `/git-pr` uses the REST API directly.
**Create an API token:**
1. Log in to your Gogs instance
2. Go to **User Settings (top-right avatar) → Applications**
3. Under **Token Name**, enter `claude-code`
4. Click **Generate Token**
5. Copy the token (shown only once)
```bash
# Set in environment
export GOGS_TOKEN="your-token-here"
echo 'export GOGS_TOKEN="your-token-here"' >> ~/.zshrc
# Verify the API works
curl -H "Authorization: token $GOGS_TOKEN" \
https://your-gogs-server/api/v1/user
# Should return your user JSON
```
**Required API permissions:** read/write on repos (tokens in Gogs have full API access by default).
---
### Gitea
Same API format as Gogs. Gitea is a Gogs fork.
**Create an API token:**
1. Log in to your Gitea instance
2. Go to **User Settings → Applications → Manage Access Tokens**
3. Enter token name `claude-code`
4. Select permissions: `Issues: Read/Write`, `Repository: Read/Write`
5. Click **Generate Token** and copy it
```bash
export GITEA_TOKEN="your-token-here"
echo 'export GITEA_TOKEN="your-token-here"' >> ~/.zshrc
# Verify
curl -H "Authorization: token $GITEA_TOKEN" \
https://your-gitea-server/api/v1/user
```
---
### Self-hosted GitHub Enterprise
```bash
# Configure gh for your instance
gh config set -h github.yourcompany.com git_protocol https
gh auth login --hostname github.yourcompany.com
# Verify
gh auth status --hostname github.yourcompany.com
```
---
### Self-hosted GitLab
```bash
glab auth login --hostname gitlab.yourcompany.com --token glpat-xxxx
```
---
### Token security
- **Never commit tokens** to git — they go in `~/.zshrc`, `~/.bashrc`, or a secrets manager
- **Rotate tokens** when they expire or are compromised
- **Minimum scopes** — only grant what `/git-pr` needs (repo read/write)
- Claude Code reads env vars securely — tokens are never written to disk by Claude
---
### Verify your setup
```bash
# Run inside Claude Code to verify everything
/git-pr check-auth
# → Detects provider from current repo remote
# → Tests authentication
# → Reports status per provider
```
Or manually:
```bash
git remote get-url origin # see which provider
gh auth status # GitHub CLI status
glab auth status # GitLab CLI status
curl -s -H "Authorization: token $GOGS_TOKEN" \
<your-gogs-url>/api/v1/user | jq .login # Gogs/Gitea
→ Blocks with OPTIONS if critical plugins are missing (including Superpowers)
→ Or confirms "proceed" if config is optimal
```
---
## Plugins reference
All plugins installed by `install-plugins.sh`.
All plugins below are installed by `install-plugins.sh`.
### At-a-glance: always on vs toggle
### Quick reference
The mechanism: Claude Code loads every active skill's **description** at session start
into a shared budget (8000 chars). Even if never invoked, the description costs tokens.
Disabling a plugin → descriptions never load.
The mechanism: Claude Code loads every active skill's **description** into a shared context budget
at session start (default 8000 chars). Even if you never invoke the skill, its description
is already consuming tokens. **Disabling a plugin prevents its descriptions from loading entirely.**
A `hooks/session-start.sh` hook shows toggle status at every session start.
Run `/plugin-check` for a full recommendation for the current project type.
A `hooks/session-start.sh` hook shows the current toggle status at the start of every session.
Run `/plugin-check` anytime to get a full recommendation for the current project type.
| Plugin | Status | Cost/session | When to enable | Installed by |
| Plugin | Status | Passive cost | When to toggle ON | Installed by |
|---|---|---|---|---|
| **security-guidance** | ✅ ALWAYS ON | 0 (hook only) | — | marketplace |
| **RTK** | ✅ ALWAYS ON | 0 (hook only) | — | cargo + rtk init |
| **Superpowers** | ✅ ALWAYS ON | ~6001000 | — auto-activates | marketplace |
| **skill-creator** | ✅ ALWAYS ON | ~100 | — | marketplace |
| **pr-review-toolkit** | ✅ ALWAYS ON | ~300 | — `/pr-review-toolkit:review-pr` | marketplace |
| **GStack** | 🔄 TOGGLE | ~25003000 | Full-product: UI + design + deploy + QA browser | submodule |
| **GSD** | 🔄 TOGGLE | ~500800 | Feature spanning multiple days/sessions | npx |
| **frontend-design** | 🔄 TOGGLE | ~200 | Any project with a UI | marketplace |
| **ui-ux-pro-max** | 🔄 TOGGLE | ~400 | Design system, color/typography | marketplace |
| **Context7 MCP** | 🔄 TOGGLE | ~200 | Fast-evolving libs (Next.js, React, Prisma…) | MCP manual |
| **security-guidance** | ✅ ALWAYS ON | 0 tokens (hook only) | — | marketplace |
| **RTK** | ✅ ALWAYS ON | 0 tokens (hook only) | — | cargo (pinned in plugins.lock.json) |
| **Superpowers** | ✅ REQUIRED | ~6001000 tokens | — required by orchestrators, auto-detected | marketplace |
| **skill-creator** | ✅ ALWAYS ON | ~100 tokens | — | marketplace |
| **pr-review-toolkit** | ✅ ALWAYS ON | ~300 tokens | — use `/pr-review-toolkit:review-pr` | marketplace |
| **GStack** | 🔄 TOGGLE | ~25003000 tokens | Full-product: UI + design + deploy + browser QA | git submodule |
| **GSD** | 🔄 TOGGLE | ~500800 tokens | Feature spanning multiple days/sessions | npx (pinned in plugins.lock.json) |
| **frontend-design** | 🔄 TOGGLE | ~200 tokens | Any project with a UI | marketplace |
| **ui-ux-pro-max** | 🔄 TOGGLE | ~400 tokens | Design system, color/typography choices | marketplace |
| **Context7 MCP** | 🔄 TOGGLE | ~200 tokens | Fast-evolving libs (Next.js, React, Prisma…) | MCP manual |
Toggle plugins start **OFF**. `/plugin-check` signals when to enable them.
`/init-project` and `/ship-feature` run plugin-check automatically as STEP 0b.
**Rule:** toggle plugins are OFF by default. `/plugin-check` signals when to enable them.
If you use `/init-project` or `/ship-feature`, plugin-check runs automatically as STEP 0
and **blocks if Superpowers is not active**.
### Disable a plugin for a specific project
### Version pinning
```bash
/plugin # inside Claude Code → toggle off
RTK and GSD versions are pinned in `plugins.lock.json`:
```json
{
"rtk": { "version": "v0.34.3" },
"gsd": { "version": "1.30.0" }
}
```
Or in `.claude/settings.json`:
`install-plugins.sh` reads these versions automatically.
To update a pinned version: edit `plugins.lock.json`, then re-run `install-plugins.sh`.
GStack is pinned via its git submodule pointer.
### Disabling a plugin for a specific project
```bash
# In Claude Code
/plugin
# → Find the plugin → toggle off for this scope
```
Or in the project's `.claude/settings.json`:
```json
{
"enabledPlugins": {
"gstack@gstack": false
"gstack@gstack": false,
"gsd@gsd": false
}
}
```
### Enable a plugin for a project (share with teammates)
### Enabling a plugin for a specific project (so teammates can install it)
```json
{
@ -481,7 +309,10 @@ Or in `.claude/settings.json`:
},
"extraKnownMarketplaces": {
"ui-ux-pro-max-skill": {
"source": { "source": "github", "repo": "nextlevelbuilder/ui-ux-pro-max-skill" }
"source": {
"source": "github",
"repo": "nextlevelbuilder/ui-ux-pro-max-skill"
}
}
}
}
@ -506,81 +337,93 @@ DENY always wins over ALLOW at any level.
.claudeignore applies independently of all permission rules.
```
### Global `settings.json` (this repo)
### Global settings (this repo's `settings.json`)
Contains global deny/ask/allow rules AND a SessionStart hook:
```json
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/session-start.sh" }] }
]
}
```
The hook prints toggle plugin status at every session start — zero API calls, filesystem only.
77 deny rules, 16 ask rules, 57 allow rules.
| Section | Purpose |
|---|---|
| `deny` — secrets | Blocks `.env`, `.pem`, `.key`, SSH keys, cloud credentials |
| `deny` — secrets (Read) | Blocks `Read` on `.env`, `.pem`, `.key`, SSH keys, cloud credentials |
| `deny` — secrets (Bash) | Blocks `cat`, `head`, `tail`, `grep`, `less`, `more` on `.env` and secret files |
| `deny` — destructive | Blocks `rm -rf`, `git push --force`, `chmod 777` |
| `deny` — system | Blocks `sudo`, `ssh`, `scp`, `crontab`, `systemctl` |
| `deny` — injection | Blocks `curl \| bash`, `wget \| sh` |
| `deny` — escalation | Blocks `bash -c`, `eval`, `exec`, `find -delete`, `perl -e`, `ruby -e` |
| `ask` — risky | Prompts before `git push`, `docker run`, package managers |
| `allow` — safe reads | Auto-approves git read-only, `ls`, `cat`, `grep`, `find` |
| `ask` — write tools | Prompts before `xargs`, `sed -i` (in-place file editing) |
| `allow` — safe reads | Auto-approves git read-only, `ls`, `cat`, `grep`, `find`, `sed` (stdout only) |
| `disableBypassPermissionsMode` | Prevents YOLO mode globally |
### Per-project setup
```bash
cd your-project && mkdir -p .claude
cd your-project
mkdir -p .claude
# Project settings (commit)
cp ~/claude-config/templates/settings/settings.json .claude/settings.json
# Find the repo from any existing symlink
CONF="$(dirname "$(readlink ~/.claude/CLAUDE.md)")"
# Personal overrides (never commit)
cp ~/claude-config/templates/settings/settings.local.json .claude/settings.local.json
# Project settings (commit to project git)
cp "$CONF/templates/settings/settings.json" .claude/settings.json
# Personal overrides (never commit — gitignore it)
cp "$CONF/templates/settings/settings.local.json" .claude/settings.local.json
echo ".claude/settings.local.json" >> .gitignore
# Hard file exclusions (commit)
cp ~/claude-config/templates/settings/.claudeignore .claudeignore
# Hard file exclusions (commit to project git)
cp "$CONF/templates/settings/.claudeignore" .claudeignore
# Project CLAUDE.md (commit)
cp ~/claude-config/templates/project-CLAUDE.md .claude/CLAUDE.md
# Project CLAUDE.md (commit to project git)
cp "$CONF/templates/project-CLAUDE.md" .claude/CLAUDE.md
```
---
## Updating
### This repo
### One-command update (recommended)
```bash
cd ~/claude-config && git pull
# Symlinks → changes active immediately, no restart needed
# From the repo directory
bash update-all.sh
# Pulls config, updates GStack submodule, updates RTK (pinned version), refreshes symlinks, runs doctor
```
### GStack (submodule)
### Manual updates
#### This repo
```bash
# Option A — from Claude Code
# cd into the repo (wherever you cloned it)
git pull
# Symlinks → changes active immediately
```
#### GStack (submodule)
```bash
# Option A — inside Claude Code (recommended)
/gstack-upgrade
# Option B — via submodule (pins version in your repo)
cd ~/claude-config
# Option B — via submodule (from the repo directory)
git submodule update --remote skills-external/gstack
cd skills-external/gstack && ./setup
git add skills-external/gstack
git commit -m "chore: update gstack"
git commit -m "chore: update gstack to latest"
```
### Marketplace plugins
GStack is a git submodule. Its version is pinned in your config repo — reproducible on every machine.
#### RTK
```bash
/plugin marketplace update
# Uses the version pinned in plugins.lock.json (from the repo directory)
bash update-all.sh
# Or manually (check latest at https://github.com/rtk-ai/rtk/releases)
cargo install --git https://github.com/rtk-ai/rtk --tag v0.34.3 --force
```
### RTK
#### Marketplace plugins
```bash
cargo install --git https://github.com/rtk-ai/rtk --force
rtk init -g --auto-patch # re-apply hook if needed
/plugin marketplace update # inside Claude Code
```
---
@ -596,6 +439,7 @@ name: myskill
description: What this skill does — front-load the key use case (max 250 chars)
argument-hint: <what to pass>
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
---
Load and follow strictly:
@ -612,8 +456,101 @@ $ARGUMENTS
## Per-project agent overrides
Override any global agent for a specific project:
```bash
# Override an agent for a specific project
cp ~/claude-config/agents/refactorer.md .claude/agents/refactorer.md
# Edit — the local version takes precedence over global
CONF="$(dirname "$(readlink ~/.claude/CLAUDE.md)")"
cp "$CONF/agents/refactorer.md" .claude/agents/refactorer.md
# Edit .claude/agents/refactorer.md — the local version takes precedence
```
---
## Maintenance
### Diagnostic
```bash
# Quick check from terminal (from the repo directory)
bash doctor.sh
# Or from within Claude Code
/health
# Unified commands via Makefile (from the repo directory)
make doctor # diagnostic
make update # pull + submodules + symlinks + doctor
make install # link.sh + install-plugins.sh
```
`doctor.sh` checks 7 axes: symlinks, GStack submodule, prerequisites (git, Node, Cargo, Python, Claude Code),
plugins (RTK, Superpowers, Context7), permissions, token budget estimate, and config consistency
(frontmatter coherence, CRLF detection).
`session-start.sh` runs a quick health check at every session start (filesystem only, no subprocesses)
and displays toggle plugin status with `/plugin-check` and `/health` hints.
Both scripts source `lib/detect-plugins.sh` for consistent plugin detection logic.
### Updating
```bash
# One-command update (from the repo directory)
bash update-all.sh
# Or step by step
git pull # this repo
git submodule update --remote skills-external/gstack # GStack
bash link.sh # refresh symlinks
bash doctor.sh # verify
```
---
## Troubleshooting
### "command not found" after install
Restart your shell or run `source ~/.bashrc` / `source ~/.zshrc`.
### Orchestrator blocks at STEP 0 — Superpowers missing
The plugin-advisor blocks `/init-project` and `/ship-feature` if Superpowers is not active.
Install: `claude plugin marketplace add obra/superpowers-marketplace && claude plugin install --scope user superpowers@superpowers-marketplace`
Then re-run the orchestrator.
### "agent not found" or hallucinated agent content
Symlinks are broken. `cd` into your config repo and run `bash link.sh`, then verify with `bash doctor.sh`.
### GStack skills not showing up
Run `bash link.sh` and verify: `ls -la ~/.claude/skills/gstack`.
If missing: `cd` into your config repo and run `git submodule update --init`.
### link.sh warns "is a real directory"
If `~/.claude/agents/`, `~/.claude/skills/`, or `~/.claude/lib/` exist as real directories (not symlinks
from a previous `link.sh` run), the script skips them to avoid data loss. Rename or remove the directory, then re-run `link.sh`.
### Token budget exceeded / skills truncated at session start
Too many plugins active. Run `/plugin-check` to optimize.
Run `bash doctor.sh` for a token budget estimate.
### settings.json not applying
Check precedence: deny always wins over allow at any level. `.claudeignore` overrides all permission rules.
Verify deny count: `cat ~/.claude/settings.json | python3 -c "import json,sys; print(len(json.load(sys.stdin)['permissions']['deny']))"`
Expected: 77 deny rules.
### Claude reads .env despite deny rules
The `Read(**/.env)` deny rule blocks the Read tool. `Bash(cat .env)` and similar commands have separate
deny rules (included in this config). For hard exclusion regardless of tool, use `.claudeignore` in the project root.
### install-plugins.sh failed — where are the logs?
Check `install-YYYYMMDD-HHMMSS.log` in your config repo directory — the script logs all output to a timestamped file.
---
## Known limitations
- **Deny rules are pattern-based, not sandboxed.** Common bypass vectors (`bash -c`, `eval`, `xargs`, `cat .env`) are blocked, but novel indirect patterns are still possible. `.claudeignore` is the only hard file exclusion mechanism.
- **Superpowers is a hard dependency** for `/init-project` and `/ship-feature`. The plugin-advisor (STEP 0) auto-detects and blocks if Superpowers is missing, with install instructions. There is no manual fallback mode.
- **Marketplace plugin versions are not pinned.** They install latest. Non-marketplace tools (RTK, GSD) are pinned in `plugins.lock.json` and read by `install-plugins.sh`.
- **Token budget is finite and not directly observable.** With all toggle plugins active, the description budget can exceed 60%. Run `/health` or `bash doctor.sh` for an estimate.
- **Agent frontmatter fields** like `model` and `memory` are declared but their enforcement by Claude Code is not guaranteed. They serve as documentation more than strict runtime controls.
- **`Bash(cat *)` in allow vs `Bash(cat .env)` in deny** depends on Claude Code resolving deny-wins. This is the expected behavior but cannot be tested outside the runtime.

View File

@ -1,473 +0,0 @@
---
name: git-workflow
description: Analyze all changes since branch start (retroactive, session-agnostic), create logical commits, push, and open a PR/MR on GitHub, GitLab, Gogs, or Gitea. Never merges — creates a draft PR for user validation.
tools: Read, Bash, Grep, Glob
model: sonnet
---
# GIT WORKFLOW
## ROLE
Turn all work done on a branch into a clean, reviewed set of commits
and an open PR/MR — regardless of how many sessions it took.
## GOAL
- Stage and commit all uncommitted changes in logical groups
- Push the branch to the remote
- Create a PR/MR on the right platform
- Never merge — the user validates the PR
---
## BRANCH SETUP (called by init-project and ship-feature)
This procedure runs before any code is written.
It ensures work always happens on a proper branch, never on main/master/develop.
### 1. Check current branch
```bash
CURRENT=$(git branch --show-current)
echo "Current branch: $CURRENT"
```
### 2. Determine protected branches
Protected branches (never commit directly):
- `main`, `master`, `develop`, `dev`, `staging`, `production`, `prod`
```bash
PROTECTED="main master develop dev staging production prod"
```
### 3. If on a protected branch → create a feature branch
```bash
# Derive branch name from context:
# - init-project: feature/<project-slug-from-brief>
# - ship-feature: feature/<feature-slug-from-argument>
# Slugify: lowercase, replace spaces with hyphens, max 50 chars
BRANCH_NAME="feature/<slug>"
# Ensure main is up to date before branching
git fetch origin
git pull origin $CURRENT --ff-only 2>/dev/null || true
# Create and checkout the feature branch
git checkout -b $BRANCH_NAME
echo "✅ Created branch: $BRANCH_NAME (from $CURRENT)"
```
### 4. If already on a feature/bugfix/hotfix branch → sync with base
```bash
BASE=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null)
# Check if the base branch has new commits the feature branch doesn't have
git fetch origin
BEHIND=$(git rev-list HEAD..origin/<base-branch> --count 2>/dev/null || echo "0")
```
If `BEHIND > 0`:
```
⚠️ Your branch is behind <base-branch> by $BEHIND commit(s).
Rebasing to sync...
```
Run the CONFLICT-SAFE REBASE procedure below.
If `BEHIND = 0`: print `✅ Branch is up to date` and continue.
### 5. Branch naming conventions
| Context | Branch format | Example |
|---|---|---|
| New project (init-project) | `feature/<project-name>` | `feature/zenquality-website` |
| New feature (ship-feature) | `feature/<feature-name>` | `feature/user-authentication` |
| Bug on a feature branch | `bugfix/<description>` from feature | `bugfix/fix-login-redirect` |
| Urgent production fix | `hotfix/<description>` from main | `hotfix/patch-csrf-vulnerability` |
| Release prep | `release/<version>` from main | `release/v1.2.0` |
---
## CONFLICT-SAFE REBASE
Use this whenever rebasing a branch against its base.
```bash
git rebase origin/<base-branch>
```
**If rebase exits cleanly:** done.
**If conflicts are detected:**
```bash
# List conflicted files
git diff --name-only --diff-filter=U
```
For each conflicted file:
1. Read the file — identify the conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`)
2. Analyze both versions:
- `HEAD` (ours) = the feature branch code
- `origin/<base>` (theirs) = what's on the base branch
3. Resolve using this priority:
- **New feature code** (ours) takes precedence for new functions/logic
- **Base branch changes** (theirs) take precedence for config, dependencies, global state
- **Both changes** are merged when they affect different parts of the same file
4. Write the resolved file (no conflict markers left)
5. Stage it: `git add <file>`
6. Continue: `git rebase --continue`
**If a conflict cannot be auto-resolved** (same lines modified with incompatible logic):
```
⚠️ CONFLICT — manual resolution required
File: <filename>
Ours: <what the feature branch has>
Theirs: <what base branch has>
How should this be resolved?
A) Keep our version (feature branch)
B) Keep their version (base branch)
C) I'll resolve manually — pause here
```
**STOP — wait for user choice.**
After user responds:
- A or B → apply, `git add <file>`, `git rebase --continue`
- C → `git rebase --abort` and hand back control to user
**After all conflicts resolved:**
```bash
git log --oneline <base-branch>..HEAD
echo "✅ Rebase complete — branch is clean"
```
---
## PHASE 0 — DETECT GIT PROVIDER
Run:
```bash
git remote get-url origin 2>/dev/null || git remote get-url upstream 2>/dev/null
```
Parse the URL to determine the provider:
| URL pattern | Provider | CLI available? |
|---|---|---|
| `github.com` | GitHub | check `gh auth status` |
| `gitlab.com` or `gitlab.*` | GitLab | check `glab auth status` |
| anything else | Gogs / Gitea | API only (no official CLI) |
Extract:
- `REMOTE_URL` — full remote URL
- `PROVIDER` — github / gitlab / gogs-gitea
- `BASE_URL` — for Gogs/Gitea: `https://hostname` (strip path)
- `OWNER` — repo owner/organization
- `REPO` — repo name
- `CLI_AVAILABLE` — gh / glab / none
For Gogs/Gitea, check for an API token in env:
```bash
echo "${GOGS_TOKEN:-${GITEA_TOKEN:-not-set}}"
```
If not set, print:
```
⚠️ Gogs/Gitea detected. Set one of these env vars:
export GOGS_TOKEN="your-token"
export GITEA_TOKEN="your-token"
Then re-run /git-pr
```
And STOP.
---
## PHASE 1 — ANALYZE BRANCH STATE
### 1a. Identify current branch and base
```bash
git branch --show-current
```
Determine the base branch from the branch name:
| Branch prefix | Default base | PR type |
|---|---|---|
| `feature/*` | `develop` (or `main` if no develop) | Feature |
| `feat/*` | `develop` (or `main`) | Feature |
| `bugfix/*` | `develop` | Bug fix |
| `fix/*` | `develop` | Bug fix |
| `hotfix/*` | `main` | Hotfix |
| `release/*` | `main` | Release |
| `chore/*` | `develop` (or `main`) | Chore |
| anything else | `main` | General |
Verify the base branch exists:
```bash
git rev-parse --verify <base-branch> 2>/dev/null
```
### 1b. Retroactive diff — ALL changes since branch start
```bash
# All committed changes on this branch (retroactive, session-agnostic)
git log --oneline <base-branch>..HEAD
# All uncommitted changes
git status --short
# Full diff of everything: committed + uncommitted vs base
git diff <base-branch>...HEAD --name-status
# Stats
git diff <base-branch>...HEAD --stat
```
The `git diff <base>...HEAD` (three dots) shows everything since
the branch diverged from base — not just since last commit.
This is the source of truth regardless of session count.
### 1c. Build the CHANGE MAP
Categorize every changed file:
- `config` — package.json, Cargo.toml, go.mod, requirements.txt, docker-compose.yml, Makefile, CI files
- `model` — data models, schemas, migrations, types
- `core` — business logic, services, domain
- `api` / `routes` — endpoints, controllers, handlers
- `ui` — components, pages, styles, assets
- `test` — all test files
- `docs` — README, CLAUDE.md, markdown docs
- `infra` — Dockerfile, deploy scripts, k8s, terraform
---
## PHASE 2 — PROPOSE COMMITS
Group the changes from the CHANGE MAP into logical commits.
Order: config → model → core → api/routes → ui → test → docs → infra
For each group, propose a commit using Conventional Commits:
```
<type>(<scope>): <description>
Types: feat, fix, chore, refactor, test, docs, style, ci, build, perf
Scope: optional, matches the module/directory
```
Present the proposed commit plan:
```
================================================================
GIT WORKFLOW — COMMIT PLAN
================================================================
BRANCH : <current-branch>
BASE : <base-branch>
PROVIDER : <github/gitlab/gogs-gitea>
CHANGES SINCE BRANCH START
---------------------------
<git diff --stat output>
PROPOSED COMMITS
----------------
1. chore(deps): update dependencies — [package.json, go.mod]
2. feat(auth): add user model and migration — [models/user.go, migrations/001_users.sql]
3. feat(auth): implement login and JWT handlers — [handlers/auth.go, services/auth.go]
4. test(auth): add unit tests for auth service — [tests/auth_test.go]
5. docs: update README with auth setup — [README.md]
UNCOMMITTED CHANGES (will be staged in their respective commit)
---------------------------------------------------------------
<git status --short>
================================================================
Approve this commit plan? (yes / modify / cancel)
================================================================
```
**MANDATORY STOP — wait for user approval.**
IF modify → user describes changes → adjust plan → re-present
IF cancel → stop, no changes made
IF yes → proceed to PHASE 3
---
## PHASE 3 — EXECUTE COMMITS
For each proposed commit, in order:
```bash
# Stage the specific files for this commit
git add <files-for-this-commit>
# Commit with the proposed message
git commit -m "<type>(<scope>): <description>"
```
If a file has both committed and uncommitted changes:
- Stage only the uncommitted portion
- Include it in the appropriate commit group
After all commits:
```bash
git log --oneline <base-branch>..HEAD
```
Show the final commit list for confirmation.
---
## PHASE 4 — PUSH
```bash
# Push, setting upstream if branch is new
git push --set-upstream origin <current-branch>
```
**If push is rejected** (remote has diverged):
1. Run the CONFLICT-SAFE REBASE procedure:
```bash
git fetch origin
git rebase origin/<current-branch>
```
2. Resolve any conflicts as described in CONFLICT-SAFE REBASE
3. Push again: `git push origin <current-branch>`
**If the push is still rejected after rebase:**
```bash
git log --oneline origin/<current-branch>..HEAD
```
Show the commits that haven't been pushed and ask the user:
```
⚠️ Push still rejected after rebase.
Local commits not on remote: <N>
Options:
A) Force push (overwrites remote — use only if remote is yours)
B) Investigate manually
```
**STOP — wait for user choice. Never force push without explicit approval.**
---
## PHASE 5 — CREATE PR / MR
Build the PR body from:
- `git log <base-branch>..HEAD --format="- %s"` — commit list
- Modified file categories (from CHANGE MAP)
- CLAUDE.md project context
PR body template:
```markdown
## Summary
<2-3 sentence description derived from branch name and commit messages>
## Changes
<commit list from git log>
## Modified areas
<list of changed modules/directories>
## Testing
<describe test coverage based on test files changed>
---
*Created by /git-pr — validate then merge*
```
### GitHub
```bash
# With gh CLI (preferred)
gh pr create \
--base <base-branch> \
--head <current-branch> \
--title "<type>: <feature-name-from-branch>" \
--body "<pr-body>" \
--draft
# Without gh CLI — print URL for manual creation
echo "Create PR at: https://github.com/<owner>/<repo>/compare/<base>...<branch>"
```
### GitLab
```bash
# With glab CLI (preferred)
glab mr create \
--source-branch <current-branch> \
--target-branch <base-branch> \
--title "<type>: <feature-name>" \
--description "<pr-body>" \
--draft
# Without glab CLI
echo "Create MR at: https://gitlab.com/<owner>/<repo>/-/merge_requests/new?merge_request[source_branch]=<branch>"
```
### Gogs / Gitea
Use the API directly (both use GitHub API v3-compatible format):
```bash
curl -s -X POST \
"${BASE_URL}/api/v1/repos/${OWNER}/${REPO}/pulls" \
-H "Authorization: token ${GOGS_TOKEN:-$GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"<type>: <feature-name>\",
\"body\": \"<pr-body-escaped>\",
\"head\": \"<current-branch>\",
\"base\": \"<base-branch>\"
}"
```
If the API call returns an error, print the full response and suggest
creating the PR manually via the web UI.
---
## PHASE 6 — FINAL REPORT
```
================================================================
PR CREATED
================================================================
BRANCH : <current-branch><base-branch>
COMMITS : <N> commits pushed
PLATFORM : <GitHub/GitLab/Gogs/Gitea>
COMMITS
-------
<git log --oneline output>
PR / MR
-------
URL : <pr-url or "create manually at <url>">
Type : Draft — awaiting your review and merge
NEXT STEPS
----------
1. Review the PR at the URL above
2. Request reviews if needed
3. Merge when approved
================================================================
```
---
## RULES
- Never merge, never rebase main/master/develop
- Never force push unless explicitly asked
- Never create commits on main, master, or develop directly
- If on main/master — STOP and ask user to checkout a feature branch first
- Draft PR by default — user controls merge
- If no CLI tool and no API token — print manual instructions, do not fail silently

View File

@ -123,6 +123,7 @@ ACTION REQUIRED? [YES — resolve blocking issues first] / [NO — proceed]
## THRESHOLDS
**Block and require action if:**
- Superpowers is not active (required by /init-project and /ship-feature orchestrators — install command: `claude plugin marketplace add obra/superpowers-marketplace && claude plugin install --scope user superpowers@superpowers-marketplace`)
- Project has significant frontend AND frontend-design + ui-ux-pro-max are both disabled
- Project uses Next.js/React/Prisma/Supabase AND context7 is not configured
- Project is full-product (UI + deploy + QA) AND gstack is not installed

261
doctor.sh Normal file
View File

@ -0,0 +1,261 @@
#!/usr/bin/env bash
# ============================================================
# Claude Code — Config doctor
# Diagnoses symlinks, prerequisites, plugins, permissions,
# and token budget. Run after install or when something breaks.
# ============================================================
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
ERRORS=0; WARNS=0
pass() { echo -e " ${GREEN}${NC} $1"; }
fail() { echo -e " ${RED}${NC} $1"; ERRORS=$((ERRORS + 1)); }
warn() { echo -e " ${YELLOW}${NC} $1"; WARNS=$((WARNS + 1)); }
info() { echo -e " ${BLUE}${NC} $1"; }
REPO="$(cd "$(dirname "$0")" && pwd)"
VERSION=$(cat "$REPO/version.txt" 2>/dev/null || echo "unknown")
# Load shared detection library
# shellcheck source=lib/detect-plugins.sh
source "$REPO/lib/detect-plugins.sh"
echo ""
echo "═══ claude-config doctor (v${VERSION}) ═══"
echo ""
# ────────────────────────────────────────────────────────────
# 1. Core symlinks
# ────────────────────────────────────────────────────────────
echo "── Symlinks ──"
check_symlink() {
local name="$1"
local target="$HOME/.claude/$name"
if [ ! -e "$target" ] && [ ! -L "$target" ]; then
fail "~/.claude/$name — MISSING"
return
fi
if [ -L "$target" ]; then
local real
real=$(readlink -f "$target" 2>/dev/null || readlink "$target")
if [ ! -e "$real" ]; then
fail "~/.claude/$name$real — BROKEN SYMLINK"
else
pass "~/.claude/$name"
fi
else
warn "~/.claude/$name exists but is NOT a symlink (expected symlink to repo)"
fi
}
check_symlink "CLAUDE.md"
check_symlink "settings.json"
check_symlink "agents"
check_symlink "skills"
check_symlink "hooks/session-start.sh"
echo ""
# ────────────────────────────────────────────────────────────
# 2. GStack submodule
# ────────────────────────────────────────────────────────────
echo "── GStack submodule ──"
if [ -d "$REPO/skills-external/gstack" ] || [ -f "$REPO/skills-external/gstack/.git" ]; then
pass "Submodule present at skills-external/gstack"
else
warn "Submodule not initialized — run: git submodule update --init"
fi
if [ -L "$HOME/.claude/skills/gstack" ]; then
real=$(readlink -f "$HOME/.claude/skills/gstack" 2>/dev/null || readlink "$HOME/.claude/skills/gstack")
if [ -d "$real" ]; then
pass "Symlink OK → $real"
else
fail "Symlink broken → $real"
fi
else
warn "GStack not symlinked — run: bash link.sh"
fi
echo ""
# ────────────────────────────────────────────────────────────
# 3. Prerequisites
# ────────────────────────────────────────────────────────────
echo "── Prerequisites ──"
if command -v git &>/dev/null; then
pass "git $(git --version | awk '{print $3}')"
else
fail "git not found"
fi
if command -v node &>/dev/null; then
NODE_VER=$(node --version | sed 's/v//' | cut -d. -f1)
if [ "$NODE_VER" -ge 18 ]; then
pass "Node.js $(node --version)"
else
warn "Node.js $(node --version) — need >=18"
fi
else
fail "Node.js not found"
fi
if command -v cargo &>/dev/null; then
pass "Cargo $(cargo --version | awk '{print $2}')"
else
warn "Cargo not found (RTK unavailable)"
fi
if command -v python3 &>/dev/null; then
pass "Python $(python3 --version | awk '{print $2}')"
else
warn "Python3 not found"
fi
if command -v claude &>/dev/null; then
pass "Claude Code $(claude --version 2>/dev/null | head -1 || echo 'installed')"
else
fail "Claude Code not found — install from https://code.claude.com"
fi
echo ""
# ────────────────────────────────────────────────────────────
# 4. Key plugins
# ────────────────────────────────────────────────────────────
echo "── Plugins ──"
if detect_rtk; then
pass "RTK installed"
else
warn "RTK not installed — run install-plugins.sh"
fi
if detect_superpowers; then
pass "Superpowers plugin detected"
else
fail "Superpowers not detected — orchestrators (/init-project, /ship-feature) will fail"
fi
if detect_context7; then
pass "Context7 MCP configured"
else
info "Context7 MCP not configured (optional — needed for fast-evolving libs)"
fi
echo ""
# ────────────────────────────────────────────────────────────
# 5. Permissions check
# ────────────────────────────────────────────────────────────
echo "── Permissions ──"
SETTINGS="$HOME/.claude/settings.json"
if [ -f "$SETTINGS" ] || [ -L "$SETTINGS" ]; then
if grep -q '"disableBypassPermissionsMode"' "$SETTINGS" 2>/dev/null; then
pass "Bypass mode disabled"
else
warn "disableBypassPermissionsMode not found in settings"
fi
DENY_COUNT=$(python3 -c "
import json
with open('$SETTINGS') as f:
d = json.load(f)
print(len(d.get('permissions',{}).get('deny',[])))
" 2>/dev/null || echo "?")
pass "Deny rules: $DENY_COUNT"
else
fail "~/.claude/settings.json not found"
fi
echo ""
# ────────────────────────────────────────────────────────────
# 6. Token budget estimate
# ────────────────────────────────────────────────────────────
echo "── Token budget estimate ──"
TOTAL_CHARS=0
# Skill descriptions
for f in "$HOME/.claude/skills/"*/SKILL.md; do
[ -f "$f" ] || continue
desc=$(sed -n 's/^description: //p' "$f" 2>/dev/null || true)
TOTAL_CHARS=$((TOTAL_CHARS + ${#desc}))
done
# Agent descriptions
for f in "$HOME/.claude/agents/"*.md; do
[ -f "$f" ] || continue
desc=$(sed -n '/^---$/,/^---$/{ s/^description: //p }' "$f" 2>/dev/null || true)
TOTAL_CHARS=$((TOTAL_CHARS + ${#desc}))
done
if [ "$TOTAL_CHARS" -gt 6000 ]; then
warn "Custom descriptions: ~${TOTAL_CHARS} chars (budget ~8000) — risk of truncation"
elif [ "$TOTAL_CHARS" -gt 4000 ]; then
info "Custom descriptions: ~${TOTAL_CHARS} chars (within budget, moderate margin)"
else
pass "Custom descriptions: ~${TOTAL_CHARS} chars (comfortable)"
fi
echo ""
# ────────────────────────────────────────────────────────────
# 7. File consistency
# ────────────────────────────────────────────────────────────
echo "── Consistency ──"
# Check all skills have disable-model-invocation
MISSING_DMI=()
for f in "$HOME/.claude/skills/"*/SKILL.md; do
[ -f "$f" ] || continue
name=$(basename "$(dirname "$f")")
if ! grep -q "disable-model-invocation" "$f" 2>/dev/null; then
MISSING_DMI+=("$name")
fi
done
if [ ${#MISSING_DMI[@]} -eq 0 ]; then
pass "All skills have disable-model-invocation"
else
warn "Skills missing disable-model-invocation: ${MISSING_DMI[*]}"
fi
# Check CRLF
CRLF_FILES=()
for f in "$REPO"/*.md "$REPO"/agents/*.md "$REPO"/skills/*/SKILL.md; do
[ -f "$f" ] || continue
if grep -qP '\r' "$f" 2>/dev/null; then
CRLF_FILES+=("$(basename "$f")")
fi
done
if [ ${#CRLF_FILES[@]} -eq 0 ]; then
pass "No CRLF line endings detected"
else
warn "CRLF detected in: ${CRLF_FILES[*]}"
fi
echo ""
# ────────────────────────────────────────────────────────────
# Summary
# ────────────────────────────────────────────────────────────
echo "═══════════════════════════════════════════"
if [ "$ERRORS" -gt 0 ]; then
echo -e "${RED} $ERRORS error(s)${NC}, ${YELLOW}$WARNS warning(s)${NC}"
echo ""
echo " Fix: cd $REPO && bash link.sh && bash install-plugins.sh"
exit 1
elif [ "$WARNS" -gt 0 ]; then
echo -e " ${GREEN}No errors${NC}, ${YELLOW}$WARNS warning(s)${NC}"
else
echo -e " ${GREEN}All checks passed ✓${NC}"
fi
echo ""

View File

@ -4,52 +4,88 @@
# Runs once per session. Zero API calls. Filesystem only.
# ============================================================
# ── Quick health check (filesystem only, no subprocesses) ──
BROKEN=()
for f in CLAUDE.md settings.json agents skills; do
[ ! -e "$HOME/.claude/$f" ] && BROKEN+=("$f")
done
if [ ${#BROKEN[@]} -gt 0 ]; then
# Try to find the repo path from an existing symlink
_repo_hint=""
for _probe in CLAUDE.md settings.json; do
if [ -L "$HOME/.claude/$_probe" ]; then
_repo_hint="$(cd "$(dirname "$(readlink "$HOME/.claude/$_probe")")" 2>/dev/null && pwd)"
break
fi
done
_fix_cmd="${_repo_hint:+cd $_repo_hint && }bash link.sh"
echo ""
echo "┌─ ⚠️ CONFIG ISSUES ────────────────────────────────┐"
for b in "${BROKEN[@]}"; do
printf "│ MISSING: ~/.claude/%-30s│\n" "$b"
done
printf "│ → %-47s│\n" "$_fix_cmd"
echo "│ → /health for full diagnostic │"
echo "└───────────────────────────────────────────────────┘"
unset _repo_hint _fix_cmd
fi
# ── Load shared detection library ──
_lib="$(dirname "${BASH_SOURCE[0]}")/../lib/detect-plugins.sh"
if [ -f "$_lib" ]; then
# shellcheck source=../lib/detect-plugins.sh
source "$_lib"
else
# Fallback: inline detection if lib is missing
detect_gstack() { [ -d "$HOME/.claude/skills/gstack" ]; }
detect_gsd() { ls "$HOME/.claude/skills/" 2>/dev/null | grep -qi "gsd"; }
detect_uiux_pro_max() { ls "$HOME/.claude/plugins/cache/" 2>/dev/null | grep -qi "ui-ux-pro-max"; }
detect_frontend_design() { ls "$HOME/.claude/plugins/cache/" 2>/dev/null | grep -qi "frontend-design"; }
detect_context7() { claude mcp list 2>/dev/null | grep -q "context7"; }
fi
unset _lib
# ── Toggle plugin detection ──
TOGGLE_ACTIVE=()
TOGGLE_INACTIVE=()
# --- GStack ---
if [ -d "$HOME/.claude/skills/gstack" ]; then
TOGGLE_ACTIVE+=("gstack")
else
TOGGLE_INACTIVE+=("gstack")
fi
for plugin in gstack gsd uiux_pro_max frontend_design context7; do
# Map function name to display name
case "$plugin" in
uiux_pro_max) display="ui-ux-pro-max" ;;
frontend_design) display="frontend-design" ;;
*) display="$plugin" ;;
esac
# --- GSD ---
if ls "$HOME/.claude/skills/" 2>/dev/null | grep -qi "gsd"; then
TOGGLE_ACTIVE+=("gsd")
else
TOGGLE_INACTIVE+=("gsd")
fi
# --- UI/UX Pro Max ---
if ls "$HOME/.claude/plugins/cache/" 2>/dev/null | grep -qi "ui-ux-pro-max"; then
TOGGLE_ACTIVE+=("ui-ux-pro-max")
else
TOGGLE_INACTIVE+=("ui-ux-pro-max")
fi
# --- frontend-design ---
if ls "$HOME/.claude/plugins/cache/" 2>/dev/null | grep -qi "frontend-design"; then
TOGGLE_ACTIVE+=("frontend-design")
else
TOGGLE_INACTIVE+=("frontend-design")
fi
# --- Context7 MCP ---
if claude mcp list 2>/dev/null | grep -q "context7"; then
TOGGLE_ACTIVE+=("context7")
else
TOGGLE_INACTIVE+=("context7")
fi
if "detect_$plugin" 2>/dev/null; then
TOGGLE_ACTIVE+=("$display")
else
TOGGLE_INACTIVE+=("$display")
fi
done
# --- Format output ---
ACTIVE_STR="${TOGGLE_ACTIVE[*]:-none}"
INACTIVE_STR="${TOGGLE_INACTIVE[*]:-none}"
# Version detection: follow CLAUDE.md symlink back to repo, then read version.txt
_claude_real="$(readlink "$HOME/.claude/CLAUDE.md" 2>/dev/null || true)"
if [ -n "$_claude_real" ]; then
_repo_dir="$(cd "$(dirname "$_claude_real")" 2>/dev/null && pwd)"
CONFIG_VERSION=$(cat "$_repo_dir/version.txt" 2>/dev/null || echo "?")
else
CONFIG_VERSION="?"
fi
unset _claude_real _repo_dir
echo ""
echo "┌─ Toggle plugins ──────────────────────────────────┐"
printf "│ 🟢 ON : %-40s│\n" "$ACTIVE_STR"
printf "│ ⚫ OFF : %-40s│\n" "$INACTIVE_STR"
echo "│ 💡 /plugin-check before starting a new project │"
echo "│ 🩺 /health to run full diagnostic │"
echo "└───────────────────────────────────────────────────┘"
echo ""

View File

@ -16,6 +16,31 @@ err() { echo -e "${RED}✗${NC} $1"; }
REPO="$(cd "$(dirname "$0")" && pwd)"
# Log to file for post-mortem debugging (terminal output unchanged)
LOG_FILE="$REPO/install-$(date +%Y%m%d-%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
# Load shared detection library
# shellcheck source=lib/detect-plugins.sh
source "$REPO/lib/detect-plugins.sh"
# Read pinned version from plugins.lock.json
# Usage: pinned_version "rtk" → prints version string or "latest"
pinned_version() {
local key="$1"
if [ -f "$REPO/plugins.lock.json" ] && command -v python3 &>/dev/null; then
python3 -c "
import json, sys
with open('$REPO/plugins.lock.json') as f:
d = json.load(f)
v = d.get('$key', {}).get('version', 'latest')
print(v)
" 2>/dev/null || echo "latest"
else
echo "latest"
fi
}
# ============================================================
# DETECT OS
# ============================================================
@ -128,52 +153,9 @@ fi
echo ""
# ============================================================
# STEP 2 — GIT CLI TOOLS (gh + glab for /git-pr)
# STEP 2 — GSTACK SUBMODULE
# ============================================================
echo "── Step 2: Git CLI tools ────────────────────────────────────"
echo ""
# --- gh (GitHub CLI) ---
if command -v gh &>/dev/null; then
ok "gh $(gh --version | head -1 | awk '{print $3}')"
else
info "Installing gh (GitHub CLI)..."
case $OS in
macos) brew install gh ;;
linux-apt) type -p curl > /dev/null || sudo apt-get install -y curl
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list
sudo apt-get update && sudo apt-get install -y gh ;;
linux-dnf) sudo dnf install -y gh ;;
linux-pacman) sudo pacman -S --noconfirm github-cli ;;
*) warn "Cannot auto-install gh on $OS — install from https://cli.github.com" ;;
esac
command -v gh &>/dev/null && ok "gh installed" || warn "gh not installed — GitHub PRs will use API fallback"
fi
# --- glab (GitLab CLI) ---
if command -v glab &>/dev/null; then
ok "glab $(glab --version | head -1)"
else
info "Installing glab (GitLab CLI)..."
case $OS in
macos) brew install glab ;;
linux-apt) curl -s https://raw.githubusercontent.com/profclems/glab/trunk/scripts/install.sh | sudo bash ;;
linux-dnf) sudo dnf install -y glab ;;
linux-pacman) sudo pacman -S --noconfirm glab ;;
*) warn "Cannot auto-install glab on $OS — install from https://gitlab.com/gitlab-org/cli" ;;
esac
command -v glab &>/dev/null && ok "glab installed" || warn "glab not installed — GitLab MRs will use API fallback"
fi
warn "Gogs/Gitea: set GOGS_TOKEN or GITEA_TOKEN in your shell profile"
echo " export GOGS_TOKEN="your-token" # add to ~/.zshrc or ~/.bashrc"
echo ""
# ============================================================
# STEP 3 — GSTACK SUBMODULE
# ============================================================
echo "── Step 3: GStack submodule ─────────────────────────────────"
echo "── Step 2: GStack submodule ─────────────────────────────────"
echo ""
# Note: GStack is managed as a git submodule in this repo.
# It lives at skills-external/gstack/ and is symlinked to ~/.claude/skills/gstack/
@ -198,10 +180,12 @@ fi
if [ -d "$GSTACK_DIR" ]; then
info "Running GStack setup..."
cd "$GSTACK_DIR" && ./setup && cd - > /dev/null
# Ensure symlink from link.sh is in place
mkdir -p "$HOME/.claude/skills"
ln -sf "$GSTACK_DIR" "$HOME/.claude/skills/gstack" 2>/dev/null || true
ok "GStack ready at ~/.claude/skills/gstack (→ submodule)"
# Symlinks are handled by link.sh — verify it was run
if [ -L "$HOME/.claude/skills/gstack" ]; then
ok "GStack ready (submodule initialized, symlink OK)"
else
warn "GStack submodule ready but not symlinked — run: bash link.sh"
fi
else
warn "GStack submodule directory not found after init — check .gitmodules"
fi
@ -211,13 +195,19 @@ echo ""
# ============================================================
# STEP 3 — RTK
# ============================================================
echo "── Step 4: RTK — Rust Token Killer ─────────────────────────"
echo "── Step 3: RTK — Rust Token Killer ─────────────────────────"
echo ""
if command -v rtk &>/dev/null; then
ok "rtk already installed ($(rtk --version 2>/dev/null | head -1))"
else
info "Installing RTK..."
cargo install --git https://github.com/rtk-ai/rtk
RTK_VER=$(pinned_version "rtk")
if [ "$RTK_VER" != "latest" ]; then
info "Installing RTK $RTK_VER (pinned in plugins.lock.json)..."
cargo install --git https://github.com/rtk-ai/rtk --tag "$RTK_VER"
else
info "Installing RTK (latest — consider pinning in plugins.lock.json)..."
cargo install --git https://github.com/rtk-ai/rtk
fi
fi
info "Configuring RTK PreToolUse hook (global)..."
rtk init -g --auto-patch
@ -227,10 +217,17 @@ echo ""
# ============================================================
# STEP 4 — GSD
# ============================================================
echo "── Step 5: GSD — get-shit-done ─────────────────────────────"
echo "── Step 4: GSD — get-shit-done ─────────────────────────────"
echo ""
info "Installing GSD globally..."
npx get-shit-done-cc --claude --global --auto
GSD_VER=$(pinned_version "gsd")
if [ "$GSD_VER" != "latest" ]; then
info "Version $GSD_VER (pinned in plugins.lock.json)"
npx "get-shit-done-cc@$GSD_VER" --claude --global --auto
else
info "Version: latest (consider pinning in plugins.lock.json)"
npx get-shit-done-cc --claude --global --auto
fi
ok "GSD installed"
echo ""
@ -239,7 +236,7 @@ echo ""
# ============================================================
# All claude plugin install commands use --scope user to ensure
# they install to ~/.claude/plugins/ regardless of working directory.
echo "── Step 6: Marketplace plugins (scope: user) ────────────────"
echo "── Step 5: Marketplace plugins (scope: user) ────────────────"
echo ""
install_plugin() {
@ -276,7 +273,7 @@ echo ""
# ============================================================
# STEP 6 — CONTEXT7 MCP (manual — requires API key)
# ============================================================
echo "── Step 7: Context7 MCP ─────────────────────────────────────"
echo "── Step 6: Context7 MCP ─────────────────────────────────────"
echo ""
if claude mcp list 2>/dev/null | grep -q "context7"; then
ok "Context7 MCP already configured"
@ -316,7 +313,6 @@ echo ""
echo " All plugins installed at: user scope (~/.claude/plugins/)"
echo " GStack at: ~/.claude/skills/gstack/ (symlink → submodule)"
echo ""
echo " → Authenticate: gh auth login (GitHub) / glab auth login (GitLab)"
echo " → Restart Claude Code"
echo " → Run /reload-plugins"
echo ""

64
lib/detect-plugins.sh Normal file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env bash
# ============================================================
# lib/detect-plugins.sh — Single source of truth for plugin detection
# Sourced by: session-start.sh, doctor.sh, install-plugins.sh
#
# Each function returns 0 (detected) or 1 (not detected).
# No output — callers handle messaging.
# ============================================================
# --- Always-on plugins ---
detect_rtk() {
command -v rtk &>/dev/null
}
detect_superpowers() {
# Fast check: filesystem (plugin cache)
local cache_dir="$HOME/.claude/plugins/cache"
if [ -d "$cache_dir" ]; then
ls "$cache_dir" 2>/dev/null | grep -qi "superpowers" && return 0
fi
# Slow fallback: CLI (only if fast check fails)
claude plugin list 2>/dev/null | grep -qi "superpowers" && return 0
return 1
}
detect_security_guidance() {
local cache_dir="$HOME/.claude/plugins/cache"
[ -d "$cache_dir" ] && ls "$cache_dir" 2>/dev/null | grep -qi "security-guidance"
}
detect_skill_creator() {
local cache_dir="$HOME/.claude/plugins/cache"
[ -d "$cache_dir" ] && ls "$cache_dir" 2>/dev/null | grep -qi "skill-creator"
}
detect_pr_review_toolkit() {
local cache_dir="$HOME/.claude/plugins/cache"
[ -d "$cache_dir" ] && ls "$cache_dir" 2>/dev/null | grep -qi "pr-review-toolkit"
}
# --- Toggle plugins ---
detect_gstack() {
[ -d "$HOME/.claude/skills/gstack" ]
}
detect_gsd() {
ls "$HOME/.claude/skills/" 2>/dev/null | grep -qi "gsd"
}
detect_frontend_design() {
local cache_dir="$HOME/.claude/plugins/cache"
[ -d "$cache_dir" ] && ls "$cache_dir" 2>/dev/null | grep -qi "frontend-design"
}
detect_uiux_pro_max() {
local cache_dir="$HOME/.claude/plugins/cache"
[ -d "$cache_dir" ] && ls "$cache_dir" 2>/dev/null | grep -qi "ui-ux-pro-max"
}
detect_context7() {
claude mcp list 2>/dev/null | grep -q "context7"
}

24
link.sh
View File

@ -9,21 +9,33 @@ CLAUDE="$HOME/.claude"
mkdir -p "$CLAUDE"
# Core config files
# Core config files (plain files — ln -sf handles these correctly)
ln -sf "$REPO/CLAUDE.md" "$CLAUDE/CLAUDE.md"
ln -sf "$REPO/settings.json" "$CLAUDE/settings.json"
# Agents and skills
ln -sf "$REPO/agents" "$CLAUDE/agents"
ln -sf "$REPO/skills" "$CLAUDE/skills"
# Agents and skills — must handle the case where target exists
# as a real directory (ln -sf would create a link INSIDE the dir
# instead of replacing it)
for item in agents skills lib; do
target="$CLAUDE/$item"
if [ -L "$target" ]; then
# Stale symlink from a previous run — remove before recreating
rm -f "$target"
elif [ -d "$target" ]; then
echo "⚠️ ~/.claude/$item is a real directory (not a symlink)."
echo " Rename or remove it, then re-run link.sh."
echo " Skipping $item to avoid data loss."
continue
fi
ln -sf "$REPO/$item" "$target"
done
# Hooks
mkdir -p "$CLAUDE/hooks"
ln -sf "$REPO/hooks/session-start.sh" "$CLAUDE/hooks/session-start.sh"
# GStack (submodule) — symlink from skills-external/ into ~/.claude/skills/
# GStack (submodule) — symlink into ~/.claude/skills/ (which points to repo/skills/)
# The submodule must be initialized first (done by install-plugins.sh)
mkdir -p "$CLAUDE/skills"
if [ -d "$REPO/skills-external/gstack" ]; then
ln -sf "$REPO/skills-external/gstack" "$CLAUDE/skills/gstack"
echo "✅ GStack symlinked from submodule"

24
plugins.lock.json Normal file
View File

@ -0,0 +1,24 @@
{
"_readme": "Pinned versions for reproducible installs. Update versions deliberately, then run install-plugins.sh.",
"rtk": {
"source": "https://github.com/rtk-ai/rtk",
"install_cmd": "cargo install --git https://github.com/rtk-ai/rtk --tag {version}",
"version": "v0.34.3",
"note": "Check latest at https://github.com/rtk-ai/rtk/releases before updating"
},
"gsd": {
"source": "npm:get-shit-done-cc",
"install_cmd": "npx get-shit-done-cc@{version} --claude --global --auto",
"version": "1.30.0",
"note": "Check latest at https://www.npmjs.com/package/get-shit-done-cc before updating"
},
"gstack": {
"source": "https://github.com/garrytan/gstack.git",
"managed_by": "git submodule",
"note": "Version controlled by submodule pointer in .gitmodules. Update: git submodule update --remote"
},
"node": {
"minimum": "18",
"recommended": "22"
}
}

View File

@ -1,5 +1,5 @@
{
"_readme": "Global user settings \u2014 place at ~/.claude/settings.json. Applies to ALL projects. Never commit this file.",
"_readme": "Global user settings place at ~/.claude/settings.json. Applies to ALL projects. Never commit this file.",
"cleanupPeriodDays": 30,
"permissions": {
"defaultMode": "default",
@ -53,7 +53,35 @@
"Write(**/.env.*)",
"Write(**/secrets/**)",
"Write(**/*.pem)",
"Write(**/*.key)"
"Write(**/*.key)",
"Bash(bash -c *)",
"Bash(eval *)",
"Bash(exec *)",
"Bash(find * -delete*)",
"Bash(find * -exec rm*)",
"Bash(find * -execdir rm*)",
"Bash(perl -e *)",
"Bash(ruby -e *)",
"Bash(cat .env)",
"Bash(cat .env.*)",
"Bash(cat */.env)",
"Bash(cat */.env.*)",
"Bash(cat */secrets/*)",
"Bash(cat */*.pem)",
"Bash(cat */*.key)",
"Bash(cat */id_rsa*)",
"Bash(cat */id_ed25519*)",
"Bash(cat */.aws/credentials)",
"Bash(head .env)",
"Bash(head .env.*)",
"Bash(tail .env)",
"Bash(tail .env.*)",
"Bash(less .env)",
"Bash(less .env.*)",
"Bash(more .env)",
"Bash(more .env.*)",
"Bash(grep * .env)",
"Bash(grep * .env.*)"
],
"ask": [
"Bash(git push *)",
@ -68,7 +96,10 @@
"Bash(dnf install *)",
"Bash(pacman -S *)",
"WebSearch",
"WebFetch"
"WebFetch",
"Bash(xargs *)",
"Bash(sed -i *)",
"Bash(sed -i'' *)"
],
"allow": [
"Bash(git status)",
@ -112,7 +143,6 @@
"Bash(awk *)",
"Bash(sort *)",
"Bash(uniq *)",
"Bash(xargs *)",
"Bash(tr *)",
"Bash(cut *)",
"Bash(diff *)",
@ -144,4 +174,4 @@
}
]
}
}
}

View File

@ -1,7 +1,9 @@
---
name: analyze
description: Analyze code or a codebase deeply before any modification
description: Deep factual code analysis — read-only, no solutions proposed
argument-hint: <code, file, or area to analyze>
disable-model-invocation: true
allowed-tools: Read, Grep, Glob, Bash
---
Load and follow strictly:

View File

@ -1,15 +0,0 @@
---
name: git-pr
description: Analyze all changes on the current branch since it diverged from base (retroactive across sessions), create logical commits, push, and open a draft PR/MR. Works with GitHub, GitLab, Gogs, and Gitea. Never merges — creates a draft for user validation.
argument-hint: [PR title or leave empty for auto-detection]
disable-model-invocation: true
allowed-tools: Read, Bash, Grep, Glob
---
Load and follow strictly:
- .claude/agents/git-workflow.md
Execute the GIT WORKFLOW on the current repository.
User context (optional title or instructions):
$ARGUMENTS

18
skills/health/SKILL.md Normal file
View File

@ -0,0 +1,18 @@
---
name: health
description: Run setup diagnostic — check symlinks, plugins, permissions, token budget
argument-hint: (no arguments needed)
disable-model-invocation: true
allowed-tools: Bash
---
Run the health check script and report findings to the user:
```bash
bash ~/.claude/doctor.sh
```
After displaying the output:
- If errors are found, suggest the specific fix commands shown in the output.
- If only warnings, note them but confirm the setup is functional.
- If all checks pass, confirm the setup is healthy.

View File

@ -1,6 +1,6 @@
---
name: init-project
description: Initialize a complete project from scratch. Plugin check → interview → analyze → design → validate → scaffold skeleton → plan v1 features → validate plan → implement (TDD, subagents) → analyze → review → finish. Same implementation rigor as ship-feature.
description: Full project init: interview → design → scaffold → implement (TDD). Two validation gates.
argument-hint: <project idea or description>
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
@ -35,42 +35,7 @@ $ARGUMENTS
---
### STEP 0a — BRANCH SETUP
Load the BRANCH SETUP section from: `.claude/agents/git-workflow.md`
Before anything else, ensure we are NOT on a protected branch.
```bash
git branch --show-current
```
**If on `main`, `master`, `develop`, or any protected branch:**
Derive a branch slug from the initial request:
- Take the first 34 meaningful words
- Lowercase, hyphen-separated
- Max 50 chars
```bash
git fetch origin
git pull origin <current> --ff-only 2>/dev/null || true
git checkout -b feature/<project-slug>
```
Print: `✅ Working branch created: feature/<project-slug>`
**If already on a feature branch:**
Run the CONFLICT-SAFE REBASE procedure from git-workflow.md
to sync with main before starting.
Print: `✅ Branch: <current> (synced with main)`
**Do not proceed until the branch is clean and ready.**
---
### STEP 0b — PLUGIN CHECK
### STEP 0 — PLUGIN CHECK
Load and follow: `.claude/agents/plugin-advisor.md`
@ -88,7 +53,7 @@ B) Type "force" to proceed without them
================================================================
```
**STOP. Wait for user response.**
- Re-run → restart from STEP 0b
- Re-run → restart from STEP 0
- "force" → note missing plugins, continue to STEP 1
**If `ACTION REQUIRED: NO`:**
@ -341,8 +306,7 @@ SYNC mode — no stop required. The readme-updater:
## RULES
- Never skip STEP 0a — branch setup is mandatory. Never commit on main/master.
- Never skip STEP 0b — plugin check is mandatory.
- Never skip STEP 0 — plugin check is mandatory.
- Never skip STEP 1 — no assumptions about missing info.
- Never implement without explicit user approval at STEP 4.
- Never implement without explicit user approval at STEP 7.

View File

@ -1,6 +1,6 @@
---
name: plugin-check
description: Check active plugins vs current project needs. Recommends enabling or disabling based on context signals (frontend, design, QA, deployment, multi-session, fast-evolving libs). Run before init-project or ship-feature on a new project type.
description: Audit active plugins vs project needs. Recommends enable/disable actions.
argument-hint: [project description or feature to build]
disable-model-invocation: true
allowed-tools: Read, Bash, Glob, Grep

View File

@ -1,6 +1,6 @@
---
name: readme
description: Update the project README to reflect the current state of the codebase. Audits what is outdated, missing, or no longer accurate, then applies surgical updates. Preserves existing structure and style.
description: README audit — detect outdated sections, apply surgical updates
argument-hint: [what changed, feature name, or leave empty for full audit]
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Bash, Glob, Grep

View File

@ -1,7 +1,9 @@
---
name: refactor
description: Improve code quality without changing behavior
description: Improve code quality without changing behavior — strict norm enforcement
argument-hint: <file, function, or module to refactor>
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Grep, Glob, Bash
---
Load and follow strictly:

View File

@ -1,6 +1,6 @@
---
name: ship-feature
description: Ship a feature end-to-end using the Superpowers workflow. Starts with a plugin check, then Brainstorm → Plan → Implement (subagent-driven) → Review → Finish branch.
description: Ship feature end-to-end: design → plan → implement (TDD) → review → finish
argument-hint: <feature description>
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
@ -33,48 +33,7 @@ $ARGUMENTS
---
### STEP 0a — BRANCH SETUP
Load the BRANCH SETUP section from: `.claude/agents/git-workflow.md`
```bash
git branch --show-current
```
**If on `main`, `master`, `develop`, or any protected branch:**
Derive a branch slug from the feature request:
- Take the first 34 meaningful words from $ARGUMENTS
- Lowercase, hyphen-separated, max 50 chars
- Prefix with `feature/`
```bash
git fetch origin
git pull origin <current> --ff-only 2>/dev/null || true
git checkout -b feature/<feature-slug>
```
Print: `✅ Working branch created: feature/<feature-slug>`
**If already on a feature/bugfix/hotfix branch:**
Run the CONFLICT-SAFE REBASE procedure from git-workflow.md
to sync with the base branch before implementing.
Print: `✅ Branch: <current> (synced)`
**Special case — bugfix on a feature branch:**
If the user explicitly says "bugfix" or "fix" in the request AND
the current branch is a feature branch:
```bash
git checkout -b bugfix/<bug-slug>
```
Creates the bugfix branch FROM the feature branch — correct hierarchy.
**Do not proceed until the branch is clean.**
---
### STEP 0b — PLUGIN CHECK (mandatory gate)
### STEP 0 — PLUGIN CHECK (mandatory gate)
Load and follow: `.claude/agents/plugin-advisor.md`
@ -105,7 +64,7 @@ Options:
```
Wait for user response.
- If user re-runs `/ship-feature` → start from STEP 0a again
- If user re-runs `/ship-feature` → start from STEP 0 again
- If user types "force" → note missing plugins and continue to STEP 1
**If the advisor output says `ACTION REQUIRED: NO`:**
@ -198,40 +157,9 @@ SYNC mode — no stop required. The readme-updater:
---
### STEP 9 — CREATE PR (optional gate)
Ask the user:
```
================================================================
SHIP FEATURE — PR CREATION
================================================================
Feature is implemented, tested, and README is synced.
Create a PR/MR now?
yes → run /git-pr and open a draft PR
no → stop here, you can run /git-pr manually later
================================================================
```
**STOP — wait for user response.**
IF yes:
Load and follow: `.claude/agents/git-workflow.md`
The git-workflow agent will:
- Show all changes since branch start (retroactive)
- Propose a commit plan for approval
- Push and create a draft PR/MR on GitHub/GitLab/Gogs/Gitea
IF no:
Print: `✅ Feature shipped. Run /git-pr when ready to open a PR.`
Stop.
---
## RULES
- Never skip STEP 0a — branch setup is mandatory. Never implement on main/master.
- Never skip STEP 0b — plugin check is mandatory.
- Never skip STEP 0 — plugin check is mandatory.
- Never skip brainstorming.
- Never implement without explicit user approval of the plan.
- Keep subagents isolated — no shared context between tasks.

78
update-all.sh Normal file
View File

@ -0,0 +1,78 @@
#!/usr/bin/env bash
# ============================================================
# Claude Code — Update all components
# Pulls latest config, updates submodules, refreshes symlinks,
# and runs doctor to verify.
# ============================================================
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
ok() { echo -e "${GREEN}${NC} $1"; }
warn() { echo -e "${YELLOW}${NC} $1"; }
info() { echo -e "${BLUE}${NC} $1"; }
REPO="$(cd "$(dirname "$0")" && pwd)"
VERSION=$(cat "$REPO/version.txt" 2>/dev/null || echo "unknown")
echo ""
echo "═══ claude-config update (v${VERSION}) ═══"
echo ""
# ── 1. Pull latest config ──
echo "── Pulling latest config..."
cd "$REPO"
if git pull --rebase 2>/dev/null; then
ok "Config repo updated"
else
warn "git pull failed — check for uncommitted changes"
fi
# ── 2. Update GStack submodule ──
echo ""
echo "── Updating GStack submodule..."
if git submodule update --remote skills-external/gstack 2>/dev/null; then
if [ -d "skills-external/gstack" ]; then
cd skills-external/gstack && ./setup 2>/dev/null && cd "$REPO"
ok "GStack updated"
fi
else
warn "GStack submodule update failed — run: git submodule update --init"
fi
# ── 3. Update RTK (if pinned version available) ──
echo ""
echo "── Updating RTK..."
if command -v cargo &>/dev/null; then
RTK_VERSION=""
if [ -f "$REPO/plugins.lock.json" ] && command -v python3 &>/dev/null; then
RTK_VERSION=$(python3 -c "
import json
with open('$REPO/plugins.lock.json') as f:
d = json.load(f)
print(d.get('rtk',{}).get('version',''))
" 2>/dev/null || true)
fi
if [ -n "$RTK_VERSION" ] && [ "$RTK_VERSION" != "latest" ]; then
info "Pinned version: $RTK_VERSION"
cargo install --git https://github.com/rtk-ai/rtk --tag "$RTK_VERSION" --force 2>/dev/null \
&& ok "RTK updated to $RTK_VERSION" \
|| warn "RTK update failed"
else
info "No pinned version — installing latest"
cargo install --git https://github.com/rtk-ai/rtk --force 2>/dev/null \
&& ok "RTK updated (latest)" \
|| warn "RTK update failed"
fi
else
warn "Cargo not available — skipping RTK"
fi
# ── 4. Refresh symlinks ──
echo ""
echo "── Refreshing symlinks..."
bash "$REPO/link.sh"
# ── 5. Run doctor ──
echo ""
bash "$REPO/doctor.sh"

1
version.txt Normal file
View File

@ -0,0 +1 @@
1.0.0