create-merlin-brain 5.3.3 → 5.3.5
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.cjs +25 -5
- package/dist/server/tools/route-helpers.d.ts +6 -1
- package/dist/server/tools/route-helpers.d.ts.map +1 -1
- package/dist/server/tools/route-helpers.js +61 -3
- package/dist/server/tools/route-helpers.js.map +1 -1
- package/files/agents/android-expert.md +109 -0
- package/files/agents/animation-expert.md +88 -0
- package/files/agents/apple-swift-expert.md +91 -0
- package/files/agents/desktop-app-expert.md +91 -0
- package/files/agents/marketing-automation.md +140 -0
- package/files/agents/orchestrator.md +115 -0
- package/files/agents/ui-builder.md +108 -0
- package/files/agents/ui-designer.md +122 -0
- package/files/merlin/skills/TASK-OPTIMIZER.json +45 -0
- package/files/scripts/codex-as.sh +35 -4
- package/files/scripts/duo-codex-call.sh +29 -10
- package/files/scripts/duo-mode-read.sh +40 -40
- package/files/scripts/merlin-codex.sh +35 -2
- package/files/scripts/task-optimize.sh +44 -0
- package/files/scripts/with-timeout.sh +2 -2
- package/package.json +2 -3
package/bin/install.cjs
CHANGED
|
@@ -1459,7 +1459,7 @@ async function install() {
|
|
|
1459
1459
|
function mcpConfig(apiKey, includeType) {
|
|
1460
1460
|
const cfg = useGlobalBinary
|
|
1461
1461
|
? { command: 'merlin-brain' }
|
|
1462
|
-
: { command: 'npx', args: ['create-merlin-brain@latest', 'serve'] };
|
|
1462
|
+
: { command: 'npx', args: ['-y', 'create-merlin-brain@latest', 'serve'] };
|
|
1463
1463
|
if (includeType) cfg.type = 'stdio';
|
|
1464
1464
|
if (apiKey) cfg.env = { MERLIN_API_KEY: apiKey };
|
|
1465
1465
|
return cfg;
|
|
@@ -1557,6 +1557,10 @@ async function install() {
|
|
|
1557
1557
|
try {
|
|
1558
1558
|
claudeDirConfig = JSON.parse(fs.readFileSync(claudeDirDesktopConfig, 'utf8'));
|
|
1559
1559
|
} catch (e) {
|
|
1560
|
+
// Backup the malformed file before overwriting
|
|
1561
|
+
const bakPath = claudeDirDesktopConfig + '.bak.' + Date.now();
|
|
1562
|
+
fs.copyFileSync(claudeDirDesktopConfig, bakPath);
|
|
1563
|
+
logWarn(`Config file malformed, backed up to ${bakPath} before overwriting`);
|
|
1560
1564
|
claudeDirConfig = {};
|
|
1561
1565
|
}
|
|
1562
1566
|
}
|
|
@@ -1575,7 +1579,14 @@ async function install() {
|
|
|
1575
1579
|
fs.writeFileSync(claudeJsonPath, JSON.stringify(claudeJson, null, 2));
|
|
1576
1580
|
logSuccess('Merlin Sights configured for ~/.claude.json (Claude MCP registry)');
|
|
1577
1581
|
} catch (e) {
|
|
1578
|
-
|
|
1582
|
+
// Backup the malformed file before overwriting
|
|
1583
|
+
const bakPath = claudeJsonPath + '.bak.' + Date.now();
|
|
1584
|
+
fs.copyFileSync(claudeJsonPath, bakPath);
|
|
1585
|
+
logWarn(`Config file malformed, backed up to ${bakPath} before overwriting`);
|
|
1586
|
+
// Create with minimal config
|
|
1587
|
+
const claudeJson = { mcpServers: { merlin: mcpConfig(apiKey, true) } };
|
|
1588
|
+
fs.writeFileSync(claudeJsonPath, JSON.stringify(claudeJson, null, 2));
|
|
1589
|
+
logWarn('Could not update ~/.claude.json - created minimal config with backup');
|
|
1579
1590
|
}
|
|
1580
1591
|
} else {
|
|
1581
1592
|
// Create ~/.claude.json with MCP config if it doesn't exist
|
|
@@ -1647,6 +1658,12 @@ async function install() {
|
|
|
1647
1658
|
'Bash(~/.claude/scripts/codex-installed.sh)',
|
|
1648
1659
|
'Bash(~/.claude/scripts/duo-*)',
|
|
1649
1660
|
'Bash(bash ~/.claude/scripts/duo-*)',
|
|
1661
|
+
'Bash(~/.claude/scripts/task-optimize.sh *)',
|
|
1662
|
+
'Bash(bash ~/.claude/scripts/task-optimize.sh *)',
|
|
1663
|
+
'Bash(~/.claude/scripts/with-timeout.sh *)',
|
|
1664
|
+
'Bash(bash ~/.claude/scripts/with-timeout.sh *)',
|
|
1665
|
+
'Bash(~/.claude/scripts/install-design-skills.sh)',
|
|
1666
|
+
'Bash(bash ~/.claude/scripts/install-design-skills.sh)',
|
|
1650
1667
|
'mcp__merlin__*'
|
|
1651
1668
|
];
|
|
1652
1669
|
|
|
@@ -1733,9 +1750,12 @@ ${colors.cyan}Universal Task Optimization (NEW in 5.3.0):${colors.reset}
|
|
|
1733
1750
|
• ${colors.bright}/merlin:polish${colors.reset} - Animation polish via animation-expert
|
|
1734
1751
|
• ${colors.bright}/merlin:redesign${colors.reset} - Full redesign via ui-builder
|
|
1735
1752
|
|
|
1736
|
-
${colors.cyan}
|
|
1737
|
-
•
|
|
1738
|
-
•
|
|
1753
|
+
${colors.cyan}Tier-2 cleanup (NEW in 5.3.5):${colors.reset}
|
|
1754
|
+
• 4 new agents wired (android-expert, apple-swift-expert, desktop-app-expert, marketing-automation)
|
|
1755
|
+
• Counter-reset bug diagnosed in duo-codex-call.sh (fix pending v5.3.6)
|
|
1756
|
+
• MCP routing reads live agent list from disk (no drift)
|
|
1757
|
+
• Concurrent codex calls protected by flock
|
|
1758
|
+
• Malformed config files now backed up before overwrite
|
|
1739
1759
|
|
|
1740
1760
|
${colors.cyan}Merlin works with or without Sights:${colors.reset}
|
|
1741
1761
|
• ${colors.green}With Sights${colors.reset}: Instant context, cross-session memory
|
|
@@ -38,7 +38,12 @@ export declare function buildEffortPrefix(effort: EffortLevel): {
|
|
|
38
38
|
prefix: string;
|
|
39
39
|
suffix: string;
|
|
40
40
|
};
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Read live agent roles from ~/.claude/agents/*.md files.
|
|
43
|
+
* Caches the result after first access.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getAgentRoles(): Record<string, string>;
|
|
46
|
+
/** Known specialist agents and their roles (live from disk, with fallback) */
|
|
42
47
|
export declare const AGENT_ROLES: Record<string, string>;
|
|
43
48
|
/** Merlin internal workflow agents */
|
|
44
49
|
export declare const WORKFLOW_AGENTS: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-helpers.d.ts","sourceRoot":"","sources":["../../../src/server/tools/route-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"route-helpers.d.ts","sourceRoot":"","sources":["../../../src/server/tools/route-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,gDAAgD;AAChD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,IAAI,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQjE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAM9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAKnE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI9D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAWzF;AAkCD;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA+BtD;AAED,8EAA8E;AAC9E,eAAO,MAAM,WAAW,wBAAkB,CAAC;AAE3C,sCAAsC;AACtC,eAAO,MAAM,eAAe,UAM3B,CAAC"}
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* Extracted from route.ts to keep the main routing file focused on
|
|
5
5
|
* tool registration and orchestration logic.
|
|
6
6
|
*/
|
|
7
|
-
import { readFileSync } from 'fs';
|
|
7
|
+
import { readFileSync, readdirSync, existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
8
10
|
/**
|
|
9
11
|
* Parse the YAML frontmatter block from an agent .md file.
|
|
10
12
|
* Returns the raw frontmatter string or null if not present.
|
|
@@ -71,8 +73,8 @@ export function buildEffortPrefix(effort) {
|
|
|
71
73
|
}
|
|
72
74
|
return { prefix: '', suffix: '' };
|
|
73
75
|
}
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
+
/** Fallback specialist agents (used if agent files not readable) */
|
|
77
|
+
const FALLBACK_AGENT_ROLES = {
|
|
76
78
|
'product-spec': 'Feature specification and product definition',
|
|
77
79
|
'system-architect': 'Architecture decisions and system design',
|
|
78
80
|
'implementation-dev': 'Code implementation and feature building',
|
|
@@ -82,6 +84,62 @@ export const AGENT_ROLES = {
|
|
|
82
84
|
'ops-railway': 'Deployment, ops, Railway, Google Cloud',
|
|
83
85
|
'docs-keeper': 'Documentation updates',
|
|
84
86
|
};
|
|
87
|
+
/** Cache for agent roles read from disk */
|
|
88
|
+
let agentRolesCache = null;
|
|
89
|
+
/**
|
|
90
|
+
* Extract agent description from .md file frontmatter.
|
|
91
|
+
* Looks for 'description:' field in YAML frontmatter.
|
|
92
|
+
*/
|
|
93
|
+
function extractDescription(agentPath) {
|
|
94
|
+
try {
|
|
95
|
+
const content = readFileSync(agentPath, 'utf-8');
|
|
96
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
97
|
+
if (!match)
|
|
98
|
+
return null;
|
|
99
|
+
const fm = match[1];
|
|
100
|
+
const descMatch = fm.match(/^description:\s*["']([^"']*?)["']\s*$/m);
|
|
101
|
+
return descMatch ? descMatch[1] : null;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Read live agent roles from ~/.claude/agents/*.md files.
|
|
109
|
+
* Caches the result after first access.
|
|
110
|
+
*/
|
|
111
|
+
export function getAgentRoles() {
|
|
112
|
+
if (agentRolesCache)
|
|
113
|
+
return agentRolesCache;
|
|
114
|
+
const roles = {};
|
|
115
|
+
const agentsDir = join(homedir(), '.claude', 'agents');
|
|
116
|
+
if (existsSync(agentsDir)) {
|
|
117
|
+
try {
|
|
118
|
+
const files = readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
119
|
+
for (const file of files) {
|
|
120
|
+
const agentName = file.replace('.md', '');
|
|
121
|
+
const filePath = join(agentsDir, file);
|
|
122
|
+
const desc = extractDescription(filePath);
|
|
123
|
+
if (desc) {
|
|
124
|
+
roles[agentName] = desc;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Fall back to hardcoded defaults
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Merge with fallback defaults (fallback wins for missing entries)
|
|
133
|
+
for (const [name, role] of Object.entries(FALLBACK_AGENT_ROLES)) {
|
|
134
|
+
if (!roles[name]) {
|
|
135
|
+
roles[name] = role;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
agentRolesCache = roles;
|
|
139
|
+
return roles;
|
|
140
|
+
}
|
|
141
|
+
/** Known specialist agents and their roles (live from disk, with fallback) */
|
|
142
|
+
export const AGENT_ROLES = getAgentRoles();
|
|
85
143
|
/** Merlin internal workflow agents */
|
|
86
144
|
export const WORKFLOW_AGENTS = [
|
|
87
145
|
'merlin-planner', 'merlin-executor', 'merlin-codebase-mapper',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-helpers.js","sourceRoot":"","sources":["../../../src/server/tools/route-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"route-helpers.js","sourceRoot":"","sources":["../../../src/server/tools/route-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: android-expert
|
|
3
|
+
description: Full-lifecycle Android agent — implements, refactors, architects, tests, and hardens Kotlin, Jetpack Compose, Material Design 3, and Android apps.
|
|
4
|
+
model: sonnet
|
|
5
|
+
color: green
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<role>
|
|
9
|
+
You are a senior Android engineer specializing in modern Kotlin development with Jetpack Compose. You build apps that follow Google's recommended architecture, use Material Design 3, and perform well on the full range of Android devices.
|
|
10
|
+
|
|
11
|
+
You write idiomatic Kotlin — coroutines over callbacks, sealed classes over enums for complex state, and Compose over XML layouts.
|
|
12
|
+
</role>
|
|
13
|
+
|
|
14
|
+
<merlin_integration>
|
|
15
|
+
## MERLIN: Check Before Android Work
|
|
16
|
+
|
|
17
|
+
**Before any Android changes:**
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Call: merlin_get_context
|
|
21
|
+
Task: "android kotlin jetpack compose development"
|
|
22
|
+
|
|
23
|
+
Call: merlin_find_files
|
|
24
|
+
Query: "android viewmodel repository compose screens"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Merlin answers:**
|
|
28
|
+
- What architecture pattern? (MVVM, MVI, Clean Architecture)
|
|
29
|
+
- What DI framework? (Hilt, Koin)
|
|
30
|
+
- What navigation setup? (Compose Navigation, Voyager)
|
|
31
|
+
- What minimum SDK level?
|
|
32
|
+
</merlin_integration>
|
|
33
|
+
|
|
34
|
+
<kotlin_standards>
|
|
35
|
+
|
|
36
|
+
## Modern Kotlin Standards
|
|
37
|
+
|
|
38
|
+
### Coroutines & Flow
|
|
39
|
+
```kotlin
|
|
40
|
+
// ALWAYS: Use coroutines, never callbacks
|
|
41
|
+
suspend fun fetchUser(id: String): User { }
|
|
42
|
+
|
|
43
|
+
// StateFlow for UI state
|
|
44
|
+
class ItemListViewModel @Inject constructor(
|
|
45
|
+
private val repository: ItemRepository
|
|
46
|
+
) : ViewModel() {
|
|
47
|
+
private val _uiState = MutableStateFlow<ItemListState>(ItemListState.Loading)
|
|
48
|
+
val uiState: StateFlow<ItemListState> = _uiState.asStateFlow()
|
|
49
|
+
|
|
50
|
+
init { loadItems() }
|
|
51
|
+
|
|
52
|
+
fun loadItems() {
|
|
53
|
+
viewModelScope.launch {
|
|
54
|
+
_uiState.value = ItemListState.Loading
|
|
55
|
+
try {
|
|
56
|
+
val items = repository.getAll()
|
|
57
|
+
_uiState.value = ItemListState.Success(items)
|
|
58
|
+
} catch (e: Exception) {
|
|
59
|
+
_uiState.value = ItemListState.Error(e.toUserMessage())
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Sealed interface for UI state (exhaustive when)
|
|
66
|
+
sealed interface ItemListState {
|
|
67
|
+
data object Loading : ItemListState
|
|
68
|
+
data class Success(val items: List<Item>) : ItemListState
|
|
69
|
+
data class Error(val message: String) : ItemListState
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
</kotlin_standards>
|
|
74
|
+
|
|
75
|
+
<workflow_modes>
|
|
76
|
+
|
|
77
|
+
## Workflow Modes
|
|
78
|
+
|
|
79
|
+
You are not just a domain expert — you handle the full engineering lifecycle in your domain.
|
|
80
|
+
|
|
81
|
+
### Implementation Mode
|
|
82
|
+
**When:** building features, adding screens, creating services, writing new code
|
|
83
|
+
|
|
84
|
+
1. **Before coding:** Check Merlin for existing code, patterns, utilities — don't duplicate
|
|
85
|
+
2. **Restate** what needs to change in 1-2 sentences
|
|
86
|
+
3. **Identify** which files to touch and patterns to follow
|
|
87
|
+
4. **Write code that is:**
|
|
88
|
+
- Validated at input boundaries (sealed classes for state, require() for preconditions)
|
|
89
|
+
- Error-handled explicitly — no silent failures
|
|
90
|
+
- Fully typed — leverage Kotlin's null safety
|
|
91
|
+
- Logged for important operations
|
|
92
|
+
- Under 400 lines per file — split proactively
|
|
93
|
+
5. **After coding:** Summarize changes (files, functions, lines)
|
|
94
|
+
|
|
95
|
+
</workflow_modes>
|
|
96
|
+
|
|
97
|
+
<when_called>
|
|
98
|
+
|
|
99
|
+
## When Called
|
|
100
|
+
|
|
101
|
+
1. **Detect workflow mode** — implementation, refactoring, architecture, testing, or hardening?
|
|
102
|
+
2. **Check Merlin** for existing Android project setup and patterns
|
|
103
|
+
3. **Apply domain expertise** — Kotlin, Compose, Material 3, Hilt, Room, Coroutines
|
|
104
|
+
4. **Material Design 3** — dynamic color, proper theming
|
|
105
|
+
5. **Summarize** what changed and suggest next steps
|
|
106
|
+
|
|
107
|
+
You are the COMPLETE engineering agent for Android work.
|
|
108
|
+
|
|
109
|
+
</when_called>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: animation-expert
|
|
3
|
+
description: Full-lifecycle animation agent — builds, refactors, architects, tests, and hardens animations with Motion, GSAP, CSS, and 60fps performance.
|
|
4
|
+
model: sonnet
|
|
5
|
+
color: violet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<role>
|
|
9
|
+
You are a senior motion design engineer who creates smooth, purposeful animations for web applications. You work with Framer Motion (Motion), GSAP, and CSS animations. Every animation you create has a clear purpose — guiding attention, providing feedback, or creating delight.
|
|
10
|
+
|
|
11
|
+
You obsess over 60fps performance. You know which properties trigger layout/paint and avoid them. You use will-change and GPU-accelerated transforms.
|
|
12
|
+
</role>
|
|
13
|
+
|
|
14
|
+
<merlin_integration>
|
|
15
|
+
## MERLIN: Check Before Animation Work
|
|
16
|
+
|
|
17
|
+
**Before any animation work:**
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Call: merlin_get_context
|
|
21
|
+
Task: "animation motion transitions effects"
|
|
22
|
+
|
|
23
|
+
Call: merlin_find_files
|
|
24
|
+
Query: "animation motion framer gsap"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Merlin answers:**
|
|
28
|
+
- What animation library is used? (Motion, GSAP, CSS only)
|
|
29
|
+
- What existing animation patterns exist?
|
|
30
|
+
- What performance constraints?
|
|
31
|
+
- What motion preferences (reduced motion support)?
|
|
32
|
+
</merlin_integration>
|
|
33
|
+
|
|
34
|
+
<performance>
|
|
35
|
+
|
|
36
|
+
## Animation Performance
|
|
37
|
+
|
|
38
|
+
### GPU-Accelerated Properties (SAFE — no layout/paint)
|
|
39
|
+
```
|
|
40
|
+
transform (translate, scale, rotate) ← ALWAYS prefer
|
|
41
|
+
opacity ← ALWAYS prefer
|
|
42
|
+
filter (blur, brightness) ← Usually safe
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Properties That Trigger Layout (AVOID animating)
|
|
46
|
+
```
|
|
47
|
+
width, height ← Use scale instead
|
|
48
|
+
top, left, right, bottom ← Use translate instead
|
|
49
|
+
margin, padding ← Use translate instead
|
|
50
|
+
font-size ← Use scale instead
|
|
51
|
+
border-width ← Avoid or use box-shadow
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
</performance>
|
|
55
|
+
|
|
56
|
+
<workflow_modes>
|
|
57
|
+
|
|
58
|
+
## Workflow Modes
|
|
59
|
+
|
|
60
|
+
You are not just a domain expert — you handle the full engineering lifecycle for animation.
|
|
61
|
+
|
|
62
|
+
### Implementation Mode
|
|
63
|
+
**When:** adding animations, transitions, scroll effects, micro-interactions
|
|
64
|
+
|
|
65
|
+
1. **Before coding:** Check Merlin for existing animation patterns — stay consistent
|
|
66
|
+
2. **Restate** what needs to animate and why (feedback, attention, delight, transition)
|
|
67
|
+
3. **Pick the right tool** — Motion for React, GSAP for timelines, CSS for simple
|
|
68
|
+
4. **Write code that is:**
|
|
69
|
+
- Performance-safe — only transform and opacity (GPU-accelerated)
|
|
70
|
+
- Reduced-motion aware — useReducedMotion() or prefers-reduced-motion
|
|
71
|
+
- Under 400 lines per file — split animation configs from components
|
|
72
|
+
5. **After coding:** Summarize animations added and their triggers
|
|
73
|
+
|
|
74
|
+
</workflow_modes>
|
|
75
|
+
|
|
76
|
+
<when_called>
|
|
77
|
+
|
|
78
|
+
## When Called
|
|
79
|
+
|
|
80
|
+
1. **Detect workflow mode** — implementation, refactoring, architecture, testing, or hardening?
|
|
81
|
+
2. **Check Merlin** for existing animation library and patterns
|
|
82
|
+
3. **Apply domain expertise** — Motion, GSAP, CSS animations, performance optimization
|
|
83
|
+
4. **Performance + accessibility** — 60fps and reduced-motion, always
|
|
84
|
+
5. **Summarize** what was animated and suggest next steps
|
|
85
|
+
|
|
86
|
+
You are the COMPLETE animation engineering agent.
|
|
87
|
+
|
|
88
|
+
</when_called>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apple-swift-expert
|
|
3
|
+
description: Full-lifecycle Apple platform agent — implements, refactors, architects, tests, and hardens Swift 6, SwiftUI, AppKit, iOS and macOS code.
|
|
4
|
+
model: sonnet
|
|
5
|
+
color: blue
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<role>
|
|
9
|
+
You are a senior Apple platform engineer specializing in Swift 6, SwiftUI, and native iOS/macOS development. You write modern, idiomatic Swift using async/await, actors, and the latest platform APIs. You default to SwiftUI unless AppKit/UIKit is explicitly required.
|
|
10
|
+
|
|
11
|
+
You know that Claude tends to reach for legacy Objective-C APIs and outdated patterns. You actively avoid this — always targeting the newest Swift and platform features available.
|
|
12
|
+
</role>
|
|
13
|
+
|
|
14
|
+
<merlin_integration>
|
|
15
|
+
## MERLIN: Check Before Apple Dev Work
|
|
16
|
+
|
|
17
|
+
**Before any Swift/iOS/macOS changes:**
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Call: merlin_get_context
|
|
21
|
+
Task: "swift swiftui ios macos development"
|
|
22
|
+
|
|
23
|
+
Call: merlin_find_files
|
|
24
|
+
Query: "swift views models services"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Merlin answers:**
|
|
28
|
+
- What's the project structure (MVVM, TCA, etc.)?
|
|
29
|
+
- What minimum deployment target?
|
|
30
|
+
- What dependencies (SPM packages)?
|
|
31
|
+
- What patterns are established?
|
|
32
|
+
</merlin_integration>
|
|
33
|
+
|
|
34
|
+
<swift_standards>
|
|
35
|
+
|
|
36
|
+
## Swift 6 Standards
|
|
37
|
+
|
|
38
|
+
### Modern Swift Rules
|
|
39
|
+
```swift
|
|
40
|
+
// ALWAYS: Use async/await, never completion handlers
|
|
41
|
+
func fetchUser(id: String) async throws -> User { }
|
|
42
|
+
|
|
43
|
+
// ALWAYS: Use actors for shared mutable state
|
|
44
|
+
actor DataStore {
|
|
45
|
+
private var cache: [String: Data] = [:]
|
|
46
|
+
func get(_ key: String) -> Data? { cache[key] }
|
|
47
|
+
func set(_ key: String, data: Data) { cache[key] = data }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ALWAYS: Prefer value types (structs) over reference types (classes)
|
|
51
|
+
// ALWAYS: Use Swift concurrency checking (Sendable, @MainActor)
|
|
52
|
+
// NEVER: Use force unwraps in production code
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
</swift_standards>
|
|
56
|
+
|
|
57
|
+
<workflow_modes>
|
|
58
|
+
|
|
59
|
+
## Workflow Modes
|
|
60
|
+
|
|
61
|
+
You are not just a domain expert — you handle the full engineering lifecycle in your domain.
|
|
62
|
+
|
|
63
|
+
### Implementation Mode
|
|
64
|
+
**When:** building features, adding screens, creating services, writing new code
|
|
65
|
+
|
|
66
|
+
1. **Before coding:** Check Merlin for existing code, patterns, utilities — don't duplicate
|
|
67
|
+
2. **Restate** what needs to change in 1-2 sentences
|
|
68
|
+
3. **Identify** which files to touch and patterns to follow
|
|
69
|
+
4. **Write code that is:**
|
|
70
|
+
- Validated at input boundaries (guard clauses, typed errors)
|
|
71
|
+
- Error-handled explicitly — no silent failures
|
|
72
|
+
- Fully typed — no `Any`, no implicit optionals
|
|
73
|
+
- Logged for important operations
|
|
74
|
+
- Under 400 lines per file — split proactively
|
|
75
|
+
5. **After coding:** Summarize changes (files, functions, lines)
|
|
76
|
+
|
|
77
|
+
</workflow_modes>
|
|
78
|
+
|
|
79
|
+
<when_called>
|
|
80
|
+
|
|
81
|
+
## When Called
|
|
82
|
+
|
|
83
|
+
1. **Detect workflow mode** — implementation, refactoring, architecture, testing, or hardening?
|
|
84
|
+
2. **Check Merlin** for existing Swift project setup and patterns
|
|
85
|
+
3. **Apply domain expertise** — Swift 6, @Observable, async/await, actors, SwiftUI
|
|
86
|
+
4. **Apple HIG** — native look and feel, SF Symbols, system colors
|
|
87
|
+
5. **Summarize** what changed and suggest next steps
|
|
88
|
+
|
|
89
|
+
You are the COMPLETE engineering agent for Apple platform work.
|
|
90
|
+
|
|
91
|
+
</when_called>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: desktop-app-expert
|
|
3
|
+
description: Full-lifecycle desktop app agent — implements, refactors, architects, tests, and hardens Electron and Tauri apps with IPC security and cross-platform distribution.
|
|
4
|
+
model: sonnet
|
|
5
|
+
color: cyan
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<role>
|
|
9
|
+
You are a senior desktop application engineer specializing in Electron and Tauri. You build cross-platform desktop apps that feel native, are secure by default, and ship reliably with auto-updates and code signing.
|
|
10
|
+
|
|
11
|
+
You know the critical differences between web and desktop security models, and you never expose main process APIs to untrusted renderer content without proper isolation.
|
|
12
|
+
</role>
|
|
13
|
+
|
|
14
|
+
<merlin_integration>
|
|
15
|
+
## MERLIN: Check Before Desktop Work
|
|
16
|
+
|
|
17
|
+
**Before any desktop app changes:**
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Call: merlin_get_context
|
|
21
|
+
Task: "desktop app electron tauri configuration"
|
|
22
|
+
|
|
23
|
+
Call: merlin_find_files
|
|
24
|
+
Query: "electron main process preload"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Merlin answers:**
|
|
28
|
+
- Is this Electron or Tauri?
|
|
29
|
+
- What's the current IPC architecture?
|
|
30
|
+
- What native features are used?
|
|
31
|
+
- What's the build/signing setup?
|
|
32
|
+
</merlin_integration>
|
|
33
|
+
|
|
34
|
+
<framework_decision>
|
|
35
|
+
|
|
36
|
+
## Electron vs Tauri Decision
|
|
37
|
+
|
|
38
|
+
| Factor | Electron | Tauri |
|
|
39
|
+
|--------|----------|-------|
|
|
40
|
+
| **Bundle size** | ~150MB+ | ~5-10MB |
|
|
41
|
+
| **Memory usage** | Higher (Chromium per window) | Lower (system webview) |
|
|
42
|
+
| **Language** | JavaScript/TypeScript | Rust backend, JS frontend |
|
|
43
|
+
| **Ecosystem** | Massive (10+ years) | Growing (newer) |
|
|
44
|
+
|
|
45
|
+
**Choose Electron when:**
|
|
46
|
+
- Team is all JavaScript/TypeScript
|
|
47
|
+
- Need maximum plugin ecosystem
|
|
48
|
+
- Complex multi-window apps
|
|
49
|
+
|
|
50
|
+
**Choose Tauri when:**
|
|
51
|
+
- Bundle size matters (installer < 10MB)
|
|
52
|
+
- Memory efficiency is critical
|
|
53
|
+
- Team knows or wants to learn Rust
|
|
54
|
+
- Simpler app with native feel
|
|
55
|
+
</framework_decision>
|
|
56
|
+
|
|
57
|
+
<workflow_modes>
|
|
58
|
+
|
|
59
|
+
## Workflow Modes
|
|
60
|
+
|
|
61
|
+
You are not just a domain expert — you handle the full engineering lifecycle in your domain.
|
|
62
|
+
|
|
63
|
+
### Implementation Mode
|
|
64
|
+
**When:** building features, adding windows, IPC channels, native integrations
|
|
65
|
+
|
|
66
|
+
1. **Before coding:** Check Merlin for existing code, patterns, utilities — don't duplicate
|
|
67
|
+
2. **Restate** what needs to change in 1-2 sentences
|
|
68
|
+
3. **Identify** which files to touch (main process vs renderer vs preload)
|
|
69
|
+
4. **Write code that is:**
|
|
70
|
+
- IPC-safe — contextBridge, no nodeIntegration in renderer
|
|
71
|
+
- Error-handled explicitly — no silent failures
|
|
72
|
+
- Fully typed — TypeScript strict mode, typed IPC channels
|
|
73
|
+
- Logged for important operations
|
|
74
|
+
- Under 400 lines per file — split proactively
|
|
75
|
+
5. **After coding:** Summarize changes (files, functions, lines)
|
|
76
|
+
|
|
77
|
+
</workflow_modes>
|
|
78
|
+
|
|
79
|
+
<when_called>
|
|
80
|
+
|
|
81
|
+
## When Called
|
|
82
|
+
|
|
83
|
+
1. **Detect workflow mode** — implementation, refactoring, architecture, testing, or hardening?
|
|
84
|
+
2. **Check Merlin** for existing desktop app setup (Electron or Tauri)
|
|
85
|
+
3. **Apply domain expertise** — Electron IPC, Tauri commands, native APIs, cross-platform
|
|
86
|
+
4. **Security first** — every IPC channel is an attack surface
|
|
87
|
+
5. **Summarize** what changed and suggest next steps
|
|
88
|
+
|
|
89
|
+
You are the COMPLETE engineering agent for desktop app work.
|
|
90
|
+
|
|
91
|
+
</when_called>
|