@haposoft/cafekit 0.16.0-rc.8 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/README.md +116 -27
  2. package/bin/__tests__/codex-hooks-ownership.test.js +239 -0
  3. package/bin/__tests__/codex-hooks.test.js +50 -0
  4. package/bin/__tests__/codex-native.test.js +1882 -70
  5. package/bin/__tests__/develop-contract.test.js +400 -23
  6. package/bin/__tests__/installer-safety.test.js +3 -3
  7. package/bin/__tests__/optional-skill-inventory.test.js +249 -0
  8. package/bin/__tests__/output-styles.test.js +214 -0
  9. package/bin/__tests__/package-inventory.test.js +1735 -98
  10. package/bin/__tests__/runtime-schema.test.js +111 -0
  11. package/bin/__tests__/secret-output-guardrail.test.js +122 -0
  12. package/bin/__tests__/skill-routing-source.test.js +172 -0
  13. package/bin/__tests__/specs-v2-execution-closeout.test.js +1 -1
  14. package/bin/install.js +10 -0
  15. package/bin/lib/codex-install.js +170 -5
  16. package/bin/lib/context.js +14 -0
  17. package/bin/lib/i18n.js +12 -6
  18. package/bin/lib/skill-deps.js +5 -5
  19. package/bin/phases/claude-runtime.js +23 -0
  20. package/bin/phases/claude-settings.js +8 -0
  21. package/bin/phases/codex-hooks.js +156 -0
  22. package/bin/phases/codex-runtime.js +29 -38
  23. package/bin/phases/copy-payload.js +8 -2
  24. package/bin/phases/select-skill-bundles.js +96 -0
  25. package/bin/phases/skill-inventory.js +71 -0
  26. package/bin/phases/skills-setup.js +9 -2
  27. package/bin/phases/write-metadata.js +8 -5
  28. package/package.json +8 -2
  29. package/src/claude/CLAUDE.md +3 -3
  30. package/src/claude/agents/brainstormer.md +52 -69
  31. package/src/claude/agents/code-auditor.md +32 -14
  32. package/src/claude/agents/debugger.md +35 -20
  33. package/src/claude/agents/deployer.md +12 -5
  34. package/src/claude/agents/docs-keeper.md +11 -1
  35. package/src/claude/agents/implementer.md +25 -13
  36. package/src/claude/agents/inspector.md +6 -3
  37. package/src/claude/agents/project-manager.md +1 -1
  38. package/src/claude/agents/researcher.md +26 -55
  39. package/src/claude/agents/spec-maker.md +12 -7
  40. package/src/claude/agents/strategist.md +52 -0
  41. package/src/claude/agents/test-runner.md +117 -132
  42. package/src/claude/agents/ui-ux-designer.md +1 -1
  43. package/src/claude/hooks/__tests__/fixtures/statusline-default.golden +1 -0
  44. package/src/claude/hooks/__tests__/precompact.test.js +158 -0
  45. package/src/claude/hooks/__tests__/spec-gate.test.js +10 -3
  46. package/src/claude/hooks/__tests__/state.test.js +5 -0
  47. package/src/claude/hooks/__tests__/statusline.test.js +196 -0
  48. package/src/claude/hooks/agent.cjs +1 -1
  49. package/src/claude/hooks/docs-sync.cjs +12 -10
  50. package/src/claude/hooks/inspect-block.cjs +1 -1
  51. package/src/claude/hooks/lib/config.cjs +3 -0
  52. package/src/claude/hooks/lib/hook-state-dir.cjs +39 -0
  53. package/src/claude/hooks/lib/secret-keywords.cjs +42 -0
  54. package/src/claude/hooks/precompact.cjs +105 -0
  55. package/src/claude/hooks/rules.cjs +1 -1
  56. package/src/claude/hooks/secret-output-guardrail.cjs +43 -0
  57. package/src/claude/hooks/session.cjs +27 -1
  58. package/src/claude/hooks/spec-gate.cjs +3 -3
  59. package/src/claude/hooks/spec-state.cjs +2 -2
  60. package/src/claude/hooks/state.cjs +1 -1
  61. package/src/claude/hooks/task-scaffold-guard.cjs +1 -1
  62. package/src/claude/hooks/usage.cjs +1 -1
  63. package/src/claude/migration-manifest.json +29 -15
  64. package/src/claude/output-styles/coding-level-0-eli5.md +103 -0
  65. package/src/claude/output-styles/coding-level-1-junior.md +124 -0
  66. package/src/claude/output-styles/coding-level-2-mid.md +146 -0
  67. package/src/claude/output-styles/coding-level-3-senior.md +148 -0
  68. package/src/claude/output-styles/coding-level-4-lead.md +159 -0
  69. package/src/claude/output-styles/coding-level-5-god.md +91 -0
  70. package/src/claude/references/debugger/core-philosophy.md +5 -3
  71. package/src/claude/references/debugger/frontend-verification.md +2 -2
  72. package/src/claude/references/debugger/log-ci-analysis.md +13 -1
  73. package/src/claude/references/debugger/parallel-agent-hydration.md +19 -34
  74. package/src/claude/references/debugger/performance-diagnostics.md +2 -2
  75. package/src/claude/references/debugger/root-cause-tracing.md +37 -6
  76. package/src/claude/references/debugger/side-effect-gate.md +3 -1
  77. package/src/claude/references/debugger/verification-protocol.md +13 -12
  78. package/src/claude/rules/orchestrator.md +7 -1
  79. package/src/claude/rules/process-management.md +39 -0
  80. package/src/claude/rules/review-audit-self-decision.md +48 -0
  81. package/src/claude/rules/skill-domain-routing.md +26 -24
  82. package/src/claude/rules/skill-workflow-routing.md +22 -14
  83. package/src/claude/rules/workflow.md +3 -3
  84. package/src/claude/runtime.json +1 -0
  85. package/src/claude/runtime.schema.json +205 -0
  86. package/src/claude/scripts/generate-skill-catalog.cjs +156 -122
  87. package/src/claude/scripts/provenance.cjs +18 -5
  88. package/src/claude/scripts/workflow-policy.cjs +1 -1
  89. package/src/claude/settings/settings.json +16 -0
  90. package/src/claude/skills/agent-browser/SKILL.md +1 -1
  91. package/src/claude/skills/ai-multimodal/SKILL.md +1 -1
  92. package/src/claude/skills/brainstorm/SKILL.md +193 -172
  93. package/src/claude/skills/brainstorm/references/question-framework.md +105 -167
  94. package/src/claude/skills/chrome-devtools/SKILL.md +1 -1
  95. package/src/claude/skills/code-review/SKILL.md +43 -25
  96. package/src/claude/skills/code-review/references/spec-compliance-review.md +3 -4
  97. package/src/claude/skills/code-review/references/verification-gate.md +1 -1
  98. package/src/claude/skills/debug/SKILL.md +48 -19
  99. package/src/claude/skills/delegate/SKILL.md +1 -1
  100. package/src/claude/skills/develop/SKILL.md +92 -65
  101. package/src/claude/skills/develop/references/parallel-waves.md +36 -63
  102. package/src/claude/skills/develop/references/quality-gate.md +31 -4
  103. package/src/claude/skills/develop/references/subagent-patterns.md +21 -7
  104. package/src/claude/skills/docs/SKILL.md +42 -23
  105. package/src/claude/skills/docs/references/init-workflow.md +4 -4
  106. package/src/claude/skills/docs/references/reconstruct-workflow.md +6 -6
  107. package/src/claude/skills/docs/references/standard-docs-workflow.md +6 -2
  108. package/src/claude/skills/docs/references/summarize-workflow.md +2 -2
  109. package/src/claude/skills/docs/references/update-workflow.md +9 -7
  110. package/src/claude/skills/docs/templates/requirements-as-is.md +1 -1
  111. package/src/claude/skills/docx/SKILL.md +1 -1
  112. package/src/claude/skills/git/SKILL.md +1 -1
  113. package/src/claude/skills/git/references/commit-protocols.md +1 -1
  114. package/src/claude/skills/git/references/finish-branch.md +1 -1
  115. package/src/claude/skills/hotfix/SKILL.md +159 -170
  116. package/src/claude/skills/hotfix/references/diagnosis-protocol.md +14 -9
  117. package/src/claude/skills/hotfix/references/parallel-patterns.md +27 -13
  118. package/src/claude/skills/hotfix/references/prevention-gate.md +5 -0
  119. package/src/claude/skills/hotfix/references/review-cycle.md +21 -15
  120. package/src/claude/skills/hotfix/references/workflow-specialized.md +53 -21
  121. package/src/claude/skills/inspect/SKILL.md +55 -46
  122. package/src/claude/skills/inspect/references/internal-inspection.md +21 -5
  123. package/src/claude/skills/loop/SKILL.md +114 -0
  124. package/src/claude/skills/loop/references/bounded-loop-protocol.md +104 -0
  125. package/src/claude/skills/loop/references/metric-and-guard-contract.md +76 -0
  126. package/src/claude/skills/pdf/SKILL.md +1 -1
  127. package/src/claude/skills/pptx/SKILL.md +1 -1
  128. package/src/claude/skills/question/SKILL.md +16 -13
  129. package/src/claude/skills/research/SKILL.md +70 -43
  130. package/src/claude/skills/route/SKILL.md +94 -0
  131. package/src/claude/skills/route/references/agent-timing.md +46 -0
  132. package/src/claude/skills/route/references/chaining-patterns.md +53 -0
  133. package/src/claude/skills/route/references/task-taxonomy.md +48 -0
  134. package/src/claude/skills/specs/SKILL.md +41 -60
  135. package/src/claude/skills/specs/references/review.md +11 -8
  136. package/src/claude/skills/specs/references/templates.md +34 -18
  137. package/src/claude/skills/specs/templates/requirements-init.md +1 -1
  138. package/src/claude/skills/specs/templates/research.md +2 -2
  139. package/src/claude/skills/sync/SKILL.md +6 -6
  140. package/src/claude/skills/sync/references/sync-protocols.md +1 -1
  141. package/src/claude/skills/test/SKILL.md +120 -120
  142. package/src/claude/skills/test/references/execution-strategy.md +208 -361
  143. package/src/claude/skills/test/references/failure-triage.md +55 -121
  144. package/src/claude/skills/test/references/test-memory.md +20 -34
  145. package/src/claude/skills/ui-ux-pro-max/SKILL.md +1 -1
  146. package/src/claude/skills/web-testing/SKILL.md +1 -1
  147. package/src/claude/skills/xlsx/SKILL.md +1 -1
  148. package/src/claude/status.cjs +135 -33
  149. package/src/codex/AGENTS.md +14 -4
  150. package/src/codex/hooks/docs-sync.cjs +8 -3
  151. package/src/codex/hooks/lib/hook-context.cjs +18 -4
  152. package/src/codex/hooks/rules.cjs +29 -1
  153. package/src/codex/hooks/secret-output-guardrail.cjs +30 -0
  154. package/src/codex/hooks/spec-gate.cjs +3 -8
  155. package/src/codex/hooks/spec-state.cjs +2 -1
  156. package/src/codex/hooks.json +5 -0
  157. package/src/codex/runtime.json +2 -0
  158. package/src/common/.env.example +1 -1
  159. package/src/claude/skills/backend-development/SKILL.md +0 -101
  160. package/src/claude/skills/backend-development/references/backend-api-design.md +0 -495
  161. package/src/claude/skills/backend-development/references/backend-architecture.md +0 -454
  162. package/src/claude/skills/backend-development/references/backend-authentication.md +0 -338
  163. package/src/claude/skills/backend-development/references/backend-code-quality.md +0 -659
  164. package/src/claude/skills/backend-development/references/backend-debugging.md +0 -904
  165. package/src/claude/skills/backend-development/references/backend-devops.md +0 -491
  166. package/src/claude/skills/backend-development/references/backend-mindset.md +0 -387
  167. package/src/claude/skills/backend-development/references/backend-performance.md +0 -397
  168. package/src/claude/skills/backend-development/references/backend-security.md +0 -342
  169. package/src/claude/skills/backend-development/references/backend-technologies.md +0 -256
  170. package/src/claude/skills/backend-development/references/backend-testing.md +0 -429
  171. package/src/claude/skills/devops/.env.example +0 -76
  172. package/src/claude/skills/devops/SKILL.md +0 -102
  173. package/src/claude/skills/devops/references/browser-rendering.md +0 -305
  174. package/src/claude/skills/devops/references/cloudflare-d1-kv.md +0 -123
  175. package/src/claude/skills/devops/references/cloudflare-platform.md +0 -271
  176. package/src/claude/skills/devops/references/cloudflare-r2-storage.md +0 -280
  177. package/src/claude/skills/devops/references/cloudflare-workers-advanced.md +0 -312
  178. package/src/claude/skills/devops/references/cloudflare-workers-apis.md +0 -309
  179. package/src/claude/skills/devops/references/cloudflare-workers-basics.md +0 -418
  180. package/src/claude/skills/devops/references/docker-basics.md +0 -297
  181. package/src/claude/skills/devops/references/docker-compose.md +0 -292
  182. package/src/claude/skills/devops/references/gcloud-platform.md +0 -297
  183. package/src/claude/skills/devops/references/gcloud-services.md +0 -304
  184. package/src/claude/skills/devops/references/kubernetes-basics.md +0 -95
  185. package/src/claude/skills/devops/references/kubernetes-helm-advanced.md +0 -70
  186. package/src/claude/skills/devops/references/kubernetes-helm.md +0 -81
  187. package/src/claude/skills/devops/references/kubernetes-kubectl.md +0 -74
  188. package/src/claude/skills/devops/references/kubernetes-security-advanced.md +0 -94
  189. package/src/claude/skills/devops/references/kubernetes-security.md +0 -89
  190. package/src/claude/skills/devops/references/kubernetes-troubleshooting-advanced.md +0 -74
  191. package/src/claude/skills/devops/references/kubernetes-troubleshooting.md +0 -49
  192. package/src/claude/skills/devops/references/kubernetes-workflows-advanced.md +0 -75
  193. package/src/claude/skills/devops/references/kubernetes-workflows.md +0 -76
  194. package/src/claude/skills/devops/scripts/cloudflare_deploy.py +0 -269
  195. package/src/claude/skills/devops/scripts/docker_optimize.py +0 -332
  196. package/src/claude/skills/devops/scripts/requirements.txt +0 -20
  197. package/src/claude/skills/devops/scripts/tests/requirements.txt +0 -3
  198. package/src/claude/skills/devops/scripts/tests/test_cloudflare_deploy.py +0 -285
  199. package/src/claude/skills/devops/scripts/tests/test_docker_optimize.py +0 -436
  200. package/src/claude/skills/frontend-design/SKILL.md +0 -135
  201. package/src/claude/skills/frontend-design/references/ai-multimodal-overview.md +0 -165
  202. package/src/claude/skills/frontend-design/references/analysis-best-practices.md +0 -80
  203. package/src/claude/skills/frontend-design/references/analysis-prompts.md +0 -141
  204. package/src/claude/skills/frontend-design/references/analysis-techniques.md +0 -118
  205. package/src/claude/skills/frontend-design/references/animejs.md +0 -396
  206. package/src/claude/skills/frontend-design/references/anti-slop-rules.md +0 -103
  207. package/src/claude/skills/frontend-design/references/asset-generation.md +0 -337
  208. package/src/claude/skills/frontend-design/references/bento-motion-engine.md +0 -142
  209. package/src/claude/skills/frontend-design/references/design-extraction-overview.md +0 -71
  210. package/src/claude/skills/frontend-design/references/extraction-best-practices.md +0 -141
  211. package/src/claude/skills/frontend-design/references/extraction-output-templates.md +0 -162
  212. package/src/claude/skills/frontend-design/references/extraction-prompts.md +0 -127
  213. package/src/claude/skills/frontend-design/references/magicui-components.md +0 -129
  214. package/src/claude/skills/frontend-design/references/performance-guardrails.md +0 -169
  215. package/src/claude/skills/frontend-design/references/premium-design-patterns.md +0 -93
  216. package/src/claude/skills/frontend-design/references/redesign-audit-checklist.md +0 -114
  217. package/src/claude/skills/frontend-design/references/technical-accessibility.md +0 -119
  218. package/src/claude/skills/frontend-design/references/technical-best-practices.md +0 -97
  219. package/src/claude/skills/frontend-design/references/technical-optimization.md +0 -44
  220. package/src/claude/skills/frontend-design/references/technical-overview.md +0 -90
  221. package/src/claude/skills/frontend-design/references/technical-workflows.md +0 -150
  222. package/src/claude/skills/frontend-design/references/visual-analysis-overview.md +0 -95
  223. package/src/claude/skills/frontend-design/references/workflow-3d.md +0 -102
  224. package/src/claude/skills/frontend-design/references/workflow-describe.md +0 -87
  225. package/src/claude/skills/frontend-design/references/workflow-immersive.md +0 -87
  226. package/src/claude/skills/frontend-design/references/workflow-quick.md +0 -57
  227. package/src/claude/skills/frontend-design/references/workflow-screenshot.md +0 -63
  228. package/src/claude/skills/frontend-design/references/workflow-video.md +0 -74
  229. package/src/claude/skills/frontend-development/SKILL.md +0 -406
  230. package/src/claude/skills/frontend-development/resources/common-patterns.md +0 -331
  231. package/src/claude/skills/frontend-development/resources/complete-examples.md +0 -872
  232. package/src/claude/skills/frontend-development/resources/component-patterns.md +0 -502
  233. package/src/claude/skills/frontend-development/resources/data-fetching.md +0 -767
  234. package/src/claude/skills/frontend-development/resources/file-organization.md +0 -502
  235. package/src/claude/skills/frontend-development/resources/loading-and-error-states.md +0 -501
  236. package/src/claude/skills/frontend-development/resources/performance.md +0 -406
  237. package/src/claude/skills/frontend-development/resources/routing-guide.md +0 -364
  238. package/src/claude/skills/frontend-development/resources/styling-guide.md +0 -428
  239. package/src/claude/skills/frontend-development/resources/typescript-standards.md +0 -418
  240. package/src/claude/skills/mobile-development/SKILL.md +0 -218
  241. package/src/claude/skills/mobile-development/references/mobile-android.md +0 -604
  242. package/src/claude/skills/mobile-development/references/mobile-best-practices.md +0 -544
  243. package/src/claude/skills/mobile-development/references/mobile-debugging.md +0 -1089
  244. package/src/claude/skills/mobile-development/references/mobile-frameworks.md +0 -465
  245. package/src/claude/skills/mobile-development/references/mobile-ios.md +0 -496
  246. package/src/claude/skills/mobile-development/references/mobile-mindset.md +0 -542
  247. package/src/claude/skills/react-best-practices/AGENTS.md +0 -2249
  248. package/src/claude/skills/react-best-practices/README.md +0 -123
  249. package/src/claude/skills/react-best-practices/SKILL.md +0 -128
  250. package/src/claude/skills/react-best-practices/metadata.json +0 -15
  251. package/src/claude/skills/react-best-practices/rules/_sections.md +0 -46
  252. package/src/claude/skills/react-best-practices/rules/_template.md +0 -28
  253. package/src/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  254. package/src/claude/skills/react-best-practices/rules/advanced-use-latest.md +0 -49
  255. package/src/claude/skills/react-best-practices/rules/async-api-routes.md +0 -38
  256. package/src/claude/skills/react-best-practices/rules/async-defer-await.md +0 -80
  257. package/src/claude/skills/react-best-practices/rules/async-dependencies.md +0 -36
  258. package/src/claude/skills/react-best-practices/rules/async-parallel.md +0 -28
  259. package/src/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +0 -99
  260. package/src/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +0 -59
  261. package/src/claude/skills/react-best-practices/rules/bundle-conditional.md +0 -31
  262. package/src/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +0 -49
  263. package/src/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  264. package/src/claude/skills/react-best-practices/rules/bundle-preload.md +0 -50
  265. package/src/claude/skills/react-best-practices/rules/client-event-listeners.md +0 -74
  266. package/src/claude/skills/react-best-practices/rules/client-swr-dedup.md +0 -56
  267. package/src/claude/skills/react-best-practices/rules/js-batch-dom-css.md +0 -82
  268. package/src/claude/skills/react-best-practices/rules/js-cache-function-results.md +0 -80
  269. package/src/claude/skills/react-best-practices/rules/js-cache-property-access.md +0 -28
  270. package/src/claude/skills/react-best-practices/rules/js-cache-storage.md +0 -70
  271. package/src/claude/skills/react-best-practices/rules/js-combine-iterations.md +0 -32
  272. package/src/claude/skills/react-best-practices/rules/js-early-exit.md +0 -50
  273. package/src/claude/skills/react-best-practices/rules/js-hoist-regexp.md +0 -45
  274. package/src/claude/skills/react-best-practices/rules/js-index-maps.md +0 -37
  275. package/src/claude/skills/react-best-practices/rules/js-length-check-first.md +0 -49
  276. package/src/claude/skills/react-best-practices/rules/js-min-max-loop.md +0 -82
  277. package/src/claude/skills/react-best-practices/rules/js-set-map-lookups.md +0 -24
  278. package/src/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +0 -57
  279. package/src/claude/skills/react-best-practices/rules/rendering-activity.md +0 -26
  280. package/src/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  281. package/src/claude/skills/react-best-practices/rules/rendering-conditional-render.md +0 -40
  282. package/src/claude/skills/react-best-practices/rules/rendering-content-visibility.md +0 -38
  283. package/src/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  284. package/src/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  285. package/src/claude/skills/react-best-practices/rules/rendering-svg-precision.md +0 -28
  286. package/src/claude/skills/react-best-practices/rules/rerender-defer-reads.md +0 -39
  287. package/src/claude/skills/react-best-practices/rules/rerender-dependencies.md +0 -45
  288. package/src/claude/skills/react-best-practices/rules/rerender-derived-state.md +0 -29
  289. package/src/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +0 -74
  290. package/src/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  291. package/src/claude/skills/react-best-practices/rules/rerender-memo.md +0 -44
  292. package/src/claude/skills/react-best-practices/rules/rerender-transitions.md +0 -40
  293. package/src/claude/skills/react-best-practices/rules/server-after-nonblocking.md +0 -73
  294. package/src/claude/skills/react-best-practices/rules/server-cache-lru.md +0 -41
  295. package/src/claude/skills/react-best-practices/rules/server-cache-react.md +0 -26
  296. package/src/claude/skills/react-best-practices/rules/server-parallel-fetching.md +0 -79
  297. package/src/claude/skills/react-best-practices/rules/server-serialization.md +0 -38
