dsh-caveman 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES +37 -0
- package/cordis.patch.yml +5 -0
- package/lib/client.js +71 -0
- package/lib/index.js +193 -0
- package/package.json +40 -0
- package/skills/cavecrew/README.md +61 -0
- package/skills/cavecrew/SKILL.md +82 -0
- package/skills/caveman/README.md +48 -0
- package/skills/caveman/SKILL.md +78 -0
- package/skills/caveman-commit/README.md +44 -0
- package/skills/caveman-commit/SKILL.md +65 -0
- package/skills/caveman-compress/README.md +163 -0
- package/skills/caveman-compress/SECURITY.md +31 -0
- package/skills/caveman-compress/SKILL.md +111 -0
- package/skills/caveman-compress/scripts/__init__.py +9 -0
- package/skills/caveman-compress/scripts/__main__.py +3 -0
- package/skills/caveman-compress/scripts/benchmark.py +80 -0
- package/skills/caveman-compress/scripts/cli.py +85 -0
- package/skills/caveman-compress/scripts/compress.py +342 -0
- package/skills/caveman-compress/scripts/detect.py +139 -0
- package/skills/caveman-compress/scripts/validate.py +213 -0
- package/skills/caveman-help/README.md +38 -0
- package/skills/caveman-help/SKILL.md +63 -0
- package/skills/caveman-review/README.md +33 -0
- package/skills/caveman-review/SKILL.md +55 -0
- package/skills/caveman-stats/README.md +30 -0
- package/skills/caveman-stats/SKILL.md +10 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Third-party notices for dsh-caveman
|
|
2
|
+
====================================
|
|
3
|
+
|
|
4
|
+
This package bundles skills under `skills/`. Their provenance:
|
|
5
|
+
|
|
6
|
+
- `skills/caveman-*` (caveman, caveman-commit, caveman-compress,
|
|
7
|
+
caveman-help, caveman-review, caveman-stats): derived from / inspired by
|
|
8
|
+
the open-source caveman toolkit
|
|
9
|
+
(https://github.com/JuliusBrussee/caveman), which declares an MIT license
|
|
10
|
+
("this MIT license covers this repo"). The Python scripts under
|
|
11
|
+
`skills/caveman-compress/scripts/` are covered by that MIT declaration.
|
|
12
|
+
Redistributed under MIT with gratitude to the original author.
|
|
13
|
+
|
|
14
|
+
- `skills/cavecrew`: original work of this package's authors.
|
|
15
|
+
|
|
16
|
+
MIT License
|
|
17
|
+
-----------
|
|
18
|
+
|
|
19
|
+
Copyright (c) 2026 dsh-caveman contributors
|
|
20
|
+
|
|
21
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
22
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
23
|
+
in the Software without restriction, including without limitation the rights
|
|
24
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
25
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
26
|
+
furnished to do so, subject to the following conditions:
|
|
27
|
+
|
|
28
|
+
The above copyright notice and this permission notice shall be included in all
|
|
29
|
+
copies or substantial portions of the Software.
|
|
30
|
+
|
|
31
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
32
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
33
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
34
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
35
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
36
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
37
|
+
SOFTWARE.
|
package/cordis.patch.yml
ADDED
package/lib/client.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-caveman",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
const React = require("react");
|
|
8
|
+
|
|
9
|
+
// Badge display is centralized in dsh-badges: this plugin only registers
|
|
10
|
+
// a badge descriptor (projection key + pure appearance renderer). The
|
|
11
|
+
// renderer maps the 'caveman' projection value to badge appearance, or
|
|
12
|
+
// null when the mode is off. Functionality (projection unit, /caveman
|
|
13
|
+
// command, prompt-section injection) lives in the host half.
|
|
14
|
+
const inject = ["slots"];
|
|
15
|
+
|
|
16
|
+
function apply(ctx) {
|
|
17
|
+
// The badge registry is provided by dsh-badges. Bundle activation order
|
|
18
|
+
// is not guaranteed (no inject edge), so registering inside the dock
|
|
19
|
+
// slots.inject callback can still race it. Retry with a growing backoff
|
|
20
|
+
// until the registry appears (idempotent: registry.register is a Map
|
|
21
|
+
// set). Stops after ~2 minutes; a missing registry only costs a badge.
|
|
22
|
+
const register = () => {
|
|
23
|
+
const registry = ctx.get("badgeRegistry");
|
|
24
|
+
if (registry === undefined) return false;
|
|
25
|
+
registry.register({
|
|
26
|
+
key: "caveman",
|
|
27
|
+
projection: "caveman",
|
|
28
|
+
title: "Click to cycle caveman mode: off -> lite -> full -> ultra",
|
|
29
|
+
onClick: (sessionId) => {
|
|
30
|
+
if (!sessionId) return;
|
|
31
|
+
try {
|
|
32
|
+
fetch("/caveman/toggle", {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "content-type": "application/json" },
|
|
35
|
+
body: JSON.stringify({ sessionId }),
|
|
36
|
+
}).catch(() => {});
|
|
37
|
+
} catch (e) {
|
|
38
|
+
/* fetch unavailable: no-op */
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
render: (value) => {
|
|
42
|
+
const mode = value && typeof value === "object" ? value.mode : undefined;
|
|
43
|
+
const on = mode && mode !== "off";
|
|
44
|
+
const label = !on
|
|
45
|
+
? "[CAVEMAN:OFF]"
|
|
46
|
+
: mode === "full"
|
|
47
|
+
? "[CAVEMAN]"
|
|
48
|
+
: "[CAVEMAN:" + mode.toUpperCase() + "]";
|
|
49
|
+
return on
|
|
50
|
+
? { label, color: "#d97706", bg: "rgba(217,119,6,.14)" }
|
|
51
|
+
: { label, color: "#6b7280", bg: "rgba(107,114,128,.12)" };
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return true;
|
|
55
|
+
};
|
|
56
|
+
const tryRegister = (delayMs) => {
|
|
57
|
+
if (register()) return;
|
|
58
|
+
if (typeof setTimeout !== "function" || delayMs > 15000) return;
|
|
59
|
+
setTimeout(() => tryRegister(delayMs * 2), delayMs);
|
|
60
|
+
};
|
|
61
|
+
ctx.slots.inject("conversation.input.dock", () => {
|
|
62
|
+
if (register()) return;
|
|
63
|
+
Promise.resolve().then(() => tryRegister(500));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
exports.apply = apply;
|
|
68
|
+
exports.inject = inject;
|
|
69
|
+
return module.exports;
|
|
70
|
+
},
|
|
71
|
+
});
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// dsh-caveman: per-session caveman communication mode.
|
|
2
|
+
// - sessionProjections unit 'caveman' folds `caveman/change` session events
|
|
3
|
+
// (default 'full'; per-session by construction, no cross-agent sharing)
|
|
4
|
+
// - /caveman command and plain-text "caveman <mode>" directive (agent/pre-step)
|
|
5
|
+
// append the change event; directive-only user messages are consumed
|
|
6
|
+
// - system-prompt section injects the current mode as an overriding directive
|
|
7
|
+
// - composer dock badge (client half, lib/client.js) renders via
|
|
8
|
+
// useProjection('caveman')
|
|
9
|
+
//
|
|
10
|
+
// OUT-OF-REPO EVENT VOCABULARY:
|
|
11
|
+
// `caveman/change` is not in the harness's static KNOWN_SESSION_EVENT_TYPES
|
|
12
|
+
// (generated in @deepseek-ai/dsh-session), so a session log containing it is
|
|
13
|
+
// refused on load unless the type is registered or the event carries
|
|
14
|
+
// `ignorable: true` (append() cannot set that flag). We register the type at
|
|
15
|
+
// apply() time on the SAME module instance the persistence loader imports
|
|
16
|
+
// (both resolve to <workspace>/node_modules/@deepseek-ai/dsh-session), so
|
|
17
|
+
// every boot WITH this plugin can read back its events. Logs written before
|
|
18
|
+
// this fix were repaired in place by .dsh/scripts/repair-caveman-events.py /
|
|
19
|
+
// fix-d8b43aa8.py (ignorable: true injected, 2-frame zstd layout).
|
|
20
|
+
import { z } from 'zod'
|
|
21
|
+
import { KNOWN_SESSION_EVENT_TYPES } from '@deepseek-ai/dsh-session'
|
|
22
|
+
|
|
23
|
+
export const name = 'caveman'
|
|
24
|
+
// Hard dependency on the HTTP route registry for the badge-click toggle
|
|
25
|
+
// route (same rationale as dsh-rtk's inject).
|
|
26
|
+
export const inject = ['webServer']
|
|
27
|
+
|
|
28
|
+
const VALID = ['off', 'lite', 'full', 'ultra', 'wenyan-lite', 'wenyan-full', 'wenyan-ultra']
|
|
29
|
+
const DIRECTIVE_RE = /^\/?caveman\s+(off|lite|full|ultra|wenyan-lite|wenyan-full|wenyan-ultra)$/i
|
|
30
|
+
const OFF_RE = /^(stop\s+caveman|normal\s+mode)$/i
|
|
31
|
+
|
|
32
|
+
const schema = z.object({ mode: z.enum(VALID) })
|
|
33
|
+
|
|
34
|
+
function parseDirective(text) {
|
|
35
|
+
if (typeof text !== 'string') return null
|
|
36
|
+
const t = text.trim()
|
|
37
|
+
const m = DIRECTIVE_RE.exec(t)
|
|
38
|
+
if (m) return m[1].toLowerCase()
|
|
39
|
+
if (OFF_RE.test(t)) return 'off'
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function directiveOf(message) {
|
|
44
|
+
const blocks = message && message.content
|
|
45
|
+
if (!Array.isArray(blocks) || blocks.length === 0) return null
|
|
46
|
+
for (const b of blocks) {
|
|
47
|
+
if (!b || typeof b !== 'object' || b.type !== 'text') return null
|
|
48
|
+
}
|
|
49
|
+
return parseDirective(blocks.map((b) => b.text).join(''))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function apply(ctx) {
|
|
53
|
+
// Register our event type on the shared KNOWN set so session logs
|
|
54
|
+
// containing `caveman/change` load in any boot that mounts this plugin.
|
|
55
|
+
try {
|
|
56
|
+
KNOWN_SESSION_EVENT_TYPES.add('caveman/change')
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.warn('[caveman] could not register event type:', err && err.message)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const projections = ctx.get('sessionProjections')
|
|
62
|
+
|
|
63
|
+
if (projections !== undefined) {
|
|
64
|
+
projections.register({
|
|
65
|
+
key: 'caveman',
|
|
66
|
+
schema,
|
|
67
|
+
stateVersion: 1,
|
|
68
|
+
init: () => ({ mode: 'full' }),
|
|
69
|
+
apply: (state, event) => {
|
|
70
|
+
if (!event || event.type !== 'caveman/change') return state
|
|
71
|
+
const mode = event.data && typeof event.data.mode === 'string' ? event.data.mode : ''
|
|
72
|
+
if (!VALID.includes(mode) || state.mode === mode) return state
|
|
73
|
+
return { mode }
|
|
74
|
+
},
|
|
75
|
+
view: (state) => ({ mode: state.mode }),
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const commands = ctx.get('commands')
|
|
80
|
+
if (commands !== undefined) {
|
|
81
|
+
commands.register({
|
|
82
|
+
name: 'caveman',
|
|
83
|
+
description: 'Set caveman communication mode',
|
|
84
|
+
input: { hint: 'lite|full|ultra|wenyan-lite|wenyan-full|wenyan-ultra|off' },
|
|
85
|
+
handler: (invocation) => {
|
|
86
|
+
const mode = invocation.rawInput.trim().toLowerCase()
|
|
87
|
+
if (!VALID.includes(mode)) {
|
|
88
|
+
return { kind: 'error', text: 'Invalid mode: "' + invocation.rawInput.trim() + '". Valid: ' + VALID.join('|') }
|
|
89
|
+
}
|
|
90
|
+
invocation.agent.session.append('caveman/change', { mode })
|
|
91
|
+
return { kind: 'success', text: mode === 'off' ? 'Caveman mode: off' : 'Caveman mode: ' + mode }
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
ctx.on('agent/pre-step', (payload, next) => {
|
|
97
|
+
if (!payload || !payload.agent || !Array.isArray(payload.messages)) return next()
|
|
98
|
+
let mode = null
|
|
99
|
+
const kept = []
|
|
100
|
+
for (const m of payload.messages) {
|
|
101
|
+
const parsed = directiveOf(m)
|
|
102
|
+
if (parsed !== null) mode = parsed
|
|
103
|
+
else kept.push(m)
|
|
104
|
+
}
|
|
105
|
+
if (mode === null) return next()
|
|
106
|
+
payload.agent.session.append('caveman/change', { mode })
|
|
107
|
+
if (kept.length === 0) return { kind: 'reject' }
|
|
108
|
+
return { kind: 'enter', messages: kept }
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// ---- badge click toggle: POST /caveman/toggle { sessionId } -------------
|
|
112
|
+
// The composer badge's onClick cycles the mode off -> lite -> full -> ultra
|
|
113
|
+
// -> off through the same caveman/change event path as /caveman on|off, so
|
|
114
|
+
// UI, projection, and prompt-section all agree via the session log.
|
|
115
|
+
const CYCLE = ['off', 'lite', 'full', 'ultra']
|
|
116
|
+
const webServer = ctx.get('webServer')
|
|
117
|
+
if (webServer !== undefined) {
|
|
118
|
+
try {
|
|
119
|
+
webServer.register({
|
|
120
|
+
kind: 'exact',
|
|
121
|
+
path: '/caveman/toggle',
|
|
122
|
+
handler: async (req, res) => {
|
|
123
|
+
if (req.method !== 'POST') {
|
|
124
|
+
res.writeHead(405)
|
|
125
|
+
res.end()
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
let raw = ''
|
|
129
|
+
try {
|
|
130
|
+
for await (const chunk of req) raw += chunk
|
|
131
|
+
} catch (e) {
|
|
132
|
+
res.writeHead(400)
|
|
133
|
+
res.end(JSON.stringify({ ok: false, error: 'bad body' }))
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
let sessionId
|
|
137
|
+
try {
|
|
138
|
+
sessionId = JSON.parse(raw || '{}').sessionId
|
|
139
|
+
} catch (e) {
|
|
140
|
+
sessionId = undefined
|
|
141
|
+
}
|
|
142
|
+
const store = ctx.get('sessions')
|
|
143
|
+
const session = typeof sessionId === 'string' && store !== undefined ? store.get(sessionId) : undefined
|
|
144
|
+
if (session === undefined) {
|
|
145
|
+
res.writeHead(404)
|
|
146
|
+
res.end(JSON.stringify({ ok: false, error: 'session not found' }))
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
let mode = 'full'
|
|
150
|
+
if (projections !== undefined) {
|
|
151
|
+
try {
|
|
152
|
+
const value = projections.snapshot(session).values.caveman
|
|
153
|
+
if (value && typeof value.mode === 'string') mode = value.mode
|
|
154
|
+
} catch (e) {
|
|
155
|
+
mode = 'full'
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const at = CYCLE.indexOf(mode)
|
|
159
|
+
const next = CYCLE[(at === -1 ? 0 : at) + 1] === undefined ? CYCLE[0] : CYCLE[at + 1]
|
|
160
|
+
session.append('caveman/change', { mode: next })
|
|
161
|
+
res.writeHead(200, { 'content-type': 'application/json' })
|
|
162
|
+
res.end(JSON.stringify({ ok: true, mode: next }))
|
|
163
|
+
},
|
|
164
|
+
})
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.error('[caveman] /caveman/toggle route registration failed:', e && e.message)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const systemPrompt = ctx.get('systemPrompt')
|
|
171
|
+
if (systemPrompt !== undefined) {
|
|
172
|
+
systemPrompt.section({
|
|
173
|
+
name: 'caveman-mode',
|
|
174
|
+
order: 50,
|
|
175
|
+
text: (context) => {
|
|
176
|
+
const agent = context && context.agent
|
|
177
|
+
if (!agent || projections === undefined) return ''
|
|
178
|
+
let mode = 'full'
|
|
179
|
+
try {
|
|
180
|
+
const value = projections.snapshot(agent.session).values.caveman
|
|
181
|
+
if (value && typeof value.mode === 'string') mode = value.mode
|
|
182
|
+
} catch (err) {
|
|
183
|
+
mode = 'full'
|
|
184
|
+
}
|
|
185
|
+
if (mode === 'off') return ''
|
|
186
|
+
const tag = mode === 'full' ? '[CAVEMAN]' : '[CAVEMAN:' + mode.toUpperCase() + ']'
|
|
187
|
+
return tag + ' Current user-set communication style. Follow the caveman skill rules at intensity "' + mode + '" for every response; this overrides any default in AGENTS.md.'
|
|
188
|
+
},
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
console.log('[caveman] host active (event projection + KNOWN registration)')
|
|
193
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-caveman",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./lib/index.js",
|
|
8
|
+
"./client": "./lib/client.js",
|
|
9
|
+
"./package.json": "./package.json"
|
|
10
|
+
},
|
|
11
|
+
"description": "Per-session caveman mode state (session projection unit) + composer dock badge + /caveman command + prompt-section injection. Ships the caveman family skills.",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"dsh",
|
|
15
|
+
"deepseek-harness",
|
|
16
|
+
"plugin",
|
|
17
|
+
"caveman",
|
|
18
|
+
"compression",
|
|
19
|
+
"token",
|
|
20
|
+
"cordis"
|
|
21
|
+
],
|
|
22
|
+
"files": [
|
|
23
|
+
"lib",
|
|
24
|
+
"skills",
|
|
25
|
+
"cordis.patch.yml",
|
|
26
|
+
"THIRD_PARTY_NOTICES"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"zod": "^4.4.3"
|
|
30
|
+
},
|
|
31
|
+
"dsh": {
|
|
32
|
+
"bundle": {
|
|
33
|
+
"patch": "./cordis.patch.yml"
|
|
34
|
+
},
|
|
35
|
+
"client": {
|
|
36
|
+
"platform": "web",
|
|
37
|
+
"inject": []
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# cavecrew
|
|
2
|
+
|
|
3
|
+
Decision guide. When to delegate to caveman subagents instead of doing the work inline.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Tells the main thread when to spawn a caveman-style subagent versus the vanilla equivalent. The win: subagent tool-results inject back into main context verbatim, and caveman output is roughly 1/3 the size of vanilla prose. Across 20 delegations in one session, that is the difference between context exhaustion and finishing the task.
|
|
8
|
+
|
|
9
|
+
Three subagents:
|
|
10
|
+
|
|
11
|
+
| Subagent | Job | Use when |
|
|
12
|
+
|----------|-----|----------|
|
|
13
|
+
| `cavecrew-investigator` | Locate code (read-only) | "Where is X defined / what calls Y / list uses of Z" |
|
|
14
|
+
| `cavecrew-builder` | Surgical edit, 1-2 files | Scope is obvious, ≤2 files. Refuses 3+ file scope. |
|
|
15
|
+
| `cavecrew-reviewer` | Diff/file review | One-line findings with severity emoji |
|
|
16
|
+
|
|
17
|
+
Use vanilla `Explore` or `Code Reviewer` when you want prose, architecture commentary, or rationale. Use main thread directly for one-line answers and 3+ file refactors.
|
|
18
|
+
|
|
19
|
+
This skill is a decision guide, not a slash command. It activates when the conversation mentions delegation.
|
|
20
|
+
|
|
21
|
+
## How to invoke
|
|
22
|
+
|
|
23
|
+
Triggers on phrases like "delegate to subagent", "use cavecrew", "spawn investigator", "save context", "compressed agent output".
|
|
24
|
+
|
|
25
|
+
## Example chaining
|
|
26
|
+
|
|
27
|
+
Locate → fix → verify (most common):
|
|
28
|
+
|
|
29
|
+
1. `cavecrew-investigator` returns site list (`path:line — symbol — note`)
|
|
30
|
+
2. Main thread picks 1-2 sites, hands paths to `cavecrew-builder`
|
|
31
|
+
3. `cavecrew-reviewer` audits the resulting diff
|
|
32
|
+
|
|
33
|
+
Parallel scout: spawn 2-3 `cavecrew-investigator` calls in one message with different angles (defs, callers, tests). Aggregate in main.
|
|
34
|
+
|
|
35
|
+
## Model overrides
|
|
36
|
+
|
|
37
|
+
By default, `cavecrew-reviewer` and `cavecrew-investigator` pin `model: haiku` in their frontmatter; `cavecrew-builder` has no `model:` line (uses the API session default). Set env vars in your shell before launching Claude Code to override per-agent:
|
|
38
|
+
|
|
39
|
+
| Env var | Agent |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `CAVECREW_REVIEWER_MODEL` | `cavecrew-reviewer` |
|
|
42
|
+
| `CAVECREW_BUILDER_MODEL` | `cavecrew-builder` |
|
|
43
|
+
| `CAVECREW_INVESTIGATOR_MODEL` | `cavecrew-investigator` |
|
|
44
|
+
|
|
45
|
+
Example — run reviewer on sonnet, keep others on default:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
export CAVECREW_REVIEWER_MODEL=sonnet
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Use the same model name strings you'd use in any Claude Code agent frontmatter (e.g. `haiku`, `sonnet`, `opus`).
|
|
52
|
+
|
|
53
|
+
Overrides patch only the `model:` line in the installed agent's frontmatter; the prompt body is untouched and keeps receiving upstream updates. Plugin installs only — standalone hook installs have no local agent files to patch. Unset or blank = no change. The patch persists in the installed file until the plugin is updated or reinstalled.
|
|
54
|
+
|
|
55
|
+
## See also
|
|
56
|
+
|
|
57
|
+
- [`SKILL.md`](./SKILL.md) — full decision matrix and output contracts
|
|
58
|
+
- [`agents/cavecrew-investigator.md`](../../agents/cavecrew-investigator.md)
|
|
59
|
+
- [`agents/cavecrew-builder.md`](../../agents/cavecrew-builder.md)
|
|
60
|
+
- [`agents/cavecrew-reviewer.md`](../../agents/cavecrew-reviewer.md)
|
|
61
|
+
- [Caveman README](../../README.md) — repo overview
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cavecrew
|
|
3
|
+
description: >
|
|
4
|
+
Decision guide for delegating to caveman-style subagents. Tells the main
|
|
5
|
+
thread WHEN to spawn `cavecrew-investigator` (locate code), `cavecrew-builder`
|
|
6
|
+
(1-2 file edit), or `cavecrew-reviewer` (diff review) instead of doing the
|
|
7
|
+
work inline or using vanilla `Explore`. Subagent output is caveman-compressed
|
|
8
|
+
so the tool-result injected back into main context is ~60% smaller — main
|
|
9
|
+
context lasts longer across long sessions.
|
|
10
|
+
Trigger: "delegate to subagent", "use cavecrew", "spawn investigator/builder/reviewer",
|
|
11
|
+
"save context", "compressed agent output".
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Cavecrew = three subagent presets that emit caveman output. Same job as Anthropic defaults (`Explore`, edit-style agents, reviewer); difference is the tool-result they return is compressed, so main context shrinks per delegation.
|
|
15
|
+
|
|
16
|
+
## When to use cavecrew vs alternatives
|
|
17
|
+
|
|
18
|
+
| Task | Use |
|
|
19
|
+
|---|---|
|
|
20
|
+
| "Where is X defined / what calls Y / list uses of Z" | `cavecrew-investigator` |
|
|
21
|
+
| Same but you also want suggestions/architecture commentary | `Explore` (vanilla) |
|
|
22
|
+
| Surgical edit, ≤2 files, scope obvious | `cavecrew-builder` |
|
|
23
|
+
| New feature / 3+ files / cross-cutting refactor | Main thread or `feature-dev:code-architect` |
|
|
24
|
+
| Review diff, branch, or file for bugs | `cavecrew-reviewer` |
|
|
25
|
+
| Deep code review with rationale + alternatives | `Code Reviewer` (vanilla) |
|
|
26
|
+
| One-line answer you already know | Main thread, no subagent |
|
|
27
|
+
|
|
28
|
+
Rule of thumb: **if you'd want the subagent's output in 1/3 the tokens, pick cavecrew. If you'd want prose, pick vanilla.**
|
|
29
|
+
|
|
30
|
+
## Why this exists (the real win)
|
|
31
|
+
|
|
32
|
+
Subagent tool results get injected into main context verbatim. A vanilla `Explore` that returns 2k tokens of prose costs 2k tokens of main-context budget every time. The same finding from `cavecrew-investigator` returns ~700 tokens. Across 20 delegations in one session that's the difference between context exhaustion and finishing the task.
|
|
33
|
+
|
|
34
|
+
## Output contracts
|
|
35
|
+
|
|
36
|
+
What main thread can rely on per agent:
|
|
37
|
+
|
|
38
|
+
**`cavecrew-investigator`**
|
|
39
|
+
```
|
|
40
|
+
<Header>:
|
|
41
|
+
- path:line — `symbol` — short note
|
|
42
|
+
totals: <counts>.
|
|
43
|
+
```
|
|
44
|
+
Or `No match.` Always file-path-first, line-number-attached, backticked symbols. Safe to grep with `path:\d+`.
|
|
45
|
+
|
|
46
|
+
**`cavecrew-builder`**
|
|
47
|
+
```
|
|
48
|
+
<path:line-range> — <change ≤10 words>.
|
|
49
|
+
verified: <re-read OK | mismatch @ path:line>.
|
|
50
|
+
```
|
|
51
|
+
Or one of: `too-big.` / `needs-confirm.` / `ambiguous.` / `regressed.` (terminal first token).
|
|
52
|
+
|
|
53
|
+
**`cavecrew-reviewer`**
|
|
54
|
+
```
|
|
55
|
+
path:line: <emoji> <severity>: <problem>. <fix>.
|
|
56
|
+
totals: N🔴 N🟡 N🔵 N❓
|
|
57
|
+
```
|
|
58
|
+
Or `No issues.` Findings sorted file → line ascending.
|
|
59
|
+
|
|
60
|
+
## Chaining patterns
|
|
61
|
+
|
|
62
|
+
**Locate → fix → verify** (most common):
|
|
63
|
+
1. `cavecrew-investigator` returns site list.
|
|
64
|
+
2. Main thread picks 1-2 sites, hands paths to `cavecrew-builder`.
|
|
65
|
+
3. `cavecrew-reviewer` audits the diff.
|
|
66
|
+
|
|
67
|
+
**Parallel scout** (when investigation is broad):
|
|
68
|
+
Spawn 2-3 `cavecrew-investigator` calls in one message (different angles: defs vs callers vs tests). Aggregate in main thread.
|
|
69
|
+
|
|
70
|
+
**Single-shot edit** (when site is already known):
|
|
71
|
+
Skip investigator. Hand exact path:line to `cavecrew-builder` directly.
|
|
72
|
+
|
|
73
|
+
## What NOT to do
|
|
74
|
+
|
|
75
|
+
- Don't use `cavecrew-builder` when you don't already know the file. Spawn investigator first or main thread will eat tokens passing context.
|
|
76
|
+
- Don't chain `cavecrew-investigator → cavecrew-builder` for a 5-file refactor. Builder will return `too-big.` and you'll have wasted a turn.
|
|
77
|
+
- Don't ask `cavecrew-reviewer` for "general feedback" — it returns findings only, no architecture opinions. Use `Code Reviewer` for that.
|
|
78
|
+
- Don't expect prose. Cavecrew output is structured, sometimes terse to the point of cryptic. If a human will read it directly, paraphrase.
|
|
79
|
+
|
|
80
|
+
## Auto-clarity (inherited)
|
|
81
|
+
|
|
82
|
+
Subagents drop caveman → normal English for security warnings, irreversible-action confirmations, and any output where fragment ambiguity could be misread. Resume caveman after.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# caveman
|
|
2
|
+
|
|
3
|
+
Talk like smart caveman. Same brain, fewer tokens.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Compress every model response to caveman-style prose. Drops articles, filler, pleasantries, and hedging. Keeps every technical detail, code block, error string, and symbol exact. Cuts 65% of output tokens (measured) with full accuracy preserved. Mode persists for the whole session until changed or stopped.
|
|
8
|
+
|
|
9
|
+
Six intensity levels:
|
|
10
|
+
|
|
11
|
+
| Level | What change |
|
|
12
|
+
|-------|-------------|
|
|
13
|
+
| `lite` | Drop filler/hedging. Sentences stay full. Professional but tight. |
|
|
14
|
+
| `full` | Default. Drop articles, fragments OK, short synonyms. |
|
|
15
|
+
| `ultra` | Bare fragments. Abbreviations (DB, auth, fn). Arrows for causality. |
|
|
16
|
+
| `wenyan-lite` | Classical Chinese register, light compression. |
|
|
17
|
+
| `wenyan-full` | Maximum 文言文. 80-90% character reduction. |
|
|
18
|
+
| `wenyan-ultra` | Extreme classical compression. |
|
|
19
|
+
|
|
20
|
+
Auto-clarity rule: caveman drops to normal prose for security warnings, irreversible-action confirmations, multi-step sequences where fragment ambiguity risks misread, and when user repeats a question. Resumes after the clear part.
|
|
21
|
+
|
|
22
|
+
## How to invoke
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
/caveman # full mode (default)
|
|
26
|
+
/caveman lite # lighter compression
|
|
27
|
+
/caveman ultra # extreme compression
|
|
28
|
+
/caveman wenyan # classical Chinese
|
|
29
|
+
stop caveman # back to normal prose
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Example output
|
|
33
|
+
|
|
34
|
+
Question: "Why does my React component re-render?"
|
|
35
|
+
|
|
36
|
+
Normal prose:
|
|
37
|
+
> Your component re-renders because you create a new object reference each render. Wrapping it in `useMemo` will fix the issue.
|
|
38
|
+
|
|
39
|
+
Caveman (full):
|
|
40
|
+
> New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`.
|
|
41
|
+
|
|
42
|
+
Caveman (ultra):
|
|
43
|
+
> Inline obj prop → new ref → re-render. `useMemo`.
|
|
44
|
+
|
|
45
|
+
## See also
|
|
46
|
+
|
|
47
|
+
- [`SKILL.md`](./SKILL.md) — full LLM-facing instructions
|
|
48
|
+
- [Caveman README](../../README.md) — repo overview, install, benchmarks
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: caveman
|
|
3
|
+
description: >
|
|
4
|
+
Ultra-compressed communication mode. Cuts output tokens 65% (measured) by speaking like caveman
|
|
5
|
+
while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra,
|
|
6
|
+
wenyan-lite, wenyan-full, wenyan-ultra.
|
|
7
|
+
Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens",
|
|
8
|
+
"be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Respond terse like smart caveman. All technical substance stay. Only fluff die.
|
|
12
|
+
|
|
13
|
+
## Persistence
|
|
14
|
+
|
|
15
|
+
ACTIVE EVERY RESPONSE. No revert after many turns. No filler drift. Still active if unsure. Off only: "stop caveman" / "normal mode".
|
|
16
|
+
|
|
17
|
+
Default: **full**. Switch: `/caveman lite|full|ultra`.
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
|
|
21
|
+
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"). No tool-call narration, no decorative tables/emoji, no dumping long raw error logs unless asked — quote shortest decisive line. Standard well-known tech acronyms OK (DB/API/HTTP); never invent new abbreviations (cfg/impl/req/res/fn) — tokenizer split them same as full word: zero token saved, reader still decode. Full word cheaper AND clearer. No causal arrows (→) either — own token, save nothing. Technical terms exact. Code blocks unchanged. Errors quoted exact.
|
|
22
|
+
|
|
23
|
+
Preserve user's dominant language. User write Portuguese → reply Portuguese caveman. User write Spanish → reply Spanish caveman. Compress the style, not the language. No forced English openings or status phrases. ALWAYS keep technical terms, code, API names, CLI commands, commit-type keywords (feat/fix/...), and exact error strings verbatim — unless user explicitly ask for translation.
|
|
24
|
+
|
|
25
|
+
No self-reference. Never name or announce the style. No "caveman mode on", "me caveman think", no third-person caveman tags. Output caveman-only — never normal answer plus "Caveman:" recap. Exception: user explicitly ask what the mode is.
|
|
26
|
+
|
|
27
|
+
Pattern: `[thing] [action] [reason]. [next step].`
|
|
28
|
+
|
|
29
|
+
Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
|
|
30
|
+
Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
|
|
31
|
+
|
|
32
|
+
## Intensity
|
|
33
|
+
|
|
34
|
+
| Level | What change |
|
|
35
|
+
|-------|------------|
|
|
36
|
+
| **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight |
|
|
37
|
+
| **full** | Drop articles, fragments OK, short synonyms. Classic caveman. No tool-call narration, no decorative tables/emoji, no long raw error-log dumps unless asked. Standard acronyms OK; no invented abbreviations |
|
|
38
|
+
| **ultra** | Strip conjunctions when cause-then-effect stay unambiguous. One word when one word enough. State each fact once. NO prose abbreviations (cfg/impl/req/res/fn/auth), NO arrows (X → Y) — measured zero token saving under tokenizer, cost decode clarity. Code symbols, function names, API names, error strings: never touch |
|
|
39
|
+
| **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register |
|
|
40
|
+
| **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) |
|
|
41
|
+
| **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse |
|
|
42
|
+
|
|
43
|
+
Example — "Why React component re-render?"
|
|
44
|
+
- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
|
|
45
|
+
- full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."
|
|
46
|
+
- ultra: "Inline obj prop, new ref, re-render. `useMemo`."
|
|
47
|
+
- wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"
|
|
48
|
+
- wenyan-full: "每繪新生對象參照,故重繪;以 useMemo 包之則免。"
|
|
49
|
+
- wenyan-ultra: "新參照則重繪。useMemo 包之。"
|
|
50
|
+
|
|
51
|
+
Example — "Explain database connection pooling."
|
|
52
|
+
- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead."
|
|
53
|
+
- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
|
|
54
|
+
- ultra: "Pool reuse open DB connections. No per-request handshake."
|
|
55
|
+
- wenyan-full: "池蓄已開之連,不逐請而新開,省握手之費。"
|
|
56
|
+
- wenyan-ultra: "池蓄連,免逐請新開,省握手。"
|
|
57
|
+
|
|
58
|
+
## Auto-Clarity
|
|
59
|
+
|
|
60
|
+
Drop caveman when:
|
|
61
|
+
- Security warnings
|
|
62
|
+
- Irreversible action confirmations
|
|
63
|
+
- Multi-step sequences where fragment order or omitted conjunctions risk misread
|
|
64
|
+
- Compression itself creates technical ambiguity (e.g., `"migrate table drop column backup first"` — order unclear without articles/conjunctions)
|
|
65
|
+
- User asks to clarify or repeats question
|
|
66
|
+
|
|
67
|
+
Resume caveman after clear part done.
|
|
68
|
+
|
|
69
|
+
Example — destructive op:
|
|
70
|
+
> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
|
|
71
|
+
> ```sql
|
|
72
|
+
> DROP TABLE users;
|
|
73
|
+
> ```
|
|
74
|
+
> Caveman resume. Verify backup exist first.
|
|
75
|
+
|
|
76
|
+
## Boundaries
|
|
77
|
+
|
|
78
|
+
Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# caveman-commit
|
|
2
|
+
|
|
3
|
+
Terse Conventional Commits. Why over what.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Generates commit messages in Conventional Commits format. Subject ≤50 chars, hard cap 72. Imperative mood. Body only when the *why* is non-obvious or there are breaking changes. No AI attribution, no "this commit does X", no emoji unless the project uses them. Body always required for breaking changes, security fixes, data migrations, and reverts — future debuggers need the context.
|
|
8
|
+
|
|
9
|
+
Outputs only the message. Does not stage, commit, or amend.
|
|
10
|
+
|
|
11
|
+
## How to invoke
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/caveman-commit
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Also triggers on phrases like "write a commit", "commit message", "generate commit".
|
|
18
|
+
|
|
19
|
+
## Example output
|
|
20
|
+
|
|
21
|
+
Diff: new endpoint for user profile.
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
feat(api): add GET /users/:id/profile
|
|
25
|
+
|
|
26
|
+
Mobile client needs profile data without the full user payload
|
|
27
|
+
to reduce LTE bandwidth on cold-launch screens.
|
|
28
|
+
|
|
29
|
+
Closes #128
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Diff: breaking API rename.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
feat(api)!: rename /v1/orders to /v1/checkout
|
|
36
|
+
|
|
37
|
+
BREAKING CHANGE: clients on /v1/orders must migrate to /v1/checkout
|
|
38
|
+
before 2026-06-01. Old route returns 410 after that date.
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## See also
|
|
42
|
+
|
|
43
|
+
- [`SKILL.md`](./SKILL.md) — full LLM-facing instructions
|
|
44
|
+
- [Caveman README](../../README.md) — repo overview
|