@hasna/skills 0.1.27 → 0.1.30

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 (671) hide show
  1. package/LICENSE +1 -10
  2. package/README.md +141 -39
  3. package/bin/index.js +30121 -27576
  4. package/bin/mcp.js +22073 -18556
  5. package/dist/cli/cli.test-utils.d.ts +15 -0
  6. package/dist/cli/commands/auth.d.ts +2 -0
  7. package/dist/cli/commands/install.d.ts +1 -1
  8. package/dist/cli/commands/runtime-mcp.d.ts +4 -0
  9. package/dist/index.d.ts +9 -4
  10. package/dist/index.js +11606 -598
  11. package/dist/lib/auth-store.d.ts +13 -0
  12. package/dist/lib/installer.d.ts +58 -55
  13. package/dist/lib/mcp-contracts.d.ts +86 -0
  14. package/dist/lib/project-state.d.ts +43 -0
  15. package/dist/lib/registry-data/business-marketing.d.ts +2 -0
  16. package/dist/lib/registry-data/communication.d.ts +2 -0
  17. package/dist/lib/registry-data/content-generation.d.ts +2 -0
  18. package/dist/lib/registry-data/data-analysis.d.ts +2 -0
  19. package/dist/lib/registry-data/design-branding.d.ts +2 -0
  20. package/dist/lib/registry-data/development-tools.d.ts +2 -0
  21. package/dist/lib/registry-data/education-learning.d.ts +2 -0
  22. package/dist/lib/registry-data/event-management.d.ts +2 -0
  23. package/dist/lib/registry-data/finance-compliance.d.ts +2 -0
  24. package/dist/lib/registry-data/health-wellness.d.ts +2 -0
  25. package/dist/lib/registry-data/index.d.ts +2 -0
  26. package/dist/lib/registry-data/media-processing.d.ts +2 -0
  27. package/dist/lib/registry-data/productivity-organization.d.ts +2 -0
  28. package/dist/lib/registry-data/project-management.d.ts +2 -0
  29. package/dist/lib/registry-data/research-writing.d.ts +2 -0
  30. package/dist/lib/registry-data/science-academic.d.ts +2 -0
  31. package/dist/lib/registry-data/travel-lifestyle.d.ts +2 -0
  32. package/dist/lib/registry-data/web-browser.d.ts +2 -0
  33. package/dist/lib/registry-types.d.ts +27 -0
  34. package/dist/lib/registry.d.ts +6 -18
  35. package/dist/lib/remote-registry.d.ts +3 -0
  36. package/dist/lib/run-state.d.ts +60 -0
  37. package/dist/lib/skill-aliases.d.ts +17 -0
  38. package/dist/lib/skillinfo.d.ts +5 -1
  39. package/dist/mcp/discovery-tools.d.ts +2 -0
  40. package/dist/mcp/helpers.d.ts +26 -0
  41. package/dist/mcp/http.d.ts +11 -0
  42. package/dist/mcp/index.d.ts +3 -2
  43. package/dist/mcp/operation-tools.d.ts +2 -0
  44. package/dist/mcp/resource-meta-tools.d.ts +2 -0
  45. package/dist/mcp/schedule-tools.d.ts +2 -0
  46. package/dist/mcp/server.d.ts +4 -0
  47. package/dist/types/api.d.ts +7 -4
  48. package/package.json +22 -11
  49. package/skills/_common/http-client.ts +1 -1
  50. package/skills/_common/index.ts +2 -3
  51. package/skills/_common/install.sh +5 -110
  52. package/skills/_common/installer.ts +31 -282
  53. package/skills/_common/skill-install.ts +14 -181
  54. package/skills/ad-creative-pack/SKILL.md +45 -0
  55. package/skills/ad-creative-pack/package.json +14 -0
  56. package/skills/advanced-math/package.json +3 -1
  57. package/skills/advanced-math/src/calculators.ts +118 -0
  58. package/skills/advanced-math/src/cli.ts +130 -0
  59. package/skills/advanced-math/src/conversion.ts +90 -0
  60. package/skills/advanced-math/src/finance.ts +75 -0
  61. package/skills/advanced-math/src/formatting.ts +95 -0
  62. package/skills/advanced-math/src/index.ts +24 -702
  63. package/skills/advanced-math/src/runtime.ts +49 -0
  64. package/skills/advanced-math/src/symbolic.ts +110 -0
  65. package/skills/advanced-math/src/types.ts +36 -0
  66. package/skills/analyze-data/SKILL.md +2 -2
  67. package/skills/analyze-data/src/analysis.ts +401 -0
  68. package/skills/analyze-data/src/cli.ts +66 -0
  69. package/skills/analyze-data/src/formatters.ts +235 -0
  70. package/skills/analyze-data/src/index.ts +6 -1027
  71. package/skills/analyze-data/src/logger.ts +36 -0
  72. package/skills/analyze-data/src/parsers.ts +57 -0
  73. package/skills/analyze-data/src/stats.ts +151 -0
  74. package/skills/analyze-data/src/types.ts +85 -0
  75. package/skills/api-docs-portal/SKILL.md +46 -0
  76. package/skills/api-docs-portal/package.json +9 -0
  77. package/skills/api-test-suite/src/index.ts +13 -0
  78. package/skills/apidocs/package.json +1 -1
  79. package/skills/apidocs/src/index.ts +3 -0
  80. package/skills/audio/package.json +2 -3
  81. package/skills/audio-cleanup-lab/SKILL.md +2 -2
  82. package/skills/audio-extract/CLAUDE.md +1 -1
  83. package/skills/audio-transcript-pack/SKILL.md +43 -0
  84. package/skills/audio-transcript-pack/package.json +10 -0
  85. package/skills/blog-article/CLAUDE.md +12 -0
  86. package/skills/blog-article/SKILL.md +45 -0
  87. package/skills/{create-blog-article → blog-article}/package.json +3 -3
  88. package/skills/brand-kit/SKILL.md +45 -0
  89. package/skills/brand-kit/package.json +14 -0
  90. package/skills/brand-photo-shoot/SKILL.md +28 -0
  91. package/skills/brand-photo-shoot/package.json +10 -0
  92. package/skills/brand-style-guide/SKILL.md +2 -2
  93. package/skills/brand-style-guide/src/index.ts +0 -0
  94. package/skills/budget-variance-analyzer/SKILL.md +2 -2
  95. package/skills/businessactivity/package.json +1 -1
  96. package/skills/businessactivity/src/index.ts +3 -0
  97. package/skills/calendar-events/src/ai-parser.ts +103 -0
  98. package/skills/calendar-events/src/api.ts +157 -0
  99. package/skills/calendar-events/src/auth.ts +22 -0
  100. package/skills/calendar-events/src/config.ts +6 -0
  101. package/skills/calendar-events/src/format.ts +96 -0
  102. package/skills/calendar-events/src/help.ts +54 -0
  103. package/skills/calendar-events/src/index.ts +21 -524
  104. package/skills/calendar-events/src/logger.ts +34 -0
  105. package/skills/calendar-events/src/types.ts +67 -0
  106. package/skills/compress-video/SKILL.md +2 -2
  107. package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.csv +16 -0
  108. package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.json +227 -0
  109. package/skills/consolelog/package.json +1 -1
  110. package/skills/consolelog/src/index.ts +3 -0
  111. package/skills/contract-review-report/SKILL.md +43 -0
  112. package/skills/contract-review-report/package.json +10 -0
  113. package/skills/convert/SKILL.md +2 -3
  114. package/skills/customer-feedback-report/SKILL.md +44 -0
  115. package/skills/customer-feedback-report/package.json +10 -0
  116. package/skills/dashboard-builder/package.json +3 -1
  117. package/skills/database-explorer/package.json +3 -1
  118. package/skills/deepresearch/README.md +4 -13
  119. package/skills/deploy/src/http-client.ts +1 -1
  120. package/skills/diff-viewer/package.json +4 -1
  121. package/skills/doc-generate/package.json +0 -1
  122. package/skills/doc-generate/src/ai.ts +50 -0
  123. package/skills/doc-generate/src/cli.ts +203 -0
  124. package/skills/doc-generate/src/dependencies.ts +44 -0
  125. package/skills/doc-generate/src/document-builder.ts +299 -0
  126. package/skills/doc-generate/src/index.ts +40 -764
  127. package/skills/doc-generate/src/markdown-parser.ts +125 -0
  128. package/skills/doc-generate/src/types.ts +68 -0
  129. package/skills/domainpurchase/SKILL.md +1 -1
  130. package/skills/domainpurchase/package.json +1 -1
  131. package/skills/domainpurchase/src/index.ts +3 -0
  132. package/skills/domainsearch/SKILL.md +1 -1
  133. package/skills/domainsearch/package.json +1 -1
  134. package/skills/domainsearch/src/index.ts +3 -0
  135. package/skills/email-sequence/SKILL.md +44 -0
  136. package/skills/email-sequence/package.json +14 -0
  137. package/skills/excel/CLAUDE.md +2 -2
  138. package/skills/experiment-power-calculator/package.json +3 -1
  139. package/skills/extract-invoice/src/cli.ts +97 -0
  140. package/skills/extract-invoice/src/extractor.ts +170 -0
  141. package/skills/extract-invoice/src/file-utils.ts +46 -0
  142. package/skills/extract-invoice/src/formatters.ts +144 -0
  143. package/skills/extract-invoice/src/index.ts +44 -629
  144. package/skills/extract-invoice/src/runtime.ts +46 -0
  145. package/skills/extract-invoice/src/types.ts +88 -0
  146. package/skills/folder-tree/package.json +3 -1
  147. package/skills/form-filler/package.json +3 -1
  148. package/skills/generate-api-client/package.json +3 -1
  149. package/skills/generate-api-client/src/generator.ts +47 -0
  150. package/skills/generate-api-client/src/index.ts +3 -777
  151. package/skills/generate-api-client/src/logger.ts +34 -0
  152. package/skills/generate-api-client/src/python-generator.ts +245 -0
  153. package/skills/generate-api-client/src/spec-loader.ts +48 -0
  154. package/skills/generate-api-client/src/type-mappers.ts +79 -0
  155. package/skills/generate-api-client/src/types.ts +76 -0
  156. package/skills/generate-api-client/src/typescript-generator.ts +247 -0
  157. package/skills/generate-book-cover/package.json +3 -1
  158. package/skills/generate-dockerfile/src/cli.ts +78 -0
  159. package/skills/generate-dockerfile/src/dockerfile-templates.ts +392 -0
  160. package/skills/generate-dockerfile/src/index.ts +12 -790
  161. package/skills/generate-dockerfile/src/logger.ts +30 -0
  162. package/skills/generate-dockerfile/src/project-detection.ts +68 -0
  163. package/skills/generate-dockerfile/src/support-files.ts +171 -0
  164. package/skills/generate-dockerfile/src/types.ts +29 -0
  165. package/skills/generate-documentation/src/ai.ts +131 -0
  166. package/skills/generate-documentation/src/cli.ts +71 -0
  167. package/skills/generate-documentation/src/code-parser.ts +300 -0
  168. package/skills/generate-documentation/src/file-processing.ts +182 -0
  169. package/skills/generate-documentation/src/index.ts +13 -753
  170. package/skills/generate-documentation/src/runtime.ts +35 -0
  171. package/skills/generate-documentation/src/types.ts +30 -0
  172. package/skills/generate-env/package.json +3 -1
  173. package/skills/generate-env/src/cli.ts +85 -0
  174. package/skills/generate-env/src/detection.ts +161 -0
  175. package/skills/generate-env/src/env-data.ts +66 -0
  176. package/skills/generate-env/src/generators.ts +240 -0
  177. package/skills/generate-env/src/index.ts +76 -676
  178. package/skills/generate-env/src/runtime.ts +30 -0
  179. package/skills/generate-env/src/types.ts +32 -0
  180. package/skills/generate-favicon/package.json +3 -1
  181. package/skills/generate-mock-data/package.json +3 -1
  182. package/skills/generate-mock-data/src/ai.ts +102 -0
  183. package/skills/generate-mock-data/src/formatters.ts +84 -0
  184. package/skills/generate-mock-data/src/generator.ts +377 -0
  185. package/skills/generate-mock-data/src/index.ts +15 -716
  186. package/skills/generate-mock-data/src/logger.ts +37 -0
  187. package/skills/generate-mock-data/src/presets.ts +110 -0
  188. package/skills/generate-mock-data/src/types.ts +21 -0
  189. package/skills/generate-pr-description/src/ai.ts +144 -0
  190. package/skills/generate-pr-description/src/cli.ts +80 -0
  191. package/skills/generate-pr-description/src/clipboard.ts +30 -0
  192. package/skills/generate-pr-description/src/formatters.ts +231 -0
  193. package/skills/generate-pr-description/src/git.ts +153 -0
  194. package/skills/generate-pr-description/src/index.ts +21 -714
  195. package/skills/generate-pr-description/src/types.ts +49 -0
  196. package/skills/generate-presentation/src/ai-clients.ts +61 -0
  197. package/skills/generate-presentation/src/cli.ts +126 -0
  198. package/skills/generate-presentation/src/index.ts +3 -751
  199. package/skills/generate-presentation/src/logger.ts +67 -0
  200. package/skills/generate-presentation/src/presentation-generator.ts +425 -0
  201. package/skills/generate-presentation/src/runtime.ts +6 -0
  202. package/skills/generate-presentation/src/security.ts +12 -0
  203. package/skills/generate-presentation/src/types.ts +28 -0
  204. package/skills/generate-qrcode/package.json +4 -1
  205. package/skills/generate-regex/package.json +3 -1
  206. package/skills/generate-resume/src/cli.ts +157 -0
  207. package/skills/generate-resume/src/index.ts +13 -917
  208. package/skills/generate-resume/src/parsers.ts +95 -0
  209. package/skills/generate-resume/src/renderers.ts +538 -0
  210. package/skills/generate-resume/src/security.ts +39 -0
  211. package/skills/generate-resume/src/types.ts +86 -0
  212. package/skills/generate-social-posts/src/ai.ts +88 -0
  213. package/skills/generate-social-posts/src/cli.ts +118 -0
  214. package/skills/generate-social-posts/src/exporters.ts +126 -0
  215. package/skills/generate-social-posts/src/generator.ts +130 -0
  216. package/skills/generate-social-posts/src/index.ts +19 -709
  217. package/skills/generate-social-posts/src/platforms.ts +39 -0
  218. package/skills/generate-social-posts/src/runtime.ts +34 -0
  219. package/skills/generate-social-posts/src/source.ts +116 -0
  220. package/skills/generate-social-posts/src/types.ts +58 -0
  221. package/skills/gif-maker/package.json +4 -1
  222. package/skills/github-manager/package.json +3 -1
  223. package/skills/gmail/CLAUDE.md +1 -1
  224. package/skills/highlight-reel-generator/src/index.ts +19 -0
  225. package/skills/hook/src/commands/create.ts +20 -845
  226. package/skills/hook/src/templates/root.ts +196 -0
  227. package/skills/hook/src/templates/source.ts +647 -0
  228. package/skills/http-server/package.json +3 -1
  229. package/skills/icon-pack/README.md +28 -0
  230. package/skills/icon-pack/SKILL.md +23 -0
  231. package/skills/icon-pack/package.json +29 -0
  232. package/skills/{audio → icon-pack}/tsconfig.json +10 -12
  233. package/skills/image/package.json +1 -2
  234. package/skills/implementation-agent/package.json +3 -1
  235. package/skills/implementation-agent/src/ai-generation.ts +225 -0
  236. package/skills/implementation-agent/src/index.ts +3 -960
  237. package/skills/implementation-agent/src/minimist.d.ts +15 -0
  238. package/skills/implementation-agent/src/templates.ts +686 -0
  239. package/skills/implementation-agent/src/types.ts +53 -0
  240. package/skills/implementation-plan/package.json +3 -1
  241. package/skills/implementation-todo/package.json +3 -1
  242. package/skills/invoice/package.json +1 -1
  243. package/skills/invoice/src/index.ts +3 -0
  244. package/skills/invoice-reconciliation/SKILL.md +42 -0
  245. package/skills/invoice-reconciliation/package.json +10 -0
  246. package/skills/landing-page-pack/SKILL.md +47 -0
  247. package/skills/landing-page-pack/package.json +14 -0
  248. package/skills/latex-table-generator/package.json +3 -1
  249. package/skills/logo-design/SKILL.md +25 -44
  250. package/skills/logo-design/package.json +3 -15
  251. package/skills/lorem-generator/package.json +3 -1
  252. package/skills/lorem-generator/src/index.ts +13 -0
  253. package/skills/managehook/package.json +1 -1
  254. package/skills/managehook/src/index.ts +3 -0
  255. package/skills/managemcp/package.json +1 -1
  256. package/skills/managemcp/src/index.ts +3 -0
  257. package/skills/manageskill/package.json +1 -1
  258. package/skills/manageskill/src/index.ts +3 -0
  259. package/skills/markdown-validator/package.json +3 -1
  260. package/skills/markdown-validator/src/index.ts +1 -4
  261. package/skills/market-research-report/SKILL.md +41 -0
  262. package/skills/market-research-report/package.json +10 -0
  263. package/skills/mcp-builder/package.json +4 -1
  264. package/skills/mcp-builder/src/ai-descriptions.ts +37 -0
  265. package/skills/mcp-builder/src/generators.ts +513 -0
  266. package/skills/mcp-builder/src/index.ts +7 -908
  267. package/skills/mcp-builder/src/minimist.d.ts +15 -0
  268. package/skills/mcp-builder/src/naming.ts +12 -0
  269. package/skills/mcp-builder/src/options.ts +170 -0
  270. package/skills/mcp-builder/src/templates.ts +149 -0
  271. package/skills/mcp-builder/src/types.ts +42 -0
  272. package/skills/meeting-pack/SKILL.md +43 -0
  273. package/skills/meeting-pack/package.json +10 -0
  274. package/skills/merge-pdfs/package.json +5 -1
  275. package/skills/migration-plan-pack/SKILL.md +45 -0
  276. package/skills/migration-plan-pack/package.json +10 -0
  277. package/skills/music/package.json +2 -3
  278. package/skills/music-album/SKILL.md +37 -0
  279. package/skills/music-album/package.json +10 -0
  280. package/skills/notion-manager/package.json +3 -1
  281. package/skills/npmpublish/CLAUDE.md +5 -8
  282. package/skills/npmpublish/README.md +5 -26
  283. package/skills/npmpublish/src/index.ts +9 -147
  284. package/skills/one-page-website/SKILL.md +46 -0
  285. package/skills/one-page-website/package.json +10 -0
  286. package/skills/one-page-website/tsconfig.json +8 -0
  287. package/skills/pdf-generate/src/cli.ts +162 -0
  288. package/skills/pdf-generate/src/html.ts +84 -0
  289. package/skills/pdf-generate/src/index.ts +11 -800
  290. package/skills/pdf-generate/src/markdown.ts +27 -0
  291. package/skills/pdf-generate/src/pdf-writer.ts +78 -0
  292. package/skills/pdf-generate/src/runtime.ts +34 -0
  293. package/skills/pdf-generate/src/security.ts +37 -0
  294. package/skills/pdf-generate/src/templates.ts +311 -0
  295. package/skills/pdf-generate/src/types.ts +28 -0
  296. package/skills/pdf-read/SKILL.md +10 -10
  297. package/skills/pdf-to-dataset/SKILL.md +45 -0
  298. package/skills/pdf-to-dataset/package.json +10 -0
  299. package/skills/pdf-to-markdown/SKILL.md +49 -0
  300. package/skills/pdf-to-markdown/package.json +10 -0
  301. package/skills/pdf-to-markdown/tsconfig.json +10 -0
  302. package/skills/performance-audit-report/SKILL.md +42 -0
  303. package/skills/performance-audit-report/package.json +10 -0
  304. package/skills/persona-based-adwriter/src/index.ts +19 -0
  305. package/skills/photo-album/SKILL.md +29 -0
  306. package/skills/photo-album/package.json +9 -0
  307. package/skills/photo-album/tsconfig.json +4 -0
  308. package/skills/pitch-deck/SKILL.md +43 -0
  309. package/skills/pitch-deck/package.json +9 -0
  310. package/skills/playlist-maker/SKILL.md +33 -0
  311. package/skills/playlist-maker/package.json +9 -0
  312. package/skills/playlist-maker/tsconfig.json +4 -0
  313. package/skills/product-mockup/SKILL.md +45 -0
  314. package/skills/product-mockup/package.json +3 -20
  315. package/skills/product-mockup/tsconfig.json +3 -5
  316. package/skills/project-retro-companion/src/index.ts +19 -0
  317. package/skills/proposal-pack/SKILL.md +45 -0
  318. package/skills/proposal-pack/package.json +10 -0
  319. package/skills/read-pdf/SKILL.md +5 -4
  320. package/skills/repo-onboarding-report/SKILL.md +42 -0
  321. package/skills/repo-onboarding-report/package.json +10 -0
  322. package/skills/sales-call-recapper/src/index.ts +20 -0
  323. package/skills/salescopy/package.json +1 -1
  324. package/skills/salescopy/src/index.ts +3 -0
  325. package/skills/scaffold-project/src/ai-detect.ts +136 -0
  326. package/skills/scaffold-project/src/file-generators.ts +292 -0
  327. package/skills/scaffold-project/src/index.ts +8 -991
  328. package/skills/scaffold-project/src/project-config.ts +338 -0
  329. package/skills/scaffold-project/src/templates.ts +173 -0
  330. package/skills/scaffold-project/src/types.ts +58 -0
  331. package/skills/scientific-figure-check/package.json +3 -1
  332. package/skills/sdk-generator/SKILL.md +45 -0
  333. package/skills/sdk-generator/package.json +10 -0
  334. package/skills/sdk-generator/tsconfig.json +8 -0
  335. package/skills/security-audit/src/index.ts +25 -6
  336. package/skills/security-audit-report/SKILL.md +40 -0
  337. package/skills/security-audit-report/package.json +10 -0
  338. package/skills/seo-content-pack/SKILL.md +44 -0
  339. package/skills/seo-content-pack/package.json +9 -0
  340. package/skills/short-video-pack/SKILL.md +30 -0
  341. package/skills/short-video-pack/package.json +10 -0
  342. package/skills/skill-academic-journal-matcher/bin/cli.ts +34 -0
  343. package/skills/skill-action-item-router/bin/cli.ts +34 -0
  344. package/skills/skill-ad-creative-generator/bin/cli.ts +34 -0
  345. package/skills/skill-advanced-math/bin/cli.ts +34 -0
  346. package/skills/skill-analyze-data/bin/cli.ts +19 -0
  347. package/skills/skill-anomaly-investigator/bin/cli.ts +34 -0
  348. package/skills/skill-api-test-suite/bin/cli.ts +34 -0
  349. package/skills/skill-apidocs/bin/cli.ts +87 -0
  350. package/skills/skill-audio-cleanup-lab/bin/cli.ts +6 -0
  351. package/skills/skill-audiobook-chapter-proofer/bin/cli.ts +34 -0
  352. package/skills/skill-banner-ad-suite/bin/cli.ts +34 -0
  353. package/skills/skill-benchmark-finder/bin/cli.ts +34 -0
  354. package/skills/skill-bio-sequence-tool/bin/cli.ts +34 -0
  355. package/skills/skill-blog-topic-cluster/bin/cli.ts +34 -0
  356. package/skills/skill-brand-style-guide/bin/cli.ts +19 -0
  357. package/skills/skill-brand-voice-audit/bin/cli.ts +34 -0
  358. package/skills/skill-budget-variance-analyzer/bin/cli.ts +6 -0
  359. package/skills/skill-businessactivity/bin/cli.ts +28 -0
  360. package/skills/skill-calendar-events/bin/cli.ts +34 -0
  361. package/skills/skill-campaign-metric-brief/bin/cli.ts +34 -0
  362. package/skills/skill-campaign-moodboard/bin/cli.ts +34 -0
  363. package/skills/skill-caption-style-stylist/bin/cli.ts +34 -0
  364. package/skills/skill-chemistry-calculator/bin/cli.ts +34 -0
  365. package/skills/skill-churn-risk-notifier/bin/cli.ts +34 -0
  366. package/skills/skill-citation-formatter/bin/cli.ts +34 -0
  367. package/skills/skill-classroom-newsletter-kit/bin/cli.ts +34 -0
  368. package/skills/skill-color-palette-harmonizer/bin/cli.ts +34 -0
  369. package/skills/skill-competitor-ad-analyzer/bin/cli.ts +34 -0
  370. package/skills/skill-compliance-copy-check/bin/cli.ts +34 -0
  371. package/skills/skill-compliance-report-pack/bin/cli.ts +34 -0
  372. package/skills/skill-compress-video/bin/cli.ts +19 -0
  373. package/skills/skill-consolelog/bin/cli.ts +884 -0
  374. package/skills/skill-contract-plainlanguage/bin/cli.ts +34 -0
  375. package/skills/skill-copytone-translator/bin/cli.ts +34 -0
  376. package/skills/skill-create-blog-article/bin/cli.ts +34 -0
  377. package/skills/skill-create-ebook/bin/cli.ts +34 -0
  378. package/skills/skill-crm-note-enhancer/bin/cli.ts +34 -0
  379. package/skills/skill-customer-journey-mapper/bin/cli.ts +34 -0
  380. package/skills/skill-dashboard-builder/bin/cli.ts +34 -0
  381. package/skills/skill-dashboard-narrator/bin/cli.ts +34 -0
  382. package/skills/skill-data-anonymizer/bin/cli.ts +34 -0
  383. package/skills/skill-database-explorer/bin/cli.ts +34 -0
  384. package/skills/skill-dataset-health-check/bin/cli.ts +34 -0
  385. package/skills/skill-decision-journal/bin/cli.ts +34 -0
  386. package/skills/skill-delegation-brief-writer/bin/cli.ts +34 -0
  387. package/skills/skill-destination-briefing/bin/cli.ts +34 -0
  388. package/skills/skill-diff-viewer/bin/cli.ts +34 -0
  389. package/skills/skill-domainpurchase/bin/cli.ts +683 -0
  390. package/skills/skill-domainsearch/bin/cli.ts +410 -0
  391. package/skills/skill-educational-resource-finder/bin/cli.ts +34 -0
  392. package/skills/skill-email-campaign/bin/cli.ts +34 -0
  393. package/skills/skill-exam-readiness-check/bin/cli.ts +34 -0
  394. package/skills/skill-experiment-power-calculator/bin/cli.ts +34 -0
  395. package/skills/skill-extract-audio/bin/cli.ts +19 -0
  396. package/skills/skill-extract-frames/bin/cli.ts +34 -0
  397. package/skills/skill-extract-invoice/bin/cli.ts +34 -0
  398. package/skills/skill-family-activity-curator/bin/cli.ts +34 -0
  399. package/skills/skill-faq-packager/bin/cli.ts +34 -0
  400. package/skills/skill-feedback-survey-designer/bin/cli.ts +34 -0
  401. package/skills/skill-field-trip-planner/bin/cli.ts +34 -0
  402. package/skills/skill-file-organizer/bin/cli.ts +34 -0
  403. package/skills/skill-folder-tree/bin/cli.ts +34 -0
  404. package/skills/skill-forecast-scenario-lab/bin/cli.ts +34 -0
  405. package/skills/skill-form-filler/bin/cli.ts +34 -0
  406. package/skills/skill-generate-api-client/bin/cli.ts +34 -0
  407. package/skills/skill-generate-book-cover/bin/cli.ts +34 -0
  408. package/skills/skill-generate-chart/bin/cli.ts +34 -0
  409. package/skills/skill-generate-diagram/bin/cli.ts +34 -0
  410. package/skills/skill-generate-dockerfile/bin/cli.ts +34 -0
  411. package/skills/skill-generate-documentation/bin/cli.ts +34 -0
  412. package/skills/skill-generate-docx/bin/cli.ts +6 -0
  413. package/skills/skill-generate-env/bin/cli.ts +34 -0
  414. package/skills/skill-generate-excel/bin/cli.ts +34 -0
  415. package/skills/skill-generate-favicon/bin/cli.ts +34 -0
  416. package/skills/skill-generate-mock-data/bin/cli.ts +34 -0
  417. package/skills/skill-generate-pdf/bin/cli.ts +6 -0
  418. package/skills/skill-generate-pr-description/bin/cli.ts +34 -0
  419. package/skills/skill-generate-presentation/bin/cli.ts +34 -0
  420. package/skills/skill-generate-qrcode/bin/cli.ts +34 -0
  421. package/skills/skill-generate-regex/bin/cli.ts +34 -0
  422. package/skills/skill-generate-resume/bin/cli.ts +34 -0
  423. package/skills/skill-generate-sitemap/bin/cli.ts +34 -0
  424. package/skills/skill-generate-social-posts/bin/cli.ts +34 -0
  425. package/skills/skill-generate-sql/bin/cli.ts +34 -0
  426. package/skills/skill-gif-maker/bin/cli.ts +34 -0
  427. package/skills/skill-github-manager/bin/cli.ts +34 -0
  428. package/skills/skill-gmail/bin/cli.ts +34 -0
  429. package/skills/skill-goal-quarterly-roadmap/bin/cli.ts +34 -0
  430. package/skills/skill-grant-application-drafter/bin/cli.ts +34 -0
  431. package/skills/skill-grocery-basket-optimizer/bin/cli.ts +34 -0
  432. package/skills/skill-guest-communication-suite/bin/cli.ts +34 -0
  433. package/skills/skill-habit-reflection-digest/bin/cli.ts +34 -0
  434. package/skills/skill-highlight-reel-generator/bin/cli.ts +34 -0
  435. package/skills/skill-homework-feedback-coach/bin/cli.ts +34 -0
  436. package/skills/skill-household-maintenance-mgr/bin/cli.ts +34 -0
  437. package/skills/skill-http-server/bin/cli.ts +34 -0
  438. package/skills/skill-implementation-agent/bin/cli.ts +34 -0
  439. package/skills/skill-implementation-plan/bin/cli.ts +34 -0
  440. package/skills/skill-implementation-todo/bin/cli.ts +34 -0
  441. package/skills/skill-inbox-priority-planner/bin/cli.ts +34 -0
  442. package/skills/skill-invoice/bin/cli.ts +20 -0
  443. package/skills/skill-invoice-dispute-helper/bin/cli.ts +34 -0
  444. package/skills/skill-itinerary-architect/bin/cli.ts +34 -0
  445. package/skills/skill-jingle-composer/bin/cli.ts +34 -0
  446. package/skills/skill-kpi-digest-generator/bin/cli.ts +34 -0
  447. package/skills/skill-lab-notebook-formatter/bin/cli.ts +34 -0
  448. package/skills/skill-landing-page-copy/bin/cli.ts +34 -0
  449. package/skills/skill-latex-table-generator/bin/cli.ts +34 -0
  450. package/skills/skill-learning-style-profiler/bin/cli.ts +34 -0
  451. package/skills/skill-lesson-plan-customizer/bin/cli.ts +34 -0
  452. package/skills/skill-livestream-runofshow/bin/cli.ts +34 -0
  453. package/skills/skill-longform-structurer/bin/cli.ts +34 -0
  454. package/skills/skill-lorem-generator/bin/cli.ts +34 -0
  455. package/skills/skill-managehook/bin/cli.ts +241 -0
  456. package/skills/skill-managemcp/bin/cli.ts +241 -0
  457. package/skills/skill-manageskill/bin/cli.ts +241 -0
  458. package/skills/skill-markdown-validator/bin/cli.ts +34 -0
  459. package/skills/skill-mcp-builder/bin/cli.ts +34 -0
  460. package/skills/skill-meal-plan-designer/bin/cli.ts +34 -0
  461. package/skills/skill-meeting-insight-summarizer/bin/cli.ts +34 -0
  462. package/skills/skill-merge-pdfs/bin/cli.ts +34 -0
  463. package/skills/skill-microcopy-generator/bin/cli.ts +34 -0
  464. package/skills/skill-mindfulness-prompt-cache/bin/cli.ts +34 -0
  465. package/skills/skill-notion-manager/bin/cli.ts +34 -0
  466. package/skills/skill-onboarding-sequence-builder/bin/cli.ts +34 -0
  467. package/skills/skill-onsite-ops-checklist/bin/cli.ts +34 -0
  468. package/skills/skill-outreach-cadence-designer/bin/cli.ts +34 -0
  469. package/skills/skill-packaging-concept-studio/bin/cli.ts +34 -0
  470. package/skills/skill-packing-plan-pro/bin/cli.ts +34 -0
  471. package/skills/skill-parent-teacher-brief/bin/cli.ts +34 -0
  472. package/skills/skill-partner-kit-assembler/bin/cli.ts +34 -0
  473. package/skills/skill-payroll-change-prepper/bin/cli.ts +34 -0
  474. package/skills/skill-persona-based-adwriter/bin/cli.ts +34 -0
  475. package/skills/skill-persona-generator/bin/cli.ts +34 -0
  476. package/skills/skill-personal-daily-ops/bin/cli.ts +34 -0
  477. package/skills/skill-pet-care-scheduler/bin/cli.ts +34 -0
  478. package/skills/skill-podcast-show-notes/bin/cli.ts +34 -0
  479. package/skills/skill-presentation-theme-maker/bin/cli.ts +34 -0
  480. package/skills/skill-press-release-drafter/bin/cli.ts +34 -0
  481. package/skills/skill-print-collateral-designer/bin/cli.ts +34 -0
  482. package/skills/skill-procurement-scorecard/bin/cli.ts +34 -0
  483. package/skills/skill-product-demo-script/bin/cli.ts +34 -0
  484. package/skills/skill-product-mockup/bin/cli.ts +34 -0
  485. package/skills/skill-project-retro-companion/bin/cli.ts +34 -0
  486. package/skills/skill-proposal-redline-advisor/bin/cli.ts +34 -0
  487. package/skills/skill-regex-tester/bin/cli.ts +34 -0
  488. package/skills/skill-remove-background/bin/cli.ts +34 -0
  489. package/skills/skill-risk-disclosure-kit/bin/cli.ts +34 -0
  490. package/skills/skill-roi-comparison-tool/bin/cli.ts +34 -0
  491. package/skills/skill-sales-call-recapper/bin/cli.ts +34 -0
  492. package/skills/skill-salescopy/bin/cli.ts +20 -0
  493. package/skills/skill-scaffold-project/bin/cli.ts +34 -0
  494. package/skills/skill-scholarship-tracker/bin/cli.ts +34 -0
  495. package/skills/skill-scientific-figure-check/bin/cli.ts +34 -0
  496. package/skills/skill-seating-chart-maker/bin/cli.ts +34 -0
  497. package/skills/skill-security-audit/bin/cli.ts +34 -0
  498. package/skills/skill-seo-brief-builder/bin/cli.ts +34 -0
  499. package/skills/skill-slack-assistant/bin/cli.ts +34 -0
  500. package/skills/skill-sleep-routine-analyzer/bin/cli.ts +34 -0
  501. package/skills/skill-social-media-kit/bin/cli.ts +34 -0
  502. package/skills/skill-split-pdf/bin/cli.ts +34 -0
  503. package/skills/skill-sponsorship-proposal-lab/bin/cli.ts +34 -0
  504. package/skills/skill-spreadsheet-cleanroom/bin/cli.ts +34 -0
  505. package/skills/skill-statistical-test-selector/bin/cli.ts +34 -0
  506. package/skills/skill-stress-relief-playbook/bin/cli.ts +34 -0
  507. package/skills/skill-study-guide-builder/bin/cli.ts +34 -0
  508. package/skills/skill-subscription-spend-watcher/bin/cli.ts +34 -0
  509. package/skills/skill-subtitle/bin/cli.ts +20 -0
  510. package/skills/skill-survey-insight-extractor/bin/cli.ts +34 -0
  511. package/skills/skill-terraform-generator/bin/cli.ts +34 -0
  512. package/skills/skill-testimonial-graphics/bin/cli.ts +34 -0
  513. package/skills/skill-timesheet/bin/cli.ts +47 -0
  514. package/skills/skill-travel-budget-balancer/bin/cli.ts +34 -0
  515. package/skills/skill-validate-config/bin/cli.ts +34 -0
  516. package/skills/skill-video-cut-suggester/bin/cli.ts +34 -0
  517. package/skills/skill-video-downloader/bin/cli.ts +34 -0
  518. package/skills/skill-video-thumbnail/bin/cli.ts +34 -0
  519. package/skills/skill-voiceover-casting-assistant/bin/cli.ts +34 -0
  520. package/skills/skill-watermark/bin/cli.ts +34 -0
  521. package/skills/skill-webcrawling/bin/cli.ts +21 -0
  522. package/skills/skill-webinar-script-coach/bin/cli.ts +34 -0
  523. package/skills/skill-wellness-progress-reporter/bin/cli.ts +34 -0
  524. package/skills/skill-workout-cycle-planner/bin/cli.ts +34 -0
  525. package/skills/slack-assistant/package.json +3 -1
  526. package/skills/slide-deck-generator/SKILL.md +44 -0
  527. package/skills/slide-deck-generator/package.json +10 -0
  528. package/skills/sms/package.json +1 -1
  529. package/skills/sms/src/index.ts +15 -0
  530. package/skills/social-content-calendar/SKILL.md +45 -0
  531. package/skills/social-content-calendar/package.json +14 -0
  532. package/skills/split-pdf/package.json +4 -1
  533. package/skills/subtitle/package.json +2 -1
  534. package/skills/subtitle/src/index.ts +3 -0
  535. package/skills/terraform-generator/package.json +3 -1
  536. package/skills/test-suite-generator/SKILL.md +41 -0
  537. package/skills/test-suite-generator/package.json +10 -0
  538. package/skills/timesheet/package.json +1 -1
  539. package/skills/timesheet/src/index.ts +3 -0
  540. package/skills/transcript/SKILL.md +1 -8
  541. package/skills/validate-config/package.json +3 -1
  542. package/skills/video/package.json +6 -4
  543. package/skills/video-downloader/package.json +3 -1
  544. package/skills/video-highlight-pack/SKILL.md +44 -0
  545. package/skills/video-highlight-pack/package.json +10 -0
  546. package/skills/voiceover-jingle-pack/SKILL.md +28 -0
  547. package/skills/voiceover-jingle-pack/package.json +10 -0
  548. package/skills/watermark/package.json +6 -1
  549. package/skills/webcrawling/package.json +2 -1
  550. package/skills/write/SKILL.md +6 -6
  551. package/dist/server/serve.d.ts +0 -11
  552. package/skills/apidocs/.claude/settings.json +0 -5
  553. package/skills/audio/.env.example +0 -14
  554. package/skills/audio/QUICKSTART.md +0 -158
  555. package/skills/audio/README.md +0 -256
  556. package/skills/audio/src/index-local.ts +0 -206
  557. package/skills/audio/src/index.ts +0 -95
  558. package/skills/audio/src/providers/elevenlabs.ts +0 -115
  559. package/skills/audio/src/providers/google.ts +0 -116
  560. package/skills/audio/src/providers/minimax.ts +0 -83
  561. package/skills/audio/src/providers/openai.ts +0 -115
  562. package/skills/audio/src/types.ts +0 -79
  563. package/skills/audiobook-chapter-proofer/CLAUDE.md +0 -19
  564. package/skills/audiobook-chapter-proofer/package.json +0 -27
  565. package/skills/audiobook-chapter-proofer/src/index.ts +0 -285
  566. package/skills/browse/src/client.ts +0 -373
  567. package/skills/browse/src/index-local.ts +0 -430
  568. package/skills/browse/src/index.ts +0 -110
  569. package/skills/browse/src/sse-server.ts +0 -919
  570. package/skills/browse/src/types.ts +0 -104
  571. package/skills/consolelog/src/server/index.ts +0 -508
  572. package/skills/create-blog-article/CLAUDE.md +0 -19
  573. package/skills/create-blog-article/src/index.ts +0 -745
  574. package/skills/create-blog-article/tsconfig.json +0 -10
  575. package/skills/deepresearch/src/agents/query-generator.ts +0 -91
  576. package/skills/deepresearch/src/agents/synthesizer.ts +0 -111
  577. package/skills/deepresearch/src/index.ts +0 -224
  578. package/skills/deepresearch/src/research.ts +0 -166
  579. package/skills/deepresearch/src/services/anthropic.ts +0 -69
  580. package/skills/deepresearch/src/services/exa.ts +0 -108
  581. package/skills/deepresearch/src/services/firecrawl.ts +0 -88
  582. package/skills/deepresearch/src/services/openai.ts +0 -81
  583. package/skills/deepresearch/src/types.ts +0 -76
  584. package/skills/deepresearch/src/utils/file.ts +0 -111
  585. package/skills/deepresearch/src/utils/logger.ts +0 -84
  586. package/skills/domainpurchase/src/server/index.ts +0 -332
  587. package/skills/domainsearch/src/server/index.ts +0 -229
  588. package/skills/e2bswarm/README.md +0 -135
  589. package/skills/e2bswarm/SKILL.md +0 -118
  590. package/skills/e2bswarm/examples/tasks-example.json +0 -38
  591. package/skills/e2bswarm/package.json +0 -59
  592. package/skills/e2bswarm/src/commands/collect.ts +0 -135
  593. package/skills/e2bswarm/src/commands/install.ts +0 -164
  594. package/skills/e2bswarm/src/commands/kill.ts +0 -62
  595. package/skills/e2bswarm/src/commands/spawn.ts +0 -134
  596. package/skills/e2bswarm/src/commands/status.ts +0 -90
  597. package/skills/e2bswarm/src/commands/sync.ts +0 -208
  598. package/skills/e2bswarm/src/index.ts +0 -121
  599. package/skills/e2bswarm/src/lib/config.ts +0 -75
  600. package/skills/e2bswarm/src/lib/e2b.ts +0 -490
  601. package/skills/e2bswarm/src/lib/github.ts +0 -253
  602. package/skills/e2bswarm/src/lib/logger.ts +0 -41
  603. package/skills/e2bswarm/src/lib/paths.ts +0 -75
  604. package/skills/e2bswarm/src/lib/tasks.ts +0 -320
  605. package/skills/e2bswarm/src/types/index.ts +0 -107
  606. package/skills/e2bswarm/templates/codebox/e2b.Dockerfile +0 -38
  607. package/skills/e2bswarm/templates/codebox/e2b.toml +0 -3
  608. package/skills/e2bswarm/templates/setup.sh +0 -21
  609. package/skills/e2bswarm/tsconfig.json +0 -19
  610. package/skills/generate-book-cover/src/index.ts +0 -694
  611. package/skills/image/src/index-local.ts +0 -206
  612. package/skills/image/src/index.ts +0 -96
  613. package/skills/image/src/providers/google.ts +0 -79
  614. package/skills/image/src/providers/minimax.ts +0 -94
  615. package/skills/image/src/providers/openai.ts +0 -80
  616. package/skills/image/src/providers/xai.ts +0 -73
  617. package/skills/image/src/types.ts +0 -37
  618. package/skills/logo-design/CLAUDE.md +0 -30
  619. package/skills/logo-design/src/index.ts +0 -322
  620. package/skills/managehook/src/server/index.ts +0 -108
  621. package/skills/managemcp/src/server/index.ts +0 -108
  622. package/skills/manageskill/src/server/index.ts +0 -108
  623. package/skills/music/CLAUDE.md +0 -9
  624. package/skills/music/src/index.ts +0 -94
  625. package/skills/music/tsconfig.json +0 -10
  626. package/skills/pdf-read/src/index.ts +0 -320
  627. package/skills/product-mockup/CLAUDE.md +0 -19
  628. package/skills/product-mockup/src/index.ts +0 -290
  629. package/skills/read-pdf/src/index.ts +0 -388
  630. package/skills/remove-background/src/index.ts +0 -405
  631. package/skills/sound-effects/SKILL.md +0 -34
  632. package/skills/sound-effects/package.json +0 -21
  633. package/skills/sound-effects/src/index.ts +0 -172
  634. package/skills/sound-effects/tsconfig.json +0 -8
  635. package/skills/transcript/src/chunker.ts +0 -215
  636. package/skills/transcript/src/formatter.ts +0 -134
  637. package/skills/transcript/src/index-local.ts +0 -226
  638. package/skills/transcript/src/index.ts +0 -110
  639. package/skills/transcript/src/providers/elevenlabs.ts +0 -133
  640. package/skills/transcript/src/providers/gemini.ts +0 -192
  641. package/skills/transcript/src/providers/index.ts +0 -54
  642. package/skills/transcript/src/providers/openai.ts +0 -203
  643. package/skills/transcript/src/types.ts +0 -106
  644. package/skills/video/.env.example +0 -14
  645. package/skills/video/EXAMPLES.md +0 -266
  646. package/skills/video/LICENSE +0 -192
  647. package/skills/video/README.md +0 -174
  648. package/skills/video/src/cli.ts +0 -155
  649. package/skills/video/src/index-local.ts +0 -148
  650. package/skills/video/src/index.ts +0 -96
  651. package/skills/video/src/providers/google-veo.ts +0 -126
  652. package/skills/video/src/providers/index.ts +0 -22
  653. package/skills/video/src/providers/minimax.ts +0 -100
  654. package/skills/video/src/providers/openai-sora.ts +0 -164
  655. package/skills/video/src/providers/runway.ts +0 -159
  656. package/skills/video/src/types.ts +0 -35
  657. package/skills/video/tsconfig.json +0 -22
  658. package/skills/voiceover-casting-assistant/CLAUDE.md +0 -19
  659. package/skills/voiceover-casting-assistant/package.json +0 -27
  660. package/skills/voiceover-casting-assistant/src/index.ts +0 -255
  661. package/skills/voiceover-casting-assistant/tsconfig.json +0 -10
  662. package/skills/webcrawling/src/commands/config.ts +0 -34
  663. package/skills/webcrawling/src/commands/crawl.ts +0 -33
  664. package/skills/webcrawling/src/commands/scrape.ts +0 -32
  665. package/skills/webcrawling/src/commands/sessions.ts +0 -42
  666. package/skills/webcrawling/src/lib/crawler.ts +0 -174
  667. package/skills/webcrawling/src/lib/storage.ts +0 -130
  668. package/skills/webcrawling/src/types/index.ts +0 -45
  669. package/skills/webcrawling/src/utils/logger.ts +0 -30
  670. package/skills/webcrawling/src/utils/paths.ts +0 -28
  671. /package/skills/{audiobook-chapter-proofer → blog-article}/tsconfig.json +0 -0