@@ -1,269 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Cloudflare Worker Deployment Utility
4
-
5
- Automates Cloudflare Worker deployments with wrangler.toml configuration handling,
6
- multi-environment support, and comprehensive error handling.
7
-
8
- Usage:
9
- python cloudflare-deploy.py --env production --dry-run
10
- python cloudflare-deploy.py --project ./my-worker --env staging
11
- """
12
-
13
- import argparse
14
- import json
15
- import subprocess
16
- import sys
17
- from pathlib import Path
18
- from typing import Dict, List, Optional, Tuple
19
-
20
-
21
- class CloudflareDeployError(Exception):
22
- """Custom exception for Cloudflare deployment errors."""
23
- pass
24
-
25
-
26
- class CloudflareDeploy:
27
- """Handle Cloudflare Worker deployments with wrangler CLI."""
28
-
29
- def __init__(self, project_dir: Path, env: Optional[str] = None,
30
- dry_run: bool = False, verbose: bool = False):
31
- """
32
- Initialize CloudflareDeploy.
33
-
34
- Args:
35
- project_dir: Path to Worker project directory
36
- env: Environment name (production, staging, dev)
37
- dry_run: Preview deployment without actually deploying
38
- verbose: Enable verbose output
39
- """
40
- self.project_dir = Path(project_dir).resolve()
41
- self.env = env
42
- self.dry_run = dry_run
43
- self.verbose = verbose
44
- self.wrangler_toml = self.project_dir / "wrangler.toml"
45
-
46
- def validate_project(self) -> bool:
47
- """
48
- Validate project directory and wrangler.toml existence.
49
-
50
- Returns:
51
- True if valid, False otherwise
52
-
53
- Raises:
54
- CloudflareDeployError: If validation fails
55
- """
56
- if not self.project_dir.exists():
57
- raise CloudflareDeployError(
58
- f"Project directory does not exist: {self.project_dir}"
59
- )
60
-
61
- if not self.wrangler_toml.exists():
62
- raise CloudflareDeployError(
63
- f"wrangler.toml not found in: {self.project_dir}"
64
- )
65
-
66
- return True
67
-
68
- def check_wrangler_installed(self) -> bool:
69
- """
70
- Check if wrangler CLI is installed.
71
-
72
- Returns:
73
- True if installed, False otherwise
74
- """
75
- try:
76
- result = subprocess.run(
77
- ["wrangler", "--version"],
78
- capture_output=True,
79
- text=True,
80
- check=True
81
- )
82
- if self.verbose:
83
- print(f"Wrangler version: {result.stdout.strip()}")
84
- return True
85
- except (subprocess.CalledProcessError, FileNotFoundError):
86
- return False
87
-
88
- def run_command(self, cmd: List[str], check: bool = True) -> Tuple[int, str, str]:
89
- """
90
- Run shell command and capture output.
91
-
92
- Args:
93
- cmd: Command and arguments as list
94
- check: Raise exception on non-zero exit code
95
-
96
- Returns:
97
- Tuple of (exit_code, stdout, stderr)
98
-
99
- Raises:
100
- CloudflareDeployError: If command fails and check=True
101
- """
102
- if self.verbose:
103
- print(f"Running: {' '.join(cmd)}")
104
-
105
- try:
106
- result = subprocess.run(
107
- cmd,
108
- capture_output=True,
109
- text=True,
110
- cwd=self.project_dir,
111
- check=check
112
- )
113
- return result.returncode, result.stdout, result.stderr
114
- except subprocess.CalledProcessError as e:
115
- if check:
116
- raise CloudflareDeployError(
117
- f"Command failed: {' '.join(cmd)}\n{e.stderr}"
118
- )
119
- return e.returncode, e.stdout, e.stderr
120
-
121
- def get_worker_name(self) -> str:
122
- """
123
- Extract worker name from wrangler.toml.
124
-
125
- Returns:
126
- Worker name
127
-
128
- Raises:
129
- CloudflareDeployError: If name cannot be extracted
130
- """
131
- try:
132
- with open(self.wrangler_toml, 'r') as f:
133
- for line in f:
134
- if line.strip().startswith('name'):
135
- # Parse: name = "worker-name"
136
- return line.split('=')[1].strip().strip('"\'')
137
- except Exception as e:
138
- raise CloudflareDeployError(f"Failed to read worker name: {e}")
139
-
140
- raise CloudflareDeployError("Worker name not found in wrangler.toml")
141
-
142
- def build_deploy_command(self) -> List[str]:
143
- """
144
- Build wrangler deploy command with appropriate flags.
145
-
146
- Returns:
147
- Command as list of strings
148
- """
149
- cmd = ["wrangler", "deploy"]
150
-
151
- if self.env:
152
- cmd.extend(["--env", self.env])
153
-
154
- if self.dry_run:
155
- cmd.append("--dry-run")
156
-
157
- return cmd
158
-
159
- def deploy(self) -> bool:
160
- """
161
- Execute deployment.
162
-
163
- Returns:
164
- True if successful
165
-
166
- Raises:
167
- CloudflareDeployError: If deployment fails
168
- """
169
- # Validate
170
- self.validate_project()
171
-
172
- if not self.check_wrangler_installed():
173
- raise CloudflareDeployError(
174
- "wrangler CLI not installed. Install: npm install -g wrangler"
175
- )
176
-
177
- worker_name = self.get_worker_name()
178
- env_suffix = f" ({self.env})" if self.env else ""
179
- mode = "DRY RUN" if self.dry_run else "DEPLOY"
180
-
181
- print(f"\n{mode}: {worker_name}{env_suffix}")
182
- print(f"Project: {self.project_dir}\n")
183
-
184
- # Build and run command
185
- cmd = self.build_deploy_command()
186
- exit_code, stdout, stderr = self.run_command(cmd)
187
-
188
- # Output results
189
- if stdout:
190
- print(stdout)
191
- if stderr:
192
- print(stderr, file=sys.stderr)
193
-
194
- if exit_code == 0:
195
- status = "would be deployed" if self.dry_run else "deployed successfully"
196
- print(f"\n✓ Worker {status}")
197
- return True
198
- else:
199
- raise CloudflareDeployError("Deployment failed")
200
-
201
-
202
- def main():
203
- """CLI entry point."""
204
- parser = argparse.ArgumentParser(
205
- description="Deploy Cloudflare Worker with wrangler",
206
- formatter_class=argparse.RawDescriptionHelpFormatter,
207
- epilog="""
208
- Examples:
209
- python cloudflare-deploy.py
210
- python cloudflare-deploy.py --env production
211
- python cloudflare-deploy.py --project ./my-worker --env staging
212
- python cloudflare-deploy.py --dry-run
213
- python cloudflare-deploy.py --env prod --verbose
214
- """
215
- )
216
-
217
- parser.add_argument(
218
- "--project",
219
- type=str,
220
- default=".",
221
- help="Path to Worker project directory (default: current directory)"
222
- )
223
-
224
- parser.add_argument(
225
- "--env",
226
- type=str,
227
- choices=["production", "staging", "dev"],
228
- help="Environment to deploy to (production, staging, dev)"
229
- )
230
-
231
- parser.add_argument(
232
- "--dry-run",
233
- action="store_true",
234
- help="Preview deployment without actually deploying"
235
- )
236
-
237
- parser.add_argument(
238
- "--verbose",
239
- "-v",
240
- action="store_true",
241
- help="Enable verbose output"
242
- )
243
-
244
- args = parser.parse_args()
245
-
246
- try:
247
- deployer = CloudflareDeploy(
248
- project_dir=args.project,
249
- env=args.env,
250
- dry_run=args.dry_run,
251
- verbose=args.verbose
252
- )
253
-
254
- success = deployer.deploy()
255
- sys.exit(0 if success else 1)
256
-
257
- except CloudflareDeployError as e:
258
- print(f"Error: {e}", file=sys.stderr)
259
- sys.exit(1)
260
- except KeyboardInterrupt:
261
- print("\nDeployment cancelled by user", file=sys.stderr)
262
- sys.exit(130)
263
- except Exception as e:
264
- print(f"Unexpected error: {e}", file=sys.stderr)
265
- sys.exit(1)
266
-
267
-
268
- if __name__ == "__main__":
269
- main()
@@ -1,332 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Dockerfile Optimization Analyzer
4
-
5
- Analyzes Dockerfiles for optimization opportunities including multi-stage builds,
6
- security issues, size reduction, and best practices.
7
-
8
- Usage:
9
- python docker-optimize.py Dockerfile
10
- python docker-optimize.py --json Dockerfile
11
- python docker-optimize.py --verbose Dockerfile
12
- """
13
-
14
- import argparse
15
- import json
16
- import re
17
- import sys
18
- from pathlib import Path
19
- from typing import Dict, List, Optional, Tuple
20
-
21
- # Windows UTF-8 compatibility (works for both local and global installs)
22
- CLAUDE_ROOT = Path(__file__).parent.parent.parent.parent
23
- sys.path.insert(0, str(CLAUDE_ROOT / 'scripts'))
24
- try:
25
- from win_compat import ensure_utf8_stdout
26
- ensure_utf8_stdout()
27
- except ImportError:
28
- if sys.platform == 'win32':
29
- import io
30
- if hasattr(sys.stdout, 'buffer'):
31
- sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
32
-
33
-
34
- class DockerfileAnalyzer:
35
- """Analyze Dockerfile for optimization opportunities."""
36
-
37
- def __init__(self, dockerfile_path: Path, verbose: bool = False):
38
- """
39
- Initialize analyzer.
40
-
41
- Args:
42
- dockerfile_path: Path to Dockerfile
43
- verbose: Enable verbose output
44
- """
45
- self.dockerfile_path = Path(dockerfile_path)
46
- self.verbose = verbose
47
- self.lines = []
48
- self.issues = []
49
- self.suggestions = []
50
-
51
- def load_dockerfile(self) -> bool:
52
- """
53
- Load and parse Dockerfile.
54
-
55
- Returns:
56
- True if loaded successfully
57
-
58
- Raises:
59
- FileNotFoundError: If Dockerfile doesn't exist
60
- """
61
- if not self.dockerfile_path.exists():
62
- raise FileNotFoundError(f"Dockerfile not found: {self.dockerfile_path}")
63
-
64
- with open(self.dockerfile_path, 'r') as f:
65
- self.lines = f.readlines()
66
-
67
- return True
68
-
69
- def analyze_base_image(self) -> None:
70
- """Check base image for optimization opportunities."""
71
- for i, line in enumerate(self.lines, 1):
72
- line = line.strip()
73
- if line.startswith('FROM'):
74
- # Check for 'latest' tag
75
- if ':latest' in line or (': ' not in line and 'AS' not in line and '@' not in line):
76
- self.issues.append({
77
- 'line': i,
78
- 'severity': 'warning',
79
- 'category': 'base_image',
80
- 'message': 'Base image uses :latest or no tag',
81
- 'suggestion': 'Use specific version tags for reproducibility'
82
- })
83
-
84
- # Check for non-alpine/slim variants
85
- if 'node' in line.lower() and 'alpine' not in line.lower():
86
- self.suggestions.append({
87
- 'line': i,
88
- 'category': 'size',
89
- 'message': 'Consider using Alpine variant',
90
- 'suggestion': 'node:20-alpine is ~10x smaller than node:20'
91
- })
92
-
93
- def analyze_multi_stage(self) -> None:
94
- """Check if multi-stage build is used."""
95
- from_count = sum(1 for line in self.lines if line.strip().startswith('FROM'))
96
-
97
- if from_count == 1:
98
- # Check if build tools are installed
99
- has_build_tools = any(
100
- any(tool in line.lower() for tool in ['gcc', 'make', 'build-essential', 'npm install', 'pip install'])
101
- for line in self.lines
102
- )
103
-
104
- if has_build_tools:
105
- self.issues.append({
106
- 'line': 0,
107
- 'severity': 'warning',
108
- 'category': 'optimization',
109
- 'message': 'Single-stage build with build tools',
110
- 'suggestion': 'Use multi-stage build to exclude build dependencies from final image'
111
- })
112
-
113
- def analyze_layer_caching(self) -> None:
114
- """Check for optimal layer caching order."""
115
- copy_lines = []
116
- run_lines = []
117
-
118
- for i, line in enumerate(self.lines, 1):
119
- stripped = line.strip()
120
- if stripped.startswith('COPY'):
121
- copy_lines.append((i, stripped))
122
- elif stripped.startswith('RUN'):
123
- run_lines.append((i, stripped))
124
-
125
- # Check if dependency files copied before source
126
- has_package_copy = any('package.json' in line or 'requirements.txt' in line or 'go.mod' in line
127
- for _, line in copy_lines)
128
- has_source_copy = any('COPY . .' in line or 'COPY ./' in line
129
- for _, line in copy_lines)
130
-
131
- if has_source_copy and not has_package_copy:
132
- self.issues.append({
133
- 'line': 0,
134
- 'severity': 'warning',
135
- 'category': 'caching',
136
- 'message': 'Source copied before dependencies',
137
- 'suggestion': 'Copy dependency files first (package.json, requirements.txt) then run install, then copy source'
138
- })
139
-
140
- def analyze_security(self) -> None:
141
- """Check for security issues."""
142
- has_user = any(line.strip().startswith('USER') and 'root' not in line.lower()
143
- for line in self.lines)
144
-
145
- if not has_user:
146
- self.issues.append({
147
- 'line': 0,
148
- 'severity': 'error',
149
- 'category': 'security',
150
- 'message': 'Container runs as root',
151
- 'suggestion': 'Create and use non-root user with USER instruction'
152
- })
153
-
154
- # Check for secrets in build
155
- for i, line in enumerate(self.lines, 1):
156
- if any(secret in line.upper() for secret in ['PASSWORD', 'SECRET', 'TOKEN', 'API_KEY']):
157
- if 'ENV' in line or 'ARG' in line:
158
- self.issues.append({
159
- 'line': i,
160
- 'severity': 'error',
161
- 'category': 'security',
162
- 'message': 'Potential secret in Dockerfile',
163
- 'suggestion': 'Use build-time arguments or runtime environment variables'
164
- })
165
-
166
- def analyze_apt_cache(self) -> None:
167
- """Check for apt cache cleanup."""
168
- for i, line in enumerate(self.lines, 1):
169
- if 'apt-get install' in line.lower() or 'apt install' in line.lower():
170
- # Check if same RUN command cleans cache
171
- if 'rm -rf /var/lib/apt/lists/*' not in line:
172
- self.suggestions.append({
173
- 'line': i,
174
- 'category': 'size',
175
- 'message': 'apt cache not cleaned in same layer',
176
- 'suggestion': 'Add && rm -rf /var/lib/apt/lists/* to reduce image size'
177
- })
178
-
179
- def analyze_combine_run(self) -> None:
180
- """Check for multiple consecutive RUN commands."""
181
- consecutive_runs = 0
182
- first_run_line = 0
183
-
184
- for i, line in enumerate(self.lines, 1):
185
- if line.strip().startswith('RUN'):
186
- if consecutive_runs == 0:
187
- first_run_line = i
188
- consecutive_runs += 1
189
- else:
190
- if consecutive_runs > 1:
191
- self.suggestions.append({
192
- 'line': first_run_line,
193
- 'category': 'layers',
194
- 'message': f'{consecutive_runs} consecutive RUN commands',
195
- 'suggestion': 'Combine related RUN commands with && to reduce layers'
196
- })
197
- consecutive_runs = 0
198
-
199
- def analyze_workdir(self) -> None:
200
- """Check for WORKDIR usage."""
201
- has_workdir = any(line.strip().startswith('WORKDIR') for line in self.lines)
202
-
203
- if not has_workdir:
204
- self.suggestions.append({
205
- 'line': 0,
206
- 'category': 'best_practice',
207
- 'message': 'No WORKDIR specified',
208
- 'suggestion': 'Use WORKDIR to set working directory instead of cd commands'
209
- })
210
-
211
- def analyze(self) -> Dict:
212
- """
213
- Run all analyses.
214
-
215
- Returns:
216
- Analysis results dictionary
217
- """
218
- self.load_dockerfile()
219
-
220
- self.analyze_base_image()
221
- self.analyze_multi_stage()
222
- self.analyze_layer_caching()
223
- self.analyze_security()
224
- self.analyze_apt_cache()
225
- self.analyze_combine_run()
226
- self.analyze_workdir()
227
-
228
- return {
229
- 'dockerfile': str(self.dockerfile_path),
230
- 'total_lines': len(self.lines),
231
- 'issues': self.issues,
232
- 'suggestions': self.suggestions,
233
- 'summary': {
234
- 'errors': len([i for i in self.issues if i.get('severity') == 'error']),
235
- 'warnings': len([i for i in self.issues if i.get('severity') == 'warning']),
236
- 'suggestions': len(self.suggestions)
237
- }
238
- }
239
-
240
- def print_results(self, results: Dict) -> None:
241
- """
242
- Print analysis results in human-readable format.
243
-
244
- Args:
245
- results: Analysis results from analyze()
246
- """
247
- print(f"\nDockerfile Analysis: {results['dockerfile']}")
248
- print(f"Total lines: {results['total_lines']}")
249
- print(f"\nSummary:")
250
- print(f" Errors: {results['summary']['errors']}")
251
- print(f" Warnings: {results['summary']['warnings']}")
252
- print(f" Suggestions: {results['summary']['suggestions']}")
253
-
254
- if results['issues']:
255
- print(f"\n{'='*60}")
256
- print("ISSUES:")
257
- print('='*60)
258
- for issue in results['issues']:
259
- severity = issue.get('severity', 'info').upper()
260
- line_info = f"Line {issue['line']}" if issue['line'] > 0 else "General"
261
- print(f"\n[{severity}] {line_info} - {issue['category']}")
262
- print(f" {issue['message']}")
263
- print(f" → {issue['suggestion']}")
264
-
265
- if results['suggestions']:
266
- print(f"\n{'='*60}")
267
- print("SUGGESTIONS:")
268
- print('='*60)
269
- for sugg in results['suggestions']:
270
- line_info = f"Line {sugg['line']}" if sugg['line'] > 0 else "General"
271
- print(f"\n{line_info} - {sugg['category']}")
272
- print(f" {sugg['message']}")
273
- print(f" → {sugg['suggestion']}")
274
-
275
- print()
276
-
277
-
278
- def main():
279
- """CLI entry point."""
280
- parser = argparse.ArgumentParser(
281
- description="Analyze Dockerfile for optimization opportunities",
282
- formatter_class=argparse.RawDescriptionHelpFormatter
283
- )
284
-
285
- parser.add_argument(
286
- "dockerfile",
287
- type=str,
288
- help="Path to Dockerfile"
289
- )
290
-
291
- parser.add_argument(
292
- "--json",
293
- action="store_true",
294
- help="Output results as JSON"
295
- )
296
-
297
- parser.add_argument(
298
- "--verbose",
299
- "-v",
300
- action="store_true",
301
- help="Enable verbose output"
302
- )
303
-
304
- args = parser.parse_args()
305
-
306
- try:
307
- analyzer = DockerfileAnalyzer(
308
- dockerfile_path=args.dockerfile,
309
- verbose=args.verbose
310
- )
311
-
312
- results = analyzer.analyze()
313
-
314
- if args.json:
315
- print(json.dumps(results, indent=2))
316
- else:
317
- analyzer.print_results(results)
318
-
319
- # Exit with error code if issues found
320
- if results['summary']['errors'] > 0:
321
- sys.exit(1)
322
-
323
- except FileNotFoundError as e:
324
- print(f"Error: {e}", file=sys.stderr)
325
- sys.exit(1)
326
- except Exception as e:
327
- print(f"Unexpected error: {e}", file=sys.stderr)
328
- sys.exit(1)
329
-
330
-
331
- if __name__ == "__main__":
332
- main()
@@ -1,20 +0,0 @@
1
- # DevOps Skill Dependencies
2
- # Python 3.10+ required
3
-
4
- # No Python package dependencies - uses only standard library
5
-
6
- # Testing dependencies (dev)
7
- pytest>=8.0.0
8
- pytest-cov>=4.1.0
9
- pytest-mock>=3.12.0
10
-
11
- # Note: This skill requires various CLI tools depending on platform:
12
- #
13
- # Cloudflare:
14
- # - wrangler CLI: npm install -g wrangler
15
- #
16
- # Docker:
17
- # - docker CLI: https://docs.docker.com/get-docker/
18
- #
19
- # Google Cloud:
20
- # - gcloud CLI: https://cloud.google.com/sdk/docs/install
@@ -1,3 +0,0 @@
1
- pytest>=7.0.0
2
- pytest-cov>=4.0.0
3
- pytest-mock>=3.10.0