homunculus-code 0.1.0 → 0.3.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.
@@ -0,0 +1,211 @@
1
+ # Architecture: Goal-Tree-Driven Evolution
2
+
3
+ This document explains the design philosophy behind Homunculus.
4
+
5
+ ## The Problem
6
+
7
+ AI assistants are statically configured. You write rules, add skills, configure hooks — but the AI never improves on its own. Every improvement requires human effort:
8
+
9
+ 1. Notice something could be better
10
+ 2. Research the solution
11
+ 3. Implement it (skill, hook, rule, script)
12
+ 4. Test it manually
13
+ 5. Maintain it when things change
14
+
15
+ This doesn't scale. As your system grows, maintenance becomes a full-time job.
16
+
17
+ ## The Solution: Goal Trees
18
+
19
+ Instead of configuring individual behaviors, you define **what you want** in a tree of goals. The system figures out **how to achieve it** — and keeps improving the "how" over time.
20
+
21
+ ### Why a Tree?
22
+
23
+ Goals are naturally hierarchical:
24
+
25
+ ```
26
+ "Ship better software"
27
+ ├── "Write fewer bugs"
28
+ │ ├── "Every change has tests"
29
+ │ └── "Catch issues before merge"
30
+ └── "Move faster"
31
+ ├── "Automate repetitive tasks"
32
+ └── "Debug faster"
33
+ ```
34
+
35
+ A tree structure gives you:
36
+ - **Decomposition** — Break big goals into measurable sub-goals
37
+ - **Priority** — Unhealthy sub-goals bubble up to their parent
38
+ - **Independence** — Each sub-goal can be implemented differently
39
+ - **Replaceability** — Swap implementations without affecting goals
40
+
41
+ ### Goal Node Schema
42
+
43
+ Every node in the tree follows the same schema:
44
+
45
+ ```yaml
46
+ goal_name:
47
+ purpose: "Why this goal exists" # Never changes
48
+ realized_by: path/to/implementation # Changes as system evolves
49
+ metrics:
50
+ - name: metric_name
51
+ source: where to get the data
52
+ healthy: "what healthy looks like" # Defines success
53
+ health_check:
54
+ command: "shell command" # Machine-executable
55
+ expected: "human description" # For readability
56
+ goals:
57
+ sub_goal_1: ... # Recursive
58
+ sub_goal_2: ...
59
+ ```
60
+
61
+ ### The `realized_by` Field
62
+
63
+ This is the key innovation. It decouples **what** (the goal) from **how** (the implementation). The value can be:
64
+
65
+ - A skill: `skills/tdd-workflow.md`
66
+ - An agent: `agents/code-reviewer.md`
67
+ - A hook: `hooks/pre-commit.sh`
68
+ - A script: `scripts/deploy.sh`
69
+ - A cron job: `launchd/nightly.plist`
70
+ - An MCP server: `mcp-servers/github`
71
+ - A rule: `rules/security.md`
72
+ - A slash command: `commands/quality-gate.md`
73
+ - Or anything else
74
+
75
+ The evolution system can **replace** the implementation at any time, as long as the goal's health check still passes. This is what makes the system truly self-improving — it's not locked into any particular approach.
76
+
77
+ ## Evolution Pipeline
78
+
79
+ ### Layer 1: Observation → Instincts
80
+
81
+ ```
82
+ Tool usage → observe.sh (hook) → observations.jsonl
83
+
84
+ evaluate-session.js (SessionEnd)
85
+
86
+
87
+ instincts/personal/*.md
88
+ (confidence-scored patterns)
89
+ ```
90
+
91
+ Instincts are small behavioral patterns with:
92
+ - **Confidence scores** — increase with reinforcement, decay over time
93
+ - **Half-life decay** — unused instincts fade (default: 90 days)
94
+ - **Automatic archival** — `prune-instincts.js` archives low-value ones
95
+
96
+ ### Layer 2: Convergence → Skills
97
+
98
+ ```
99
+ Related instincts (3+) → /evolve → evolved/skills/*.md
100
+
101
+ eval spec (scenarios)
102
+
103
+ /eval-skill → score
104
+
105
+ /improve-skill → iterate
106
+
107
+ 100% pass rate
108
+ ```
109
+
110
+ Skills are:
111
+ - **Tested** — every skill has an eval spec with scenario tests
112
+ - **Versioned** — changes tracked with semver
113
+ - **Quality-gated** — must pass eval before adoption
114
+ - **Regression-protected** — rollback if quality drops
115
+
116
+ ### Layer 3: Goal-Directed Evolution
117
+
118
+ ```
119
+ architecture.yaml
120
+
121
+
122
+ health_check.command → pass/fail per goal
123
+
124
+
125
+ Unhealthy goals get priority
126
+
127
+
128
+ Evolution engine focuses improvement
129
+ on the weakest areas
130
+ ```
131
+
132
+ The goal tree adds **direction** to evolution. Without it, the system learns whatever patterns happen to occur. With it, the system asks: "which goals are failing?" and focuses there.
133
+
134
+ ### Layer 4: Autonomous Operation (Nightly Agent)
135
+
136
+ ```
137
+ launchd/cron → heartbeat.sh (scheduled)
138
+
139
+ ┌───────────────┼───────────────┐
140
+ ▼ ▼ ▼
141
+ Health Check Evolve Pipeline Research
142
+ │ │ │
143
+ ▼ ▼ ▼
144
+ Identify weak eval → improve Scan for better
145
+ goals → prune approaches
146
+ │ │ │
147
+ └───────────────┼───────────────┘
148
+
149
+ Morning Report
150
+ ```
151
+
152
+ The nightly agent closes the loop — no human intervention needed for routine evolution.
153
+
154
+ ### Layer 5: Meta-Evolution
155
+
156
+ The evolution mechanism itself is measured and adjusted:
157
+
158
+ | Metric | What it measures | Action if unhealthy |
159
+ |--------|-----------------|-------------------|
160
+ | `instinct_survival_rate` | % of instincts surviving 14 days | Raise extraction thresholds |
161
+ | `skill_convergence` | Time from first instinct to skill | Adjust aggregation triggers |
162
+ | `eval_discrimination` | % of scenarios that distinguish versions | Add harder boundary scenarios |
163
+
164
+ This prevents the system from degenerating — if it's extracting too many low-quality instincts, it automatically becomes more selective.
165
+
166
+ ## Design Principles
167
+
168
+ ### 1. Goals Over Implementations
169
+
170
+ Never optimize an implementation directly. Always ask: "which goal does this serve?" If there's no goal, the implementation shouldn't exist.
171
+
172
+ ### 2. Measure Everything
173
+
174
+ If you can't measure it, you can't evolve it. Every goal should eventually have a `health_check` or `metrics` entry. Start with approximate metrics and refine them.
175
+
176
+ ### 3. Replaceable Everything
177
+
178
+ No implementation is sacred. A skill can be replaced by a hook. A script can be replaced by an agent. The only constant is the goal tree.
179
+
180
+ ### 4. Safe Evolution
181
+
182
+ - Eval specs prevent regression
183
+ - Experiments run in isolated worktrees
184
+ - Rollback if quality drops
185
+ - Noise tolerance (5pp) prevents chasing statistical artifacts
186
+
187
+ ### 5. Progressive Complexity
188
+
189
+ Start simple:
190
+ 1. Just the goal tree + observation hook
191
+ 2. Let instincts accumulate naturally
192
+ 3. Evolve first skill when you have enough instincts
193
+ 4. Add eval spec for quality control
194
+ 5. Set up nightly agent when you're ready for autonomy
195
+
196
+ Don't try to build the full system on day one. Let it grow.
197
+
198
+ ## Comparison with Other Approaches
199
+
200
+ | Approach | Optimizes | Direction | Quality Control | Autonomous |
201
+ |----------|-----------|-----------|----------------|------------|
202
+ | Manual rules | Individual behaviors | Human-directed | None | No |
203
+ | Claude Memory | Fact recall | Usage-driven | None | No |
204
+ | OpenClaw skills | Skill generation | Human-triggered | None | Partial |
205
+ | **Homunculus** | **Goal achievement** | **Goal-tree-driven** | **Eval specs** | **Yes (nightly)** |
206
+
207
+ ## Further Reading
208
+
209
+ - [README.md](README.md) — Quick start and overview
210
+ - [docs/nightly-agent.md](docs/nightly-agent.md) — Setting up autonomous operation
211
+ - [examples/reference/](examples/reference/) — Real-world system after 15 days
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Homunculus for Claude Code
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/homunculus-code)](https://www.npmjs.com/package/homunculus-code)
3
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
  [![Claude Code](https://img.shields.io/badge/Claude%20Code-v2.1.70+-blue)](https://docs.anthropic.com/en/docs/claude-code)
5
6
  [![Node.js](https://img.shields.io/badge/Node.js-18+-green)](https://nodejs.org)
@@ -153,35 +154,74 @@ The evolution engine then:
153
154
  npx homunculus-code init
154
155
  ```
155
156
 
156
- The wizard asks you a few questions and sets everything up:
157
+ ```
158
+ Homunculus — Self-evolving AI Assistant
159
+
160
+ ✓ Created homunculus/ directory structure
161
+ ✓ Added evolution rules
162
+ ✓ Copied evolution scripts
163
+ ✓ Added slash commands (/hm-setup, /hm-night, /hm-status)
164
+ ✓ Configured observation hook
157
165
 
166
+ Done! Homunculus is installed.
167
+
168
+ Next steps:
169
+ 1. Run claude to open Claude Code
170
+ 2. Type /hm-setup to define your goals (AI-guided)
171
+ 3. Type /hm-night to run your first evolution cycle
158
172
  ```
159
- 🧬 Homunculus — Self-evolving AI Assistant
160
173
 
161
- ? What's your project name? my-app
162
- ? What's your main goal? Build a reliable SaaS product
174
+ ### 2. Define Your Goals
163
175
 
164
- Created homunculus/ structure
165
- ✅ Generated architecture.yaml with your goals
166
- ✅ Added observation hook to Claude Code
167
- ✅ Copied evolution scripts
176
+ Open Claude Code and type `/hm-setup`. Claude will have a short conversation with you to understand your project and goals, then generate your `architecture.yaml` automatically.
168
177
 
169
- Done! Start using Claude Code. Your assistant will evolve.
170
178
  ```
179
+ > /hm-setup
171
180
 
172
- ### 2. Use Claude Code Normally
181
+ Claude: What kind of project is this?
182
+ You: A SaaS app for team collaboration
173
183
 
174
- That's it. The system observes, extracts, and evolves in the background. Check progress anytime:
184
+ Claude: What do you spend most time on?
185
+ You: Debugging auth issues and writing tests
175
186
 
176
- ```bash
177
- claude "/eval-skill" # Run skill evaluations
178
- claude "/improve-skill" # Auto-improve a skill
179
- claude "/evolve" # Converge instincts into skills
187
+ Claude: Here's your goal tree:
188
+ 🎯 Team Collaboration SaaS
189
+ ├── code_quality Ship fewer bugs
190
+ │ ├── testing Every change has tests
191
+ │ └── auth_reliability — Auth works every time
192
+ ├── productivity — Move faster
193
+ │ └── debugging — Find root causes faster
194
+ └── knowledge — Stay current
195
+ └── tool_updates — Track Claude Code updates
196
+
197
+ Does this look right?
198
+ You: Yes!
199
+
200
+ Claude: ✅ architecture.yaml created with 5 goals!
180
201
  ```
181
202
 
182
- ### 3. Refine Your Goals (Optional)
203
+ ### 3. Run Your First Evolution Cycle
204
+
205
+ ```
206
+ > /hm-night
207
+ ```
208
+
209
+ Watch Claude check your goals, scan for patterns, evaluate skills, and generate a report — all in one command. This is what the nightly agent does autonomously while you sleep.
210
+
211
+ ### 4. Keep Using Claude Code
212
+
213
+ The observation hook watches your usage automatically. As patterns emerge:
214
+
215
+ ```
216
+ /hm-night Run an evolution cycle
217
+ /hm-status Check evolution progress
218
+ /hm-setup Refine your goals anytime
219
+ /eval-skill Evaluate a specific skill
220
+ /improve-skill Auto-improve a skill
221
+ /evolve Converge instincts into skills
222
+ ```
183
223
 
184
- As you use the system, refine `architecture.yaml` add sub-goals, metrics, and health checks. The more specific your goals, the smarter the evolution.
224
+ Set up the [nightly agent](docs/nightly-agent.md) to run `/hm-night` autonomously while you sleep.
185
225
 
186
226
  ---
187
227
 
package/bin/cli.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ // homunculus-code CLI — entry point
3
+
4
+ const command = process.argv[2];
5
+
6
+ switch (command) {
7
+ case 'init':
8
+ require('./init.js');
9
+ break;
10
+ case 'night':
11
+ require('./night.js');
12
+ break;
13
+ case 'help':
14
+ case '--help':
15
+ case '-h':
16
+ case undefined:
17
+ console.log('');
18
+ console.log(' \x1b[1mHomunculus\x1b[0m — Self-evolving AI Assistant for Claude Code');
19
+ console.log('');
20
+ console.log(' Usage:');
21
+ console.log(' npx homunculus-code <command>');
22
+ console.log('');
23
+ console.log(' Commands:');
24
+ console.log(' init Set up Homunculus in your project');
25
+ console.log(' night Run one evolution cycle (health check → evolve → report)');
26
+ console.log(' help Show this help message');
27
+ console.log('');
28
+ console.log(' After init, use Claude Code normally. Evolution happens automatically.');
29
+ console.log(' Run "night" anytime to trigger a manual evolution cycle.');
30
+ console.log('');
31
+ break;
32
+ default:
33
+ console.error(` Unknown command: ${command}`);
34
+ console.error(' Run "npx homunculus-code help" for available commands.');
35
+ process.exit(1);
36
+ }
package/bin/init.js CHANGED
@@ -1,44 +1,17 @@
1
1
  #!/usr/bin/env node
2
- // homunculus init — Set up a self-evolving AI assistant in your project
2
+ // homunculus init — Set up the evolution structure in your project
3
3
 
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
- const readline = require('readline');
7
6
 
8
7
  const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
9
8
  const CORE_DIR = path.join(__dirname, '..', 'core');
10
9
  const COMMANDS_DIR = path.join(__dirname, '..', 'commands');
11
10
 
12
- const YES_MODE = process.argv.includes('--yes') || process.argv.includes('-y');
13
-
14
- let rl;
15
- if (!YES_MODE) {
16
- rl = readline.createInterface({
17
- input: process.stdin,
18
- output: process.stdout
19
- });
20
- }
21
-
22
- function ask(question, defaultVal) {
23
- if (YES_MODE) return Promise.resolve(process.env[`HOMUNCULUS_${question.replace(/[^A-Z]/gi, '_').toUpperCase()}`] || defaultVal || '');
24
- return new Promise(resolve => {
25
- const suffix = defaultVal ? ` (${defaultVal})` : '';
26
- rl.question(`${question}${suffix}: `, answer => {
27
- resolve(answer.trim() || defaultVal || '');
28
- });
29
- });
30
- }
31
-
32
11
  function ensureDir(dir) {
33
12
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
34
13
  }
35
14
 
36
- function copyFile(src, dest) {
37
- if (fs.existsSync(src)) {
38
- fs.copyFileSync(src, dest);
39
- }
40
- }
41
-
42
15
  function copyDir(src, dest) {
43
16
  ensureDir(dest);
44
17
  if (!fs.existsSync(src)) return;
@@ -53,18 +26,9 @@ function copyDir(src, dest) {
53
26
  }
54
27
  }
55
28
 
56
- function replaceTemplateVars(content, vars) {
57
- let result = content;
58
- for (const [key, value] of Object.entries(vars)) {
59
- result = result.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
60
- }
61
- return result;
62
- }
63
-
64
- async function main() {
29
+ function main() {
65
30
  console.log('');
66
31
  console.log(' \x1b[1mHomunculus\x1b[0m — Self-evolving AI Assistant');
67
- console.log(' A seed that grows into your own AI assistant.');
68
32
  console.log('');
69
33
 
70
34
  const projectDir = process.cwd();
@@ -75,128 +39,6 @@ async function main() {
75
39
  console.log('');
76
40
  }
77
41
 
78
- // Gather info
79
- const projectName = await ask(' Project name', path.basename(projectDir));
80
- const purpose = await ask(' What is this project\'s main goal?', 'My evolving AI assistant');
81
-
82
- console.log('');
83
- console.log(' Select areas you want your AI to improve in:');
84
- console.log('');
85
-
86
- const goalOptions = [
87
- { key: '1', name: 'code_quality', label: 'Code Quality', desc: 'Ship fewer bugs, better tests' },
88
- { key: '2', name: 'productivity', label: 'Productivity', desc: 'Complete tasks faster' },
89
- { key: '3', name: 'debugging', label: 'Debugging', desc: 'Faster root cause analysis' },
90
- { key: '4', name: 'documentation', label: 'Documentation', desc: 'Keep docs up to date' },
91
- { key: '5', name: 'automation', label: 'Automation', desc: 'Automate repetitive work' },
92
- { key: '6', name: 'learning', label: 'Continuous Learning', desc: 'Stay up to date with tools and patterns' },
93
- ];
94
-
95
- for (const opt of goalOptions) {
96
- console.log(` ${opt.key}. ${opt.label} — ${opt.desc}`);
97
- }
98
- console.log('');
99
-
100
- const selectedStr = await ask(' Select areas (enter numbers, e.g. 1,2,5)', '1,2');
101
- const selectedKeys = selectedStr.split(/[,\s]+/).map(s => s.trim()).filter(Boolean);
102
- const selectedGoals = goalOptions.filter(o => selectedKeys.includes(o.key));
103
- if (selectedGoals.length === 0) selectedGoals.push(goalOptions[0], goalOptions[1]);
104
-
105
- console.log('');
106
-
107
- const vars = {
108
- PROJECT_NAME: projectName,
109
- PROJECT_PURPOSE: purpose
110
- };
111
-
112
- // Generate architecture.yaml from selected goals
113
- function generateArchitecture(goals, rootPurpose) {
114
- let yaml = `# architecture.yaml — Your goal tree\n`;
115
- yaml += `# Goals are stable. Implementations evolve.\n`;
116
- yaml += `# See: https://github.com/JavanC/Homunculus\n\n`;
117
- yaml += `version: "1.0"\n\n`;
118
- yaml += `root:\n`;
119
- yaml += ` purpose: "${rootPurpose}"\n\n`;
120
- yaml += ` goals:\n`;
121
-
122
- const goalTemplates = {
123
- code_quality: {
124
- purpose: 'Ship fewer bugs, write more maintainable code',
125
- goals: {
126
- testing: { purpose: 'Every change has tests', realized_by: '# will evolve' },
127
- review: { purpose: 'Catch issues before merge', realized_by: '# will evolve' }
128
- },
129
- metrics: [{ name: 'test_pass_rate', healthy: '> 90%' }]
130
- },
131
- productivity: {
132
- purpose: 'Complete tasks faster with fewer iterations',
133
- goals: {
134
- task_completion: { purpose: 'Finish tasks in fewer cycles', realized_by: '# will evolve' },
135
- tool_mastery: { purpose: 'Use the right tool on first try', realized_by: '# will evolve' }
136
- },
137
- metrics: [{ name: 'avg_iterations_per_task', healthy: 'decreasing trend' }]
138
- },
139
- debugging: {
140
- purpose: 'Find and fix bugs faster',
141
- goals: {
142
- root_cause: { purpose: 'Identify root causes, not symptoms', realized_by: '# will evolve' },
143
- diagnosis_tools: { purpose: 'Use the right debugging approach', realized_by: '# will evolve' }
144
- },
145
- metrics: [{ name: 'avg_debug_time', healthy: 'decreasing trend' }]
146
- },
147
- documentation: {
148
- purpose: 'Keep documentation accurate and up to date',
149
- goals: {
150
- api_docs: { purpose: 'API docs match implementation', realized_by: '# will evolve' },
151
- decision_records: { purpose: 'Document why, not just what', realized_by: '# will evolve' }
152
- },
153
- metrics: [{ name: 'doc_freshness', healthy: '< 1 week behind code' }]
154
- },
155
- automation: {
156
- purpose: 'Automate repetitive work',
157
- goals: {
158
- ci_cd: { purpose: 'Automated build, test, deploy', realized_by: '# will evolve' },
159
- workflows: { purpose: 'Common sequences as one command', realized_by: '# will evolve' }
160
- },
161
- metrics: [{ name: 'manual_steps_per_deploy', healthy: '< 3' }]
162
- },
163
- learning: {
164
- purpose: 'Stay up to date with tools and best practices',
165
- goals: {
166
- tool_updates: { purpose: 'Track and adopt useful updates', realized_by: '# will evolve' },
167
- pattern_discovery: { purpose: 'Find better ways to do things', realized_by: '# will evolve' }
168
- },
169
- metrics: [{ name: 'patterns_adopted_per_month', healthy: '> 2' }]
170
- }
171
- };
172
-
173
- for (const goal of goals) {
174
- const tmpl = goalTemplates[goal.name];
175
- if (!tmpl) continue;
176
- yaml += ` ${goal.name}:\n`;
177
- yaml += ` purpose: "${tmpl.purpose}"\n`;
178
- if (tmpl.metrics) {
179
- yaml += ` metrics:\n`;
180
- for (const m of tmpl.metrics) {
181
- yaml += ` - name: ${m.name}\n`;
182
- yaml += ` healthy: "${m.healthy}"\n`;
183
- }
184
- }
185
- if (tmpl.goals) {
186
- yaml += ` goals:\n`;
187
- for (const [subName, sub] of Object.entries(tmpl.goals)) {
188
- yaml += ` ${subName}:\n`;
189
- yaml += ` purpose: "${sub.purpose}"\n`;
190
- yaml += ` realized_by: ${sub.realized_by}\n`;
191
- }
192
- }
193
- yaml += `\n`;
194
- }
195
-
196
- yaml += ` # Add more goals as your system evolves...\n`;
197
- return yaml;
198
- }
199
-
200
42
  // 1. Create directory structure
201
43
  const dirs = [
202
44
  'homunculus/instincts/personal',
@@ -205,6 +47,7 @@ async function main() {
205
47
  'homunculus/evolved/agents',
206
48
  'homunculus/evolved/evals',
207
49
  'homunculus/experiments',
50
+ 'homunculus/reports',
208
51
  'scripts',
209
52
  '.claude/rules',
210
53
  '.claude/commands'
@@ -215,51 +58,37 @@ async function main() {
215
58
  }
216
59
  console.log(' \x1b[32m✓\x1b[0m Created homunculus/ directory structure');
217
60
 
218
- // 2. Generate architecture.yaml from selected goals
219
- const archDest = path.join(projectDir, 'architecture.yaml');
220
- if (!fs.existsSync(archDest)) {
221
- const archContent = generateArchitecture(selectedGoals, purpose);
222
- fs.writeFileSync(archDest, archContent);
223
- console.log(` \x1b[32m✓\x1b[0m Created architecture.yaml with ${selectedGoals.length} goals: ${selectedGoals.map(g => g.label).join(', ')}`);
224
- } else {
225
- console.log(' \x1b[33m-\x1b[0m architecture.yaml already exists, skipping');
61
+ // 2. Copy evolution rules
62
+ const rulesSrc = path.join(TEMPLATES_DIR, 'rules', 'evolution-system.md');
63
+ const rulesDest = path.join(projectDir, '.claude', 'rules', 'evolution-system.md');
64
+ if (!fs.existsSync(rulesDest) && fs.existsSync(rulesSrc)) {
65
+ fs.copyFileSync(rulesSrc, rulesDest);
66
+ console.log(' \x1b[32m✓\x1b[0m Added evolution rules');
226
67
  }
227
68
 
228
- // 3. Copy CLAUDE.md template (append if exists)
69
+ // 3. Copy CLAUDE.md template
70
+ const claudeSrc = path.join(TEMPLATES_DIR, 'CLAUDE.md.template');
229
71
  const claudeDest = path.join(projectDir, 'CLAUDE.md');
230
- if (!fs.existsSync(claudeDest)) {
231
- const template = fs.readFileSync(
232
- path.join(TEMPLATES_DIR, 'CLAUDE.md.template'), 'utf8'
233
- );
234
- fs.writeFileSync(claudeDest, replaceTemplateVars(template, vars));
72
+ if (!fs.existsSync(claudeDest) && fs.existsSync(claudeSrc)) {
73
+ const template = fs.readFileSync(claudeSrc, 'utf8');
74
+ const projectName = path.basename(projectDir);
75
+ fs.writeFileSync(claudeDest, template.replace(/\{\{PROJECT_NAME\}\}/g, projectName));
235
76
  console.log(' \x1b[32m✓\x1b[0m Created CLAUDE.md');
236
- } else {
237
- console.log(' \x1b[33m-\x1b[0m CLAUDE.md already exists, skipping');
238
77
  }
239
78
 
240
- // 4. Copy evolution rules
241
- const rulesDest = path.join(projectDir, '.claude', 'rules', 'evolution-system.md');
242
- if (!fs.existsSync(rulesDest)) {
243
- copyFile(
244
- path.join(TEMPLATES_DIR, 'rules', 'evolution-system.md'),
245
- rulesDest
246
- );
247
- console.log(' \x1b[32m✓\x1b[0m Created .claude/rules/evolution-system.md');
248
- }
249
-
250
- // 5. Copy core scripts
79
+ // 4. Copy core scripts
251
80
  if (fs.existsSync(CORE_DIR)) {
252
81
  copyDir(CORE_DIR, path.join(projectDir, 'scripts'));
253
- console.log(' \x1b[32m✓\x1b[0m Copied evolution scripts to scripts/');
82
+ console.log(' \x1b[32m✓\x1b[0m Copied evolution scripts');
254
83
  }
255
84
 
256
- // 6. Copy slash commands
85
+ // 5. Copy slash commands
257
86
  if (fs.existsSync(COMMANDS_DIR)) {
258
87
  copyDir(COMMANDS_DIR, path.join(projectDir, '.claude', 'commands'));
259
- console.log(' \x1b[32m✓\x1b[0m Copied slash commands to .claude/commands/');
88
+ console.log(' \x1b[32m✓\x1b[0m Added slash commands (/hm-setup, /hm-night, /hm-status)');
260
89
  }
261
90
 
262
- // 7. Configure Claude Code hooks (if settings exist)
91
+ // 6. Configure Claude Code hooks
263
92
  const settingsPath = path.join(projectDir, '.claude', 'settings.json');
264
93
  let settings = {};
265
94
  if (fs.existsSync(settingsPath)) {
@@ -275,10 +104,10 @@ async function main() {
275
104
  }];
276
105
  ensureDir(path.join(projectDir, '.claude'));
277
106
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
278
- console.log(' \x1b[32m✓\x1b[0m Configured Claude Code observation hook');
107
+ console.log(' \x1b[32m✓\x1b[0m Configured observation hook');
279
108
  }
280
109
 
281
- // 8. Create .gitignore additions
110
+ // 7. Create .gitignore additions
282
111
  const gitignorePath = path.join(projectDir, '.gitignore');
283
112
  const gitignoreEntries = [
284
113
  '',
@@ -299,19 +128,15 @@ async function main() {
299
128
  console.log(' \x1b[32m✓\x1b[0m Created .gitignore');
300
129
  }
301
130
 
131
+ // Done
302
132
  console.log('');
303
- console.log(' \x1b[1m\x1b[32mDone!\x1b[0m Your assistant is ready to evolve.');
133
+ console.log(' \x1b[1m\x1b[32mDone!\x1b[0m Homunculus is installed.');
304
134
  console.log('');
305
135
  console.log(' Next steps:');
306
- console.log(' 1. Edit \x1b[1marchitecture.yaml\x1b[0m to define your goals');
307
- console.log(' 2. Use Claude Code normally the system observes automatically');
308
- console.log(' 3. Run \x1b[1mclaude "/eval-skill"\x1b[0m to check evolution progress');
136
+ console.log(' 1. Run \x1b[1mclaude\x1b[0m to open Claude Code');
137
+ console.log(' 2. Type \x1b[1m/hm-setup\x1b[0m to define your goals (AI-guided)');
138
+ console.log(' 3. Type \x1b[1m/hm-night\x1b[0m to run your first evolution cycle');
309
139
  console.log('');
310
-
311
- if (rl) rl.close();
312
140
  }
313
141
 
314
- main().catch(err => {
315
- console.error('Error:', err.message);
316
- process.exit(1);
317
- });
142
+ main();