Add windsurf skill, hooks, and install docs

Add .windsurf/skills/caveman SKILL.md and update the sync workflow to copy and commit the new file. Expand README install docs with agent-specific install instructions and standalone hook usage; update AGENTS.md and GEMINI.md to use the new caveman-compress path. Add Windows PowerShell installers (hooks/install.ps1 and hooks/uninstall.ps1) and enhance shell installers (hooks/install.sh, hooks/uninstall.sh) to support --force, plugin detection, clearer statusline wiring messages, and idempotent JSON merging/removal of hook entries. Provides uninstall guidance for other agents and improves overall install/uninstall robustness.
This commit is contained in:
Julius Brussee
2026-04-11 11:30:34 +02:00
parent cfd76590bd
commit 79fa46a4a0
9 changed files with 512 additions and 33 deletions
+3 -1
View File
@@ -31,6 +31,8 @@ jobs:
cp skills/caveman/SKILL.md caveman/SKILL.md
cp skills/caveman/SKILL.md plugins/caveman/skills/caveman/SKILL.md
cp skills/caveman/SKILL.md .cursor/skills/caveman/SKILL.md
mkdir -p .windsurf/skills/caveman
cp skills/caveman/SKILL.md .windsurf/skills/caveman/SKILL.md
- name: Rebuild caveman.skill ZIP
run: |
@@ -39,6 +41,6 @@ jobs:
- name: Commit and push if changed
run: |
git diff --quiet && exit 0
git add caveman/SKILL.md plugins/caveman/skills/caveman/SKILL.md .cursor/skills/caveman/SKILL.md caveman.skill
git add caveman/SKILL.md plugins/caveman/skills/caveman/SKILL.md .cursor/skills/caveman/SKILL.md .windsurf/skills/caveman/SKILL.md caveman.skill
git commit -m "chore: sync SKILL.md copies and caveman.skill [skip ci]"
git push
+63
View File
@@ -0,0 +1,63 @@
---
name: caveman
description: >
Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman
while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra,
wenyan-lite, wenyan-full, wenyan-ultra.
Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens",
"be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
---
Respond terse like smart caveman. All technical substance stay. Only fluff die.
Default: **full**. Switch: `/caveman lite|full|ultra`.
## Rules
Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). Technical terms exact. Code blocks unchanged. Errors quoted exact.
Pattern: `[thing] [action] [reason]. [next step].`
Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
## Intensity
| Level | What change |
|-------|------------|
| **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight |
| **full** | Drop articles, fragments OK, short synonyms. Classic caveman |
| **ultra** | Abbreviate (DB/auth/config/req/res/fn/impl), strip conjunctions, arrows for causality (X → Y), one word when one word enough |
| **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register |
| **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) |
| **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse |
Example — "Why React component re-render?"
- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
- full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."
- ultra: "Inline obj prop → new ref → re-render. `useMemo`."
- wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"
- wenyan-full: "物出新參照,致重繪。useMemo .Wrap之。"
- wenyan-ultra: "新參照→重繪。useMemo Wrap。"
Example — "Explain database connection pooling."
- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead."
- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
- ultra: "Pool = reuse DB conn. Skip handshake → fast under load."
- wenyan-full: "池reuse open connection。不每req新開。skip handshake overhead。"
- wenyan-ultra: "池reuse conn。skip handshake → fast。"
## Auto-Clarity
Drop caveman for: security warnings, irreversible action confirmations, multi-step sequences where fragment order risks misread, user asks to clarify or repeats question. Resume caveman after clear part done.
Example — destructive op:
> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
> ```sql
> DROP TABLE users;
> ```
> Caveman resume. Verify backup exist first.
## Boundaries
Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
+1 -1
View File
@@ -1,4 +1,4 @@
@./skills/caveman/SKILL.md
@./skills/caveman-commit/SKILL.md
@./skills/caveman-review/SKILL.md
@./skills/compress/SKILL.md
@./caveman-compress/SKILL.md
+1 -1
View File
@@ -1,4 +1,4 @@
@./skills/caveman/SKILL.md
@./skills/caveman-commit/SKILL.md
@./skills/caveman-review/SKILL.md
@./skills/compress/SKILL.md
@./caveman-compress/SKILL.md
+90 -22
View File
@@ -122,44 +122,112 @@ Based on the viral observation that caveman-speak dramatically reduces LLM token
## Install
### Claude Code (recommended)
Pick your agent. One command. Done.
Install as a plugin — includes skills + auto-loading hooks + statusline badge. Caveman activates every session, `[CAVEMAN:ULTRA]` badge tracks mode, Claude sets up the statusline on first session:
| Agent | Install |
|-------|---------|
| **Claude Code** | `claude plugin marketplace add JuliusBrussee/caveman && claude plugin install caveman@caveman` |
| **Codex** | Clone repo → `/plugins` → Search "Caveman" → Install |
| **Gemini CLI** | `gemini extensions install https://github.com/JuliusBrussee/caveman` |
| **Cursor** | `npx skills add JuliusBrussee/caveman -a cursor` |
| **Windsurf** | `npx skills add JuliusBrussee/caveman -a windsurf` |
| **Copilot** | `npx skills add JuliusBrussee/caveman -a github-copilot` |
| **Cline** | `npx skills add JuliusBrussee/caveman -a cline` |
| **Any other** | `npx skills add JuliusBrussee/caveman` |
Install once. Use in all sessions after that. One rock. That it.
### What You Get
Not all install paths are equal. Claude Code plugin is the richest experience:
| Feature | Claude Code (plugin) | Codex | Gemini CLI | npx skills |
|---------|:-------------------:|:-----:|:----------:|:----------:|
| Caveman mode | Y | Y | Y | Y |
| Auto-activate every session | Y | — | Y | — |
| Statusline badge `[CAVEMAN:ULTRA]` | Y | — | — | — |
| Mode tracking (`/caveman ultra`) | Y | — | — | — |
| caveman-commit | Y | Y | Y | Y |
| caveman-review | Y | Y | Y | Y |
| caveman-compress | Y | Y | Y | Y |
<details>
<summary><strong>Claude Code — full details</strong></summary>
The plugin install gives you everything: skills + auto-loading hooks + statusline badge.
```bash
claude plugin marketplace add JuliusBrussee/caveman
claude plugin install caveman@caveman
```
### Any agent (Claude Code, Cursor, Copilot, Windsurf, Cline, Codex, Gemini CLI, Antigravity)
**Standalone hooks (without plugin):** If you prefer not to use the plugin system:
```bash
npx skills add JuliusBrussee/caveman
# macOS / Linux / WSL
bash <(curl -s https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks/install.sh)
# Windows (PowerShell)
irm https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks/install.ps1 | iex
```
For a specific agent: `npx skills add JuliusBrussee/caveman -a cursor`
Or from a local clone: `bash hooks/install.sh` / `powershell -File hooks\install.ps1`
> [!NOTE]
> `npx skills` installs skills only (no hooks). For Claude Code auto-loading hooks, use the plugin install above or run `bash hooks/install.sh`.
> Gemini CLI users can also install directly: `gemini extensions install https://github.com/JuliusBrussee/caveman`
Uninstall: `bash hooks/uninstall.sh` or `powershell -File hooks\uninstall.ps1`
### Codex
1. Clone repo → Open Codex in repo → `/plugins` → Search `Caveman` → Install
> [!NOTE]
> **Windows Codex users:** Clone repo → VS Code → Codex Settings → Plugins → find `Caveman` under local marketplace → Install → Reload Window. Also enable `git config core.symlinks true` before cloning (requires developer mode or admin).
Install once. Use in all sessions after that. One rock. That it.
### Statusline Badge
The plugin ships a statusline script that shows `[CAVEMAN]`, `[CAVEMAN:ULTRA]`, etc. in your Claude Code status bar.
**Statusline badge:** The plugin ships a statusline script that shows `[CAVEMAN]`, `[CAVEMAN:ULTRA]`, etc. in your Claude Code status bar.
- **Plugin install:** Claude offers to configure it on first session (auto-detected)
- **Standalone install (`install.sh`):** Configured automatically
- **Standalone install:** Configured automatically by `install.sh` / `install.ps1`
- **Custom statusline:** See [`hooks/README.md`](hooks/README.md) for the snippet to add to your existing script
</details>
<details>
<summary><strong>Codex — full details</strong></summary>
**macOS / Linux:**
1. Clone repo → Open Codex in the repo directory → `/plugins` → Search "Caveman" → Install
**Windows:**
1. Enable symlinks first: `git config --global core.symlinks true` (requires Developer Mode or admin)
2. Clone repo → Open VS Code → Codex Settings → Plugins → find "Caveman" under local marketplace → Install → Reload Window
</details>
<details>
<summary><strong>Gemini CLI — full details</strong></summary>
```bash
gemini extensions install https://github.com/JuliusBrussee/caveman
```
Update: `gemini extensions update caveman` · Uninstall: `gemini extensions uninstall caveman`
Gemini loads the skill via `GEMINI.md` + `gemini-extension.json`. Auto-activates every session through the context file.
</details>
<details>
<summary><strong>Cursor / Windsurf / Cline / Copilot / others</strong></summary>
All use [npx skills](https://github.com/vercel-labs/skills) (supports 40+ agents):
```bash
npx skills add JuliusBrussee/caveman -a cursor
npx skills add JuliusBrussee/caveman -a windsurf
npx skills add JuliusBrussee/caveman -a cline
npx skills add JuliusBrussee/caveman -a github-copilot
npx skills add JuliusBrussee/caveman # auto-detect agent
```
Uninstall: `npx skills remove caveman`
> **Note:** `npx skills` installs skills only (no hooks or auto-activation). You'll trigger caveman manually with `/caveman` or "talk like caveman" each session.
> **Windows note:** `npx skills` uses symlinks by default. If symlinks fail, add `--copy`: `npx skills add JuliusBrussee/caveman --copy`
</details>
## Usage
Trigger with:
+146
View File
@@ -0,0 +1,146 @@
# caveman — one-command hook installer for Claude Code (Windows PowerShell)
# Installs: SessionStart hook (auto-load rules) + UserPromptSubmit hook (mode tracking)
# Usage: powershell -ExecutionPolicy Bypass -File hooks\install.ps1
# or: irm https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks/install.ps1 | iex
# or: powershell -ExecutionPolicy Bypass -File hooks\install.ps1 -Force
param(
[switch]$Force
)
$ErrorActionPreference = "Stop"
# Require node
if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
Write-Host "ERROR: 'node' is required to install the caveman hooks (used to merge" -ForegroundColor Red
Write-Host " the hook config into settings.json safely)." -ForegroundColor Red
Write-Host " Install Node.js from https://nodejs.org and re-run this script." -ForegroundColor Red
exit 1
}
$ClaudeDir = Join-Path $env:USERPROFILE ".claude"
$HooksDir = Join-Path $ClaudeDir "hooks"
$Settings = Join-Path $ClaudeDir "settings.json"
$RepoUrl = "https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks"
$HookFiles = @("caveman-activate.js", "caveman-mode-tracker.js", "caveman-statusline.sh")
# Resolve source — works from repo clone or remote
$ScriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { $null }
# Check if already installed (unless -Force)
$ActivateExists = Test-Path (Join-Path $HooksDir "caveman-activate.js")
$TrackerExists = Test-Path (Join-Path $HooksDir "caveman-mode-tracker.js")
if (-not $Force -and $ActivateExists -and $TrackerExists) {
Write-Host "Caveman hooks already installed in $HooksDir"
Write-Host " Re-run with -Force to overwrite: powershell -File hooks\install.ps1 -Force"
Write-Host ""
Write-Host "Nothing to do. Hooks are already in place."
exit 0
}
if ($Force -and $ActivateExists) {
Write-Host "Reinstalling caveman hooks (-Force)..."
} else {
Write-Host "Installing caveman hooks..."
}
# 1. Ensure hooks dir exists
if (-not (Test-Path $HooksDir)) {
New-Item -ItemType Directory -Path $HooksDir -Force | Out-Null
}
# 2. Copy or download hook files
foreach ($hook in $HookFiles) {
$dest = Join-Path $HooksDir $hook
$localSource = if ($ScriptDir) { Join-Path $ScriptDir $hook } else { $null }
if ($localSource -and (Test-Path $localSource)) {
Copy-Item $localSource $dest -Force
} else {
Invoke-WebRequest -Uri "$RepoUrl/$hook" -OutFile $dest -UseBasicParsing
}
Write-Host " Installed: $dest"
}
# 3. Wire hooks + statusline into settings.json (idempotent)
if (-not (Test-Path $Settings)) {
Set-Content -Path $Settings -Value "{}"
}
# Back up existing settings.json before touching it
Copy-Item $Settings "$Settings.bak" -Force
# Use node for safe JSON merging (same approach as bash version)
$HooksDirEscaped = $HooksDir -replace '\\', '/'
$nodeScript = @"
const fs = require('fs');
const settings = JSON.parse(fs.readFileSync('$($Settings -replace '\\', '/')', 'utf8'));
if (!settings.hooks) settings.hooks = {};
// SessionStart
if (!settings.hooks.SessionStart) settings.hooks.SessionStart = [];
const hasStart = settings.hooks.SessionStart.some(e =>
e.hooks && e.hooks.some(h => h.command && h.command.includes('caveman'))
);
if (!hasStart) {
settings.hooks.SessionStart.push({
hooks: [{
type: 'command',
command: 'node $HooksDirEscaped/caveman-activate.js',
timeout: 5,
statusMessage: 'Loading caveman mode...'
}]
});
}
// UserPromptSubmit
if (!settings.hooks.UserPromptSubmit) settings.hooks.UserPromptSubmit = [];
const hasPrompt = settings.hooks.UserPromptSubmit.some(e =>
e.hooks && e.hooks.some(h => h.command && h.command.includes('caveman'))
);
if (!hasPrompt) {
settings.hooks.UserPromptSubmit.push({
hooks: [{
type: 'command',
command: 'node $HooksDirEscaped/caveman-mode-tracker.js',
timeout: 5,
statusMessage: 'Tracking caveman mode...'
}]
});
}
// Statusline
if (!settings.statusLine) {
settings.statusLine = {
type: 'command',
command: 'bash $HooksDirEscaped/caveman-statusline.sh'
};
console.log(' Statusline badge configured.');
} else {
const cmd = typeof settings.statusLine === 'string'
? settings.statusLine
: (settings.statusLine.command || '');
if (!cmd.includes('caveman')) {
console.log(' NOTE: Existing statusline detected - caveman badge NOT added.');
console.log(' See hooks/README.md to add the badge to your existing statusline.');
} else {
console.log(' Statusline badge already configured.');
}
}
fs.writeFileSync('$($Settings -replace '\\', '/')', JSON.stringify(settings, null, 2) + '\n');
console.log(' Hooks wired in settings.json');
"@
node -e $nodeScript
Write-Host ""
Write-Host "Done! Restart Claude Code to activate." -ForegroundColor Green
Write-Host ""
Write-Host "What's installed:"
Write-Host " - SessionStart hook: auto-loads caveman rules every session"
Write-Host " - Mode tracker hook: updates statusline badge when you switch modes"
Write-Host " (/caveman lite, /caveman ultra, /caveman-commit, etc.)"
Write-Host " - Statusline badge: shows [CAVEMAN] or [CAVEMAN:ULTRA] etc."
+56 -5
View File
@@ -3,8 +3,27 @@
# Installs: SessionStart hook (auto-load rules) + UserPromptSubmit hook (mode tracking)
# Usage: bash hooks/install.sh
# or: bash <(curl -s https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks/install.sh)
# or: bash hooks/install.sh --force (re-install over existing hooks)
set -e
FORCE=0
for arg in "$@"; do
case "$arg" in
--force|-f) FORCE=1 ;;
esac
done
# Detect Windows (Git Bash / MSYS / MINGW) — not WSL (WSL reports "linux-gnu")
case "$OSTYPE" in
msys*|cygwin*|mingw*)
echo "WARNING: Running on Windows ($OSTYPE)."
echo " This script works in Git Bash/MSYS but symlinks may require"
echo " Developer Mode or admin privileges."
echo " If you installed via 'claude plugin install', you don't need this script."
echo ""
;;
esac
# Require node — we use it to merge the hook config into settings.json
if ! command -v node >/dev/null 2>&1; then
echo "ERROR: 'node' is required to install the caveman hooks (used to merge"
@@ -21,16 +40,37 @@ REPO_URL="https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks"
HOOK_FILES=("caveman-activate.js" "caveman-mode-tracker.js" "caveman-statusline.sh")
# Resolve source — works from repo clone or curl pipe
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}" 2>/dev/null)" 2>/dev/null && pwd)"
SCRIPT_DIR=""
if [ -n "${BASH_SOURCE[0]:-}" ] && [ -f "${BASH_SOURCE[0]}" ]; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
fi
echo "Installing caveman hooks..."
# Check if already installed (unless --force)
ALREADY_INSTALLED=0
if [ "$FORCE" -eq 0 ] && [ -f "$HOOKS_DIR/caveman-activate.js" ] && [ -f "$HOOKS_DIR/caveman-mode-tracker.js" ]; then
ALREADY_INSTALLED=1
echo "Caveman hooks already installed in $HOOKS_DIR"
echo " Re-run with --force to overwrite: bash hooks/install.sh --force"
echo ""
fi
if [ "$ALREADY_INSTALLED" -eq 1 ] && [ "$FORCE" -eq 0 ]; then
echo "Nothing to do. Hooks are already in place."
exit 0
fi
if [ "$FORCE" -eq 1 ] && [ -f "$HOOKS_DIR/caveman-activate.js" ]; then
echo "Reinstalling caveman hooks (--force)..."
else
echo "Installing caveman hooks..."
fi
# 1. Ensure hooks dir exists
mkdir -p "$HOOKS_DIR"
# 2. Copy or download hook files
for hook in "${HOOK_FILES[@]}"; do
if [ -f "$SCRIPT_DIR/$hook" ]; then
if [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/$hook" ]; then
cp "$SCRIPT_DIR/$hook" "$HOOKS_DIR/$hook"
else
curl -fsSL "$REPO_URL/$hook" -o "$HOOKS_DIR/$hook"
@@ -86,17 +126,28 @@ node -e "
});
}
// Statusline — wire caveman badge (only if no statusLine is already configured)
// Statusline — wire caveman badge (report if skipped)
if (!settings.statusLine) {
settings.statusLine = {
type: 'command',
command: 'bash $HOOKS_DIR/caveman-statusline.sh'
};
console.log(' Statusline badge configured.');
} else {
const cmd = typeof settings.statusLine === 'string'
? settings.statusLine
: (settings.statusLine.command || '');
if (!cmd.includes('caveman')) {
console.log(' NOTE: Existing statusline detected — caveman badge NOT added.');
console.log(' See hooks/README.md to add the badge to your existing statusline.');
} else {
console.log(' Statusline badge already configured.');
}
}
fs.writeFileSync('$SETTINGS', JSON.stringify(settings, null, 2) + '\n');
console.log(' Hooks wired in settings.json');
"
echo " Hooks + statusline wired in settings.json"
echo ""
echo "Done! Restart Claude Code to activate."
+121
View File
@@ -0,0 +1,121 @@
# caveman — uninstaller for the SessionStart + UserPromptSubmit hooks (Windows PowerShell)
# Removes: hook files in ~/.claude/hooks, settings.json entries, and the flag file
# Usage: powershell -ExecutionPolicy Bypass -File hooks\uninstall.ps1
# or: irm https://raw.githubusercontent.com/JuliusBrussee/caveman/main/hooks/uninstall.ps1 | iex
param()
$ErrorActionPreference = "Stop"
$ClaudeDir = Join-Path $env:USERPROFILE ".claude"
$HooksDir = Join-Path $ClaudeDir "hooks"
$Settings = Join-Path $ClaudeDir "settings.json"
$FlagFile = Join-Path $ClaudeDir ".caveman-active"
$HookFiles = @("caveman-activate.js", "caveman-mode-tracker.js", "caveman-statusline.sh")
# Detect if caveman is installed as a plugin
$PluginInstalled = $false
$PluginsDir = Join-Path $ClaudeDir "plugins"
if (Test-Path $PluginsDir) {
$found = Get-ChildItem -Path $PluginsDir -Recurse -Filter "plugin.json" -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match "caveman" }
if ($found) { $PluginInstalled = $true }
}
if ($PluginInstalled) {
Write-Host "Caveman appears to be installed as a Claude Code plugin." -ForegroundColor Yellow
Write-Host "To uninstall the plugin, run:"
Write-Host ""
Write-Host " claude plugin disable caveman" -ForegroundColor Cyan
Write-Host ""
Write-Host "This script removes standalone hooks (installed via install.ps1)."
Write-Host "Continuing with standalone hook removal..."
Write-Host ""
}
Write-Host "Uninstalling caveman hooks..."
# 1. Remove hook files
$RemovedFiles = 0
foreach ($hook in $HookFiles) {
$path = Join-Path $HooksDir $hook
if (Test-Path $path) {
Remove-Item $path -Force
Write-Host " Removed: $path"
$RemovedFiles++
}
}
if ($RemovedFiles -eq 0) {
Write-Host " No hook files found in $HooksDir"
}
# 2. Remove caveman entries from settings.json (idempotent)
if (Test-Path $Settings) {
if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
Write-Host "WARNING: 'node' not found - cannot safely edit settings.json." -ForegroundColor Yellow
Write-Host " Remove the caveman SessionStart and UserPromptSubmit"
Write-Host " entries from $Settings manually."
} else {
# Back up before editing
Copy-Item $Settings "$Settings.bak" -Force
$nodeScript = @"
const fs = require('fs');
const settings = JSON.parse(fs.readFileSync('$($Settings -replace '\\', '/')', 'utf8'));
const isCavemanEntry = (entry) =>
entry && entry.hooks && entry.hooks.some(h =>
h.command && h.command.includes('caveman')
);
let removed = 0;
if (settings.hooks) {
for (const event of ['SessionStart', 'UserPromptSubmit']) {
if (Array.isArray(settings.hooks[event])) {
const before = settings.hooks[event].length;
settings.hooks[event] = settings.hooks[event].filter(e => !isCavemanEntry(e));
removed += before - settings.hooks[event].length;
if (settings.hooks[event].length === 0) {
delete settings.hooks[event];
}
}
}
if (Object.keys(settings.hooks).length === 0) {
delete settings.hooks;
}
}
if (settings.statusLine) {
const cmd = typeof settings.statusLine === 'string'
? settings.statusLine
: (settings.statusLine.command || '');
if (cmd.includes('caveman')) {
delete settings.statusLine;
console.log(' Removed caveman statusLine from settings.json');
}
}
fs.writeFileSync('$($Settings -replace '\\', '/')', JSON.stringify(settings, null, 2) + '\n');
console.log(' Removed ' + removed + ' caveman hook entries from settings.json');
"@
node -e $nodeScript
}
}
# 3. Remove flag file
if (Test-Path $FlagFile) {
Remove-Item $FlagFile -Force
Write-Host " Removed: $FlagFile"
}
Write-Host ""
Write-Host "Done! Restart Claude Code to complete the uninstall." -ForegroundColor Green
# Guidance for other agents
Write-Host ""
Write-Host "Other agents:"
Write-Host " npx skills remove caveman # Cursor, Windsurf, Cline, Copilot, etc."
Write-Host " claude plugin disable caveman # Claude Code plugin"
Write-Host " gemini extensions uninstall caveman # Gemini CLI"
+31 -3
View File
@@ -12,16 +12,41 @@ FLAG_FILE="$CLAUDE_DIR/.caveman-active"
HOOK_FILES=("caveman-activate.js" "caveman-mode-tracker.js" "caveman-statusline.sh")
# Detect if caveman is installed as a plugin (check plugin cache)
PLUGIN_INSTALLED=0
if [ -d "$CLAUDE_DIR/plugins" ]; then
if find "$CLAUDE_DIR/plugins" -path "*/caveman*" -name "plugin.json" -print -quit 2>/dev/null | grep -q .; then
PLUGIN_INSTALLED=1
fi
fi
if [ "$PLUGIN_INSTALLED" -eq 1 ]; then
echo "Caveman appears to be installed as a Claude Code plugin."
echo "To uninstall the plugin, run:"
echo ""
echo " claude plugin disable caveman"
echo ""
echo "This script removes standalone hooks (installed via install.sh)."
echo "Continuing with standalone hook removal..."
echo ""
fi
echo "Uninstalling caveman hooks..."
# 1. Remove hook files
REMOVED_FILES=0
for hook in "${HOOK_FILES[@]}"; do
if [ -f "$HOOKS_DIR/$hook" ]; then
rm "$HOOKS_DIR/$hook"
echo " Removed: $HOOKS_DIR/$hook"
REMOVED_FILES=$((REMOVED_FILES + 1))
fi
done
if [ "$REMOVED_FILES" -eq 0 ]; then
echo " No hook files found in $HOOKS_DIR"
fi
# 2. Remove caveman entries from settings.json (idempotent)
if [ -f "$SETTINGS" ]; then
# Require node for the same reason install.sh does — safe JSON editing
@@ -86,7 +111,10 @@ fi
echo ""
echo "Done! Restart Claude Code to complete the uninstall."
# Guidance for other agents
echo ""
echo "Note: If you installed caveman as a plugin, disabling the plugin is"
echo " the recommended way to deactivate hooks — this script is only"
echo " needed if you installed manually via install.sh."
echo "Other agents:"
echo " npx skills remove caveman # Cursor, Windsurf, Cline, Copilot, etc."
echo " claude plugin disable caveman # Claude Code plugin"
echo " gemini extensions uninstall caveman # Gemini CLI"