create-merlin-brain 1.1.2 → 1.1.4
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/bin/install.js +41 -16
- package/bin/merlin-cli.js +38 -3
- package/files/CLAUDE.md +55 -41
- package/files/loop/config.json +1 -1
- package/files/loop/lib/context.sh +1 -1
- package/files/loop/lib/state.sh +4 -4
- package/package.json +1 -1
package/bin/install.js
CHANGED
|
@@ -185,14 +185,43 @@ _merlin_check_update() {
|
|
|
185
185
|
fi
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
# Main claude wrapper with Merlin branding
|
|
188
|
+
# Main claude wrapper with Merlin branding and Sights pre-check
|
|
189
189
|
claude() {
|
|
190
|
-
# Show Merlin branding
|
|
191
|
-
echo -e "\\033[35m✦ Merlin\\033[0m"
|
|
192
|
-
|
|
193
190
|
# Check for updates in background (silent, non-blocking)
|
|
194
191
|
(_merlin_check_update &) 2>/dev/null
|
|
195
192
|
|
|
193
|
+
# Pre-flight: Check Sights connection (enforced at terminal level)
|
|
194
|
+
local status_output=$(merlin status 2>/dev/null)
|
|
195
|
+
local status_code=$(echo "$status_output" | head -1)
|
|
196
|
+
|
|
197
|
+
case "$status_code" in
|
|
198
|
+
CONNECTED)
|
|
199
|
+
local repo_name=$(echo "$status_output" | sed -n '2p')
|
|
200
|
+
echo -e "\\033[35m🔮 Merlin Sights:\\033[0m \\033[32mCONNECTED\\033[0m ✓"
|
|
201
|
+
echo -e " Repository: $repo_name"
|
|
202
|
+
;;
|
|
203
|
+
NOT_CONNECTED)
|
|
204
|
+
local repo_url=$(echo "$status_output" | sed -n '2p')
|
|
205
|
+
echo -e "\\033[35m🔮 Merlin Sights:\\033[0m \\033[33mNOT CONNECTED\\033[0m"
|
|
206
|
+
echo ""
|
|
207
|
+
echo " This repo isn't in Sights yet: $repo_url"
|
|
208
|
+
echo ""
|
|
209
|
+
echo -e " \\033[36m[1]\\033[0m Connect now (analysis takes 2-5 min)"
|
|
210
|
+
echo -e " \\033[36m[2]\\033[0m Skip - work without Sights"
|
|
211
|
+
echo ""
|
|
212
|
+
echo -n " Choice [1/2]: "
|
|
213
|
+
read -r choice
|
|
214
|
+
if [ "$choice" = "1" ]; then
|
|
215
|
+
merlin connect
|
|
216
|
+
echo ""
|
|
217
|
+
fi
|
|
218
|
+
;;
|
|
219
|
+
*)
|
|
220
|
+
# Not in git repo or CLI not available - just show branding
|
|
221
|
+
echo -e "\\033[35m✦ Merlin\\033[0m"
|
|
222
|
+
;;
|
|
223
|
+
esac
|
|
224
|
+
|
|
196
225
|
# Run claude with Merlin agent
|
|
197
226
|
command claude --agent merlin "$@"
|
|
198
227
|
}
|
|
@@ -284,7 +313,7 @@ function cleanupLegacy() {
|
|
|
284
313
|
if (apiKey) {
|
|
285
314
|
config.mcpServers.merlin = {
|
|
286
315
|
command: 'npx',
|
|
287
|
-
args: ['merlin-mcp'],
|
|
316
|
+
args: ['merlin-mcp@latest'],
|
|
288
317
|
env: { MERLIN_API_KEY: apiKey }
|
|
289
318
|
};
|
|
290
319
|
}
|
|
@@ -295,7 +324,7 @@ function cleanupLegacy() {
|
|
|
295
324
|
if (config.mcpServers?.merlin) {
|
|
296
325
|
const args = config.mcpServers.merlin.args;
|
|
297
326
|
if (args && (args[0] === 'create-merlin-brain' || args[0] === 'ccwiki-mcp')) {
|
|
298
|
-
config.mcpServers.merlin.args = ['merlin-mcp'];
|
|
327
|
+
config.mcpServers.merlin.args = ['merlin-mcp@latest'];
|
|
299
328
|
modified = true;
|
|
300
329
|
}
|
|
301
330
|
if (config.mcpServers.merlin.env?.CCWIKI_API_KEY) {
|
|
@@ -327,7 +356,7 @@ function cleanupLegacy() {
|
|
|
327
356
|
if (apiKey) {
|
|
328
357
|
config.mcpServers.merlin = {
|
|
329
358
|
command: 'npx',
|
|
330
|
-
args: ['merlin-mcp'],
|
|
359
|
+
args: ['merlin-mcp@latest'],
|
|
331
360
|
env: { MERLIN_API_KEY: apiKey }
|
|
332
361
|
};
|
|
333
362
|
}
|
|
@@ -337,7 +366,7 @@ function cleanupLegacy() {
|
|
|
337
366
|
if (config.mcpServers?.merlin) {
|
|
338
367
|
const args = config.mcpServers.merlin.args;
|
|
339
368
|
if (args && (args[0] === 'create-merlin-brain' || args[0] === 'ccwiki-mcp')) {
|
|
340
|
-
config.mcpServers.merlin.args = ['merlin-mcp'];
|
|
369
|
+
config.mcpServers.merlin.args = ['merlin-mcp@latest'];
|
|
341
370
|
modified = true;
|
|
342
371
|
}
|
|
343
372
|
if (config.mcpServers.merlin.env?.CCWIKI_API_KEY) {
|
|
@@ -546,14 +575,10 @@ async function install() {
|
|
|
546
575
|
const claudeMdDest = path.join(CLAUDE_DIR, 'CLAUDE.md');
|
|
547
576
|
|
|
548
577
|
if (fs.existsSync(claudeMdSrc)) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
const backup = claudeMdDest + '.backup';
|
|
552
|
-
fs.copyFileSync(claudeMdDest, backup);
|
|
553
|
-
logWarn(`Backed up existing CLAUDE.md to CLAUDE.md.backup`);
|
|
554
|
-
}
|
|
578
|
+
// Always replace CLAUDE.md - it's managed by Merlin
|
|
579
|
+
// Old versions are cleaned up by cleanupLegacy()
|
|
555
580
|
fs.copyFileSync(claudeMdSrc, claudeMdDest);
|
|
556
|
-
logSuccess('Installed CLAUDE.md');
|
|
581
|
+
logSuccess('Installed CLAUDE.md (Merlin instructions)');
|
|
557
582
|
}
|
|
558
583
|
|
|
559
584
|
// Step 6: Install Merlin Loop (autonomous orchestration)
|
|
@@ -604,7 +629,7 @@ async function install() {
|
|
|
604
629
|
config.mcpServers = config.mcpServers || {};
|
|
605
630
|
config.mcpServers.merlin = {
|
|
606
631
|
command: 'npx',
|
|
607
|
-
args: ['merlin-mcp'],
|
|
632
|
+
args: ['merlin-mcp@latest'],
|
|
608
633
|
env: {
|
|
609
634
|
MERLIN_API_KEY: apiKey
|
|
610
635
|
}
|
package/bin/merlin-cli.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
const https = require('https');
|
|
18
18
|
const { execSync } = require('child_process');
|
|
19
19
|
|
|
20
|
-
const API_URL = process.env.MERLIN_API_URL || 'https://
|
|
20
|
+
const API_URL = process.env.MERLIN_API_URL || 'https://auth.merlin.build';
|
|
21
21
|
const API_KEY = process.env.MERLIN_API_KEY || '';
|
|
22
22
|
|
|
23
23
|
// ============================================================
|
|
@@ -243,21 +243,53 @@ async function connect() {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
+
async function status() {
|
|
247
|
+
const repoUrl = detectGitRepo();
|
|
248
|
+
if (!repoUrl) {
|
|
249
|
+
// Not in a git repo - output for shell parsing
|
|
250
|
+
console.log('NO_GIT_REPO');
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const repoId = await findRepoId(repoUrl);
|
|
255
|
+
if (!repoId) {
|
|
256
|
+
// Repo not connected
|
|
257
|
+
console.log('NOT_CONNECTED');
|
|
258
|
+
console.log(repoUrl);
|
|
259
|
+
process.exit(0);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Connected - get repo name
|
|
263
|
+
try {
|
|
264
|
+
const overview = await apiRequest(`/api/agent/${repoId}/overview`);
|
|
265
|
+
const nameMatch = overview.match(/Name:\s*(.+)/);
|
|
266
|
+
const repoName = nameMatch ? nameMatch[1].trim() : repoUrl.split('/').pop();
|
|
267
|
+
console.log('CONNECTED');
|
|
268
|
+
console.log(repoName);
|
|
269
|
+
console.log(repoId);
|
|
270
|
+
} catch {
|
|
271
|
+
console.log('CONNECTED');
|
|
272
|
+
console.log(repoUrl.split('/').pop());
|
|
273
|
+
console.log(repoId);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
246
277
|
function showHelp() {
|
|
247
278
|
console.log(`
|
|
248
279
|
Merlin CLI - Universal codebase intelligence for ALL AI agents
|
|
249
280
|
|
|
250
281
|
Usage:
|
|
282
|
+
merlin status Check if current repo is connected to Sights
|
|
283
|
+
merlin connect Connect repo to Merlin Sights
|
|
251
284
|
merlin context <task> Get context for a task
|
|
252
285
|
merlin search <query> Search the codebase
|
|
253
286
|
merlin brief Get project overview
|
|
254
287
|
merlin rules Get coding rules
|
|
255
288
|
merlin files <purpose> Find files by purpose
|
|
256
|
-
merlin connect Connect repo to Merlin Sights
|
|
257
289
|
|
|
258
290
|
Environment:
|
|
259
291
|
MERLIN_API_KEY Your merlin.build API key
|
|
260
|
-
MERLIN_API_URL API URL (default: https://
|
|
292
|
+
MERLIN_API_URL API URL (default: https://auth.merlin.build)
|
|
261
293
|
|
|
262
294
|
Works with: Claude, Cursor, Windsurf, Copilot, Aider, and any AI agent!
|
|
263
295
|
`);
|
|
@@ -290,6 +322,9 @@ async function main() {
|
|
|
290
322
|
case 'connect':
|
|
291
323
|
await connect();
|
|
292
324
|
break;
|
|
325
|
+
case 'status':
|
|
326
|
+
await status();
|
|
327
|
+
break;
|
|
293
328
|
case 'help':
|
|
294
329
|
case '--help':
|
|
295
330
|
case '-h':
|
package/files/CLAUDE.md
CHANGED
|
@@ -1,33 +1,40 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ⚡⚡⚡ STOP — READ THIS FIRST ⚡⚡⚡
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## YOUR VERY FIRST ACTION (BEFORE ANYTHING ELSE)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
**DO NOT read the user's message yet. DO NOT start working. FIRST:**
|
|
6
|
+
|
|
7
|
+
1. **Call this tool NOW:** `merlin_get_selected_repo`
|
|
8
8
|
|
|
9
|
-
Then
|
|
9
|
+
2. **Then show ONE of these responses:**
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**If repo IS connected:**
|
|
12
12
|
```
|
|
13
|
-
🔮 Merlin
|
|
13
|
+
🔮 Merlin Sights: CONNECTED ✓
|
|
14
|
+
Repository: {repo_name}
|
|
15
|
+
|
|
14
16
|
What would you like to work on?
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
**If repo is NOT connected:**
|
|
18
20
|
```
|
|
19
|
-
🔮
|
|
21
|
+
🔮 Merlin Sights: NOT CONNECTED
|
|
22
|
+
|
|
23
|
+
This repository isn't in Sights yet.
|
|
20
24
|
|
|
21
|
-
[1] Connect now (
|
|
25
|
+
[1] Connect now (2-5 min analysis)
|
|
22
26
|
[2] Skip - work without Sights
|
|
23
27
|
|
|
24
28
|
Which would you like?
|
|
25
29
|
```
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
If user picks [2]: Proceed without Sights, use traditional file exploration.
|
|
31
|
+
3. **WAIT for user response if not connected**
|
|
29
32
|
|
|
30
|
-
**ONLY
|
|
33
|
+
4. **ONLY THEN proceed with their actual request**
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
**WHY THIS MATTERS:** The user needs visual confirmation that Sights is working. Always show the 🔮 status box at session start. Never skip this step.
|
|
31
38
|
|
|
32
39
|
---
|
|
33
40
|
|
|
@@ -185,47 +192,54 @@ Merlin Sights is Claude's memory. Use it **throughout every session**, not just
|
|
|
185
192
|
|
|
186
193
|
---
|
|
187
194
|
|
|
188
|
-
##
|
|
195
|
+
## 🔮 VISUAL CUES — Show When Merlin Is Used
|
|
189
196
|
|
|
190
|
-
**ALWAYS
|
|
197
|
+
**ALWAYS show a visual indicator when you query Merlin Sights.**
|
|
191
198
|
|
|
192
|
-
|
|
199
|
+
After EVERY Merlin tool call, display a cue box showing what you found and whether it helped:
|
|
193
200
|
|
|
201
|
+
**Format:**
|
|
194
202
|
```
|
|
195
|
-
🔮
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
203
|
+
🔮 SIGHTS › [tool_name]
|
|
204
|
+
[what you searched for]
|
|
205
|
+
|
|
206
|
+
[result indicator] [brief summary of what was found]
|
|
199
207
|
```
|
|
200
208
|
|
|
201
|
-
**
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
- `merlin_get_brief` provides project overview
|
|
206
|
-
- `merlin_search` finds relevant information
|
|
209
|
+
**Result indicators:**
|
|
210
|
+
- ✅ **Helped** — Found useful files, patterns, or context
|
|
211
|
+
- ⚠️ **Partial** — Found something but not exactly what was needed
|
|
212
|
+
- ❌ **No match** — Nothing relevant found, using other methods
|
|
207
213
|
|
|
208
|
-
**
|
|
214
|
+
**Examples:**
|
|
209
215
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
216
|
+
```
|
|
217
|
+
🔮 SIGHTS › get_context("payment processing")
|
|
218
|
+
✅ Found PaymentService.ts, StripeClient.ts
|
|
219
|
+
Pattern: Async handlers with retry logic
|
|
220
|
+
```
|
|
215
221
|
|
|
216
|
-
|
|
222
|
+
```
|
|
223
|
+
🔮 SIGHTS › find_files("email templates")
|
|
224
|
+
⚠️ Partial — Found EmailService but no templates folder
|
|
225
|
+
Will check manually with Glob
|
|
226
|
+
```
|
|
217
227
|
|
|
218
228
|
```
|
|
219
|
-
🔮
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
└─ ✓ test_required: true
|
|
229
|
+
🔮 SIGHTS › search("GraphQL resolvers")
|
|
230
|
+
❌ No match — This codebase uses REST, not GraphQL
|
|
231
|
+
```
|
|
223
232
|
|
|
224
|
-
|
|
225
|
-
|
|
233
|
+
**Quick format for rapid queries:**
|
|
234
|
+
```
|
|
235
|
+
🔮 get_context → ✅ Found 3 auth files
|
|
236
|
+
🔮 find_files → ⚠️ Partial match
|
|
237
|
+
🔮 conventions → ✅ max 400 lines, always test
|
|
226
238
|
```
|
|
227
239
|
|
|
228
|
-
|
|
240
|
+
**Why this matters:** The user wants to see Merlin working. Every query should be visible so they know when Sights is providing value (or when it's not and you're falling back to file exploration).
|
|
241
|
+
|
|
242
|
+
---
|
|
229
243
|
|
|
230
244
|
**Merlin Sights Tools:**
|
|
231
245
|
- `merlin_get_context` - Task context ("add auth", "fix bug in X")
|
package/files/loop/config.json
CHANGED
|
@@ -125,7 +125,7 @@ get_cloud_context() {
|
|
|
125
125
|
project=$(basename "$PWD")
|
|
126
126
|
|
|
127
127
|
local cloud_context
|
|
128
|
-
cloud_context=$(curl -sf "https://
|
|
128
|
+
cloud_context=$(curl -sf "https://auth.merlin.build/v1/context/relevant?project=$project&mode=$mode" \
|
|
129
129
|
-H "Authorization: Bearer $api_key" 2>/dev/null || echo "")
|
|
130
130
|
|
|
131
131
|
if [ -n "$cloud_context" ] && [ "$cloud_context" != "{}" ]; then
|
package/files/loop/lib/state.sh
CHANGED
|
@@ -331,7 +331,7 @@ sync_to_cloud() {
|
|
|
331
331
|
project_id=$(get_state_value "project")
|
|
332
332
|
|
|
333
333
|
# POST state to merlin.build
|
|
334
|
-
curl -sf -X POST "https://
|
|
334
|
+
curl -sf -X POST "https://auth.merlin.build/v1/loop/sync" \
|
|
335
335
|
-H "Authorization: Bearer $api_key" \
|
|
336
336
|
-H "Content-Type: application/json" \
|
|
337
337
|
-d @"$STATE_FILE" \
|
|
@@ -355,7 +355,7 @@ sync_from_cloud() {
|
|
|
355
355
|
|
|
356
356
|
# GET state from merlin.build
|
|
357
357
|
local cloud_state
|
|
358
|
-
cloud_state=$(curl -sf "https://
|
|
358
|
+
cloud_state=$(curl -sf "https://auth.merlin.build/v1/loop/state/$project_id" \
|
|
359
359
|
-H "Authorization: Bearer $api_key" 2>/dev/null || echo "")
|
|
360
360
|
|
|
361
361
|
if [ -n "$cloud_state" ] && [ "$cloud_state" != "{}" ]; then
|
|
@@ -390,7 +390,7 @@ push_memory() {
|
|
|
390
390
|
fi
|
|
391
391
|
|
|
392
392
|
# Store in cloud memory for cross-session retrieval
|
|
393
|
-
curl -sf -X POST "https://
|
|
393
|
+
curl -sf -X POST "https://auth.merlin.build/v1/memory/store" \
|
|
394
394
|
-H "Authorization: Bearer $api_key" \
|
|
395
395
|
-H "Content-Type: application/json" \
|
|
396
396
|
-d "{\"project\":\"$(basename "$PWD")\",\"key\":\"$key\",\"value\":\"$value\"}" \
|
|
@@ -407,6 +407,6 @@ pull_memory() {
|
|
|
407
407
|
return 0
|
|
408
408
|
fi
|
|
409
409
|
|
|
410
|
-
curl -sf "https://
|
|
410
|
+
curl -sf "https://auth.merlin.build/v1/memory/get?project=$(basename "$PWD")&key=$key" \
|
|
411
411
|
-H "Authorization: Bearer $api_key" 2>/dev/null || echo ""
|
|
412
412
|
}
|