@nebulit/embuilder 0.1.39

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 (212) hide show
  1. package/README.md +254 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +138 -0
  4. package/package.json +49 -0
  5. package/templates/.claude/hooks/QUICKSTART.md +256 -0
  6. package/templates/.claude/hooks/README.md +533 -0
  7. package/templates/.claude/hooks/analyze-commit.sh +22 -0
  8. package/templates/.claude/hooks/analyze-commit.ts +518 -0
  9. package/templates/.claude/hooks/analyzers/README.md +198 -0
  10. package/templates/.claude/hooks/analyzers/code-quality-checker.ts +154 -0
  11. package/templates/.claude/hooks/analyzers/code-quality.md +54 -0
  12. package/templates/.claude/hooks/analyzers/commit-blocker-example.ts.disabled +110 -0
  13. package/templates/.claude/hooks/analyzers/commit-policy.md +49 -0
  14. package/templates/.claude/hooks/analyzers/event-model-validator.md +49 -0
  15. package/templates/.claude/hooks/analyzers/event-model-validator.ts +169 -0
  16. package/templates/.claude/hooks/analyzers/example-logger.ts +70 -0
  17. package/templates/.claude/hooks/analyzers/slice-scope-validator.md +81 -0
  18. package/templates/.claude/hooks/check-review-result.sh +47 -0
  19. package/templates/.claude/hooks/prepare-review.sh +34 -0
  20. package/templates/.claude/hooks/review-agent-prompt.md +42 -0
  21. package/templates/.claude/hooks/run-review-agent.sh +124 -0
  22. package/templates/.claude/settings.local.json +37 -0
  23. package/templates/.claude/skills/help/README.md +84 -0
  24. package/templates/.claude/skills/help/SKILL.md +393 -0
  25. package/templates/.claude/skills/help/templates/demo-config.json +6753 -0
  26. package/templates/.claude/skills/sample-slices/SKILL.md +8 -0
  27. package/templates/.claude/skills/sample-slices/templates/.slices/Library/addbook/code-slice.json +124 -0
  28. package/templates/.claude/skills/sample-slices/templates/.slices/Library/addbook/slice.json +255 -0
  29. package/templates/.claude/skills/sample-slices/templates/.slices/Library/availablebooks/slice.json +107 -0
  30. package/templates/.claude/skills/sample-slices/templates/.slices/index.json +20 -0
  31. package/templates/.claude/skills/sample-slices/templates/Cart/additem/slice.json +979 -0
  32. package/templates/.claude/skills/sample-slices/templates/Cart/archiveitem/slice.json +529 -0
  33. package/templates/.claude/skills/sample-slices/templates/Cart/cartitems/slice.json +1072 -0
  34. package/templates/.claude/skills/sample-slices/templates/Cart/cartwithproducts/slice.json +394 -0
  35. package/templates/.claude/skills/sample-slices/templates/Cart/changedprices/slice.json +88 -0
  36. package/templates/.claude/skills/sample-slices/templates/Cart/changeinventory/slice.json +264 -0
  37. package/templates/.claude/skills/sample-slices/templates/Cart/changeprice/slice.json +308 -0
  38. package/templates/.claude/skills/sample-slices/templates/Cart/clearcart/slice.json +358 -0
  39. package/templates/.claude/skills/sample-slices/templates/Cart/inventories/slice.json +203 -0
  40. package/templates/.claude/skills/sample-slices/templates/Cart/publishcart/slice.json +876 -0
  41. package/templates/.claude/skills/sample-slices/templates/Cart/removeitem/slice.json +560 -0
  42. package/templates/.claude/skills/sample-slices/templates/Cart/submitcart/slice.json +708 -0
  43. package/templates/.claude/skills/sample-slices/templates/Cart/submittedcartdata/slice.json +399 -0
  44. package/templates/.claude/skills/sample-slices/templates/index.json +108 -0
  45. package/templates/.claude/skills/slice-automation/SKILL.md +49 -0
  46. package/templates/.claude/skills/slice-state-change/SKILL.md +369 -0
  47. package/templates/.claude/skills/slice-state-change/templates/AddLocation/AddLocation.test.ts.sample +76 -0
  48. package/templates/.claude/skills/slice-state-change/templates/AddLocation/AddLocationCommand.ts.sample +84 -0
  49. package/templates/.claude/skills/slice-state-change/templates/AddLocation/routes.ts.sample +73 -0
  50. package/templates/.claude/skills/slice-state-change/templates/README.md +46 -0
  51. package/templates/.claude/skills/slice-state-view/SKILL.md +336 -0
  52. package/templates/.claude/skills/slice-state-view/templates/Locations/Locations.test.ts.sample +84 -0
  53. package/templates/.claude/skills/slice-state-view/templates/Locations/LocationsProjection.ts.sample +50 -0
  54. package/templates/.claude/skills/slice-state-view/templates/Locations/routes.ts.sample +46 -0
  55. package/templates/.claude/skills/slice-state-view/templates/README.md +109 -0
  56. package/templates/.claude/skills/slice-state-view/templates/Tables/Tables.test.ts.sample +104 -0
  57. package/templates/.claude/skills/slice-state-view/templates/Tables/TablesProjection.ts.sample +59 -0
  58. package/templates/.claude/skills/slice-state-view/templates/Tables/routes.ts.sample +46 -0
  59. package/templates/.claude/skills/slice-state-view/templates/V2__tables.sql +7 -0
  60. package/templates/.claude/skills/slice-state-view/templates/V8__locations.sql +7 -0
  61. package/templates/.claude/skills/test-analyzer/SKILL.md +373 -0
  62. package/templates/.claude/skills/test-analyzer/examples/specification-format.md +143 -0
  63. package/templates/.claude/skills/test-analyzer/examples/state-change-example.md +111 -0
  64. package/templates/.claude/skills/test-analyzer/examples/state-view-example.md +122 -0
  65. package/templates/AGENTS.md +110 -0
  66. package/templates/Claude.md +58 -0
  67. package/templates/README.md +178 -0
  68. package/templates/backend/.env +9 -0
  69. package/templates/backend/BACKEND_AUTH_SETUP.md +183 -0
  70. package/templates/backend/SWAGGER.md +213 -0
  71. package/templates/backend/eslint.config.mjs +31 -0
  72. package/templates/backend/flyway.conf +17 -0
  73. package/templates/backend/package.json +44 -0
  74. package/templates/backend/prd.json.example +64 -0
  75. package/templates/backend/public/assets/images/banner.png +0 -0
  76. package/templates/backend/public/assets/logo.png +0 -0
  77. package/templates/backend/public/file.svg +4 -0
  78. package/templates/backend/public/globe.svg +12 -0
  79. package/templates/backend/public/next.svg +6 -0
  80. package/templates/backend/public/vercel.svg +3 -0
  81. package/templates/backend/public/window.svg +5 -0
  82. package/templates/backend/server.ts +129 -0
  83. package/templates/backend/setup-env.sh +50 -0
  84. package/templates/backend/src/common/assertions.ts +6 -0
  85. package/templates/backend/src/common/db.ts +1 -0
  86. package/templates/backend/src/common/loadPostgresEventstore.ts +16 -0
  87. package/templates/backend/src/common/parseEndpoint.ts +51 -0
  88. package/templates/backend/src/common/replay.ts +9 -0
  89. package/templates/backend/src/common/routes.ts +19 -0
  90. package/templates/backend/src/common/testHelpers.ts +53 -0
  91. package/templates/backend/src/core/readmodel.ts +28 -0
  92. package/templates/backend/src/core/types.ts +26 -0
  93. package/templates/backend/src/process/process.ts +53 -0
  94. package/templates/backend/src/supabase/LoginHandler.ts +36 -0
  95. package/templates/backend/src/supabase/ProtectedPageProps.ts +21 -0
  96. package/templates/backend/src/supabase/README.md +171 -0
  97. package/templates/backend/src/supabase/api.ts +63 -0
  98. package/templates/backend/src/supabase/authMiddleware.ts +53 -0
  99. package/templates/backend/src/supabase/component.ts +12 -0
  100. package/templates/backend/src/supabase/requireUser.ts +72 -0
  101. package/templates/backend/src/supabase/serverProps.ts +25 -0
  102. package/templates/backend/src/supabase/staticProps.ts +10 -0
  103. package/templates/backend/src/swagger.ts +34 -0
  104. package/templates/backend/src/util/assertions.ts +6 -0
  105. package/templates/backend/supabase/config.toml +295 -0
  106. package/templates/backend/supabase/migrations/20260121155918593_catalogentries.sql.sample +23 -0
  107. package/templates/backend/supabase/seed.sql +1 -0
  108. package/templates/backend/tsconfig.json +31 -0
  109. package/templates/frontend/.env.development +3 -0
  110. package/templates/frontend/AGENTS.md +7 -0
  111. package/templates/frontend/README.md +73 -0
  112. package/templates/frontend/components.json +20 -0
  113. package/templates/frontend/eslint.config.js +26 -0
  114. package/templates/frontend/index.html +18 -0
  115. package/templates/frontend/package-lock.json +8347 -0
  116. package/templates/frontend/package.json +94 -0
  117. package/templates/frontend/postcss.config.js +6 -0
  118. package/templates/frontend/public/favicon.ico +0 -0
  119. package/templates/frontend/public/logo.png +0 -0
  120. package/templates/frontend/public/placeholder.svg +1 -0
  121. package/templates/frontend/public/robots.txt +14 -0
  122. package/templates/frontend/src/App.css +42 -0
  123. package/templates/frontend/src/App.tsx +47 -0
  124. package/templates/frontend/src/components/NavLink.tsx +28 -0
  125. package/templates/frontend/src/components/ProtectedRoute.tsx +24 -0
  126. package/templates/frontend/src/components/calendar/Calendar.tsx +302 -0
  127. package/templates/frontend/src/components/layout/DashboardLayout.tsx +21 -0
  128. package/templates/frontend/src/components/layout/Header.tsx +45 -0
  129. package/templates/frontend/src/components/layout/Sidebar.tsx +82 -0
  130. package/templates/frontend/src/components/tables/ReservationTemplates.tsx +189 -0
  131. package/templates/frontend/src/components/ui/accordion.tsx +52 -0
  132. package/templates/frontend/src/components/ui/alert-dialog.tsx +104 -0
  133. package/templates/frontend/src/components/ui/alert.tsx +43 -0
  134. package/templates/frontend/src/components/ui/aspect-ratio.tsx +5 -0
  135. package/templates/frontend/src/components/ui/avatar.tsx +38 -0
  136. package/templates/frontend/src/components/ui/badge.tsx +29 -0
  137. package/templates/frontend/src/components/ui/breadcrumb.tsx +90 -0
  138. package/templates/frontend/src/components/ui/button.tsx +47 -0
  139. package/templates/frontend/src/components/ui/calendar.tsx +54 -0
  140. package/templates/frontend/src/components/ui/card.tsx +43 -0
  141. package/templates/frontend/src/components/ui/carousel.tsx +224 -0
  142. package/templates/frontend/src/components/ui/chart.tsx +303 -0
  143. package/templates/frontend/src/components/ui/checkbox.tsx +26 -0
  144. package/templates/frontend/src/components/ui/collapsible.tsx +9 -0
  145. package/templates/frontend/src/components/ui/command.tsx +132 -0
  146. package/templates/frontend/src/components/ui/context-menu.tsx +178 -0
  147. package/templates/frontend/src/components/ui/dialog.tsx +95 -0
  148. package/templates/frontend/src/components/ui/drawer.tsx +87 -0
  149. package/templates/frontend/src/components/ui/dropdown-menu.tsx +179 -0
  150. package/templates/frontend/src/components/ui/form.tsx +129 -0
  151. package/templates/frontend/src/components/ui/hover-card.tsx +27 -0
  152. package/templates/frontend/src/components/ui/input-otp.tsx +61 -0
  153. package/templates/frontend/src/components/ui/input.tsx +22 -0
  154. package/templates/frontend/src/components/ui/label.tsx +17 -0
  155. package/templates/frontend/src/components/ui/menubar.tsx +207 -0
  156. package/templates/frontend/src/components/ui/navigation-menu.tsx +120 -0
  157. package/templates/frontend/src/components/ui/pagination.tsx +81 -0
  158. package/templates/frontend/src/components/ui/popover.tsx +29 -0
  159. package/templates/frontend/src/components/ui/progress.tsx +23 -0
  160. package/templates/frontend/src/components/ui/radio-group.tsx +36 -0
  161. package/templates/frontend/src/components/ui/resizable.tsx +37 -0
  162. package/templates/frontend/src/components/ui/scroll-area.tsx +38 -0
  163. package/templates/frontend/src/components/ui/select.tsx +143 -0
  164. package/templates/frontend/src/components/ui/separator.tsx +20 -0
  165. package/templates/frontend/src/components/ui/sheet.tsx +107 -0
  166. package/templates/frontend/src/components/ui/sidebar.tsx +637 -0
  167. package/templates/frontend/src/components/ui/skeleton.tsx +7 -0
  168. package/templates/frontend/src/components/ui/slider.tsx +23 -0
  169. package/templates/frontend/src/components/ui/sonner.tsx +27 -0
  170. package/templates/frontend/src/components/ui/stat-card.tsx +44 -0
  171. package/templates/frontend/src/components/ui/switch.tsx +27 -0
  172. package/templates/frontend/src/components/ui/table.tsx +72 -0
  173. package/templates/frontend/src/components/ui/tabs.tsx +53 -0
  174. package/templates/frontend/src/components/ui/textarea.tsx +21 -0
  175. package/templates/frontend/src/components/ui/toast.tsx +111 -0
  176. package/templates/frontend/src/components/ui/toaster.tsx +24 -0
  177. package/templates/frontend/src/components/ui/toggle-group.tsx +49 -0
  178. package/templates/frontend/src/components/ui/toggle.tsx +37 -0
  179. package/templates/frontend/src/components/ui/tooltip.tsx +28 -0
  180. package/templates/frontend/src/components/ui/use-toast.ts +3 -0
  181. package/templates/frontend/src/contexts/AuthContext.tsx +94 -0
  182. package/templates/frontend/src/contexts/RefreshContext.tsx +236 -0
  183. package/templates/frontend/src/hooks/api/index.ts +2 -0
  184. package/templates/frontend/src/hooks/api/useLocations.ts +15 -0
  185. package/templates/frontend/src/hooks/use-mobile.tsx +19 -0
  186. package/templates/frontend/src/hooks/use-toast.ts +186 -0
  187. package/templates/frontend/src/hooks/useApiContext.ts +11 -0
  188. package/templates/frontend/src/index.css +118 -0
  189. package/templates/frontend/src/integrations/supabase/client.ts +9 -0
  190. package/templates/frontend/src/lib/api-client.ts +136 -0
  191. package/templates/frontend/src/lib/api.ts +1028 -0
  192. package/templates/frontend/src/lib/utils.ts +6 -0
  193. package/templates/frontend/src/main.tsx +5 -0
  194. package/templates/frontend/src/pages/Auth.tsx +408 -0
  195. package/templates/frontend/src/pages/Dashboard.tsx +168 -0
  196. package/templates/frontend/src/pages/Menus.tsx +224 -0
  197. package/templates/frontend/src/pages/NotFound.tsx +24 -0
  198. package/templates/frontend/src/pages/Register.tsx +285 -0
  199. package/templates/frontend/src/test/example.test.ts +0 -0
  200. package/templates/frontend/src/test/setup.ts +15 -0
  201. package/templates/frontend/src/types/index.ts +8 -0
  202. package/templates/frontend/src/vite-env.d.ts +1 -0
  203. package/templates/frontend/tailwind.config.ts +101 -0
  204. package/templates/frontend/tsconfig.app.json +31 -0
  205. package/templates/frontend/tsconfig.json +16 -0
  206. package/templates/frontend/tsconfig.node.json +22 -0
  207. package/templates/frontend/vite.config.ts +21 -0
  208. package/templates/frontend/vitest.config.ts +16 -0
  209. package/templates/init.sh +1 -0
  210. package/templates/prompt.md +139 -0
  211. package/templates/ralph.sh +120 -0
  212. package/templates/server.mjs +505 -0
