@rune-kit/rune 2.10.0 → 2.12.0

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 (240) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +65 -6
  3. package/commands/rune.md +168 -168
  4. package/compiler/__tests__/detect-invariants.test.js +136 -0
  5. package/compiler/__tests__/doctor-mesh.test.js +229 -0
  6. package/compiler/__tests__/hook-dispatch.test.js +91 -0
  7. package/compiler/__tests__/hooks-antigravity.test.js +118 -0
  8. package/compiler/__tests__/hooks-cursor.test.js +139 -0
  9. package/compiler/__tests__/hooks-install.test.js +305 -0
  10. package/compiler/__tests__/hooks-merge.test.js +204 -0
  11. package/compiler/__tests__/hooks-tiers.test.js +519 -0
  12. package/compiler/__tests__/hooks-windsurf.test.js +115 -0
  13. package/compiler/__tests__/inject-claude-md.test.js +152 -0
  14. package/compiler/__tests__/load-invariants.test.js +408 -0
  15. package/compiler/__tests__/onboard-invariants.test.js +240 -0
  16. package/compiler/adapters/hooks/antigravity.js +140 -0
  17. package/compiler/adapters/hooks/claude.js +166 -0
  18. package/compiler/adapters/hooks/cursor.js +191 -0
  19. package/compiler/adapters/hooks/index.js +82 -0
  20. package/compiler/adapters/hooks/tier-emitter.js +182 -0
  21. package/compiler/adapters/hooks/windsurf.js +202 -0
  22. package/compiler/bin/rune.js +196 -6
  23. package/compiler/commands/hook-dispatch.js +87 -0
  24. package/compiler/commands/hooks/install.js +120 -0
  25. package/compiler/commands/hooks/merge.js +211 -0
  26. package/compiler/commands/hooks/presets.js +116 -0
  27. package/compiler/commands/hooks/status.js +112 -0
  28. package/compiler/commands/hooks/tiers.js +221 -0
  29. package/compiler/commands/hooks/uninstall.js +94 -0
  30. package/compiler/doctor.js +236 -0
  31. package/contexts/dev.md +34 -34
  32. package/contexts/research.md +43 -43
  33. package/contexts/review.md +55 -55
  34. package/extensions/ai-ml/PACK.md +88 -88
  35. package/extensions/ai-ml/skills/ai-agents.md +172 -172
  36. package/extensions/ai-ml/skills/code-sandbox.md +187 -187
  37. package/extensions/ai-ml/skills/deep-research.md +146 -146
  38. package/extensions/ai-ml/skills/embedding-search.md +66 -66
  39. package/extensions/ai-ml/skills/fine-tuning-guide.md +74 -74
  40. package/extensions/ai-ml/skills/llm-architect.md +125 -125
  41. package/extensions/ai-ml/skills/llm-integration.md +64 -64
  42. package/extensions/ai-ml/skills/prompt-patterns.md +72 -72
  43. package/extensions/ai-ml/skills/rag-patterns.md +66 -66
  44. package/extensions/ai-ml/skills/web-extraction.md +114 -114
  45. package/extensions/analytics/PACK.md +92 -92
  46. package/extensions/analytics/skills/ab-testing.md +72 -72
  47. package/extensions/analytics/skills/dashboard-patterns.md +83 -83
  48. package/extensions/analytics/skills/data-validation.md +68 -68
  49. package/extensions/analytics/skills/funnel-analysis.md +81 -81
  50. package/extensions/analytics/skills/sql-patterns.md +57 -57
  51. package/extensions/analytics/skills/statistical-analysis.md +79 -79
  52. package/extensions/analytics/skills/tracking-setup.md +71 -71
  53. package/extensions/backend/PACK.md +104 -104
  54. package/extensions/backend/skills/api-patterns.md +84 -84
  55. package/extensions/backend/skills/async-pipeline.md +193 -193
  56. package/extensions/backend/skills/auth-patterns.md +97 -97
  57. package/extensions/backend/skills/background-jobs.md +133 -133
  58. package/extensions/backend/skills/caching-patterns.md +108 -108
  59. package/extensions/backend/skills/cli-generation.md +133 -133
  60. package/extensions/backend/skills/database-patterns.md +87 -87
  61. package/extensions/backend/skills/middleware-patterns.md +104 -104
  62. package/extensions/chrome-ext/PACK.md +93 -93
  63. package/extensions/chrome-ext/skills/cws-preflight.md +143 -143
  64. package/extensions/chrome-ext/skills/cws-publish.md +104 -104
  65. package/extensions/chrome-ext/skills/ext-ai-integration.md +251 -251
  66. package/extensions/chrome-ext/skills/ext-messaging.md +139 -139
  67. package/extensions/chrome-ext/skills/ext-storage.md +133 -133
  68. package/extensions/chrome-ext/skills/mv3-scaffold.md +164 -164
  69. package/extensions/content/PACK.md +96 -96
  70. package/extensions/content/skills/blog-patterns.md +88 -88
  71. package/extensions/content/skills/cms-integration.md +131 -131
  72. package/extensions/content/skills/content-scoring.md +107 -107
  73. package/extensions/content/skills/i18n.md +83 -83
  74. package/extensions/content/skills/mdx-authoring.md +137 -137
  75. package/extensions/content/skills/reference.md +1014 -1014
  76. package/extensions/content/skills/seo-patterns.md +67 -67
  77. package/extensions/content/skills/video-repurpose.md +153 -153
  78. package/extensions/devops/PACK.md +101 -101
  79. package/extensions/devops/skills/chaos-testing.md +67 -67
  80. package/extensions/devops/skills/ci-cd.md +75 -75
  81. package/extensions/devops/skills/docker.md +58 -58
  82. package/extensions/devops/skills/edge-serverless.md +163 -163
  83. package/extensions/devops/skills/infra-as-code.md +158 -158
  84. package/extensions/devops/skills/kubernetes.md +110 -110
  85. package/extensions/devops/skills/monitoring.md +57 -57
  86. package/extensions/devops/skills/server-setup.md +64 -64
  87. package/extensions/devops/skills/ssl-domain.md +42 -42
  88. package/extensions/ecommerce/PACK.md +116 -116
  89. package/extensions/ecommerce/skills/cart-system.md +79 -79
  90. package/extensions/ecommerce/skills/inventory-mgmt.md +102 -102
  91. package/extensions/ecommerce/skills/order-management.md +126 -126
  92. package/extensions/ecommerce/skills/payment-integration.md +472 -472
  93. package/extensions/ecommerce/skills/shopify-dev.md +69 -69
  94. package/extensions/ecommerce/skills/subscription-billing.md +93 -93
  95. package/extensions/ecommerce/skills/tax-compliance.md +117 -117
  96. package/extensions/gamedev/PACK.md +142 -142
  97. package/extensions/gamedev/skills/asset-pipeline.md +74 -74
  98. package/extensions/gamedev/skills/audio-system.md +129 -129
  99. package/extensions/gamedev/skills/camera-system.md +87 -87
  100. package/extensions/gamedev/skills/ecs.md +98 -98
  101. package/extensions/gamedev/skills/game-loops.md +72 -72
  102. package/extensions/gamedev/skills/input-system.md +199 -199
  103. package/extensions/gamedev/skills/multiplayer.md +180 -180
  104. package/extensions/gamedev/skills/particles.md +105 -105
  105. package/extensions/gamedev/skills/physics-engine.md +89 -89
  106. package/extensions/gamedev/skills/scene-management.md +146 -146
  107. package/extensions/gamedev/skills/threejs-patterns.md +90 -90
  108. package/extensions/gamedev/skills/webgl.md +71 -71
  109. package/extensions/mobile/PACK.md +106 -106
  110. package/extensions/mobile/skills/app-store-connect.md +152 -152
  111. package/extensions/mobile/skills/app-store-prep.md +66 -66
  112. package/extensions/mobile/skills/deep-linking.md +109 -109
  113. package/extensions/mobile/skills/flutter.md +60 -60
  114. package/extensions/mobile/skills/ios-build-pipeline.md +142 -142
  115. package/extensions/mobile/skills/native-bridge.md +66 -66
  116. package/extensions/mobile/skills/ota-updates.md +97 -97
  117. package/extensions/mobile/skills/push-notifications.md +111 -111
  118. package/extensions/mobile/skills/react-native.md +82 -82
  119. package/extensions/saas/PACK.md +116 -116
  120. package/extensions/saas/skills/billing-integration.md +200 -200
  121. package/extensions/saas/skills/feature-flags.md +130 -130
  122. package/extensions/saas/skills/multi-tenant.md +103 -103
  123. package/extensions/saas/skills/onboarding-flow.md +139 -139
  124. package/extensions/saas/skills/subscription-flow.md +95 -95
  125. package/extensions/saas/skills/team-management.md +144 -144
  126. package/extensions/security/PACK.md +99 -99
  127. package/extensions/security/skills/api-security.md +140 -140
  128. package/extensions/security/skills/compliance.md +68 -68
  129. package/extensions/security/skills/owasp-audit.md +64 -64
  130. package/extensions/security/skills/pentest-patterns.md +77 -77
  131. package/extensions/security/skills/secret-mgmt.md +65 -65
  132. package/extensions/security/skills/supply-chain.md +65 -65
  133. package/extensions/trading/PACK.md +80 -80
  134. package/extensions/trading/skills/chart-components.md +55 -55
  135. package/extensions/trading/skills/experiment-loop.md +125 -125
  136. package/extensions/trading/skills/fintech-patterns.md +47 -47
  137. package/extensions/trading/skills/indicator-library.md +58 -58
  138. package/extensions/trading/skills/quant-analysis.md +111 -111
  139. package/extensions/trading/skills/realtime-data.md +58 -58
  140. package/extensions/trading/skills/trade-logic.md +104 -104
  141. package/extensions/ui/PACK.md +130 -130
  142. package/extensions/ui/skills/a11y-audit.md +91 -91
  143. package/extensions/ui/skills/animation-patterns.md +127 -127
  144. package/extensions/ui/skills/component-patterns.md +100 -100
  145. package/extensions/ui/skills/design-decision.md +108 -108
  146. package/extensions/ui/skills/design-system.md +68 -68
  147. package/extensions/ui/skills/landing-patterns.md +155 -155
  148. package/extensions/ui/skills/palette-picker.md +173 -173
  149. package/extensions/ui/skills/react-health.md +90 -90
  150. package/extensions/ui/skills/type-system.md +125 -125
  151. package/extensions/ui/skills/web-vitals.md +153 -153
  152. package/extensions/zalo/PACK.md +145 -145
  153. package/extensions/zalo/skills/zalo-oa-mcp.md +317 -317
  154. package/extensions/zalo/skills/zalo-oa-messaging.md +429 -429
  155. package/extensions/zalo/skills/zalo-oa-setup.md +236 -236
  156. package/extensions/zalo/skills/zalo-oa-webhook.md +189 -189
  157. package/extensions/zalo/skills/zalo-personal-messaging.md +194 -194
  158. package/extensions/zalo/skills/zalo-personal-setup.md +153 -153
  159. package/extensions/zalo/skills/zalo-rate-guard.md +219 -219
  160. package/hooks/auto-format/index.cjs +48 -48
  161. package/hooks/hooks.json +111 -111
  162. package/hooks/post-session-reflect/index.cjs +189 -189
  163. package/hooks/pre-compact/index.cjs +95 -95
  164. package/hooks/run-hook.cmd +1 -1
  165. package/hooks/secrets-scan/index.cjs +100 -100
  166. package/hooks/session-start/index.cjs +71 -71
  167. package/hooks/typecheck/index.cjs +65 -65
  168. package/package.json +63 -63
  169. package/references/ui-pro-max-data/LICENSE-UI-PRO-MAX +21 -21
  170. package/references/ui-pro-max-data/charts.csv +26 -26
  171. package/references/ui-pro-max-data/colors.csv +161 -161
  172. package/references/ui-pro-max-data/styles.csv +68 -68
  173. package/references/ui-pro-max-data/typography.csv +74 -74
  174. package/references/ui-pro-max-data/ui-reasoning.csv +162 -162
  175. package/references/ui-pro-max-data/ux-guidelines.csv +99 -99
  176. package/skills/adversary/SKILL.md +283 -283
  177. package/skills/asset-creator/SKILL.md +157 -157
  178. package/skills/audit/SKILL.md +147 -2
  179. package/skills/autopsy/SKILL.md +335 -335
  180. package/skills/ba/SKILL.md +85 -1
  181. package/skills/brainstorm/SKILL.md +380 -342
  182. package/skills/browser-pilot/SKILL.md +169 -168
  183. package/skills/constraint-check/SKILL.md +165 -165
  184. package/skills/context-engine/SKILL.md +408 -404
  185. package/skills/cook/SKILL.md +917 -863
  186. package/skills/db/SKILL.md +273 -273
  187. package/skills/debug/SKILL.md +465 -465
  188. package/skills/dependency-doctor/SKILL.md +265 -235
  189. package/skills/deploy/SKILL.md +274 -231
  190. package/skills/design/DESIGN-REFERENCE.md +365 -365
  191. package/skills/design/SKILL.md +590 -589
  192. package/skills/doc-processor/SKILL.md +254 -254
  193. package/skills/docs/SKILL.md +374 -374
  194. package/skills/docs-seeker/SKILL.md +178 -177
  195. package/skills/fix/SKILL.md +332 -330
  196. package/skills/git/SKILL.md +339 -339
  197. package/skills/hallucination-guard/SKILL.md +220 -219
  198. package/skills/incident/SKILL.md +254 -253
  199. package/skills/integrity-check/SKILL.md +169 -169
  200. package/skills/journal/SKILL.md +241 -240
  201. package/skills/launch/SKILL.md +344 -344
  202. package/skills/logic-guardian/SKILL.md +269 -251
  203. package/skills/marketing/SKILL.md +351 -289
  204. package/skills/mcp-builder/SKILL.md +425 -425
  205. package/skills/neural-memory/SKILL.md +359 -362
  206. package/skills/onboard/SKILL.md +432 -403
  207. package/skills/onboard/references/invariants-template.md +76 -0
  208. package/skills/onboard/scripts/detect-invariants.js +439 -0
  209. package/skills/onboard/scripts/inject-claude-md.js +150 -0
  210. package/skills/onboard/scripts/onboard-invariants.js +194 -0
  211. package/skills/perf/SKILL.md +347 -346
  212. package/skills/plan/SKILL.md +435 -428
  213. package/skills/preflight/SKILL.md +415 -415
  214. package/skills/problem-solver/SKILL.md +380 -284
  215. package/skills/rescue/SKILL.md +474 -474
  216. package/skills/research/SKILL.md +4 -0
  217. package/skills/retro/SKILL.md +3 -1
  218. package/skills/review/SKILL.md +614 -588
  219. package/skills/review-intake/SKILL.md +249 -249
  220. package/skills/safeguard/SKILL.md +200 -200
  221. package/skills/sast/SKILL.md +190 -190
  222. package/skills/scaffold/SKILL.md +328 -287
  223. package/skills/scope-guard/SKILL.md +183 -180
  224. package/skills/scout/SKILL.md +269 -263
  225. package/skills/sentinel/SKILL.md +384 -381
  226. package/skills/sentinel-env/SKILL.md +254 -254
  227. package/skills/sequential-thinking/SKILL.md +234 -234
  228. package/skills/session-bridge/SKILL.md +595 -543
  229. package/skills/session-bridge/scripts/load-invariants.js +397 -0
  230. package/skills/skill-forge/SKILL.md +581 -581
  231. package/skills/skill-router/SKILL.md +3 -0
  232. package/skills/slides/SKILL.md +19 -0
  233. package/skills/surgeon/SKILL.md +215 -215
  234. package/skills/team/SKILL.md +557 -537
  235. package/skills/test/SKILL.md +620 -614
  236. package/skills/trend-scout/SKILL.md +145 -145
  237. package/skills/verification/SKILL.md +334 -326
  238. package/skills/video-creator/SKILL.md +201 -201
  239. package/skills/watchdog/SKILL.md +168 -168
  240. package/skills/worktree/SKILL.md +140 -140
