@thanhvn14/csvibe 0.1.4 → 0.1.5
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.
- package/.github/agents/schemas/base-output.schema.json +88 -0
- package/.github/agents/schemas/brainstorm-output.schema.json +88 -0
- package/.github/agents/schemas/scout-output.schema.json +60 -0
- package/.github/agents/scripts/fetch-copilot-tools.js +245 -0
- package/.github/agents/scripts/lib/parse-agent-file.js +275 -0
- package/.github/agents/scripts/package-lock.json +78 -0
- package/.github/agents/scripts/package.json +22 -0
- package/.github/agents/scripts/schemas/agent-frontmatter.schema.json +83 -0
- package/.github/agents/scripts/validate-agent-all.js +157 -0
- package/.github/agents/scripts/validate-agent-frontmatter.js +96 -0
- package/.github/agents/scripts/validate-agent-handoffs.js +169 -0
- package/.github/agents/scripts/validate-agent-output.js +157 -0
- package/.github/agents/scripts/validate-agent-tools.js +278 -0
- package/.github/skills/.env.example +100 -0
- package/.github/skills/.install-state.json +23 -0
- package/.github/skills/README.md +149 -0
- package/.github/skills/ai-multimodal/.env.example +204 -0
- package/.github/skills/ai-multimodal/scripts/.coverage +0 -0
- package/.github/skills/ai-multimodal/scripts/check_setup.py +305 -0
- package/.github/skills/ai-multimodal/scripts/document_converter.py +395 -0
- package/.github/skills/ai-multimodal/scripts/gemini_batch_process.py +1184 -0
- package/.github/skills/ai-multimodal/scripts/media_optimizer.py +506 -0
- package/.github/skills/ai-multimodal/scripts/requirements.txt +26 -0
- package/.github/skills/better-auth/scripts/.coverage +0 -0
- package/.github/skills/better-auth/scripts/better_auth_init.py +521 -0
- package/.github/skills/better-auth/scripts/requirements.txt +15 -0
- package/.github/skills/chrome-devtools/scripts/README.md +272 -0
- package/.github/skills/chrome-devtools/scripts/__tests__/selector.test.js +210 -0
- package/.github/skills/chrome-devtools/scripts/aria-snapshot.js +362 -0
- package/.github/skills/chrome-devtools/scripts/click.js +83 -0
- package/.github/skills/chrome-devtools/scripts/console.js +79 -0
- package/.github/skills/chrome-devtools/scripts/evaluate.js +53 -0
- package/.github/skills/chrome-devtools/scripts/fill.js +76 -0
- package/.github/skills/chrome-devtools/scripts/inject-auth.js +229 -0
- package/.github/skills/chrome-devtools/scripts/install-deps.sh +181 -0
- package/.github/skills/chrome-devtools/scripts/install.sh +83 -0
- package/.github/skills/chrome-devtools/scripts/lib/browser.js +318 -0
- package/.github/skills/chrome-devtools/scripts/lib/selector.js +178 -0
- package/.github/skills/chrome-devtools/scripts/navigate.js +54 -0
- package/.github/skills/chrome-devtools/scripts/network.js +106 -0
- package/.github/skills/chrome-devtools/scripts/package-lock.json +1589 -0
- package/.github/skills/chrome-devtools/scripts/package.json +16 -0
- package/.github/skills/chrome-devtools/scripts/performance.js +149 -0
- package/.github/skills/chrome-devtools/scripts/screenshot.js +198 -0
- package/.github/skills/chrome-devtools/scripts/select-ref.js +131 -0
- package/.github/skills/chrome-devtools/scripts/snapshot.js +135 -0
- package/.github/skills/common/README.md +120 -0
- package/.github/skills/common/api_key_helper.py +411 -0
- package/.github/skills/common/api_key_rotator.py +248 -0
- package/.github/skills/databases/scripts/.coverage +0 -0
- package/.github/skills/databases/scripts/db_backup.py +502 -0
- package/.github/skills/databases/scripts/db_migrate.py +425 -0
- package/.github/skills/databases/scripts/db_performance_check.py +456 -0
- package/.github/skills/databases/scripts/requirements.txt +20 -0
- package/.github/skills/debugging/scripts/find-polluter.sh +63 -0
- package/.github/skills/devops/.env.example +76 -0
- package/.github/skills/devops/scripts/cloudflare_deploy.py +269 -0
- package/.github/skills/devops/scripts/docker_optimize.py +331 -0
- package/.github/skills/devops/scripts/requirements.txt +20 -0
- package/.github/skills/docs-seeker/.env.example +15 -0
- package/.github/skills/docs-seeker/package.json +25 -0
- package/.github/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
- package/.github/skills/docs-seeker/scripts/detect-topic.js +172 -0
- package/.github/skills/docs-seeker/scripts/fetch-docs.js +213 -0
- package/.github/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
- package/.github/skills/document-skills/docx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/.github/skills/document-skills/docx/scripts/__init__.py +1 -0
- package/.github/skills/document-skills/docx/scripts/document.py +1276 -0
- package/.github/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/people.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/utilities.py +374 -0
- package/.github/skills/document-skills/pdf/LICENSE.txt +30 -0
- package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
- package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/.github/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
- package/.github/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/.github/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
- package/.github/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
- package/.github/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
- package/.github/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/.github/skills/document-skills/pptx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/.github/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
- package/.github/skills/document-skills/pptx/scripts/inventory.py +1020 -0
- package/.github/skills/document-skills/pptx/scripts/rearrange.py +231 -0
- package/.github/skills/document-skills/pptx/scripts/replace.py +385 -0
- package/.github/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
- package/.github/skills/document-skills/xlsx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/xlsx/recalc.py +190 -0
- package/.github/skills/install.ps1 +1220 -0
- package/.github/skills/install.sh +1032 -0
- package/.github/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
- package/.github/skills/markdown-novel-viewer/assets/favicon.png +0 -0
- package/.github/skills/markdown-novel-viewer/assets/novel-theme.css +818 -0
- package/.github/skills/markdown-novel-viewer/assets/reader.js +262 -0
- package/.github/skills/markdown-novel-viewer/assets/template.html +80 -0
- package/.github/skills/markdown-novel-viewer/package-lock.json +146 -0
- package/.github/skills/markdown-novel-viewer/package.json +15 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +272 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +48 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
- package/.github/skills/markdown-novel-viewer/scripts/server.cjs +411 -0
- package/.github/skills/mcp-builder/LICENSE.txt +202 -0
- package/.github/skills/mcp-builder/scripts/connections.py +151 -0
- package/.github/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/.github/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/.github/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/.github/skills/mcp-management/README.md +219 -0
- package/.github/skills/mcp-management/assets/tools.json +3146 -0
- package/.github/skills/mcp-management/package-lock.json +6 -0
- package/.github/skills/mcp-management/scripts/.env.example +10 -0
- package/.github/skills/mcp-management/scripts/cli.ts +195 -0
- package/.github/skills/mcp-management/scripts/dist/analyze-tools.js +70 -0
- package/.github/skills/mcp-management/scripts/dist/cli.js +160 -0
- package/.github/skills/mcp-management/scripts/dist/mcp-client.js +183 -0
- package/.github/skills/mcp-management/scripts/mcp-client.ts +230 -0
- package/.github/skills/mcp-management/scripts/package.json +20 -0
- package/.github/skills/media-processing/scripts/README.md +111 -0
- package/.github/skills/media-processing/scripts/batch-remove-background.sh +124 -0
- package/.github/skills/media-processing/scripts/batch_resize.py +342 -0
- package/.github/skills/media-processing/scripts/media_convert.py +311 -0
- package/.github/skills/media-processing/scripts/remove-background.sh +96 -0
- package/.github/skills/media-processing/scripts/remove-bg-node.js +158 -0
- package/.github/skills/media-processing/scripts/requirements.txt +24 -0
- package/.github/skills/media-processing/scripts/video_optimize.py +414 -0
- package/.github/skills/payment-integration/README.md +185 -0
- package/.github/skills/payment-integration/scripts/.env.example +20 -0
- package/.github/skills/payment-integration/scripts/checkout-helper.js +244 -0
- package/.github/skills/payment-integration/scripts/package.json +17 -0
- package/.github/skills/payment-integration/scripts/polar-webhook-verify.js +202 -0
- package/.github/skills/payment-integration/scripts/sepay-webhook-verify.js +193 -0
- package/.github/skills/payment-integration/scripts/test-scripts.js +237 -0
- package/.github/skills/plans-kanban/assets/dashboard-template.html +119 -0
- package/.github/skills/plans-kanban/assets/dashboard.css +1594 -0
- package/.github/skills/plans-kanban/assets/dashboard.js +596 -0
- package/.github/skills/plans-kanban/assets/favicon.png +0 -0
- package/.github/skills/plans-kanban/package-lock.json +123 -0
- package/.github/skills/plans-kanban/package.json +13 -0
- package/.github/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +884 -0
- package/.github/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-parser.cjs +175 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-scanner.cjs +272 -0
- package/.github/skills/plans-kanban/scripts/lib/port-finder.cjs +48 -0
- package/.github/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
- package/.github/skills/plans-kanban/scripts/server.cjs +260 -0
- package/.github/skills/repomix/scripts/.coverage +0 -0
- package/.github/skills/repomix/scripts/README.md +179 -0
- package/.github/skills/repomix/scripts/repomix_batch.py +455 -0
- package/.github/skills/repomix/scripts/repos.example.json +15 -0
- package/.github/skills/repomix/scripts/requirements.txt +15 -0
- package/.github/skills/scout-validation/scripts/lib/broad-pattern-detector.cjs +124 -0
- package/.github/skills/scout-validation/scripts/lib/path-checker.cjs +66 -0
- package/.github/skills/scout-validation/scripts/lib/schema-validator.cjs +45 -0
- package/.github/skills/scout-validation/scripts/package.json +11 -0
- package/.github/skills/scout-validation/scripts/validate-scout-output.cjs +219 -0
- package/.github/skills/scout-validation/test/broad-pattern-output.json +18 -0
- package/.github/skills/scout-validation/test/invalid-path-output.json +18 -0
- package/.github/skills/scout-validation/test/valid-scout-output.json +26 -0
- package/.github/skills/sequential-thinking/.env.example +8 -0
- package/.github/skills/sequential-thinking/README.md +183 -0
- package/.github/skills/sequential-thinking/package.json +31 -0
- package/.github/skills/sequential-thinking/scripts/format-thought.js +159 -0
- package/.github/skills/sequential-thinking/scripts/process-thought.js +236 -0
- package/.github/skills/shopify/README.md +66 -0
- package/.github/skills/shopify/scripts/.coverage +0 -0
- package/.github/skills/shopify/scripts/requirements.txt +19 -0
- package/.github/skills/shopify/scripts/shopify_init.py +423 -0
- package/.github/skills/skill-creator/LICENSE.txt +202 -0
- package/.github/skills/skill-creator/scripts/init_skill.py +303 -0
- package/.github/skills/skill-creator/scripts/package_skill.py +110 -0
- package/.github/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/.github/skills/ui-styling/LICENSE.txt +202 -0
- package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/.github/skills/ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/scripts/.coverage +0 -0
- package/.github/skills/ui-styling/scripts/requirements.txt +17 -0
- package/.github/skills/ui-styling/scripts/shadcn_add.py +292 -0
- package/.github/skills/ui-styling/scripts/tailwind_config_gen.py +456 -0
- package/.github/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.github/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.github/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.github/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.github/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +51 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.github/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.github/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.github/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.github/skills/ui-ux-pro-max/scripts/core.py +236 -0
- package/.github/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/.github/skills/web-frameworks/scripts/.coverage +0 -0
- package/.github/skills/web-frameworks/scripts/__init__.py +0 -0
- package/.github/skills/web-frameworks/scripts/nextjs_init.py +547 -0
- package/.github/skills/web-frameworks/scripts/requirements.txt +16 -0
- package/.github/skills/web-frameworks/scripts/turborepo_migrate.py +394 -0
- package/dist/config/constants.d.ts +2 -0
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +4 -1
- package/dist/config/constants.js.map +1 -1
- package/dist/domains/github/github-client.d.ts +5 -0
- package/dist/domains/github/github-client.d.ts.map +1 -1
- package/dist/domains/github/github-client.js +44 -0
- package/dist/domains/github/github-client.js.map +1 -1
- package/dist/utils/downloader.d.ts +3 -1
- package/dist/utils/downloader.d.ts.map +1 -1
- package/dist/utils/downloader.js +48 -11
- package/dist/utils/downloader.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,269 @@
|
|
|
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()
|
|
@@ -0,0 +1,331 @@
|
|
|
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
|
|
22
|
+
sys.path.insert(0, str(Path.home() / '.claude' / 'scripts'))
|
|
23
|
+
try:
|
|
24
|
+
from win_compat import ensure_utf8_stdout
|
|
25
|
+
ensure_utf8_stdout()
|
|
26
|
+
except ImportError:
|
|
27
|
+
if sys.platform == 'win32':
|
|
28
|
+
import io
|
|
29
|
+
if hasattr(sys.stdout, 'buffer'):
|
|
30
|
+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DockerfileAnalyzer:
|
|
34
|
+
"""Analyze Dockerfile for optimization opportunities."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, dockerfile_path: Path, verbose: bool = False):
|
|
37
|
+
"""
|
|
38
|
+
Initialize analyzer.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
dockerfile_path: Path to Dockerfile
|
|
42
|
+
verbose: Enable verbose output
|
|
43
|
+
"""
|
|
44
|
+
self.dockerfile_path = Path(dockerfile_path)
|
|
45
|
+
self.verbose = verbose
|
|
46
|
+
self.lines = []
|
|
47
|
+
self.issues = []
|
|
48
|
+
self.suggestions = []
|
|
49
|
+
|
|
50
|
+
def load_dockerfile(self) -> bool:
|
|
51
|
+
"""
|
|
52
|
+
Load and parse Dockerfile.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
True if loaded successfully
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
FileNotFoundError: If Dockerfile doesn't exist
|
|
59
|
+
"""
|
|
60
|
+
if not self.dockerfile_path.exists():
|
|
61
|
+
raise FileNotFoundError(f"Dockerfile not found: {self.dockerfile_path}")
|
|
62
|
+
|
|
63
|
+
with open(self.dockerfile_path, 'r') as f:
|
|
64
|
+
self.lines = f.readlines()
|
|
65
|
+
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
def analyze_base_image(self) -> None:
|
|
69
|
+
"""Check base image for optimization opportunities."""
|
|
70
|
+
for i, line in enumerate(self.lines, 1):
|
|
71
|
+
line = line.strip()
|
|
72
|
+
if line.startswith('FROM'):
|
|
73
|
+
# Check for 'latest' tag
|
|
74
|
+
if ':latest' in line or (': ' not in line and 'AS' not in line and '@' not in line):
|
|
75
|
+
self.issues.append({
|
|
76
|
+
'line': i,
|
|
77
|
+
'severity': 'warning',
|
|
78
|
+
'category': 'base_image',
|
|
79
|
+
'message': 'Base image uses :latest or no tag',
|
|
80
|
+
'suggestion': 'Use specific version tags for reproducibility'
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
# Check for non-alpine/slim variants
|
|
84
|
+
if 'node' in line.lower() and 'alpine' not in line.lower():
|
|
85
|
+
self.suggestions.append({
|
|
86
|
+
'line': i,
|
|
87
|
+
'category': 'size',
|
|
88
|
+
'message': 'Consider using Alpine variant',
|
|
89
|
+
'suggestion': 'node:20-alpine is ~10x smaller than node:20'
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
def analyze_multi_stage(self) -> None:
|
|
93
|
+
"""Check if multi-stage build is used."""
|
|
94
|
+
from_count = sum(1 for line in self.lines if line.strip().startswith('FROM'))
|
|
95
|
+
|
|
96
|
+
if from_count == 1:
|
|
97
|
+
# Check if build tools are installed
|
|
98
|
+
has_build_tools = any(
|
|
99
|
+
any(tool in line.lower() for tool in ['gcc', 'make', 'build-essential', 'npm install', 'pip install'])
|
|
100
|
+
for line in self.lines
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if has_build_tools:
|
|
104
|
+
self.issues.append({
|
|
105
|
+
'line': 0,
|
|
106
|
+
'severity': 'warning',
|
|
107
|
+
'category': 'optimization',
|
|
108
|
+
'message': 'Single-stage build with build tools',
|
|
109
|
+
'suggestion': 'Use multi-stage build to exclude build dependencies from final image'
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
def analyze_layer_caching(self) -> None:
|
|
113
|
+
"""Check for optimal layer caching order."""
|
|
114
|
+
copy_lines = []
|
|
115
|
+
run_lines = []
|
|
116
|
+
|
|
117
|
+
for i, line in enumerate(self.lines, 1):
|
|
118
|
+
stripped = line.strip()
|
|
119
|
+
if stripped.startswith('COPY'):
|
|
120
|
+
copy_lines.append((i, stripped))
|
|
121
|
+
elif stripped.startswith('RUN'):
|
|
122
|
+
run_lines.append((i, stripped))
|
|
123
|
+
|
|
124
|
+
# Check if dependency files copied before source
|
|
125
|
+
has_package_copy = any('package.json' in line or 'requirements.txt' in line or 'go.mod' in line
|
|
126
|
+
for _, line in copy_lines)
|
|
127
|
+
has_source_copy = any('COPY . .' in line or 'COPY ./' in line
|
|
128
|
+
for _, line in copy_lines)
|
|
129
|
+
|
|
130
|
+
if has_source_copy and not has_package_copy:
|
|
131
|
+
self.issues.append({
|
|
132
|
+
'line': 0,
|
|
133
|
+
'severity': 'warning',
|
|
134
|
+
'category': 'caching',
|
|
135
|
+
'message': 'Source copied before dependencies',
|
|
136
|
+
'suggestion': 'Copy dependency files first (package.json, requirements.txt) then run install, then copy source'
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
def analyze_security(self) -> None:
|
|
140
|
+
"""Check for security issues."""
|
|
141
|
+
has_user = any(line.strip().startswith('USER') and 'root' not in line.lower()
|
|
142
|
+
for line in self.lines)
|
|
143
|
+
|
|
144
|
+
if not has_user:
|
|
145
|
+
self.issues.append({
|
|
146
|
+
'line': 0,
|
|
147
|
+
'severity': 'error',
|
|
148
|
+
'category': 'security',
|
|
149
|
+
'message': 'Container runs as root',
|
|
150
|
+
'suggestion': 'Create and use non-root user with USER instruction'
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
# Check for secrets in build
|
|
154
|
+
for i, line in enumerate(self.lines, 1):
|
|
155
|
+
if any(secret in line.upper() for secret in ['PASSWORD', 'SECRET', 'TOKEN', 'API_KEY']):
|
|
156
|
+
if 'ENV' in line or 'ARG' in line:
|
|
157
|
+
self.issues.append({
|
|
158
|
+
'line': i,
|
|
159
|
+
'severity': 'error',
|
|
160
|
+
'category': 'security',
|
|
161
|
+
'message': 'Potential secret in Dockerfile',
|
|
162
|
+
'suggestion': 'Use build-time arguments or runtime environment variables'
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
def analyze_apt_cache(self) -> None:
|
|
166
|
+
"""Check for apt cache cleanup."""
|
|
167
|
+
for i, line in enumerate(self.lines, 1):
|
|
168
|
+
if 'apt-get install' in line.lower() or 'apt install' in line.lower():
|
|
169
|
+
# Check if same RUN command cleans cache
|
|
170
|
+
if 'rm -rf /var/lib/apt/lists/*' not in line:
|
|
171
|
+
self.suggestions.append({
|
|
172
|
+
'line': i,
|
|
173
|
+
'category': 'size',
|
|
174
|
+
'message': 'apt cache not cleaned in same layer',
|
|
175
|
+
'suggestion': 'Add && rm -rf /var/lib/apt/lists/* to reduce image size'
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
def analyze_combine_run(self) -> None:
|
|
179
|
+
"""Check for multiple consecutive RUN commands."""
|
|
180
|
+
consecutive_runs = 0
|
|
181
|
+
first_run_line = 0
|
|
182
|
+
|
|
183
|
+
for i, line in enumerate(self.lines, 1):
|
|
184
|
+
if line.strip().startswith('RUN'):
|
|
185
|
+
if consecutive_runs == 0:
|
|
186
|
+
first_run_line = i
|
|
187
|
+
consecutive_runs += 1
|
|
188
|
+
else:
|
|
189
|
+
if consecutive_runs > 1:
|
|
190
|
+
self.suggestions.append({
|
|
191
|
+
'line': first_run_line,
|
|
192
|
+
'category': 'layers',
|
|
193
|
+
'message': f'{consecutive_runs} consecutive RUN commands',
|
|
194
|
+
'suggestion': 'Combine related RUN commands with && to reduce layers'
|
|
195
|
+
})
|
|
196
|
+
consecutive_runs = 0
|
|
197
|
+
|
|
198
|
+
def analyze_workdir(self) -> None:
|
|
199
|
+
"""Check for WORKDIR usage."""
|
|
200
|
+
has_workdir = any(line.strip().startswith('WORKDIR') for line in self.lines)
|
|
201
|
+
|
|
202
|
+
if not has_workdir:
|
|
203
|
+
self.suggestions.append({
|
|
204
|
+
'line': 0,
|
|
205
|
+
'category': 'best_practice',
|
|
206
|
+
'message': 'No WORKDIR specified',
|
|
207
|
+
'suggestion': 'Use WORKDIR to set working directory instead of cd commands'
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
def analyze(self) -> Dict:
|
|
211
|
+
"""
|
|
212
|
+
Run all analyses.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Analysis results dictionary
|
|
216
|
+
"""
|
|
217
|
+
self.load_dockerfile()
|
|
218
|
+
|
|
219
|
+
self.analyze_base_image()
|
|
220
|
+
self.analyze_multi_stage()
|
|
221
|
+
self.analyze_layer_caching()
|
|
222
|
+
self.analyze_security()
|
|
223
|
+
self.analyze_apt_cache()
|
|
224
|
+
self.analyze_combine_run()
|
|
225
|
+
self.analyze_workdir()
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
'dockerfile': str(self.dockerfile_path),
|
|
229
|
+
'total_lines': len(self.lines),
|
|
230
|
+
'issues': self.issues,
|
|
231
|
+
'suggestions': self.suggestions,
|
|
232
|
+
'summary': {
|
|
233
|
+
'errors': len([i for i in self.issues if i.get('severity') == 'error']),
|
|
234
|
+
'warnings': len([i for i in self.issues if i.get('severity') == 'warning']),
|
|
235
|
+
'suggestions': len(self.suggestions)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
def print_results(self, results: Dict) -> None:
|
|
240
|
+
"""
|
|
241
|
+
Print analysis results in human-readable format.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
results: Analysis results from analyze()
|
|
245
|
+
"""
|
|
246
|
+
print(f"\nDockerfile Analysis: {results['dockerfile']}")
|
|
247
|
+
print(f"Total lines: {results['total_lines']}")
|
|
248
|
+
print(f"\nSummary:")
|
|
249
|
+
print(f" Errors: {results['summary']['errors']}")
|
|
250
|
+
print(f" Warnings: {results['summary']['warnings']}")
|
|
251
|
+
print(f" Suggestions: {results['summary']['suggestions']}")
|
|
252
|
+
|
|
253
|
+
if results['issues']:
|
|
254
|
+
print(f"\n{'='*60}")
|
|
255
|
+
print("ISSUES:")
|
|
256
|
+
print('='*60)
|
|
257
|
+
for issue in results['issues']:
|
|
258
|
+
severity = issue.get('severity', 'info').upper()
|
|
259
|
+
line_info = f"Line {issue['line']}" if issue['line'] > 0 else "General"
|
|
260
|
+
print(f"\n[{severity}] {line_info} - {issue['category']}")
|
|
261
|
+
print(f" {issue['message']}")
|
|
262
|
+
print(f" → {issue['suggestion']}")
|
|
263
|
+
|
|
264
|
+
if results['suggestions']:
|
|
265
|
+
print(f"\n{'='*60}")
|
|
266
|
+
print("SUGGESTIONS:")
|
|
267
|
+
print('='*60)
|
|
268
|
+
for sugg in results['suggestions']:
|
|
269
|
+
line_info = f"Line {sugg['line']}" if sugg['line'] > 0 else "General"
|
|
270
|
+
print(f"\n{line_info} - {sugg['category']}")
|
|
271
|
+
print(f" {sugg['message']}")
|
|
272
|
+
print(f" → {sugg['suggestion']}")
|
|
273
|
+
|
|
274
|
+
print()
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def main():
|
|
278
|
+
"""CLI entry point."""
|
|
279
|
+
parser = argparse.ArgumentParser(
|
|
280
|
+
description="Analyze Dockerfile for optimization opportunities",
|
|
281
|
+
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
parser.add_argument(
|
|
285
|
+
"dockerfile",
|
|
286
|
+
type=str,
|
|
287
|
+
help="Path to Dockerfile"
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
parser.add_argument(
|
|
291
|
+
"--json",
|
|
292
|
+
action="store_true",
|
|
293
|
+
help="Output results as JSON"
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
parser.add_argument(
|
|
297
|
+
"--verbose",
|
|
298
|
+
"-v",
|
|
299
|
+
action="store_true",
|
|
300
|
+
help="Enable verbose output"
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
args = parser.parse_args()
|
|
304
|
+
|
|
305
|
+
try:
|
|
306
|
+
analyzer = DockerfileAnalyzer(
|
|
307
|
+
dockerfile_path=args.dockerfile,
|
|
308
|
+
verbose=args.verbose
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
results = analyzer.analyze()
|
|
312
|
+
|
|
313
|
+
if args.json:
|
|
314
|
+
print(json.dumps(results, indent=2))
|
|
315
|
+
else:
|
|
316
|
+
analyzer.print_results(results)
|
|
317
|
+
|
|
318
|
+
# Exit with error code if issues found
|
|
319
|
+
if results['summary']['errors'] > 0:
|
|
320
|
+
sys.exit(1)
|
|
321
|
+
|
|
322
|
+
except FileNotFoundError as e:
|
|
323
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
324
|
+
sys.exit(1)
|
|
325
|
+
except Exception as e:
|
|
326
|
+
print(f"Unexpected error: {e}", file=sys.stderr)
|
|
327
|
+
sys.exit(1)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
if __name__ == "__main__":
|
|
331
|
+
main()
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Context7 API Configuration (optional)
|
|
2
|
+
# Get your API key from https://context7.com/dashboard/api-keys
|
|
3
|
+
CONTEXT7_API_KEY=
|
|
4
|
+
|
|
5
|
+
# Gemini API Configuration (optional, for ai-multimodal integration)
|
|
6
|
+
# Get your API key from https://aistudio.google.com/app/apikey
|
|
7
|
+
GEMINI_API_KEY=
|
|
8
|
+
|
|
9
|
+
# GitHub Token (optional, for higher rate limits on repository analysis)
|
|
10
|
+
# Create at https://github.com/settings/tokens
|
|
11
|
+
GITHUB_TOKEN=
|
|
12
|
+
|
|
13
|
+
# Output settings
|
|
14
|
+
OUTPUT_FORMAT=json
|
|
15
|
+
DEBUG=false
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "docs-seeker-scripts",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Documentation discovery scripts for docs-seeker skill",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node scripts/tests/run-tests.js",
|
|
8
|
+
"test:detect": "node scripts/tests/test-detect-topic.js",
|
|
9
|
+
"test:fetch": "node scripts/tests/test-fetch-docs.js",
|
|
10
|
+
"test:analyze": "node scripts/tests/test-analyze-llms.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"documentation",
|
|
14
|
+
"llms.txt",
|
|
15
|
+
"context7",
|
|
16
|
+
"docs-discovery"
|
|
17
|
+
],
|
|
18
|
+
"author": "ClaudeKit",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {},
|
|
21
|
+
"devDependencies": {},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=14.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|