Commit Graph
237 Commits
Author SHA1 Message Date
Julius BrusseeandClaude Fable 5 51e1990340 fix(#603): caveman-init command no longer needs the caveman repo checkout
commands/caveman-init.toml told every installed Codex/Gemini user to run
node src/tools/caveman-init.js — a path that only exists inside the
caveman clone, so the command failed with Cannot find module for
everyone but caveman developers.

- toml prompt now gates the repo-relative path on the file existing and
  falls back to the standalone script via curl | node -
- src/tools/caveman-init.js: the documented curl|node stdin path was
  silently a no-op — require.main is undefined under node -, so the
  require.main === module guard never ran main() (exit 0, no output,
  no files). Guard now also matches module.id === '[stdin]'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011kmm2umRGb5nLxdimrwweZ
2026-07-02 15:11:38 +02:00
Julius Brussee 15465d30b5 Merge PR #499: fix(shrink): restore nested protected-segment sentinels (fixes #444) 2026-07-02 15:00:17 +02:00
Julius Brussee daa8ec3732 fix: refresh src/hooks checksums.sha256 after #608/#591/#538 hook changes 2026-07-02 14:57:21 +02:00
Julius Brusseeandousamabenyounes e7ee55f936 fix(#538): handle stdin 'error' in mode-tracker (hand-applied from PR #560)
PR #560 shipped the regression test but its source change never made it
into the diff — the branch only adds tests/test_mode_tracker_stdin.js.
Applied the one-line silent-exit error listener the PR describes and
took the author's test verbatim.

Co-authored-by: ousamabenyounes <ousamabenyounes@users.noreply.github.com>
2026-07-02 14:57:10 +02:00
Julius Brussee bd36cdc953 Merge PR #614: add SECURITY.md, CODE_OF_CONDUCT.md, .editorconfig repository standards 2026-07-02 14:56:16 +02:00
Julius Brussee 452055463b Merge PR #591: fix(hooks): SessionStart SKILL.md path off-by-one (fixes #587, #589) 2026-07-02 14:55:48 +02:00
Julius Brussee a2cb2f95e8 Merge PR #608: fix(hooks): NL trigger misfires + one-shot independent modes (fixes #598, #599) 2026-07-02 14:55:36 +02:00
Julius Brussee c1e1ffdd47 Merge PR #606: fix(compress): never classify build files or shebang scripts as prose (fixes #600) 2026-07-02 14:55:36 +02:00
Julius Brussee 14eea5d5ee Merge PR #586: fix(install): avoid EXDEV cross-device link on claude plugin install (fixes #585)
# Conflicts:
#	bin/install.js
2026-07-02 14:55:21 +02:00
Julius Brussee cdb0d0c613 Merge PR #604: fix(install): treat spawn ENOENT as failure, not success (fixes #592)
# Conflicts:
#	tests/installer/e2e.freshinstall.test.mjs
2026-07-02 14:54:36 +02:00
Julius Brussee 9663344b79 Merge PR #607: fix(settings): string-aware trailing-comma removal in JSONC reader (fixes #595) 2026-07-02 14:52:58 +02:00
Julius Brussee d900443b84 Merge PR #605: fix(uninstall): match managed hook basenames, not substring (fixes #593) 2026-07-02 14:52:58 +02:00
Julius Brussee 5b875b8e2e Merge PR #609: fix(openclaw): stray SOUL.md marker no longer chains into data loss (fixes #596)
# Conflicts:
#	tests/installer/e2e.freshinstall.test.mjs
2026-07-02 14:52:49 +02:00
Julius Brussee 79a14ee79f Merge PR #610: fix(opencode): --force migrates legacy AGENTS.md, never wipes it (fixes #594) 2026-07-02 14:51:43 +02:00
Shiva Vinodkumar c0e3c1e140 Add/Update .editorconfig to improve repository standards 2026-07-02 17:57:43 +05:30
Shiva Vinodkumar 79285a4c00 Add/Update SECURITY.md to improve repository standards 2026-07-02 17:57:40 +05:30
Shiva Vinodkumar 7dc87d0a32 Add/Update CODE_OF_CONDUCT.md to improve repository standards 2026-07-02 17:57:38 +05:30
AmirF194 516f917619 fix(opencode): --force migrates legacy AGENTS.md, never wipes it
--force on an AGENTS.md containing the legacy un-fenced sentinel
replaced the entire file with the fenced block — destroying all
user-authored content around the legacy block. The installer's own
hint told users with mixed files to run exactly that.

Migrate instead: back up once to AGENTS.md.bak, remove the legacy
block (exact match of the current rule body when possible, otherwise
cut from the sentinel's paragraph start — the legacy path appended the
block, so user content precedes it), and write the fenced block after
the preserved user content.

Fixes #594
2026-07-01 23:52:36 -06:00
AmirF194 ae02d2a560 fix(openclaw): stray SOUL.md marker no longer chains into data loss
A truncated/stray marker (interrupted write, partial user edit) chained
into deleting user content: appendBootstrapToSoul saw 'no complete
block' and appended a second one; stripBootstrapFromSoul then cut from
the FIRST begin to the FIRST end — spanning everything between the
stray marker and the appended block. Reported reproduction ended with
the whole SOUL.md deleted.

Replace the single-span cut with a scan that pairs each begin with the
nearest end before the next begin; unpaired markers are removed as just
the marker text, never as a span. Append now detects damaged markers
(orphans, duplicates), strips them safely, and writes one clean block.

Fixes #596
2026-07-01 23:50:28 -06:00
AmirF194 2fb7c91183 fix(hooks): NL trigger misfires + one-shot independent modes
Natural-language matching (#598):
- Deactivation computed first, word-order tolerant: 'turn caveman mode
  off' used to ACTIVATE caveman (and reset the level to default),
  'turn caveman off' was a no-op.
- 'enable caveman and stop apologizing' no longer deactivates (the old
  stop-guard fired on 'stop' anywhere, then the deactivation regex
  matched 'caveman and stop').
- Questions ('what is caveman mode?') no longer arm the mode.
- 'normal mode' deactivates only as a command or with caveman context
  ('how do I exit vim normal mode' no longer kills the session mode).
- Prompts normalized to one line so multiline input matches.
- Scoped brevity ('be brief in the summary section') is a one-off
  instruction, not a session-wide switch.

One-shot modes (#599):
- /caveman-commit|-review|-compress save the displaced prose mode to
  .caveman-active.prev and the next ordinary prompt restores it (or
  deactivates if caveman wasn't active before) — SKILL.md's 'level
  persist until changed or session end' holds again.
- Plugin-namespaced /caveman:caveman-commit and -review recognized
  (only compress and stats had the variant).
- Deactivation clears the saved prev so nothing resurrects the mode.

Fixes #598, fixes #599
2026-07-01 23:47:59 -06:00
AmirF194 704a460ef8 fix(settings): string-aware trailing-comma removal in JSONC reader
The trailing-comma sweep ran a global regex over the whole
comment-stripped output, including string contents — a JSONC
settings.json with a value containing ',}' or ',]' (shell brace
expansion, inline JSON in hook args) was silently corrupted on read
and persisted corrupted on the next write.

Replace the regex with a scan that tracks string state (same approach
as the comment stripper above it) and only drops commas outside
strings.

Fixes #595
2026-07-01 23:44:57 -06:00
AmirF194 4dad1afe84 fix(compress): never classify build files or scripts as prose
detect.py listed .dockerfile/.makefile in SKIP_EXTENSIONS, but real
files are named Dockerfile/Makefile with no extension, so they fell
through to the content heuristic and came back compressible —
/caveman-compress Dockerfile overwrote a Dockerfile with caveman prose.

Add a basename guard (Dockerfile, Makefile, Jenkinsfile, Vagrantfile,
CMakeLists.txt, ...) checked before any extension rule — CMakeLists.txt
would otherwise ride the compressible .txt rule — and a shebang check
in the extensionless branch so executable scripts are always code.

Mirror synced to plugins/caveman (sync workflow only triggers on
SKILL.md changes, so scripts/ must ride along).

Fixes #600
2026-07-01 23:36:17 -06:00
AmirF194 70ea40dced fix(uninstall): match managed hook basenames, not substring
removeCavemanHooks stripped any settings.json hook whose command
contained the substring 'caveman' anywhere — a user-authored hook like
'node ~/Projects/caveman-notes/my-hook.js' was silently deleted by
--uninstall.

Match tokens against MANAGED_HOOK_BASENAMES by exact basename instead
(win32.basename so Windows-written configs match anywhere), the same
pattern pruneOrphanedManagedHooks already uses. Hoist the tokenizer to
module scope and reuse it in the prune pass. Add caveman-statusline.ps1
to the managed set so the Windows statusline wiring is covered by
removal and orphan-pruning too.

Fixes #593
2026-07-01 23:34:41 -06:00
AmirF194 959b943ad4 fix(install): treat spawn ENOENT as failure, not success
spawnSync reports a missing binary as { status: null, error }, and the
(r.status || 0) === 0 checks coerced that null to success. On a machine
without the claude CLI, --only claude printed 'installed: claude',
skipped the standalone-hook fallback (which works offline), and left
nothing installed. Same pattern at 8 sites: claude, gemini, npx-skills
providers, mcp-shrink, runInit (both paths), uninstall, skills-auto.

Route every spawn result through spawnOk() (!r.error && r.status === 0)
and warn when the claude CLI itself could not be spawned. Regression
test runs the installer with an empty PATH and asserts failure is
reported and standalone hooks get wired.

Fixes #592
2026-07-01 23:31:35 -06:00
AmirF194 6d71b9ec6f fix(hooks): SessionStart SKILL.md path off-by-one
Hook lives at <plugin_root>/src/hooks/ but read SKILL.md via a single
'..' — resolving to nonexistent src/skills/, so every plugin install
silently fell back to the stale hardcoded ruleset (missing language
preservation, no-self-reference, intensity table).

Resolve via candidates in order: $CLAUDE_PLUGIN_ROOT/skills/,
__dirname/../../skills/ (plugin + repo layout), __dirname/../skills/
(standalone $CLAUDE_CONFIG_DIR layout). Sync the two missing rules
into the fallback for installs with no SKILL.md at all.

Fixes #587, fixes #589
2026-07-01 22:42:53 -06:00
Paul Jobson e0bb39f267 Fix for: https://github.com/JuliusBrussee/caveman/issues/585
This fixes the edge case for the following error by instantiating the
paths differently.

✘ Failed to install plugin "caveman@caveman": EXDEV: cross-device link not permitted
2026-06-30 21:44:27 -04:00
Ousama Ben YounesandClaude 93d9a439b4 fix(shrink): restore nested protected-segment sentinels (#444)
withProtectedSegments built sentinels in a single pass and restored them
in a single pass. When two PROTECTED_PATTERNS matched the same span
(e.g. path rule swallows STARTER/BUSINESS, then function-call rule
swallows the resulting type ( 0 )), the outer sentinel restored to
"type ( 0 )" but the inner " 0 " was never substituted back — enum
values reaching the model became literal "( 0 )".

Restore now loops with MAX_RESTORE_PASSES bound; same depth is reached
on the actual #444 inputs in <=2 passes.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-24 08:55:49 +00:00
Julius BrusseeandClaude Opus 4.8 e8139f86e3 fix(#524): make Hermes install/uninstall symmetric + verify against real Hermes
Adversarial review against a live Hermes Agent install (v0.11.0) found the
forward install was correct (skills land in the real ~/.hermes/skills/
productivity/<skill>/ layout, all 7 load as 'enabled' via 'hermes skills
list' — verified empirically, no version: field required), but uninstall had
NO Hermes handling: --uninstall silently orphaned all 7 skill folders forever.

- add Hermes block to uninstall() honoring HERMES_HOME (mirrors opencode/openclaw)
- tests/installer/hermes.test.mjs: install lands 7 skills, uninstall removes
  them (regression guard for the asymmetry), dry-run uninstall is a no-op
- INSTALL.md: add Hermes Agent row to the per-agent install table (CLAUDE.md
  mandates the install table stay complete)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:25:44 +02:00
Julius BrusseeandClaude Opus 4.8 6ebdb375c4 fix(#524): clean up Hermes provider entry
- restore 2-space PROVIDERS indent and 4-space dispatch-loop indent (PR
  re-indented existing gemini/opencode/openclaw lines as churn)
- correct mech label: 'native hermes skills copy' (it does a native dir
  copy via installHermes, not 'npx skills add')
- drop dead profile: 'hermes' — shadowed by the installHermes special-case
  and not a valid upstream vercel-labs/skills slug

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:05:27 +02:00
Julius Brussee 62446eb525 Merge PR #524: add Hermes Agent install support 2026-06-14 22:03:00 +02:00
Julius BrusseeandClaude Opus 4.8 62e77e66ff fix(#527): correct stale checksums for caveman-activate.js + cavecrew-model-overrides.js
PR #527 added cavecrew-model-overrides.js with a wrong sha256 (eae3... vs
actual 9f26...) and modified caveman-activate.js without regenerating its
entry. bin/install.js verifies downloaded hooks against this manifest and
aborts on mismatch, so both were latent install-breakers on the remote path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:02:49 +02:00
Julius Brussee f60a45a98d Merge PR #527: per-agent cavecrew model overrides (#521) 2026-06-14 22:01:44 +02:00
Julius Brussee c1ac0664c9 Merge PR #505: register /caveman-stats slash command (#470) 2026-06-14 22:01:18 +02:00
Ijtihed Kilani a325c64dd4 feat(cavecrew): add per-agent model overrides 2026-06-14 13:16:56 +03:00
vagesh 8753bf90d5 feat(install): add Hermes Agent support
Adds Hermes Agent as a supported provider with native skill installation.
Hermes Agent uses SKILL.md format (same as upstream), so the installer
copies all 7 caveman skills directly to ~/.hermes/skills/productivity/.

Closes #45914 (related)
2026-06-14 12:29:42 +10:00
Julius Brussee 25d22f864a Update README.md 2026-06-12 15:51:04 +02:00
Julius BrusseeandClaude Opus 4.8 32f37af81a chore(release): pin remote fetches to v1.9.0
First tag shipping src/hooks/checksums.sha256 — with PINNED_REF now
pointing at it, curl|bash / detached installs fetch hook files from the
immutable v1.9.0 ref and SHA-256 enforcement activates fully (#261,
#262). Manifest verified current against src/hooks/ before the bump.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v1.9.0
2026-06-12 14:57:52 +02:00
Julius BrusseeandClaude Opus 4.8 ddf212173a fix(opencode): plugin now loads in compiled Bun runtime
Smoke-tested against real opencode 1.4.0 (the missing verification
flagged in 22f75e3) — the plugin never loaded: opencode runs plugins
inside a compiled Bun binary where require() of on-disk files is
rejected ('require() async module is unsupported') and await import()
of a CJS file returns an empty namespace. caveman-config.cjs is now
evaluated as CommonJS by hand (readFileSync + Function wrapper with a
createRequire shim — built-ins still resolve fine).

Three more real-runtime gaps found and fixed in the same pass:
- session-init flag write now also happens at plugin factory time; in
  one-shot 'opencode run' the first session.created publishes before
  plugin event dispatch is wired, so the event handler alone missed it
- the TUI expands '/caveman <level>' into the command template before
  chat.message fires; the parser now recovers the level from the
  expanded 'Activate caveman mode: <level>' text
- the non-interactive run path wraps messages in literal quotes
  ('"/caveman ultra"'); the parser unwraps symmetric quotes

Verified end-to-end against opencode 1.4.0: plugin loads clean,
session-init writes the flag, /caveman ultra flips it, 'stop caveman'
deletes it, and the reinforcement line shows up in the outgoing LLM
system prompt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:57:15 +02:00
github-actions[bot] 22e59bf067 chore: sync SKILL.md copies [skip ci] 2026-06-12 12:17:17 +00:00
Julius BrusseeandClaude Opus 4.8 efd490a5fc test: fix caveman-init counts, isolate openclaw ws
Counts were stale after the opencode + openclaw targets landed (5 -> 6
repo files, 7 with the openclaw line). Tests also ran the openclaw
installer against the developer's real ~/.openclaw/workspace; runInit()
now pins OPENCLAW_WORKSPACE inside the fixture tmp dir so nothing
escapes the sandbox. verify_repo.py drops the removed
.agents/plugins/marketplace.json from its manifest list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:13:28 +02:00
Julius BrusseeandClaude Opus 4.8 eb447dad2e chore: remove stale dotdir cavecrew mirrors
.junie/, .kiro/, .roo/, .agents/ held pre-cleanup cavecrew/SKILL.md
mirrors (plus an unused .agents/plugins/marketplace.json). Nothing in
the current install path reads them — bin/install.js handles Codex via
npx skills add, and Claude Code marketplace discovery uses
.claude-plugin/marketplace.json. CLAUDE.md marks these remove-on-sight.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:12:04 +02:00
Julius Brussee baf10366f6 Add Sponsors section and Atlas Cloud logos
Add a Sponsors section to README promoting Atlas Cloud with a centered logo, link, and a call to sponsor the project. Include two new SVG assets (atlas-cloud.svg and atlas-cloud-dark.svg) under docs/assets for light/dark mode logo display.
2026-06-12 14:05:15 +02:00
Ousama Ben YounesandClaude Opus 4.7 b5e8cdaf1f fix(commands): add caveman-stats.toml so Claude Code registers /caveman-stats
Without commands/caveman-stats.toml on disk Claude Code rejects
/caveman-stats as 'Unknown command' before the UserPromptSubmit
hook in src/hooks/caveman-mode-tracker.js can intercept it. README
and INSTALL.md both advertise the command; this brings the slash
command registry in line with the docs.

Fixes #470

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-10 10:04:13 +00:00
Julius BrusseeandClaude Opus 4.8 bdcba4c6ef chore: sync plugin mirror + dist locally (replicates CI sync-skill)
Verbatim copies of edited sources into the CI-managed plugins/caveman mirror and rebuilt dist/caveman.skill, so local main is self-consistent without a push. CI's sync-skill.yml regenerates these on push; this just keeps verify_repo green locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:05:24 +02:00
Julius BrusseeandClaude Opus 4.8 22f75e3de6 fix(opencode): real lifecycle hooks + ship caveman-compress command
Folds in #419 (replace the non-existent session.created/tui.prompt.append hooks with real opencode hooks: event dispatcher for session.created, chat.message for mode parsing, experimental.chat.system.transform for reinforcement; fixes #418/#421), #398 (ship the missing caveman-compress.md command + un-ignore it; fixes #426/#451/#464), and #376 plugin-side (drop %APPDATA% branch). Smoke test rewritten for the new hook shapes. NOTE: not smoke-tested against a real opencode runtime here — verify before release.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:05:24 +02:00
Julius BrusseeandClaude Opus 4.8 f0dd780305 fix(install): Windows/Copilot/skills fixes, hook-wiring + MCP-shrink, security hardening
Installer fixes: #414 (rename PS1 $Args->$InstallerArgs), #437 (detect Copilot via extension dirs, fixes #336), #395 (--skill '*' instead of --all so -a <agent> is honored, fixes #389), #472 (prune orphaned managed hooks from settings.json, fixes #471), #393 (don't double-wire hooks when the plugin manifest already does, fixes #392), #380 (MCP-shrink off by default, requires an upstream, fixes #474), #376 install-side (opencode uses ~/.config/opencode, drop %APPDATA%), #443 (strip tools: from cavecrew agent copies for opencode, #386), #434 (existsSync guard on command copy), #396 (doc: discover profile slugs via --list).

Security hardening: #261 (pin remote fetch to release tag PINNED_REF=v1.8.2, not moving main) and #262 (SHA-256-verify downloaded hook files against src/hooks/checksums.sha256 before they execute; abort on mismatch). #260 (inspect-before-run note). NOTE: enforcement activates fully once a release tag shipping checksums.sha256 is published and PINNED_REF is bumped; v1.8.2 predates the manifest so downloads there warn-and-proceed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:05:24 +02:00
Julius BrusseeandClaude Opus 4.8 cd4009effa feat(config): repo-local .caveman/config.json + NL brevity triggers
Folds in #429 (repo-local <repo>/.caveman/config.json resolution layer between env and user config; symlink-safe, bounded walk) and #248 intent (recognize 'less tokens'/'be brief'/'be terse' as natural-language caveman activation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:04:58 +02:00
Julius BrusseeandClaude Opus 4.8 6ce47d4445 fix(mcp-shrink): shell:true on Windows so npx/.cmd upstream resolves
Folds in #387 — extract spawn options to spawn-options.js; shell:true only on win32 (PATHEXT resolution), POSIX unchanged. Args still come from installer-controlled config (trust boundary unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:04:58 +02:00
Julius BrusseeandClaude Opus 4.8 46de578a7e fix(docs): escape user input in demo terminal (XSS)
Folds in #438 — the docs demo terminal interpolated user input via innerHTML (real reflected/DOM XSS); build nodes with textContent instead. (PR title 'CLI input handler' was a misnomer.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:04:58 +02:00
Julius BrusseeandClaude Opus 4.8 f68111acc3 fix(stats): Opus output price $75->$25 for 4.5+ era; Windows statusline UTF-8
Folds in #466 (correct Opus 4.5-4.8 output price to $25/M, keep legacy 4.0/4.1 carve-outs at $75/M; fixes #465) and #459 (UTF-8 console + Get-Content so the pickaxe renders on Windows; +spacing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 21:04:58 +02:00