create-merlin-brain 5.0.2 → 5.3.2
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/README.md +25 -4
- package/bin/install.cjs +95 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +75 -0
- package/dist/server/server.js.map +1 -1
- package/dist/server/tools/context.d.ts.map +1 -1
- package/dist/server/tools/context.js +60 -0
- package/dist/server/tools/context.js.map +1 -1
- package/dist/server/tools/project-picture.d.ts +17 -0
- package/dist/server/tools/project-picture.d.ts.map +1 -0
- package/dist/server/tools/project-picture.js +204 -0
- package/dist/server/tools/project-picture.js.map +1 -0
- package/dist/server/tools/types.d.ts +24 -0
- package/dist/server/tools/types.d.ts.map +1 -1
- package/files/agents/challenger-academic.md +8 -0
- package/files/agents/challenger-arbiter.md +8 -0
- package/files/agents/challenger-insider.md +8 -0
- package/files/agents/code-organization-supervisor.md +8 -0
- package/files/agents/codex-planner.md +36 -9
- package/files/agents/context-guardian.md +8 -0
- package/files/agents/docs-keeper.md +8 -0
- package/files/agents/dry-refactor.md +8 -0
- package/files/agents/elite-code-refactorer.md +8 -0
- package/files/agents/hardening-guard.md +8 -0
- package/files/agents/implementation-dev.md +8 -0
- package/files/agents/merlin-access-control-reviewer.md +8 -0
- package/files/agents/merlin-api-designer.md +8 -0
- package/files/agents/merlin-codebase-mapper.md +8 -0
- package/files/agents/merlin-debugger.md +8 -0
- package/files/agents/merlin-dependency-auditor.md +8 -0
- package/files/agents/merlin-edge-case-hunter.md +8 -0
- package/files/agents/merlin-executor.md +8 -0
- package/files/agents/merlin-frontend.md +8 -0
- package/files/agents/merlin-input-validator.md +8 -0
- package/files/agents/merlin-integration-checker.md +8 -0
- package/files/agents/merlin-migrator.md +8 -0
- package/files/agents/merlin-milestone-auditor.md +8 -0
- package/files/agents/merlin-party-review.md +8 -0
- package/files/agents/merlin-performance.md +8 -0
- package/files/agents/merlin-planner.md +9 -1
- package/files/agents/merlin-researcher.md +8 -0
- package/files/agents/merlin-reviewer.md +8 -0
- package/files/agents/merlin-sast-reviewer.md +8 -0
- package/files/agents/merlin-secret-scanner.md +8 -0
- package/files/agents/merlin-security.md +8 -0
- package/files/agents/merlin-verifier.md +8 -0
- package/files/agents/merlin-work-verifier.md +8 -0
- package/files/agents/merlin.md +8 -0
- package/files/agents/ops-railway.md +8 -0
- package/files/agents/orchestrator-retrofit.md +8 -0
- package/files/agents/product-spec.md +8 -0
- package/files/agents/remotion.md +8 -0
- package/files/agents/system-architect.md +8 -0
- package/files/agents/tests-qa.md +8 -0
- package/files/commands/merlin/course-correct.md +8 -0
- package/files/commands/merlin/design-audit.md +92 -0
- package/files/commands/merlin/health.md +8 -0
- package/files/commands/merlin/next.md +8 -0
- package/files/commands/merlin/optimize.md +89 -0
- package/files/commands/merlin/polish.md +99 -0
- package/files/commands/merlin/quick.md +8 -0
- package/files/commands/merlin/readiness-gate.md +8 -0
- package/files/commands/merlin/redesign.md +108 -0
- package/files/loop/README.md +11 -0
- package/files/merlin/skills/SKILLS-INDEX.md +16 -1
- package/files/merlin/skills/TASK-OPTIMIZER.json +310 -0
- package/files/merlin/skills/coding/focus-mode.md +8 -0
- package/files/merlin/skills/design/emil-design-eng.md +31 -0
- package/files/merlin/skills/design/impeccable.md +36 -0
- package/files/merlin/skills/duo/offer.md +20 -7
- package/files/merlin/skills/duo/on.md +26 -17
- package/files/merlin/skills/duo/status.md +10 -3
- package/files/merlin/templates/DEBUG.md +11 -0
- package/files/merlin/templates/UAT.md +11 -0
- package/files/merlin/templates/phase-prompt.md +11 -0
- package/files/merlin/templates/project.md +11 -0
- package/files/merlin/templates/requirements.md +11 -0
- package/files/merlin/templates/roadmap.md +11 -0
- package/files/merlin/templates/state.md +11 -0
- package/files/merlin/templates/verification-report.md +11 -0
- package/files/merlin/workflows/execute-phase.md +11 -0
- package/files/merlin/workflows/plan-phase.md +11 -0
- package/files/merlin/workflows/progress.md +11 -0
- package/files/merlin/workflows/resume-project.md +11 -0
- package/files/merlin/workflows/verify-phase.md +11 -0
- package/files/merlin/workflows/verify-work.md +11 -0
- package/files/merlin-system-prompt.txt +35 -1
- package/files/rules/codex-routing.md +19 -0
- package/files/rules/duo-routing.md +109 -10
- package/files/rules/merlin-routing.md +40 -0
- package/files/scripts/codex-as.sh +5 -2
- package/files/scripts/design-intent-detect.sh +8 -0
- package/files/scripts/duo-badge.sh +3 -5
- package/files/scripts/duo-installed.sh +3 -3
- package/files/scripts/duo-mode-read.sh +30 -10
- package/files/scripts/duo-mode-write.sh +28 -3
- package/files/scripts/duo-pre-route.sh +2 -8
- package/files/scripts/install-design-skills.sh +86 -0
- package/files/scripts/merlin-codex.sh +9 -4
- package/files/scripts/task-optimize.sh +335 -0
- package/package.json +1 -1
|
@@ -15,6 +15,46 @@ Route user intent to the matching workflow. Do not analyze or fix problems yours
|
|
|
15
15
|
| "build API" / "backend" / "endpoint" | `Skill("merlin:workflow", args='run api-build "<task>"')` |
|
|
16
16
|
| Small, isolated task | `merlin_smart_route(task="...")` then `merlin_route()` |
|
|
17
17
|
|
|
18
|
+
## Universal Task Optimization (RUN FIRST on every routing decision)
|
|
19
|
+
|
|
20
|
+
BEFORE every routing decision (workflow, agent, or specialist), run:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
bash ~/.claude/scripts/task-optimize.sh --task "<full user task text>"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The optimizer returns single-line JSON: `{"score":<0-100>,"intent":"<id>","skills":[<ids>],"agent":"<name>","matched_phrases":[...]}`.
|
|
27
|
+
|
|
28
|
+
If `score >= 25`:
|
|
29
|
+
1. Read the matched skill files (`~/.claude/merlin/skills/<id>.md` or `~/.claude/skills/<external>/SKILL.md` for external skills).
|
|
30
|
+
2. Announce the pairing: `⟡🔮 MERLIN › Intent: <intent>. Loading <skills> + routing to <agent>.` (use the duo badge variant if duo mode is on)
|
|
31
|
+
3. Route to the optimizer-recommended `agent` with skill bodies prepended into context.
|
|
32
|
+
|
|
33
|
+
If `score < 25`: fall through to the existing routing tables below.
|
|
34
|
+
|
|
35
|
+
The registry of skill→agent pairings lives at `~/.claude/merlin/skills/TASK-OPTIMIZER.json`. To add a new skill, append an entry there — no code changes needed.
|
|
36
|
+
|
|
37
|
+
### Common skill+agent pairings (reference; full registry in TASK-OPTIMIZER.json)
|
|
38
|
+
|
|
39
|
+
| Task signal | Skills | Agent |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| Design / UI / typography / color / responsive | design/impeccable, design/emil-design-eng | ui-builder |
|
|
42
|
+
| Animation / polish / micro-interactions | design/emil-design-eng | animation-expert |
|
|
43
|
+
| Accessibility / WCAG / a11y | coding/accessibility | hardening-guard |
|
|
44
|
+
| Auth / OWASP / CSRF / hardening | coding/security-hardening | hardening-guard |
|
|
45
|
+
| API / REST / OpenAPI / GraphQL | coding/api-design | merlin-api-designer |
|
|
46
|
+
| Performance / Core Web Vitals / bundle | coding/performance | merlin-performance |
|
|
47
|
+
| Tests / TDD / Jest / Vitest | testing/tdd-workflow | tests-qa |
|
|
48
|
+
| Docker / containers / CI | devops/docker-containers | ops-railway |
|
|
49
|
+
| Bug / crash / error / debug | coding/debug-mode | merlin-debugger |
|
|
50
|
+
| Stripe / billing / webhooks / email | automation/*, communication/* | implementation-dev |
|
|
51
|
+
| Brainstorm / ideate / options | research/brainstorm | merlin-researcher |
|
|
52
|
+
| React / hooks / Next.js / components | coding/react-patterns | merlin-frontend |
|
|
53
|
+
|
|
54
|
+
Slash commands: `/merlin:optimize`, `/merlin:design-audit`, `/merlin:polish`, `/merlin:redesign`.
|
|
55
|
+
|
|
56
|
+
The optimizer is the AUTHORITY. Don't override its recommendations unless the user explicitly asks for a different agent.
|
|
57
|
+
|
|
18
58
|
## Agent Routing
|
|
19
59
|
|
|
20
60
|
Call `merlin_smart_route(task="...")` FIRST (searches 500+ community agents). Then:
|
|
@@ -69,6 +69,9 @@ FULL_PROMPT="${PROMPT_BODY}
|
|
|
69
69
|
|
|
70
70
|
${TASK_TEXT}"
|
|
71
71
|
|
|
72
|
-
# Invoke codex with
|
|
72
|
+
# Invoke codex with workspace-write sandbox to allow file modifications inside cwd.
|
|
73
|
+
# (The legacy --write flag was removed from `codex exec`; -s workspace-write is the
|
|
74
|
+
# current equivalent. Use --dangerously-bypass-approvals-and-sandbox only if you
|
|
75
|
+
# explicitly want to skip all prompts — workspace-write is the safer default.)
|
|
73
76
|
# shellcheck disable=SC2086
|
|
74
|
-
exec codex exec
|
|
77
|
+
exec codex exec -s workspace-write --cd "$PWD" $MODEL_FLAG "$FULL_PROMPT"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# design-intent-detect.sh — thin wrapper around task-optimize.sh (v5.3+)
|
|
3
|
+
# Preserves the v5.2.0 contract for slash commands that reference this script.
|
|
4
|
+
# Usage: design-intent-detect.sh --task "<text>" [--self-test]
|
|
5
|
+
# Output: same JSON as task-optimize.sh
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
exec "$SCRIPT_DIR/task-optimize.sh" "$@"
|
|
@@ -8,12 +8,10 @@ set -euo pipefail
|
|
|
8
8
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
9
|
STEP_PHRASE="${1:-}"
|
|
10
10
|
|
|
11
|
-
# Determine if duo is active:
|
|
11
|
+
# Determine if duo is active: mode is enabled (duo-installed.sh is always-pass, no longer checked)
|
|
12
12
|
DUO_ACTIVE=false
|
|
13
|
-
if "${SCRIPT_DIR}/duo-
|
|
14
|
-
|
|
15
|
-
DUO_ACTIVE=true
|
|
16
|
-
fi
|
|
13
|
+
if [[ "$("${SCRIPT_DIR}/duo-mode-read.sh" 2>/dev/null)" == "enabled" ]]; then
|
|
14
|
+
DUO_ACTIVE=true
|
|
17
15
|
fi
|
|
18
16
|
|
|
19
17
|
# Build badge
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# duo-installed.sh — composite install gate for duo mode
|
|
3
|
-
#
|
|
3
|
+
# Always exits 0: duo is available regardless of Codex. Pair selection (claude+codex vs claude+claude)
|
|
4
|
+
# is determined separately via codex-installed.sh at toggle time.
|
|
4
5
|
|
|
5
6
|
set -euo pipefail
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
"${SCRIPT_DIR}/codex-installed.sh"
|
|
8
|
+
exit 0
|
|
@@ -1,51 +1,71 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# duo-mode-read.sh — reads duo-mode.json, applies 24h auto-expire (read-time only, never modifies file)
|
|
3
|
-
#
|
|
3
|
+
# Without --pair: prints exactly "enabled" or "disabled" to stdout
|
|
4
|
+
# With --pair: prints the pair value: "claude+codex", "claude+claude", or "none"
|
|
4
5
|
|
|
5
6
|
set -euo pipefail
|
|
6
7
|
|
|
7
8
|
STATE_FILE="${HOME}/.claude/merlin-state/duo-mode.json"
|
|
9
|
+
PAIR_MODE=false
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
for arg in "$@"; do
|
|
12
|
+
if [[ "$arg" == "--pair" ]]; then
|
|
13
|
+
PAIR_MODE=true
|
|
14
|
+
fi
|
|
15
|
+
done
|
|
16
|
+
|
|
17
|
+
# If state file missing, default to disabled / none
|
|
10
18
|
if [[ ! -f "$STATE_FILE" ]]; then
|
|
11
|
-
|
|
19
|
+
if [[ "$PAIR_MODE" == "true" ]]; then
|
|
20
|
+
echo "none"
|
|
21
|
+
else
|
|
22
|
+
echo "disabled"
|
|
23
|
+
fi
|
|
12
24
|
exit 0
|
|
13
25
|
fi
|
|
14
26
|
|
|
15
|
-
python3 - "$STATE_FILE" <<'PYEOF'
|
|
27
|
+
python3 - "$STATE_FILE" "$PAIR_MODE" <<'PYEOF'
|
|
16
28
|
import sys
|
|
17
29
|
import json
|
|
18
30
|
from datetime import datetime, timezone, timedelta
|
|
19
31
|
|
|
20
32
|
state_path = sys.argv[1]
|
|
33
|
+
pair_mode = sys.argv[2] == "true"
|
|
21
34
|
|
|
22
35
|
try:
|
|
23
36
|
with open(state_path, "r") as f:
|
|
24
37
|
data = json.load(f)
|
|
25
38
|
except (json.JSONDecodeError, OSError):
|
|
26
|
-
print("disabled")
|
|
39
|
+
print("none" if pair_mode else "disabled")
|
|
27
40
|
sys.exit(0)
|
|
28
41
|
|
|
29
42
|
enabled = data.get("enabled", False)
|
|
30
43
|
since_iso = data.get("sinceISO")
|
|
44
|
+
pair = data.get("pair")
|
|
31
45
|
|
|
32
46
|
if not enabled or since_iso is None:
|
|
33
|
-
print("disabled")
|
|
47
|
+
print("none" if pair_mode else "disabled")
|
|
34
48
|
sys.exit(0)
|
|
35
49
|
|
|
36
50
|
# Parse sinceISO and apply 24h auto-expire (read-time interpretation, no file write)
|
|
37
51
|
try:
|
|
38
|
-
# Handle both Z suffix and +00:00 format
|
|
39
52
|
since_str = since_iso.replace("Z", "+00:00")
|
|
40
53
|
since_dt = datetime.fromisoformat(since_str)
|
|
41
54
|
now_dt = datetime.now(timezone.utc)
|
|
42
55
|
if (now_dt - since_dt) > timedelta(hours=24):
|
|
43
|
-
print("disabled")
|
|
56
|
+
print("none" if pair_mode else "disabled")
|
|
44
57
|
sys.exit(0)
|
|
45
58
|
except (ValueError, TypeError):
|
|
46
59
|
# Unparseable timestamp — treat as expired
|
|
47
|
-
print("disabled")
|
|
60
|
+
print("none" if pair_mode else "disabled")
|
|
48
61
|
sys.exit(0)
|
|
49
62
|
|
|
50
|
-
|
|
63
|
+
if pair_mode:
|
|
64
|
+
# Legacy state (no pair field) when enabled defaults to claude+codex
|
|
65
|
+
if pair is None:
|
|
66
|
+
print("claude+codex")
|
|
67
|
+
else:
|
|
68
|
+
print(pair)
|
|
69
|
+
else:
|
|
70
|
+
print("enabled")
|
|
51
71
|
PYEOF
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# duo-mode-write.sh — atomic write to duo-mode.json
|
|
3
|
-
# Usage: duo-mode-write.sh on "<reason>" |
|
|
3
|
+
# Usage: duo-mode-write.sh on "<reason>" [claude+codex|claude+claude]
|
|
4
|
+
# duo-mode-write.sh off "<reason>"
|
|
4
5
|
|
|
5
6
|
set -euo pipefail
|
|
6
7
|
|
|
7
8
|
if [[ $# -lt 2 ]]; then
|
|
8
|
-
echo "Usage: duo-mode-write.sh on|off \"<reason>\"" >&2
|
|
9
|
+
echo "Usage: duo-mode-write.sh on|off \"<reason>\" [claude+codex|claude+claude|codex+codex]" >&2
|
|
9
10
|
exit 1
|
|
10
11
|
fi
|
|
11
12
|
|
|
12
13
|
ACTION="$1"
|
|
13
14
|
REASON="$2"
|
|
15
|
+
PAIR_ARG="${3:-}"
|
|
14
16
|
STATE_FILE="${HOME}/.claude/merlin-state/duo-mode.json"
|
|
15
17
|
STATE_DIR="$(dirname "$STATE_FILE")"
|
|
18
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
19
|
|
|
17
20
|
# Ensure state directory exists
|
|
18
21
|
mkdir -p "$STATE_DIR"
|
|
@@ -20,9 +23,28 @@ mkdir -p "$STATE_DIR"
|
|
|
20
23
|
case "$ACTION" in
|
|
21
24
|
on)
|
|
22
25
|
ENABLED="true"
|
|
26
|
+
|
|
27
|
+
# Validate explicit pair arg if provided
|
|
28
|
+
if [[ -n "$PAIR_ARG" ]]; then
|
|
29
|
+
if [[ "$PAIR_ARG" != "claude+codex" && "$PAIR_ARG" != "claude+claude" && "$PAIR_ARG" != "codex+codex" ]]; then
|
|
30
|
+
echo "Error: pair must be 'claude+codex', 'claude+claude', or 'codex+codex', got: $PAIR_ARG" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
PAIR="$PAIR_ARG"
|
|
34
|
+
else
|
|
35
|
+
# Auto-detect pair: MERLIN_RUNTIME=codex → codex+codex; codex installed → claude+codex; else → claude+claude
|
|
36
|
+
if [[ "${MERLIN_RUNTIME:-}" == "codex" ]]; then
|
|
37
|
+
PAIR="codex+codex"
|
|
38
|
+
elif "${SCRIPT_DIR}/codex-installed.sh" 2>/dev/null; then
|
|
39
|
+
PAIR="claude+codex"
|
|
40
|
+
else
|
|
41
|
+
PAIR="claude+claude"
|
|
42
|
+
fi
|
|
43
|
+
fi
|
|
23
44
|
;;
|
|
24
45
|
off)
|
|
25
46
|
ENABLED="false"
|
|
47
|
+
PAIR="null"
|
|
26
48
|
;;
|
|
27
49
|
*)
|
|
28
50
|
echo "Error: first argument must be 'on' or 'off', got: $ACTION" >&2
|
|
@@ -31,7 +53,7 @@ case "$ACTION" in
|
|
|
31
53
|
esac
|
|
32
54
|
|
|
33
55
|
# Use python3 for JSON serialization and atomic write via mktemp + mv (same FS = atomic)
|
|
34
|
-
python3 - "$STATE_FILE" "$ENABLED" "$REASON" <<'PYEOF'
|
|
56
|
+
python3 - "$STATE_FILE" "$ENABLED" "$REASON" "$PAIR" <<'PYEOF'
|
|
35
57
|
import sys
|
|
36
58
|
import json
|
|
37
59
|
import os
|
|
@@ -41,13 +63,16 @@ from datetime import datetime, timezone
|
|
|
41
63
|
state_path = sys.argv[1]
|
|
42
64
|
enabled = sys.argv[2] == "true"
|
|
43
65
|
reason = sys.argv[3]
|
|
66
|
+
pair_arg = sys.argv[4]
|
|
44
67
|
|
|
45
68
|
now_iso = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") if enabled else None
|
|
69
|
+
pair_value = None if pair_arg == "null" else pair_arg
|
|
46
70
|
|
|
47
71
|
data = {
|
|
48
72
|
"enabled": enabled,
|
|
49
73
|
"sinceISO": now_iso,
|
|
50
74
|
"lastToggleReason": reason,
|
|
75
|
+
"pair": pair_value,
|
|
51
76
|
}
|
|
52
77
|
|
|
53
78
|
state_dir = os.path.dirname(state_path)
|
|
@@ -30,13 +30,7 @@ if [[ "$DUO_STATE" == "enabled" ]]; then
|
|
|
30
30
|
exit 0
|
|
31
31
|
fi
|
|
32
32
|
|
|
33
|
-
# Branch 2:
|
|
34
|
-
if ! "${SCRIPT_DIR}/duo-installed.sh" 2>/dev/null; then
|
|
35
|
-
echo "mode=solo"
|
|
36
|
-
exit 0
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
# Branch 3: risk-detect suggestion
|
|
33
|
+
# Branch 2: risk-detect suggestion (duo-installed.sh is always-pass; offer fires regardless of Codex)
|
|
40
34
|
RISK_DETECT="${SCRIPT_DIR}/duo-risk-detect.sh"
|
|
41
35
|
if [[ ! -x "$RISK_DETECT" ]]; then
|
|
42
36
|
echo "mode=solo"
|
|
@@ -62,7 +56,7 @@ if [[ "$SUGGEST_DUO" != "true" ]]; then
|
|
|
62
56
|
exit 0
|
|
63
57
|
fi
|
|
64
58
|
|
|
65
|
-
# Branch
|
|
59
|
+
# Branch 2a: suppression check — use a temp python script to avoid heredoc-in-subshell issues
|
|
66
60
|
REASONS_JSON=$(python3 -c "
|
|
67
61
|
import json, sys
|
|
68
62
|
try:
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# Merlin Design Skills Installer
|
|
5
|
+
# Installs and prioritizes emilkowalski/skill and pbakaus/impeccable
|
|
6
|
+
|
|
7
|
+
# Honor skip flag
|
|
8
|
+
if [ "${MERLIN_SKIP_DESIGN_SKILLS:-0}" = "1" ]; then
|
|
9
|
+
exit 0
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
echo "[merlin] Installing priority design skills…"
|
|
13
|
+
|
|
14
|
+
SKILLS_DIR="${HOME}/.claude/skills"
|
|
15
|
+
mkdir -p "$SKILLS_DIR"
|
|
16
|
+
|
|
17
|
+
# ═══════════════════════════════════════════════════════════════
|
|
18
|
+
# Install emilkowalski/skill (install-only, no license vendoring)
|
|
19
|
+
# ═══════════════════════════════════════════════════════════════
|
|
20
|
+
|
|
21
|
+
if [ ! -f "$SKILLS_DIR/emil-design-eng/SKILL.md" ]; then
|
|
22
|
+
if command -v npx >/dev/null 2>&1; then
|
|
23
|
+
# Attempt install via skills CLI
|
|
24
|
+
if npx --yes skills add emilkowalski/skill 2>/dev/null; then
|
|
25
|
+
: # Success
|
|
26
|
+
else
|
|
27
|
+
# Non-fatal — user can install manually
|
|
28
|
+
echo "[merlin] emil skill install hint: npx --yes skills add emilkowalski/skill"
|
|
29
|
+
fi
|
|
30
|
+
else
|
|
31
|
+
echo "[merlin] npx not found; skipping emil skill (user can install: npx --yes skills add emilkowalski/skill)"
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# ═══════════════════════════════════════════════════════════════
|
|
36
|
+
# Install pbakaus/impeccable (fetch + preserve Apache-2.0 attribution)
|
|
37
|
+
# ═══════════════════════════════════════════════════════════════
|
|
38
|
+
|
|
39
|
+
if [ ! -d "$SKILLS_DIR/impeccable" ]; then
|
|
40
|
+
if command -v git >/dev/null 2>&1; then
|
|
41
|
+
tmp=$(mktemp -d)
|
|
42
|
+
trap "rm -rf '$tmp'" EXIT
|
|
43
|
+
|
|
44
|
+
if git clone --depth 1 https://github.com/pbakaus/impeccable.git "$tmp" 2>/dev/null; then
|
|
45
|
+
# Copy the skill subtree (contains SKILL.md and commands/)
|
|
46
|
+
if [ -d "$tmp/dist/claude-code/.claude/skills/impeccable" ]; then
|
|
47
|
+
mkdir -p "$SKILLS_DIR"
|
|
48
|
+
cp -R "$tmp/dist/claude-code/.claude/skills/impeccable" "$SKILLS_DIR/"
|
|
49
|
+
|
|
50
|
+
# Preserve license attribution
|
|
51
|
+
if [ -f "$tmp/LICENSE" ]; then
|
|
52
|
+
cp "$tmp/LICENSE" "$SKILLS_DIR/impeccable/LICENSE"
|
|
53
|
+
fi
|
|
54
|
+
if [ -f "$tmp/NOTICE.md" ]; then
|
|
55
|
+
cp "$tmp/NOTICE.md" "$SKILLS_DIR/impeccable/NOTICE.md"
|
|
56
|
+
fi
|
|
57
|
+
else
|
|
58
|
+
echo "[merlin] impeccable skill structure not found in cloned repo"
|
|
59
|
+
fi
|
|
60
|
+
else
|
|
61
|
+
echo "[merlin] git clone failed for impeccable; user can install manually"
|
|
62
|
+
fi
|
|
63
|
+
else
|
|
64
|
+
echo "[merlin] git not found; skipping impeccable skill (user can install manually: git clone pbakaus/impeccable)"
|
|
65
|
+
fi
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# ═══════════════════════════════════════════════════════════════
|
|
69
|
+
# Verification
|
|
70
|
+
# ═══════════════════════════════════════════════════════════════
|
|
71
|
+
|
|
72
|
+
has_impeccable=0
|
|
73
|
+
has_emil=0
|
|
74
|
+
|
|
75
|
+
[ -d "$SKILLS_DIR/impeccable" ] && has_impeccable=1
|
|
76
|
+
[ -f "$SKILLS_DIR/emil-design-eng/SKILL.md" ] && has_emil=1
|
|
77
|
+
|
|
78
|
+
if [ "$has_impeccable" = "1" ] || [ "$has_emil" = "1" ]; then
|
|
79
|
+
echo "[merlin] Design skills ready:"
|
|
80
|
+
[ "$has_impeccable" = "1" ] && echo " ✓ impeccable"
|
|
81
|
+
[ "$has_emil" = "1" ] && echo " ✓ emil-design-eng"
|
|
82
|
+
else
|
|
83
|
+
echo "[merlin] Design skills install: no changes (already present or install failed)"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
exit 0
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
#
|
|
16
16
|
set -euo pipefail
|
|
17
17
|
|
|
18
|
+
export MERLIN_RUNTIME=codex
|
|
19
|
+
|
|
18
20
|
SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
21
|
SYSTEM_PROMPT_FILE="${HOME}/.claude/merlin-system-prompt.txt"
|
|
20
22
|
FALLBACK_PROMPT="You are Merlin: orchestrator, not coder. Route implementation to specialists. Badge every action with ⟡🔮 MERLIN ›."
|
|
@@ -22,20 +24,23 @@ FALLBACK_PROMPT="You are Merlin: orchestrator, not coder. Route implementation t
|
|
|
22
24
|
# ── Pass-through subcommands (no Merlin prompt injection) ──────
|
|
23
25
|
PASSTHROUGH_CMDS="login logout mcp mcp-server app app-server completion sandbox debug"
|
|
24
26
|
|
|
25
|
-
# ── Determine duo mode for banner
|
|
27
|
+
# ── Determine duo mode and pair for banner ─────────────────────
|
|
26
28
|
_mode_label="Solo"
|
|
29
|
+
_pair_label=""
|
|
27
30
|
if [ -x "${SCRIPTS_DIR}/duo-mode-read.sh" ]; then
|
|
28
31
|
_duo=$("${SCRIPTS_DIR}/duo-mode-read.sh" 2>/dev/null) || _duo="disabled"
|
|
29
32
|
if [ "${_duo}" = "enabled" ]; then
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
_mode_label="Duo"
|
|
34
|
+
_pair=$("${SCRIPTS_DIR}/duo-mode-read.sh" --pair 2>/dev/null) || _pair="none"
|
|
35
|
+
if [ "${_pair}" != "none" ]; then
|
|
36
|
+
_pair_label=" (${_pair})"
|
|
32
37
|
fi
|
|
33
38
|
fi
|
|
34
39
|
fi
|
|
35
40
|
|
|
36
41
|
# ── Print banner to stderr (always) ───────────────────────────
|
|
37
42
|
printf '⟡🔮 MERLIN · entering Codex via merlin-codex\n' >&2
|
|
38
|
-
printf '🎯 Mode: %s\n' "${_mode_label}" >&2
|
|
43
|
+
printf '🎯 Mode: %s%s\n' "${_mode_label}" "${_pair_label}" >&2
|
|
39
44
|
printf '▶ Codex will inherit Merlin'"'"'s orchestrator instructions\n' >&2
|
|
40
45
|
|
|
41
46
|
# ── If no args, open interactive Codex shell ──────────────────
|