@hailer/mcp 0.0.6 → 0.1.1
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/.claude/agents/ada.md +127 -0
- package/.claude/agents/agent-builder.md +151 -0
- package/.claude/agents/alejandro.md +66 -0
- package/.claude/agents/bjorn.md +305 -0
- package/.claude/agents/dmitri.md +61 -0
- package/.claude/agents/giuseppe.md +66 -0
- package/.claude/agents/gunther.md +355 -0
- package/.claude/agents/helga.md +68 -0
- package/.claude/agents/ingrid.md +108 -0
- package/.claude/agents/kenji.md +58 -0
- package/.claude/agents/svetlana.md +394 -0
- package/.claude/agents/viktor.md +63 -0
- package/.claude/agents/yevgeni.md +60 -0
- package/.claude/hooks/agent-failure-detector.cjs +286 -0
- package/.claude/hooks/app-edit-guard.cjs +462 -0
- package/.claude/hooks/interactive-mode.cjs +59 -0
- package/.claude/hooks/mcp-server-guard.cjs +92 -0
- package/.claude/hooks/post-scaffold-hook.cjs +31 -0
- package/.claude/hooks/sdk-delete-guard.cjs +2 -0
- package/.claude/hooks/src-edit-guard.cjs +208 -0
- package/.claude/settings.json +47 -2
- package/.claude/skills/insight-join-patterns/SKILL.md +209 -0
- package/.env.example +13 -1
- package/CLAUDE.md +135 -0
- package/dist/app.js +4 -3
- package/dist/cli.js +0 -0
- package/dist/client/adaptive-documentation-bot.d.ts +0 -2
- package/dist/client/adaptive-documentation-bot.js +5 -16
- package/dist/client/message-processor.js +5 -0
- package/dist/client/providers/anthropic-provider.js +21 -7
- package/dist/mcp/UserContextCache.d.ts +14 -0
- package/dist/mcp/UserContextCache.js +49 -24
- package/dist/mcp/auth.d.ts +7 -0
- package/dist/mcp/auth.js +13 -5
- package/dist/mcp/hailer-clients.d.ts +5 -2
- package/dist/mcp/signal-handler.d.ts +28 -2
- package/dist/mcp/signal-handler.js +4 -2
- package/dist/mcp/tool-registry.d.ts +55 -2
- package/dist/mcp/tool-registry.js +197 -2
- package/dist/mcp/tools/app-core.d.ts +15 -0
- package/dist/mcp/tools/app-core.js +609 -0
- package/dist/mcp/tools/app-marketplace.d.ts +21 -0
- package/dist/mcp/tools/app-marketplace.js +1284 -0
- package/dist/mcp/tools/app-member.d.ts +11 -0
- package/dist/mcp/tools/app-member.js +258 -0
- package/dist/mcp/tools/app-scaffold.d.ts +11 -0
- package/dist/mcp/tools/app-scaffold.js +743 -0
- package/dist/mcp/tools/app.d.ts +13 -22
- package/dist/mcp/tools/app.js +17 -2466
- package/dist/mcp/tools/file.js +6 -6
- package/dist/mcp/tools/insight.d.ts +1 -0
- package/dist/mcp/tools/insight.js +203 -64
- package/dist/mcp/tools/user.js +3 -9
- package/dist/mcp/tools/workflow.js +49 -38
- package/dist/mcp/utils/hailer-api-client.js +4 -13
- package/dist/mcp/utils/tool-helpers.d.ts +102 -0
- package/dist/mcp/utils/tool-helpers.js +179 -0
- package/dist/mcp/utils/types.d.ts +6 -0
- package/dist/mcp/workspace-cache.d.ts +5 -5
- package/dist/mcp/workspace-cache.js +4 -3
- package/package.json +1 -1
- package/.claude/hooks/PreToolUse.sh +0 -52
- package/.claude/hooks/prompt-skill-loader.cjs +0 -553
- package/.claude/hooks/skill-loader.cjs +0 -142
- package/.claude/settings.local.json +0 -49
- package/.claude/skills/MCP-add-app-member-skill/SKILL.md +0 -977
- package/.claude/skills/MCP-build-data-app-skill/SKILL.md +0 -372
- package/.claude/skills/MCP-create-app-skill/SKILL.md +0 -1101
- package/.claude/skills/MCP-create-insight-skill/SKILL.md +0 -1317
- package/.claude/skills/MCP-get-insight-data-skill/SKILL.md +0 -1053
- package/.claude/skills/MCP-insight-api/SKILL.md +0 -185
- package/.claude/skills/MCP-insight-api/references/insight-endpoints.md +0 -514
- package/.claude/skills/MCP-install-workflow-skill/SKILL.md +0 -1056
- package/.claude/skills/MCP-list-apps-skill/SKILL.md +0 -1010
- package/.claude/skills/MCP-list-workflows-minimal-skill/SKILL.md +0 -992
- package/.claude/skills/MCP-local-first-skill/SKILL.md +0 -570
- package/.claude/skills/MCP-populate-workflow-data-skill/SKILL.md +0 -395
- package/.claude/skills/MCP-preview-insight-skill/SKILL.md +0 -1290
- package/.claude/skills/MCP-publish-hailer-app-skill/SKILL.md +0 -453
- package/.claude/skills/MCP-publish-template-skill/SKILL.md +0 -278
- package/.claude/skills/MCP-remove-app-member-skill/SKILL.md +0 -671
- package/.claude/skills/MCP-remove-app-skill/SKILL.md +0 -985
- package/.claude/skills/MCP-remove-insight-skill/SKILL.md +0 -1011
- package/.claude/skills/MCP-remove-workflow-skill/SKILL.md +0 -920
- package/.claude/skills/MCP-scaffold-hailer-app-skill/SKILL.md +0 -1314
- package/.claude/skills/MCP-update-app-skill/SKILL.md +0 -970
- package/.claude/skills/MCP-update-workflow-field-skill/SKILL.md +0 -1098
- package/.claude/skills/SDK-create-function-field-skill/SKILL.md +0 -313
- package/.claude/skills/SDK-generate-skill/SKILL.md +0 -223
- package/.claude/skills/SDK-init-skill/SKILL.md +0 -177
- package/.claude/skills/SDK-workspace-setup-skill/SKILL.md +0 -605
- package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -435
- package/.claude/skills/activity-api/SKILL.md +0 -96
- package/.claude/skills/activity-api/references/activity-endpoints.md +0 -845
- package/.claude/skills/agent-building/SKILL.md +0 -243
- package/.claude/skills/agent-building/references/architecture-patterns.md +0 -446
- package/.claude/skills/agent-building/references/code-examples.md +0 -587
- package/.claude/skills/agent-building/references/implementation-guide.md +0 -619
- package/.claude/skills/app-api/SKILL.md +0 -219
- package/.claude/skills/app-api/references/app-endpoints.md +0 -759
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +0 -813
- package/.claude/skills/hailer-api/SKILL.md +0 -283
- package/.claude/skills/hailer-api/references/activities.md +0 -620
- package/.claude/skills/hailer-api/references/authentication.md +0 -216
- package/.claude/skills/hailer-api/references/datasets.md +0 -437
- package/.claude/skills/hailer-api/references/files.md +0 -301
- package/.claude/skills/hailer-api/references/insights.md +0 -469
- package/.claude/skills/hailer-api/references/workflows.md +0 -720
- package/.claude/skills/hailer-api/references/workspaces-users.md +0 -445
- package/.claude/skills/hailer-app-builder/SKILL.md +0 -340
- package/.claude/skills/mcp-tools/SKILL.md +0 -419
- package/.claude/skills/mcp-tools/references/api-endpoints.md +0 -499
- package/.claude/skills/mcp-tools/references/data-structures.md +0 -554
- package/.claude/skills/mcp-tools/references/implementation-patterns.md +0 -717
- package/.claude/skills/skill-testing/README.md +0 -137
- package/.claude/skills/skill-testing/SKILL.md +0 -348
- package/.claude/skills/skill-testing/references/test-patterns.md +0 -705
- package/.claude/skills/skill-testing/references/testing-guide.md +0 -603
- package/.claude/skills/skill-testing/references/validation-checklist.md +0 -537
- package/.claude/skills/spawn-app-builder/SKILL.md +0 -366
- package/.claude/skills/tool-builder/SKILL.md +0 -328
- package/tsconfig.json +0 -23
|
@@ -1,553 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Claude Code UserPromptSubmit Hook - Auto-loads skills based on prompt keywords
|
|
4
|
-
*
|
|
5
|
-
* This hook detects keywords in user prompts and triggers disambiguation
|
|
6
|
-
* questions to clarify user intent before loading skills.
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Keyword-based skill loading
|
|
10
|
-
* - Disambiguation prompts for ALL keywords (no assumptions)
|
|
11
|
-
* - Marker files to avoid loading same skill twice per session
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const fs = require('fs');
|
|
15
|
-
const path = require('path');
|
|
16
|
-
const os = require('os');
|
|
17
|
-
|
|
18
|
-
// Read hook input from stdin
|
|
19
|
-
let input = '';
|
|
20
|
-
process.stdin.setEncoding('utf8');
|
|
21
|
-
process.stdin.on('data', chunk => input += chunk);
|
|
22
|
-
process.stdin.on('end', () => {
|
|
23
|
-
try {
|
|
24
|
-
const data = JSON.parse(input);
|
|
25
|
-
processHook(data);
|
|
26
|
-
} catch {
|
|
27
|
-
// Invalid JSON, exit silently
|
|
28
|
-
process.exit(0);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// Mapping from followUp types to skill file names
|
|
33
|
-
const FOLLOW_UP_SKILLS = {
|
|
34
|
-
'build-app-flow': 'MCP-build-data-app-skill',
|
|
35
|
-
'spawn-builder-flow': 'spawn-app-builder',
|
|
36
|
-
'publish-template-flow': 'MCP-publish-template-skill'
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// ALL keywords are now ambiguous - always ask for clarification
|
|
40
|
-
const AMBIGUOUS_KEYWORDS = [
|
|
41
|
-
// Pull operations
|
|
42
|
-
{
|
|
43
|
-
keyword: /\bpull\b/i,
|
|
44
|
-
contextPatterns: [
|
|
45
|
-
/\b(config|workspace|fields?|phases?|groups?|teams?|ws-config)\b/i,
|
|
46
|
-
/\bnpm run pull\b/i
|
|
47
|
-
],
|
|
48
|
-
skill: 'SDK-ws-config-skill',
|
|
49
|
-
disambiguation: {
|
|
50
|
-
keyword: 'pull',
|
|
51
|
-
question: 'What would you like to pull?',
|
|
52
|
-
options: [
|
|
53
|
-
{ label: 'Workspace configuration', description: 'Pull workflow configs, fields, phases (npm run pull)', skill: 'SDK-ws-config-skill' },
|
|
54
|
-
{ label: 'Activity data', description: 'Fetch activities from a workflow (MCP tools)', skill: null }
|
|
55
|
-
]
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
// Push operations
|
|
59
|
-
{
|
|
60
|
-
keyword: /\bpush\b/i,
|
|
61
|
-
contextPatterns: [
|
|
62
|
-
/\b(config|workspace|fields?|phases?|groups?|teams?|ws-config)\b/i,
|
|
63
|
-
/\bnpm run push\b/i
|
|
64
|
-
],
|
|
65
|
-
skill: 'SDK-ws-config-skill',
|
|
66
|
-
disambiguation: {
|
|
67
|
-
keyword: 'push',
|
|
68
|
-
question: 'What would you like to push?',
|
|
69
|
-
options: [
|
|
70
|
-
{ label: 'Workspace configuration', description: 'Push workflow configs, fields, phases (npm run push)', skill: 'SDK-ws-config-skill' },
|
|
71
|
-
{ label: 'Activity updates', description: 'Update activities in a workflow (MCP tools)', skill: null }
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
// Generate operations
|
|
76
|
-
{
|
|
77
|
-
keyword: /\bgenerate\b/i,
|
|
78
|
-
contextPatterns: [
|
|
79
|
-
/\b(types?|enums?|typescript|ts)\b/i,
|
|
80
|
-
/\bnpm run generate\b/i
|
|
81
|
-
],
|
|
82
|
-
skill: 'SDK-generate-skill',
|
|
83
|
-
disambiguation: {
|
|
84
|
-
keyword: 'generate',
|
|
85
|
-
question: 'What would you like to generate?',
|
|
86
|
-
options: [
|
|
87
|
-
{ label: 'TypeScript types/enums', description: 'Generate types from Hailer workspace (npm run generate)', skill: 'SDK-generate-skill' },
|
|
88
|
-
{ label: 'Sample data', description: 'Create test activities in workflows', skill: 'MCP-populate-workflow-data-skill' },
|
|
89
|
-
{ label: 'Reports/insights', description: 'Create SQL-like insights', skill: 'MCP-create-insight-skill' }
|
|
90
|
-
]
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
// Setup operations
|
|
94
|
-
{
|
|
95
|
-
keyword: /\bsetup\b/i,
|
|
96
|
-
contextPatterns: [
|
|
97
|
-
/\b(project|init|mcp|bot.?account)\b/i,
|
|
98
|
-
/\bhailer-sdk init\b/i
|
|
99
|
-
],
|
|
100
|
-
skill: 'SDK-init-skill',
|
|
101
|
-
disambiguation: {
|
|
102
|
-
keyword: 'setup',
|
|
103
|
-
question: 'What would you like to set up?',
|
|
104
|
-
options: [
|
|
105
|
-
{ label: 'New Hailer project', description: 'Initialize project with hailer-sdk init', skill: 'SDK-init-skill' },
|
|
106
|
-
{ label: 'Workspace structure', description: 'Create workflows, fields, phases', skill: 'SDK-workspace-setup-skill' },
|
|
107
|
-
{ label: 'Hailer app', description: 'Scaffold a new Hailer application', skill: 'MCP-scaffold-hailer-app-skill' }
|
|
108
|
-
]
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
// Initialize operations
|
|
112
|
-
{
|
|
113
|
-
keyword: /\b(init|initialize)\b/i,
|
|
114
|
-
contextPatterns: [
|
|
115
|
-
/\bhailer-sdk init\b/i,
|
|
116
|
-
/\bnew project\b/i
|
|
117
|
-
],
|
|
118
|
-
skill: 'SDK-init-skill',
|
|
119
|
-
disambiguation: {
|
|
120
|
-
keyword: 'init',
|
|
121
|
-
question: 'What would you like to initialize?',
|
|
122
|
-
options: [
|
|
123
|
-
{ label: 'New Hailer project', description: 'Initialize project with hailer-sdk init', skill: 'SDK-init-skill' },
|
|
124
|
-
{ label: 'Bot account', description: 'Set up a bot account for automation', skill: 'SDK-init-skill' },
|
|
125
|
-
{ label: 'MCP server', description: 'Configure MCP server integration', skill: 'SDK-init-skill' }
|
|
126
|
-
]
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
// Workflow operations
|
|
130
|
-
{
|
|
131
|
-
keyword: /\bworkflow\b/i,
|
|
132
|
-
contextPatterns: [
|
|
133
|
-
/\b(install|create|new).?workflow\b/i,
|
|
134
|
-
/\bworkflow.?(install|create|new)\b/i
|
|
135
|
-
],
|
|
136
|
-
skill: 'MCP-install-workflow-skill',
|
|
137
|
-
disambiguation: {
|
|
138
|
-
keyword: 'workflow',
|
|
139
|
-
question: 'What would you like to do with workflows?',
|
|
140
|
-
options: [
|
|
141
|
-
{ label: 'Create new workflow', description: 'Install a new workflow structure', skill: 'MCP-install-workflow-skill' },
|
|
142
|
-
{ label: 'List workflows', description: 'View existing workflows in workspace', skill: null },
|
|
143
|
-
{ label: 'Update workflow structure', description: 'Modify fields, phases via SDK', skill: 'SDK-ws-config-skill' },
|
|
144
|
-
{ label: 'Remove workflow', description: 'Delete a workflow from workspace', skill: 'MCP-remove-workflow-skill' }
|
|
145
|
-
]
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
// Insight/Report operations
|
|
149
|
-
{
|
|
150
|
-
keyword: /\b(insight|report|analytics)\b/i,
|
|
151
|
-
contextPatterns: [
|
|
152
|
-
/\b(create|new|build).?(insight|report)\b/i,
|
|
153
|
-
/\b(insight|report).?(create|new|build)\b/i
|
|
154
|
-
],
|
|
155
|
-
skill: 'MCP-create-insight-skill',
|
|
156
|
-
disambiguation: {
|
|
157
|
-
keyword: 'insight',
|
|
158
|
-
question: 'What would you like to do with insights?',
|
|
159
|
-
options: [
|
|
160
|
-
{ label: 'Create new insight', description: 'Build a new SQL-like report', skill: 'MCP-create-insight-skill' },
|
|
161
|
-
{ label: 'List insights', description: 'View existing insights in workspace', skill: null },
|
|
162
|
-
{ label: 'Get insight data', description: 'Execute an insight and retrieve results', skill: 'MCP-get-insight-data-skill' },
|
|
163
|
-
{ label: 'Preview/test SQL', description: 'Test a query before saving', skill: 'MCP-preview-insight-skill' }
|
|
164
|
-
]
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
// SQL/Query operations (alias for insight)
|
|
168
|
-
{
|
|
169
|
-
keyword: /\b(sql|query)\b/i,
|
|
170
|
-
contextPatterns: [
|
|
171
|
-
/\b(run|execute|test|preview).?(sql|query)\b/i
|
|
172
|
-
],
|
|
173
|
-
skill: 'MCP-preview-insight-skill',
|
|
174
|
-
disambiguation: {
|
|
175
|
-
keyword: 'sql',
|
|
176
|
-
question: 'What would you like to do with SQL queries?',
|
|
177
|
-
options: [
|
|
178
|
-
{ label: 'Create insight with SQL', description: 'Build a saved SQL report', skill: 'MCP-create-insight-skill' },
|
|
179
|
-
{ label: 'Preview/test SQL', description: 'Test a query before saving', skill: 'MCP-preview-insight-skill' },
|
|
180
|
-
{ label: 'Run existing insight', description: 'Execute a saved insight', skill: 'MCP-get-insight-data-skill' }
|
|
181
|
-
]
|
|
182
|
-
}
|
|
183
|
-
},
|
|
184
|
-
// App operations
|
|
185
|
-
{
|
|
186
|
-
keyword: /\b(app|application)\b/i,
|
|
187
|
-
contextPatterns: [
|
|
188
|
-
/\b(scaffold|create|new|build).?app\b/i,
|
|
189
|
-
/\bhailer.?app\b/i
|
|
190
|
-
],
|
|
191
|
-
skill: 'MCP-scaffold-hailer-app-skill',
|
|
192
|
-
disambiguation: {
|
|
193
|
-
keyword: 'app',
|
|
194
|
-
question: 'What would you like to do with Hailer apps?',
|
|
195
|
-
options: [
|
|
196
|
-
{ label: 'Scaffold new app', description: 'Create a new app project from template', skill: 'MCP-scaffold-hailer-app-skill' },
|
|
197
|
-
{ label: 'Build data app', description: 'Build app to visualize/manage workspace data', skill: 'MCP-scaffold-hailer-app-skill', followUp: 'build-app-flow' },
|
|
198
|
-
{ label: 'Create app entry', description: 'Register an app in Hailer (no scaffold)', skill: 'MCP-create-app-skill' },
|
|
199
|
-
{ label: 'List apps', description: 'View existing apps in workspace', skill: 'MCP-list-apps-skill' },
|
|
200
|
-
{ label: 'Update app', description: 'Modify app properties', skill: 'MCP-update-app-skill' }
|
|
201
|
-
]
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
// Build data app / visualize data operations
|
|
205
|
-
{
|
|
206
|
-
keyword: /\b(visualize|dashboard|data.?manager|manage.?data|data.?app)\b/i,
|
|
207
|
-
contextPatterns: [
|
|
208
|
-
/\b(build|create|make).*(visualize|dashboard|data)\b/i
|
|
209
|
-
],
|
|
210
|
-
skill: 'MCP-scaffold-hailer-app-skill',
|
|
211
|
-
disambiguation: {
|
|
212
|
-
keyword: 'data app',
|
|
213
|
-
question: 'What kind of data app would you like to build?',
|
|
214
|
-
options: [
|
|
215
|
-
{ label: 'Full data manager', description: 'Browse, edit, create across all workflows', skill: 'MCP-scaffold-hailer-app-skill', followUp: 'build-app-flow' },
|
|
216
|
-
{ label: 'Dashboard overview', description: 'Cards/stats for workflows at a glance', skill: 'MCP-scaffold-hailer-app-skill', followUp: 'build-app-flow' },
|
|
217
|
-
{ label: 'Specific workflow app', description: 'Focus on one or few workflows', skill: 'MCP-scaffold-hailer-app-skill', followUp: 'build-app-flow' }
|
|
218
|
-
]
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
// Write app code / Code the app operations
|
|
222
|
-
{
|
|
223
|
-
keyword: /\b(code|write|implement|develop).{0,20}(app|component|feature)\b/i,
|
|
224
|
-
contextPatterns: [
|
|
225
|
-
/\b(start|begin).{0,10}(code|coding|writing|implementing)\b/i,
|
|
226
|
-
/\bwrite.{0,10}(code|component|feature)\b/i,
|
|
227
|
-
/\bcode.{0,10}(app|component)\b/i
|
|
228
|
-
],
|
|
229
|
-
skill: 'spawn-app-builder',
|
|
230
|
-
disambiguation: {
|
|
231
|
-
keyword: 'code app',
|
|
232
|
-
question: 'What would you like to do?',
|
|
233
|
-
options: [
|
|
234
|
-
{ label: 'Spawn app builder agent', description: 'Launch isolated agent with TypeScript + SDK skills embedded', skill: 'spawn-app-builder', followUp: 'spawn-builder-flow' },
|
|
235
|
-
{ label: 'Load skills in current session', description: 'Load skills here instead of spawning new agent', skill: 'hailer-app-builder', loadMultiple: ['building-hailer-apps-skill', 'hailer-app-builder'] },
|
|
236
|
-
{ label: 'Scaffold new app first', description: 'Create project structure then write code', skill: 'MCP-scaffold-hailer-app-skill' }
|
|
237
|
-
]
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
// Continue app development / dev on app / work on app / build more / add features
|
|
241
|
-
{
|
|
242
|
-
keyword: /\b(dev|work|continue|build|add|improve|enhance|extend|modify|change|update|fix).{0,15}(on|the|to|for)?.{0,10}(app|component|dashboard|feature|ui|code)\b/i,
|
|
243
|
-
contextPatterns: [], // Always require disambiguation for safety
|
|
244
|
-
skill: 'spawn-app-builder',
|
|
245
|
-
disambiguation: {
|
|
246
|
-
keyword: 'dev app',
|
|
247
|
-
question: 'How should I proceed with app development?',
|
|
248
|
-
options: [
|
|
249
|
-
{ label: 'Spawn builder agent', description: 'RECOMMENDED: Isolated agent with TypeScript + SDK skills', skill: 'spawn-app-builder', followUp: 'spawn-builder-flow' },
|
|
250
|
-
{ label: 'Load skills here', description: 'Continue in this conversation with skills loaded', skill: 'hailer-app-builder', loadMultiple: ['building-hailer-apps-skill', 'hailer-app-builder'] }
|
|
251
|
-
]
|
|
252
|
-
}
|
|
253
|
-
},
|
|
254
|
-
// Publish/Deploy operations
|
|
255
|
-
{
|
|
256
|
-
keyword: /\b(publish|deploy)\b/i,
|
|
257
|
-
contextPatterns: [
|
|
258
|
-
/\b(publish|deploy).?app\b/i
|
|
259
|
-
],
|
|
260
|
-
skill: 'MCP-publish-hailer-app-skill',
|
|
261
|
-
disambiguation: {
|
|
262
|
-
keyword: 'publish',
|
|
263
|
-
question: 'What would you like to publish or deploy?',
|
|
264
|
-
options: [
|
|
265
|
-
{ label: 'Publish Hailer app', description: 'Build and upload app to production', skill: 'MCP-publish-hailer-app-skill' },
|
|
266
|
-
{ label: 'Publish workspace template', description: 'Share workspace config in marketplace', skill: 'MCP-publish-template-skill' },
|
|
267
|
-
{ label: 'Share app with users', description: 'Add members to access an app', skill: 'MCP-add-app-member-skill' }
|
|
268
|
-
]
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
// Template/Marketplace operations
|
|
272
|
-
{
|
|
273
|
-
keyword: /\b(template|marketplace)\b/i,
|
|
274
|
-
contextPatterns: [
|
|
275
|
-
/\b(publish|create|install|list).?template\b/i,
|
|
276
|
-
/\btemplate.?(publish|create|install|list)\b/i
|
|
277
|
-
],
|
|
278
|
-
skill: 'MCP-publish-template-skill',
|
|
279
|
-
disambiguation: {
|
|
280
|
-
keyword: 'template',
|
|
281
|
-
question: 'What would you like to do with templates?',
|
|
282
|
-
options: [
|
|
283
|
-
{ label: 'Publish template', description: 'Share workspace config in marketplace', skill: 'MCP-publish-template-skill', followUp: 'publish-template-flow' },
|
|
284
|
-
{ label: 'Install template', description: 'Add template to workspace', skill: null },
|
|
285
|
-
{ label: 'List templates', description: 'View available templates', skill: null },
|
|
286
|
-
{ label: 'Get template details', description: 'View template info', skill: null }
|
|
287
|
-
]
|
|
288
|
-
}
|
|
289
|
-
},
|
|
290
|
-
// Function field / Calculated field operations
|
|
291
|
-
{
|
|
292
|
-
keyword: /\b(function.?field|calculated.?field|formula)\b/i,
|
|
293
|
-
contextPatterns: [
|
|
294
|
-
/\b(create|add|new).?(function|calculated).?field\b/i
|
|
295
|
-
],
|
|
296
|
-
skill: 'SDK-create-function-field-skill',
|
|
297
|
-
disambiguation: {
|
|
298
|
-
keyword: 'function field',
|
|
299
|
-
question: 'What would you like to do with function fields?',
|
|
300
|
-
options: [
|
|
301
|
-
{ label: 'Create function field', description: 'Add a new calculated field to workflow', skill: 'SDK-create-function-field-skill' },
|
|
302
|
-
{ label: 'Update function field', description: 'Modify existing function field formula', skill: 'MCP-update-workflow-field-skill' },
|
|
303
|
-
{ label: 'Test function', description: 'Test function code against real data', skill: null }
|
|
304
|
-
]
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
// Sample data / Populate operations
|
|
308
|
-
{
|
|
309
|
-
keyword: /\b(sample.?data|test.?data|populate|bulk.?create)\b/i,
|
|
310
|
-
contextPatterns: [
|
|
311
|
-
/\b(create|add|generate).?(sample|test).?data\b/i
|
|
312
|
-
],
|
|
313
|
-
skill: 'MCP-populate-workflow-data-skill',
|
|
314
|
-
disambiguation: {
|
|
315
|
-
keyword: 'data',
|
|
316
|
-
question: 'What would you like to do with data?',
|
|
317
|
-
options: [
|
|
318
|
-
{ label: 'Populate with sample data', description: 'Generate realistic test activities', skill: 'MCP-populate-workflow-data-skill' },
|
|
319
|
-
{ label: 'Bulk create activities', description: 'Create multiple activities at once', skill: null },
|
|
320
|
-
{ label: 'Import data', description: 'Import from external source', skill: null }
|
|
321
|
-
]
|
|
322
|
-
}
|
|
323
|
-
},
|
|
324
|
-
// Field operations
|
|
325
|
-
{
|
|
326
|
-
keyword: /\b(add|modify|update|delete|remove|create).{0,20}field\b/i,
|
|
327
|
-
contextPatterns: [
|
|
328
|
-
/\bnpm run (fields|push)\b/i,
|
|
329
|
-
/\bworkspace.?config\b/i
|
|
330
|
-
],
|
|
331
|
-
skill: 'SDK-ws-config-skill',
|
|
332
|
-
disambiguation: {
|
|
333
|
-
keyword: 'field',
|
|
334
|
-
question: 'How would you like to modify fields?',
|
|
335
|
-
options: [
|
|
336
|
-
{ label: 'Via SDK (local files)', description: 'Edit workspace/ files and push (version controlled)', skill: 'SDK-ws-config-skill' },
|
|
337
|
-
{ label: 'Via MCP (direct API)', description: 'Update field directly via API', skill: 'MCP-update-workflow-field-skill' }
|
|
338
|
-
]
|
|
339
|
-
}
|
|
340
|
-
},
|
|
341
|
-
// Phase operations
|
|
342
|
-
{
|
|
343
|
-
keyword: /\b(add|modify|update|delete|remove|create).{0,20}phase\b/i,
|
|
344
|
-
contextPatterns: [
|
|
345
|
-
/\bnpm run (phases|push)\b/i,
|
|
346
|
-
/\bworkspace.?config\b/i
|
|
347
|
-
],
|
|
348
|
-
skill: 'SDK-ws-config-skill',
|
|
349
|
-
disambiguation: {
|
|
350
|
-
keyword: 'phase',
|
|
351
|
-
question: 'How would you like to modify phases?',
|
|
352
|
-
options: [
|
|
353
|
-
{ label: 'Via SDK (local files)', description: 'Edit workspace/ files and push (version controlled)', skill: 'SDK-ws-config-skill' },
|
|
354
|
-
{ label: 'Via MCP (direct API)', description: 'Update phase directly via API', skill: null }
|
|
355
|
-
]
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
// Activity operations
|
|
359
|
-
{
|
|
360
|
-
keyword: /\b(activities|activity)\b/i,
|
|
361
|
-
contextPatterns: [
|
|
362
|
-
/\b(list|show|get|fetch|create|update|delete).?(activities|activity)\b/i
|
|
363
|
-
],
|
|
364
|
-
skill: null,
|
|
365
|
-
disambiguation: {
|
|
366
|
-
keyword: 'activity',
|
|
367
|
-
question: 'What would you like to do with activities?',
|
|
368
|
-
options: [
|
|
369
|
-
{ label: 'List activities', description: 'View activities in a workflow', skill: null },
|
|
370
|
-
{ label: 'Create activity', description: 'Add a new activity to workflow', skill: null },
|
|
371
|
-
{ label: 'Update activity', description: 'Modify an existing activity', skill: null },
|
|
372
|
-
{ label: 'Bulk create activities', description: 'Create multiple activities at once', skill: 'MCP-populate-workflow-data-skill' }
|
|
373
|
-
]
|
|
374
|
-
}
|
|
375
|
-
},
|
|
376
|
-
// Sync operations (DESTRUCTIVE - require confirmation)
|
|
377
|
-
{
|
|
378
|
-
keyword: /\b(sync|workflows?.?sync)\b/i,
|
|
379
|
-
contextPatterns: [], // Always require confirmation, never auto-proceed
|
|
380
|
-
skill: 'SDK-ws-config-skill',
|
|
381
|
-
disambiguation: {
|
|
382
|
-
keyword: 'sync',
|
|
383
|
-
question: '⚠️ Sync operations can DELETE resources from Hailer. Items removed from local config will be PERMANENTLY deleted remotely. Proceed?',
|
|
384
|
-
options: [
|
|
385
|
-
{ label: 'Yes, run sync', description: 'I understand - proceed with destructive sync operation', skill: 'SDK-ws-config-skill', action: 'confirm-sync' },
|
|
386
|
-
{ label: 'No, cancel', description: 'Abort - don\'t delete anything', skill: null, action: 'cancel' }
|
|
387
|
-
]
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
];
|
|
391
|
-
|
|
392
|
-
// Note: DIRECT_KEYWORDS removed - all keywords now require disambiguation
|
|
393
|
-
// Flow instructions are now loaded from skill files instead of inline functions
|
|
394
|
-
|
|
395
|
-
function processHook(data) {
|
|
396
|
-
const { prompt, cwd } = data;
|
|
397
|
-
|
|
398
|
-
if (!prompt) {
|
|
399
|
-
process.exit(0);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Marker directory for tracking loaded skills this session
|
|
403
|
-
const markerDir = path.join(os.tmpdir(), '.claude-skills-loaded');
|
|
404
|
-
if (!fs.existsSync(markerDir)) {
|
|
405
|
-
fs.mkdirSync(markerDir, { recursive: true });
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// Find project directory
|
|
409
|
-
const projectDir = process.env.CLAUDE_PROJECT_DIR || cwd || process.cwd();
|
|
410
|
-
|
|
411
|
-
// Track what we'll output
|
|
412
|
-
const skillsToLoad = [];
|
|
413
|
-
const disambiguationsNeeded = [];
|
|
414
|
-
const seenDisambiguations = new Set(); // Avoid duplicate questions
|
|
415
|
-
const loadedFollowUpSkills = new Set(); // Avoid duplicate follow-up skill content
|
|
416
|
-
|
|
417
|
-
// Check all ambiguous keywords
|
|
418
|
-
for (const entry of AMBIGUOUS_KEYWORDS) {
|
|
419
|
-
if (entry.keyword.test(prompt)) {
|
|
420
|
-
// Check if context makes it clear
|
|
421
|
-
const hasContext = entry.contextPatterns && entry.contextPatterns.some(p => p.test(prompt));
|
|
422
|
-
|
|
423
|
-
if (hasContext && entry.skill) {
|
|
424
|
-
// Context is clear - load the skill
|
|
425
|
-
const markerFile = path.join(markerDir, entry.skill);
|
|
426
|
-
if (!fs.existsSync(markerFile)) {
|
|
427
|
-
const skillPath = path.join(projectDir, '.claude', 'skills', entry.skill, 'SKILL.md');
|
|
428
|
-
if (fs.existsSync(skillPath)) {
|
|
429
|
-
skillsToLoad.push({
|
|
430
|
-
skill: entry.skill,
|
|
431
|
-
description: entry.disambiguation.question,
|
|
432
|
-
path: skillPath,
|
|
433
|
-
markerFile
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
} else {
|
|
438
|
-
// Context unclear - need disambiguation (avoid duplicates)
|
|
439
|
-
const disambKey = entry.disambiguation.keyword;
|
|
440
|
-
if (!seenDisambiguations.has(disambKey)) {
|
|
441
|
-
seenDisambiguations.add(disambKey);
|
|
442
|
-
disambiguationsNeeded.push(entry.disambiguation);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// Nothing to output
|
|
449
|
-
if (skillsToLoad.length === 0 && disambiguationsNeeded.length === 0) {
|
|
450
|
-
process.exit(0);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// Build output
|
|
454
|
-
let output = '\n';
|
|
455
|
-
|
|
456
|
-
// Output disambiguation prompts first
|
|
457
|
-
if (disambiguationsNeeded.length > 0) {
|
|
458
|
-
output += '='.repeat(60) + '\n';
|
|
459
|
-
output += '⚠️ MANDATORY ACTION REQUIRED - DO NOT SKIP\n';
|
|
460
|
-
output += '='.repeat(60) + '\n\n';
|
|
461
|
-
output += 'STOP! You MUST use the AskUserQuestion tool BEFORE doing anything else.\n';
|
|
462
|
-
output += 'The user\'s intent is ambiguous. Do NOT guess or assume.\n\n';
|
|
463
|
-
|
|
464
|
-
for (const disamb of disambiguationsNeeded) {
|
|
465
|
-
output += '-'.repeat(40) + '\n';
|
|
466
|
-
output += `Ambiguous keyword detected: "${disamb.keyword}"\n\n`;
|
|
467
|
-
output += 'USE THIS EXACT AskUserQuestion CALL:\n\n';
|
|
468
|
-
output += '```json\n';
|
|
469
|
-
output += JSON.stringify({
|
|
470
|
-
questions: [{
|
|
471
|
-
question: disamb.question,
|
|
472
|
-
header: disamb.keyword.charAt(0).toUpperCase() + disamb.keyword.slice(1),
|
|
473
|
-
options: disamb.options.map(opt => ({
|
|
474
|
-
label: opt.label,
|
|
475
|
-
description: opt.description
|
|
476
|
-
})),
|
|
477
|
-
multiSelect: false
|
|
478
|
-
}]
|
|
479
|
-
}, null, 2);
|
|
480
|
-
output += '\n```\n\n';
|
|
481
|
-
|
|
482
|
-
output += 'After user responds:\n';
|
|
483
|
-
for (const opt of disamb.options) {
|
|
484
|
-
if (opt.action === 'confirm-sync') {
|
|
485
|
-
output += ` - If "${opt.label}": Load Skill(${opt.skill}), then run with: yes | npm run workflows-sync\n`;
|
|
486
|
-
} else if (opt.action === 'cancel') {
|
|
487
|
-
output += ` - If "${opt.label}": Acknowledge cancellation, do NOT run any sync command\n`;
|
|
488
|
-
} else if (opt.followUp === 'publish-template-flow') {
|
|
489
|
-
output += ` - If "${opt.label}": Load Skill(${opt.skill}), then use EXACTLY this AskUserQuestion (see below)\n`;
|
|
490
|
-
} else if (opt.loadMultiple && Array.isArray(opt.loadMultiple)) {
|
|
491
|
-
output += ` - If "${opt.label}": Load BOTH skills in order: Skill(${opt.loadMultiple.join('), Skill(')}), then proceed\n`;
|
|
492
|
-
} else if (opt.skill) {
|
|
493
|
-
output += ` - If "${opt.label}": Load Skill(${opt.skill}), then proceed\n`;
|
|
494
|
-
} else {
|
|
495
|
-
output += ` - If "${opt.label}": Use MCP tools directly (no skill needed)\n`;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
output += '\n';
|
|
499
|
-
|
|
500
|
-
// Add follow-up skill content (deduplicated - each skill only included once)
|
|
501
|
-
for (const opt of disamb.options) {
|
|
502
|
-
if (opt.followUp && !loadedFollowUpSkills.has(opt.followUp)) {
|
|
503
|
-
const skillName = FOLLOW_UP_SKILLS[opt.followUp];
|
|
504
|
-
if (skillName) {
|
|
505
|
-
const skillPath = path.join(projectDir, '.claude', 'skills', skillName, 'SKILL.md');
|
|
506
|
-
if (fs.existsSync(skillPath)) {
|
|
507
|
-
loadedFollowUpSkills.add(opt.followUp);
|
|
508
|
-
output += '\n' + '-'.repeat(40) + '\n';
|
|
509
|
-
output += `📚 FOLLOW-UP SKILL: ${skillName}\n`;
|
|
510
|
-
output += '-'.repeat(40) + '\n';
|
|
511
|
-
output += fs.readFileSync(skillPath, 'utf8');
|
|
512
|
-
output += '\n';
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
output += '='.repeat(60) + '\n';
|
|
520
|
-
output += 'REMEMBER: Ask FIRST, then act. Never assume user intent.\n';
|
|
521
|
-
output += '='.repeat(60) + '\n\n';
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
// Output skills that can be loaded directly (only when context is clear)
|
|
525
|
-
if (skillsToLoad.length > 0) {
|
|
526
|
-
output += '='.repeat(60) + '\n';
|
|
527
|
-
output += 'AUTO-LOADED SKILLS (context was clear from prompt)\n';
|
|
528
|
-
output += '='.repeat(60) + '\n\n';
|
|
529
|
-
|
|
530
|
-
for (const skill of skillsToLoad) {
|
|
531
|
-
const skillContent = fs.readFileSync(skill.path, 'utf8');
|
|
532
|
-
|
|
533
|
-
output += '-'.repeat(60) + '\n';
|
|
534
|
-
output += `SKILL: ${skill.skill}\n`;
|
|
535
|
-
output += `Purpose: ${skill.description}\n`;
|
|
536
|
-
output += '-'.repeat(60) + '\n\n';
|
|
537
|
-
output += skillContent;
|
|
538
|
-
output += '\n\n';
|
|
539
|
-
|
|
540
|
-
// Mark skill as loaded
|
|
541
|
-
fs.writeFileSync(skill.markerFile, new Date().toISOString());
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
output += '='.repeat(60) + '\n';
|
|
545
|
-
output += 'END OF AUTO-LOADED SKILLS\n';
|
|
546
|
-
output += '='.repeat(60) + '\n';
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Output to stderr - displays to user
|
|
550
|
-
console.error(output);
|
|
551
|
-
|
|
552
|
-
process.exit(0);
|
|
553
|
-
}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Claude Code PreToolUse Hook - Auto-loads skills before tools
|
|
4
|
-
*
|
|
5
|
-
* This hook intercepts tool calls and outputs relevant skill content
|
|
6
|
-
* to stderr (which Claude sees) when matching tools are detected.
|
|
7
|
-
*
|
|
8
|
-
* Supports:
|
|
9
|
-
* - SDK commands (Bash tool with npm run pull/push/etc.)
|
|
10
|
-
* - MCP tools (mcp__hailer__install_workflow, etc.)
|
|
11
|
-
*
|
|
12
|
-
* Uses marker files to avoid loading the same skill twice in a session.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const fs = require('fs');
|
|
16
|
-
const path = require('path');
|
|
17
|
-
const os = require('os');
|
|
18
|
-
|
|
19
|
-
// Read hook input from stdin
|
|
20
|
-
let input = '';
|
|
21
|
-
process.stdin.setEncoding('utf8');
|
|
22
|
-
process.stdin.on('data', chunk => input += chunk);
|
|
23
|
-
process.stdin.on('end', () => {
|
|
24
|
-
try {
|
|
25
|
-
const data = JSON.parse(input);
|
|
26
|
-
processHook(data);
|
|
27
|
-
} catch {
|
|
28
|
-
// Invalid JSON, exit silently
|
|
29
|
-
process.exit(0);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
// MCP tool to skill mapping
|
|
34
|
-
const MCP_TOOL_SKILLS = {
|
|
35
|
-
'mcp__hailer__install_workflow': 'MCP-install-workflow-skill',
|
|
36
|
-
'mcp__hailer__create_insight': 'MCP-create-insight-skill',
|
|
37
|
-
'mcp__hailer__preview_insight': 'MCP-preview-insight-skill',
|
|
38
|
-
'mcp__hailer__get_insight_data': 'MCP-get-insight-data-skill',
|
|
39
|
-
'mcp__hailer__create_app': 'MCP-create-app-skill',
|
|
40
|
-
'mcp__hailer__update_app': 'MCP-update-app-skill',
|
|
41
|
-
'mcp__hailer__add_app_member': 'MCP-add-app-member-skill',
|
|
42
|
-
'mcp__hailer__remove_app_member': 'MCP-remove-app-member-skill',
|
|
43
|
-
'mcp__hailer__scaffold_hailer_app': 'MCP-scaffold-hailer-app-skill',
|
|
44
|
-
'mcp__hailer__publish_hailer_app': 'MCP-publish-hailer-app-skill',
|
|
45
|
-
'mcp__hailer__update_workflow_field': 'MCP-update-workflow-field-skill',
|
|
46
|
-
'mcp__hailer__remove_workflow': 'MCP-remove-workflow-skill',
|
|
47
|
-
'mcp__hailer__remove_insight': 'MCP-remove-insight-skill',
|
|
48
|
-
'mcp__hailer__remove_app': 'MCP-remove-app-skill',
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// SDK command patterns to skill mapping
|
|
52
|
-
const SDK_COMMAND_SKILLS = [
|
|
53
|
-
{
|
|
54
|
-
patterns: [
|
|
55
|
-
/npm run pull/,
|
|
56
|
-
/npm run push/,
|
|
57
|
-
/npm run workflows/,
|
|
58
|
-
/npm run phases/,
|
|
59
|
-
/npm run fields/,
|
|
60
|
-
/npm run groups/,
|
|
61
|
-
/npm run teams/,
|
|
62
|
-
/npm run insights/,
|
|
63
|
-
/hailer-sdk ws-config/,
|
|
64
|
-
/hailer-sdk workspace-config/
|
|
65
|
-
],
|
|
66
|
-
skill: 'SDK-ws-config-skill'
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
patterns: [/npm run generate/, /hailer-sdk generate/],
|
|
70
|
-
skill: 'SDK-generate-skill'
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
patterns: [/hailer-sdk init/],
|
|
74
|
-
skill: 'SDK-init-skill'
|
|
75
|
-
}
|
|
76
|
-
];
|
|
77
|
-
|
|
78
|
-
function processHook(data) {
|
|
79
|
-
const { tool_name, tool_input, cwd } = data;
|
|
80
|
-
|
|
81
|
-
let matchedSkill = null;
|
|
82
|
-
|
|
83
|
-
// Check for MCP tools first
|
|
84
|
-
if (tool_name && tool_name.startsWith('mcp__hailer__')) {
|
|
85
|
-
matchedSkill = MCP_TOOL_SKILLS[tool_name];
|
|
86
|
-
}
|
|
87
|
-
// Check for Bash commands (SDK)
|
|
88
|
-
else if (tool_name === 'Bash') {
|
|
89
|
-
const command = tool_input?.command || '';
|
|
90
|
-
for (const mapping of SDK_COMMAND_SKILLS) {
|
|
91
|
-
for (const pattern of mapping.patterns) {
|
|
92
|
-
if (pattern.test(command)) {
|
|
93
|
-
matchedSkill = mapping.skill;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (matchedSkill) break;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (!matchedSkill) {
|
|
102
|
-
process.exit(0);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Marker directory for tracking loaded skills this session
|
|
106
|
-
const markerDir = path.join(os.tmpdir(), '.claude-skills-loaded');
|
|
107
|
-
if (!fs.existsSync(markerDir)) {
|
|
108
|
-
fs.mkdirSync(markerDir, { recursive: true });
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Check if skill was already loaded this session
|
|
112
|
-
const markerFile = path.join(markerDir, matchedSkill);
|
|
113
|
-
if (fs.existsSync(markerFile)) {
|
|
114
|
-
process.exit(0);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Find skill file - try project dir first, then cwd
|
|
118
|
-
const projectDir = process.env.CLAUDE_PROJECT_DIR || cwd || process.cwd();
|
|
119
|
-
const skillPath = path.join(projectDir, '.claude', 'skills', matchedSkill, 'SKILL.md');
|
|
120
|
-
|
|
121
|
-
if (!fs.existsSync(skillPath)) {
|
|
122
|
-
process.exit(0);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Read and output skill content to stderr (Claude sees stderr)
|
|
126
|
-
const skillContent = fs.readFileSync(skillPath, 'utf8');
|
|
127
|
-
|
|
128
|
-
console.error('');
|
|
129
|
-
console.error('━'.repeat(60));
|
|
130
|
-
console.error(`📚 AUTO-LOADING SKILL: ${matchedSkill}`);
|
|
131
|
-
console.error('━'.repeat(60));
|
|
132
|
-
console.error('');
|
|
133
|
-
console.error(skillContent);
|
|
134
|
-
console.error('');
|
|
135
|
-
console.error('━'.repeat(60));
|
|
136
|
-
console.error('');
|
|
137
|
-
|
|
138
|
-
// Mark skill as loaded
|
|
139
|
-
fs.writeFileSync(markerFile, new Date().toISOString());
|
|
140
|
-
|
|
141
|
-
process.exit(0);
|
|
142
|
-
}
|