@@ -1,133 +1,133 @@
1
- ---
2
- name: "cli-generation"
3
- pack: "@rune/backend"
4
- description: "Generate production-grade CLI wrappers for backend services — command groups, dual output mode (human + JSON), stateful REPL, session management with undo/redo, and pip/npm-installable packaging."
5
- model: sonnet
6
- tools: [Read, Edit, Write, Grep, Glob, Bash]
7
- ---
8
-
9
- # cli-generation
10
-
11
- Generate production-grade CLI wrappers for backend services — command groups, dual output mode (human + JSON), stateful REPL, session management with undo/redo, and pip/npm-installable packaging.
12
-
13
- #### Workflow
14
-
15
- **Step 1 — Analyze backend service surface**
16
- Map existing API endpoints, service methods, or data models to CLI command groups:
17
- ```typescript
18
- interface CLICommandGroup {
19
- name: string; // e.g., 'users', 'orders', 'config'
20
- source: string; // API route file or service class
21
- commands: CLICommand[];
22
- }
23
-
24
- interface CLICommand {
25
- name: string; // e.g., 'list', 'create', 'delete'
26
- sourceMethod: string; // e.g., 'UserService.findAll'
27
- params: CLIParam[];
28
- mutating: boolean; // true = needs confirmation/undo support
29
- }
30
- ```
31
-
32
- **Step 2 — Design dual output mode**
33
- Every command MUST support both human-readable and machine-readable output:
34
- ```typescript
35
- // Human mode (default): tables, colors, formatted text
36
- function formatHuman(data: any, format: 'table' | 'list' | 'detail'): string {
37
- if (format === 'table') return formatTable(data, { borders: true, colors: true });
38
- if (format === 'list') return data.map((d: any) => ` • ${d.name}`).join('\n');
39
- return JSON.stringify(data, null, 2);
40
- }
41
-
42
- // JSON mode (--json flag): structured output for piping/scripting
43
- function formatJSON(data: any): string {
44
- return JSON.stringify(data, null, 2);
45
- }
46
-
47
- // Error output follows same dual pattern
48
- function formatError(error: Error, jsonMode: boolean): string {
49
- if (jsonMode) return JSON.stringify({ error: error.message, type: error.constructor.name });
50
- return chalk.red(`Error: ${error.message}`);
51
- }
52
- ```
53
-
54
- **Step 3 — Implement session with undo/redo**
55
- For mutating operations, maintain session state:
56
- ```typescript
57
- interface CLISession {
58
- id: string;
59
- history: SessionSnapshot[];
60
- undoStack: SessionSnapshot[]; // max 50
61
- redoStack: SessionSnapshot[];
62
- modified: boolean;
63
- }
64
-
65
- function snapshot(session: CLISession, action: string): CLISession {
66
- return {
67
- ...session,
68
- undoStack: [...session.undoStack.slice(-49), { action, state: deepCopy(session) }],
69
- redoStack: [], // new action clears redo
70
- modified: true,
71
- };
72
- }
73
- ```
74
-
75
- **Step 4 — Build REPL mode**
76
- CLI enters REPL when invoked without subcommand:
77
- ```typescript
78
- // Click (Python) — invoke_without_command=True enters REPL
79
- @click.group(invoke_without_command=True)
80
- @click.pass_context
81
- def cli(ctx):
82
- if ctx.invoked_subcommand is None:
83
- start_repl(ctx)
84
-
85
- // Commander (Node.js) — detect no args
86
- if (process.argv.length <= 2) {
87
- startREPL({ history: '~/.myapp_history', prompt: 'myapp> ' });
88
- }
89
- ```
90
-
91
- REPL features: command history (file-persisted), auto-suggest from history, tab completion, colored prompt, help command, status bar showing connection state.
92
-
93
- **Step 5 — Package for distribution**
94
- ```bash
95
- # Python: PEP 420 namespace packages for independent installability
96
- # pyproject.toml or setup.py
97
- entry_points = {
98
- 'console_scripts': ['myapp = myapp.cli:main'],
99
- }
100
-
101
- # Node.js: bin field in package.json
102
- {
103
- "bin": { "myapp": "./bin/cli.js" },
104
- "files": ["bin/", "lib/"]
105
- }
106
- ```
107
-
108
- **Step 6 — Verify installation**
109
- After packaging: install locally (`pip install -e .` or `npm link`), verify binary on PATH (`which myapp`), run `myapp --version`, test `myapp --json` mode, and verify REPL launch.
110
-
111
- #### Example
112
-
113
- ```python
114
- # Generated CLI structure for a backend service
115
- # myapp/
116
- # ├── cli.py ← Click entry point + REPL
117
- # ├── commands/
118
- # │ ├── users.py ← User CRUD commands
119
- # │ ├── orders.py ← Order management
120
- # │ └── config.py ← Config operations
121
- # ├── core/
122
- # │ ├── session.py ← Session + undo/redo
123
- # │ └── client.py ← API client wrapper
124
- # └── utils/
125
- # ├── output.py ← Dual output (human + JSON)
126
- # └── repl.py ← REPL with prompt-toolkit
127
-
128
- # Usage:
129
- # myapp users list → human-readable table
130
- # myapp users list --json → JSON output for piping
131
- # myapp users create --name "Alice" → creates user, snapshots for undo
132
- # myapp → enters REPL mode
133
- ```
1
+ ---
2
+ name: "cli-generation"
3
+ pack: "@rune/backend"
4
+ description: "Generate production-grade CLI wrappers for backend services — command groups, dual output mode (human + JSON), stateful REPL, session management with undo/redo, and pip/npm-installable packaging."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # cli-generation
10
+
11
+ Generate production-grade CLI wrappers for backend services — command groups, dual output mode (human + JSON), stateful REPL, session management with undo/redo, and pip/npm-installable packaging.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Analyze backend service surface**
16
+ Map existing API endpoints, service methods, or data models to CLI command groups:
17
+ ```typescript
18
+ interface CLICommandGroup {
19
+ name: string; // e.g., 'users', 'orders', 'config'
20
+ source: string; // API route file or service class
21
+ commands: CLICommand[];
22
+ }
23
+
24
+ interface CLICommand {
25
+ name: string; // e.g., 'list', 'create', 'delete'
26
+ sourceMethod: string; // e.g., 'UserService.findAll'
27
+ params: CLIParam[];
28
+ mutating: boolean; // true = needs confirmation/undo support
29
+ }
30
+ ```
31
+
32
+ **Step 2 — Design dual output mode**
33
+ Every command MUST support both human-readable and machine-readable output:
34
+ ```typescript
35
+ // Human mode (default): tables, colors, formatted text
36
+ function formatHuman(data: any, format: 'table' | 'list' | 'detail'): string {
37
+ if (format === 'table') return formatTable(data, { borders: true, colors: true });
38
+ if (format === 'list') return data.map((d: any) => ` • ${d.name}`).join('\n');
39
+ return JSON.stringify(data, null, 2);
40
+ }
41
+
42
+ // JSON mode (--json flag): structured output for piping/scripting
43
+ function formatJSON(data: any): string {
44
+ return JSON.stringify(data, null, 2);
45
+ }
46
+
47
+ // Error output follows same dual pattern
48
+ function formatError(error: Error, jsonMode: boolean): string {
49
+ if (jsonMode) return JSON.stringify({ error: error.message, type: error.constructor.name });
50
+ return chalk.red(`Error: ${error.message}`);
51
+ }
52
+ ```
53
+
54
+ **Step 3 — Implement session with undo/redo**
55
+ For mutating operations, maintain session state:
56
+ ```typescript
57
+ interface CLISession {
58
+ id: string;
59
+ history: SessionSnapshot[];
60
+ undoStack: SessionSnapshot[]; // max 50
61
+ redoStack: SessionSnapshot[];
62
+ modified: boolean;
63
+ }
64
+
65
+ function snapshot(session: CLISession, action: string): CLISession {
66
+ return {
67
+ ...session,
68
+ undoStack: [...session.undoStack.slice(-49), { action, state: deepCopy(session) }],
69
+ redoStack: [], // new action clears redo
70
+ modified: true,
71
+ };
72
+ }
73
+ ```
74
+
75
+ **Step 4 — Build REPL mode**
76
+ CLI enters REPL when invoked without subcommand:
77
+ ```typescript
78
+ // Click (Python) — invoke_without_command=True enters REPL
79
+ @click.group(invoke_without_command=True)
80
+ @click.pass_context
81
+ def cli(ctx):
82
+ if ctx.invoked_subcommand is None:
83
+ start_repl(ctx)
84
+
85
+ // Commander (Node.js) — detect no args
86
+ if (process.argv.length <= 2) {
87
+ startREPL({ history: '~/.myapp_history', prompt: 'myapp> ' });
88
+ }
89
+ ```
90
+
91
+ REPL features: command history (file-persisted), auto-suggest from history, tab completion, colored prompt, help command, status bar showing connection state.
92
+
93
+ **Step 5 — Package for distribution**
94
+ ```bash
95
+ # Python: PEP 420 namespace packages for independent installability
96
+ # pyproject.toml or setup.py
97
+ entry_points = {
98
+ 'console_scripts': ['myapp = myapp.cli:main'],
99
+ }
100
+
101
+ # Node.js: bin field in package.json
102
+ {
103
+ "bin": { "myapp": "./bin/cli.js" },
104
+ "files": ["bin/", "lib/"]
105
+ }
106
+ ```
107
+
108
+ **Step 6 — Verify installation**
109
+ After packaging: install locally (`pip install -e .` or `npm link`), verify binary on PATH (`which myapp`), run `myapp --version`, test `myapp --json` mode, and verify REPL launch.
110
+
111
+ #### Example
112
+
113
+ ```python
114
+ # Generated CLI structure for a backend service
115
+ # myapp/
116
+ # ├── cli.py ← Click entry point + REPL
117
+ # ├── commands/
118
+ # │ ├── users.py ← User CRUD commands
119
+ # │ ├── orders.py ← Order management
120
+ # │ └── config.py ← Config operations
121
+ # ├── core/
122
+ # │ ├── session.py ← Session + undo/redo
123
+ # │ └── client.py ← API client wrapper
124
+ # └── utils/
125
+ # ├── output.py ← Dual output (human + JSON)
126
+ # └── repl.py ← REPL with prompt-toolkit
127
+
128
+ # Usage:
129
+ # myapp users list → human-readable table
130
+ # myapp users list --json → JSON output for piping
131
+ # myapp users create --name "Alice" → creates user, snapshots for undo
132
+ # myapp → enters REPL mode
133
+ ```
@@ -1,87 +1,87 @@
1
- ---
2
- name: "database-patterns"
3
- pack: "@rune/backend"
4
- description: "Database design and query patterns — schema design, migrations, indexing strategies, N+1 prevention, soft deletes, read replicas, connection pooling, seeding."
5
- model: sonnet
6
- tools: [Read, Edit, Write, Grep, Glob, Bash]
7
- ---
8
-
9
- # database-patterns
10
-
11
- Database design and query patterns — schema design, migrations, indexing strategies, N+1 prevention, soft deletes, read replicas, connection pooling, seeding.
12
-
13
- #### Workflow
14
-
15
- **Step 1 — Detect ORM and query patterns**
16
- Use Grep to find ORM usage (`prisma.`, `knex(`, `sequelize.`, `typeorm`, `drizzle`, `mongoose.`, `db.query`) and raw SQL strings. Read schema files (`schema.prisma`, `migrations/`, `models/`) to understand the data model.
17
-
18
- **Step 2 — Detect N+1 and missing indexes**
19
- Scan for loops containing database calls (a query inside `for`, `map`, `forEach` → N+1). Check foreign key columns for missing indexes. Identify queries with `WHERE` clauses on unindexed columns. Flag each with the specific query and fix.
20
-
21
- **Step 3 — Emit optimized queries**
22
- For N+1: emit eager loading (`include`, `populate`, `JOIN`). For missing indexes: emit migration files. For unsafe raw SQL: emit parameterized version. For connection pooling: check pool config and recommend sizing based on max connections.
23
-
24
- **Step 4 — Soft delete and query scoping**
25
- Emit soft delete pattern: add `deleted_at TIMESTAMPTZ` column, update all `findMany`/`findUnique` calls to include `WHERE deleted_at IS NULL`. Cascade consideration: soft-delete parent should soft-delete children (emit trigger or application-level cascade). For Prisma: emit a custom extension that injects the filter automatically. Warn about index bloat from soft-deleted rows — add partial index `WHERE deleted_at IS NULL` to keep index lean.
26
-
27
- **Step 5 — Read replicas, connection pooling, and seeding**
28
- Read replicas: emit query routing — writes to primary, reads to replica. Handle replication lag: do not read from replica immediately after write in the same request (use primary for the read-after-write). For Prisma: emit `$extends` with read/write client split. Connection pooling deep dive: PgBouncer in transaction mode for serverless (each query gets a connection); Prisma's built-in pool for long-running servers. Pool sizing formula: `connections = (core_count * 2) + effective_spindle_count`. Seeding: emit factory functions using `@faker-js/faker` — deterministic seeds via `faker.seed(42)` for reproducible test data.
29
-
30
- #### Example
31
-
32
- ```typescript
33
- // BEFORE: N+1 — one query per post to get author
34
- const posts = await prisma.post.findMany();
35
- for (const post of posts) {
36
- post.author = await prisma.user.findUnique({ where: { id: post.authorId } });
37
- }
38
-
39
- // AFTER: eager loading, single query with JOIN
40
- const posts = await prisma.post.findMany({
41
- include: { author: { select: { id: true, name: true, avatar: true } } },
42
- });
43
-
44
- // Migration: missing indexes + soft delete column
45
- -- Migration: add_indexes_and_soft_delete_to_posts
46
- ALTER TABLE posts ADD COLUMN deleted_at TIMESTAMPTZ;
47
- CREATE INDEX idx_posts_author_id ON posts(author_id);
48
- CREATE INDEX idx_posts_created_at ON posts(created_at DESC);
49
- CREATE INDEX idx_posts_active ON posts(author_id, created_at DESC) WHERE deleted_at IS NULL;
50
-
51
- // Prisma soft delete extension (auto-scopes all queries)
52
- const softDelete = Prisma.defineExtension({
53
- name: 'softDelete',
54
- query: {
55
- $allModels: {
56
- async findMany({ model, operation, args, query }) {
57
- args.where = { ...args.where, deletedAt: null };
58
- return query(args);
59
- },
60
- async delete({ model, args, query }) {
61
- return (query as any)({ ...args, data: { deletedAt: new Date() } } as any);
62
- },
63
- },
64
- },
65
- });
66
- const prisma = new PrismaClient().$extends(softDelete);
67
-
68
- // Read replica routing with Prisma
69
- const primaryClient = new PrismaClient({ datasources: { db: { url: PRIMARY_URL } } });
70
- const replicaClient = new PrismaClient({ datasources: { db: { url: REPLICA_URL } } });
71
- const db = { write: primaryClient, read: replicaClient };
72
- // Usage: db.write.user.create(...) vs db.read.user.findMany(...)
73
-
74
- // Factory seeding
75
- import { faker } from '@faker-js/faker';
76
- faker.seed(42); // reproducible
77
-
78
- const createUserFactory = (overrides = {}) => ({
79
- id: faker.string.uuid(),
80
- email: faker.internet.email(),
81
- name: faker.person.fullName(),
82
- createdAt: faker.date.past(),
83
- ...overrides,
84
- });
85
-
86
- await prisma.user.createMany({ data: Array.from({ length: 50 }, () => createUserFactory()) });
87
- ```
1
+ ---
2
+ name: "database-patterns"
3
+ pack: "@rune/backend"
4
+ description: "Database design and query patterns — schema design, migrations, indexing strategies, N+1 prevention, soft deletes, read replicas, connection pooling, seeding."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # database-patterns
10
+
11
+ Database design and query patterns — schema design, migrations, indexing strategies, N+1 prevention, soft deletes, read replicas, connection pooling, seeding.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Detect ORM and query patterns**
16
+ Use Grep to find ORM usage (`prisma.`, `knex(`, `sequelize.`, `typeorm`, `drizzle`, `mongoose.`, `db.query`) and raw SQL strings. Read schema files (`schema.prisma`, `migrations/`, `models/`) to understand the data model.
17
+
18
+ **Step 2 — Detect N+1 and missing indexes**
19
+ Scan for loops containing database calls (a query inside `for`, `map`, `forEach` → N+1). Check foreign key columns for missing indexes. Identify queries with `WHERE` clauses on unindexed columns. Flag each with the specific query and fix.
20
+
21
+ **Step 3 — Emit optimized queries**
22
+ For N+1: emit eager loading (`include`, `populate`, `JOIN`). For missing indexes: emit migration files. For unsafe raw SQL: emit parameterized version. For connection pooling: check pool config and recommend sizing based on max connections.
23
+
24
+ **Step 4 — Soft delete and query scoping**
25
+ Emit soft delete pattern: add `deleted_at TIMESTAMPTZ` column, update all `findMany`/`findUnique` calls to include `WHERE deleted_at IS NULL`. Cascade consideration: soft-delete parent should soft-delete children (emit trigger or application-level cascade). For Prisma: emit a custom extension that injects the filter automatically. Warn about index bloat from soft-deleted rows — add partial index `WHERE deleted_at IS NULL` to keep index lean.
26
+
27
+ **Step 5 — Read replicas, connection pooling, and seeding**
28
+ Read replicas: emit query routing — writes to primary, reads to replica. Handle replication lag: do not read from replica immediately after write in the same request (use primary for the read-after-write). For Prisma: emit `$extends` with read/write client split. Connection pooling deep dive: PgBouncer in transaction mode for serverless (each query gets a connection); Prisma's built-in pool for long-running servers. Pool sizing formula: `connections = (core_count * 2) + effective_spindle_count`. Seeding: emit factory functions using `@faker-js/faker` — deterministic seeds via `faker.seed(42)` for reproducible test data.
29
+
30
+ #### Example
31
+
32
+ ```typescript
33
+ // BEFORE: N+1 — one query per post to get author
34
+ const posts = await prisma.post.findMany();
35
+ for (const post of posts) {
36
+ post.author = await prisma.user.findUnique({ where: { id: post.authorId } });
37
+ }
38
+
39
+ // AFTER: eager loading, single query with JOIN
40
+ const posts = await prisma.post.findMany({
41
+ include: { author: { select: { id: true, name: true, avatar: true } } },
42
+ });
43
+
44
+ // Migration: missing indexes + soft delete column
45
+ -- Migration: add_indexes_and_soft_delete_to_posts
46
+ ALTER TABLE posts ADD COLUMN deleted_at TIMESTAMPTZ;
47
+ CREATE INDEX idx_posts_author_id ON posts(author_id);
48
+ CREATE INDEX idx_posts_created_at ON posts(created_at DESC);
49
+ CREATE INDEX idx_posts_active ON posts(author_id, created_at DESC) WHERE deleted_at IS NULL;
50
+
51
+ // Prisma soft delete extension (auto-scopes all queries)
52
+ const softDelete = Prisma.defineExtension({
53
+ name: 'softDelete',
54
+ query: {
55
+ $allModels: {
56
+ async findMany({ model, operation, args, query }) {
57
+ args.where = { ...args.where, deletedAt: null };
58
+ return query(args);
59
+ },
60
+ async delete({ model, args, query }) {
61
+ return (query as any)({ ...args, data: { deletedAt: new Date() } } as any);
62
+ },
63
+ },
64
+ },
65
+ });
66
+ const prisma = new PrismaClient().$extends(softDelete);
67
+
68
+ // Read replica routing with Prisma
69
+ const primaryClient = new PrismaClient({ datasources: { db: { url: PRIMARY_URL } } });
70
+ const replicaClient = new PrismaClient({ datasources: { db: { url: REPLICA_URL } } });
71
+ const db = { write: primaryClient, read: replicaClient };
72
+ // Usage: db.write.user.create(...) vs db.read.user.findMany(...)
73
+
74
+ // Factory seeding
75
+ import { faker } from '@faker-js/faker';
76
+ faker.seed(42); // reproducible
77
+
78
+ const createUserFactory = (overrides = {}) => ({
79
+ id: faker.string.uuid(),
80
+ email: faker.internet.email(),
81
+ name: faker.person.fullName(),
82
+ createdAt: faker.date.past(),
83
+ ...overrides,
84
+ });
85
+
86
+ await prisma.user.createMany({ data: Array.from({ length: 50 }, () => createUserFactory()) });
87
+ ```
@@ -1,104 +1,104 @@
1
- ---
2
- name: "middleware-patterns"
3
- pack: "@rune/backend"
4
- description: "Middleware architecture — request validation, error handling, logging, CORS, compression, graceful shutdown, health checks, request ID tracking."
5
- model: sonnet
6
- tools: [Read, Edit, Write, Grep, Glob, Bash]
7
- ---
8
-
9
- # middleware-patterns
10
-
11
- Middleware architecture — request validation, error handling, logging, CORS, compression, graceful shutdown, health checks, request ID tracking.
12
-
13
- #### Workflow
14
-
15
- **Step 1 — Audit middleware stack**
16
- Read the main server file (app.ts, server.ts, index.ts) to inventory all middleware in registration order. Check for: missing request ID generation, missing structured logging, inconsistent error responses, missing input validation, CORS misconfiguration (`*` in production).
17
-
18
- **Step 2 — Detect error handling gaps**
19
- Use Grep to find `catch` blocks, error middleware signatures (`err, req, res, next`), and unhandled promise rejections. Check if errors return consistent format (same envelope for 400, 401, 403, 404, 500). Flag any that leak stack traces or internal details in production.
20
-
21
- **Step 3 — Emit middleware improvements**
22
- For each gap, emit the middleware function: request ID (`X-Request-Id` header, UUID per request), structured JSON logger (request method, path, status, duration, request ID), global error handler with consistent envelope, Zod-based request validation middleware.
23
-
24
- **Step 4 — Compression strategy**
25
- Emit response compression middleware. Use `brotli` for static assets and pre-compressible responses (better ratio than gzip, supported by all modern clients). Use `gzip` as fallback for older clients. Conditional compression: skip for already-compressed content types (`image/*`, `video/*`, `application/zip`) — compressing these wastes CPU. In Express: use `compression` package with a `filter` function. In Fastify: `@fastify/compress` with `encodings: ['br', 'gzip']`. Minimum size threshold: do not compress responses < 1KB (overhead exceeds benefit).
26
-
27
- **Step 5 — Graceful shutdown and health checks**
28
- Graceful shutdown: on `SIGTERM`/`SIGINT`, stop accepting new connections, wait for in-flight requests to complete (timeout 30s), then close DB pools and exit. Emit the shutdown handler for Express (`server.close()`), Fastify (`fastify.close()`), and worker processes. Health check endpoints: `/health/live` (liveness — is the process alive? return 200 always unless process is broken), `/health/ready` (readiness — can it serve traffic? check DB connection, Redis connection, return 503 if dependencies are down). In Kubernetes: map liveness to `livenessProbe`, readiness to `readinessProbe`. Do NOT check external third-party APIs in readiness — only your own dependencies.
29
-
30
- #### Example
31
-
32
- ```typescript
33
- // Request ID middleware
34
- const requestId = (req, res, next) => {
35
- req.id = req.headers['x-request-id'] || crypto.randomUUID();
36
- res.setHeader('X-Request-Id', req.id);
37
- next();
38
- };
39
-
40
- // Structured error handler — consistent envelope, no stack leak
41
- const errorHandler = (err, req, res, _next) => {
42
- const status = err.status || 500;
43
- const message = status < 500 ? err.message : 'Internal server error';
44
- logger.error({ err, requestId: req.id, path: req.path });
45
- res.status(status).json({
46
- error: { code: err.code || 'INTERNAL_ERROR', message },
47
- request_id: req.id,
48
- });
49
- };
50
-
51
- // Zod validation middleware
52
- const validate = (schema: z.ZodSchema) => (req, res, next) => {
53
- const result = schema.safeParse({ body: req.body, query: req.query, params: req.params });
54
- if (!result.success) {
55
- return res.status(400).json({ error: { code: 'VALIDATION_ERROR', message: 'Invalid request', details: result.error.flatten() } });
56
- }
57
- Object.assign(req, result.data);
58
- next();
59
- };
60
-
61
- // Compression with conditional skip (Express)
62
- import compression from 'compression';
63
- app.use(compression({
64
- filter: (req, res) => {
65
- const contentType = res.getHeader('Content-Type') as string || '';
66
- if (/image|video|audio|zip|gz|br/.test(contentType)) return false;
67
- return compression.filter(req, res);
68
- },
69
- threshold: 1024, // skip responses < 1KB
70
- }));
71
-
72
- // Graceful shutdown
73
- const gracefulShutdown = async (signal: string) => {
74
- console.log(`Received ${signal}, shutting down gracefully...`);
75
- server.close(async () => {
76
- try {
77
- await prisma.$disconnect();
78
- await redis.quit();
79
- console.log('All connections closed. Exiting.');
80
- process.exit(0);
81
- } catch (err) {
82
- console.error('Error during shutdown:', err);
83
- process.exit(1);
84
- }
85
- });
86
- // Force exit after 30s if still not done
87
- setTimeout(() => { console.error('Forced shutdown after timeout'); process.exit(1); }, 30_000);
88
- };
89
- process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
90
- process.on('SIGINT', () => gracefulShutdown('SIGINT'));
91
-
92
- // Health check endpoints
93
- app.get('/health/live', (req, res) => res.json({ status: 'ok' }));
94
-
95
- app.get('/health/ready', async (req, res) => {
96
- const checks = await Promise.allSettled([
97
- prisma.$queryRaw`SELECT 1`, // DB check
98
- redis.ping(), // Redis check
99
- ]);
100
- const results = { db: checks[0].status, redis: checks[1].status };
101
- const allHealthy = checks.every(c => c.status === 'fulfilled');
102
- res.status(allHealthy ? 200 : 503).json({ status: allHealthy ? 'ready' : 'degraded', checks: results });
103
- });
104
- ```
1
+ ---
2
+ name: "middleware-patterns"
3
+ pack: "@rune/backend"
4
+ description: "Middleware architecture — request validation, error handling, logging, CORS, compression, graceful shutdown, health checks, request ID tracking."
5
+ model: sonnet
6
+ tools: [Read, Edit, Write, Grep, Glob, Bash]
7
+ ---
8
+
9
+ # middleware-patterns
10
+
11
+ Middleware architecture — request validation, error handling, logging, CORS, compression, graceful shutdown, health checks, request ID tracking.
12
+
13
+ #### Workflow
14
+
15
+ **Step 1 — Audit middleware stack**
16
+ Read the main server file (app.ts, server.ts, index.ts) to inventory all middleware in registration order. Check for: missing request ID generation, missing structured logging, inconsistent error responses, missing input validation, CORS misconfiguration (`*` in production).
17
+
18
+ **Step 2 — Detect error handling gaps**
19
+ Use Grep to find `catch` blocks, error middleware signatures (`err, req, res, next`), and unhandled promise rejections. Check if errors return consistent format (same envelope for 400, 401, 403, 404, 500). Flag any that leak stack traces or internal details in production.
20
+
21
+ **Step 3 — Emit middleware improvements**
22
+ For each gap, emit the middleware function: request ID (`X-Request-Id` header, UUID per request), structured JSON logger (request method, path, status, duration, request ID), global error handler with consistent envelope, Zod-based request validation middleware.
23
+
24
+ **Step 4 — Compression strategy**
25
+ Emit response compression middleware. Use `brotli` for static assets and pre-compressible responses (better ratio than gzip, supported by all modern clients). Use `gzip` as fallback for older clients. Conditional compression: skip for already-compressed content types (`image/*`, `video/*`, `application/zip`) — compressing these wastes CPU. In Express: use `compression` package with a `filter` function. In Fastify: `@fastify/compress` with `encodings: ['br', 'gzip']`. Minimum size threshold: do not compress responses < 1KB (overhead exceeds benefit).
26
+
27
+ **Step 5 — Graceful shutdown and health checks**
28
+ Graceful shutdown: on `SIGTERM`/`SIGINT`, stop accepting new connections, wait for in-flight requests to complete (timeout 30s), then close DB pools and exit. Emit the shutdown handler for Express (`server.close()`), Fastify (`fastify.close()`), and worker processes. Health check endpoints: `/health/live` (liveness — is the process alive? return 200 always unless process is broken), `/health/ready` (readiness — can it serve traffic? check DB connection, Redis connection, return 503 if dependencies are down). In Kubernetes: map liveness to `livenessProbe`, readiness to `readinessProbe`. Do NOT check external third-party APIs in readiness — only your own dependencies.
29
+
30
+ #### Example
31
+
32
+ ```typescript
33
+ // Request ID middleware
34
+ const requestId = (req, res, next) => {
35
+ req.id = req.headers['x-request-id'] || crypto.randomUUID();
36
+ res.setHeader('X-Request-Id', req.id);
37
+ next();
38
+ };
39
+
40
+ // Structured error handler — consistent envelope, no stack leak
41
+ const errorHandler = (err, req, res, _next) => {
42
+ const status = err.status || 500;
43
+ const message = status < 500 ? err.message : 'Internal server error';
44
+ logger.error({ err, requestId: req.id, path: req.path });
45
+ res.status(status).json({
46
+ error: { code: err.code || 'INTERNAL_ERROR', message },
47
+ request_id: req.id,
48
+ });
49
+ };
50
+
51
+ // Zod validation middleware
52
+ const validate = (schema: z.ZodSchema) => (req, res, next) => {
53
+ const result = schema.safeParse({ body: req.body, query: req.query, params: req.params });
54
+ if (!result.success) {
55
+ return res.status(400).json({ error: { code: 'VALIDATION_ERROR', message: 'Invalid request', details: result.error.flatten() } });
56
+ }
57
+ Object.assign(req, result.data);
58
+ next();
59
+ };
60
+
61
+ // Compression with conditional skip (Express)
62
+ import compression from 'compression';
63
+ app.use(compression({
64
+ filter: (req, res) => {
65
+ const contentType = res.getHeader('Content-Type') as string || '';
66
+ if (/image|video|audio|zip|gz|br/.test(contentType)) return false;
67
+ return compression.filter(req, res);
68
+ },
69
+ threshold: 1024, // skip responses < 1KB
70
+ }));
71
+
72
+ // Graceful shutdown
73
+ const gracefulShutdown = async (signal: string) => {
74
+ console.log(`Received ${signal}, shutting down gracefully...`);
75
+ server.close(async () => {
76
+ try {
77
+ await prisma.$disconnect();
78
+ await redis.quit();
79
+ console.log('All connections closed. Exiting.');
80
+ process.exit(0);
81
+ } catch (err) {
82
+ console.error('Error during shutdown:', err);
83
+ process.exit(1);
84
+ }
85
+ });
86
+ // Force exit after 30s if still not done
87
+ setTimeout(() => { console.error('Forced shutdown after timeout'); process.exit(1); }, 30_000);
88
+ };
89
+ process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
90
+ process.on('SIGINT', () => gracefulShutdown('SIGINT'));
91
+
92
+ // Health check endpoints
93
+ app.get('/health/live', (req, res) => res.json({ status: 'ok' }));
94
+
95
+ app.get('/health/ready', async (req, res) => {
96
+ const checks = await Promise.allSettled([
97
+ prisma.$queryRaw`SELECT 1`, // DB check
98
+ redis.ping(), // Redis check
99
+ ]);
100
+ const results = { db: checks[0].status, redis: checks[1].status };
101
+ const allHealthy = checks.every(c => c.status === 'fulfilled');
102
+ res.status(allHealthy ? 200 : 503).json({ status: allHealthy ? 'ready' : 'degraded', checks: results });
103
+ });
104
+ ```