From cfb028670bdb136541db394351716b6e8dfacf46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mart=C3=ADn=20=28Noda=29?= Date: Tue, 2 Jun 2026 13:20:40 +0200 Subject: [PATCH 1/2] fix(opencode): repair install and startup flow --- .gitignore | 1 + INSTALL.md | 31 +++++++++++++++++-- README.md | 2 +- agents/cavecrew-builder.md | 9 ++++-- agents/cavecrew-investigator.md | 10 ++++-- agents/cavecrew-reviewer.md | 9 ++++-- bin/install.js | 23 ++++++-------- plugins/caveman/agents/cavecrew-builder.md | 9 ++++-- .../caveman/agents/cavecrew-investigator.md | 10 ++++-- plugins/caveman/agents/cavecrew-reviewer.md | 9 ++++-- src/plugins/opencode/README.md | 28 +++++++++++++++++ .../opencode/commands/caveman-compress.md | 10 ++++++ src/plugins/opencode/plugin.js | 6 ---- tests/installer/opencode.test.mjs | 3 +- 14 files changed, 120 insertions(+), 40 deletions(-) create mode 100644 src/plugins/opencode/commands/caveman-compress.md diff --git a/.gitignore b/.gitignore index be5bedb1..ed5209cd 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ __pycache__/ .venv/ .env.local caveman-compress.md +!src/plugins/opencode/commands/caveman-compress.md **/.DS_Store .claude/worktrees/ evals/snapshots/*.html diff --git a/INSTALL.md b/INSTALL.md index 4def7b62..ac4fd1ef 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -106,7 +106,7 @@ Useful flags: | `--only ` | One agent only. Repeatable: `--only claude --only cursor`. | | `--dry-run` | Print every command. Write nothing. | | `--with-init` | Drop always-on rule files into the current repo (`.cursor/`, `.windsurf/`, `.clinerules/`, `.github/copilot-instructions.md`, `.opencode/AGENTS.md`, `AGENTS.md`) and, if OpenClaw is on the box, append the bootstrap block to `~/.openclaw/workspace/SOUL.md`. | -| `--with-mcp-shrink` | Register `caveman-shrink` MCP proxy. **On by default.** | +| `--with-mcp-shrink` | Register `caveman-shrink` MCP proxy for Claude Code. **On by default.** OpenCode must wrap MCP servers manually. | | `--no-mcp-shrink` | Skip MCP-shrink registration. | | `--with-hooks` / `--no-hooks` | Force-on or force-off the Claude Code hook installer. (Default: on.) | | `--skip-skills` | Don't run the npx-skills auto-detect fallback when nothing else matched. | @@ -170,7 +170,7 @@ What it removes: - Caveman hook entries from `$CLAUDE_CONFIG_DIR/settings.json` (default `~/.claude/`; matched by the substring `caveman`). - Hook files in `$CLAUDE_CONFIG_DIR/hooks/` (`caveman-activate.js`, `caveman-mode-tracker.js`, `caveman-stats.js`, `caveman-config.js`, `caveman-statusline.{sh,ps1}`, plus the dir's `package.json` marker). - The Claude Code plugin and the Gemini CLI extension (if installed). -- The opencode native plugin (`~/.config/opencode/plugins/caveman/`, the `plugin` and `mcp.caveman-shrink` entries from `opencode.json`, our skill/agent/command files, the caveman block from `AGENTS.md`, and the opencode flag file). +- The opencode native plugin (`~/.config/opencode/plugins/caveman/`, the `plugin` entry from `opencode.json`, our skill/agent/command files, the caveman block from `AGENTS.md`, and the opencode flag file). Old `mcp.caveman-shrink` entries are pruned if present. - The OpenClaw workspace skill folder and the marker-fenced block from `~/.openclaw/workspace/SOUL.md` (when present). - The `.caveman-active` flag file. @@ -191,6 +191,33 @@ Agent read repo. Agent run install. Caveman make agent talk less — agent first Still broken? [Open an issue](https://github.com/JuliusBrussee/caveman/issues). +**"I want `caveman-shrink` in OpenCode."** + +OpenCode install no longer auto-registers `caveman-shrink`. Add a manual MCP +entry that wraps specific upstream servers: + +```json +{ + "mcp": { + "filesystem-shrink": { + "type": "local", + "command": [ + "npx", + "-y", + "caveman-shrink", + "npx", + "-y", + "@modelcontextprotocol/server-filesystem", + "/absolute/path/to/project" + ], + "enabled": true + } + } +} +``` + +Pattern: `caveman-shrink [...args]`. + **"I ran the installer but Claude Code isn't talking caveman."** 1. Run `node bin/install.js --list` — confirm `claude` is on the detected list. If not, `claude` isn't on `PATH`. Fix that first. diff --git a/README.md b/README.md index 60ab5744..5e659a6e 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ Install break? Open agent, say *"Read CLAUDE.md and INSTALL.md, install caveman | `/caveman-review` | One-line PR comments: `L42: 🔴 bug: user null. Add guard.` | | `/caveman-stats` | Real session token usage + lifetime savings + USD. Tweetable line via `--share`. | | `/caveman-compress ` | Rewrite memory file (e.g. `CLAUDE.md`) into caveman-speak. Cuts ~46% input tokens every session. Code/URLs/paths byte-preserved. | -| `caveman-shrink` | MCP middleware. Wraps any MCP server, compresses tool descriptions. [npm](https://www.npmjs.com/package/caveman-shrink). | +| `caveman-shrink` | MCP middleware. Wraps any MCP server, compresses tool descriptions. Auto-wired for Claude Code; OpenCode wraps manually. [npm](https://www.npmjs.com/package/caveman-shrink). | | `cavecrew-*` | Caveman subagents (investigator/builder/reviewer). ~60% fewer tokens than vanilla, main context lasts longer. | **Statusline badge** — Claude Code shows `[CAVEMAN] ⛏ 12.4k` (lifetime tokens saved). Updates every `/caveman-stats` run. Set `CAVEMAN_STATUSLINE_SAVINGS=0` to silence. diff --git a/agents/cavecrew-builder.md b/agents/cavecrew-builder.md index 65750df3..8d6db3a9 100644 --- a/agents/cavecrew-builder.md +++ b/agents/cavecrew-builder.md @@ -1,12 +1,17 @@ --- -name: cavecrew-builder description: > Surgical 1-2 file edit. Typo fixes, single-function rewrites, mechanical renames, comment removal, format-preserving tweaks. Hard refuses 3+ file scope. Returns caveman diff receipt. Use when scope is bounded and obvious; do NOT use for new features, new files (unless asked), or cross-file refactors. -tools: [Read, Edit, Write, Grep, Glob] +mode: subagent +permission: + read: allow + edit: allow + glob: allow + grep: allow + bash: deny --- Caveman-ultra. Drop articles/filler. Code/paths exact, backticked. No narration. diff --git a/agents/cavecrew-investigator.md b/agents/cavecrew-investigator.md index be274987..943dbaf9 100644 --- a/agents/cavecrew-investigator.md +++ b/agents/cavecrew-investigator.md @@ -1,12 +1,16 @@ --- -name: cavecrew-investigator description: > Read-only code locator. Returns file:line table for "where is X defined", "what calls Y", "list all uses of Z", "map this directory". Output is caveman-compressed so the main thread eats ~60% fewer tokens than vanilla Explore. Refuses to suggest fixes. -tools: [Read, Grep, Glob, Bash] -model: haiku +mode: subagent +permission: + read: allow + edit: deny + glob: allow + grep: allow + bash: allow --- Caveman-ultra. Drop articles/filler/hedging. Code/symbols/paths exact, backticked. Lead with answer. diff --git a/agents/cavecrew-reviewer.md b/agents/cavecrew-reviewer.md index 97049ce9..d6adb57a 100644 --- a/agents/cavecrew-reviewer.md +++ b/agents/cavecrew-reviewer.md @@ -1,12 +1,15 @@ --- -name: cavecrew-reviewer description: > Diff/branch/file reviewer. One line per finding, severity-tagged, no praise, no scope creep. Output format `path:line: : . .` Use for "review this PR", "review my diff", "audit this file". Skips formatting nits unless they change meaning. -tools: [Read, Grep, Bash] -model: haiku +mode: subagent +permission: + read: allow + edit: deny + grep: allow + bash: allow --- Caveman-ultra. Findings only. No "looks good", no "I'd suggest", no preamble. diff --git a/bin/install.js b/bin/install.js index def0d144..6f5ab6a4 100755 --- a/bin/install.js +++ b/bin/install.js @@ -475,7 +475,6 @@ const OPENCODE_AGENTS_MD_END = ''; function opencodeConfigDir() { if (process.env.XDG_CONFIG_HOME) return path.join(process.env.XDG_CONFIG_HOME, 'opencode'); - if (IS_WIN) return path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 'opencode'); return path.join(os.homedir(), '.config', 'opencode'); } @@ -516,7 +515,10 @@ function installOpencode(ctx) { note(` would copy ${OPENCODE_COMMAND_FILES.length} command files into ${commandsDir}/`); note(` would copy ${OPENCODE_AGENT_FILES.length} cavecrew agents into ${agentsDir}/`); note(` would copy ${OPENCODE_SKILL_DIRS.length} skill dirs into ${skillsDir}/`); - note(` would patch ${opencodeJson} with "plugin" entry${opts.withMcpShrink ? ' + caveman-shrink MCP' : ''}`); + note(` would patch ${opencodeJson} with "plugin" entry`); + if (opts.withMcpShrink) { + note(' would not auto-register caveman-shrink for opencode; wrap specific MCP servers manually'); + } note(` would write Tier-3 ruleset to ${agentsMd}`); results.installed.push('opencode'); process.stdout.write('\n'); @@ -614,7 +616,8 @@ function installOpencode(ctx) { process.stdout.write(` installed: ${agentsMd}\n`); } - // 6. opencode.json — add plugin entry; optional caveman-shrink MCP. + // 6. opencode.json — add plugin entry only. caveman-shrink stays manual for + // opencode because the standalone MCP registration has broken startup. let cfg = SETTINGS.readSettings(opencodeJson); if (cfg === null) { warn(` ${opencodeJson} unparseable; will not touch it. Edit manually then re-run.`); @@ -632,19 +635,11 @@ function installOpencode(ctx) { if (!cfg.plugin.includes(OPENCODE_PLUGIN_REL)) { cfg.plugin.push(OPENCODE_PLUGIN_REL); } - if (opts.withMcpShrink) { - if (!cfg.mcp || typeof cfg.mcp !== 'object') cfg.mcp = {}; - if (!cfg.mcp['caveman-shrink']) { - cfg.mcp['caveman-shrink'] = { - type: 'local', - command: ['npx', '-y', MCP_SHRINK_PKG], - enabled: true, - }; - process.stdout.write(' registered caveman-shrink MCP server\n'); - } - } SETTINGS.writeSettings(opencodeJson, cfg); process.stdout.write(` patched: ${opencodeJson}\n`); + if (opts.withMcpShrink) { + note(' caveman-shrink not auto-registered for opencode; wrap MCP servers manually if wanted'); + } results.installed.push('opencode'); } catch (e) { diff --git a/plugins/caveman/agents/cavecrew-builder.md b/plugins/caveman/agents/cavecrew-builder.md index 65750df3..8d6db3a9 100644 --- a/plugins/caveman/agents/cavecrew-builder.md +++ b/plugins/caveman/agents/cavecrew-builder.md @@ -1,12 +1,17 @@ --- -name: cavecrew-builder description: > Surgical 1-2 file edit. Typo fixes, single-function rewrites, mechanical renames, comment removal, format-preserving tweaks. Hard refuses 3+ file scope. Returns caveman diff receipt. Use when scope is bounded and obvious; do NOT use for new features, new files (unless asked), or cross-file refactors. -tools: [Read, Edit, Write, Grep, Glob] +mode: subagent +permission: + read: allow + edit: allow + glob: allow + grep: allow + bash: deny --- Caveman-ultra. Drop articles/filler. Code/paths exact, backticked. No narration. diff --git a/plugins/caveman/agents/cavecrew-investigator.md b/plugins/caveman/agents/cavecrew-investigator.md index be274987..943dbaf9 100644 --- a/plugins/caveman/agents/cavecrew-investigator.md +++ b/plugins/caveman/agents/cavecrew-investigator.md @@ -1,12 +1,16 @@ --- -name: cavecrew-investigator description: > Read-only code locator. Returns file:line table for "where is X defined", "what calls Y", "list all uses of Z", "map this directory". Output is caveman-compressed so the main thread eats ~60% fewer tokens than vanilla Explore. Refuses to suggest fixes. -tools: [Read, Grep, Glob, Bash] -model: haiku +mode: subagent +permission: + read: allow + edit: deny + glob: allow + grep: allow + bash: allow --- Caveman-ultra. Drop articles/filler/hedging. Code/symbols/paths exact, backticked. Lead with answer. diff --git a/plugins/caveman/agents/cavecrew-reviewer.md b/plugins/caveman/agents/cavecrew-reviewer.md index 97049ce9..d6adb57a 100644 --- a/plugins/caveman/agents/cavecrew-reviewer.md +++ b/plugins/caveman/agents/cavecrew-reviewer.md @@ -1,12 +1,15 @@ --- -name: cavecrew-reviewer description: > Diff/branch/file reviewer. One line per finding, severity-tagged, no praise, no scope creep. Output format `path:line: : . .` Use for "review this PR", "review my diff", "audit this file". Skips formatting nits unless they change meaning. -tools: [Read, Grep, Bash] -model: haiku +mode: subagent +permission: + read: allow + edit: deny + grep: allow + bash: allow --- Caveman-ultra. Findings only. No "looks good", no "I'd suggest", no preamble. diff --git a/src/plugins/opencode/README.md b/src/plugins/opencode/README.md index 1c681988..cb4f5ee0 100644 --- a/src/plugins/opencode/README.md +++ b/src/plugins/opencode/README.md @@ -17,6 +17,34 @@ to `caveman-config.cjs` because this directory is `"type": "module"`) into `~/.config/opencode/plugins/caveman/` and patches `opencode.json` with a `"plugin"` array entry. +It does **not** auto-register `caveman-shrink` as an OpenCode MCP server. +That startup path is currently broken upstream in caveman, so wrap specific MCP +servers manually if you want shrink behavior in OpenCode. + +Example `opencode.json` entry: + +```json +{ + "mcp": { + "filesystem-shrink": { + "type": "local", + "command": [ + "npx", + "-y", + "caveman-shrink", + "npx", + "-y", + "@modelcontextprotocol/server-filesystem", + "/absolute/path/to/project" + ], + "enabled": true + } + } +} +``` + +Pattern: `caveman-shrink [...args]`. + ## What it does - `session.created` → writes the configured default mode to diff --git a/src/plugins/opencode/commands/caveman-compress.md b/src/plugins/opencode/commands/caveman-compress.md new file mode 100644 index 00000000..dec23db8 --- /dev/null +++ b/src/plugins/opencode/commands/caveman-compress.md @@ -0,0 +1,10 @@ +--- +description: Compress a Markdown file into caveman format to save tokens +--- +Compress the file at: $ARGUMENTS + +Load the `caveman-compress` skill, then run: + +`python3 -m scripts ` + +The compressed version overwrites the original. A human-readable backup is saved as `FILE.original.md`. diff --git a/src/plugins/opencode/plugin.js b/src/plugins/opencode/plugin.js index 7f3a870e..66436fb5 100644 --- a/src/plugins/opencode/plugin.js +++ b/src/plugins/opencode/plugin.js @@ -50,12 +50,6 @@ function opencodeConfigDir() { if (process.env.XDG_CONFIG_HOME) { return path.join(process.env.XDG_CONFIG_HOME, 'opencode'); } - if (process.platform === 'win32') { - return path.join( - process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), - 'opencode' - ); - } return path.join(os.homedir(), '.config', 'opencode'); } diff --git a/tests/installer/opencode.test.mjs b/tests/installer/opencode.test.mjs index f2691db8..8df9eb17 100644 --- a/tests/installer/opencode.test.mjs +++ b/tests/installer/opencode.test.mjs @@ -41,7 +41,7 @@ function shimOpencode() { } function runInstaller(args, env) { - return spawnSync('node', [INSTALLER, ...args, '--non-interactive', '--no-mcp-shrink'], { + return spawnSync('node', [INSTALLER, ...args, '--non-interactive'], { env, encoding: 'utf8', }); } @@ -91,6 +91,7 @@ test('opencode fresh install drops plugin, commands, agents, skills, AGENTS.md, const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8')); assert.ok(Array.isArray(cfg.plugin), 'opencode.json missing plugin array'); assert.ok(cfg.plugin.includes('./plugins/caveman/plugin.js'), 'plugin entry missing'); + assert.equal(cfg.mcp?.['caveman-shrink'], undefined, 'opencode install should not auto-register caveman-shrink'); } finally { fs.rmSync(xdg, { recursive: true, force: true }); fs.rmSync(shimDir, { recursive: true, force: true }); From 069b7d1b56db2c6dd3e95bffbb3aaf49459974ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mart=C3=ADn=20=28Noda=29?= Date: Tue, 2 Jun 2026 13:36:44 +0200 Subject: [PATCH 2/2] fix(opencode): keep agent frontmatter portable --- .gitignore | 2 -- agents/cavecrew-builder.md | 14 ++++++++------ agents/cavecrew-investigator.md | 14 ++++++++------ agents/cavecrew-reviewer.md | 12 +++++++----- plugins/caveman/agents/cavecrew-builder.md | 14 ++++++++------ plugins/caveman/agents/cavecrew-investigator.md | 14 ++++++++------ plugins/caveman/agents/cavecrew-reviewer.md | 12 +++++++----- 7 files changed, 46 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index ed5209cd..acd7bd5c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,6 @@ __pycache__/ *.pyc .venv/ .env.local -caveman-compress.md -!src/plugins/opencode/commands/caveman-compress.md **/.DS_Store .claude/worktrees/ evals/snapshots/*.html diff --git a/agents/cavecrew-builder.md b/agents/cavecrew-builder.md index 8d6db3a9..d2b57383 100644 --- a/agents/cavecrew-builder.md +++ b/agents/cavecrew-builder.md @@ -1,4 +1,5 @@ --- +name: cavecrew-builder description: > Surgical 1-2 file edit. Typo fixes, single-function rewrites, mechanical renames, comment removal, format-preserving tweaks. Hard refuses 3+ file @@ -6,12 +7,13 @@ description: > obvious; do NOT use for new features, new files (unless asked), or cross-file refactors. mode: subagent -permission: - read: allow - edit: allow - glob: allow - grep: allow - bash: deny +tools: + read: true + edit: true + write: true + glob: true + grep: true + bash: false --- Caveman-ultra. Drop articles/filler. Code/paths exact, backticked. No narration. diff --git a/agents/cavecrew-investigator.md b/agents/cavecrew-investigator.md index 943dbaf9..a9f90e75 100644 --- a/agents/cavecrew-investigator.md +++ b/agents/cavecrew-investigator.md @@ -1,16 +1,18 @@ --- +name: cavecrew-investigator description: > Read-only code locator. Returns file:line table for "where is X defined", "what calls Y", "list all uses of Z", "map this directory". Output is caveman-compressed so the main thread eats ~60% fewer tokens than vanilla Explore. Refuses to suggest fixes. mode: subagent -permission: - read: allow - edit: deny - glob: allow - grep: allow - bash: allow +tools: + read: true + edit: false + write: false + glob: true + grep: true + bash: true --- Caveman-ultra. Drop articles/filler/hedging. Code/symbols/paths exact, backticked. Lead with answer. diff --git a/agents/cavecrew-reviewer.md b/agents/cavecrew-reviewer.md index d6adb57a..0f2c8c35 100644 --- a/agents/cavecrew-reviewer.md +++ b/agents/cavecrew-reviewer.md @@ -1,15 +1,17 @@ --- +name: cavecrew-reviewer description: > Diff/branch/file reviewer. One line per finding, severity-tagged, no praise, no scope creep. Output format `path:line: : . .` Use for "review this PR", "review my diff", "audit this file". Skips formatting nits unless they change meaning. mode: subagent -permission: - read: allow - edit: deny - grep: allow - bash: allow +tools: + read: true + edit: false + write: false + grep: true + bash: true --- Caveman-ultra. Findings only. No "looks good", no "I'd suggest", no preamble. diff --git a/plugins/caveman/agents/cavecrew-builder.md b/plugins/caveman/agents/cavecrew-builder.md index 8d6db3a9..d2b57383 100644 --- a/plugins/caveman/agents/cavecrew-builder.md +++ b/plugins/caveman/agents/cavecrew-builder.md @@ -1,4 +1,5 @@ --- +name: cavecrew-builder description: > Surgical 1-2 file edit. Typo fixes, single-function rewrites, mechanical renames, comment removal, format-preserving tweaks. Hard refuses 3+ file @@ -6,12 +7,13 @@ description: > obvious; do NOT use for new features, new files (unless asked), or cross-file refactors. mode: subagent -permission: - read: allow - edit: allow - glob: allow - grep: allow - bash: deny +tools: + read: true + edit: true + write: true + glob: true + grep: true + bash: false --- Caveman-ultra. Drop articles/filler. Code/paths exact, backticked. No narration. diff --git a/plugins/caveman/agents/cavecrew-investigator.md b/plugins/caveman/agents/cavecrew-investigator.md index 943dbaf9..a9f90e75 100644 --- a/plugins/caveman/agents/cavecrew-investigator.md +++ b/plugins/caveman/agents/cavecrew-investigator.md @@ -1,16 +1,18 @@ --- +name: cavecrew-investigator description: > Read-only code locator. Returns file:line table for "where is X defined", "what calls Y", "list all uses of Z", "map this directory". Output is caveman-compressed so the main thread eats ~60% fewer tokens than vanilla Explore. Refuses to suggest fixes. mode: subagent -permission: - read: allow - edit: deny - glob: allow - grep: allow - bash: allow +tools: + read: true + edit: false + write: false + glob: true + grep: true + bash: true --- Caveman-ultra. Drop articles/filler/hedging. Code/symbols/paths exact, backticked. Lead with answer. diff --git a/plugins/caveman/agents/cavecrew-reviewer.md b/plugins/caveman/agents/cavecrew-reviewer.md index d6adb57a..0f2c8c35 100644 --- a/plugins/caveman/agents/cavecrew-reviewer.md +++ b/plugins/caveman/agents/cavecrew-reviewer.md @@ -1,15 +1,17 @@ --- +name: cavecrew-reviewer description: > Diff/branch/file reviewer. One line per finding, severity-tagged, no praise, no scope creep. Output format `path:line: : . .` Use for "review this PR", "review my diff", "audit this file". Skips formatting nits unless they change meaning. mode: subagent -permission: - read: allow - edit: deny - grep: allow - bash: allow +tools: + read: true + edit: false + write: false + grep: true + bash: true --- Caveman-ultra. Findings only. No "looks good", no "I'd suggest", no preamble.