@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.
Files changed (122) hide show
  1. package/.claude/agents/ada.md +127 -0
  2. package/.claude/agents/agent-builder.md +151 -0
  3. package/.claude/agents/alejandro.md +66 -0
  4. package/.claude/agents/bjorn.md +305 -0
  5. package/.claude/agents/dmitri.md +61 -0
  6. package/.claude/agents/giuseppe.md +66 -0
  7. package/.claude/agents/gunther.md +355 -0
  8. package/.claude/agents/helga.md +68 -0
  9. package/.claude/agents/ingrid.md +108 -0
  10. package/.claude/agents/kenji.md +58 -0
  11. package/.claude/agents/svetlana.md +394 -0
  12. package/.claude/agents/viktor.md +63 -0
  13. package/.claude/agents/yevgeni.md +60 -0
  14. package/.claude/hooks/agent-failure-detector.cjs +286 -0
  15. package/.claude/hooks/app-edit-guard.cjs +462 -0
  16. package/.claude/hooks/interactive-mode.cjs +59 -0
  17. package/.claude/hooks/mcp-server-guard.cjs +92 -0
  18. package/.claude/hooks/post-scaffold-hook.cjs +31 -0
  19. package/.claude/hooks/sdk-delete-guard.cjs +2 -0
  20. package/.claude/hooks/src-edit-guard.cjs +208 -0
  21. package/.claude/settings.json +47 -2
  22. package/.claude/skills/insight-join-patterns/SKILL.md +209 -0
  23. package/.env.example +13 -1
  24. package/CLAUDE.md +135 -0
  25. package/dist/app.js +4 -3
  26. package/dist/cli.js +0 -0
  27. package/dist/client/adaptive-documentation-bot.d.ts +0 -2
  28. package/dist/client/adaptive-documentation-bot.js +5 -16
  29. package/dist/client/message-processor.js +5 -0
  30. package/dist/client/providers/anthropic-provider.js +21 -7
  31. package/dist/mcp/UserContextCache.d.ts +14 -0
  32. package/dist/mcp/UserContextCache.js +49 -24
  33. package/dist/mcp/auth.d.ts +7 -0
  34. package/dist/mcp/auth.js +13 -5
  35. package/dist/mcp/hailer-clients.d.ts +5 -2
  36. package/dist/mcp/signal-handler.d.ts +28 -2
  37. package/dist/mcp/signal-handler.js +4 -2
  38. package/dist/mcp/tool-registry.d.ts +55 -2
  39. package/dist/mcp/tool-registry.js +197 -2
  40. package/dist/mcp/tools/app-core.d.ts +15 -0
  41. package/dist/mcp/tools/app-core.js +609 -0
  42. package/dist/mcp/tools/app-marketplace.d.ts +21 -0
  43. package/dist/mcp/tools/app-marketplace.js +1284 -0
  44. package/dist/mcp/tools/app-member.d.ts +11 -0
  45. package/dist/mcp/tools/app-member.js +258 -0
  46. package/dist/mcp/tools/app-scaffold.d.ts +11 -0
  47. package/dist/mcp/tools/app-scaffold.js +743 -0
  48. package/dist/mcp/tools/app.d.ts +13 -22
  49. package/dist/mcp/tools/app.js +17 -2466
  50. package/dist/mcp/tools/file.js +6 -6
  51. package/dist/mcp/tools/insight.d.ts +1 -0
  52. package/dist/mcp/tools/insight.js +203 -64
  53. package/dist/mcp/tools/user.js +3 -9
  54. package/dist/mcp/tools/workflow.js +49 -38
  55. package/dist/mcp/utils/hailer-api-client.js +4 -13
  56. package/dist/mcp/utils/tool-helpers.d.ts +102 -0
  57. package/dist/mcp/utils/tool-helpers.js +179 -0
  58. package/dist/mcp/utils/types.d.ts +6 -0
  59. package/dist/mcp/workspace-cache.d.ts +5 -5
  60. package/dist/mcp/workspace-cache.js +4 -3
  61. package/package.json +1 -1
  62. package/.claude/hooks/PreToolUse.sh +0 -52
  63. package/.claude/hooks/prompt-skill-loader.cjs +0 -553
  64. package/.claude/hooks/skill-loader.cjs +0 -142
  65. package/.claude/settings.local.json +0 -49
  66. package/.claude/skills/MCP-add-app-member-skill/SKILL.md +0 -977
  67. package/.claude/skills/MCP-build-data-app-skill/SKILL.md +0 -372
  68. package/.claude/skills/MCP-create-app-skill/SKILL.md +0 -1101
  69. package/.claude/skills/MCP-create-insight-skill/SKILL.md +0 -1317
  70. package/.claude/skills/MCP-get-insight-data-skill/SKILL.md +0 -1053
  71. package/.claude/skills/MCP-insight-api/SKILL.md +0 -185
  72. package/.claude/skills/MCP-insight-api/references/insight-endpoints.md +0 -514
  73. package/.claude/skills/MCP-install-workflow-skill/SKILL.md +0 -1056
  74. package/.claude/skills/MCP-list-apps-skill/SKILL.md +0 -1010
  75. package/.claude/skills/MCP-list-workflows-minimal-skill/SKILL.md +0 -992
  76. package/.claude/skills/MCP-local-first-skill/SKILL.md +0 -570
  77. package/.claude/skills/MCP-populate-workflow-data-skill/SKILL.md +0 -395
  78. package/.claude/skills/MCP-preview-insight-skill/SKILL.md +0 -1290
  79. package/.claude/skills/MCP-publish-hailer-app-skill/SKILL.md +0 -453
  80. package/.claude/skills/MCP-publish-template-skill/SKILL.md +0 -278
  81. package/.claude/skills/MCP-remove-app-member-skill/SKILL.md +0 -671
  82. package/.claude/skills/MCP-remove-app-skill/SKILL.md +0 -985
  83. package/.claude/skills/MCP-remove-insight-skill/SKILL.md +0 -1011
  84. package/.claude/skills/MCP-remove-workflow-skill/SKILL.md +0 -920
  85. package/.claude/skills/MCP-scaffold-hailer-app-skill/SKILL.md +0 -1314
  86. package/.claude/skills/MCP-update-app-skill/SKILL.md +0 -970
  87. package/.claude/skills/MCP-update-workflow-field-skill/SKILL.md +0 -1098
  88. package/.claude/skills/SDK-create-function-field-skill/SKILL.md +0 -313
  89. package/.claude/skills/SDK-generate-skill/SKILL.md +0 -223
  90. package/.claude/skills/SDK-init-skill/SKILL.md +0 -177
  91. package/.claude/skills/SDK-workspace-setup-skill/SKILL.md +0 -605
  92. package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -435
  93. package/.claude/skills/activity-api/SKILL.md +0 -96
  94. package/.claude/skills/activity-api/references/activity-endpoints.md +0 -845
  95. package/.claude/skills/agent-building/SKILL.md +0 -243
  96. package/.claude/skills/agent-building/references/architecture-patterns.md +0 -446
  97. package/.claude/skills/agent-building/references/code-examples.md +0 -587
  98. package/.claude/skills/agent-building/references/implementation-guide.md +0 -619
  99. package/.claude/skills/app-api/SKILL.md +0 -219
  100. package/.claude/skills/app-api/references/app-endpoints.md +0 -759
  101. package/.claude/skills/building-hailer-apps-skill/SKILL.md +0 -813
  102. package/.claude/skills/hailer-api/SKILL.md +0 -283
  103. package/.claude/skills/hailer-api/references/activities.md +0 -620
  104. package/.claude/skills/hailer-api/references/authentication.md +0 -216
  105. package/.claude/skills/hailer-api/references/datasets.md +0 -437
  106. package/.claude/skills/hailer-api/references/files.md +0 -301
  107. package/.claude/skills/hailer-api/references/insights.md +0 -469
  108. package/.claude/skills/hailer-api/references/workflows.md +0 -720
  109. package/.claude/skills/hailer-api/references/workspaces-users.md +0 -445
  110. package/.claude/skills/hailer-app-builder/SKILL.md +0 -340
  111. package/.claude/skills/mcp-tools/SKILL.md +0 -419
  112. package/.claude/skills/mcp-tools/references/api-endpoints.md +0 -499
  113. package/.claude/skills/mcp-tools/references/data-structures.md +0 -554
  114. package/.claude/skills/mcp-tools/references/implementation-patterns.md +0 -717
  115. package/.claude/skills/skill-testing/README.md +0 -137
  116. package/.claude/skills/skill-testing/SKILL.md +0 -348
  117. package/.claude/skills/skill-testing/references/test-patterns.md +0 -705
  118. package/.claude/skills/skill-testing/references/testing-guide.md +0 -603
  119. package/.claude/skills/skill-testing/references/validation-checklist.md +0 -537
  120. package/.claude/skills/spawn-app-builder/SKILL.md +0 -366
  121. package/.claude/skills/tool-builder/SKILL.md +0 -328
  122. package/tsconfig.json +0 -23