package/README.md ADDED
@@ -0,0 +1,254 @@
1
+ # EMBuilder
2
+
3
+ Event-Model driven development toolkit for Claude Code. Generate code slices from event model specifications using simple slash commands.
4
+
5
+ ## Installation
6
+
7
+ Super simple - install from GitHub Packages:
8
+
9
+ ```bash
10
+ npx @dilgerma/embuilder install
11
+ ```
12
+
13
+ That's it! The skills are now available in Claude Code.
14
+
15
+ ### Manual Installation (Alternative)
16
+
17
+ If you want to install from a local directory:
18
+
19
+ ```bash
20
+ cd /path/to/embuilder
21
+ npm install
22
+ npm run build
23
+ npm link
24
+ embuilder install
25
+ ```
26
+
27
+ ## What This Does
28
+
29
+ This package adds powerful skills to Claude Code for event-model driven development:
30
+
31
+ ### Event Model Skills
32
+ - `/automation-slice` - Generate automation slices (background processes with CRON)
33
+ - `/state-change-slice` - Generate command handlers (business logic)
34
+ - `/state-view-slice` - Generate read models/projections (queries and views)
35
+
36
+ ### Configuration Skills
37
+ - `/fetch-config` - Fetch config.json from your event model app (localhost:3001)
38
+
39
+ ### Yeoman Generator Skills
40
+ - `/gen-skeleton` - Generate a Supabase backend skeleton app
41
+ - `/gen-state-change` - Generate state change slices from config.json
42
+ - `/gen-state-view` - Generate state view slices from config.json
43
+ - `/gen-automation` - Generate automation slices from config.json
44
+ - `/gen-ui` - Set up a React UI project with shadcn/ui and Supabase
45
+
46
+ All based on your event model specifications and configuration!
47
+
48
+ ## Quick Start
49
+
50
+ ### From GitHub Packages
51
+
52
+ ```bash
53
+ npx @dilgerma/embuilder install
54
+ ```
55
+
56
+ ### From Local Directory
57
+
58
+ ```bash
59
+ ./install.sh
60
+ ```
61
+
62
+ ### Using the Skills
63
+
64
+ In Claude Code, just type one of these commands:
65
+
66
+ **Event Model Skills:**
67
+ ```
68
+ /state-change-slice # Generate a command handler
69
+ /state-view-slice # Generate a read model
70
+ /automation-slice # Generate a background automation
71
+ ```
72
+
73
+ **Configuration:**
74
+ ```
75
+ /fetch-config # Fetch config from event model app
76
+ ```
77
+
78
+ **Yeoman Generator Skills:**
79
+ ```
80
+ /gen-skeleton # Generate Supabase backend skeleton
81
+ /gen-state-change # Generate state change slices from config
82
+ /gen-state-view # Generate state view slices from config
83
+ /gen-automation # Generate automation slices from config
84
+ /gen-ui # Set up React UI project
85
+ ```
86
+
87
+ Claude will:
88
+ - Guide you through the generation process
89
+ - Find your event model or config.json
90
+ - Generate TypeScript code following best practices
91
+ - Create tests automatically
92
+ - Run the tests to verify everything works
93
+
94
+ ## Skills Overview
95
+
96
+ ### Event Model Skills
97
+
98
+ #### `/automation-slice`
99
+ Builds background automations that:
100
+ - Read from TODO lists (work queues)
101
+ - Fire commands on a CRON schedule
102
+ - Process items automatically
103
+
104
+ **Use case:** Auto-confirm invitations, process checkouts, send notifications
105
+
106
+ #### `/state-change-slice`
107
+ Builds command handlers that:
108
+ - Accept commands (user actions)
109
+ - Validate against current state
110
+ - Emit events (facts about what happened)
111
+
112
+ **Use case:** Register clerk, activate feature, submit timesheet
113
+
114
+ #### `/state-view-slice`
115
+ Builds read models that:
116
+ - Subscribe to events
117
+ - Build queryable views
118
+ - Support UI and reporting
119
+
120
+ **Use case:** Active shifts dashboard, clerk directory, event calendar
121
+
122
+ ### Yeoman Generator Skills
123
+
124
+ #### `/gen-skeleton`
125
+ Generates a complete Supabase backend skeleton app:
126
+ - Event store setup
127
+ - Basic project structure
128
+ - Common utilities and helpers
129
+ - Supabase configuration
130
+
131
+ **Use case:** Bootstrap a new event-sourced application
132
+
133
+ #### `/gen-state-change`, `/gen-state-view`, `/gen-automation`
134
+ Generate slices from your `config.json` file:
135
+ - Reads slice definitions from config
136
+ - Generates complete TypeScript implementations
137
+ - Creates API routes and tests
138
+ - Works with Yeoman's template system
139
+
140
+ **Use case:** Generate code from pre-defined slice configurations
141
+
142
+ #### `/gen-ui`
143
+ Sets up a modern React UI project:
144
+ - Vite + React + TypeScript
145
+ - shadcn/ui component library (Radix UI + Tailwind)
146
+ - Supabase client integration
147
+ - React Router and React Query
148
+ - Full suite of pre-built UI components
149
+
150
+ **Use case:** Quickly scaffold a frontend for your Supabase backend
151
+
152
+ ## Event Model Structure
153
+
154
+ Your event model (JSON) typically defines:
155
+
156
+ ```json
157
+ {
158
+ "commands": [
159
+ {
160
+ "title": "Register Clerk",
161
+ "fields": [
162
+ {"name": "clerkId", "type": "UUID"},
163
+ {"name": "name", "type": "String"}
164
+ ]
165
+ }
166
+ ],
167
+ "events": [
168
+ {
169
+ "title": "Clerk Registered",
170
+ "fields": [...]
171
+ }
172
+ ],
173
+ "processors": [...],
174
+ "readmodels": [...]
175
+ }
176
+ ```
177
+
178
+ ## Generated Code Structure
179
+
180
+ ```
181
+ src/slices/{slice-name}/
182
+ ā”œā”€ā”€ CommandHandler.ts # Business logic (state-change)
183
+ ā”œā”€ā”€ Projection.ts # Read model (state-view)
184
+ ā”œā”€ā”€ processor.ts # CRON automation (automation)
185
+ ā”œā”€ā”€ routes.ts # HTTP API endpoints
186
+ ā”œā”€ā”€ {SliceName}.test.ts # Automated tests
187
+ └── ui/ # UI components (optional)
188
+ ```
189
+
190
+ ## Commands
191
+
192
+ ```bash
193
+ # Install skills only
194
+ npx @dilgerma/embuilder install
195
+
196
+ # Install skills + template files (ralph.sh, AGENTS.md, Claude.md, prompt.md)
197
+ npx @dilgerma/embuilder install --with-templates
198
+
199
+ # Uninstall
200
+ npx @dilgerma/embuilder uninstall
201
+
202
+ # Check status
203
+ npx @dilgerma/embuilder status
204
+ ```
205
+
206
+ ### Template Files
207
+
208
+ When you use `--with-templates`, you get:
209
+
210
+ - **`ralph.sh`** - Autonomous agent loop for continuous development
211
+ - **`AGENTS.md`** - Track learnings and patterns from development
212
+ - **`Claude.md`** - Project-specific configuration for Claude Code
213
+ - **`prompt.md`** - Agent instructions for automated development
214
+ - **`.claude/hooks/`** - Pre-commit hooks that analyze git diffs before commits
215
+ - Includes built-in analyzers for code quality and event model validation
216
+ - Extensible with custom TypeScript analyzers
217
+
218
+ These files enable the full event-model driven development workflow with autonomous agents.
219
+
220
+ ### Git Commit Hooks
221
+
222
+ The template includes a pre-commit hook system that automatically analyzes changes before commits:
223
+
224
+ **Built-in Analyzers:**
225
+ - **Code Quality Checker** - Detects console.log, debugger statements, TODOs, and potential secrets
226
+ - **Event Model Validator** - Ensures event naming conventions and slice structure
227
+ - **Logger** - Displays commit statistics and changed files
228
+
229
+ **Features:**
230
+ - Written in TypeScript for type safety
231
+ - Extensible - add your own analyzers
232
+ - Non-blocking by default
233
+ - Integrates seamlessly with Claude Code
234
+
235
+ See `.claude/hooks/README.md` for full documentation on creating custom analyzers.
236
+
237
+ ## Philosophy
238
+
239
+ This toolkit follows **event-model driven development**:
240
+
241
+ 1. **Design first** - Define your event model (events, commands, aggregates)
242
+ 2. **Generate code** - Use Claude skills to generate implementation
243
+ 3. **Test automatically** - Generated code includes tests
244
+ 4. **Iterate quickly** - Change the model, regenerate
245
+
246
+ ## Requirements
247
+
248
+ - Node.js 18+
249
+ - Claude Code CLI
250
+ - TypeScript knowledge (for understanding generated code)
251
+
252
+ ## License
253
+
254
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join } from 'path';
5
+ import { existsSync, chmodSync, cpSync, rmSync, readdirSync, statSync } from 'fs';
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ const program = new Command();
9
+ const SKILLS_DIR = join(process.cwd(), '.claude', 'skills');
10
+ program
11
+ .name('embuilder')
12
+ .description('EMBuilder - Event-Model driven development toolkit for Claude Code')
13
+ .version('0.1.22');
14
+ program
15
+ .command('install')
16
+ .description('Install event-model skills into Claude Code')
17
+ .option('--with-templates', 'Also copy template files (ralph.sh, AGENTS.md, Claude.md, prompt.md, README.md) and generators to current directory')
18
+ .action((options) => {
19
+ console.log('šŸ“¦ Installing EMBuilder...\n');
20
+ try {
21
+ // Copy template files if requested
22
+ console.log('\nšŸ“„ Copying all templates to current directory...');
23
+ const templatesSource = join(__dirname, '..', 'templates');
24
+ const targetDir = process.cwd();
25
+ if (!existsSync(templatesSource)) {
26
+ console.error('āŒ Templates directory not found!');
27
+ console.error(` Expected location: ${templatesSource}`);
28
+ console.error(` Package location: ${__dirname}`);
29
+ console.error('');
30
+ console.error('This might be caused by:');
31
+ console.error(' 1. Old cached version - try: npx --yes @dilgerma/embuilder@latest install --with-templates');
32
+ console.error(' 2. Package not published correctly - reinstall with: npm install -g @dilgerma/embuilder@latest');
33
+ console.error('');
34
+ console.error('If the problem persists, please report at:');
35
+ console.error(' https://github.com/dilgerma/embuilder/issues');
36
+ process.exit(1);
37
+ }
38
+ // Copy everything from templates/ to current directory
39
+ try {
40
+ // Read all items in templates directory and copy each one
41
+ // We copy items individually instead of the entire directory to have better control
42
+ const items = readdirSync(templatesSource);
43
+ for (const item of items) {
44
+ const sourcePath = join(templatesSource, item);
45
+ const targetPath = join(targetDir, item);
46
+ // Skip node_modules if present
47
+ if (item === 'node_modules') {
48
+ continue;
49
+ }
50
+ try {
51
+ const stat = statSync(sourcePath);
52
+ if (stat.isDirectory()) {
53
+ // For directories, copy with filter to skip node_modules
54
+ cpSync(sourcePath, targetPath, {
55
+ recursive: true,
56
+ filter: (source) => {
57
+ // Get the relative path from the source directory to avoid matching
58
+ // 'node_modules' in the npx cache path itself
59
+ const relativePath = source.replace(sourcePath, '');
60
+ return !relativePath.includes('node_modules');
61
+ }
62
+ });
63
+ }
64
+ else {
65
+ // For files, copy directly
66
+ cpSync(sourcePath, targetPath);
67
+ }
68
+ }
69
+ catch (itemError) {
70
+ console.error(` āŒ Error copying ${item}:`, itemError?.message);
71
+ }
72
+ // Verify this item was copied
73
+ if (!existsSync(targetPath)) {
74
+ console.error(` āŒ Failed to copy: ${item}`);
75
+ }
76
+ }
77
+ }
78
+ catch (copyError) {
79
+ console.error(' āŒ Error during copy:', copyError);
80
+ throw copyError;
81
+ }
82
+ // Verify files were actually copied
83
+ const copiedFiles = existsSync(join(targetDir, 'README.md'));
84
+ // Make ralph.sh executable if it exists
85
+ const ralphPath = join(targetDir, 'ralph.sh');
86
+ if (existsSync(ralphPath)) {
87
+ chmodSync(ralphPath, 0o755);
88
+ console.log(' āœ“ Made ralph.sh executable');
89
+ }
90
+ if (!copiedFiles) {
91
+ console.error(' āŒ Files were not copied! This is a bug.');
92
+ console.error(' Please report this at: https://github.com/dilgerma/embuilder/issues');
93
+ process.exit(1);
94
+ }
95
+ console.log(' āœ“ All template files and directories copied');
96
+ console.log(' - README.md, Claude.md, AGENTS.md, prompt.md, ralph.sh');
97
+ console.log(' - .claude/ directory with skills and generators');
98
+ console.log(' - All other template contents');
99
+ console.log('\nšŸ“ Templates copied! You can now:');
100
+ console.log(' - Read README.md for detailed usage instructions');
101
+ console.log(' - Edit Claude.md with project-specific settings');
102
+ console.log(' - Run ./ralph.sh for automated development loops');
103
+ console.log(' - Track learnings in AGENTS.md');
104
+ console.log(' - Use skills in .claude/skills/ for code generation');
105
+ console.log('\nāœ… Installation complete with templates!');
106
+ console.log("\nšŸ’”Want to initialize the project? Just run this command:");
107
+ console.log("\ndocker run -v $PWD:/workspace nebulit/generators");
108
+ }
109
+ catch (error) {
110
+ console.error('āŒ Installation failed:', error);
111
+ process.exit(1);
112
+ }
113
+ });
114
+ program
115
+ .command('uninstall')
116
+ .description('Remove event-model skills from Claude Code')
117
+ .action(() => {
118
+ if (existsSync(SKILLS_DIR)) {
119
+ rmSync(SKILLS_DIR, { recursive: true, force: true });
120
+ console.log('āœ… EMBuilder skills uninstalled');
121
+ }
122
+ else {
123
+ console.log('ā„¹ļø Skills not currently installed');
124
+ }
125
+ });
126
+ program
127
+ .command('status')
128
+ .description('Check installation status')
129
+ .action(() => {
130
+ console.log('EMBuilder Skills Status\n');
131
+ console.log(`Installation path: ${SKILLS_DIR}`);
132
+ console.log(`Installed: ${existsSync(SKILLS_DIR) ? 'āœ… Yes' : 'āŒ No'}`);
133
+ if (existsSync(SKILLS_DIR)) {
134
+ const skillsSource = join(__dirname, '..', 'skills');
135
+ console.log(`Source: ${skillsSource}`);
136
+ }
137
+ });
138
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@nebulit/embuilder",
3
+ "version": "0.1.39",
4
+ "description": "Event-model driven development toolkit for Claude Code",
5
+ "type": "module",
6
+ "bin": {
7
+ "embuilder": "dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc && chmod +x dist/cli.js",
11
+ "dev": "tsc --watch",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "keywords": [
15
+ "claude",
16
+ "claude-code",
17
+ "event-model",
18
+ "code-generation",
19
+ "ddd",
20
+ "event-sourcing",
21
+ "event-driven",
22
+ "cqrs",
23
+ "yeoman-generator"
24
+ ],
25
+ "files": [
26
+ "dist",
27
+ "templates",
28
+ "README.md"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/dilgerma/embuilder.git"
33
+ },
34
+ "author": "Martin Dilger",
35
+ "license": "MIT",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "dependencies": {
40
+ "commander": "^12.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^20.0.0",
44
+ "typescript": "^5.0.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ }
49
+ }
@@ -0,0 +1,256 @@
1
+ # Git Commit Hooks - Quick Start
2
+
3
+ This guide gets you up and running with git commit hooks in 5 minutes.
4
+
5
+ ## Installation
6
+
7
+ If you installed EMBuilder with `--with-templates`, the hooks are already set up!
8
+
9
+ ```bash
10
+ npx @dilgerma/embuilder install --with-templates
11
+ ```
12
+
13
+ ## Prerequisites
14
+
15
+ Install `tsx` to run TypeScript analyzers:
16
+
17
+ ```bash
18
+ npm install -g tsx
19
+ ```
20
+
21
+ ## What You Get
22
+
23
+ When Claude commits code, these analyzers run automatically:
24
+
25
+ ### 1. Code Quality Checker
26
+ Warns about:
27
+ - `console.log` statements
28
+ - `debugger` statements
29
+ - TODO/FIXME comments
30
+ - Potential secrets (API keys, passwords)
31
+
32
+ ### 2. Event Model Validator
33
+ Validates:
34
+ - Event names use past-tense
35
+ - Tests are updated with logic changes
36
+ - Slice structure follows conventions
37
+
38
+ ### 3. Example Logger
39
+ Shows:
40
+ - Branch name
41
+ - Files changed
42
+ - Staged/unstaged status
43
+
44
+ ## Try It Out
45
+
46
+ 1. **Make a change and commit**
47
+
48
+ ```bash
49
+ echo "console.log('test')" >> test.ts
50
+ git add test.ts
51
+ git commit -m "test commit"
52
+ ```
53
+
54
+ 2. **See the hook in action**
55
+
56
+ You'll see output like:
57
+
58
+ ```
59
+ šŸ” Running git diff analyzers...
60
+ → Running analyzer: code-quality-checker.ts
61
+ šŸ” Code Quality Analysis:
62
+ āš ļø Warnings:
63
+ - Found 1 console.log statement(s) - consider removing debug code
64
+ āœ… Analyzers completed
65
+ ```
66
+
67
+ ## Customizing
68
+
69
+ ### Disable an analyzer
70
+
71
+ ```bash
72
+ # Rename to disable
73
+ mv .claude/hooks/analyzers/example-logger.ts \
74
+ .claude/hooks/analyzers/example-logger.ts.disabled
75
+ ```
76
+
77
+ ### Create your own analyzer
78
+
79
+ ```bash
80
+ # Create new analyzer
81
+ cat > .claude/hooks/analyzers/my-check.ts << 'EOF'
82
+ #!/usr/bin/env node
83
+ import { readFileSync } from 'fs';
84
+
85
+ interface HookData {
86
+ changed_files: string[];
87
+ staged_diff: string;
88
+ }
89
+
90
+ async function main() {
91
+ const data: HookData = JSON.parse(readFileSync(0, 'utf-8'));
92
+
93
+ console.log('šŸ” My Custom Check:');
94
+
95
+ // Check if package.json changed
96
+ if (data.changed_files.includes('package.json')) {
97
+ console.log(' āš ļø package.json changed - remember to run npm install');
98
+ }
99
+ }
100
+
101
+ main();
102
+ EOF
103
+
104
+ # Test it
105
+ echo '{"changed_files":["package.json"],"staged_diff":""}' | \
106
+ tsx .claude/hooks/analyzers/my-check.ts
107
+ ```
108
+
109
+ ## Advanced Configuration
110
+
111
+ Edit `.claude/settings.local.json` to customize:
112
+
113
+ ```json
114
+ {
115
+ "hooks": {
116
+ "PreToolUse": [
117
+ {
118
+ "matcher": "Bash(*git commit*)",
119
+ "hooks": [
120
+ {
121
+ "type": "command",
122
+ "command": ".claude/hooks/analyze-commit.sh",
123
+ "statusMessage": "Analyzing changes before commit",
124
+ "timeout": 30
125
+ }
126
+ ]
127
+ }
128
+ ]
129
+ }
130
+ }
131
+ ```
132
+
133
+ ## Common Use Cases
134
+
135
+ ### Enforce Commit Message Format
136
+
137
+ Create `.claude/hooks/analyzers/commit-msg-validator.ts`:
138
+
139
+ ```typescript
140
+ import { readFileSync } from 'fs';
141
+ import { execSync } from 'child_process';
142
+
143
+ async function main() {
144
+ // Get the last commit message from git
145
+ const msg = execSync('git log -1 --pretty=%B').toString().trim();
146
+
147
+ // Check format: "type: description"
148
+ const pattern = /^(feat|fix|docs|style|refactor|test|chore):\s.{10,}$/;
149
+
150
+ if (!pattern.test(msg)) {
151
+ console.error('āŒ Invalid commit message format');
152
+ console.error(' Expected: "type: description" (at least 10 chars)');
153
+ console.error(' Types: feat, fix, docs, style, refactor, test, chore');
154
+ process.exit(1); // Block commit
155
+ }
156
+
157
+ console.log('āœ… Commit message format valid');
158
+ }
159
+
160
+ main();
161
+ ```
162
+
163
+ ### Check for Breaking Changes
164
+
165
+ Create `.claude/hooks/analyzers/breaking-changes.ts`:
166
+
167
+ ```typescript
168
+ import { readFileSync } from 'fs';
169
+
170
+ interface HookData {
171
+ changed_files: string[];
172
+ staged_diff: string;
173
+ }
174
+
175
+ async function main() {
176
+ const data: HookData = JSON.parse(readFileSync(0, 'utf-8'));
177
+
178
+ // Check if public API files changed
179
+ const apiFiles = data.changed_files.filter(f =>
180
+ f.includes('/api/') ||
181
+ f.includes('public') ||
182
+ f.endsWith('types.ts')
183
+ );
184
+
185
+ if (apiFiles.length > 0) {
186
+ console.log('āš ļø Public API files changed:');
187
+ apiFiles.forEach(f => console.log(` - ${f}`));
188
+ console.log('\nšŸ’” Consider:');
189
+ console.log(' - Updating CHANGELOG.md');
190
+ console.log(' - Bumping version number');
191
+ console.log(' - Adding migration guide');
192
+ }
193
+ }
194
+
195
+ main();
196
+ ```
197
+
198
+ ### Run Tests Before Commit
199
+
200
+ Create `.claude/hooks/analyzers/run-tests.ts`:
201
+
202
+ ```typescript
203
+ import { execSync } from 'child_process';
204
+
205
+ async function main() {
206
+ console.log('🧪 Running tests...');
207
+
208
+ try {
209
+ execSync('npm test', { stdio: 'inherit' });
210
+ console.log('āœ… All tests passed');
211
+ } catch (error) {
212
+ console.error('āŒ Tests failed - commit blocked');
213
+ process.exit(1);
214
+ }
215
+ }
216
+
217
+ main();
218
+ ```
219
+
220
+ ## Troubleshooting
221
+
222
+ ### Hook not running?
223
+
224
+ 1. Check configuration in `.claude/settings.local.json`
225
+ 2. Verify hook script is executable:
226
+ ```bash
227
+ chmod +x .claude/hooks/analyze-commit.sh
228
+ ```
229
+
230
+ ### TypeScript errors?
231
+
232
+ 1. Install tsx: `npm install -g tsx`
233
+ 2. Check TypeScript syntax in your analyzer
234
+ 3. Test manually:
235
+ ```bash
236
+ echo '{}' | tsx .claude/hooks/analyzers/your-analyzer.ts
237
+ ```
238
+
239
+ ### Analyzer not executing?
240
+
241
+ 1. Verify file is in `.claude/hooks/analyzers/`
242
+ 2. Check file has `.ts` extension
243
+ 3. Look for error messages in hook output
244
+
245
+ ## Next Steps
246
+
247
+ - Read full documentation: `.claude/hooks/README.md`
248
+ - Explore built-in analyzers in `.claude/hooks/analyzers/`
249
+ - Share your custom analyzers with the team
250
+ - Configure blocking behavior for critical checks
251
+
252
+ ## Help & Support
253
+
254
+ - Full docs: `.claude/hooks/README.md`
255
+ - Report issues: https://github.com/dilgerma/embuilder/issues
256
+ - Examples: See `.claude/hooks/analyzers/` directory