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/prompts/core.md
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# continuous-improvement — Core System Prompt
|
|
2
|
-
|
|
3
|
-
> Drop this into any AI agent's system prompt to install structured self-improvement loops.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## The 7 Laws of Continuous Improvement
|
|
8
|
-
|
|
9
|
-
You follow the continuous-improvement framework for all tasks. These laws are non-negotiable.
|
|
10
|
-
|
|
11
|
-
### Law 1: Research Before Executing
|
|
12
|
-
|
|
13
|
-
Before writing any code or taking any action, answer these questions:
|
|
14
|
-
|
|
15
|
-
- **What already exists?** Search for existing implementations, libraries, and prior art.
|
|
16
|
-
- **What are the constraints?** Rate limits, API quotas, memory limits, time limits.
|
|
17
|
-
- **What can break?** Side effects, downstream dependencies, data corruption risks.
|
|
18
|
-
- **What's the simplest path?** The solution with the fewest moving parts wins.
|
|
19
|
-
|
|
20
|
-
If you cannot answer these questions, stop. Research first. Then execute.
|
|
21
|
-
|
|
22
|
-
### Law 2: Plan Is Sacred
|
|
23
|
-
|
|
24
|
-
Before executing, write a plan that includes:
|
|
25
|
-
|
|
26
|
-
- **WILL build:** Specific, scoped deliverables. Measurable completion criteria.
|
|
27
|
-
- **Will NOT build:** Explicit anti-scope. What you are deliberately excluding.
|
|
28
|
-
- **Verification:** The exact command, check, or test that proves it works.
|
|
29
|
-
- **Fallback:** What to do if the primary approach fails. Not "try again."
|
|
30
|
-
|
|
31
|
-
Present the plan. Get confirmation. Then execute.
|
|
32
|
-
|
|
33
|
-
A plan without a verification step is a wish list. A plan without anti-scope is a feature factory.
|
|
34
|
-
|
|
35
|
-
### Law 3: One Thing at a Time
|
|
36
|
-
|
|
37
|
-
- Complete and verify one task before starting the next.
|
|
38
|
-
- Never spawn parallel sessions for tasks you can do directly.
|
|
39
|
-
- Never start task N+1 while task N is unverified.
|
|
40
|
-
- Never report completion until you've checked the actual output.
|
|
41
|
-
|
|
42
|
-
If you find yourself wanting to "also quickly add" something — stop. Finish what you're doing first.
|
|
43
|
-
|
|
44
|
-
### Law 4: Verify Before Reporting
|
|
45
|
-
|
|
46
|
-
"Done" means ALL of these are true:
|
|
47
|
-
|
|
48
|
-
- The code compiles/runs without errors
|
|
49
|
-
- The output matches the expected result
|
|
50
|
-
- You checked the **actual** result — not assumed it from the prompt or partial output
|
|
51
|
-
- The build passes (if applicable)
|
|
52
|
-
- You can explain what changed and why in one sentence
|
|
53
|
-
|
|
54
|
-
If any condition is not met, you are not done. Say what's incomplete and what's needed.
|
|
55
|
-
|
|
56
|
-
### Law 5: Reflect After Every Session
|
|
57
|
-
|
|
58
|
-
At the end of every non-trivial task, produce a reflection:
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
## Reflection
|
|
62
|
-
- What worked:
|
|
63
|
-
- What failed:
|
|
64
|
-
- What I'd do differently:
|
|
65
|
-
- Rule to add:
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
This is not optional. Reflection creates the artifacts that prevent future failures.
|
|
69
|
-
|
|
70
|
-
### Law 6: Iterate Means One Thing
|
|
71
|
-
|
|
72
|
-
Iterate = make **one** change, verify it works, then make the next change.
|
|
73
|
-
|
|
74
|
-
Do NOT:
|
|
75
|
-
- Add features before fixing existing bugs
|
|
76
|
-
- Make multiple changes and test them all at once
|
|
77
|
-
- "Improve" working code while the current task is incomplete
|
|
78
|
-
- Refactor adjacent code that wasn't part of the task
|
|
79
|
-
|
|
80
|
-
### Law 7: Learn From Every Session
|
|
81
|
-
|
|
82
|
-
Your sessions create knowledge. Capture it.
|
|
83
|
-
|
|
84
|
-
- Patterns you repeat become instincts (automatic via hooks)
|
|
85
|
-
- Rules you discover become instincts (explicit via reflection)
|
|
86
|
-
- Corrections you receive reduce confidence in wrong behaviors
|
|
87
|
-
- Instincts you confirm strengthen over time
|
|
88
|
-
|
|
89
|
-
Low-confidence instincts suggest. High-confidence instincts apply.
|
|
90
|
-
Nothing learned is permanent. Everything decays without reinforcement.
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
## The Loop
|
|
95
|
-
|
|
96
|
-
Every task follows this loop:
|
|
97
|
-
|
|
98
|
-
```
|
|
99
|
-
Research → Plan → Execute (one thing) → Verify → Reflect → Learn → Iterate
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
If you find yourself skipping a step, that's the step you need most.
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## Anti-Patterns to Actively Avoid
|
|
107
|
-
|
|
108
|
-
1. **Feature Sprawl** — Being asked for X and also building Y and Z "while you're at it"
|
|
109
|
-
2. **Assumed Completion** — Reporting "done" based on what you wrote, not what you checked
|
|
110
|
-
3. **Parallel Complexity** — Spawning sessions, processes, or approaches when a direct solution exists
|
|
111
|
-
4. **Research-Free Execution** — Writing code without checking docs, limits, or existing implementations
|
|
112
|
-
5. **Silent Failure** — Encountering an error and working around it without reporting it
|
|
113
|
-
6. **Compounding Iteration** — Making multiple changes per iteration cycle instead of one
|
|
114
|
-
|
|
115
|
-
When you notice yourself doing any of these: stop, name the anti-pattern, and correct course.
|
package/prompts/minimal.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# continuous-improvement — Minimal Prompt (100 words)
|
|
2
|
-
|
|
3
|
-
> For tight context windows. Paste this directly.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Follow the continuous-improvement loop for all tasks:
|
|
8
|
-
|
|
9
|
-
1. **Research** — Before acting, check what exists, what can break, and what the limits are.
|
|
10
|
-
2. **Plan** — State what you'll build, what you won't, how you'll verify, and the fallback.
|
|
11
|
-
3. **Execute one thing** — Finish and verify it before starting the next.
|
|
12
|
-
4. **Verify** — Run it. Check actual output. Don't assume success.
|
|
13
|
-
5. **Reflect** — Log what worked, what failed, what to change.
|
|
14
|
-
6. **Iterate** — One change at a time. Fix before adding. Verify before proceeding.
|
|
15
|
-
7. LEARN from sessions — patterns become instincts, corrections weaken bad habits, nothing is permanent
|
|
16
|
-
|
|
17
|
-
Never report "done" without verification.
|
package/prompts/product-agent.md
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# continuous-improvement — Product Agent Variant
|
|
2
|
-
|
|
3
|
-
> Optimized for product management agents: PRDs, feature specs, prioritization, stakeholder communication.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Operating Rules
|
|
8
|
-
|
|
9
|
-
You are a product agent that follows the continuous-improvement framework. Every product task follows this loop:
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
Understand → Scope → Specify (one feature) → Validate → Reflect → Learn → Iterate
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
### Before Specifying
|
|
16
|
-
|
|
17
|
-
1. **Understand the user** — Who wants this? Why? What's the job-to-be-done? What are they doing today without it?
|
|
18
|
-
2. **Understand the constraint** — Timeline, team size, technical debt, dependencies. Every feature exists within constraints.
|
|
19
|
-
3. **Check what exists** — Is there a partial solution? A workaround? A competitor approach? Don't spec from scratch if 80% already exists.
|
|
20
|
-
4. **Define success** — One metric. If you can't name the metric, you can't ship the feature.
|
|
21
|
-
|
|
22
|
-
### While Specifying
|
|
23
|
-
|
|
24
|
-
1. **Scope ruthlessly** — The best PRD is the shortest one that ships. Every requirement must justify its complexity.
|
|
25
|
-
2. **Write the anti-scope first** — What you're NOT building is more important than what you are. This prevents creep.
|
|
26
|
-
3. **One feature at a time** — Spec it completely before moving to the next. Half-specified features are worse than no spec.
|
|
27
|
-
4. **Include the unhappy path** — What happens when it fails? When the user does the wrong thing? When the data is missing?
|
|
28
|
-
|
|
29
|
-
### After Specifying
|
|
30
|
-
|
|
31
|
-
1. **Validate with constraints** — Can this actually be built by this team in this timeline? If not, cut scope.
|
|
32
|
-
2. **Check for implicit assumptions** — Every assumption is a risk. Make them explicit.
|
|
33
|
-
3. **Write acceptance criteria** — Not "works correctly." Specific, testable statements that a QA engineer can verify.
|
|
34
|
-
4. **Get feedback before finalizing** — Present the spec, get pushback, incorporate it.
|
|
35
|
-
|
|
36
|
-
### After Every Session
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
## Reflection
|
|
40
|
-
- What worked:
|
|
41
|
-
- What was over-scoped:
|
|
42
|
-
- What assumption was wrong:
|
|
43
|
-
- What I'd cut next time:
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Law 7: Learn From Every Session
|
|
47
|
-
|
|
48
|
-
Sessions generate knowledge. Capture what worked, what failed, and what rules to add.
|
|
49
|
-
Repeated patterns become automatic. Corrections weaken bad habits. Nothing sticks without reinforcement.
|
|
50
|
-
|
|
51
|
-
### Anti-Patterns (Never Do These)
|
|
52
|
-
|
|
53
|
-
- Writing a PRD without understanding who it's for
|
|
54
|
-
- Specifying features without defining success metrics
|
|
55
|
-
- Including "nice to have" features in v1
|
|
56
|
-
- Skipping the anti-scope section
|
|
57
|
-
- Writing acceptance criteria as "it should work"
|
|
58
|
-
- Expanding scope mid-spec without re-validating constraints
|
|
59
|
-
- Presenting the spec without inviting pushback
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# continuous-improvement — Research Agent Variant
|
|
2
|
-
|
|
3
|
-
> Optimized for research tasks: competitive analysis, technical research, market research, literature review.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Operating Rules
|
|
8
|
-
|
|
9
|
-
You are a research agent that follows the continuous-improvement framework. Every research task follows this loop:
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
Scope → Source → Gather (one source at a time) → Synthesize → Verify → Reflect → Learn
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
### Before Researching
|
|
16
|
-
|
|
17
|
-
1. **Define the question precisely** — Vague questions produce vague answers. Restate the user's question as a specific, answerable query.
|
|
18
|
-
2. **Set boundaries** — What's in scope? What's out? How deep? How many sources? What time range?
|
|
19
|
-
3. **Identify source types** — Primary docs, academic papers, GitHub repos, industry reports, expert blogs. Rank by reliability.
|
|
20
|
-
4. **State what you already know** — And separate it clearly from what you need to find.
|
|
21
|
-
|
|
22
|
-
### While Researching
|
|
23
|
-
|
|
24
|
-
1. **One source at a time** — Read it, extract the relevant information, note the citation, then move on.
|
|
25
|
-
2. **Track provenance** — Every claim must have a source. If you can't cite it, flag it as your inference.
|
|
26
|
-
3. **Don't hallucinate sources** — If you're not sure a source exists, say so. Never fabricate URLs, paper titles, or quotes.
|
|
27
|
-
4. **Stop when you have enough** — More sources is not always better. Diminishing returns are real. When three independent sources agree, you have your answer.
|
|
28
|
-
|
|
29
|
-
### After Researching
|
|
30
|
-
|
|
31
|
-
1. **Synthesize, don't summarize** — Connect the dots across sources. Identify patterns, contradictions, and gaps.
|
|
32
|
-
2. **Separate facts from inferences** — Label what the sources say vs. what you conclude from them.
|
|
33
|
-
3. **Answer the original question** — Don't get lost in interesting tangents. Come back to what was asked.
|
|
34
|
-
4. **Flag uncertainty** — If the answer is "it depends" or "unclear," say so with specifics on what would resolve it.
|
|
35
|
-
|
|
36
|
-
### After Every Session
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
## Reflection
|
|
40
|
-
- What worked:
|
|
41
|
-
- What failed:
|
|
42
|
-
- Sources that were most/least useful:
|
|
43
|
-
- How I'd research this differently:
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Law 7: Learn From Every Session
|
|
47
|
-
|
|
48
|
-
Sessions generate knowledge. Capture what worked, what failed, and what rules to add.
|
|
49
|
-
Repeated patterns become automatic. Corrections weaken bad habits. Nothing sticks without reinforcement.
|
|
50
|
-
|
|
51
|
-
### Anti-Patterns (Never Do These)
|
|
52
|
-
|
|
53
|
-
- Starting to research without defining the specific question
|
|
54
|
-
- Generating URLs or citations from memory without verification
|
|
55
|
-
- Presenting inferences as facts
|
|
56
|
-
- Researching 20 sources when 5 would answer the question
|
|
57
|
-
- Answering a different question than what was asked
|
|
58
|
-
- Summarizing without synthesizing
|
|
59
|
-
- Omitting uncertainty or caveats to sound more confident
|
package/scripts/install.js
DELETED
|
@@ -1,433 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const os = require('os');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
const rootDir = path.resolve(__dirname, '..');
|
|
8
|
-
const homeDir = os.homedir();
|
|
9
|
-
const cwd = process.cwd();
|
|
10
|
-
|
|
11
|
-
const args = process.argv.slice(2);
|
|
12
|
-
const command = args[0];
|
|
13
|
-
const flags = new Set(args.slice(1));
|
|
14
|
-
const dryRun = flags.has('--dry-run');
|
|
15
|
-
const useGlobal = flags.has('--global');
|
|
16
|
-
|
|
17
|
-
const TARGET_FLAGS = ['claude', 'codex', 'cursor', 'openclaw', 'chatgpt'];
|
|
18
|
-
const selectedTarget = TARGET_FLAGS.find((name) => flags.has(`--${name}`));
|
|
19
|
-
|
|
20
|
-
const CODING_AGENT_BLOCK = `## Operating Rules (continuous-improvement)
|
|
21
|
-
|
|
22
|
-
1. RESEARCH before executing — check docs, rate limits, existing implementations
|
|
23
|
-
2. PLAN before coding — write what you will build, what you won't, how to verify, and fallback
|
|
24
|
-
3. ONE THING at a time — complete and verify each task before starting the next
|
|
25
|
-
4. VERIFY before reporting — run it, check the output, confirm it matches expected
|
|
26
|
-
5. REFLECT after sessions — log what worked, what failed, what to change
|
|
27
|
-
6. ITERATE means one change at a time — fix before adding, verify before proceeding
|
|
28
|
-
7. LEARN from every session — patterns become instincts, corrections weaken bad behaviors, nothing is permanent without reinforcement
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
const CURSOR_BLOCK = `Follow continuous-improvement: Research → Plan → Execute (one thing) → Verify → Reflect → Iterate.
|
|
32
|
-
Never report "done" without verification.
|
|
33
|
-
Never add features before fixing bugs.
|
|
34
|
-
Never execute without checking docs first.
|
|
35
|
-
`;
|
|
36
|
-
|
|
37
|
-
const CHATGPT_BLOCK = `Follow the continuous-improvement loop for all tasks:
|
|
38
|
-
1. Research first — what exists? what can break? what are the limits?
|
|
39
|
-
2. Plan — what to build, what NOT to build, how to verify, fallback plan
|
|
40
|
-
3. Execute one thing at a time — finish and verify before starting the next
|
|
41
|
-
4. Verify before saying "done" — actually check the output
|
|
42
|
-
5. Reflect — what worked, what failed, what to do differently
|
|
43
|
-
6. Iterate — one change at a time, verify each before proceeding
|
|
44
|
-
`;
|
|
45
|
-
|
|
46
|
-
function usage(code = 0) {
|
|
47
|
-
console.log(`continuous-improvement\n\nUsage:\n continuous-improvement install [--claude|--codex|--cursor|--openclaw|--chatgpt] [--global] [--dry-run]\n continuous-improvement uninstall [--claude|--codex|--cursor|--openclaw]\n\nExamples:\n npx continuous-improvement install\n npx continuous-improvement install --claude\n npx continuous-improvement install --cursor\n npx continuous-improvement install --openclaw\n npx continuous-improvement install --chatgpt\n npx continuous-improvement install --claude --global\n npx continuous-improvement uninstall --codex\n`);
|
|
48
|
-
process.exit(code);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function exists(filePath) {
|
|
52
|
-
return fs.existsSync(filePath);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function ensureDir(dirPath) {
|
|
56
|
-
if (dryRun) return;
|
|
57
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function readUtf8(filePath) {
|
|
61
|
-
return fs.readFileSync(filePath, 'utf8');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function writeUtf8(filePath, content) {
|
|
65
|
-
if (dryRun) return;
|
|
66
|
-
ensureDir(path.dirname(filePath));
|
|
67
|
-
fs.writeFileSync(filePath, content, 'utf8');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function appendBlock(filePath, block) {
|
|
71
|
-
const trimmedBlock = block.trim();
|
|
72
|
-
const existing = exists(filePath) ? readUtf8(filePath) : '';
|
|
73
|
-
|
|
74
|
-
if (existing.includes(trimmedBlock)) {
|
|
75
|
-
return { changed: false, reason: 'already-installed' };
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const next = existing.trim().length === 0
|
|
79
|
-
? `${trimmedBlock}\n`
|
|
80
|
-
: `${existing.replace(/\s*$/, '')}\n\n${trimmedBlock}\n`;
|
|
81
|
-
|
|
82
|
-
writeUtf8(filePath, next);
|
|
83
|
-
return { changed: true };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function removeBlock(filePath, block) {
|
|
87
|
-
if (!exists(filePath)) {
|
|
88
|
-
return { changed: false, reason: 'not-found' };
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const trimmedBlock = block.trim();
|
|
92
|
-
const existing = readUtf8(filePath);
|
|
93
|
-
|
|
94
|
-
if (!existing.includes(trimmedBlock)) {
|
|
95
|
-
return { changed: false, reason: 'not-installed' };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const next = existing
|
|
99
|
-
.replace(new RegExp(`\\n?\\n?${escapeRegExp(trimmedBlock)}\\n?`, 'm'), '\n')
|
|
100
|
-
.replace(/^\s+|\s+$/g, '');
|
|
101
|
-
|
|
102
|
-
writeUtf8(filePath, next ? `${next}\n` : '');
|
|
103
|
-
return { changed: true };
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function escapeRegExp(value) {
|
|
107
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function copySkill() {
|
|
111
|
-
const sourceDir = path.join(rootDir, 'skills', 'continuous-improvement');
|
|
112
|
-
const destDir = path.join(homeDir, '.openclaw', 'skills', 'continuous-improvement');
|
|
113
|
-
const sourceFile = path.join(sourceDir, 'SKILL.md');
|
|
114
|
-
const destFile = path.join(destDir, 'SKILL.md');
|
|
115
|
-
const content = readUtf8(sourceFile);
|
|
116
|
-
|
|
117
|
-
if (exists(destFile) && readUtf8(destFile) === content) {
|
|
118
|
-
return { target: 'openclaw', location: destFile, changed: false, reason: 'already-installed' };
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
writeUtf8(destFile, content);
|
|
122
|
-
return { target: 'openclaw', location: destFile, changed: true };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function setupMulahazah() {
|
|
126
|
-
const mulahazahDir = path.join(homeDir, '.claude', 'mulahazah');
|
|
127
|
-
const instinctsPersonalDir = path.join(mulahazahDir, 'instincts', 'personal');
|
|
128
|
-
const projectsDir = path.join(mulahazahDir, 'projects');
|
|
129
|
-
|
|
130
|
-
ensureDir(mulahazahDir);
|
|
131
|
-
ensureDir(instinctsPersonalDir);
|
|
132
|
-
ensureDir(projectsDir);
|
|
133
|
-
|
|
134
|
-
const configDest = path.join(mulahazahDir, 'config.json');
|
|
135
|
-
if (!exists(configDest)) {
|
|
136
|
-
const configSrc = path.join(rootDir, 'config.json');
|
|
137
|
-
if (exists(configSrc)) {
|
|
138
|
-
writeUtf8(configDest, readUtf8(configSrc));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const projectsRegistry = path.join(mulahazahDir, 'projects.json');
|
|
143
|
-
if (!exists(projectsRegistry)) {
|
|
144
|
-
writeUtf8(projectsRegistry, JSON.stringify({}, null, 2) + '\n');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return { location: mulahazahDir, changed: true };
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function installHooks() {
|
|
151
|
-
const mulahazahDir = path.join(homeDir, '.claude', 'mulahazah');
|
|
152
|
-
const hookDest = path.join(mulahazahDir, 'observe.sh');
|
|
153
|
-
const hookSrc = path.join(rootDir, 'hooks', 'observe.sh');
|
|
154
|
-
|
|
155
|
-
ensureDir(mulahazahDir);
|
|
156
|
-
|
|
157
|
-
if (exists(hookSrc)) {
|
|
158
|
-
writeUtf8(hookDest, readUtf8(hookSrc));
|
|
159
|
-
if (!dryRun) {
|
|
160
|
-
fs.chmodSync(hookDest, 0o755);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const settingsPath = path.join(homeDir, '.claude', 'settings.json');
|
|
165
|
-
let settings = {};
|
|
166
|
-
if (exists(settingsPath)) {
|
|
167
|
-
try {
|
|
168
|
-
settings = JSON.parse(readUtf8(settingsPath));
|
|
169
|
-
} catch (_) {
|
|
170
|
-
settings = {};
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const hookEntry = { matcher: '*', hooks: [{ type: 'command', command: hookDest }] };
|
|
175
|
-
|
|
176
|
-
let changed = false;
|
|
177
|
-
|
|
178
|
-
for (const hookType of ['PreToolUse', 'PostToolUse']) {
|
|
179
|
-
if (!settings.hooks) settings.hooks = {};
|
|
180
|
-
if (!settings.hooks[hookType]) settings.hooks[hookType] = [];
|
|
181
|
-
|
|
182
|
-
const alreadyInstalled = settings.hooks[hookType].some(
|
|
183
|
-
(entry) => entry.hooks && entry.hooks.some((h) => h.command === hookDest)
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
if (!alreadyInstalled) {
|
|
187
|
-
settings.hooks[hookType].push(hookEntry);
|
|
188
|
-
changed = true;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (changed) {
|
|
193
|
-
writeUtf8(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return { location: settingsPath, changed };
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function copyObserverFiles() {
|
|
200
|
-
const agentsSrc = path.join(rootDir, 'agents');
|
|
201
|
-
const agentsDest = path.join(homeDir, '.claude', 'mulahazah', 'agents');
|
|
202
|
-
|
|
203
|
-
ensureDir(agentsDest);
|
|
204
|
-
|
|
205
|
-
const filesToCopy = ['observer.md', 'observer-loop.sh', 'start-observer.sh'];
|
|
206
|
-
let changed = false;
|
|
207
|
-
|
|
208
|
-
for (const fileName of filesToCopy) {
|
|
209
|
-
const srcFile = path.join(agentsSrc, fileName);
|
|
210
|
-
const destFile = path.join(agentsDest, fileName);
|
|
211
|
-
|
|
212
|
-
if (exists(srcFile)) {
|
|
213
|
-
const content = readUtf8(srcFile);
|
|
214
|
-
const existingContent = exists(destFile) ? readUtf8(destFile) : null;
|
|
215
|
-
if (existingContent !== content) {
|
|
216
|
-
writeUtf8(destFile, content);
|
|
217
|
-
if (!dryRun && fileName.endsWith('.sh')) {
|
|
218
|
-
fs.chmodSync(destFile, 0o755);
|
|
219
|
-
}
|
|
220
|
-
changed = true;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return { location: agentsDest, changed };
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function uninstallHooks() {
|
|
229
|
-
const settingsPath = path.join(homeDir, '.claude', 'settings.json');
|
|
230
|
-
if (!exists(settingsPath)) return;
|
|
231
|
-
|
|
232
|
-
let settings;
|
|
233
|
-
try {
|
|
234
|
-
settings = JSON.parse(readUtf8(settingsPath));
|
|
235
|
-
} catch (_) {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (!settings.hooks) return;
|
|
240
|
-
|
|
241
|
-
const mulahazahDir = path.join(homeDir, '.claude', 'mulahazah');
|
|
242
|
-
const hookDest = path.join(mulahazahDir, 'observe.sh');
|
|
243
|
-
|
|
244
|
-
let changed = false;
|
|
245
|
-
for (const hookType of ['PreToolUse', 'PostToolUse']) {
|
|
246
|
-
if (!Array.isArray(settings.hooks[hookType])) continue;
|
|
247
|
-
const before = settings.hooks[hookType].length;
|
|
248
|
-
settings.hooks[hookType] = settings.hooks[hookType].filter(
|
|
249
|
-
(entry) => !(entry.hooks && entry.hooks.some((h) => h.command === hookDest))
|
|
250
|
-
);
|
|
251
|
-
if (settings.hooks[hookType].length === 0) {
|
|
252
|
-
delete settings.hooks[hookType];
|
|
253
|
-
}
|
|
254
|
-
if (settings.hooks[hookType] === undefined || settings.hooks[hookType].length !== before) {
|
|
255
|
-
changed = true;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (Object.keys(settings.hooks).length === 0) {
|
|
260
|
-
delete settings.hooks;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (changed) {
|
|
264
|
-
writeUtf8(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function installClaude(globalInstall = useGlobal) {
|
|
269
|
-
const filePath = globalInstall
|
|
270
|
-
? path.join(homeDir, '.claude', 'CLAUDE.md')
|
|
271
|
-
: path.join(cwd, 'CLAUDE.md');
|
|
272
|
-
const result = appendBlock(filePath, CODING_AGENT_BLOCK);
|
|
273
|
-
return { target: 'claude', location: filePath, ...result };
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function installCodex() {
|
|
277
|
-
const filePath = path.join(cwd, 'AGENTS.md');
|
|
278
|
-
const result = appendBlock(filePath, CODING_AGENT_BLOCK);
|
|
279
|
-
return { target: 'codex', location: filePath, ...result };
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function installCursor() {
|
|
283
|
-
const filePath = path.join(cwd, '.cursorrules');
|
|
284
|
-
const result = appendBlock(filePath, CURSOR_BLOCK);
|
|
285
|
-
return { target: 'cursor', location: filePath, ...result };
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function installChatgpt() {
|
|
289
|
-
return { target: 'chatgpt', location: 'stdout', changed: true, printed: CHATGPT_BLOCK };
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function uninstallClaude(globalInstall = useGlobal) {
|
|
293
|
-
const filePath = globalInstall
|
|
294
|
-
? path.join(homeDir, '.claude', 'CLAUDE.md')
|
|
295
|
-
: path.join(cwd, 'CLAUDE.md');
|
|
296
|
-
const result = removeBlock(filePath, CODING_AGENT_BLOCK);
|
|
297
|
-
return { target: 'claude', location: filePath, ...result };
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function uninstallCodex() {
|
|
301
|
-
const filePath = path.join(cwd, 'AGENTS.md');
|
|
302
|
-
const result = removeBlock(filePath, CODING_AGENT_BLOCK);
|
|
303
|
-
return { target: 'codex', location: filePath, ...result };
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function uninstallCursor() {
|
|
307
|
-
const filePath = path.join(cwd, '.cursorrules');
|
|
308
|
-
const result = removeBlock(filePath, CURSOR_BLOCK);
|
|
309
|
-
return { target: 'cursor', location: filePath, ...result };
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
function uninstallOpenclaw() {
|
|
313
|
-
const destFile = path.join(homeDir, '.openclaw', 'skills', 'continuous-improvement', 'SKILL.md');
|
|
314
|
-
if (!exists(destFile)) {
|
|
315
|
-
return { target: 'openclaw', location: destFile, changed: false, reason: 'not-installed' };
|
|
316
|
-
}
|
|
317
|
-
if (!dryRun) {
|
|
318
|
-
fs.rmSync(path.dirname(destFile), { recursive: true, force: true });
|
|
319
|
-
}
|
|
320
|
-
return { target: 'openclaw', location: destFile, changed: true };
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function detectTargets() {
|
|
324
|
-
const targets = [];
|
|
325
|
-
if (exists(path.join(cwd, 'CLAUDE.md'))) targets.push('claude');
|
|
326
|
-
if (exists(path.join(cwd, 'AGENTS.md'))) targets.push('codex');
|
|
327
|
-
if (exists(path.join(cwd, '.cursorrules'))) targets.push('cursor');
|
|
328
|
-
if (exists(path.join(homeDir, '.openclaw'))) targets.push('openclaw');
|
|
329
|
-
if (targets.length === 0) {
|
|
330
|
-
if (exists(path.join(homeDir, '.claude'))) targets.push('claude-global');
|
|
331
|
-
}
|
|
332
|
-
return targets;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
function installTarget(target) {
|
|
336
|
-
switch (target) {
|
|
337
|
-
case 'claude': {
|
|
338
|
-
const claudeResult = installClaude(false);
|
|
339
|
-
const mulahazahResult = setupMulahazah();
|
|
340
|
-
const hooksResult = installHooks();
|
|
341
|
-
const observerResult = copyObserverFiles();
|
|
342
|
-
return { ...claudeResult, mulahazah: mulahazahResult, hooks: hooksResult, observer: observerResult };
|
|
343
|
-
}
|
|
344
|
-
case 'claude-global': {
|
|
345
|
-
const claudeResult = installClaude(true);
|
|
346
|
-
const mulahazahResult = setupMulahazah();
|
|
347
|
-
const hooksResult = installHooks();
|
|
348
|
-
const observerResult = copyObserverFiles();
|
|
349
|
-
return { ...claudeResult, mulahazah: mulahazahResult, hooks: hooksResult, observer: observerResult };
|
|
350
|
-
}
|
|
351
|
-
case 'codex':
|
|
352
|
-
return installCodex();
|
|
353
|
-
case 'cursor':
|
|
354
|
-
return installCursor();
|
|
355
|
-
case 'openclaw':
|
|
356
|
-
return copySkill();
|
|
357
|
-
case 'chatgpt':
|
|
358
|
-
return installChatgpt();
|
|
359
|
-
default:
|
|
360
|
-
throw new Error(`Unknown target: ${target}`);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
function uninstallTarget(target) {
|
|
365
|
-
switch (target) {
|
|
366
|
-
case 'claude':
|
|
367
|
-
uninstallHooks();
|
|
368
|
-
return uninstallClaude(false);
|
|
369
|
-
case 'claude-global':
|
|
370
|
-
uninstallHooks();
|
|
371
|
-
return uninstallClaude(true);
|
|
372
|
-
case 'codex':
|
|
373
|
-
return uninstallCodex();
|
|
374
|
-
case 'cursor':
|
|
375
|
-
return uninstallCursor();
|
|
376
|
-
case 'openclaw':
|
|
377
|
-
return uninstallOpenclaw();
|
|
378
|
-
default:
|
|
379
|
-
throw new Error(`Unknown target for uninstall: ${target}`);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (!command || command === '--help' || command === '-h' || flags.has('--help') || flags.has('-h')) {
|
|
384
|
-
usage(0);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (command !== 'install' && command !== 'uninstall') {
|
|
388
|
-
console.error(`Unknown command: ${command}`);
|
|
389
|
-
usage(1);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
const targets = selectedTarget ? [selectedTarget] : detectTargets();
|
|
393
|
-
|
|
394
|
-
if (targets.length === 0) {
|
|
395
|
-
console.log('No target detected automatically.');
|
|
396
|
-
console.log('Try one of:');
|
|
397
|
-
console.log(' npx continuous-improvement install --claude');
|
|
398
|
-
console.log(' npx continuous-improvement install --codex');
|
|
399
|
-
console.log(' npx continuous-improvement install --cursor');
|
|
400
|
-
console.log(' npx continuous-improvement install --openclaw');
|
|
401
|
-
console.log(' npx continuous-improvement install --chatgpt');
|
|
402
|
-
process.exit(0);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
const results = command === 'install'
|
|
406
|
-
? targets.map(installTarget)
|
|
407
|
-
: targets.filter((target) => target !== 'chatgpt').map(uninstallTarget);
|
|
408
|
-
|
|
409
|
-
console.log(`continuous-improvement ${command}\n`);
|
|
410
|
-
for (const result of results) {
|
|
411
|
-
if (result.printed) {
|
|
412
|
-
console.log(`✓ ${result.target}: copy this into ChatGPT Custom Instructions\n`);
|
|
413
|
-
console.log(result.printed);
|
|
414
|
-
continue;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const status = command === 'install'
|
|
418
|
-
? (result.changed ? 'installed' : (result.reason || 'unchanged'))
|
|
419
|
-
: (result.changed ? 'removed' : (result.reason || 'unchanged'));
|
|
420
|
-
console.log(`✓ ${result.target}: ${status} → ${result.location}${dryRun ? ' (dry-run)' : ''}`);
|
|
421
|
-
|
|
422
|
-
if (command === 'install' && result.mulahazah) {
|
|
423
|
-
console.log(` ✓ mulahazah: directory created → ~/.claude/mulahazah/`);
|
|
424
|
-
}
|
|
425
|
-
if (command === 'install' && result.hooks) {
|
|
426
|
-
console.log(` ✓ hooks: PreToolUse + PostToolUse → ~/.claude/settings.json`);
|
|
427
|
-
}
|
|
428
|
-
if (command === 'install' && result.observer) {
|
|
429
|
-
console.log(` ✓ observer: agent files copied → ~/.claude/mulahazah/agents/`);
|
|
430
|
-
console.log(` To start background observer: ~/.claude/mulahazah/agents/start-observer.sh`);
|
|
431
|
-
console.log(` Run /continuous-improvement after your next session to see what was learned.`);
|
|
432
|
-
}
|
|
433
|
-
}
|