@@ -0,0 +1,884 @@
1
+ #!/usr/bin/env bun
2
+ import { Command } from "commander";
3
+ import { createTables } from "../src/db/schema";
4
+ import { ensureInstalled } from "../src/lib/installer";
5
+
6
+ // Ensure service directory exists on startup
7
+ ensureInstalled();
8
+ import {
9
+ createApp,
10
+ getAllApps,
11
+ getAppById,
12
+ getAppByName,
13
+ updateApp,
14
+ deleteApp,
15
+ createPage,
16
+ getPagesByAppId,
17
+ getPageByAppAndPath,
18
+ deletePage,
19
+ createScan,
20
+ getScans,
21
+ getScanById,
22
+ updateScan,
23
+ getConsoleLogs,
24
+ countConsoleLogs,
25
+ createConsoleLogsBatch,
26
+ getLogsByLevel,
27
+ getLastScanForApp,
28
+ createScreenshot,
29
+ getScreenshotsByScanId,
30
+ } from "../src/db/queries";
31
+ import { getDb, closeConnection } from "../src/db/index";
32
+ import { ConsoleMonitor, getMonitor, shutdownMonitor } from "../src/lib/monitor";
33
+ import {
34
+ loadConfig,
35
+ saveConfig,
36
+ getConfigPath,
37
+ isHeadless,
38
+ getDefaultTimeout,
39
+ } from "../src/lib/config";
40
+ import {
41
+ startWatching,
42
+ stopWatching,
43
+ getWatchStatus,
44
+ stopAllWatchers,
45
+ } from "../src/lib/watcher";
46
+ import {
47
+ install,
48
+ uninstall,
49
+ isInstalled,
50
+ logScanStart,
51
+ logScanComplete,
52
+ logWatchStart,
53
+ logWatchStop,
54
+ logError,
55
+ ensureSnapshotsDir,
56
+ generateScreenshotFilename,
57
+ getScreenshotPath,
58
+ getSnapshotsDir,
59
+ } from "../src/lib/installer";
60
+ import type { ConsoleLogLevel, CreateConsoleLogInput } from "../src/lib/types";
61
+
62
+ // Helper for Commander option parsing (parseInt needs explicit radix)
63
+ const parseIntOption = (val: string) => parseInt(val, 10);
64
+
65
+ const program = new Command();
66
+
67
+ program
68
+ .name("service-consolelog")
69
+ .description("Monitor console logs from web applications using Playwright")
70
+ .version("1.0.0");
71
+
72
+ // ============ INIT/INSTALL COMMANDS ============
73
+
74
+ program
75
+ .command("init")
76
+ .description("Initialize service-consolelog in the current project")
77
+ .option("-f, --force", "Force reinstall even if already installed")
78
+ .action((options) => {
79
+ const result = install({ force: options.force });
80
+ if (result.success) {
81
+ console.log(`āœ“ ${result.message}`);
82
+ console.log(` Created: .service-consolelog/README.md`);
83
+ console.log(` Created: .service-consolelog/service-consolelog.log`);
84
+ console.log(` Created: .service-consolelog/snapshots/`);
85
+ } else {
86
+ console.log(`⚠ ${result.message}`);
87
+ }
88
+ });
89
+
90
+ program
91
+ .command("uninit")
92
+ .description("Remove service-consolelog from the current project")
93
+ .action(() => {
94
+ const result = uninstall();
95
+ if (result.success) {
96
+ console.log(`āœ“ ${result.message}`);
97
+ } else {
98
+ console.log(`⚠ ${result.message}`);
99
+ }
100
+ });
101
+
102
+ program
103
+ .command("status")
104
+ .description("Check installation status")
105
+ .action(() => {
106
+ if (isInstalled()) {
107
+ console.log("āœ“ Installed in current project");
108
+ } else {
109
+ console.log("āœ— Not installed. Run 'service-consolelog init' to set up.");
110
+ }
111
+ });
112
+
113
+ // ============ APP COMMANDS ============
114
+
115
+ const appCmd = program.command("app").description("Manage monitored applications");
116
+
117
+ appCmd
118
+ .command("add")
119
+ .description("Add a new app to monitor")
120
+ .requiredOption("-n, --name <name>", "App name")
121
+ .requiredOption("-p, --port <port>", "App port", parseIntOption)
122
+ .requiredOption("-u, --url <url>", "Base URL")
123
+ .option("-d, --description <desc>", "Description")
124
+ .action(async (options) => {
125
+ try {
126
+ await ensureDb();
127
+ const app = await createApp({
128
+ name: options.name,
129
+ port: options.port,
130
+ base_url: options.url,
131
+ description: options.description,
132
+ });
133
+ console.log(`āœ“ Created app "${app.name}" (ID: ${app.id})`);
134
+ } catch (error) {
135
+ const err = error as Error;
136
+ if (err.message.includes("unique") || err.message.includes("duplicate")) {
137
+ console.error(`āœ— App "${options.name}" already exists`);
138
+ } else {
139
+ console.error(`āœ— Error: ${err.message}`);
140
+ }
141
+ process.exit(1);
142
+ }
143
+ });
144
+
145
+ appCmd
146
+ .command("list")
147
+ .description("List all apps")
148
+ .option("-a, --active-only", "Show only active apps")
149
+ .action(async (options) => {
150
+ await ensureDb();
151
+ const apps = await getAllApps(options.activeOnly);
152
+
153
+ if (apps.length === 0) {
154
+ console.log("No apps found. Add one with: service-consolelog app add");
155
+ return;
156
+ }
157
+
158
+ console.log("\nApps:\n");
159
+ for (const app of apps) {
160
+ const status = app.active ? "ā—" : "ā—‹";
161
+ console.log(` ${status} ${app.name} (ID: ${app.id})`);
162
+ console.log(` URL: ${app.base_url}`);
163
+ console.log(` Port: ${app.port}`);
164
+ if (app.description) {
165
+ console.log(` Description: ${app.description}`);
166
+ }
167
+ console.log();
168
+ }
169
+ });
170
+
171
+ appCmd
172
+ .command("get <idOrName>")
173
+ .description("Get app details")
174
+ .action(async (idOrName) => {
175
+ await ensureDb();
176
+ const app = await resolveApp(idOrName);
177
+
178
+ if (!app) {
179
+ console.error(`āœ— App "${idOrName}" not found`);
180
+ process.exit(1);
181
+ }
182
+
183
+ console.log(`\nApp: ${app.name}\n`);
184
+ console.log(` ID: ${app.id}`);
185
+ console.log(` URL: ${app.base_url}`);
186
+ console.log(` Port: ${app.port}`);
187
+ console.log(` Active: ${app.active ? "Yes" : "No"}`);
188
+ if (app.description) {
189
+ console.log(` Description: ${app.description}`);
190
+ }
191
+ console.log(` Created: ${app.created_at}`);
192
+ console.log(` Updated: ${app.updated_at}`);
193
+
194
+ const pages = await getPagesByAppId(app.id);
195
+ console.log(` Pages: ${pages.length}`);
196
+ });
197
+
198
+ appCmd
199
+ .command("update <idOrName>")
200
+ .description("Update an app")
201
+ .option("-n, --name <name>", "New name")
202
+ .option("-p, --port <port>", "New port", parseIntOption)
203
+ .option("-u, --url <url>", "New base URL")
204
+ .option("-d, --description <desc>", "New description")
205
+ .option("--active <bool>", "Set active status", (v) => v === "true")
206
+ .action(async (idOrName, options) => {
207
+ await ensureDb();
208
+ const app = await resolveApp(idOrName);
209
+
210
+ if (!app) {
211
+ console.error(`āœ— App "${idOrName}" not found`);
212
+ process.exit(1);
213
+ }
214
+
215
+ const updated = await updateApp(app.id, {
216
+ name: options.name,
217
+ port: options.port,
218
+ base_url: options.url,
219
+ description: options.description,
220
+ active: options.active,
221
+ });
222
+
223
+ console.log(`āœ“ Updated app "${updated?.name}"`);
224
+ });
225
+
226
+ appCmd
227
+ .command("remove <idOrName>")
228
+ .description("Remove an app")
229
+ .action(async (idOrName) => {
230
+ await ensureDb();
231
+ const app = await resolveApp(idOrName);
232
+
233
+ if (!app) {
234
+ console.error(`āœ— App "${idOrName}" not found`);
235
+ process.exit(1);
236
+ }
237
+
238
+ await deleteApp(app.id);
239
+ console.log(`āœ“ Removed app "${app.name}"`);
240
+ });
241
+
242
+ // ============ PAGE COMMANDS ============
243
+
244
+ const pageCmd = program.command("page").description("Manage monitored pages");
245
+
246
+ pageCmd
247
+ .command("add")
248
+ .description("Add a page to monitor")
249
+ .requiredOption("-a, --app <app>", "App name or ID")
250
+ .requiredOption("-p, --path <path>", "Page path (e.g., '/', '/dashboard')")
251
+ .option("-n, --name <name>", "Page name")
252
+ .option("-w, --wait-for <selector>", "CSS selector to wait for")
253
+ .option("-t, --timeout <ms>", "Timeout in milliseconds", parseIntOption)
254
+ .action(async (options) => {
255
+ await ensureDb();
256
+ const app = await resolveApp(options.app);
257
+
258
+ if (!app) {
259
+ console.error(`āœ— App "${options.app}" not found`);
260
+ process.exit(1);
261
+ }
262
+
263
+ try {
264
+ const page = await createPage({
265
+ app_id: app.id,
266
+ path: options.path,
267
+ name: options.name,
268
+ wait_for: options.waitFor,
269
+ timeout: options.timeout,
270
+ });
271
+ console.log(`āœ“ Added page "${page.path}" to "${app.name}" (ID: ${page.id})`);
272
+ } catch (error) {
273
+ const err = error as Error;
274
+ if (err.message.includes("unique") || err.message.includes("duplicate")) {
275
+ console.error(`āœ— Page "${options.path}" already exists for "${app.name}"`);
276
+ } else {
277
+ console.error(`āœ— Error: ${err.message}`);
278
+ }
279
+ process.exit(1);
280
+ }
281
+ });
282
+
283
+ pageCmd
284
+ .command("list")
285
+ .description("List pages for an app")
286
+ .requiredOption("-a, --app <app>", "App name or ID")
287
+ .option("--active-only", "Show only active pages")
288
+ .action(async (options) => {
289
+ await ensureDb();
290
+ const app = await resolveApp(options.app);
291
+
292
+ if (!app) {
293
+ console.error(`āœ— App "${options.app}" not found`);
294
+ process.exit(1);
295
+ }
296
+
297
+ const pages = await getPagesByAppId(app.id, options.activeOnly);
298
+
299
+ if (pages.length === 0) {
300
+ console.log(`No pages for "${app.name}". Add one with: service-consolelog page add`);
301
+ return;
302
+ }
303
+
304
+ console.log(`\nPages for "${app.name}":\n`);
305
+ for (const page of pages) {
306
+ const status = page.active ? "ā—" : "ā—‹";
307
+ console.log(` ${status} ${page.path} (ID: ${page.id})`);
308
+ if (page.name) {
309
+ console.log(` Name: ${page.name}`);
310
+ }
311
+ if (page.wait_for) {
312
+ console.log(` Wait for: ${page.wait_for}`);
313
+ }
314
+ console.log(` Timeout: ${page.timeout}ms`);
315
+ console.log();
316
+ }
317
+ });
318
+
319
+ pageCmd
320
+ .command("remove <id>")
321
+ .description("Remove a page")
322
+ .action(async (id) => {
323
+ await ensureDb();
324
+ const success = await deletePage(parseInt(id, 10));
325
+
326
+ if (success) {
327
+ console.log(`āœ“ Removed page ID ${id}`);
328
+ } else {
329
+ console.error(`āœ— Page ID ${id} not found`);
330
+ process.exit(1);
331
+ }
332
+ });
333
+
334
+ // ============ SCAN COMMANDS ============
335
+
336
+ program
337
+ .command("scan")
338
+ .description("Scan pages for console logs")
339
+ .option("-a, --app <app>", "App name or ID")
340
+ .option("--all", "Scan all active apps")
341
+ .option("-p, --pages <paths...>", "Specific paths to scan")
342
+ .option("--headless <bool>", "Run headless", (v) => v !== "false")
343
+ .action(async (options) => {
344
+ await ensureDb();
345
+
346
+ if (!options.app && !options.all) {
347
+ console.error("āœ— Specify --app or --all");
348
+ process.exit(1);
349
+ }
350
+
351
+ const headless = options.headless ?? isHeadless();
352
+ const monitor = getMonitor(headless);
353
+ await monitor.start();
354
+
355
+ try {
356
+ if (options.all) {
357
+ const apps = await getAllApps(true);
358
+ for (const app of apps) {
359
+ await scanApp(app.id, monitor, options.pages);
360
+ }
361
+ } else {
362
+ const app = await resolveApp(options.app);
363
+ if (!app) {
364
+ console.error(`āœ— App "${options.app}" not found`);
365
+ process.exit(1);
366
+ }
367
+ await scanApp(app.id, monitor, options.pages);
368
+ }
369
+ } finally {
370
+ await shutdownMonitor();
371
+ }
372
+ });
373
+
374
+ // ============ LOG COMMANDS ============
375
+
376
+ program
377
+ .command("logs")
378
+ .description("Query console logs")
379
+ .requiredOption("-a, --app <app>", "App name or ID")
380
+ .option("-l, --level <level>", "Filter by level (error, warn, info, log, debug)")
381
+ .option("-s, --scan <id>", "Filter by scan ID", parseIntOption)
382
+ .option("--since <date>", "Filter logs since date (ISO format)")
383
+ .option("--until <date>", "Filter logs until date (ISO format)")
384
+ .option("--limit <n>", "Limit results", parseIntOption, 50)
385
+ .option("--offset <n>", "Offset results", parseIntOption, 0)
386
+ .action(async (options) => {
387
+ await ensureDb();
388
+ const app = await resolveApp(options.app);
389
+
390
+ if (!app) {
391
+ console.error(`āœ— App "${options.app}" not found`);
392
+ process.exit(1);
393
+ }
394
+
395
+ const logs = await getConsoleLogs({
396
+ app_id: app.id,
397
+ level: options.level as ConsoleLogLevel,
398
+ scan_id: isNaN(options.scan) ? undefined : options.scan,
399
+ since: options.since,
400
+ until: options.until,
401
+ limit: isNaN(options.limit) ? 50 : options.limit,
402
+ offset: isNaN(options.offset) ? 0 : options.offset,
403
+ });
404
+
405
+ if (logs.length === 0) {
406
+ console.log("No logs found matching criteria.");
407
+ return;
408
+ }
409
+
410
+ console.log(`\nLogs for "${app.name}" (${logs.length} results):\n`);
411
+
412
+ for (const log of logs) {
413
+ const levelIcon = getLevelIcon(log.level);
414
+ console.log(`${levelIcon} [${log.timestamp}] ${log.level.toUpperCase()}`);
415
+ console.log(` ${log.message}`);
416
+ if (log.source_url) {
417
+ console.log(` at ${log.source_url}:${log.line_number || "?"}:${log.column_number || "?"}`);
418
+ }
419
+ if (log.stack_trace) {
420
+ console.log(` Stack: ${log.stack_trace.split("\n")[0]}...`);
421
+ }
422
+ console.log();
423
+ }
424
+ });
425
+
426
+ program
427
+ .command("history")
428
+ .description("View scan history")
429
+ .requiredOption("-a, --app <app>", "App name or ID")
430
+ .option("--limit <n>", "Limit results", parseIntOption, 10)
431
+ .action(async (options) => {
432
+ await ensureDb();
433
+ const app = await resolveApp(options.app);
434
+
435
+ if (!app) {
436
+ console.error(`āœ— App "${options.app}" not found`);
437
+ process.exit(1);
438
+ }
439
+
440
+ const scans = await getScans({ app_id: app.id, limit: options.limit });
441
+
442
+ if (scans.length === 0) {
443
+ console.log(`No scan history for "${app.name}".`);
444
+ return;
445
+ }
446
+
447
+ console.log(`\nScan history for "${app.name}":\n`);
448
+
449
+ for (const scan of scans) {
450
+ const statusIcon =
451
+ scan.status === "completed" ? "āœ“" : scan.status === "failed" ? "āœ—" : "ā—Œ";
452
+ console.log(
453
+ ` ${statusIcon} Scan #${scan.id} - ${scan.status.toUpperCase()}`
454
+ );
455
+ console.log(` Started: ${scan.started_at}`);
456
+ if (scan.completed_at) {
457
+ console.log(` Completed: ${scan.completed_at}`);
458
+ }
459
+ console.log(
460
+ ` Pages: ${scan.pages_scanned} | Errors: ${scan.errors_found}`
461
+ );
462
+ console.log();
463
+ }
464
+ });
465
+
466
+ // ============ EXPORT COMMAND ============
467
+
468
+ program
469
+ .command("export")
470
+ .description("Export logs to file")
471
+ .requiredOption("-a, --app <app>", "App name or ID")
472
+ .requiredOption("-o, --output <path>", "Output file path")
473
+ .option("-f, --format <format>", "Format: json or csv", "json")
474
+ .option("-l, --level <level>", "Filter by level")
475
+ .option("--since <date>", "Filter logs since date")
476
+ .option("--until <date>", "Filter logs until date")
477
+ .action(async (options) => {
478
+ await ensureDb();
479
+ const app = await resolveApp(options.app);
480
+
481
+ if (!app) {
482
+ console.error(`āœ— App "${options.app}" not found`);
483
+ process.exit(1);
484
+ }
485
+
486
+ const logs = await getConsoleLogs({
487
+ app_id: app.id,
488
+ level: options.level as ConsoleLogLevel,
489
+ since: options.since,
490
+ until: options.until,
491
+ });
492
+
493
+ let content: string;
494
+ if (options.format === "csv") {
495
+ const headers = [
496
+ "id",
497
+ "scan_id",
498
+ "page_id",
499
+ "level",
500
+ "message",
501
+ "source_url",
502
+ "line_number",
503
+ "column_number",
504
+ "timestamp",
505
+ ];
506
+ const rows = logs.map((l) =>
507
+ [
508
+ l.id,
509
+ l.scan_id,
510
+ l.page_id,
511
+ l.level,
512
+ `"${l.message.replace(/"/g, '""')}"`,
513
+ l.source_url || "",
514
+ l.line_number || "",
515
+ l.column_number || "",
516
+ l.timestamp,
517
+ ].join(",")
518
+ );
519
+ content = [headers.join(","), ...rows].join("\n");
520
+ } else {
521
+ content = JSON.stringify(logs, null, 2);
522
+ }
523
+
524
+ Bun.write(options.output, content);
525
+ console.log(`āœ“ Exported ${logs.length} logs to ${options.output}`);
526
+ });
527
+
528
+ // ============ WATCH COMMANDS ============
529
+
530
+ const watchCmd = program.command("watch").description("Continuous monitoring");
531
+
532
+ watchCmd
533
+ .command("start")
534
+ .description("Start watching an app")
535
+ .requiredOption("-a, --app <app>", "App name or ID")
536
+ .option("-i, --interval <min>", "Interval in minutes", parseIntOption, 5)
537
+ .action(async (options) => {
538
+ await ensureDb();
539
+ const app = await resolveApp(options.app);
540
+
541
+ if (!app) {
542
+ console.error(`āœ— App "${options.app}" not found`);
543
+ process.exit(1);
544
+ }
545
+
546
+ const intervalMs = options.interval * 60 * 1000;
547
+
548
+ try {
549
+ const started = await startWatching(app.id, intervalMs);
550
+ if (started) {
551
+ console.log(`āœ“ Started watching "${app.name}" (interval: ${options.interval}min)`);
552
+ logWatchStart(app.name, intervalMs);
553
+
554
+ // Keep process alive
555
+ console.log("Press Ctrl+C to stop watching.\n");
556
+ process.on("SIGINT", async () => {
557
+ console.log("\nStopping...");
558
+ await stopAllWatchers();
559
+ logWatchStop(app.name);
560
+ process.exit(0);
561
+ });
562
+
563
+ // Keep the process running
564
+ await new Promise(() => {});
565
+ } else {
566
+ console.log(`Already watching "${app.name}"`);
567
+ }
568
+ } catch (error) {
569
+ const err = error as Error;
570
+ console.error(`āœ— Error: ${err.message}`);
571
+ process.exit(1);
572
+ }
573
+ });
574
+
575
+ watchCmd
576
+ .command("stop")
577
+ .description("Stop watching an app")
578
+ .requiredOption("-a, --app <app>", "App name or ID")
579
+ .action(async (options) => {
580
+ await ensureDb();
581
+ const app = await resolveApp(options.app);
582
+
583
+ if (!app) {
584
+ console.error(`āœ— App "${options.app}" not found`);
585
+ process.exit(1);
586
+ }
587
+
588
+ const stopped = stopWatching(app.id);
589
+ if (stopped) {
590
+ console.log(`āœ“ Stopped watching "${app.name}"`);
591
+ logWatchStop(app.name);
592
+ } else {
593
+ console.log(`Not watching "${app.name}"`);
594
+ }
595
+ });
596
+
597
+ watchCmd
598
+ .command("status")
599
+ .description("Check watch status")
600
+ .action(async () => {
601
+ const statuses = await getWatchStatus();
602
+
603
+ if (statuses.length === 0) {
604
+ console.log("No apps being watched.");
605
+ return;
606
+ }
607
+
608
+ console.log("\nActive watchers:\n");
609
+ for (const status of statuses) {
610
+ const intervalMin = (status.intervalMs || 0) / 60000;
611
+ console.log(` ā— ${status.appName} (ID: ${status.appId})`);
612
+ console.log(` Interval: ${intervalMin}min`);
613
+ if (status.lastScan) {
614
+ console.log(` Last scan: ${status.lastScan}`);
615
+ }
616
+ console.log();
617
+ }
618
+ });
619
+
620
+ // ============ CONFIG COMMANDS ============
621
+
622
+ program
623
+ .command("config")
624
+ .description("Manage configuration")
625
+ .option("--show", "Show current config")
626
+ .option("--path", "Show config file path")
627
+ .option("--set-headless <bool>", "Set headless mode", (v) => v === "true")
628
+ .option("--set-timeout <ms>", "Set default timeout", parseIntOption)
629
+ .option("--set-db-path <path>", "Set database path")
630
+ .option("--set-watch-interval <ms>", "Set watch interval", parseIntOption)
631
+ .action((options) => {
632
+ if (options.path) {
633
+ console.log(getConfigPath());
634
+ return;
635
+ }
636
+
637
+ if (options.show) {
638
+ const config = loadConfig();
639
+ console.log("\nConfiguration:\n");
640
+ console.log(` Database path: ${config.databasePath}`);
641
+ console.log(` Headless: ${config.headless}`);
642
+ console.log(` Default timeout: ${config.defaultTimeout}ms`);
643
+ console.log(` Watch interval: ${config.watchInterval}ms`);
644
+ console.log(` Log level: ${config.logLevel}`);
645
+ console.log(`\n Config file: ${getConfigPath()}`);
646
+ return;
647
+ }
648
+
649
+ const updates: Record<string, unknown> = {};
650
+ if (options.setHeadless !== undefined) {
651
+ updates.headless = options.setHeadless;
652
+ }
653
+ if (options.setTimeout !== undefined) {
654
+ updates.defaultTimeout = options.setTimeout;
655
+ }
656
+ if (options.setDbPath !== undefined) {
657
+ updates.databasePath = options.setDbPath;
658
+ }
659
+ if (options.setWatchInterval !== undefined) {
660
+ updates.watchInterval = options.setWatchInterval;
661
+ }
662
+
663
+ if (Object.keys(updates).length > 0) {
664
+ saveConfig(updates);
665
+ console.log("āœ“ Configuration updated");
666
+ } else {
667
+ console.log("No changes. Use --show to view config or --set-* to modify.");
668
+ }
669
+ });
670
+
671
+ // ============ SNAPSHOTS COMMAND ============
672
+
673
+ program
674
+ .command("snapshots")
675
+ .description("List snapshots from a scan")
676
+ .option("-s, --scan <id>", "Scan ID", parseIntOption)
677
+ .option("-a, --app <app>", "App name or ID (shows latest scan)")
678
+ .action(async (options) => {
679
+ await ensureDb();
680
+
681
+ let scanId: number | undefined = options.scan;
682
+
683
+ if (!scanId && options.app) {
684
+ const app = await resolveApp(options.app);
685
+ if (!app) {
686
+ console.error(`āœ— App "${options.app}" not found`);
687
+ process.exit(1);
688
+ }
689
+ const lastScan = await getLastScanForApp(app.id);
690
+ if (!lastScan) {
691
+ console.log(`No scans found for "${app.name}"`);
692
+ return;
693
+ }
694
+ scanId = lastScan.id;
695
+ }
696
+
697
+ if (!scanId) {
698
+ console.error("āœ— Specify --scan or --app");
699
+ process.exit(1);
700
+ }
701
+
702
+ const screenshots = await getScreenshotsByScanId(scanId);
703
+
704
+ if (screenshots.length === 0) {
705
+ console.log("No screenshots found for this scan.");
706
+ return;
707
+ }
708
+
709
+ console.log(`\nSnapshots for scan #${scanId}:\n`);
710
+ for (const ss of screenshots) {
711
+ console.log(` šŸ“ø ${ss.filename}`);
712
+ console.log(` Path: ${ss.filepath}`);
713
+ console.log(` Created: ${ss.created_at}`);
714
+ console.log();
715
+ }
716
+
717
+ console.log(`Total: ${screenshots.length} screenshots`);
718
+ console.log(`\nTo view a screenshot, open the path in your file viewer.`);
719
+ });
720
+
721
+ // ============ SERVER COMMAND ============
722
+
723
+ program
724
+ .command("server")
725
+ .description("Start the HTTP API server")
726
+ .option("-p, --port <port>", "Server port", parseIntOption, 3100)
727
+ .action(async (options) => {
728
+ await ensureDb();
729
+ console.log(`Starting server on port ${options.port}...`);
730
+ console.log(`See: http://localhost:${options.port}/health`);
731
+
732
+ // Import and start server
733
+ const { startServer } = await import("../src/server/index");
734
+ startServer(options.port);
735
+ });
736
+
737
+ // ============ HELPER FUNCTIONS ============
738
+
739
+ async function ensureDb(): Promise<void> {
740
+ getDb();
741
+ await createTables();
742
+ }
743
+
744
+ async function resolveApp(idOrName: string) {
745
+ const id = parseInt(idOrName, 10);
746
+ if (!isNaN(id)) {
747
+ return await getAppById(id);
748
+ }
749
+ return await getAppByName(idOrName);
750
+ }
751
+
752
+ async function scanApp(
753
+ appId: number,
754
+ monitor: ConsoleMonitor,
755
+ specificPaths?: string[]
756
+ ): Promise<void> {
757
+ const app = await getAppById(appId);
758
+ if (!app) {
759
+ console.error(`āœ— App ID ${appId} not found`);
760
+ return;
761
+ }
762
+
763
+ let pages = await getPagesByAppId(appId, true);
764
+
765
+ if (specificPaths && specificPaths.length > 0) {
766
+ pages = pages.filter((p) => specificPaths.includes(p.path));
767
+ }
768
+
769
+ if (pages.length === 0) {
770
+ console.log(`No pages to scan for "${app.name}"`);
771
+ return;
772
+ }
773
+
774
+ // Ensure snapshots directory exists
775
+ const snapshotsDir = ensureSnapshotsDir();
776
+
777
+ console.log(`\nScanning "${app.name}" (${pages.length} pages)...\n`);
778
+ logScanStart(app.name, pages.length);
779
+
780
+ const scan = await createScan({ app_id: appId });
781
+ let totalErrors = 0;
782
+ let pagesScanned = 0;
783
+ const screenshotPaths: string[] = [];
784
+
785
+ for (const page of pages) {
786
+ const url = `${app.base_url}${page.path}`;
787
+ process.stdout.write(` Scanning ${page.path}... `);
788
+
789
+ // Generate screenshot filename
790
+ const screenshotFilename = generateScreenshotFilename(page.name, page.path);
791
+ const screenshotFullPath = getScreenshotPath(screenshotFilename);
792
+
793
+ try {
794
+ const result = await monitor.scanPage(url, {
795
+ timeout: page.timeout,
796
+ waitFor: page.wait_for || undefined,
797
+ captureScreenshot: true,
798
+ screenshotDir: screenshotFullPath,
799
+ });
800
+
801
+ const { logs, screenshotPath } = result;
802
+
803
+ // Save screenshot record if captured
804
+ if (screenshotPath) {
805
+ await createScreenshot({
806
+ scan_id: scan.id,
807
+ page_id: page.id,
808
+ filename: screenshotFilename,
809
+ filepath: screenshotPath,
810
+ });
811
+ screenshotPaths.push(screenshotPath);
812
+ }
813
+
814
+ if (logs.length > 0) {
815
+ const logInputs: CreateConsoleLogInput[] = logs.map((log) => ({
816
+ scan_id: scan.id,
817
+ page_id: page.id,
818
+ level: log.level as ConsoleLogLevel,
819
+ message: log.message,
820
+ source_url: log.sourceUrl,
821
+ line_number: log.lineNumber,
822
+ column_number: log.columnNumber,
823
+ stack_trace: log.stackTrace,
824
+ }));
825
+
826
+ await createConsoleLogsBatch(logInputs);
827
+
828
+ const errorCount = logs.filter((l) => l.level === "error").length;
829
+ const warnCount = logs.filter((l) => l.level === "warn").length;
830
+ totalErrors += errorCount;
831
+
832
+ console.log(`${logs.length} logs (${errorCount} errors, ${warnCount} warnings)`);
833
+ } else {
834
+ console.log("clean");
835
+ }
836
+
837
+ if (screenshotPath) {
838
+ console.log(` šŸ“ø ${screenshotPath}`);
839
+ }
840
+
841
+ pagesScanned++;
842
+ } catch (error) {
843
+ const err = error as Error;
844
+ console.log(`failed: ${err.message}`);
845
+ logError(`Failed to scan ${url}: ${err.message}`);
846
+ }
847
+ }
848
+
849
+ await updateScan(scan.id, {
850
+ status: "completed",
851
+ pages_scanned: pagesScanned,
852
+ errors_found: totalErrors,
853
+ completed_at: new Date().toISOString(),
854
+ });
855
+
856
+ console.log(`\nāœ“ Scan complete: ${pagesScanned} pages, ${totalErrors} errors`);
857
+ if (screenshotPaths.length > 0) {
858
+ console.log(`šŸ“ø Screenshots saved to: ${getSnapshotsDir()}`);
859
+ console.log(`\nScreenshot paths:`);
860
+ for (const path of screenshotPaths) {
861
+ console.log(` ${path}`);
862
+ }
863
+ }
864
+ console.log();
865
+ logScanComplete(app.name, pagesScanned, totalErrors);
866
+ }
867
+
868
+ function getLevelIcon(level: string): string {
869
+ switch (level) {
870
+ case "error":
871
+ return "āŒ";
872
+ case "warn":
873
+ return "āš ļø";
874
+ case "info":
875
+ return "ā„¹ļø";
876
+ case "debug":
877
+ return "šŸ”";
878
+ default:
879
+ return "šŸ“";
880
+ }
881
+ }
882
+
883
+ // Run CLI
884
+ program.parse(process.argv);