@su-record/vibe 2.6.17 → 2.6.18

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 (238) hide show
  1. package/CLAUDE.md +681 -681
  2. package/LICENSE +21 -21
  3. package/README.md +235 -239
  4. package/agents/architect-low.md +41 -41
  5. package/agents/architect-medium.md +59 -59
  6. package/agents/architect.md +80 -80
  7. package/agents/build-error-resolver.md +115 -115
  8. package/agents/compounder.md +261 -261
  9. package/agents/diagrammer.md +178 -178
  10. package/agents/e2e-tester.md +266 -266
  11. package/agents/explorer-low.md +42 -42
  12. package/agents/explorer-medium.md +59 -59
  13. package/agents/explorer.md +48 -48
  14. package/agents/implementer-low.md +43 -43
  15. package/agents/implementer-medium.md +52 -52
  16. package/agents/implementer.md +54 -54
  17. package/agents/refactor-cleaner.md +143 -143
  18. package/agents/research/best-practices-agent.md +199 -199
  19. package/agents/research/codebase-patterns-agent.md +157 -157
  20. package/agents/research/framework-docs-agent.md +188 -188
  21. package/agents/research/security-advisory-agent.md +213 -213
  22. package/agents/review/architecture-reviewer.md +107 -107
  23. package/agents/review/complexity-reviewer.md +116 -116
  24. package/agents/review/data-integrity-reviewer.md +88 -88
  25. package/agents/review/git-history-reviewer.md +103 -103
  26. package/agents/review/performance-reviewer.md +86 -86
  27. package/agents/review/python-reviewer.md +150 -150
  28. package/agents/review/rails-reviewer.md +139 -139
  29. package/agents/review/react-reviewer.md +144 -144
  30. package/agents/review/security-reviewer.md +80 -80
  31. package/agents/review/simplicity-reviewer.md +140 -140
  32. package/agents/review/test-coverage-reviewer.md +116 -116
  33. package/agents/review/typescript-reviewer.md +127 -127
  34. package/agents/searcher.md +54 -54
  35. package/agents/simplifier.md +120 -120
  36. package/agents/tester.md +49 -49
  37. package/agents/ui-previewer.md +268 -268
  38. package/commands/vibe.analyze.md +356 -356
  39. package/commands/vibe.reason.md +329 -329
  40. package/commands/vibe.review.md +412 -412
  41. package/commands/vibe.run.md +1266 -1266
  42. package/commands/vibe.spec.md +1054 -1054
  43. package/commands/vibe.spec.review.md +319 -319
  44. package/commands/vibe.trace.md +161 -161
  45. package/commands/vibe.utils.md +376 -376
  46. package/commands/vibe.verify.md +375 -375
  47. package/dist/cli/collaborator.js +52 -52
  48. package/dist/cli/detect.js +32 -32
  49. package/dist/cli/hud.js +20 -20
  50. package/dist/cli/index.d.ts.map +1 -1
  51. package/dist/cli/index.js +120 -118
  52. package/dist/cli/index.js.map +1 -1
  53. package/dist/cli/llm.js +144 -144
  54. package/dist/cli/postinstall.d.ts +1 -0
  55. package/dist/cli/postinstall.d.ts.map +1 -1
  56. package/dist/cli/postinstall.js +859 -859
  57. package/dist/cli/postinstall.js.map +1 -1
  58. package/dist/cli/setup/ProjectSetup.d.ts +2 -2
  59. package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
  60. package/dist/cli/setup/ProjectSetup.js +51 -17
  61. package/dist/cli/setup/ProjectSetup.js.map +1 -1
  62. package/dist/lib/DeepInit.js +24 -24
  63. package/dist/lib/IterationTracker.js +11 -11
  64. package/dist/lib/PythonParser.js +108 -108
  65. package/dist/lib/ReviewRace.js +96 -96
  66. package/dist/lib/SkillFrontmatter.js +28 -28
  67. package/dist/lib/SkillQualityGate.js +9 -9
  68. package/dist/lib/SkillRepository.js +159 -159
  69. package/dist/lib/UltraQA.js +77 -77
  70. package/dist/lib/gemini-api.js +5 -5
  71. package/dist/lib/gpt-api.js +4 -4
  72. package/dist/lib/memory/KnowledgeGraph.js +4 -4
  73. package/dist/lib/memory/MemorySearch.js +20 -20
  74. package/dist/lib/memory/MemoryStorage.js +64 -64
  75. package/dist/orchestrator/AgentManager.js +12 -12
  76. package/dist/orchestrator/MultiLlmResearch.js +8 -8
  77. package/dist/orchestrator/SmartRouter.js +11 -11
  78. package/dist/orchestrator/SwarmOrchestrator.test.js +16 -16
  79. package/dist/orchestrator/parallelResearch.js +24 -24
  80. package/dist/tools/convention/analyzeComplexity.test.js +115 -115
  81. package/dist/tools/convention/validateCodeQuality.test.js +104 -104
  82. package/dist/tools/spec/prdParser.test.js +171 -171
  83. package/dist/tools/spec/specGenerator.js +169 -169
  84. package/dist/tools/spec/traceabilityMatrix.js +64 -64
  85. package/dist/tools/spec/traceabilityMatrix.test.js +28 -28
  86. package/hooks/hooks.json +222 -222
  87. package/hooks/scripts/code-check.js +22 -22
  88. package/hooks/scripts/code-review.js +22 -22
  89. package/hooks/scripts/complexity.js +22 -22
  90. package/hooks/scripts/compound.js +23 -23
  91. package/hooks/scripts/context-save.js +33 -33
  92. package/hooks/scripts/gemini-ui-gen.js +281 -281
  93. package/hooks/scripts/generate-brand-assets.js +474 -474
  94. package/hooks/scripts/hud-multiline.js +262 -262
  95. package/hooks/scripts/hud-status.js +291 -291
  96. package/hooks/scripts/keyword-detector.js +214 -214
  97. package/hooks/scripts/llm-orchestrate.js +171 -171
  98. package/hooks/scripts/post-edit.js +97 -97
  99. package/hooks/scripts/post-tool-verify.js +210 -210
  100. package/hooks/scripts/pre-tool-guard.js +125 -125
  101. package/hooks/scripts/recall.js +22 -22
  102. package/hooks/scripts/session-start.js +30 -30
  103. package/hooks/scripts/skill-injector.js +191 -191
  104. package/hooks/scripts/utils.js +97 -97
  105. package/languages/csharp-unity.md +515 -515
  106. package/languages/gdscript-godot.md +470 -470
  107. package/languages/ruby-rails.md +489 -489
  108. package/languages/typescript-angular.md +433 -433
  109. package/languages/typescript-astro.md +416 -416
  110. package/languages/typescript-electron.md +406 -406
  111. package/languages/typescript-nestjs.md +524 -524
  112. package/languages/typescript-svelte.md +407 -407
  113. package/languages/typescript-tauri.md +365 -365
  114. package/package.json +84 -84
  115. package/skills/brand-assets.md +141 -141
  116. package/skills/commerce-patterns.md +361 -361
  117. package/skills/context7-usage.md +102 -102
  118. package/skills/e2e-commerce.md +304 -304
  119. package/skills/frontend-design.md +92 -92
  120. package/skills/git-worktree.md +181 -181
  121. package/skills/parallel-research.md +77 -77
  122. package/skills/priority-todos.md +239 -239
  123. package/skills/seo-checklist.md +244 -244
  124. package/skills/tool-fallback.md +190 -190
  125. package/skills/vibe-capabilities.md +161 -161
  126. package/vibe/constitution.md +227 -227
  127. package/vibe/rules/core/communication-guide.md +98 -98
  128. package/vibe/rules/core/development-philosophy.md +52 -52
  129. package/vibe/rules/core/quick-start.md +102 -102
  130. package/vibe/rules/quality/bdd-contract-testing.md +393 -393
  131. package/vibe/rules/quality/checklist.md +276 -276
  132. package/vibe/rules/quality/testing-strategy.md +440 -440
  133. package/vibe/rules/standards/anti-patterns.md +541 -541
  134. package/vibe/rules/standards/code-structure.md +291 -291
  135. package/vibe/rules/standards/complexity-metrics.md +313 -313
  136. package/vibe/rules/standards/naming-conventions.md +198 -198
  137. package/vibe/setup.sh +31 -31
  138. package/vibe/templates/constitution-template.md +252 -252
  139. package/vibe/templates/contract-backend-template.md +526 -526
  140. package/vibe/templates/contract-frontend-template.md +599 -599
  141. package/vibe/templates/feature-template.md +96 -96
  142. package/vibe/templates/spec-template.md +221 -221
  143. package/dist/cli/mcp.d.ts +0 -49
  144. package/dist/cli/mcp.d.ts.map +0 -1
  145. package/dist/cli/mcp.js +0 -169
  146. package/dist/cli/mcp.js.map +0 -1
  147. package/dist/lib/gemini-mcp.d.ts +0 -10
  148. package/dist/lib/gemini-mcp.d.ts.map +0 -1
  149. package/dist/lib/gemini-mcp.js +0 -353
  150. package/dist/lib/gemini-mcp.js.map +0 -1
  151. package/dist/lib/gpt-mcp.d.ts +0 -10
  152. package/dist/lib/gpt-mcp.d.ts.map +0 -1
  153. package/dist/lib/gpt-mcp.js +0 -352
  154. package/dist/lib/gpt-mcp.js.map +0 -1
  155. package/dist/tools/analytics/getUsageAnalytics.d.ts +0 -10
  156. package/dist/tools/analytics/getUsageAnalytics.d.ts.map +0 -1
  157. package/dist/tools/analytics/getUsageAnalytics.js +0 -246
  158. package/dist/tools/analytics/getUsageAnalytics.js.map +0 -1
  159. package/dist/tools/analytics/index.d.ts +0 -5
  160. package/dist/tools/analytics/index.d.ts.map +0 -1
  161. package/dist/tools/analytics/index.js +0 -5
  162. package/dist/tools/analytics/index.js.map +0 -1
  163. package/dist/tools/convention/getCodingGuide.d.ts +0 -7
  164. package/dist/tools/convention/getCodingGuide.d.ts.map +0 -1
  165. package/dist/tools/convention/getCodingGuide.js +0 -69
  166. package/dist/tools/convention/getCodingGuide.js.map +0 -1
  167. package/dist/tools/planning/analyzeRequirements.d.ts +0 -9
  168. package/dist/tools/planning/analyzeRequirements.d.ts.map +0 -1
  169. package/dist/tools/planning/analyzeRequirements.js +0 -171
  170. package/dist/tools/planning/analyzeRequirements.js.map +0 -1
  171. package/dist/tools/planning/createUserStories.d.ts +0 -9
  172. package/dist/tools/planning/createUserStories.d.ts.map +0 -1
  173. package/dist/tools/planning/createUserStories.js +0 -124
  174. package/dist/tools/planning/createUserStories.js.map +0 -1
  175. package/dist/tools/planning/featureRoadmap.d.ts +0 -10
  176. package/dist/tools/planning/featureRoadmap.d.ts.map +0 -1
  177. package/dist/tools/planning/featureRoadmap.js +0 -207
  178. package/dist/tools/planning/featureRoadmap.js.map +0 -1
  179. package/dist/tools/planning/generatePrd.d.ts +0 -11
  180. package/dist/tools/planning/generatePrd.d.ts.map +0 -1
  181. package/dist/tools/planning/generatePrd.js +0 -161
  182. package/dist/tools/planning/generatePrd.js.map +0 -1
  183. package/dist/tools/planning/index.d.ts +0 -8
  184. package/dist/tools/planning/index.d.ts.map +0 -1
  185. package/dist/tools/planning/index.js +0 -8
  186. package/dist/tools/planning/index.js.map +0 -1
  187. package/dist/tools/prompt/analyzePrompt.d.ts +0 -7
  188. package/dist/tools/prompt/analyzePrompt.d.ts.map +0 -1
  189. package/dist/tools/prompt/analyzePrompt.js +0 -150
  190. package/dist/tools/prompt/analyzePrompt.js.map +0 -1
  191. package/dist/tools/prompt/enhancePrompt.d.ts +0 -8
  192. package/dist/tools/prompt/enhancePrompt.d.ts.map +0 -1
  193. package/dist/tools/prompt/enhancePrompt.js +0 -110
  194. package/dist/tools/prompt/enhancePrompt.js.map +0 -1
  195. package/dist/tools/prompt/enhancePromptGemini.d.ts +0 -8
  196. package/dist/tools/prompt/enhancePromptGemini.d.ts.map +0 -1
  197. package/dist/tools/prompt/enhancePromptGemini.js +0 -332
  198. package/dist/tools/prompt/enhancePromptGemini.js.map +0 -1
  199. package/dist/tools/prompt/index.d.ts +0 -7
  200. package/dist/tools/prompt/index.d.ts.map +0 -1
  201. package/dist/tools/prompt/index.js +0 -7
  202. package/dist/tools/prompt/index.js.map +0 -1
  203. package/dist/tools/reasoning/applyReasoningFramework.d.ts +0 -8
  204. package/dist/tools/reasoning/applyReasoningFramework.d.ts.map +0 -1
  205. package/dist/tools/reasoning/applyReasoningFramework.js +0 -266
  206. package/dist/tools/reasoning/applyReasoningFramework.js.map +0 -1
  207. package/dist/tools/reasoning/index.d.ts +0 -5
  208. package/dist/tools/reasoning/index.d.ts.map +0 -1
  209. package/dist/tools/reasoning/index.js +0 -5
  210. package/dist/tools/reasoning/index.js.map +0 -1
  211. package/dist/tools/thinking/analyzeProblem.d.ts +0 -7
  212. package/dist/tools/thinking/analyzeProblem.d.ts.map +0 -1
  213. package/dist/tools/thinking/analyzeProblem.js +0 -55
  214. package/dist/tools/thinking/analyzeProblem.js.map +0 -1
  215. package/dist/tools/thinking/breakDownProblem.d.ts +0 -8
  216. package/dist/tools/thinking/breakDownProblem.d.ts.map +0 -1
  217. package/dist/tools/thinking/breakDownProblem.js +0 -145
  218. package/dist/tools/thinking/breakDownProblem.js.map +0 -1
  219. package/dist/tools/thinking/createThinkingChain.d.ts +0 -7
  220. package/dist/tools/thinking/createThinkingChain.d.ts.map +0 -1
  221. package/dist/tools/thinking/createThinkingChain.js +0 -44
  222. package/dist/tools/thinking/createThinkingChain.js.map +0 -1
  223. package/dist/tools/thinking/formatAsPlan.d.ts +0 -9
  224. package/dist/tools/thinking/formatAsPlan.d.ts.map +0 -1
  225. package/dist/tools/thinking/formatAsPlan.js +0 -78
  226. package/dist/tools/thinking/formatAsPlan.js.map +0 -1
  227. package/dist/tools/thinking/index.d.ts +0 -10
  228. package/dist/tools/thinking/index.d.ts.map +0 -1
  229. package/dist/tools/thinking/index.js +0 -10
  230. package/dist/tools/thinking/index.js.map +0 -1
  231. package/dist/tools/thinking/stepByStepAnalysis.d.ts +0 -8
  232. package/dist/tools/thinking/stepByStepAnalysis.d.ts.map +0 -1
  233. package/dist/tools/thinking/stepByStepAnalysis.js +0 -63
  234. package/dist/tools/thinking/stepByStepAnalysis.js.map +0 -1
  235. package/dist/tools/thinking/thinkAloudProcess.d.ts +0 -8
  236. package/dist/tools/thinking/thinkAloudProcess.d.ts.map +0 -1
  237. package/dist/tools/thinking/thinkAloudProcess.js +0 -80
  238. package/dist/tools/thinking/thinkAloudProcess.js.map +0 -1
