create-merlin-brain 3.13.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +18 -8
- package/dist/server/server.js.map +1 -1
- package/dist/server/session-coach.d.ts +21 -16
- package/dist/server/session-coach.d.ts.map +1 -1
- package/dist/server/session-coach.js +89 -64
- package/dist/server/session-coach.js.map +1 -1
- package/dist/server/session-guardian.d.ts +28 -0
- package/dist/server/session-guardian.d.ts.map +1 -0
- package/dist/server/session-guardian.js +168 -0
- package/dist/server/session-guardian.js.map +1 -0
- package/dist/server/stats.js +7 -7
- package/dist/server/stats.js.map +1 -1
- package/dist/server/tools/context.d.ts.map +1 -1
- package/dist/server/tools/context.js +24 -0
- package/dist/server/tools/context.js.map +1 -1
- package/dist/server/tools/project.js +1 -1
- package/dist/server/tools/project.js.map +1 -1
- package/files/CLAUDE.md +66 -5
- package/files/agents/merlin.md +21 -13
- package/files/hooks/config-change.sh +2 -2
- package/files/hooks/notify-desktop.sh +2 -2
- package/files/hooks/notify-webhook.sh +1 -1
- package/files/hooks/post-edit-logger.sh +23 -1
- package/files/hooks/pre-compact.sh +52 -5
- package/files/hooks/pre-edit-sights-check.sh +56 -31
- package/files/hooks/task-completed-verify.sh +2 -2
- package/files/hooks/worktree-create.sh +1 -1
- package/files/hooks/worktree-remove.sh +1 -1
- package/package.json +1 -1
- package/files/hooks/agent-sync.sh +0 -50
- package/files/hooks/pre-edit-sights-enforce.md +0 -1
- package/files/hooks/session-start-boot.md +0 -69
- package/files/hooks/session-start-context.sh +0 -23
- package/files/hooks/stop-check.md +0 -13
- package/files/hooks/task-completed-verify.md +0 -13
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
#
|
|
3
3
|
# Merlin Hook: PreToolUse (Edit/Write)
|
|
4
|
-
#
|
|
4
|
+
# Three responsibilities:
|
|
5
5
|
# 1. Secret detection — blocks writes that contain leaked credentials.
|
|
6
6
|
# Exit code 2 with a clear message. This is the only hard block.
|
|
7
|
-
# 2.
|
|
8
|
-
#
|
|
7
|
+
# 2. Guardian check — asks the MCP server's HTTP sidecar for session-aware
|
|
8
|
+
# enforcement. Returns additionalContext nudges when context is stale.
|
|
9
|
+
# 3. File-based fallback — if guardian is unreachable, checks the timestamp
|
|
10
|
+
# file and returns additionalContext directly.
|
|
9
11
|
#
|
|
10
12
|
set -euo pipefail
|
|
11
13
|
trap 'echo "{}"; exit 0' ERR
|
|
@@ -34,66 +36,89 @@ if [ -n "$input" ] && command -v jq >/dev/null 2>&1; then
|
|
|
34
36
|
fi
|
|
35
37
|
|
|
36
38
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
37
|
-
# SECRET DETECTION
|
|
38
|
-
# Scans the content being written for common credential patterns.
|
|
39
|
-
# Uses grep with POSIX ERE for speed (<5ms on typical file sizes).
|
|
39
|
+
# 1. SECRET DETECTION (always local, always fast, always blocking)
|
|
40
40
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
41
41
|
if [ -n "$content_to_write" ]; then
|
|
42
42
|
SECRET_FOUND=""
|
|
43
43
|
SECRET_TYPE=""
|
|
44
44
|
|
|
45
|
-
# AWS access key: AKIA followed by 16 uppercase alphanumeric chars
|
|
46
45
|
if echo "$content_to_write" | grep -qE 'AKIA[0-9A-Z]{16}' 2>/dev/null; then
|
|
47
|
-
SECRET_FOUND=1
|
|
48
|
-
SECRET_TYPE="AWS access key (AKIA...)"
|
|
46
|
+
SECRET_FOUND=1; SECRET_TYPE="AWS access key (AKIA...)"
|
|
49
47
|
fi
|
|
50
|
-
|
|
51
|
-
# OpenAI / Anthropic style API key: sk- followed by 48+ alphanumeric chars
|
|
52
48
|
if [ -z "$SECRET_FOUND" ] && echo "$content_to_write" | grep -qE 'sk-[a-zA-Z0-9]{48,}' 2>/dev/null; then
|
|
53
|
-
SECRET_FOUND=1
|
|
54
|
-
SECRET_TYPE="API secret key (sk-...)"
|
|
49
|
+
SECRET_FOUND=1; SECRET_TYPE="API secret key (sk-...)"
|
|
55
50
|
fi
|
|
56
|
-
|
|
57
|
-
# PEM private key header
|
|
58
51
|
if [ -z "$SECRET_FOUND" ] && echo "$content_to_write" | \
|
|
59
52
|
grep -qE '-----BEGIN (RSA|EC|DSA|OPENSSH|PRIVATE) KEY-----' 2>/dev/null; then
|
|
60
|
-
SECRET_FOUND=1
|
|
61
|
-
SECRET_TYPE="PEM private key"
|
|
53
|
+
SECRET_FOUND=1; SECRET_TYPE="PEM private key"
|
|
62
54
|
fi
|
|
63
|
-
|
|
64
|
-
# Generic password assignment in config-like contexts
|
|
65
|
-
# Matches: password=, PASSWORD=, "password": "...", passwd=
|
|
66
|
-
# Requires the value to be non-empty and at least 8 chars to avoid false positives
|
|
67
55
|
if [ -z "$SECRET_FOUND" ] && echo "$content_to_write" | \
|
|
68
56
|
grep -qiE '(password|passwd|secret|api_key|apikey)\s*[=:]\s*["\x27]?[A-Za-z0-9@#$%^&*!_\-]{8,}' 2>/dev/null; then
|
|
69
|
-
# Exclude known placeholder patterns: <password>, ${PASSWORD}, %(password)s, REPLACE_ME, etc.
|
|
70
57
|
if ! echo "$content_to_write" | \
|
|
71
58
|
grep -qiE '(password|passwd|secret|api_key|apikey)\s*[=:]\s*["\x27]?(<[^>]+>|\$\{[^}]+\}|%\([^)]+\)s|REPLACE_ME|YOUR_|TODO|CHANGEME|example|placeholder|xxx+|test)' 2>/dev/null; then
|
|
72
|
-
SECRET_FOUND=1
|
|
73
|
-
SECRET_TYPE="credential assignment (password/secret/api_key)"
|
|
59
|
+
SECRET_FOUND=1; SECRET_TYPE="credential assignment (password/secret/api_key)"
|
|
74
60
|
fi
|
|
75
61
|
fi
|
|
76
62
|
|
|
77
63
|
if [ -n "$SECRET_FOUND" ]; then
|
|
78
64
|
if declare -f log_event >/dev/null 2>&1; then
|
|
79
|
-
log_event "secret_detected" "$(printf '{"file":"%s","type":"%s"}'
|
|
80
|
-
"${file_path:-unknown}" "$SECRET_TYPE")"
|
|
65
|
+
log_event "secret_detected" "$(printf '{"file":"%s","type":"%s"}' "${file_path:-unknown}" "$SECRET_TYPE")"
|
|
81
66
|
fi
|
|
82
|
-
echo "SECRET DETECTED: ${SECRET_TYPE}
|
|
83
|
-
# Output block decision — Claude Code reads this JSON when exit code is 2
|
|
67
|
+
echo "SECRET DETECTED: ${SECRET_TYPE} in '${file_path:-unknown}'. Remove the secret." >&2
|
|
84
68
|
echo '{"decision":"block","reason":"Secret detected in file write. Remove the secret before committing."}'
|
|
85
69
|
exit 2
|
|
86
70
|
fi
|
|
87
71
|
fi
|
|
88
72
|
|
|
89
73
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
90
|
-
#
|
|
74
|
+
# 2. GUARDIAN CHECK — ask MCP server for session-aware enforcement
|
|
75
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
76
|
+
GUARDIAN_RESPONSE=""
|
|
77
|
+
MERLIN_DIR="${HOME}/.claude/merlin"
|
|
78
|
+
PORT_FILE="${MERLIN_DIR}/.guardian-port"
|
|
79
|
+
|
|
80
|
+
if [ -f "$PORT_FILE" ] && command -v jq >/dev/null 2>&1; then
|
|
81
|
+
GUARDIAN_PORT=$(jq -r '.port // empty' "$PORT_FILE" 2>/dev/null || true)
|
|
82
|
+
GUARDIAN_PID=$(jq -r '.pid // empty' "$PORT_FILE" 2>/dev/null || true)
|
|
83
|
+
|
|
84
|
+
# Verify the guardian process is still alive
|
|
85
|
+
if [ -n "$GUARDIAN_PORT" ] && [ -n "$GUARDIAN_PID" ] && kill -0 "$GUARDIAN_PID" 2>/dev/null; then
|
|
86
|
+
# 200ms timeout — hooks must be fast
|
|
87
|
+
GUARDIAN_RESPONSE=$(curl -s --max-time 0.2 "http://127.0.0.1:${GUARDIAN_PORT}/edit-check" 2>/dev/null || true)
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
if [ -n "$GUARDIAN_RESPONSE" ] && [ "$GUARDIAN_RESPONSE" != "{}" ]; then
|
|
92
|
+
# Guardian responded with enforcement data — use it directly
|
|
93
|
+
if declare -f log_event >/dev/null 2>&1; then
|
|
94
|
+
log_event "guardian_edit_check" "$(printf '{"file":"%s","response":"ok"}' "${file_path:-unknown}")"
|
|
95
|
+
fi
|
|
96
|
+
echo "$GUARDIAN_RESPONSE"
|
|
97
|
+
exit 0
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
101
|
+
# 3. FILE-BASED FALLBACK — guardian unreachable, use timestamp file
|
|
91
102
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
92
103
|
if declare -f sights_was_checked_recently >/dev/null 2>&1; then
|
|
93
104
|
if ! sights_was_checked_recently 120; then
|
|
94
105
|
if declare -f log_event >/dev/null 2>&1; then
|
|
95
|
-
log_event "sights_skip_warning" "$(printf '{"file":"%s"}' "${file_path:-unknown}")"
|
|
106
|
+
log_event "sights_skip_warning" "$(printf '{"file":"%s","source":"fallback"}' "${file_path:-unknown}")"
|
|
107
|
+
fi
|
|
108
|
+
# Return additionalContext nudge — this is the key fix that was missing
|
|
109
|
+
if command -v jq >/dev/null 2>&1; then
|
|
110
|
+
jq -n '{
|
|
111
|
+
hookSpecificOutput: {
|
|
112
|
+
hookEventName: "PreToolUse",
|
|
113
|
+
permissionDecision: "allow",
|
|
114
|
+
additionalContext: "⟡\uD83D\uDD2E MERLIN \u203A Sights context is stale (>2 minutes since last check). Call `merlin_get_context(\"your current task\")` before continuing edits to stay in sync with the codebase."
|
|
115
|
+
}
|
|
116
|
+
}'
|
|
117
|
+
else
|
|
118
|
+
# No jq — output a simpler JSON manually
|
|
119
|
+
printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","additionalContext":"Merlin: Sights context is stale. Call merlin_get_context before continuing edits."}}\n'
|
|
96
120
|
fi
|
|
121
|
+
exit 0
|
|
97
122
|
fi
|
|
98
123
|
fi
|
|
99
124
|
|
|
@@ -102,6 +127,6 @@ if declare -f log_event >/dev/null 2>&1; then
|
|
|
102
127
|
log_event "pre_edit" "$(printf '{"file":"%s"}' "${file_path:-unknown}")"
|
|
103
128
|
fi
|
|
104
129
|
|
|
105
|
-
#
|
|
130
|
+
# All clear — allow the edit
|
|
106
131
|
echo '{}'
|
|
107
132
|
exit 0
|
|
@@ -24,7 +24,7 @@ if [ -f "package.json" ] && command -v jq >/dev/null 2>&1; then
|
|
|
24
24
|
build_exit=$?
|
|
25
25
|
if [ "$build_exit" -ne 0 ]; then
|
|
26
26
|
log_event "build_failed" "$(printf '{"exit_code":%d}' "$build_exit")"
|
|
27
|
-
echo "
|
|
27
|
+
echo "⟡🔮 MERLIN › Build check failed (exit $build_exit)" >&2
|
|
28
28
|
else
|
|
29
29
|
log_event "build_passed" '{}'
|
|
30
30
|
fi
|
|
@@ -37,7 +37,7 @@ if [ -f "tsconfig.json" ] && command -v npx >/dev/null 2>&1; then
|
|
|
37
37
|
tsc_exit=$?
|
|
38
38
|
if [ "$tsc_exit" -ne 0 ]; then
|
|
39
39
|
log_event "typecheck_failed" "$(printf '{"exit_code":%d}' "$tsc_exit")"
|
|
40
|
-
echo "
|
|
40
|
+
echo "⟡🔮 MERLIN › Type check failed (exit $tsc_exit)" >&2
|
|
41
41
|
else
|
|
42
42
|
log_event "typecheck_passed" '{}'
|
|
43
43
|
fi
|
|
@@ -55,7 +55,7 @@ if declare -f log_event >/dev/null 2>&1; then
|
|
|
55
55
|
"$WORKTREE_PATH" "$AGENT_ID" "$AGENT_TYPE")"
|
|
56
56
|
fi
|
|
57
57
|
|
|
58
|
-
echo "
|
|
58
|
+
echo "⟡🔮 MERLIN › propagated config to worktree ${WORKTREE_PATH} (agent: ${AGENT_TYPE})" >&2
|
|
59
59
|
|
|
60
60
|
echo '{}'
|
|
61
61
|
exit 0
|
|
@@ -48,7 +48,7 @@ fi
|
|
|
48
48
|
|
|
49
49
|
LIFETIME_MSG=""
|
|
50
50
|
[ -n "$LIFETIME_S" ] && LIFETIME_MSG=" (lifetime: ${LIFETIME_S}s)"
|
|
51
|
-
echo "
|
|
51
|
+
echo "⟡🔮 MERLIN › cleaned up worktree ${WORKTREE_PATH}${LIFETIME_MSG} (agent: ${AGENT_TYPE})" >&2
|
|
52
52
|
|
|
53
53
|
echo '{}'
|
|
54
54
|
exit 0
|
package/package.json
CHANGED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Merlin Hook: Agent Sync (SessionStart, background)
|
|
3
|
-
# Checks installed agents freshness and updates from cloud. Max once/hour.
|
|
4
|
-
#
|
|
5
|
-
# ASYNC: This hook should be registered as async (non-blocking)
|
|
6
|
-
# Claude Code supports async hooks — register this one as background
|
|
7
|
-
set -euo pipefail
|
|
8
|
-
trap 'echo "{}"; exit 0' ERR
|
|
9
|
-
|
|
10
|
-
AGENTS_DIR="${HOME}/.claude/agents"
|
|
11
|
-
MERLIN_DIR="${HOME}/.claude/merlin"
|
|
12
|
-
LAST_SYNC="${MERLIN_DIR}/.last-agent-sync"
|
|
13
|
-
API_URL="${MERLIN_API_URL:-https://api.merlin.build}"
|
|
14
|
-
|
|
15
|
-
[ -d "${AGENTS_DIR}" ] || { echo '{}'; exit 0; }
|
|
16
|
-
|
|
17
|
-
# Skip if synced within the last hour
|
|
18
|
-
if [ -f "${LAST_SYNC}" ]; then
|
|
19
|
-
last=$(cat "${LAST_SYNC}" 2>/dev/null || echo "0")
|
|
20
|
-
[ $(($(date +%s) - last)) -lt 3600 ] && { echo '{}'; exit 0; }
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
sync_agents() {
|
|
24
|
-
local installed=""
|
|
25
|
-
for f in "${AGENTS_DIR}"/*.md; do
|
|
26
|
-
[ -f "${f}" ] || continue
|
|
27
|
-
local name hash
|
|
28
|
-
name=$(basename "${f}" .md)
|
|
29
|
-
hash=$(md5sum "${f}" 2>/dev/null | cut -c1-8 || md5 -q "${f}" 2>/dev/null | cut -c1-8 || echo "unknown")
|
|
30
|
-
installed="${installed}${name}:${hash},"
|
|
31
|
-
done
|
|
32
|
-
local response
|
|
33
|
-
response=$(curl -s --max-time 5 "${API_URL}/api/agents-sync/check?installed=${installed}" 2>/dev/null) || return 0
|
|
34
|
-
local stale_names
|
|
35
|
-
stale_names=$(echo "${response}" | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"//' 2>/dev/null) || return 0
|
|
36
|
-
[ -z "${stale_names}" ] && { date +%s > "${LAST_SYNC}"; return 0; }
|
|
37
|
-
for agent_name in ${stale_names}; do
|
|
38
|
-
local content md_content
|
|
39
|
-
content=$(curl -s --max-time 5 "${API_URL}/api/agents-sync/${agent_name}" 2>/dev/null) || continue
|
|
40
|
-
md_content=$(echo "${content}" | python3 -c "import sys,json;print(json.load(sys.stdin).get('content',''))" 2>/dev/null) || continue
|
|
41
|
-
[ -n "${md_content}" ] && echo "${md_content}" > "${AGENTS_DIR}/${agent_name}.md"
|
|
42
|
-
done
|
|
43
|
-
date +%s > "${LAST_SYNC}"
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
sync_agents &
|
|
47
|
-
|
|
48
|
-
# Claude Code command hooks must output valid JSON to stdout
|
|
49
|
-
echo '{}'
|
|
50
|
-
exit 0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Always allow this edit. Respond with ONLY: {"ok": true}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# You Are a Merlin-Powered Session
|
|
2
|
-
|
|
3
|
-
You are not generic Claude. You are a **Merlin agent** — enhanced with codebase intelligence, specialist routing, and session continuity. Every action you take should reflect this.
|
|
4
|
-
|
|
5
|
-
## BOOT NOW (do this immediately, before reading the user's message)
|
|
6
|
-
|
|
7
|
-
1. `merlin_get_selected_repo` → Connect to Sights
|
|
8
|
-
2. `merlin_get_project_status` → Load project state
|
|
9
|
-
3. Display: `Merlin | [repo] | [X] done [Y] pending | Next: [action]`
|
|
10
|
-
4. If checkpoint exists → offer to resume
|
|
11
|
-
5. Show numbered options for what's next
|
|
12
|
-
|
|
13
|
-
## YOUR IDENTITY THIS SESSION
|
|
14
|
-
|
|
15
|
-
**You check Sights before every action.** Not sometimes. Every time. Before editing, before creating, before suggesting. You call `merlin_get_context`, `merlin_find_files`, or `merlin_search`. You show what you found: `Merlin | [what you checked] → [what you found]`
|
|
16
|
-
|
|
17
|
-
**You route to specialists.** You don't do everything yourself. Complex tasks go to fresh 200K specialist agents:
|
|
18
|
-
|
|
19
|
-
| Keywords in task | Specialist | Command |
|
|
20
|
-
|---|---|---|
|
|
21
|
-
| security, auth, login, password, encrypt, oauth, jwt | hardening-guard | `Skill("merlin:route", args='hardening-guard "..."')` |
|
|
22
|
-
| ui, component, frontend, react, css, layout, tailwind | merlin-frontend | `Skill("merlin:route", args='merlin-frontend "..."')` |
|
|
23
|
-
| api, endpoint, route, rest, graphql, webhook, middleware | merlin-api-designer | `Skill("merlin:route", args='merlin-api-designer "..."')` |
|
|
24
|
-
| database, schema, model, migration, architecture | system-architect | `Skill("merlin:route", args='system-architect "..."')` |
|
|
25
|
-
| test, spec, coverage, unit, integration, e2e, jest | tests-qa | `Skill("merlin:route", args='tests-qa "..."')` |
|
|
26
|
-
| refactor, cleanup, dry, organize, split, extract | dry-refactor | `Skill("merlin:route", args='dry-refactor "..."')` |
|
|
27
|
-
| deploy, infra, docker, env, ci, pipeline, railway | ops-railway | `Skill("merlin:route", args='ops-railway "..."')` |
|
|
28
|
-
| docs, readme, documentation, jsdoc, changelog | docs-keeper | `Skill("merlin:route", args='docs-keeper "..."')` |
|
|
29
|
-
| debug, fix, error, bug, crash, trace, investigate | merlin-debugger | `Skill("merlin:route", args='merlin-debugger "..."')` |
|
|
30
|
-
| swift, swiftui, ios, macos, xcode | apple-swift-expert | route via merlin:route |
|
|
31
|
-
| android, kotlin, compose, jetpack | android-expert | route via merlin:route |
|
|
32
|
-
| electron, tauri, desktop, native | desktop-app-expert | route via merlin:route |
|
|
33
|
-
| animation, motion, framer, gsap | animation-expert | route via merlin:route |
|
|
34
|
-
| design-system, accessibility, ux, wireframe | ui-designer | route via merlin:route |
|
|
35
|
-
| plan, roadmap, phase, milestone | Use /merlin:plan-phase or /merlin:discuss-milestone |
|
|
36
|
-
| map, analyze, understand codebase | Use /merlin:map-codebase |
|
|
37
|
-
|
|
38
|
-
**You suggest workflows.** When a user's task matches a workflow pattern, suggest it proactively:
|
|
39
|
-
|
|
40
|
-
| User says | Suggest workflow |
|
|
41
|
-
|---|---|
|
|
42
|
-
| "build [feature]", "add [feature]" | `feature-dev` |
|
|
43
|
-
| "build the whole thing", "full product" | `product-dev` |
|
|
44
|
-
| "fix [bug]", "broken", "not working" | `bug-fix` |
|
|
45
|
-
| "security", "audit", "vulnerabilities" | `security-audit` |
|
|
46
|
-
| "refactor", "cleanup", "tech debt" | `refactor` |
|
|
47
|
-
| "build UI", "frontend", "components" | `ui-build` |
|
|
48
|
-
| "build API", "endpoints", "REST" | `api-build` |
|
|
49
|
-
| "idea", "from scratch", "spec first" | `spec-to-code` |
|
|
50
|
-
| Complex multi-step or unusual task | `/merlin:workflow create "..."` |
|
|
51
|
-
|
|
52
|
-
Show as: `[1] Run **workflow-name** workflow (automated N-step pipeline)` — users don't need to know commands.
|
|
53
|
-
|
|
54
|
-
**You maintain continuity.** You save checkpoints (`merlin_save_checkpoint`) so the next session picks up where this one left off. You commit work incrementally. You never let work disappear.
|
|
55
|
-
|
|
56
|
-
**You verify before committing.** Call `merlin_run_verification` before every git commit. Build, types, lint must pass.
|
|
57
|
-
|
|
58
|
-
**You show options.** At every decision point, show numbered choices. The user should never wonder "what can Merlin do here?"
|
|
59
|
-
|
|
60
|
-
**You announce yourself.** Prefix Sights results with `Merlin |`. When routing to a specialist, say `Merlin | Routing to [agent]...`. When checking context, say `Merlin | Checking [area]...`. The user should SEE Merlin working throughout the session, not just at the start.
|
|
61
|
-
|
|
62
|
-
## REFRESH CYCLE
|
|
63
|
-
|
|
64
|
-
Every few minutes during active work:
|
|
65
|
-
- Call `merlin_get_context` for the area you're working on
|
|
66
|
-
- Check if patterns or files have changed
|
|
67
|
-
- Adjust your approach based on fresh context
|
|
68
|
-
|
|
69
|
-
This is what makes you different from raw Claude. You are always informed. Always connected. Always routing to the best specialist. Always maintaining continuity.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# Merlin Hook: SessionStart (context injection)
|
|
4
|
-
# Injects Merlin identity context into the session via additionalContext.
|
|
5
|
-
# Uses the SessionStart command hook JSON output format.
|
|
6
|
-
# Always exits 0 — never blocks Claude Code startup.
|
|
7
|
-
#
|
|
8
|
-
set -euo pipefail
|
|
9
|
-
trap 'echo "{}"; exit 0' ERR
|
|
10
|
-
|
|
11
|
-
# Output additionalContext JSON for Claude to see at session start.
|
|
12
|
-
# This reminds Claude it's a Merlin-powered session.
|
|
13
|
-
# Full boot instructions are in CLAUDE.md — this is a lightweight nudge.
|
|
14
|
-
cat <<'CONTEXT_JSON'
|
|
15
|
-
{
|
|
16
|
-
"hookSpecificOutput": {
|
|
17
|
-
"hookEventName": "SessionStart",
|
|
18
|
-
"additionalContext": "You are a Merlin-powered session. Before working: (1) call merlin_get_selected_repo to connect Sights, (2) call merlin_get_project_status to load state, (3) show numbered options. Check Sights before every edit. Route complex tasks to specialists via /merlin:route. Save checkpoints before stopping."
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
CONTEXT_JSON
|
|
22
|
-
|
|
23
|
-
exit 0
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
You are evaluating whether Claude should stop working. Analyze the conversation context: $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
Check these criteria:
|
|
4
|
-
1. Did the user's most recent request get fully addressed?
|
|
5
|
-
2. Are there any obvious errors or broken code that should be fixed before stopping?
|
|
6
|
-
3. Did Claude mention follow-up tasks it intended to complete but hasn't done yet?
|
|
7
|
-
|
|
8
|
-
IMPORTANT: This is NOT about saving checkpoints or showing summaries — those are handled elsewhere.
|
|
9
|
-
Only evaluate whether the core work is done.
|
|
10
|
-
|
|
11
|
-
Respond with ONLY valid JSON, no other text:
|
|
12
|
-
- If stopping is appropriate: {"ok": true}
|
|
13
|
-
- If Claude should continue: {"ok": false, "reason": "brief explanation of what's unfinished"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
You are evaluating whether a task should be marked as completed. Context: $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
Check these criteria:
|
|
4
|
-
1. Was the task's stated objective accomplished based on the conversation?
|
|
5
|
-
2. Were there any errors or test failures mentioned that haven't been resolved?
|
|
6
|
-
3. Is the implementation reasonably complete (not a half-finished skeleton)?
|
|
7
|
-
|
|
8
|
-
Be lenient — don't block completion for minor issues like missing docs or style nits.
|
|
9
|
-
Only block if the core objective clearly wasn't met or there are unresolved errors.
|
|
10
|
-
|
|
11
|
-
Respond with ONLY valid JSON, no other text:
|
|
12
|
-
- Task is complete: {"ok": true}
|
|
13
|
-
- Task is not complete: {"ok": false, "reason": "brief explanation of what's unfinished"}
|