@@ -1,1314 +0,0 @@
1
- ---
2
- name: scaffold-hailer-app-skill
3
- description: Complete guide to ONE-SHOT Hailer app creation - scaffolds project, creates dev app, shares with workspace, and starts dev server all in one command
4
- ---
5
-
6
- # Scaffold Hailer App Skill (ONE-SHOT SETUP)
7
-
8
- Complete guide to using the `scaffold_hailer_app` tool - a ONE-SHOT solution that scaffolds your project, creates the dev app entry in Hailer, shares it with your workspace, updates manifest.json, and starts the dev server automatically.
9
-
10
- ---
11
-
12
- ## ⚠️ MANDATORY: SPAWN BUILDER AGENT AFTER SCAFFOLDING
13
-
14
- **THIS IS NOT OPTIONAL.** After `scaffold_hailer_app` completes successfully, you MUST:
15
-
16
- 1. **IMMEDIATELY spawn the app builder agent** using the Task tool
17
- 2. **DO NOT** start building components in the current session
18
- 3. **DO NOT** skip this step
19
-
20
- ### Why This Is Required
21
-
22
- - The builder agent has **isolated context** for focused work
23
- - It's **pre-loaded with TypeScript + SDK patterns**
24
- - Building in main session leads to **context overflow** and **mistakes**
25
- - The agent produces **higher quality code**
26
-
27
- ### Exact Steps After Scaffold Succeeds
28
-
29
- ```javascript
30
- // Step 1: Get workflow context (REQUIRED)
31
- list_workflows_minimal()
32
-
33
- // Step 2: Spawn the builder agent with Task tool
34
- Task({
35
- subagent_type: "general-purpose",
36
- description: "Build Hailer app components",
37
- prompt: `You are building a Hailer app.
38
-
39
- PROJECT: <project-path>
40
- DESCRIPTION: <from scaffold description>
41
- WORKFLOWS: <paste list_workflows_minimal output>
42
-
43
- Load these skills FIRST:
44
- 1. Skill("building-hailer-apps-skill")
45
- 2. Skill("hailer-app-builder")
46
-
47
- Then build the app components following the patterns in those skills.
48
-
49
- Requirements:
50
- - Use Chakra UI for components
51
- - Follow TypeScript strict mode
52
- - Use hailer.activity.list(workflowId, phaseId, options) - 3 params
53
- - Access fields via activity.fields?.[fieldId]
54
- - Build full CRUD: list, create, edit, delete
55
- `
56
- })
57
- ```
58
-
59
- ### DO NOT PROCEED WITHOUT SPAWNING
60
-
61
- If you find yourself writing React components after scaffolding WITHOUT spawning an agent first, **STOP** and spawn the agent.
62
-
63
- ---
64
-
65
- ## Table of Contents
66
- - [Quick Reference](#quick-reference)
67
- - [Overview](#overview)
68
- - [What's Different: One-Shot Setup](#whats-different-one-shot-setup)
69
- - [Core Concepts](#core-concepts)
70
- - [Available Templates](#available-templates)
71
- - [Basic Usage](#basic-usage)
72
- - [Common Scenarios](#common-scenarios)
73
- - [Best Practices](#best-practices)
74
- - [Troubleshooting](#troubleshooting)
75
- - [Advanced Options](#advanced-options)
76
- - [Additional Resources](#additional-resources)
77
-
78
- ## Quick Reference
79
-
80
- ### Create app with one command (recommended)
81
- ```javascript
82
- scaffold_hailer_app({
83
- projectName: "task-manager",
84
- template: "react-ts",
85
- description: "Task management application"
86
- })
87
- // ✅ Project scaffolded
88
- // ✅ Dependencies installed
89
- // ✅ Dev app created in Hailer
90
- // ✅ App shared with workspace
91
- // ✅ manifest.json configured
92
- // ✅ Dev server started on port 3000
93
- // 🎉 App ready to open in Hailer!
94
- ```
95
-
96
- ### Minimal one-shot setup
97
- ```javascript
98
- scaffold_hailer_app({
99
- projectName: "my-app",
100
- template: "react-ts"
101
- })
102
- // Everything done automatically!
103
- ```
104
-
105
- ### Fast builds with SWC
106
- ```javascript
107
- scaffold_hailer_app({
108
- projectName: "enterprise-app",
109
- template: "react-swc-ts",
110
- description: "Enterprise dashboard with fast builds"
111
- })
112
- ```
113
-
114
- ### Simple vanilla app
115
- ```javascript
116
- scaffold_hailer_app({
117
- projectName: "quick-tool",
118
- template: "vanilla",
119
- description: "Lightweight utility"
120
- })
121
- ```
122
-
123
- ### Custom options
124
- ```javascript
125
- scaffold_hailer_app({
126
- projectName: "analytics-dashboard",
127
- template: "react-ts",
128
- description: "Analytics and reporting dashboard",
129
- targetDirectory: "/path/to/projects",
130
- autoCreateDevApp: true, // Create dev app (default)
131
- autoShareWithWorkspace: true, // Share with workspace (default)
132
- autoStartDevServer: true, // Start dev server (default)
133
- installDependencies: true // Install npm packages (default)
134
- })
135
- ```
136
-
137
- ## Overview
138
-
139
- The `scaffold_hailer_app` tool is a **ONE-SHOT SOLUTION** that handles the entire app setup process automatically:
140
-
141
- **What happens in ONE command:**
142
- 1. ✅ Scaffolds project from official template
143
- 2. ✅ Installs all npm dependencies
144
- 3. ✅ Configures CORS in vite.config.ts for Hailer access
145
- 4. ✅ Creates dev app entry in Hailer (pointing to localhost:3000)
146
- 5. ✅ Shares app with entire workspace
147
- 6. ✅ Updates manifest.json with app ID
148
- 7. ✅ Starts dev server in background on port 3000
149
- 8. ✅ **App immediately ready to open in Hailer!**
150
-
151
- **Requirements:**
152
- - Node.js 18+ installed
153
- - npm available in PATH
154
- - Write permissions in target directory
155
- - Internet connection
156
- - Active Hailer workspace
157
-
158
- **Time savings:**
159
- - **Before:** 7 manual steps (~5-10 minutes)
160
- - **After:** 1 command (~1-2 minutes)
161
-
162
- ## What's Different: One-Shot Setup
163
-
164
- ### Old Way (Manual - 7 Steps)
165
- ```javascript
166
- // Step 1: Scaffold
167
- scaffold_hailer_app({ projectName: "my-app", template: "react-ts" })
168
-
169
- // Step 2: Navigate
170
- // cd my-app
171
-
172
- // Step 3: Install dependencies
173
- // npm install
174
-
175
- // Step 4: Start dev server
176
- // npm run dev
177
-
178
- // Step 5: Create dev app in Hailer
179
- create_app({ name: "My App (Dev)", url: "http://localhost:3000" })
180
-
181
- // Step 6: Update manifest.json with app ID
182
- // (manually edit file)
183
-
184
- // Step 7: Share with workspace
185
- add_app_member({ appId: "xxx", member: "network_xxx" })
186
- ```
187
-
188
- ### New Way (ONE-SHOT - 1 Step)
189
- ```javascript
190
- scaffold_hailer_app({
191
- projectName: "my-app",
192
- template: "react-ts",
193
- description: "My awesome app"
194
- })
195
- // Done! App ready to open in Hailer immediately! 🎉
196
- ```
197
-
198
- ### What Gets Automated
199
-
200
- | Step | Manual Approach | One-Shot Approach |
201
- |------|-----------------|-------------------|
202
- | **Scaffold project** | ✅ Manual command | ✅ Automatic |
203
- | **Install dependencies** | ⏱️ Run `npm install` | ✅ Automatic |
204
- | **Configure CORS** | ⏱️ Edit vite.config.ts | ✅ Automatic |
205
- | **Create dev app** | ⏱️ Call `create_app` tool | ✅ Automatic |
206
- | **Share with workspace** | ⏱️ Call `add_app_member` | ✅ Automatic |
207
- | **Update manifest** | ⏱️ Edit file manually | ✅ Automatic |
208
- | **Start dev server** | ⏱️ Run `npm run dev` | ✅ Automatic |
209
- | **Total time** | ~5-10 minutes | ~1-2 minutes |
210
- | **Commands needed** | 6+ commands | **1 command** |
211
-
212
- ## Core Concepts
213
-
214
- ### Templates
215
-
216
- Three official templates are available:
217
-
218
- | Template | Technology | Use Case | Build Speed |
219
- |----------|-----------|----------|-------------|
220
- | **react-ts** | React + TypeScript | Production apps, recommended | Standard |
221
- | **react-swc-ts** | React + SWC + TypeScript | Large apps needing fast builds | Fast |
222
- | **vanilla** | Vanilla JS/TS | Simple apps, learning | Fast |
223
-
224
- ### One-Shot Parameters
225
-
226
- **Required:**
227
- - `projectName` - Project folder name
228
- - `template` - "react-ts", "react-swc-ts", or "vanilla"
229
-
230
- **Optional:**
231
- - `description` - App description shown in Hailer
232
- - `targetDirectory` - Custom location (defaults to current directory)
233
- - `autoCreateDevApp` - Create dev app entry (default: true)
234
- - `autoShareWithWorkspace` - Share with workspace (default: true)
235
- - `autoStartDevServer` - Start dev server (default: true)
236
- - `installDependencies` - Install npm packages (default: true)
237
-
238
- ### What Gets Created
239
-
240
- ```
241
- project-name/
242
- ├── src/ # Source code
243
- ├── public/ # Static assets
244
- │ └── manifest.json # ✅ Auto-configured with app ID
245
- ├── vite.config.ts # Vite configuration
246
- ├── tsconfig.json # TypeScript configuration
247
- ├── package.json # Dependencies and scripts
248
- └── node_modules/ # ✅ Auto-installed dependencies
249
- ```
250
-
251
- **Plus:**
252
- - ✅ Dev app entry in Hailer
253
- - ✅ App shared with workspace
254
- - ✅ Dev server running in background
255
-
256
- ## Available Templates
257
-
258
- ### react-ts (Recommended)
259
-
260
- **Best for:**
261
- - Production applications
262
- - Teams familiar with React
263
- - Most use cases
264
-
265
- **Example:**
266
- ```javascript
267
- scaffold_hailer_app({
268
- projectName: "customer-portal",
269
- template: "react-ts",
270
- description: "Customer management portal"
271
- })
272
- ```
273
-
274
- ### react-swc-ts (High Performance)
275
-
276
- **Best for:**
277
- - Large applications
278
- - Fast build times (2-10x faster)
279
- - Enterprise apps
280
-
281
- **Example:**
282
- ```javascript
283
- scaffold_hailer_app({
284
- projectName: "enterprise-dashboard",
285
- template: "react-swc-ts",
286
- description: "Enterprise analytics dashboard"
287
- })
288
- ```
289
-
290
- ### vanilla (Lightweight)
291
-
292
- **Best for:**
293
- - Simple utilities
294
- - Learning Hailer development
295
- - Minimal dependencies
296
-
297
- **Example:**
298
- ```javascript
299
- scaffold_hailer_app({
300
- projectName: "quick-report",
301
- template: "vanilla",
302
- description: "Quick reporting tool"
303
- })
304
- ```
305
-
306
- ## Basic Usage
307
-
308
- ### Complete Setup in One Command
309
-
310
- ```javascript
311
- scaffold_hailer_app({
312
- projectName: "sales-dashboard",
313
- template: "react-ts",
314
- description: "Sales analytics and reporting"
315
- })
316
- ```
317
-
318
- **Output:**
319
- ```
320
- 🚀 ONE-SHOT HAILER APP SETUP
321
-
322
- Project: sales-dashboard
323
- Template: react-ts
324
- Location: /current/directory/sales-dashboard
325
-
326
- ⏳ Step 1/7: Creating project from template...
327
- ✅ Project scaffolded
328
-
329
- ⏳ Step 2/7: Installing dependencies...
330
- ✅ Dependencies installed
331
-
332
- ⏳ Step 3/7: Creating dev app entry in Hailer...
333
- ✅ App created: 691ed3fa98ebad373bbe98de
334
- URL: http://localhost:3000
335
-
336
- ⏳ Step 4/7: Sharing app with workspace...
337
- ✅ App shared with entire workspace
338
-
339
- ⏳ Step 5/7: Updating manifest.json with app ID...
340
- ✅ manifest.json updated with appId
341
-
342
- ⏳ Step 6/7: Starting dev server on port 3000...
343
- ✅ Dev server started in background
344
- PID: 12345
345
- URL: http://localhost:3000
346
-
347
- ✅ Step 7/7: Setup Complete!
348
-
349
- ## 🎉 Your Hailer App is Ready!
350
-
351
- **What was done:**
352
- - ✅ Project scaffolded from react-ts template
353
- - ✅ Dependencies installed
354
- - ✅ Dev app entry created in Hailer (ID: 691ed3fa98ebad373bbe98de)
355
- - ✅ App shared with entire workspace
356
- - ✅ manifest.json configured with app ID
357
- - ✅ Dev server started on http://localhost:3000
358
-
359
- ## 🚀 Next Steps
360
-
361
- 1. **Open the app in Hailer** - Look for "sales-dashboard" in your apps menu
362
- 2. **Start coding** - Files in /path/to/sales-dashboard/src will hot-reload
363
- 3. **View logs** - Check dev server output if needed
364
-
365
- ## 🔗 App Info
366
-
367
- - **App ID:** 691ed3fa98ebad373bbe98de
368
- - **Dev URL:** http://localhost:3000
369
- - **Shared with:** Entire workspace
370
- ```
371
-
372
- ### That's It!
373
-
374
- Just open the app in Hailer and start coding. All setup is done automatically.
375
-
376
- ## Common Scenarios
377
-
378
- ### Scenario 1: Quick Dashboard App
379
-
380
- ```javascript
381
- // One command, ready immediately
382
- scaffold_hailer_app({
383
- projectName: "analytics-dashboard",
384
- template: "react-ts",
385
- description: "Analytics and metrics dashboard"
386
- })
387
-
388
- // Open app in Hailer and start coding!
389
- ```
390
-
391
- ### Scenario 2: Enterprise App with Fast Builds
392
-
393
- ```javascript
394
- scaffold_hailer_app({
395
- projectName: "enterprise-crm",
396
- template: "react-swc-ts",
397
- description: "Enterprise CRM system"
398
- })
399
-
400
- // SWC provides 2-10x faster builds automatically
401
- ```
402
-
403
- ### Scenario 3: Simple Utility
404
-
405
- ```javascript
406
- scaffold_hailer_app({
407
- projectName: "csv-exporter",
408
- template: "vanilla",
409
- description: "CSV export utility"
410
- })
411
-
412
- // Lightweight app ready immediately
413
- ```
414
-
415
- ### Scenario 4: Multiple Apps in Directory
416
-
417
- ```javascript
418
- // All apps in dedicated directory
419
- scaffold_hailer_app({
420
- projectName: "app-one",
421
- template: "react-ts",
422
- description: "First application",
423
- targetDirectory: "/home/user/hailer-apps"
424
- })
425
-
426
- scaffold_hailer_app({
427
- projectName: "app-two",
428
- template: "react-swc-ts",
429
- description: "Second application",
430
- targetDirectory: "/home/user/hailer-apps"
431
- })
432
-
433
- // Result:
434
- // /home/user/hailer-apps/
435
- // app-one/ (running on port 3000, first one)
436
- // app-two/ (needs manual start on different port)
437
- ```
438
-
439
- ### Scenario 5: Custom Automation Options
440
-
441
- ```javascript
442
- // Control what gets automated
443
- scaffold_hailer_app({
444
- projectName: "custom-app",
445
- template: "react-ts",
446
- description: "Custom configuration",
447
- autoCreateDevApp: true, // Create dev app
448
- autoShareWithWorkspace: false, // Don't share (dev only)
449
- autoStartDevServer: false, // Start manually later
450
- installDependencies: true // Install packages
451
- })
452
-
453
- // Dev app created but not shared, server not started
454
- // Good for testing before sharing
455
- ```
456
-
457
- ## Best Practices
458
-
459
- ### 1. Use Descriptive Names and Descriptions
460
-
461
- ```javascript
462
- // ❌ Bad: Generic, no description
463
- scaffold_hailer_app({
464
- projectName: "app1",
465
- template: "react-ts"
466
- })
467
-
468
- // ✅ Good: Clear name and description
469
- scaffold_hailer_app({
470
- projectName: "customer-feedback-dashboard",
471
- template: "react-ts",
472
- description: "Customer feedback collection and analysis"
473
- })
474
- ```
475
-
476
- ### 2. Let Automation Handle Setup
477
-
478
- ```javascript
479
- // ✅ Recommended: Use defaults (everything automatic)
480
- scaffold_hailer_app({
481
- projectName: "my-app",
482
- template: "react-ts",
483
- description: "My application"
484
- })
485
-
486
- // Only disable automation for specific reasons:
487
- scaffold_hailer_app({
488
- projectName: "team-only-app",
489
- template: "react-ts",
490
- description: "Team-specific tool",
491
- autoShareWithWorkspace: false // Don't share publicly
492
- })
493
- ```
494
-
495
- ### 3. Choose Appropriate Template
496
-
497
- Decision tree:
498
- ```
499
- Is this a complex UI app?
500
- ├─ Yes → Is performance critical?
501
- │ ├─ Yes → Use react-swc-ts (fastest)
502
- │ └─ No → Use react-ts (recommended)
503
- └─ No → Use vanilla (simple)
504
- ```
505
-
506
- ### 4. Organize Multiple Apps
507
-
508
- ```javascript
509
- // Consistent directory structure
510
- const appsDir = "/home/user/workspace/hailer-apps";
511
-
512
- scaffold_hailer_app({
513
- projectName: "customer-portal",
514
- template: "react-ts",
515
- description: "Customer portal",
516
- targetDirectory: appsDir
517
- })
518
-
519
- scaffold_hailer_app({
520
- projectName: "admin-dashboard",
521
- template: "react-swc-ts",
522
- description: "Admin dashboard",
523
- targetDirectory: appsDir
524
- })
525
- ```
526
-
527
- ### 5. Start Coding Immediately
528
-
529
- ```javascript
530
- // 1. Run one command
531
- scaffold_hailer_app({
532
- projectName: "my-app",
533
- template: "react-ts",
534
- description: "My awesome app"
535
- })
536
-
537
- // 2. Open app in Hailer (find in apps menu)
538
-
539
- // 3. Edit code in my-app/src/
540
- // Changes appear live in Hailer!
541
-
542
- // No manual setup needed!
543
- ```
544
-
545
- ## Troubleshooting
546
-
547
- ### Error: "Directory Already Exists"
548
-
549
- **Solution:**
550
- ```javascript
551
- // Choose different name
552
- scaffold_hailer_app({
553
- projectName: "my-app-v2", // Different name
554
- template: "react-ts",
555
- description: "My app (version 2)"
556
- })
557
-
558
- // Or use different directory
559
- scaffold_hailer_app({
560
- projectName: "my-app",
561
- template: "react-ts",
562
- description: "My app",
563
- targetDirectory: "/different/path"
564
- })
565
- ```
566
-
567
- ### Error: "Workspace cache not available"
568
-
569
- **Problem:** Not connected to Hailer workspace.
570
-
571
- **Solution:**
572
- 1. Verify Hailer connection
573
- 2. Check .env.local credentials
574
- 3. Restart MCP server if needed
575
-
576
- ### Error: "Failed to create app in Hailer"
577
-
578
- **Problem:** Permission or API issue.
579
-
580
- **Solution:**
581
- ```javascript
582
- // Disable automatic app creation
583
- scaffold_hailer_app({
584
- projectName: "my-app",
585
- template: "react-ts",
586
- autoCreateDevApp: false // Skip app creation
587
- })
588
-
589
- // Create app manually later:
590
- create_app({
591
- name: "my-app",
592
- url: "http://localhost:3000"
593
- })
594
- ```
595
-
596
- ### Port 3000 Already in Use
597
-
598
- **Problem:** Dev server can't start on port 3000.
599
-
600
- **Solution:**
601
- 1. First app gets port 3000 automatically
602
- 2. Additional apps: start manually on different ports
603
- 3. Or stop existing server first
604
-
605
- ```bash
606
- # Manual start on different port
607
- cd my-app
608
- PORT=3001 npm run dev
609
-
610
- # Then update app URL:
611
- update_app({
612
- appId: "xxx",
613
- name: "My App",
614
- url: "http://localhost:3001"
615
- })
616
- ```
617
-
618
- ### Dependencies Fail to Install
619
-
620
- **Workaround:**
621
- Project still created successfully. Install manually:
622
- ```bash
623
- cd my-app
624
- npm install
625
- npm run dev
626
- ```
627
-
628
- ### Dev Server Fails to Start
629
-
630
- **Problem:** Background server didn't start.
631
-
632
- **Solution:**
633
- Start manually:
634
- ```bash
635
- cd my-app
636
- npm run dev
637
- ```
638
-
639
- App is already created in Hailer, just needs server running.
640
-
641
- ### Infinite Loop When Loading Data
642
-
643
- **Problem:** App keeps re-fetching data infinitely, causing performance issues.
644
-
645
- **Cause:** Using `hailer` object in useEffect dependencies. The `hailer` object from `useHailer()` changes reference on every render.
646
-
647
- **Solution:**
648
- ```typescript
649
- // ❌ WRONG - causes infinite loop
650
- useEffect(() => {
651
- if (!hailer) return;
652
- hailer.activity.list(...);
653
- }, [hailer]); // hailer changes every render!
654
-
655
- // ✅ CORRECT - use `inside` and access hailer from window
656
- useEffect(() => {
657
- if (!inside) return;
658
- const hailer = (window as any).hailerApiInstance;
659
- if (!hailer) return;
660
- hailer.activity.list(...);
661
- }, [inside]); // inside is a stable boolean
662
- ```
663
-
664
- ### Chakra UI Table Not Showing Text
665
-
666
- **Problem:** Table rows render but text is invisible/white.
667
-
668
- **Cause:** CSS inheritance issues when running inside Hailer iframe.
669
-
670
- **Solution:** Add explicit `color="black"` to Td components:
671
- ```typescript
672
- <Tr key={activity._id} bg="white">
673
- <Td color="black">{value}</Td>
674
- </Tr>
675
- ```
676
-
677
- ### CORS Error When Opening App in Hailer
678
-
679
- **Problem:** Browser console shows "Access to fetch at 'http://localhost:3000/manifest.json' from origin 'https://next.hailer.com' has been blocked by CORS policy"
680
-
681
- **Solution:**
682
- The `scaffold_hailer_app` tool automatically configures CORS in vite.config.ts. If you scaffolded the app manually or CORS is not working:
683
-
684
- ```typescript
685
- // vite.config.ts
686
- import { defineConfig } from 'vite'
687
- import react from '@vitejs/plugin-react'
688
- import dns from 'dns'
689
-
690
- dns.setDefaultResultOrder('verbatim');
691
-
692
- export default defineConfig({
693
- plugins: [react()],
694
- base: '',
695
- server: {
696
- port: 3000,
697
- cors: {
698
- origin: '*', // Allow all origins
699
- credentials: true // Allow credentials
700
- }
701
- },
702
- })
703
- ```
704
-
705
- **Why this is needed:**
706
- - Hailer loads your app from `https://next.hailer.com` (or your Hailer domain)
707
- - Your dev server runs on `http://localhost:3000`
708
- - Without CORS configuration, browsers block cross-origin requests
709
- - The CORS config allows Hailer to fetch your app's manifest.json and assets
710
-
711
- **Note:** The scaffold tool now automatically adds this configuration, so new apps should work immediately!
712
-
713
- ## Advanced Options
714
-
715
- ### Minimal Automation
716
-
717
- ```javascript
718
- // Just scaffold project
719
- scaffold_hailer_app({
720
- projectName: "my-app",
721
- template: "react-ts",
722
- installDependencies: false,
723
- autoCreateDevApp: false,
724
- autoStartDevServer: false
725
- })
726
-
727
- // Then do manual setup as needed
728
- ```
729
-
730
- ### Dev-Only Setup (Not Shared)
731
-
732
- ```javascript
733
- // Create app but don't share
734
- scaffold_hailer_app({
735
- projectName: "experimental-app",
736
- template: "react-ts",
737
- description: "Experimental features",
738
- autoShareWithWorkspace: false // Only visible to you
739
- })
740
-
741
- // Share later when ready:
742
- add_app_member({
743
- appId: "xxx",
744
- member: "network_workspace-id"
745
- })
746
- ```
747
-
748
- ### Custom Target Directory
749
-
750
- ```javascript
751
- // Use environment variable or custom path
752
- scaffold_hailer_app({
753
- projectName: "my-app",
754
- template: "react-ts",
755
- description: "My app",
756
- targetDirectory: process.env.DEV_APPS_PATH || "/custom/path"
757
- })
758
- ```
759
-
760
- ## Hailer SDK API Reference
761
-
762
- ### Critical: Correct API Usage
763
-
764
- When developing Hailer apps, you MUST use the correct Hailer SDK API patterns:
765
-
766
- #### ✅ CORRECT: Activity API
767
-
768
- ```typescript
769
- // ✅ Use hailer.activity (SINGULAR)
770
- const activities = await hailer.activity.list(
771
- processId, // First parameter: workflow ID
772
- phaseId, // Second parameter: phase ID
773
- options // Third parameter: options object
774
- );
775
-
776
- // Example with generic IDs (replace with actual IDs from your workspace)
777
- const activities = await hailer.activity.list(
778
- workflowId, // Get from list_workflows_minimal() or hailer.workflow.list()
779
- phaseId, // Get from hailer.workflow.get(workflowId).phases
780
- {
781
- sortBy: 'created',
782
- sortOrder: 'asc',
783
- limit: 20
784
- }
785
- );
786
- ```
787
-
788
- #### ❌ WRONG: Common Mistakes
789
-
790
- ```typescript
791
- // ❌ WRONG: Using 'activities' (plural)
792
- const result = await hailer.activities.list({ ... }) // activities is undefined!
793
-
794
- // ❌ WRONG: Single object parameter
795
- const activities = await hailer.activity.list({
796
- workflowId: 'xxx',
797
- phaseId: 'yyy'
798
- }) // Wrong signature!
799
-
800
- // ❌ WRONG: Accessing fields directly
801
- match.opponent // undefined!
802
- match.matchDate // undefined!
803
- ```
804
-
805
- ### Activity Data Structure
806
-
807
- Activities have a specific structure - custom fields are in the `fields` object:
808
-
809
- ```typescript
810
- interface Activity {
811
- _id: string; // Activity ID
812
- name: string; // Activity name/title
813
- process: string; // Workflow ID
814
- currentPhase: string; // Phase ID
815
- created: number; // Timestamp
816
- updated?: number; // Timestamp
817
- fields?: { // ✅ Custom fields are here!
818
- [fieldKey: string]: any
819
- };
820
- }
821
- ```
822
-
823
- #### ✅ CORRECT: Accessing Custom Fields
824
-
825
- ```typescript
826
- // ✅ Access via fields object
827
- const opponent = match.fields?.opponent;
828
- const matchDate = match.fields?.matchDate;
829
- const competition = match.fields?.competition;
830
-
831
- // ✅ Display with fallbacks
832
- <span>{match.fields?.opponent?.name || match.name}</span>
833
- ```
834
-
835
- #### ❌ WRONG: Direct Field Access
836
-
837
- ```typescript
838
- // ❌ These will be undefined!
839
- const opponent = match.opponent; // undefined
840
- const matchDate = match.matchDate; // undefined
841
- const competition = match.competition; // undefined
842
- ```
843
-
844
- ### Complete Working Example
845
-
846
- **⚠️ CRITICAL: Do NOT use `hailer` in useEffect dependencies - it causes infinite loops!**
847
-
848
- ```typescript
849
- import { useEffect, useState, useRef } from 'react';
850
- import useHailer from './hailer/use-hailer';
851
-
852
- // Define your activity interface based on workflow fields
853
- interface Activity {
854
- _id: string;
855
- name: string;
856
- fields?: {
857
- [fieldId: string]: { type: string; value: unknown }; // Fields have type and value
858
- };
859
- }
860
-
861
- interface Props {
862
- workflowId: string;
863
- phaseId: string;
864
- }
865
-
866
- export default function ActivityList({ workflowId, phaseId }: Props) {
867
- const { hailer, inside } = useHailer();
868
- const [activities, setActivities] = useState<Activity[]>([]);
869
- const [loading, setLoading] = useState(true);
870
- const loadedRef = useRef(false);
871
-
872
- useEffect(() => {
873
- // ✅ Use `inside` as trigger - it's stable
874
- if (!inside) return;
875
- if (loadedRef.current) return;
876
-
877
- // ✅ Access hailer from window to avoid reference changes
878
- const hailerApi = (window as any).hailerApiInstance;
879
- if (!hailerApi) return;
880
-
881
- async function fetchActivities() {
882
- try {
883
- // ✅ CORRECT: activity.list with separate parameters
884
- const result = await hailerApi.activity.list(
885
- workflowId,
886
- phaseId,
887
- {
888
- sortBy: 'created',
889
- sortOrder: 'asc',
890
- limit: 50
891
- }
892
- );
893
-
894
- setActivities(result || []);
895
- loadedRef.current = true;
896
- } catch (err) {
897
- console.error('Failed to fetch:', err);
898
- } finally {
899
- setLoading(false);
900
- }
901
- }
902
-
903
- fetchActivities();
904
- }, [inside, workflowId, phaseId]); // ✅ NO hailer in deps!
905
-
906
- if (loading) return <div>Loading...</div>;
907
-
908
- return (
909
- <div>
910
- {activities.map((activity) => (
911
- <div key={activity._id}>
912
- <h3>{activity.name}</h3>
913
- {/* Access fields: activity.fields?.[fieldId]?.value */}
914
- </div>
915
- ))}
916
- </div>
917
- );
918
- }
919
- ```
920
-
921
- ### Other Hailer SDK APIs
922
-
923
- #### Activity Operations
924
-
925
- ```typescript
926
- // Get single activity
927
- const activity = await hailer.activity.get(activityId);
928
-
929
- // Create activities
930
- const created = await hailer.activity.create(
931
- processId,
932
- [
933
- { name: 'Activity 1', fields: { status: 'Active' } },
934
- { name: 'Activity 2', fields: { status: 'Pending' } }
935
- ]
936
- );
937
-
938
- // Update activities
939
- await hailer.activity.update(
940
- [
941
- { _id: 'xxx', fields: { status: 'Completed' } },
942
- { _id: 'yyy', name: 'New Name' }
943
- ],
944
- {} // options
945
- );
946
-
947
- // Remove activities
948
- await hailer.activity.remove(['activity-id-1', 'activity-id-2']);
949
- ```
950
-
951
- #### Workflow Operations
952
-
953
- ```typescript
954
- // Get workflow with fields and phases
955
- const workflow = await hailer.workflow.get(workflowId);
956
- // workflow.fields = { fieldId: { label, type, key, ... } }
957
- // workflow.phases = { phaseId: { name, fields: [...] } }
958
-
959
- // List all workflows
960
- const workflows = await hailer.workflow.list();
961
- ```
962
-
963
- #### User Operations
964
-
965
- ```typescript
966
- // Get current user
967
- const user = await hailer.user.getCurrent();
968
-
969
- // Get workspace info
970
- const workspace = await hailer.workspace.get();
971
- ```
972
-
973
- ### Common Patterns
974
-
975
- #### Pattern 1: List Activities with Filtering
976
-
977
- ```typescript
978
- const activities = await hailer.activity.list(
979
- workflowId,
980
- phaseId,
981
- {
982
- sortBy: 'created',
983
- sortOrder: 'desc',
984
- limit: 50,
985
- filters: {
986
- // Custom filters based on field IDs
987
- fieldId: { operator: 'equals', value: 'someValue' }
988
- }
989
- }
990
- );
991
- ```
992
-
993
- #### Pattern 2: Display Activity with Custom Fields
994
-
995
- ```typescript
996
- function ActivityCard({ activity }: { activity: Activity }) {
997
- return (
998
- <div>
999
- <h3>{activity.name}</h3>
1000
- {/* Access custom fields via fields object */}
1001
- <p>Status: {activity.fields?.status}</p>
1002
- <p>Priority: {activity.fields?.priority}</p>
1003
- <p>Due Date: {formatDate(activity.fields?.dueDate)}</p>
1004
- </div>
1005
- );
1006
- }
1007
- ```
1008
-
1009
- #### Pattern 3: Handle ActivityLink Fields
1010
-
1011
- ```typescript
1012
- // ActivityLink fields are objects with _id and name
1013
- const linkedActivity = activity.fields?.linkedField;
1014
-
1015
- if (linkedActivity) {
1016
- console.log(linkedActivity._id); // Activity ID
1017
- console.log(linkedActivity.name); // Activity name
1018
- }
1019
- ```
1020
-
1021
- ### TypeScript Types
1022
-
1023
- For better type safety, extend the Activity interface:
1024
-
1025
- ```typescript
1026
- interface CustomActivity extends Activity {
1027
- fields?: {
1028
- status?: string;
1029
- priority?: string;
1030
- dueDate?: number;
1031
- assignedTo?: { _id: string; name: string };
1032
- relatedActivity?: { _id: string; name: string };
1033
- };
1034
- }
1035
- ```
1036
-
1037
- ### Key Takeaways
1038
-
1039
- 1. **Always use `hailer.activity` (singular), never `hailer.activities`**
1040
- 2. **Pass parameters separately**: `list(processId, phaseId, options)`
1041
- 3. **Access custom fields via `activity.fields?.fieldName`**
1042
- 4. **ActivityLink fields are objects with `_id` and `name` properties**
1043
- 5. **Use optional chaining (`?.`) to safely access nested fields**
1044
-
1045
- ## Additional Resources
1046
-
1047
- ### Related Skills
1048
- - **create-app-skill** - Create Hailer app entries (now automatic!)
1049
- - **publish-hailer-app-skill** - Deploy apps to production
1050
- - **add-app-member-skill** - Share apps with users (now automatic!)
1051
- - **list-apps-skill** - View and manage apps
1052
-
1053
- ### Related Tools
1054
- - `create_app` - Create app entry (now automatic!)
1055
- - `publish_hailer_app` - Deploy to production
1056
- - `add_app_member` - Share access (now automatic!)
1057
- - `update_app` - Modify app properties
1058
- - `list_apps` - View all workspace apps
1059
-
1060
- ### Key Improvements
1061
-
1062
- **Before (Manual):**
1063
- - 7 separate steps
1064
- - 5-10 minutes
1065
- - Error-prone
1066
- - Easy to forget steps
1067
-
1068
- **After (One-Shot):**
1069
- - 1 command
1070
- - 1-2 minutes
1071
- - Automated
1072
- - Nothing to forget!
1073
-
1074
- ### Template Comparison
1075
-
1076
- | Feature | react-ts | react-swc-ts | vanilla |
1077
- |---------|----------|--------------|---------|
1078
- | **Framework** | React 18 | React 18 | None |
1079
- | **TypeScript** | ✅ Yes | ✅ Yes | ✅ Yes |
1080
- | **Compiler** | Babel/esbuild | SWC (Rust) | esbuild |
1081
- | **Build Speed** | Standard | 2-10x faster | Fast |
1082
- | **Bundle Size** | ~150KB | ~150KB | ~10KB |
1083
- | **Best For** | Most apps | Large apps | Simple apps |
1084
-
1085
- ### Complete Workflow
1086
-
1087
- **Development:**
1088
- ```javascript
1089
- // 1. Create app (one command!)
1090
- scaffold_hailer_app({
1091
- projectName: "my-app",
1092
- template: "react-ts",
1093
- description: "My application"
1094
- })
1095
-
1096
- // 2. Open in Hailer and start coding
1097
- // App already running, shared, configured!
1098
-
1099
- // 3. Edit files in my-app/src/
1100
- // Changes appear live
1101
-
1102
- // 4. When ready, publish
1103
- publish_hailer_app({
1104
- email: "user@example.com",
1105
- password: "password",
1106
- projectDirectory: "./my-app"
1107
- })
1108
- ```
1109
-
1110
- That's it! The one-shot approach eliminates all manual setup steps.
1111
-
1112
- ---
1113
-
1114
- ## Next Steps: SPAWN THE BUILDER AGENT (MANDATORY)
1115
-
1116
- **⚠️ DO NOT BUILD IN CURRENT SESSION.** After scaffolding completes:
1117
-
1118
- ### Step 1: Get Workflow Context
1119
-
1120
- ```javascript
1121
- list_workflows_minimal()
1122
- ```
1123
-
1124
- ### Step 2: Spawn the Builder Agent
1125
-
1126
- ```javascript
1127
- Task({
1128
- subagent_type: "general-purpose",
1129
- description: "Build Hailer app components",
1130
- prompt: `You are building a Hailer app.
1131
-
1132
- PROJECT PATH: /path/to/project
1133
- DESCRIPTION: <description from scaffold>
1134
- APP TYPE: Full CRUD application
1135
-
1136
- WORKFLOWS IN WORKSPACE:
1137
- <paste list_workflows_minimal output here>
1138
-
1139
- ## MANDATORY: Load Skills First
1140
-
1141
- Before writing ANY code, load these skills:
1142
- 1. Skill("building-hailer-apps-skill") - SDK API patterns
1143
- 2. Skill("hailer-app-builder") - TypeScript standards
1144
-
1145
- ## ⚠️ CRITICAL FIRST STEP: Fix main.tsx
1146
-
1147
- **THE TEMPLATE IS MISSING ChakraProvider!** You MUST fix this FIRST or styles won't work:
1148
-
1149
- \`\`\`typescript
1150
- // src/main.tsx - REPLACE the entire file with this:
1151
- import React from 'react'
1152
- import ReactDOM from 'react-dom/client'
1153
- import { ChakraProvider } from '@chakra-ui/react'
1154
- import App from './App.tsx'
1155
- import './index.css'
1156
-
1157
- ReactDOM.createRoot(document.getElementById('root')!).render(
1158
- <React.StrictMode>
1159
- <ChakraProvider>
1160
- <App />
1161
- </ChakraProvider>
1162
- </React.StrictMode>,
1163
- )
1164
- \`\`\`
1165
-
1166
- **If you skip this, the app will render with NO STYLES!**
1167
-
1168
- ## Data Loading Pattern (CRITICAL - PREVENTS INFINITE LOOPS)
1169
-
1170
- **⚠️ THE `hailer` OBJECT CHANGES ON EVERY RENDER!** Using `hailer` in useEffect dependencies causes infinite loops.
1171
-
1172
- Use `inside` boolean as the trigger and access hailer from window:
1173
-
1174
- \`\`\`typescript
1175
- import { useState, useEffect, useRef } from 'react';
1176
-
1177
- // Hook takes `inside` boolean, NOT hailer object
1178
- function useMyData(inside: boolean) {
1179
- const [data, setData] = useState([]);
1180
- const [loading, setLoading] = useState(true);
1181
- const [error, setError] = useState<string | null>(null);
1182
- const [refreshTrigger, setRefreshTrigger] = useState(0);
1183
- const loadedRef = useRef(false);
1184
-
1185
- useEffect(() => {
1186
- // Use `inside` as trigger - it's a stable boolean
1187
- if (!inside) return;
1188
- if (loadedRef.current && refreshTrigger === 0) return;
1189
-
1190
- // Access hailer from window to avoid reference changes
1191
- const hailer = (window as any).hailerApiInstance;
1192
- if (!hailer) return;
1193
-
1194
- async function loadData() {
1195
- try {
1196
- setLoading(true);
1197
- setError(null);
1198
-
1199
- // 3 positional params: workflowId, phaseId, options
1200
- const result = await hailer.activity.list(
1201
- WORKFLOW_ID,
1202
- PHASE_ID,
1203
- { limit: 100 }
1204
- );
1205
-
1206
- setData(result || []);
1207
- loadedRef.current = true;
1208
- } catch (err) {
1209
- setError(err instanceof Error ? err.message : 'Failed to load');
1210
- } finally {
1211
- setLoading(false);
1212
- }
1213
- }
1214
-
1215
- loadData();
1216
- }, [inside, refreshTrigger]); // ✅ inside is stable, hailer is NOT
1217
-
1218
- const refresh = () => {
1219
- loadedRef.current = false;
1220
- setRefreshTrigger(prev => prev + 1);
1221
- };
1222
-
1223
- return { data, loading, error, refresh };
1224
- }
1225
- \`\`\`
1226
-
1227
- **In App.tsx, pass `inside` not `hailer`:**
1228
- \`\`\`typescript
1229
- export default function App() {
1230
- const { hailer, inside } = useHailer();
1231
- const { data, loading, error } = useMyData(inside); // ✅ Pass inside, not hailer
1232
-
1233
- if (!hailer || !inside) {
1234
- return <Spinner />;
1235
- }
1236
- // ...
1237
- }
1238
- \`\`\`
1239
-
1240
- **KEY RULES:**
1241
- 1. ❌ NEVER use `hailer` in useEffect dependencies - causes infinite loops
1242
- 2. ✅ Use `inside` boolean as the stable trigger
1243
- 3. ✅ Access hailer via `(window as any).hailerApiInstance` inside useEffect
1244
- 4. ✅ Use `loadedRef` to prevent duplicate loads
1245
-
1246
- ## Field Access Pattern
1247
-
1248
- Fields are keyed by FIELD IDs, not readable names:
1249
-
1250
- \`\`\`typescript
1251
- // Get field IDs from get_workflow_schema() first!
1252
- const FIELDS = {
1253
- PLAYER_NAME: '691ffdf84217e9e8434e5694', // From schema
1254
- JERSEY_NUMBER: '691ffdf84217e9e8434e5695',
1255
- };
1256
-
1257
- // Helper function
1258
- function getFieldValue<T>(fields: Record<string, {value: unknown}> | undefined, fieldId: string): T | null {
1259
- return (fields?.[fieldId]?.value as T) ?? null;
1260
- }
1261
-
1262
- // Usage
1263
- const name = getFieldValue<string>(activity.fields, FIELDS.PLAYER_NAME);
1264
- \`\`\`
1265
-
1266
- ## Requirements
1267
-
1268
- Build a functional app with:
1269
- - Dashboard showing overview stats
1270
- - List view with data from workflows
1271
- - Proper error handling and loading states
1272
- - Styled with Chakra UI (AFTER fixing main.tsx!)
1273
-
1274
- ## Technical Requirements
1275
-
1276
- - Fix main.tsx with ChakraProvider FIRST
1277
- - Chakra UI components for all UI
1278
- - TypeScript strict mode (no 'any')
1279
- - hailer.activity.list(workflowId, phaseId, options) - 3 params
1280
- - Access fields via getFieldValue helper with field IDs
1281
- - Simple useEffect pattern (no useCallback/useRef for data loading)
1282
-
1283
- ## Deliverables
1284
-
1285
- 1. **FIRST**: Fix src/main.tsx with ChakraProvider
1286
- 2. Create src/constants.ts with workflow/field IDs
1287
- 3. Create src/hooks/ with data fetching hooks
1288
- 4. Create src/components/ with UI components
1289
- 5. Update src/App.tsx with the dashboard
1290
-
1291
- ## Verification
1292
-
1293
- After building, the app should:
1294
- 1. Show styled UI (not plain HTML) - confirms ChakraProvider works
1295
- 2. Load data without infinite loops - confirms useEffect pattern works
1296
- 3. Display field values correctly - confirms field access works
1297
-
1298
- Report back what was created and confirm the 3 checks above pass.
1299
- `
1300
- })
1301
- ```
1302
-
1303
- ### Why Spawn Is Required
1304
-
1305
- | Current Session | Spawned Agent |
1306
- |-----------------|---------------|
1307
- | Context gets cluttered | Clean, focused context |
1308
- | May forget patterns | Skills pre-loaded |
1309
- | Easier to make mistakes | Follows patterns strictly |
1310
- | Can't see full picture | Dedicated to this task |
1311
-
1312
- ### DO NOT Skip This Step
1313
-
1314
- If you catch yourself writing components without spawning, **STOP** and spawn the agent first.