continuous-improvement 1.1.0 → 2.1.1
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/CHANGELOG.md +87 -0
- package/QUICKSTART.md +81 -0
- package/README.md +100 -93
- package/SKILL.md +171 -0
- package/bin/analyze.sh +167 -0
- package/bin/install.mjs +331 -0
- package/commands/continuous-improvement.md +74 -0
- package/hooks/observe.sh +63 -62
- package/package.json +31 -14
- package/agents/observer-loop.sh +0 -282
- package/agents/observer.md +0 -145
- package/agents/start-observer.sh +0 -115
- package/config.json +0 -9
- package/docs/failure-taxonomy.md +0 -153
- package/docs/integration-guide.md +0 -105
- package/docs/philosophy.md +0 -127
- package/docs/superpowers/plans/2026-04-05-mulahazah-implementation.md +0 -1666
- package/docs/superpowers/specs/2026-04-05-mulahazah-instinct-learning-design.md +0 -636
- package/prompts/coding-agent.md +0 -67
- package/prompts/core.md +0 -115
- package/prompts/minimal.md +0 -17
- package/prompts/product-agent.md +0 -59
- package/prompts/research-agent.md +0 -59
- package/scripts/install.js +0 -433
- package/skills/continuous-improvement/SKILL.md +0 -111
package/bin/analyze.sh
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# analyze.sh — Read observations.jsonl, detect patterns, create instinct YAML files
|
|
3
|
+
# Runs via /continuous-improvement command. Uses claude CLI with Haiku for cost-efficient analysis.
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
INSTINCTS_DIR="${HOME}/.claude/instincts"
|
|
8
|
+
|
|
9
|
+
# ---------------------------------------------------------------------------
|
|
10
|
+
# Detect project
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
PROJECT_ROOT=""
|
|
13
|
+
if [[ -n "${CLAUDE_PROJECT_DIR:-}" && -d "${CLAUDE_PROJECT_DIR}" ]]; then
|
|
14
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR}"
|
|
15
|
+
fi
|
|
16
|
+
if [[ -z "$PROJECT_ROOT" ]]; then
|
|
17
|
+
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
18
|
+
fi
|
|
19
|
+
if [[ -z "$PROJECT_ROOT" ]]; then
|
|
20
|
+
PROJECT_ROOT="global"
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
PROJECT_HASH="$(printf '%s' "$PROJECT_ROOT" | sha256sum | cut -c1-12)"
|
|
24
|
+
PROJECT_NAME="$(basename "${PROJECT_ROOT%.git}")"
|
|
25
|
+
PROJECT_DIR="${INSTINCTS_DIR}/${PROJECT_HASH}"
|
|
26
|
+
OBS_FILE="${PROJECT_DIR}/observations.jsonl"
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Check observations exist
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
if [[ ! -f "$OBS_FILE" ]] || [[ ! -s "$OBS_FILE" ]]; then
|
|
32
|
+
echo "No observations found at ${OBS_FILE}"
|
|
33
|
+
echo "Use Claude Code with hooks installed to generate observations."
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
OBS_COUNT=$(wc -l < "$OBS_FILE")
|
|
38
|
+
echo "Found ${OBS_COUNT} observations in ${OBS_FILE}"
|
|
39
|
+
|
|
40
|
+
if (( OBS_COUNT < 20 )); then
|
|
41
|
+
echo "Need at least 20 observations for meaningful analysis. Keep using Claude Code (${OBS_COUNT}/20)."
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
# Read existing instincts to avoid duplicates
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
EXISTING_INSTINCTS=""
|
|
49
|
+
for f in "${PROJECT_DIR}"/*.yaml "${INSTINCTS_DIR}/global"/*.yaml; do
|
|
50
|
+
[[ -f "$f" ]] && EXISTING_INSTINCTS="${EXISTING_INSTINCTS}$(cat "$f")"$'\n'
|
|
51
|
+
done
|
|
52
|
+
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
# Take last 500 observations
|
|
55
|
+
# ---------------------------------------------------------------------------
|
|
56
|
+
RECENT_OBS=$(tail -500 "$OBS_FILE")
|
|
57
|
+
|
|
58
|
+
# ---------------------------------------------------------------------------
|
|
59
|
+
# Build analysis prompt
|
|
60
|
+
# ---------------------------------------------------------------------------
|
|
61
|
+
ANALYSIS_PROMPT="Analyze these Claude Code session observations and extract behavioral patterns as instinct YAML files.
|
|
62
|
+
|
|
63
|
+
OBSERVATIONS (JSONL — each line is a tool call):
|
|
64
|
+
${RECENT_OBS}
|
|
65
|
+
|
|
66
|
+
EXISTING INSTINCTS (already learned — do NOT duplicate these):
|
|
67
|
+
${EXISTING_INSTINCTS}
|
|
68
|
+
|
|
69
|
+
YOUR TASK:
|
|
70
|
+
1. Look for REPEATED PATTERNS — same tool sequence used 3+ times
|
|
71
|
+
2. Look for ERROR-THEN-FIX sequences — tool fails, next tools fix it
|
|
72
|
+
3. Look for TOOL PREFERENCES — one tool consistently chosen over alternatives
|
|
73
|
+
4. Look for WORKFLOW PATTERNS — consistent ordering of operations
|
|
74
|
+
5. Look for USER CORRECTIONS — user says no/stop/don't after an action
|
|
75
|
+
|
|
76
|
+
OUTPUT FORMAT — output ONLY new instincts as YAML blocks, separated by ---:
|
|
77
|
+
|
|
78
|
+
id: descriptive-kebab-case-id
|
|
79
|
+
trigger: \"when [specific situation]\"
|
|
80
|
+
confidence: 0.5
|
|
81
|
+
domain: workflow|tooling|testing|patterns
|
|
82
|
+
source: observation
|
|
83
|
+
scope: project
|
|
84
|
+
project_id: ${PROJECT_HASH}
|
|
85
|
+
created: \"$(date -u +%Y-%m-%d)\"
|
|
86
|
+
last_seen: \"$(date -u +%Y-%m-%d)\"
|
|
87
|
+
observation_count: [number of times pattern was seen]
|
|
88
|
+
---
|
|
89
|
+
[One sentence describing the specific actionable behavior]
|
|
90
|
+
|
|
91
|
+
Rules:
|
|
92
|
+
- Only create instincts for patterns seen 3+ times
|
|
93
|
+
- Start confidence at 0.5 (suggest level)
|
|
94
|
+
- Be specific and actionable (not vague advice)
|
|
95
|
+
- Different from existing instincts listed above
|
|
96
|
+
|
|
97
|
+
If no new patterns are found, output exactly: NO_NEW_PATTERNS
|
|
98
|
+
|
|
99
|
+
Output ONLY the YAML blocks or NO_NEW_PATTERNS. No explanation, no preamble."
|
|
100
|
+
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
# Run analysis with Haiku
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
echo "Analyzing patterns with Haiku..."
|
|
105
|
+
RESULT=$(echo "$ANALYSIS_PROMPT" | claude --model haiku --print -p - 2>/dev/null) || {
|
|
106
|
+
echo "Analysis failed — claude CLI error. Try running manually."
|
|
107
|
+
exit 1
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if [[ "$RESULT" == "NO_NEW_PATTERNS" ]] || [[ -z "$RESULT" ]]; then
|
|
111
|
+
echo "No new patterns detected yet. Keep using Claude Code — patterns emerge over time."
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# ---------------------------------------------------------------------------
|
|
116
|
+
# Write instinct YAML files
|
|
117
|
+
# ---------------------------------------------------------------------------
|
|
118
|
+
mkdir -p "$PROJECT_DIR"
|
|
119
|
+
|
|
120
|
+
NEW_COUNT=0
|
|
121
|
+
while IFS= read -r -d '' block; do
|
|
122
|
+
[[ -z "$block" ]] && continue
|
|
123
|
+
# Extract id from the block
|
|
124
|
+
INSTINCT_ID=$(echo "$block" | grep -oP '(?<=^id: ).*' | head -1 | tr -d '"' | tr -d "'")
|
|
125
|
+
if [[ -n "$INSTINCT_ID" ]]; then
|
|
126
|
+
DEST="${PROJECT_DIR}/${INSTINCT_ID}.yaml"
|
|
127
|
+
printf '%s\n' "$block" > "$DEST"
|
|
128
|
+
echo " + ${INSTINCT_ID} → ${DEST}"
|
|
129
|
+
NEW_COUNT=$((NEW_COUNT + 1))
|
|
130
|
+
fi
|
|
131
|
+
done < <(printf '%s\0' "$RESULT" | sed 's/\n---\n/\x00/g')
|
|
132
|
+
|
|
133
|
+
# Fallback: if the splitting didn't work, try line-based parsing
|
|
134
|
+
if (( NEW_COUNT == 0 )); then
|
|
135
|
+
# Try splitting on --- delimiter
|
|
136
|
+
INSTINCT_ID=""
|
|
137
|
+
BLOCK=""
|
|
138
|
+
while IFS= read -r line; do
|
|
139
|
+
if [[ "$line" == "---" ]] && [[ -n "$BLOCK" ]]; then
|
|
140
|
+
if [[ -n "$INSTINCT_ID" ]]; then
|
|
141
|
+
DEST="${PROJECT_DIR}/${INSTINCT_ID}.yaml"
|
|
142
|
+
printf '%s\n' "$BLOCK" > "$DEST"
|
|
143
|
+
echo " + ${INSTINCT_ID} → ${DEST}"
|
|
144
|
+
NEW_COUNT=$((NEW_COUNT + 1))
|
|
145
|
+
fi
|
|
146
|
+
INSTINCT_ID=""
|
|
147
|
+
BLOCK=""
|
|
148
|
+
else
|
|
149
|
+
BLOCK="${BLOCK}${line}"$'\n'
|
|
150
|
+
if [[ "$line" =~ ^id:\ (.+) ]]; then
|
|
151
|
+
INSTINCT_ID="${BASH_REMATCH[1]}"
|
|
152
|
+
INSTINCT_ID="${INSTINCT_ID//\"/}"
|
|
153
|
+
INSTINCT_ID="${INSTINCT_ID//\'/}"
|
|
154
|
+
fi
|
|
155
|
+
fi
|
|
156
|
+
done <<< "$RESULT"
|
|
157
|
+
# Handle last block
|
|
158
|
+
if [[ -n "$INSTINCT_ID" ]] && [[ -n "$BLOCK" ]]; then
|
|
159
|
+
DEST="${PROJECT_DIR}/${INSTINCT_ID}.yaml"
|
|
160
|
+
printf '%s\n' "$BLOCK" > "$DEST"
|
|
161
|
+
echo " + ${INSTINCT_ID} → ${DEST}"
|
|
162
|
+
NEW_COUNT=$((NEW_COUNT + 1))
|
|
163
|
+
fi
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
echo ""
|
|
167
|
+
echo "Created ${NEW_COUNT} new instinct(s) in ${PROJECT_DIR}/"
|
package/bin/install.mjs
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* continuous-improvement installer
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx continuous-improvement install # auto-detect & install
|
|
8
|
+
* npx continuous-improvement install --target claude # install to ~/.claude/skills/ + Mulahazah
|
|
9
|
+
* npx continuous-improvement install --target openclaw # install to ~/.openclaw/skills/
|
|
10
|
+
* npx continuous-improvement install --target cursor # install to ~/.cursor/skills/
|
|
11
|
+
* npx continuous-improvement install --target all # install to all detected targets
|
|
12
|
+
* npx continuous-improvement install --uninstall # remove from all targets
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
existsSync,
|
|
17
|
+
mkdirSync,
|
|
18
|
+
copyFileSync,
|
|
19
|
+
readFileSync,
|
|
20
|
+
writeFileSync,
|
|
21
|
+
rmSync,
|
|
22
|
+
chmodSync,
|
|
23
|
+
} from "node:fs";
|
|
24
|
+
import { join, dirname } from "node:path";
|
|
25
|
+
import { homedir } from "node:os";
|
|
26
|
+
import { fileURLToPath } from "node:url";
|
|
27
|
+
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
const __dirname = dirname(__filename);
|
|
30
|
+
const SKILL_SOURCE = join(__dirname, "..", "SKILL.md");
|
|
31
|
+
const SKILL_NAME = "continuous-improvement";
|
|
32
|
+
const REPO_ROOT = join(__dirname, "..");
|
|
33
|
+
|
|
34
|
+
const TARGETS = {
|
|
35
|
+
claude: {
|
|
36
|
+
label: "Claude Code",
|
|
37
|
+
dir: join(homedir(), ".claude", "skills", SKILL_NAME),
|
|
38
|
+
},
|
|
39
|
+
openclaw: {
|
|
40
|
+
label: "OpenClaw",
|
|
41
|
+
dir: join(homedir(), ".openclaw", "skills", SKILL_NAME),
|
|
42
|
+
},
|
|
43
|
+
cursor: {
|
|
44
|
+
label: "Cursor",
|
|
45
|
+
dir: join(homedir(), ".cursor", "skills", SKILL_NAME),
|
|
46
|
+
},
|
|
47
|
+
codex: {
|
|
48
|
+
label: "Codex",
|
|
49
|
+
dir: join(homedir(), ".codex", "skills", SKILL_NAME),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function detectTargets() {
|
|
54
|
+
const detected = [];
|
|
55
|
+
for (const [key, target] of Object.entries(TARGETS)) {
|
|
56
|
+
const parentDir = dirname(target.dir);
|
|
57
|
+
const configDir = dirname(parentDir);
|
|
58
|
+
if (existsSync(configDir)) {
|
|
59
|
+
detected.push(key);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return detected;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function installTo(key) {
|
|
66
|
+
const target = TARGETS[key];
|
|
67
|
+
if (!target) {
|
|
68
|
+
console.error(` Unknown target: ${key}`);
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
mkdirSync(target.dir, { recursive: true });
|
|
74
|
+
copyFileSync(SKILL_SOURCE, join(target.dir, "SKILL.md"));
|
|
75
|
+
console.log(` ✓ ${target.label} → ${target.dir}/SKILL.md`);
|
|
76
|
+
|
|
77
|
+
if (key === "claude") {
|
|
78
|
+
setupMulahazah();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return true;
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error(` ✗ ${target.label}: ${err.message}`);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function setupMulahazah() {
|
|
89
|
+
const home = homedir();
|
|
90
|
+
const instinctsDir = join(home, ".claude", "instincts");
|
|
91
|
+
const globalDir = join(instinctsDir, "global");
|
|
92
|
+
|
|
93
|
+
// 1. Create directory structure
|
|
94
|
+
mkdirSync(globalDir, { recursive: true });
|
|
95
|
+
console.log(` ✓ Instincts dir → ${instinctsDir}/`);
|
|
96
|
+
|
|
97
|
+
// 2. Copy observe.sh and make executable
|
|
98
|
+
const observeSrc = join(REPO_ROOT, "hooks", "observe.sh");
|
|
99
|
+
const observeDest = join(instinctsDir, "observe.sh");
|
|
100
|
+
if (existsSync(observeSrc)) {
|
|
101
|
+
copyFileSync(observeSrc, observeDest);
|
|
102
|
+
chmodSync(observeDest, 0o755);
|
|
103
|
+
console.log(` ✓ observe.sh → ${observeDest}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 3. Copy /continuous-improvement command
|
|
107
|
+
const commandsDir = join(home, ".claude", "commands");
|
|
108
|
+
mkdirSync(commandsDir, { recursive: true });
|
|
109
|
+
const cmdSrc = join(REPO_ROOT, "commands", "continuous-improvement.md");
|
|
110
|
+
const cmdDest = join(commandsDir, "continuous-improvement.md");
|
|
111
|
+
if (existsSync(cmdSrc)) {
|
|
112
|
+
copyFileSync(cmdSrc, cmdDest);
|
|
113
|
+
console.log(` ✓ /continuous-improvement command → ${cmdDest}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 4. Patch ~/.claude/settings.json with hooks
|
|
117
|
+
patchClaudeSettings(observeDest);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function patchClaudeSettings(observePath) {
|
|
121
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
122
|
+
|
|
123
|
+
let settings = {};
|
|
124
|
+
if (existsSync(settingsPath)) {
|
|
125
|
+
try {
|
|
126
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
127
|
+
} catch {
|
|
128
|
+
console.warn(` ! Could not parse ${settingsPath} — skipping hook patch`);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!settings.hooks) settings.hooks = {};
|
|
134
|
+
|
|
135
|
+
const hookEntry = {
|
|
136
|
+
matcher: "",
|
|
137
|
+
hooks: [
|
|
138
|
+
{
|
|
139
|
+
type: "command",
|
|
140
|
+
command: `bash "${observePath}"`,
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
let changed = false;
|
|
146
|
+
|
|
147
|
+
for (const hookType of ["PreToolUse", "PostToolUse"]) {
|
|
148
|
+
if (!Array.isArray(settings.hooks[hookType])) {
|
|
149
|
+
settings.hooks[hookType] = [];
|
|
150
|
+
}
|
|
151
|
+
const alreadyPatched = settings.hooks[hookType].some(
|
|
152
|
+
(h) =>
|
|
153
|
+
Array.isArray(h.hooks) &&
|
|
154
|
+
h.hooks.some((hh) => hh.command && hh.command.includes("observe.sh"))
|
|
155
|
+
);
|
|
156
|
+
if (!alreadyPatched) {
|
|
157
|
+
settings.hooks[hookType].push(hookEntry);
|
|
158
|
+
changed = true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (changed) {
|
|
163
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
164
|
+
console.log(` ✓ Patched ~/.claude/settings.json with PreToolUse/PostToolUse hooks`);
|
|
165
|
+
} else {
|
|
166
|
+
console.log(` ✓ settings.json already has observe.sh hooks — no change needed`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function uninstallAll() {
|
|
171
|
+
console.log("\nUninstalling continuous-improvement skill...\n");
|
|
172
|
+
const home = homedir();
|
|
173
|
+
let removed = 0;
|
|
174
|
+
|
|
175
|
+
// 1. Remove skill files from all targets
|
|
176
|
+
for (const [key, target] of Object.entries(TARGETS)) {
|
|
177
|
+
const skillFile = join(target.dir, "SKILL.md");
|
|
178
|
+
if (existsSync(skillFile)) {
|
|
179
|
+
try {
|
|
180
|
+
rmSync(target.dir, { recursive: true });
|
|
181
|
+
console.log(` ✓ Removed skill from ${target.label}`);
|
|
182
|
+
removed++;
|
|
183
|
+
} catch (err) {
|
|
184
|
+
console.error(` ✗ ${target.label}: ${err.message}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 2. Remove /continuous-improvement command
|
|
190
|
+
const cmdFile = join(home, ".claude", "commands", "continuous-improvement.md");
|
|
191
|
+
if (existsSync(cmdFile)) {
|
|
192
|
+
try {
|
|
193
|
+
rmSync(cmdFile);
|
|
194
|
+
console.log(` ✓ Removed /continuous-improvement command`);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.error(` ✗ Command file: ${err.message}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 3. Remove observe.sh from instincts dir
|
|
201
|
+
const observeFile = join(home, ".claude", "instincts", "observe.sh");
|
|
202
|
+
if (existsSync(observeFile)) {
|
|
203
|
+
try {
|
|
204
|
+
rmSync(observeFile);
|
|
205
|
+
console.log(` ✓ Removed observe.sh`);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
console.error(` ✗ observe.sh: ${err.message}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 4. Remove hooks from settings.json
|
|
212
|
+
const settingsPath = join(home, ".claude", "settings.json");
|
|
213
|
+
if (existsSync(settingsPath)) {
|
|
214
|
+
try {
|
|
215
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
216
|
+
let changed = false;
|
|
217
|
+
for (const hookType of ["PreToolUse", "PostToolUse"]) {
|
|
218
|
+
if (Array.isArray(settings.hooks?.[hookType])) {
|
|
219
|
+
const before = settings.hooks[hookType].length;
|
|
220
|
+
settings.hooks[hookType] = settings.hooks[hookType].filter(
|
|
221
|
+
(h) =>
|
|
222
|
+
!(
|
|
223
|
+
Array.isArray(h.hooks) &&
|
|
224
|
+
h.hooks.some(
|
|
225
|
+
(hh) => hh.command && hh.command.includes("observe.sh")
|
|
226
|
+
)
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
if (settings.hooks[hookType].length < before) changed = true;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (changed) {
|
|
233
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
234
|
+
console.log(` ✓ Removed hooks from settings.json`);
|
|
235
|
+
}
|
|
236
|
+
} catch {
|
|
237
|
+
console.warn(` ! Could not clean settings.json — remove hooks manually`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (removed === 0) {
|
|
242
|
+
console.log(" No skill installations found.");
|
|
243
|
+
}
|
|
244
|
+
console.log(
|
|
245
|
+
"\n Note: Instinct data in ~/.claude/instincts/ was preserved.\n" +
|
|
246
|
+
" To remove learned data too: rm -rf ~/.claude/instincts/\n"
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function printUsage() {
|
|
251
|
+
console.log(`
|
|
252
|
+
Usage: npx continuous-improvement install [options]
|
|
253
|
+
|
|
254
|
+
Options:
|
|
255
|
+
--target <name> Install to specific target (claude, openclaw, cursor, codex, all)
|
|
256
|
+
--uninstall Remove from all targets
|
|
257
|
+
--help Show this help
|
|
258
|
+
|
|
259
|
+
Examples:
|
|
260
|
+
npx continuous-improvement install # auto-detect & install
|
|
261
|
+
npx continuous-improvement install --target all # install everywhere
|
|
262
|
+
npx continuous-improvement install --uninstall # remove all
|
|
263
|
+
`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// --- Main ---
|
|
267
|
+
|
|
268
|
+
const args = process.argv.slice(2);
|
|
269
|
+
const command = args[0];
|
|
270
|
+
|
|
271
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
272
|
+
printUsage();
|
|
273
|
+
process.exit(0);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (!command || !["install", "--help", "-h", "--uninstall"].includes(command)) {
|
|
277
|
+
printUsage();
|
|
278
|
+
process.exit(command ? 1 : 0);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (args.includes("--uninstall")) {
|
|
282
|
+
uninstallAll();
|
|
283
|
+
process.exit(0);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
console.log(`
|
|
287
|
+
continuous-improvement v2.1
|
|
288
|
+
Research → Plan → Execute → Verify → Reflect → Learn → Iterate
|
|
289
|
+
`);
|
|
290
|
+
|
|
291
|
+
const targetIdx = args.indexOf("--target");
|
|
292
|
+
let targets;
|
|
293
|
+
|
|
294
|
+
if (targetIdx !== -1 && args[targetIdx + 1]) {
|
|
295
|
+
const requested = args[targetIdx + 1].toLowerCase();
|
|
296
|
+
if (requested === "all") {
|
|
297
|
+
targets = Object.keys(TARGETS);
|
|
298
|
+
} else if (TARGETS[requested]) {
|
|
299
|
+
targets = [requested];
|
|
300
|
+
} else {
|
|
301
|
+
console.error(`Unknown target: ${requested}`);
|
|
302
|
+
console.error(`Available: ${Object.keys(TARGETS).join(", ")}, all`);
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
targets = detectTargets();
|
|
307
|
+
if (targets.length === 0) {
|
|
308
|
+
console.log("No supported agent configs detected. Installing to Claude Code by default.\n");
|
|
309
|
+
targets = ["claude"];
|
|
310
|
+
} else {
|
|
311
|
+
console.log(`Detected: ${targets.map((t) => TARGETS[t].label).join(", ")}\n`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
console.log("Installing...\n");
|
|
316
|
+
|
|
317
|
+
let installed = 0;
|
|
318
|
+
for (const t of targets) {
|
|
319
|
+
if (installTo(t)) installed++;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const hasClaude = targets.includes("claude");
|
|
323
|
+
|
|
324
|
+
console.log(`
|
|
325
|
+
${installed > 0 ? "Done." : "Failed."} Installed to ${installed}/${targets.length} target(s).
|
|
326
|
+
${hasClaude ? "\nHooks are capturing. System auto-levels as you use it." : ""}
|
|
327
|
+
Next steps:
|
|
328
|
+
1. Start a new Claude Code session
|
|
329
|
+
2. Say: "Use the continuous-improvement framework to [your task]"
|
|
330
|
+
3. After your first task, run: /continuous-improvement
|
|
331
|
+
`);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: continuous-improvement
|
|
3
|
+
description: "Reflect on the current session, analyze observations for patterns, and show instinct status. Run after finishing significant work."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /continuous-improvement
|
|
7
|
+
|
|
8
|
+
Run this after completing significant work. It does three things in order.
|
|
9
|
+
|
|
10
|
+
## Step 1: Reflect
|
|
11
|
+
|
|
12
|
+
Generate a reflection for this session based on what happened:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
## Reflection — [Date]
|
|
16
|
+
- What worked:
|
|
17
|
+
- What failed:
|
|
18
|
+
- What I'd do differently:
|
|
19
|
+
- Rule to add:
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If there's a "Rule to add", create an instinct YAML file with 0.6 starting confidence in the project's instinct directory.
|
|
23
|
+
|
|
24
|
+
## Step 2: Analyze Observations
|
|
25
|
+
|
|
26
|
+
Check `~/.claude/instincts/` for the current project (detect via git root → SHA-256 first 12 chars).
|
|
27
|
+
|
|
28
|
+
Look at `~/.claude/instincts/<hash>/observations.jsonl`. If 20+ lines exist:
|
|
29
|
+
|
|
30
|
+
1. Read the last 500 lines
|
|
31
|
+
2. Read existing instinct `*.yaml` files (project + global)
|
|
32
|
+
3. Detect patterns:
|
|
33
|
+
- User corrections → "don't do X" instincts
|
|
34
|
+
- Error→fix sequences → "when X fails, try Y"
|
|
35
|
+
- Repeated workflows (3+ times) → "for X, do A→B→C"
|
|
36
|
+
- Tool preferences → "use tool Y for task X"
|
|
37
|
+
4. Create/update instinct YAML files
|
|
38
|
+
5. Be conservative: only create instincts for 3+ observations of the same pattern
|
|
39
|
+
|
|
40
|
+
If fewer than 20 observations, skip analysis and note the count.
|
|
41
|
+
|
|
42
|
+
## Step 3: Show Status
|
|
43
|
+
|
|
44
|
+
Display all instincts for the current project + global:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
=== continuous-improvement ===
|
|
48
|
+
|
|
49
|
+
## Level: [CAPTURE | ANALYZE | SUGGEST | AUTO-APPLY]
|
|
50
|
+
|
|
51
|
+
## Session Reflection
|
|
52
|
+
- What worked: [from this session]
|
|
53
|
+
- What failed: [from this session]
|
|
54
|
+
- What I'd do differently: [from this session]
|
|
55
|
+
- Rule to add: [captured as instinct]
|
|
56
|
+
|
|
57
|
+
## Learning
|
|
58
|
+
NEW [instinct-id] [domain] [confidence] (from reflection)
|
|
59
|
+
↑ [instinct-id] [domain] [old]→[new] (+N observations)
|
|
60
|
+
|
|
61
|
+
## Instincts — [project-name] ([hash])
|
|
62
|
+
● [0.85] instinct-id domain auto-apply
|
|
63
|
+
◐ [0.60] instinct-id domain suggest
|
|
64
|
+
○ [0.35] instinct-id domain silent
|
|
65
|
+
|
|
66
|
+
## Instincts — global
|
|
67
|
+
● [0.90] instinct-id domain auto-apply
|
|
68
|
+
|
|
69
|
+
## Next
|
|
70
|
+
- Keep working — hooks capture automatically
|
|
71
|
+
- System auto-levels as instincts gain confidence
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If no instincts or observations exist yet, explain this is expected — the system is in CAPTURE level and will create instincts after 20+ observations accumulate.
|