@@ -1,406 +1,406 @@
1
- # TypeScript + Electron Quality Rules
2
-
3
- ## Core Principles (inherited from core)
4
-
5
- ```markdown
6
- # Core Principles (inherited from core)
7
- Single Responsibility (SRP)
8
- No Duplication (DRY)
9
- Reusability
10
- Low Complexity
11
- Function <= 30 lines
12
- Nesting <= 3 levels
13
- Cyclomatic complexity <= 10
14
- ```
15
-
16
- ## Electron Architecture Understanding
17
-
18
- ```text
19
- Main Process (Node.js)
20
- - App lifecycle management
21
- - System APIs (file, network)
22
- - BrowserWindow creation/management
23
-
24
- Preload Script (Isolated Context)
25
- - Expose APIs via contextBridge
26
- - Main <-> Renderer bridge
27
-
28
- Renderer Process (Chromium)
29
- - UI rendering (React/Vue/etc)
30
- - Use window.electronAPI
31
- ```
32
-
33
- ## TypeScript/Electron Specific Rules
34
-
35
- ### 1. Process Separation Required
36
-
37
- ```typescript
38
- // Bad: Direct Node.js usage in Renderer (security vulnerability)
39
- // nodeIntegration: true is prohibited!
40
-
41
- // Good: Main Process (main.ts)
42
- import { app, BrowserWindow, ipcMain } from 'electron';
43
- import path from 'path';
44
-
45
- function createWindow(): BrowserWindow {
46
- const win = new BrowserWindow({
47
- width: 800,
48
- height: 600,
49
- webPreferences: {
50
- preload: path.join(__dirname, 'preload.js'),
51
- contextIsolation: true, // Required!
52
- nodeIntegration: false, // Required!
53
- sandbox: true // Recommended
54
- }
55
- });
56
-
57
- win.loadFile('index.html');
58
- return win;
59
- }
60
-
61
- app.whenReady().then(createWindow);
62
- ```
63
-
64
- ### 2. Preload Script Pattern
65
-
66
- ```typescript
67
- // preload.ts
68
- import { contextBridge, ipcRenderer } from 'electron';
69
-
70
- // Good: Type definition
71
- interface ElectronAPI {
72
- readFile: (path: string) => Promise<string>;
73
- writeFile: (path: string, content: string) => Promise<void>;
74
- onFileChanged: (callback: (path: string) => void) => () => void;
75
- platform: NodeJS.Platform;
76
- }
77
-
78
- // Good: Safely expose API
79
- contextBridge.exposeInMainWorld('electronAPI', {
80
- readFile: (path: string) => ipcRenderer.invoke('read-file', path),
81
- writeFile: (path: string, content: string) =>
82
- ipcRenderer.invoke('write-file', path, content),
83
- onFileChanged: (callback: (path: string) => void) => {
84
- const handler = (_event: Electron.IpcRendererEvent, path: string) => callback(path);
85
- ipcRenderer.on('file-changed', handler);
86
- return () => ipcRenderer.removeListener('file-changed', handler);
87
- },
88
- platform: process.platform
89
- } satisfies ElectronAPI);
90
-
91
- // Good: Type declaration (for use in renderer)
92
- declare global {
93
- interface Window {
94
- electronAPI: ElectronAPI;
95
- }
96
- }
97
- ```
98
-
99
- ### 3. IPC Communication Type Safety
100
-
101
- ```typescript
102
- // shared/ipc-types.ts
103
- export interface IpcChannels {
104
- 'read-file': { args: [string]; return: string };
105
- 'write-file': { args: [string, string]; return: void };
106
- 'get-app-info': { args: []; return: AppInfo };
107
- }
108
-
109
- export interface AppInfo {
110
- version: string;
111
- name: string;
112
- paths: {
113
- userData: string;
114
- temp: string;
115
- };
116
- }
117
-
118
- // main.ts
119
- import { ipcMain } from 'electron';
120
- import fs from 'fs/promises';
121
-
122
- // Good: Type-safe handler
123
- ipcMain.handle('read-file', async (_event, path: string): Promise<string> => {
124
- return fs.readFile(path, 'utf-8');
125
- });
126
-
127
- ipcMain.handle('write-file', async (_event, path: string, content: string): Promise<void> => {
128
- await fs.writeFile(path, content, 'utf-8');
129
- });
130
-
131
- ipcMain.handle('get-app-info', async (): Promise<AppInfo> => {
132
- return {
133
- version: app.getVersion(),
134
- name: app.getName(),
135
- paths: {
136
- userData: app.getPath('userData'),
137
- temp: app.getPath('temp')
138
- }
139
- };
140
- });
141
- ```
142
-
143
- ### 4. IPC Usage in Renderer
144
-
145
- ```typescript
146
- // renderer/hooks/useElectron.ts
147
-
148
- // Good: Custom Hook
149
- function useFileReader() {
150
- const [content, setContent] = useState<string | null>(null);
151
- const [loading, setLoading] = useState(false);
152
- const [error, setError] = useState<string | null>(null);
153
-
154
- const readFile = useCallback(async (path: string) => {
155
- setLoading(true);
156
- setError(null);
157
- try {
158
- const result = await window.electronAPI.readFile(path);
159
- setContent(result);
160
- return result;
161
- } catch (e) {
162
- const msg = e instanceof Error ? e.message : 'Unknown error';
163
- setError(msg);
164
- throw e;
165
- } finally {
166
- setLoading(false);
167
- }
168
- }, []);
169
-
170
- return { content, loading, error, readFile };
171
- }
172
-
173
- // Good: Event subscription Hook
174
- function useFileWatcher(onChanged: (path: string) => void) {
175
- useEffect(() => {
176
- const unsubscribe = window.electronAPI.onFileChanged(onChanged);
177
- return unsubscribe;
178
- }, [onChanged]);
179
- }
180
- ```
181
-
182
- ### 5. Window Management
183
-
184
- ```typescript
185
- // main.ts
186
- import { BrowserWindow, screen } from 'electron';
187
-
188
- // Good: Save/restore window state
189
- interface WindowState {
190
- x?: number;
191
- y?: number;
192
- width: number;
193
- height: number;
194
- isMaximized: boolean;
195
- }
196
-
197
- function createWindowWithState(): BrowserWindow {
198
- const state = loadWindowState();
199
-
200
- const win = new BrowserWindow({
201
- x: state.x,
202
- y: state.y,
203
- width: state.width,
204
- height: state.height,
205
- webPreferences: {
206
- preload: path.join(__dirname, 'preload.js'),
207
- contextIsolation: true,
208
- nodeIntegration: false
209
- }
210
- });
211
-
212
- if (state.isMaximized) {
213
- win.maximize();
214
- }
215
-
216
- // Save state on change
217
- win.on('close', () => {
218
- saveWindowState({
219
- ...win.getBounds(),
220
- isMaximized: win.isMaximized()
221
- });
222
- });
223
-
224
- return win;
225
- }
226
-
227
- // Good: Multiple window management
228
- const windows = new Map<string, BrowserWindow>();
229
-
230
- function getOrCreateWindow(id: string): BrowserWindow {
231
- const existing = windows.get(id);
232
- if (existing && !existing.isDestroyed()) {
233
- existing.focus();
234
- return existing;
235
- }
236
-
237
- const win = new BrowserWindow({ /* ... */ });
238
- windows.set(id, win);
239
- win.on('closed', () => windows.delete(id));
240
- return win;
241
- }
242
- ```
243
-
244
- ### 6. Menu Configuration
245
-
246
- ```typescript
247
- import { Menu, MenuItemConstructorOptions } from 'electron';
248
-
249
- // Good: Platform-specific menu
250
- function createMenu(): Menu {
251
- const isMac = process.platform === 'darwin';
252
-
253
- const template: MenuItemConstructorOptions[] = [
254
- ...(isMac ? [{
255
- label: app.name,
256
- submenu: [
257
- { role: 'about' as const },
258
- { type: 'separator' as const },
259
- { role: 'quit' as const }
260
- ]
261
- }] : []),
262
- {
263
- label: 'File',
264
- submenu: [
265
- {
266
- label: 'Open',
267
- accelerator: 'CmdOrCtrl+O',
268
- click: () => handleOpen()
269
- },
270
- {
271
- label: 'Save',
272
- accelerator: 'CmdOrCtrl+S',
273
- click: () => handleSave()
274
- },
275
- { type: 'separator' },
276
- isMac ? { role: 'close' } : { role: 'quit' }
277
- ]
278
- }
279
- ];
280
-
281
- return Menu.buildFromTemplate(template);
282
- }
283
- ```
284
-
285
- ### 7. Auto Update
286
-
287
- ```typescript
288
- import { autoUpdater } from 'electron-updater';
289
-
290
- // Good: Auto update setup
291
- function setupAutoUpdater(): void {
292
- autoUpdater.autoDownload = false;
293
- autoUpdater.autoInstallOnAppQuit = true;
294
-
295
- autoUpdater.on('update-available', (info) => {
296
- // Notify user
297
- dialog.showMessageBox({
298
- type: 'info',
299
- title: 'Update Available',
300
- message: `Version ${info.version} is available.`,
301
- buttons: ['Download', 'Later']
302
- }).then(({ response }) => {
303
- if (response === 0) {
304
- autoUpdater.downloadUpdate();
305
- }
306
- });
307
- });
308
-
309
- autoUpdater.on('update-downloaded', () => {
310
- dialog.showMessageBox({
311
- type: 'info',
312
- title: 'Update Ready',
313
- message: 'Restart to install update?',
314
- buttons: ['Restart', 'Later']
315
- }).then(({ response }) => {
316
- if (response === 0) {
317
- autoUpdater.quitAndInstall();
318
- }
319
- });
320
- });
321
-
322
- // Check for updates on app start
323
- autoUpdater.checkForUpdates();
324
- }
325
- ```
326
-
327
- ### 8. Security Checklist
328
-
329
- ```typescript
330
- // Good: Validate security settings
331
- function validateSecuritySettings(win: BrowserWindow): void {
332
- const webPrefs = win.webContents.getWebPreferences();
333
-
334
- if (webPrefs.nodeIntegration) {
335
- console.error('SECURITY: nodeIntegration should be false');
336
- }
337
- if (!webPrefs.contextIsolation) {
338
- console.error('SECURITY: contextIsolation should be true');
339
- }
340
- if (!webPrefs.sandbox) {
341
- console.warn('SECURITY: sandbox is recommended');
342
- }
343
- }
344
-
345
- // Good: Handle external links
346
- win.webContents.setWindowOpenHandler(({ url }) => {
347
- // Open external URLs in system browser
348
- if (url.startsWith('https://')) {
349
- shell.openExternal(url);
350
- }
351
- return { action: 'deny' };
352
- });
353
- ```
354
-
355
- ## Recommended Folder Structure
356
-
357
- ```text
358
- my-electron-app/
359
- ├── src/
360
- │ ├── main/ # Main Process
361
- │ │ ├── main.ts
362
- │ │ ├── ipc-handlers.ts
363
- │ │ └── menu.ts
364
- │ ├── preload/ # Preload Scripts
365
- │ │ └── preload.ts
366
- │ ├── renderer/ # Renderer (React/Vue)
367
- │ │ ├── components/
368
- │ │ ├── hooks/
369
- │ │ └── App.tsx
370
- │ └── shared/ # Shared types
371
- │ └── ipc-types.ts
372
- ├── electron-builder.yml
373
- └── package.json
374
- ```
375
-
376
- ## Build Configuration (electron-builder)
377
-
378
- ```yaml
379
- # electron-builder.yml
380
- appId: com.example.myapp
381
- productName: MyApp
382
- directories:
383
- output: dist
384
- files:
385
- - "build/**/*"
386
- - "node_modules/**/*"
387
- mac:
388
- target: [dmg, zip]
389
- category: public.app-category.developer-tools
390
- win:
391
- target: [nsis, portable]
392
- linux:
393
- target: [AppImage, deb]
394
- ```
395
-
396
- ## Checklist
397
-
398
- - [ ] `contextIsolation: true` configured
399
- - [ ] `nodeIntegration: false` configured
400
- - [ ] Expose APIs only through preload script
401
- - [ ] Define IPC channel types
402
- - [ ] Handle external links (setWindowOpenHandler)
403
- - [ ] Save/restore window state
404
- - [ ] Auto update setup
405
- - [ ] Platform-specific menu configuration
406
- - [ ] CSP header configured
1
+ # TypeScript + Electron Quality Rules
2
+
3
+ ## Core Principles (inherited from core)
4
+
5
+ ```markdown
6
+ # Core Principles (inherited from core)
7
+ Single Responsibility (SRP)
8
+ No Duplication (DRY)
9
+ Reusability
10
+ Low Complexity
11
+ Function <= 30 lines
12
+ Nesting <= 3 levels
13
+ Cyclomatic complexity <= 10
14
+ ```
15
+
16
+ ## Electron Architecture Understanding
17
+
18
+ ```text
19
+ Main Process (Node.js)
20
+ - App lifecycle management
21
+ - System APIs (file, network)
22
+ - BrowserWindow creation/management
23
+
24
+ Preload Script (Isolated Context)
25
+ - Expose APIs via contextBridge
26
+ - Main <-> Renderer bridge
27
+
28
+ Renderer Process (Chromium)
29
+ - UI rendering (React/Vue/etc)
30
+ - Use window.electronAPI
31
+ ```
32
+
33
+ ## TypeScript/Electron Specific Rules
34
+
35
+ ### 1. Process Separation Required
36
+
37
+ ```typescript
38
+ // Bad: Direct Node.js usage in Renderer (security vulnerability)
39
+ // nodeIntegration: true is prohibited!
40
+
41
+ // Good: Main Process (main.ts)
42
+ import { app, BrowserWindow, ipcMain } from 'electron';
43
+ import path from 'path';
44
+
45
+ function createWindow(): BrowserWindow {
46
+ const win = new BrowserWindow({
47
+ width: 800,
48
+ height: 600,
49
+ webPreferences: {
50
+ preload: path.join(__dirname, 'preload.js'),
51
+ contextIsolation: true, // Required!
52
+ nodeIntegration: false, // Required!
53
+ sandbox: true // Recommended
54
+ }
55
+ });
56
+
57
+ win.loadFile('index.html');
58
+ return win;
59
+ }
60
+
61
+ app.whenReady().then(createWindow);
62
+ ```
63
+
64
+ ### 2. Preload Script Pattern
65
+
66
+ ```typescript
67
+ // preload.ts
68
+ import { contextBridge, ipcRenderer } from 'electron';
69
+
70
+ // Good: Type definition
71
+ interface ElectronAPI {
72
+ readFile: (path: string) => Promise<string>;
73
+ writeFile: (path: string, content: string) => Promise<void>;
74
+ onFileChanged: (callback: (path: string) => void) => () => void;
75
+ platform: NodeJS.Platform;
76
+ }
77
+
78
+ // Good: Safely expose API
79
+ contextBridge.exposeInMainWorld('electronAPI', {
80
+ readFile: (path: string) => ipcRenderer.invoke('read-file', path),
81
+ writeFile: (path: string, content: string) =>
82
+ ipcRenderer.invoke('write-file', path, content),
83
+ onFileChanged: (callback: (path: string) => void) => {
84
+ const handler = (_event: Electron.IpcRendererEvent, path: string) => callback(path);
85
+ ipcRenderer.on('file-changed', handler);
86
+ return () => ipcRenderer.removeListener('file-changed', handler);
87
+ },
88
+ platform: process.platform
89
+ } satisfies ElectronAPI);
90
+
91
+ // Good: Type declaration (for use in renderer)
92
+ declare global {
93
+ interface Window {
94
+ electronAPI: ElectronAPI;
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### 3. IPC Communication Type Safety
100
+
101
+ ```typescript
102
+ // shared/ipc-types.ts
103
+ export interface IpcChannels {
104
+ 'read-file': { args: [string]; return: string };
105
+ 'write-file': { args: [string, string]; return: void };
106
+ 'get-app-info': { args: []; return: AppInfo };
107
+ }
108
+
109
+ export interface AppInfo {
110
+ version: string;
111
+ name: string;
112
+ paths: {
113
+ userData: string;
114
+ temp: string;
115
+ };
116
+ }
117
+
118
+ // main.ts
119
+ import { ipcMain } from 'electron';
120
+ import fs from 'fs/promises';
121
+
122
+ // Good: Type-safe handler
123
+ ipcMain.handle('read-file', async (_event, path: string): Promise<string> => {
124
+ return fs.readFile(path, 'utf-8');
125
+ });
126
+
127
+ ipcMain.handle('write-file', async (_event, path: string, content: string): Promise<void> => {
128
+ await fs.writeFile(path, content, 'utf-8');
129
+ });
130
+
131
+ ipcMain.handle('get-app-info', async (): Promise<AppInfo> => {
132
+ return {
133
+ version: app.getVersion(),
134
+ name: app.getName(),
135
+ paths: {
136
+ userData: app.getPath('userData'),
137
+ temp: app.getPath('temp')
138
+ }
139
+ };
140
+ });
141
+ ```
142
+
143
+ ### 4. IPC Usage in Renderer
144
+
145
+ ```typescript
146
+ // renderer/hooks/useElectron.ts
147
+
148
+ // Good: Custom Hook
149
+ function useFileReader() {
150
+ const [content, setContent] = useState<string | null>(null);
151
+ const [loading, setLoading] = useState(false);
152
+ const [error, setError] = useState<string | null>(null);
153
+
154
+ const readFile = useCallback(async (path: string) => {
155
+ setLoading(true);
156
+ setError(null);
157
+ try {
158
+ const result = await window.electronAPI.readFile(path);
159
+ setContent(result);
160
+ return result;
161
+ } catch (e) {
162
+ const msg = e instanceof Error ? e.message : 'Unknown error';
163
+ setError(msg);
164
+ throw e;
165
+ } finally {
166
+ setLoading(false);
167
+ }
168
+ }, []);
169
+
170
+ return { content, loading, error, readFile };
171
+ }
172
+
173
+ // Good: Event subscription Hook
174
+ function useFileWatcher(onChanged: (path: string) => void) {
175
+ useEffect(() => {
176
+ const unsubscribe = window.electronAPI.onFileChanged(onChanged);
177
+ return unsubscribe;
178
+ }, [onChanged]);
179
+ }
180
+ ```
181
+
182
+ ### 5. Window Management
183
+
184
+ ```typescript
185
+ // main.ts
186
+ import { BrowserWindow, screen } from 'electron';
187
+
188
+ // Good: Save/restore window state
189
+ interface WindowState {
190
+ x?: number;
191
+ y?: number;
192
+ width: number;
193
+ height: number;
194
+ isMaximized: boolean;
195
+ }
196
+
197
+ function createWindowWithState(): BrowserWindow {
198
+ const state = loadWindowState();
199
+
200
+ const win = new BrowserWindow({
201
+ x: state.x,
202
+ y: state.y,
203
+ width: state.width,
204
+ height: state.height,
205
+ webPreferences: {
206
+ preload: path.join(__dirname, 'preload.js'),
207
+ contextIsolation: true,
208
+ nodeIntegration: false
209
+ }
210
+ });
211
+
212
+ if (state.isMaximized) {
213
+ win.maximize();
214
+ }
215
+
216
+ // Save state on change
217
+ win.on('close', () => {
218
+ saveWindowState({
219
+ ...win.getBounds(),
220
+ isMaximized: win.isMaximized()
221
+ });
222
+ });
223
+
224
+ return win;
225
+ }
226
+
227
+ // Good: Multiple window management
228
+ const windows = new Map<string, BrowserWindow>();
229
+
230
+ function getOrCreateWindow(id: string): BrowserWindow {
231
+ const existing = windows.get(id);
232
+ if (existing && !existing.isDestroyed()) {
233
+ existing.focus();
234
+ return existing;
235
+ }
236
+
237
+ const win = new BrowserWindow({ /* ... */ });
238
+ windows.set(id, win);
239
+ win.on('closed', () => windows.delete(id));
240
+ return win;
241
+ }
242
+ ```
243
+
244
+ ### 6. Menu Configuration
245
+
246
+ ```typescript
247
+ import { Menu, MenuItemConstructorOptions } from 'electron';
248
+
249
+ // Good: Platform-specific menu
250
+ function createMenu(): Menu {
251
+ const isMac = process.platform === 'darwin';
252
+
253
+ const template: MenuItemConstructorOptions[] = [
254
+ ...(isMac ? [{
255
+ label: app.name,
256
+ submenu: [
257
+ { role: 'about' as const },
258
+ { type: 'separator' as const },
259
+ { role: 'quit' as const }
260
+ ]
261
+ }] : []),
262
+ {
263
+ label: 'File',
264
+ submenu: [
265
+ {
266
+ label: 'Open',
267
+ accelerator: 'CmdOrCtrl+O',
268
+ click: () => handleOpen()
269
+ },
270
+ {
271
+ label: 'Save',
272
+ accelerator: 'CmdOrCtrl+S',
273
+ click: () => handleSave()
274
+ },
275
+ { type: 'separator' },
276
+ isMac ? { role: 'close' } : { role: 'quit' }
277
+ ]
278
+ }
279
+ ];
280
+
281
+ return Menu.buildFromTemplate(template);
282
+ }
283
+ ```
284
+
285
+ ### 7. Auto Update
286
+
287
+ ```typescript
288
+ import { autoUpdater } from 'electron-updater';
289
+
290
+ // Good: Auto update setup
291
+ function setupAutoUpdater(): void {
292
+ autoUpdater.autoDownload = false;
293
+ autoUpdater.autoInstallOnAppQuit = true;
294
+
295
+ autoUpdater.on('update-available', (info) => {
296
+ // Notify user
297
+ dialog.showMessageBox({
298
+ type: 'info',
299
+ title: 'Update Available',
300
+ message: `Version ${info.version} is available.`,
301
+ buttons: ['Download', 'Later']
302
+ }).then(({ response }) => {
303
+ if (response === 0) {
304
+ autoUpdater.downloadUpdate();
305
+ }
306
+ });
307
+ });
308
+
309
+ autoUpdater.on('update-downloaded', () => {
310
+ dialog.showMessageBox({
311
+ type: 'info',
312
+ title: 'Update Ready',
313
+ message: 'Restart to install update?',
314
+ buttons: ['Restart', 'Later']
315
+ }).then(({ response }) => {
316
+ if (response === 0) {
317
+ autoUpdater.quitAndInstall();
318
+ }
319
+ });
320
+ });
321
+
322
+ // Check for updates on app start
323
+ autoUpdater.checkForUpdates();
324
+ }
325
+ ```
326
+
327
+ ### 8. Security Checklist
328
+
329
+ ```typescript
330
+ // Good: Validate security settings
331
+ function validateSecuritySettings(win: BrowserWindow): void {
332
+ const webPrefs = win.webContents.getWebPreferences();
333
+
334
+ if (webPrefs.nodeIntegration) {
335
+ console.error('SECURITY: nodeIntegration should be false');
336
+ }
337
+ if (!webPrefs.contextIsolation) {
338
+ console.error('SECURITY: contextIsolation should be true');
339
+ }
340
+ if (!webPrefs.sandbox) {
341
+ console.warn('SECURITY: sandbox is recommended');
342
+ }
343
+ }
344
+
345
+ // Good: Handle external links
346
+ win.webContents.setWindowOpenHandler(({ url }) => {
347
+ // Open external URLs in system browser
348
+ if (url.startsWith('https://')) {
349
+ shell.openExternal(url);
350
+ }
351
+ return { action: 'deny' };
352
+ });
353
+ ```
354
+
355
+ ## Recommended Folder Structure
356
+
357
+ ```text
358
+ my-electron-app/
359
+ ├── src/
360
+ │ ├── main/ # Main Process
361
+ │ │ ├── main.ts
362
+ │ │ ├── ipc-handlers.ts
363
+ │ │ └── menu.ts
364
+ │ ├── preload/ # Preload Scripts
365
+ │ │ └── preload.ts
366
+ │ ├── renderer/ # Renderer (React/Vue)
367
+ │ │ ├── components/
368
+ │ │ ├── hooks/
369
+ │ │ └── App.tsx
370
+ │ └── shared/ # Shared types
371
+ │ └── ipc-types.ts
372
+ ├── electron-builder.yml
373
+ └── package.json
374
+ ```
375
+
376
+ ## Build Configuration (electron-builder)
377
+
378
+ ```yaml
379
+ # electron-builder.yml
380
+ appId: com.example.myapp
381
+ productName: MyApp
382
+ directories:
383
+ output: dist
384
+ files:
385
+ - "build/**/*"
386
+ - "node_modules/**/*"
387
+ mac:
388
+ target: [dmg, zip]
389
+ category: public.app-category.developer-tools
390
+ win:
391
+ target: [nsis, portable]
392
+ linux:
393
+ target: [AppImage, deb]
394
+ ```
395
+
396
+ ## Checklist
397
+
398
+ - [ ] `contextIsolation: true` configured
399
+ - [ ] `nodeIntegration: false` configured
400
+ - [ ] Expose APIs only through preload script
401
+ - [ ] Define IPC channel types
402
+ - [ ] Handle external links (setWindowOpenHandler)
403
+ - [ ] Save/restore window state
404
+ - [ ] Auto update setup
405
+ - [ ] Platform-specific menu configuration
406
+ - [ ] CSP header configured