Full Code of openai/skills for AI

main dc48aff82081 cached
644 files
3.2 MB
887.9k tokens
513 symbols
1 requests
Download .txt
Showing preview only (3,539K chars total). Download the full file or copy to clipboard to get everything.
Repository: openai/skills
Branch: main
Commit: dc48aff82081
Files: 644
Total size: 3.2 MB

Directory structure:
gitextract_f89akwzt/

├── .gitignore
├── README.md
├── contributing.md
└── skills/
    ├── .curated/
    │   ├── aspnet-core/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── _sections.md
    │   │       ├── apis-minimal-and-controllers.md
    │   │       ├── data-state-and-services.md
    │   │       ├── program-and-pipeline.md
    │   │       ├── realtime-grpc-and-background-work.md
    │   │       ├── security-and-identity.md
    │   │       ├── source-map.md
    │   │       ├── stack-selection.md
    │   │       ├── testing-performance-and-operations.md
    │   │       ├── ui-blazor.md
    │   │       ├── ui-mvc.md
    │   │       ├── ui-razor-pages.md
    │   │       └── versioning-and-upgrades.md
    │   ├── chatgpt-apps/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── app-archetypes.md
    │   │   │   ├── apps-sdk-docs-workflow.md
    │   │   │   ├── interactive-state-sync-patterns.md
    │   │   │   ├── repo-contract-and-validation.md
    │   │   │   ├── search-fetch-standard.md
    │   │   │   ├── upstream-example-workflow.md
    │   │   │   └── window-openai-patterns.md
    │   │   └── scripts/
    │   │       └── scaffold_node_ext_apps.mjs
    │   ├── cloudflare-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── agents-sdk/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── ai-gateway/
    │   │       │   ├── README.md
    │   │       │   ├── configuration.md
    │   │       │   ├── dynamic-routing.md
    │   │       │   ├── features.md
    │   │       │   ├── sdk-integration.md
    │   │       │   └── troubleshooting.md
    │   │       ├── ai-search/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── analytics-engine/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── api/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── api-shield/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── argo-smart-routing/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── bindings/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── bot-management/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── browser-rendering/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── c3/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── cache-reserve/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── containers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── cron-triggers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── d1/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── ddos/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── do-storage/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   ├── patterns.md
    │   │       │   └── testing.md
    │   │       ├── durable-objects/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── email-routing/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── email-workers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── hyperdrive/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── images/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── kv/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── miniflare/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── network-interconnect/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── observability/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pages/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pages-functions/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pipelines/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pulumi/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── queues/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── r2/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── r2-data-catalog/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── r2-sql/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── realtime-sfu/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── realtimekit/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── sandbox/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── secrets-store/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── smart-placement/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── snippets/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── spectrum/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── static-assets/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── stream/
    │   │       │   ├── README.md
    │   │       │   ├── api-live.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── tail-workers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── terraform/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── tunnel/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   ├── networking.md
    │   │       │   └── patterns.md
    │   │       ├── turn/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── turnstile/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── vectorize/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── waf/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── web-analytics/
    │   │       │   ├── README.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   ├── integration.md
    │   │       │   └── patterns.md
    │   │       ├── workerd/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── frameworks.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-ai/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-for-platforms/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-playground/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-vpc/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workflows/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── wrangler/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── auth.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       └── zaraz/
    │   │           ├── IMPLEMENTATION_SUMMARY.md
    │   │           ├── README.md
    │   │           ├── api.md
    │   │           ├── configuration.md
    │   │           ├── gotchas.md
    │   │           └── patterns.md
    │   ├── develop-web-game/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   └── action_payloads.json
    │   │   └── scripts/
    │   │       └── web_game_playwright_client.js
    │   ├── doc/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── render_docx.py
    │   ├── figma/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── figma-mcp-config.md
    │   │       └── figma-tools-and-prompts.md
    │   ├── figma-implement-design/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── gh-address-comments/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── fetch_comments.py
    │   ├── gh-fix-ci/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── inspect_pr_checks.py
    │   ├── imagegen/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── cli.md
    │   │   │   ├── codex-network.md
    │   │   │   ├── image-api.md
    │   │   │   ├── prompting.md
    │   │   │   └── sample-prompts.md
    │   │   └── scripts/
    │   │       └── image_gen.py
    │   ├── jupyter-notebook/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── assets/
    │   │   │   ├── experiment-template.ipynb
    │   │   │   └── tutorial-template.ipynb
    │   │   ├── references/
    │   │   │   ├── experiment-patterns.md
    │   │   │   ├── notebook-structure.md
    │   │   │   ├── quality-checklist.md
    │   │   │   └── tutorial-patterns.md
    │   │   └── scripts/
    │   │       └── new_notebook.py
    │   ├── linear/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── netlify-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── cli-commands.md
    │   │       ├── deployment-patterns.md
    │   │       └── netlify-toml.md
    │   ├── notion-knowledge-capture/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── conversation-to-wiki.json
    │   │   │   └── decision-record.json
    │   │   ├── examples/
    │   │   │   ├── conversation-to-faq.md
    │   │   │   ├── decision-capture.md
    │   │   │   └── how-to-guide.md
    │   │   └── reference/
    │   │       ├── database-best-practices.md
    │   │       ├── decision-log-database.md
    │   │       ├── documentation-database.md
    │   │       ├── faq-database.md
    │   │       ├── how-to-guide-database.md
    │   │       ├── learning-database.md
    │   │       └── team-wiki-database.md
    │   ├── notion-meeting-intelligence/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── decision-meeting-prep.json
    │   │   │   └── status-meeting-prep.json
    │   │   ├── examples/
    │   │   │   ├── customer-meeting.md
    │   │   │   ├── executive-review.md
    │   │   │   ├── project-decision.md
    │   │   │   └── sprint-planning.md
    │   │   └── reference/
    │   │       ├── brainstorming-template.md
    │   │       ├── decision-meeting-template.md
    │   │       ├── one-on-one-template.md
    │   │       ├── retrospective-template.md
    │   │       ├── sprint-planning-template.md
    │   │       ├── status-update-template.md
    │   │       └── template-selection-guide.md
    │   ├── notion-research-documentation/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── basic-research.json
    │   │   │   └── research-to-database.json
    │   │   ├── examples/
    │   │   │   ├── competitor-analysis.md
    │   │   │   ├── market-research.md
    │   │   │   ├── technical-investigation.md
    │   │   │   └── trip-planning.md
    │   │   └── reference/
    │   │       ├── advanced-search.md
    │   │       ├── citations.md
    │   │       ├── comparison-format.md
    │   │       ├── comparison-template.md
    │   │       ├── comprehensive-report-format.md
    │   │       ├── comprehensive-report-template.md
    │   │       ├── format-selection-guide.md
    │   │       ├── quick-brief-format.md
    │   │       ├── quick-brief-template.md
    │   │       ├── research-summary-format.md
    │   │       └── research-summary-template.md
    │   ├── notion-spec-to-implementation/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── basic-spec-implementation.json
    │   │   │   └── spec-to-tasks.json
    │   │   ├── examples/
    │   │   │   ├── api-feature.md
    │   │   │   ├── database-migration.md
    │   │   │   └── ui-component.md
    │   │   └── reference/
    │   │       ├── milestone-summary-template.md
    │   │       ├── progress-tracking.md
    │   │       ├── progress-update-template.md
    │   │       ├── quick-implementation-plan.md
    │   │       ├── spec-parsing.md
    │   │       ├── standard-implementation-plan.md
    │   │       ├── task-creation-template.md
    │   │       └── task-creation.md
    │   ├── openai-docs/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── gpt-5p4-prompting-guide.md
    │   │       ├── latest-model.md
    │   │       └── upgrading-to-gpt-5p4.md
    │   ├── pdf/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── playwright/
    │   │   ├── LICENSE.txt
    │   │   ├── NOTICE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── cli.md
    │   │   │   └── workflows.md
    │   │   └── scripts/
    │   │       └── playwright_cli.sh
    │   ├── playwright-interactive/
    │   │   ├── LICENSE.txt
    │   │   ├── NOTICE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── render-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── assets/
    │   │   │   ├── docker.yaml
    │   │   │   ├── go-api.yaml
    │   │   │   ├── nextjs-postgres.yaml
    │   │   │   ├── node-express.yaml
    │   │   │   ├── python-django.yaml
    │   │   │   └── static-site.yaml
    │   │   └── references/
    │   │       ├── blueprint-spec.md
    │   │       ├── codebase-analysis.md
    │   │       ├── configuration-guide.md
    │   │       ├── deployment-details.md
    │   │       ├── direct-creation.md
    │   │       ├── error-patterns.md
    │   │       ├── post-deploy-checks.md
    │   │       ├── runtimes.md
    │   │       ├── service-types.md
    │   │       └── troubleshooting-basics.md
    │   ├── screenshot/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       ├── ensure_macos_permissions.sh
    │   │       ├── macos_display_info.swift
    │   │       ├── macos_permissions.swift
    │   │       ├── macos_window_info.swift
    │   │       ├── take_screenshot.ps1
    │   │       └── take_screenshot.py
    │   ├── security-best-practices/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── golang-general-backend-security.md
    │   │       ├── javascript-express-web-server-security.md
    │   │       ├── javascript-general-web-frontend-security.md
    │   │       ├── javascript-jquery-web-frontend-security.md
    │   │       ├── javascript-typescript-nextjs-web-server-security.md
    │   │       ├── javascript-typescript-react-web-frontend-security.md
    │   │       ├── javascript-typescript-vue-web-frontend-security.md
    │   │       ├── python-django-web-server-security.md
    │   │       ├── python-fastapi-web-server-security.md
    │   │       └── python-flask-web-server-security.md
    │   ├── security-ownership-map/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   └── neo4j-import.md
    │   │   └── scripts/
    │   │       ├── build_ownership_map.py
    │   │       ├── community_maintainers.py
    │   │       ├── query_ownership.py
    │   │       └── run_ownership_map.py
    │   ├── security-threat-model/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── prompt-template.md
    │   │       └── security-controls-and-assets.md
    │   ├── sentry/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── sentry_api.py
    │   ├── slides/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── assets/
    │   │   │   └── pptxgenjs_helpers/
    │   │   │       ├── code.js
    │   │   │       ├── image.js
    │   │   │       ├── index.js
    │   │   │       ├── latex.js
    │   │   │       ├── layout.js
    │   │   │       ├── layout_builders.js
    │   │   │       ├── svg.js
    │   │   │       ├── text.js
    │   │   │       └── util.js
    │   │   ├── references/
    │   │   │   └── pptxgenjs-helpers.md
    │   │   └── scripts/
    │   │       ├── create_montage.py
    │   │       ├── detect_font.py
    │   │       ├── ensure_raster_image.py
    │   │       ├── render_slides.py
    │   │       └── slides_test.py
    │   ├── sora/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── cinematic-shots.md
    │   │   │   ├── cli.md
    │   │   │   ├── codex-network.md
    │   │   │   ├── prompting.md
    │   │   │   ├── sample-prompts.md
    │   │   │   ├── social-ads.md
    │   │   │   ├── troubleshooting.md
    │   │   │   └── video-api.md
    │   │   └── scripts/
    │   │       └── sora.py
    │   ├── speech/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── accessibility.md
    │   │   │   ├── audio-api.md
    │   │   │   ├── cli.md
    │   │   │   ├── codex-network.md
    │   │   │   ├── ivr.md
    │   │   │   ├── narration.md
    │   │   │   ├── prompting.md
    │   │   │   ├── sample-prompts.md
    │   │   │   ├── voice-directions.md
    │   │   │   └── voiceover.md
    │   │   └── scripts/
    │   │       └── text_to_speech.py
    │   ├── spreadsheet/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       └── examples/
    │   │           └── openpyxl/
    │   │               ├── create_basic_spreadsheet.py
    │   │               ├── create_spreadsheet_with_styling.py
    │   │               ├── read_existing_spreadsheet.py
    │   │               └── styling_spreadsheet.py
    │   ├── transcribe/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   └── api.md
    │   │   └── scripts/
    │   │       └── transcribe_diarize.py
    │   ├── vercel-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── deploy.sh
    │   ├── winui-app/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── config.yaml
    │   │   └── references/
    │   │       ├── _sections.md
    │   │       ├── accessibility-input-and-localization.md
    │   │       ├── build-run-and-launch-verification.md
    │   │       ├── community-toolkit-controls-and-helpers.md
    │   │       ├── controls-layout-and-adaptive-ui.md
    │   │       ├── foundation-environment-audit-and-remediation.md
    │   │       ├── foundation-setup-and-project-selection.md
    │   │       ├── foundation-template-first-recovery.md
    │   │       ├── foundation-winui-app-structure.md
    │   │       ├── motion-animations-and-polish.md
    │   │       ├── performance-diagnostics-and-responsiveness.md
    │   │       ├── sample-source-map.md
    │   │       ├── shell-navigation-and-windowing.md
    │   │       ├── styling-theming-materials-and-icons.md
    │   │       ├── testing-debugging-and-review-checklists.md
    │   │       └── windows-app-sdk-lifecycle-notifications-and-deployment.md
    │   └── yeet/
    │       ├── LICENSE.txt
    │       ├── SKILL.md
    │       └── agents/
    │           └── openai.yaml
    └── .system/
        ├── openai-docs/
        │   ├── LICENSE.txt
        │   ├── SKILL.md
        │   ├── agents/
        │   │   └── openai.yaml
        │   └── references/
        │       ├── gpt-5p4-prompting-guide.md
        │       ├── latest-model.md
        │       └── upgrading-to-gpt-5p4.md
        ├── skill-creator/
        │   ├── LICENSE.txt
        │   ├── SKILL.md
        │   ├── agents/
        │   │   └── openai.yaml
        │   ├── references/
        │   │   └── openai_yaml.md
        │   └── scripts/
        │       ├── generate_openai_yaml.py
        │       ├── init_skill.py
        │       └── quick_validate.py
        └── skill-installer/
            ├── LICENSE.txt
            ├── SKILL.md
            ├── agents/
            │   └── openai.yaml
            └── scripts/
                ├── github_utils.py
                ├── install-skill-from-github.py
                └── list-skills.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# macOS system files
.DS_Store

# Python bytecode files
__pycache__/
*.pyc


================================================
FILE: README.md
================================================
# Agent Skills

Agent Skills are folders of instructions, scripts, and resources that AI agents can discover and use to perform at specific tasks. Write once, use everywhere.

Codex uses skills to help package capabilities that teams and individuals can use to complete specific tasks in a repeatable way. This repository catalogs skills for use and distribution with Codex.

Learn more:
- [Using skills in Codex](https://developers.openai.com/codex/skills)
- [Create custom skills in Codex](https://developers.openai.com/codex/skills/create-skill)
- [Agent Skills open standard](https://agentskills.io)

## Installing a skill

Skills in [`.system`](skills/.system/) are automatically installed in the latest version of Codex.

To install [curated](skills/.curated/) or [experimental](skills/.experimental/) skills, you can use the `$skill-installer` inside Codex.

Curated skills can be installed by name (defaults to `skills/.curated`):

```
$skill-installer gh-address-comments
```

For experimental skills, specify the skill folder. For example:

```
$skill-installer install the create-plan skill from the .experimental folder
```

Or provide the GitHub directory URL:

```
$skill-installer install https://github.com/openai/skills/tree/main/skills/.experimental/create-plan
```

After installing a skill, restart Codex to pick up new skills.

## License

The license of an individual skill can be found directly inside the skill's directory inside the `LICENSE.txt` file.


================================================
FILE: contributing.md
================================================
## Contributing

### Community values

- **Be kind and inclusive.** Treat others with respect; we follow the [Contributor Covenant](https://www.contributor-covenant.org/).
- **Assume good intent.** Written communication is hard - err on the side of generosity.
- **Teach & learn.** If you spot something confusing, open an issue or PR with improvements.

### Security & responsible AI

Have you discovered a vulnerability or have concerns about model output? Please e-mail **security@openai.com** and we will respond promptly.


================================================
FILE: skills/.curated/aspnet-core/LICENSE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: skills/.curated/aspnet-core/SKILL.md
================================================
---
name: aspnet-core
description: Build, review, refactor, or architect ASP.NET Core web applications using current official guidance for .NET web development. Use when working on Blazor Web Apps, Razor Pages, MVC, Minimal APIs, controller-based Web APIs, SignalR, gRPC, middleware, dependency injection, configuration, authentication, authorization, testing, performance, deployment, or ASP.NET Core upgrades.
---

# ASP.NET Core

## Overview

Choose the right ASP.NET Core application model, compose the host and request pipeline correctly, and implement features in the framework style Microsoft documents today.

Load the smallest set of references that fits the task. Do not load every reference by default.

## Workflow

1. Confirm the target framework, SDK, and current app model.
2. Open [references/stack-selection.md](references/stack-selection.md) first for new apps or major refactors.
3. Open [references/program-and-pipeline.md](references/program-and-pipeline.md) next for `Program.cs`, DI, configuration, middleware, routing, logging, and static assets.
4. Open exactly one primary app-model reference:
   - [references/ui-blazor.md](references/ui-blazor.md)
   - [references/ui-razor-pages.md](references/ui-razor-pages.md)
   - [references/ui-mvc.md](references/ui-mvc.md)
   - [references/apis-minimal-and-controllers.md](references/apis-minimal-and-controllers.md)
5. Add cross-cutting references only as needed:
   - [references/data-state-and-services.md](references/data-state-and-services.md)
   - [references/security-and-identity.md](references/security-and-identity.md)
   - [references/realtime-grpc-and-background-work.md](references/realtime-grpc-and-background-work.md)
   - [references/testing-performance-and-operations.md](references/testing-performance-and-operations.md)
6. Open [references/versioning-and-upgrades.md](references/versioning-and-upgrades.md) before introducing new platform APIs into an older solution or when migrating between major versions.
7. Use [references/source-map.md](references/source-map.md) when you need the Microsoft Learn section that corresponds to a task not already covered by the focused references.

## Default Operating Assumptions

- Prefer the latest stable ASP.NET Core and .NET unless the repository or user request pins an older target.
- As of March 2026, prefer .NET 10 / ASP.NET Core 10 for new production work. Treat ASP.NET Core 11 as preview unless the user explicitly asks for preview features.
- Prefer `WebApplicationBuilder` and `WebApplication`. Avoid older `Startup` and `WebHost` patterns unless the codebase already uses them or the task is migration.
- Prefer built-in DI, options/configuration, logging, ProblemDetails, OpenAPI, health checks, rate limiting, output caching, and Identity before adding third-party infrastructure.
- Keep feature slices cohesive so the page, component, endpoint, controller, validation, service, data access, and tests are easy to trace.
- Respect the existing app model. Do not rewrite Razor Pages to MVC or controllers to Minimal APIs without a clear reason.

## Reference Guide

- [references/_sections.md](references/_sections.md): Quick index and reading order.
- [references/stack-selection.md](references/stack-selection.md): Choose the right ASP.NET Core application model and template.
- [references/program-and-pipeline.md](references/program-and-pipeline.md): Structure `Program.cs`, services, middleware, routing, configuration, logging, and static assets.
- [references/ui-blazor.md](references/ui-blazor.md): Build Blazor Web Apps, choose render modes, and use components, forms, and JS interop correctly.
- [references/ui-razor-pages.md](references/ui-razor-pages.md): Build page-focused server-rendered apps with handlers, model binding, and conventions.
- [references/ui-mvc.md](references/ui-mvc.md): Build controller/view applications with clear separation of concerns.
- [references/apis-minimal-and-controllers.md](references/apis-minimal-and-controllers.md): Build HTTP APIs with Minimal APIs or controllers, including validation and response patterns.
- [references/data-state-and-services.md](references/data-state-and-services.md): Use EF Core, `DbContext`, options, `IHttpClientFactory`, session, temp data, and app state responsibly.
- [references/security-and-identity.md](references/security-and-identity.md): Apply authentication, authorization, Identity, secrets, data protection, CORS, CSRF, and HTTPS guidance.
- [references/realtime-grpc-and-background-work.md](references/realtime-grpc-and-background-work.md): Use SignalR, gRPC, and hosted services.
- [references/testing-performance-and-operations.md](references/testing-performance-and-operations.md): Add integration tests, browser tests, caching, compression, health checks, rate limits, and deployment concerns.
- [references/versioning-and-upgrades.md](references/versioning-and-upgrades.md): Handle target frameworks, breaking changes, obsolete APIs, and migrations.
- [references/source-map.md](references/source-map.md): Map the official ASP.NET Core documentation tree to the references in this skill.

## Execution Notes

- When generating new code, start from the correct `dotnet new` template and keep the generated structure recognizable.
- When editing an existing solution, follow the solution's conventions first and use these references to avoid framework misuse or outdated patterns.
- When a task mentions "latest", verify the feature on Microsoft Learn or the ASP.NET Core docs repo before relying on memory.


================================================
FILE: skills/.curated/aspnet-core/agents/openai.yaml
================================================
interface:
  display_name: "ASP.NET Core"
  short_description: "[Windows only] Build and review ASP.NET Core web apps"
  icon_large: "./assets/dotnet-logo.png"
  default_prompt: "Create a new $aspnet-core website for me."


================================================
FILE: skills/.curated/aspnet-core/references/_sections.md
================================================
# Reference Sections

Use this file as the routing table for the rest of the skill.

## Start Here

- New app or major redesign: `stack-selection.md` -> `program-and-pipeline.md` -> one primary app-model reference -> `security-and-identity.md` -> `testing-performance-and-operations.md`
- Existing app feature work: primary app-model reference -> `program-and-pipeline.md` -> any needed cross-cutting references
- API-first work: `apis-minimal-and-controllers.md` -> `security-and-identity.md` -> `data-state-and-services.md` -> `testing-performance-and-operations.md`
- Authentication, authorization, or secrets: `security-and-identity.md`
- Realtime, streaming, or background processing: `realtime-grpc-and-background-work.md`
- Upgrade or migration work: `versioning-and-upgrades.md`

## Primary References

| File | Open when |
| --- | --- |
| `stack-selection.md` | Choose Blazor, Razor Pages, MVC, Minimal APIs, controllers, SignalR, or gRPC |
| `program-and-pipeline.md` | Structure `Program.cs`, services, configuration, middleware, routing, logging, static files, and app startup |
| `ui-blazor.md` | Build or review Blazor Web Apps and component-based UI |
| `ui-razor-pages.md` | Build or review page-focused server-rendered applications |
| `ui-mvc.md` | Build or review controller/view applications |
| `apis-minimal-and-controllers.md` | Build or review HTTP APIs |

## Cross-Cutting References

| File | Open when |
| --- | --- |
| `data-state-and-services.md` | Register services, use EF Core, handle options/configuration, or manage app state |
| `security-and-identity.md` | Add Identity, cookies, bearer auth, policies, CORS, CSRF, HTTPS, or secrets handling |
| `realtime-grpc-and-background-work.md` | Add SignalR, gRPC, streaming, or hosted services |
| `testing-performance-and-operations.md` | Add tests, caching, compression, health checks, rate limits, deployment, or proxy configuration |
| `versioning-and-upgrades.md` | Migrate across ASP.NET Core versions, avoid obsolete APIs, or target preview features deliberately |
| `source-map.md` | Map a task to the official ASP.NET Core documentation tree |

## Reading Strategy

- Open one app-model reference at a time unless the codebase genuinely mixes models.
- Prefer the framework's built-in abstractions first.
- Check `versioning-and-upgrades.md` before introducing APIs that might not exist in the repository's target framework.


================================================
FILE: skills/.curated/aspnet-core/references/apis-minimal-and-controllers.md
================================================
# APIs: Minimal And Controllers

Primary docs:
- https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
- https://learn.microsoft.com/aspnet/core/web-api/
- https://learn.microsoft.com/aspnet/core/fundamentals/error-handling-api

## First Decision

Choose between:

- Minimal APIs for focused, low-ceremony HTTP endpoints
- controller-based APIs for richer MVC conventions and attribute-driven behavior

Do not mix both styles in the same feature unless that split is genuinely useful.

## Minimal API Guidance

Prefer Minimal APIs when the surface is small to medium and you want concise endpoint definitions.

Good defaults:

- organize endpoints with route groups
- keep route handlers thin
- move business logic into services
- prefer `TypedResults` over untyped results
- use endpoint filters when cross-cutting behavior belongs at the endpoint layer
- use built-in validation support on supported target frameworks

Minimal API reminders:

- handler parameters can be bound from route, query, headers, body, form, or DI
- authorization can be applied with `RequireAuthorization`
- return `IResult` or `TypedResults` when response shape matters
- use OpenAPI support for discoverable contracts

On .NET 10, Minimal APIs support built-in validation with `AddValidation()`. Use that instead of inventing parallel validation infrastructure when the target framework supports it.

## Controller API Guidance

Prefer controllers when the API needs:

- `[ApiController]` behaviors
- attribute routing and conventions
- filters
- custom formatters
- mature controller organization in an existing codebase

Controller defaults:

- derive API controllers from `ControllerBase`
- annotate with `[ApiController]`
- use attribute routing
- return ProblemDetails-compatible failures
- let automatic model validation handle invalid requests unless there is a concrete override requirement

Key `[ApiController]` behaviors:

- attribute routing is required
- invalid model state automatically becomes HTTP 400
- binding source inference applies
- error responses use ProblemDetails patterns

## Shared API Practices

- Keep request and response DTOs separate from persistence models
- Use version-stable route and payload contracts
- Use `CreatedAt...` patterns for resource creation
- Prefer explicit status codes and typed results over implicit behavior
- Apply authorization at the endpoint or controller boundary, not only inside service methods
- Use `ProblemDetails` for errors instead of ad hoc JSON shapes

## Browser-Facing Notes

- Be careful with cookie-authenticated API endpoints and CORS
- For browser-based form or file upload endpoints, account for antiforgery requirements
- In ASP.NET Core 10, known API endpoints no longer use cookie-login redirects by default; rely on API-appropriate unauthorized responses instead

## Native AOT

Use `dotnet new webapiaot` only when native AOT is an explicit deployment requirement. Treat it as a constraint that affects library choice, reflection, JSON patterns, and compatibility.


================================================
FILE: skills/.curated/aspnet-core/references/data-state-and-services.md
================================================
# Data, State, And Services

Primary docs:
- https://learn.microsoft.com/aspnet/core/data/
- https://learn.microsoft.com/aspnet/core/fundamentals/dependency-injection
- https://learn.microsoft.com/aspnet/core/fundamentals/http-requests
- https://learn.microsoft.com/aspnet/core/fundamentals/app-state

## Dependency Injection Defaults

- Register infrastructure and business services in `Program.cs`
- Inject dependencies through constructors by default
- Keep scoped services request-bound
- Avoid resolving scoped services from singletons
- Use keyed or named patterns only when there is a real need for multiple implementations

## EF Core And DbContext

Use EF Core for common relational data access patterns unless the repository already uses another data layer.

Default guidance:

- register `DbContext` with `AddDbContext`
- treat `DbContext` as scoped
- keep queries and transactions in services, not UI code
- use migrations intentionally
- keep entities out of public API contracts and UI view models

Use `IDbContextFactory<TContext>` when the execution model is not request-scoped, such as:

- Blazor components with longer-lived scopes
- background services
- explicit factory-driven data work

## Options And Configuration

- Bind structured configuration into options classes
- validate options early when bad configuration should fail fast
- keep configuration access close to the service that owns it
- avoid scattering raw configuration keys across the codebase

## Outbound HTTP

Use `IHttpClientFactory` for outbound HTTP calls.

Prefer:

- named clients for distinct external systems
- typed clients for richer integrations
- delegating handlers for retries, headers, or telemetry concerns

Avoid manual `new HttpClient()` patterns scattered through request handlers.

## App State

Use the smallest state mechanism that fits:

- query string or route values for transparent request state
- form posts for user input
- TempData for short-lived redirect-friendly messages
- session only when necessary and with an understanding of its server-side and scaling implications

Do not treat session as the primary application data store.

## Caching And State Boundaries

- Keep cached data derivable from a durable source
- Separate cache shape from persistence shape when it improves safety or performance
- Revisit session, in-memory cache, and singleton state when the app scales to multiple instances


================================================
FILE: skills/.curated/aspnet-core/references/program-and-pipeline.md
================================================
# Program And Pipeline

Primary docs:
- https://learn.microsoft.com/aspnet/core/fundamentals/
- https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis/webapplication
- https://learn.microsoft.com/aspnet/core/fundamentals/middleware/
- https://learn.microsoft.com/aspnet/core/fundamentals/configuration/

## Startup Shape

Prefer the modern hosting model:

1. Create `var builder = WebApplication.CreateBuilder(args);`
2. Register services on `builder.Services`
3. Build `var app = builder.Build();`
4. Configure middleware in the correct order
5. Map endpoints
6. Call `app.Run();`

Use older `Startup` patterns only when the repository already uses them or the task is migration.

## Service Registration

- Register framework services explicitly: Razor Pages, controllers, Razor components, authentication, authorization, health checks, rate limiting, response compression, output caching, EF Core, and `IHttpClientFactory`
- Keep business logic in services instead of controllers, page models, or route handlers
- Use constructor injection as the default
- Use options classes for structured configuration
- Choose lifetimes intentionally:
  - singleton: stateless or shared infrastructure
  - scoped: request-bound work such as `DbContext`
  - transient: lightweight stateless services

## Configuration Defaults

`WebApplication.CreateBuilder` already loads configuration from common providers such as:

- `appsettings.json`
- environment-specific `appsettings.{Environment}.json`
- environment variables
- command-line arguments

For secrets:

- use Secret Manager in development
- use a secure external store in production
- do not commit secrets to source control

## Middleware Order

Middleware order is a frequent source of broken behavior. Favor this shape and adjust only with a concrete reason:

1. Forwarded headers if behind a proxy or load balancer
2. Exception handling and HSTS for non-development environments
3. HTTPS redirection
4. Static files
5. Routing when explicit routing middleware is needed
6. CORS when endpoints require it
7. Authentication
8. Authorization
9. Endpoint-specific middleware such as rate limiting or session as required
10. Endpoint mapping with `MapRazorPages`, `MapControllers`, `MapGet`, `MapHub`, or `MapGrpcService`

Important ordering rules:

- Call `UseAuthentication()` before `UseAuthorization()`
- Keep proxy/header processing before auth, redirects, and link generation
- Do not insert custom middleware randomly between auth and authorization without a reason
- In Minimal API apps, explicit `UseRouting()` is usually unnecessary unless you need to control order

## Routing And Endpoints

- Prefer endpoint routing everywhere
- Use route groups for larger Minimal API surfaces
- Keep MVC and API routes explicit and predictable
- Use areas only when the application is large enough to benefit from bounded sections
- Keep endpoint names stable when generating links or integrating with clients

## Error Handling

- Use centralized exception handling instead of scattered `try/catch` blocks for ordinary request failures
- Prefer ProblemDetails-style responses for APIs
- Keep the developer exception page limited to development
- Separate user-facing failures from internal exception details

## Logging And Diagnostics

- Use `ILogger<T>` from DI
- Log structured values, not concatenated strings
- Put correlation and request diagnostics in middleware or infrastructure, not business logic
- Enable HTTP logging only when the scenario warrants it and avoid leaking sensitive data

## Static Assets And Web Root

- Keep public assets in `wwwroot`
- Treat the web root as publicly readable content
- Prevent publishing local-only static content through project file rules when needed
- Use Razor Class Libraries for reusable UI assets across apps

## Architectural Defaults

- Keep `Program.cs` readable; extract feature registration to extension methods when it starts accumulating unrelated concerns
- Prefer vertical slices or feature folders over giant "Controllers", "Services", and "Repositories" buckets with weak boundaries
- Keep framework configuration close to the host and business logic out of it


================================================
FILE: skills/.curated/aspnet-core/references/realtime-grpc-and-background-work.md
================================================
# Realtime, gRPC, And Background Work

Primary docs:
- https://learn.microsoft.com/aspnet/core/signalr/introduction
- https://learn.microsoft.com/aspnet/core/grpc/
- https://learn.microsoft.com/aspnet/core/fundamentals/host/hosted-services

## SignalR

Use SignalR when the server must push updates to connected clients in near real time.

Good fits:

- chat
- dashboards
- notifications
- collaborative editing
- live status streams

Guidance:

- model the hub as a communication boundary, not the home of business logic
- use groups and user targeting deliberately
- authenticate connections when data is user-specific
- plan for scale-out if the app may run on multiple instances

Remember that Blazor interactive server rendering already relies on a real-time connection. Do not add a second realtime channel unless the feature truly needs one.

## gRPC

Use gRPC for efficient service-to-service communication, strongly typed contracts, and streaming over HTTP/2.

Prefer gRPC when:

- both ends are under your control
- performance and contract fidelity matter
- streaming is a first-class requirement

Guidance:

- keep `.proto` contracts versioned and stable
- generate client and server types from contracts
- keep auth, logging, and DI integrated with the host
- account for browser interoperability differences before choosing gRPC for public browser clients

## Background Work

Use `IHostedService` or `BackgroundService` for in-process background tasks tied to the application host.

Defaults:

- keep background services small and observable
- create scopes for scoped dependencies
- do not capture scoped services directly in singleton hosted services
- respect cancellation tokens
- avoid long blocking startup paths

If the work is durable, high-volume, or business-critical, consider whether it belongs in an out-of-process queue or worker instead of only inside the web host.


================================================
FILE: skills/.curated/aspnet-core/references/security-and-identity.md
================================================
# Security And Identity

Primary docs:
- https://learn.microsoft.com/aspnet/core/security/
- https://learn.microsoft.com/aspnet/core/security/authentication/identity
- https://learn.microsoft.com/aspnet/core/security/authorization/introduction

## Security Defaults

- Use the most secure authentication flow available
- Keep secrets out of source code and plain configuration files
- Use Secret Manager in development
- Use a secure production secret store
- Enforce HTTPS
- Apply least privilege to users, services, and data access

## Authentication And Authorization

Authentication answers who the user or caller is. Authorization answers what they can do.

Default pipeline order:

1. `UseAuthentication()`
2. `UseAuthorization()`

Apply authorization at boundaries:

- `[Authorize]` on controllers, actions, page models, or hubs
- `RequireAuthorization()` on endpoints and route groups
- policies for reusable rules
- roles only when role-based checks are actually the right abstraction

Use `AllowAnonymous` sparingly and intentionally.

## Identity

Use ASP.NET Core Identity when the app needs first-party user accounts, login flows, password management, email confirmation, MFA, or related account management.

Useful starting points:

- `dotnet new webapp -au Individual`
- `dotnet new mvc -au Individual`

Identity guidance:

- scaffold only the pages you truly need to customize
- keep Identity UI updates maintainable; full scaffolding increases merge and upgrade cost
- use policies and claims for authorization rather than encoding all decisions in page logic
- persist data-protection keys appropriately in multi-instance deployments

On ASP.NET Core 10, Identity metrics are available for observing auth-related behavior. Use them when the app has meaningful authentication traffic or security monitoring requirements.

## CSRF, CORS, And Browser Security

- Use antiforgery protection for cookie-based interactive apps and form posts
- Do not confuse CORS with authentication or authorization
- Avoid permissive `AllowAnyOrigin` plus credentials combinations
- Treat browser-side state as untrusted

## HTTPS, HSTS, And Forwarded Headers

- redirect HTTP to HTTPS
- enable HSTS outside development when appropriate
- configure forwarded headers correctly when behind proxies or load balancers
- do not generate links or evaluate scheme-sensitive behavior before proxy headers are processed

## Data Protection And Secrets

- persist data-protection keys outside ephemeral local storage when the app runs on multiple instances
- do not use environment variables as the preferred long-term home for production secrets when a stronger secret store is available
- never check production credentials into source control

## Blazor Note

For Blazor apps, read the general ASP.NET Core security guidance first and then the Blazor-specific security docs. Some Blazor security guidance adds to or supersedes the general guidance.


================================================
FILE: skills/.curated/aspnet-core/references/source-map.md
================================================
# ASP.NET Core Source Map

This skill is synthesized from the official ASP.NET Core documentation tree and overview pages. Use this file to map a task to the corresponding Microsoft Learn area before opening deeper docs.

Core sources:

- https://learn.microsoft.com/aspnet/core/
- https://raw.githubusercontent.com/dotnet/AspNetCore.Docs/main/aspnetcore/toc.yml
- https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore

## Documentation Tree Mapping

| ASP.NET Core docs area | Use this skill reference first |
| --- | --- |
| Overview, Get started, What's new | `stack-selection.md`, `versioning-and-upgrades.md` |
| Fundamentals | `program-and-pipeline.md` |
| Web apps | `ui-blazor.md`, `ui-razor-pages.md`, `ui-mvc.md` |
| APIs | `apis-minimal-and-controllers.md` |
| Real-time apps | `realtime-grpc-and-background-work.md` |
| Remote Procedure Call apps | `realtime-grpc-and-background-work.md` |
| Servers, Host and deploy | `testing-performance-and-operations.md` |
| Test, Debug, Troubleshoot | `testing-performance-and-operations.md` |
| Data access | `data-state-and-services.md` |
| Security and Identity | `security-and-identity.md` |
| Performance | `testing-performance-and-operations.md` |
| Migration and updates | `versioning-and-upgrades.md` |

## Areas To Consult Directly On Microsoft Learn

The following topics are part of the ASP.NET Core documentation tree but are not expanded into their own dedicated reference file here:

- globalization and localization
- advanced hosting and YARP details
- debugger and diagnostics tooling specifics
- narrow API-reference pages for individual types

When a task is dominated by one of those areas, go straight to the matching Microsoft Learn section after checking the reference files in this skill.

## Practical Deep-Dive Rule

- Start with the focused reference in this skill
- If the task depends on a narrow platform detail, open the matching Learn article
- If the task depends on version-specific behavior, confirm the correct moniker or breaking-changes page


================================================
FILE: skills/.curated/aspnet-core/references/stack-selection.md
================================================
# Stack Selection

Primary docs:
- https://learn.microsoft.com/aspnet/core/
- https://learn.microsoft.com/aspnet/core/blazor/
- https://learn.microsoft.com/aspnet/core/razor-pages/
- https://learn.microsoft.com/aspnet/core/mvc/overview
- https://learn.microsoft.com/aspnet/core/web-api/
- https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis

## Default Version Choice

- Prefer the latest stable .NET and ASP.NET Core for new production work.
- As of March 2026, that means `net10.0` unless the repository or user request says otherwise.
- Treat ASP.NET Core 11 as preview. Do not adopt preview APIs by default.
- If the repository already targets `net8.0`, `net9.0`, or another framework, stay within that target unless the task is explicitly an upgrade.

## Template Short Names

The current .NET 10 SDK templates include:

- `dotnet new blazor`
- `dotnet new webapp`
- `dotnet new mvc`
- `dotnet new webapi`
- `dotnet new webapiaot`
- `dotnet new grpc`
- `dotnet new web`
- `dotnet new razorclasslib`

Verify template names with `dotnet new list` if the environment differs.

## Application Model Matrix

| Model | Prefer when | Watch out for | Typical starting point |
| --- | --- | --- | --- |
| Blazor Web App | Build full-stack .NET UI with SSR plus optional interactivity | Interactive server needs a live connection; WebAssembly increases payload size | `dotnet new blazor` |
| Razor Pages | Build page-focused CRUD, forms, dashboards, and line-of-business apps | Authorization cannot be applied per page handler; use MVC if handler-level control matters | `dotnet new webapp` |
| MVC | Build large server-rendered apps with clear controller/view separation, filters, and action-based patterns | More ceremony than Razor Pages for simple page flows | `dotnet new mvc` |
| Minimal APIs | Build focused HTTP APIs, internal services, lightweight backends, and small surface areas | Route handlers can become hard to manage if business logic or metadata grows without structure | `dotnet new webapi` or `dotnet new web` |
| Controller-based Web API | Build APIs that benefit from `[ApiController]`, content negotiation, filters, formatters, and mature controller conventions | More ceremony than Minimal APIs for small endpoints | `dotnet new webapi` |
| SignalR | Add server push, live updates, chat, collaborative UI, or notifications | Requires connection lifecycle management and scale-out planning | Add to an existing ASP.NET Core app |
| gRPC | Build service-to-service or streaming RPC over HTTP/2 | Browser support is different from ordinary JSON APIs; use gRPC-Web only when needed | `dotnet new grpc` |

## Fast Heuristics

- Choose Blazor Web App when the UI itself should be a .NET component model.
- Choose Razor Pages when the app is mostly page and form oriented.
- Choose MVC when actions, views, filters, and controller conventions are the center of the design.
- Choose Minimal APIs first for small to medium HTTP services.
- Switch to controllers when the API needs richer attribute-driven behavior, custom formatters, or strong alignment with existing MVC/Web API conventions.
- Keep the current app model in an existing codebase unless the mismatch is causing real complexity.

## Mixed-Model Guidance

ASP.NET Core can mix models in one host. Common combinations:

- Razor Pages or MVC for server-rendered UI plus Minimal APIs for AJAX or mobile endpoints
- Blazor Web App plus Minimal APIs for external integration endpoints
- MVC or Razor Pages plus SignalR for live updates
- Web API plus gRPC for internal service-to-service calls

Mix models only when it simplifies the public surface. Do not add a second app model just because ASP.NET Core allows it.


================================================
FILE: skills/.curated/aspnet-core/references/testing-performance-and-operations.md
================================================
# Testing, Performance, And Operations

Primary docs:
- https://learn.microsoft.com/aspnet/core/test/integration-tests
- https://learn.microsoft.com/aspnet/core/host-and-deploy/
- https://learn.microsoft.com/aspnet/core/host-and-deploy/health-checks
- https://learn.microsoft.com/aspnet/core/performance/

## Testing Strategy

Use layered testing instead of relying on one style:

- unit tests for pure services and business logic
- integration tests for request pipeline, DI, database, auth, and framework wiring
- browser tests for end-to-end user flows

## Integration Tests

Use `Microsoft.AspNetCore.Mvc.Testing` and `WebApplicationFactory<Program>` for integration tests.

Guidance from the official docs:

- use a test host and `HttpClient`
- replace services with test doubles when needed
- control redirects when asserting auth behavior
- handle antiforgery correctly for form posts
- prefer SQLite in-memory over the EF Core in-memory provider for more realistic database tests

For SPA or browser-driven scenarios, Microsoft recommends browser automation such as Playwright for .NET.

## Performance Defaults

Reach for built-in features before custom optimization layers:

- output caching
- response caching where appropriate
- response compression
- HTTP request timeouts
- rate limiting
- static file handling

General performance guidance:

- measure first
- keep database and network round trips visible
- reduce payload size
- use streaming or pagination when data is large
- keep synchronous blocking out of hot paths

## Health Checks And Observability

Add health checks for dependencies that matter operationally.

Use separate checks or tags when you need:

- liveness
- readiness
- dependency-specific health surfaces

Also ensure:

- structured logs
- request tracing where applicable
- metrics for critical paths such as auth, API latency, and background work

## Hosting And Deployment

Typical deployment flow:

1. `dotnet publish`
2. deploy the publish output
3. run behind a process manager
4. place a reverse proxy in front when the environment requires it

Know the deployment environment:

- IIS or Windows Service on Windows
- Kestrel plus Nginx or another reverse proxy on Linux
- container hosting when the platform expects it

Behind proxies or load balancers:

- configure forwarded headers
- validate scheme, host, and remote IP behavior
- test auth redirects and callback URLs in the deployed topology

## Operational Safeguards

- add health checks for databases and critical external services
- fail fast on invalid configuration where possible
- keep secrets out of publish artifacts
- verify data-protection key persistence in multi-instance deployments


================================================
FILE: skills/.curated/aspnet-core/references/ui-blazor.md
================================================
# Blazor

Primary docs:
- https://learn.microsoft.com/aspnet/core/blazor/
- https://learn.microsoft.com/aspnet/core/blazor/fundamentals/
- https://learn.microsoft.com/aspnet/core/blazor/security/

## Choose Blazor Deliberately

Prefer Blazor when the UI itself should be built as reusable .NET components and the team wants a full-stack .NET model.

Current guidance centers on the Blazor Web App model, which can combine:

- static SSR for fast first render
- interactive server rendering
- interactive WebAssembly rendering
- per-component render mode choices

Use standalone Blazor WebAssembly only when the app is intentionally client-heavy or must run as static files without a server-rendered host.

## Render Mode Heuristics

- Start with static SSR when the page is mostly read-only and fast first paint matters
- Use interactive server rendering when you want rich interactivity without shipping the full .NET runtime to the browser
- Use interactive WebAssembly when offline capability, client-side execution, or browser-local compute is the point
- Mix render modes only when the split is clear and justified

## Component Patterns

- Keep components focused and composable
- Move data access and business rules into injected services
- Pass data through parameters, not hidden global state
- Use forms and validation with Blazor's built-in editing and validation components
- Prefer shared Razor Class Libraries for reusable component sets

## Data And Interactivity

- Use DI in components with restraint; avoid turning components into service locators
- Treat JS interop as an edge mechanism for browser APIs or third-party libraries, not the primary application model
- Keep long-running work off the UI event path
- Be deliberate about prerendering, streaming rendering, and enhanced navigation when they improve perceived performance

## Security Notes

- Follow the general ASP.NET Core security guidance first, then load the Blazor-specific docs for details that supersede it
- Remember that client-side code and browser state are not trusted
- Keep secrets and privileged operations on the server
- Use authorization-aware UI only as a convenience layer; enforce rules on the server as well

## When Not To Use Blazor

- Do not force Blazor onto a mostly conventional server-rendered app that already fits Razor Pages or MVC well
- Do not choose WebAssembly by default for small interaction needs that SSR or interactive server rendering handles more simply


================================================
FILE: skills/.curated/aspnet-core/references/ui-mvc.md
================================================
# MVC

Primary docs:
- https://learn.microsoft.com/aspnet/core/mvc/overview
- https://learn.microsoft.com/aspnet/core/mvc/controllers/
- https://learn.microsoft.com/aspnet/core/mvc/views/

## Choose MVC When Actions And Views Matter

Prefer MVC when the application benefits from explicit controllers, action-based routing, filters, view models, and a strong separation between orchestration and presentation.

This is often the right fit for:

- large server-rendered sites
- applications with many cross-cutting filters or action conventions
- applications that mix views and APIs in the same controller layer
- teams already organized around controllers and views

## Core Shape

Enable MVC with views using:

- `builder.Services.AddControllersWithViews();`
- `app.MapControllerRoute(...)`

Keep views focused on presentation. Keep controllers focused on HTTP orchestration. Put business rules in services.

## Controller Guidance

- Derive from `Controller` when the controller returns views
- Keep actions small and explicit
- Use model binding and validation instead of manual request parsing
- Return view models, not EF entities, to views
- Use POST-Redirect-GET for form submissions

## View Guidance

- Use layouts, partial views, and Tag Helpers to keep markup consistent
- Keep complex display logic out of Razor markup when it becomes hard to follow
- Use strongly typed view models
- Avoid coupling views directly to persistence models

## Structure And Scale

- Use areas for large bounded sections such as Admin or BackOffice
- Keep route conventions explicit
- Apply filters when behavior truly belongs at the MVC layer
- Avoid giant god controllers; split by cohesive feature or resource

## Choosing MVC Over Razor Pages

Prefer MVC over Razor Pages when:

- multiple related actions share controller-level behavior
- handler-level authorization or action filters matter
- URL and action design are more natural than page-file routing


================================================
FILE: skills/.curated/aspnet-core/references/ui-razor-pages.md
================================================
# Razor Pages

Primary docs:
- https://learn.microsoft.com/aspnet/core/razor-pages/
- https://learn.microsoft.com/aspnet/core/tutorials/razor-pages/

## Choose Razor Pages For Page-Centered Apps

Prefer Razor Pages when requests naturally map to pages, forms, and page-level handlers. This is a strong default for internal tools, CRUD apps, account flows, and admin surfaces.

## Core Shape

Enable Razor Pages with:

- `builder.Services.AddRazorPages();`
- `app.MapRazorPages();`

Use the `@page` directive to turn a `.cshtml` file into an endpoint. Keep request logic in the paired `PageModel` class when the page is more than trivial.

## Routing Model

- File system location defines the route by default
- `Pages/Index.cshtml` maps to `/`
- `Pages/Store/Index.cshtml` maps to `/Store`
- Keep folder structure meaningful because it becomes the URL structure

## PageModel Guidance

- Use `OnGet`, `OnPost`, and named handlers for request processing
- Use bindable properties and model validation for forms
- Keep page models thin; move business logic into injected services
- Use Tag Helpers and model binding instead of manual request parsing

## Good Fits

- form-heavy workflows
- dashboards and back-office applications
- simple content with server-side validation
- applications where a page is the primary navigation unit

## Key Limitation

Do not rely on per-handler authorization with Razor Pages. Microsoft explicitly recommends using MVC controllers when different handlers on the same logical surface need different authorization behavior.

Preferred responses to that limitation:

- split the handlers into separate pages
- move the surface to MVC if action-level authorization is a better fit

## Organizational Guidance

- Group related pages into folders
- Use partial views for repeated fragments
- Use areas only when the application has clear bounded sections
- Keep shared layout and page conventions centralized


================================================
FILE: skills/.curated/aspnet-core/references/versioning-and-upgrades.md
================================================
# Versioning And Upgrades

Primary docs:
- https://learn.microsoft.com/aspnet/core/release-notes/
- https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-10.0
- https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-9.0
- https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/breaking-changes

## Versioning Default

- For new production apps in March 2026, prefer `net10.0`
- For existing apps, match the repository's target framework unless the task is explicitly an upgrade
- Before using a new API, confirm it exists in the target framework

## Upgrade Workflow

1. Identify the current target framework and SDK
2. Read the "What's new" and breaking-changes pages for each version hop
3. Compile and resolve obsoletions intentionally
4. Re-run integration tests and auth flows
5. Re-test deployment-specific behavior such as proxies, cookies, and static assets

## High-Value Breaking-Change Checks

When moving to ASP.NET Core 10, watch for:

- cookie login redirects disabled for known API endpoints
- `WithOpenApi` deprecation
- `WebHostBuilder`, `IWebHost`, and `WebHost` obsolescence
- Razor runtime compilation obsolescence

When moving to ASP.NET Core 9, watch for:

- `ValidateOnBuild` and `ValidateScopes` enabled in development when using `HostBuilder`
- middleware constructor expectations and DI validation changes

When moving to ASP.NET Core 8, watch for:

- Minimal API `IFormFile` antiforgery requirements
- `AddRateLimiter()` and `AddHttpLogging()` requirements when corresponding middleware is used

## Migration Principles

- Prefer migration to the modern hosting model when touching startup extensively
- Remove compatibility shims only after tests confirm behavior
- Avoid mixing new framework idioms with old startup architecture in a half-migrated state
- Keep one authoritative target framework in project files unless multi-targeting is deliberate

## Preview Feature Rule

Do not introduce preview-only APIs or docs guidance unless the user explicitly asks for preview adoption or the repository is already on preview SDKs.


================================================
FILE: skills/.curated/chatgpt-apps/LICENSE.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

   "License" shall mean the terms and conditions for use, reproduction,
   and distribution as defined by Sections 1 through 9 of this document.

   "Licensor" shall mean the copyright owner or entity authorized by
   the copyright owner that is granting the License.

   "Legal Entity" shall mean the union of the acting entity and all
   other entities that control, are controlled by, or are under common
   control with that entity. For the purposes of this definition,
   "control" means (i) the power, direct or indirect, to cause the
   direction or management of such entity, whether by contract or
   otherwise, or (ii) ownership of fifty percent (50%) or more of the
   outstanding shares, or (iii) beneficial ownership of such entity.

   "You" (or "Your") shall mean an individual or Legal Entity
   exercising permissions granted by this License.

   "Source" form shall mean the preferred form for making modifications,
   including but not limited to software source code, documentation
   source, and configuration files.

   "Object" form shall mean any form resulting from mechanical
   transformation or translation of a Source form, including but
   not limited to compiled object code, generated documentation,
   and conversions to other media types.

   "Work" shall mean the work of authorship, whether in Source or
   Object form, made available under the License, as indicated by a
   copyright notice that is included in or attached to the work
   (an example is provided in the Appendix below).

   "Derivative Works" shall mean any work, whether in Source or Object
   form, that is based on (or derived from) the Work and for which the
   editorial revisions, annotations, elaborations, or other modifications
   represent, as a whole, an original work of authorship. For the purposes
   of this License, Derivative Works shall not include works that remain
   separable from, or merely link (or bind by name) to the interfaces of,
   the Work and Derivative Works thereof.

   "Contribution" shall mean any work of authorship, including
   the original version of the Work and any modifications or additions
   to that Work or Derivative Works thereof, that is intentionally
   submitted to Licensor for inclusion in the Work by the copyright owner
   or by an individual or Legal Entity authorized to submit on behalf of
   the copyright owner. For the purposes of this definition, "submitted"
   means any form of electronic, verbal, or written communication sent
   to the Licensor or its representatives, including but not limited to
   communication on electronic mailing lists, source code control systems,
   and issue tracking systems that are managed by, or on behalf of, the
   Licensor for the purpose of discussing and improving the Work, but
   excluding communication that is conspicuously marked or otherwise
   designated in writing by the copyright owner as "Not a Contribution."

   "Contributor" shall mean Licensor and any individual or Legal Entity
   on behalf of whom a Contribution has been received by Licensor and
   subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   copyright license to reproduce, prepare Derivative Works of,
   publicly display, publicly perform, sublicense, and distribute the
   Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   (except as stated in this section) patent license to make, have made,
   use, offer to sell, sell, import, and otherwise transfer the Work,
   where such license applies only to those patent claims licensable
   by such Contributor that are necessarily infringed by their
   Contribution(s) alone or by combination of their Contribution(s)
   with the Work to which such Contribution(s) was submitted. If You
   institute patent litigation against any entity (including a
   cross-claim or counterclaim in a lawsuit) alleging that the Work
   or a Contribution incorporated within the Work constitutes direct
   or contributory patent infringement, then any patent licenses
   granted to You under this License for that Work shall terminate
   as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
   Work or Derivative Works thereof in any medium, with or without
   modifications, and in Source or Object form, provided that You
   meet the following conditions:

   (a) You must give any other recipients of the Work or
       Derivative Works a copy of this License; and

   (b) You must cause any modified files to carry prominent notices
       stating that You changed the files; and

   (c) You must retain, in the Source form of any Derivative Works
       that You distribute, all copyright, patent, trademark, and
       attribution notices from the Source form of the Work,
       excluding those notices that do not pertain to any part of
       the Derivative Works; and

   (d) If the Work includes a "NOTICE" text file as part of its
       distribution, then any Derivative Works that You distribute must
       include a readable copy of the attribution notices contained
       within such NOTICE file, excluding those notices that do not
       pertain to any part of the Derivative Works, in at least one
       of the following places: within a NOTICE text file distributed
       as part of the Derivative Works; within the Source form or
       documentation, if provided along with the Derivative Works; or,
       within a display generated by the Derivative Works, if and
       wherever such third-party notices normally appear. The contents
       of the NOTICE file are for informational purposes only and
       do not modify the License. You may add Your own attribution
       notices within Derivative Works that You distribute, alongside
       or as an addendum to the NOTICE text from the Work, provided
       that such additional attribution notices cannot be construed
       as modifying the License.

   You may add Your own copyright statement to Your modifications and
   may provide additional or different license terms and conditions
   for use, reproduction, or distribution of Your modifications, or
   for any such Derivative Works as a whole, provided Your use,
   reproduction, and distribution of the Work otherwise complies with
   the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
   names, trademarks, service marks, or product names of the Licensor,
   except as required for reasonable and customary use in describing the
   origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
   agreed to in writing, Licensor provides the Work (and each
   Contributor provides its Contributions) on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied, including, without limitation, any warranties or conditions
   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
   PARTICULAR PURPOSE. You are solely responsible for determining the
   appropriateness of using or redistributing the Work and assume any
   risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
   whether in tort (including negligence), contract, or otherwise,
   unless required by applicable law (such as deliberate and grossly
   negligent acts) or agreed to in writing, shall any Contributor be
   liable to You for damages, including any direct, indirect, special,
   incidental, or consequential damages of any character arising as a
   result of this License or out of the use or inability to use the
   Work (including but not limited to damages for loss of goodwill,
   work stoppage, computer failure or malfunction, or any and all
   other commercial damages or losses), even if such Contributor
   has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
   the Work or Derivative Works thereof, You may choose to offer,
   and charge a fee for, acceptance of support, warranty, indemnity,
   or other liability obligations and/or rights consistent with this
   License. However, in accepting such obligations, You may act only
   on Your own behalf and on Your sole responsibility, not on behalf of
   any other Contributor, and only if You agree to indemnify,
   defend, and hold each Contributor harmless for any liability
   incurred by, or claims asserted against, such Contributor by reason
   of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

   To apply the Apache License to your work, attach the following
   boilerplate notice, with the fields enclosed by brackets "[]"
   replaced with your own identifying information. (Don't include
   the brackets!) The text should be enclosed in the appropriate
   comment syntax for the file format. We also recommend that a
   file or class name and description of purpose be included on the
   same "printed page" as the copyright notice for easier
   identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


================================================
FILE: skills/.curated/chatgpt-apps/SKILL.md
================================================
---
name: chatgpt-apps
description: Build, scaffold, refactor, and troubleshoot ChatGPT Apps SDK applications that combine an MCP server and widget UI. Use when Codex needs to design tools, register UI resources, wire the MCP Apps bridge or ChatGPT compatibility APIs, apply Apps SDK metadata or CSP or domain settings, or produce a docs-aligned project scaffold. Prefer a docs-first workflow by invoking the openai-docs skill or OpenAI developer docs MCP tools before generating code.
---

# ChatGPT Apps

## Overview

Scaffold ChatGPT Apps SDK implementations with a docs-first, example-first workflow, then generate code that follows current Apps SDK and MCP Apps bridge patterns.

Use this skill to produce:

- A primary app-archetype classification and repo-shape decision
- A tool plan (names, schemas, annotations, outputs)
- An upstream starting-point recommendation (official example, ext-apps example, or local fallback scaffold)
- An MCP server scaffold (resource registration, tool handlers, metadata)
- A widget scaffold (MCP Apps bridge first, `window.openai` compatibility/extensions second)
- A reusable Node + `@modelcontextprotocol/ext-apps` starter scaffold for low-dependency fallbacks
- A validation report against the minimum working repo contract
- Local dev and connector setup steps
- A short stakeholder summary of what the app does (when requested)

## Mandatory Docs-First Workflow

Use `$openai-docs` first whenever building or changing a ChatGPT Apps SDK app.

1. Invoke `$openai-docs` (preferred) or call the OpenAI docs MCP server directly.
2. Fetch current Apps SDK docs before writing code, especially (baseline pages):
   - `apps-sdk/build/mcp-server`
   - `apps-sdk/build/chatgpt-ui`
   - `apps-sdk/build/examples`
   - `apps-sdk/plan/tools`
   - `apps-sdk/reference`
3. Fetch `apps-sdk/quickstart` when scaffolding a new app or generating a first-pass implementation, and check the official examples repo/page before inventing a scaffold from scratch.
4. Fetch deployment/submission docs when the task includes local ChatGPT testing, hosting, or public launch:
   - `apps-sdk/deploy`
   - `apps-sdk/deploy/submission`
   - `apps-sdk/app-submission-guidelines`
5. Cite the docs URLs you used when explaining design choices or generated scaffolds.
6. Prefer current docs guidance over older repo patterns when they differ, and call out compatibility aliases explicitly.
7. If doc search times out or returns poor matches, fetch the canonical Apps SDK pages directly by URL and continue; do not let search failure block scaffolding.

If `$openai-docs` is unavailable, use:

- `mcp__openaiDeveloperDocs__search_openai_docs`
- `mcp__openaiDeveloperDocs__fetch_openai_doc`

Read `references/apps-sdk-docs-workflow.md` for suggested doc queries and a compact checklist.
Read `references/app-archetypes.md` to classify the request into a small number of supported app shapes before choosing examples or scaffolds.
Read `references/repo-contract-and-validation.md` when generating or reviewing a repo so the output stays inside a stable “working app” contract.
Read `references/search-fetch-standard.md` when the app is connector-like, data-only, sync-oriented, or meant to work well with company knowledge or deep research.
Read `references/upstream-example-workflow.md` when starting a greenfield app or when deciding whether to adapt an upstream example or use the local fallback scaffold.
Read `references/window-openai-patterns.md` when the task needs ChatGPT-specific widget behavior or when translating repo examples that use wrapper-specific `app.*` helpers.

## Prompt Guidance

Use prompts that explicitly pair this skill with `$openai-docs` so the resulting scaffold is grounded in current docs.

Preferred prompt patterns:

- `Use $chatgpt-apps with $openai-docs to scaffold a ChatGPT app for <use case> with a <TS/Python> MCP server and <React/vanilla> widget.`
- `Use $chatgpt-apps with $openai-docs to adapt the closest official Apps SDK example into a ChatGPT app for <use case>.`
- `Use $chatgpt-apps and $openai-docs to refactor this Apps SDK demo into a production-ready structure with tool annotations, CSP, and URI versioning.`
- `Use $chatgpt-apps with $openai-docs to plan tools first, then generate the MCP server and widget code.`

When responding, ask for or infer these inputs before coding:

- Use case and primary user flows
- Read-only vs mutating tools
- Demo vs production target
- Private/internal use vs public directory submission
- Backend language and UI stack
- Auth requirements
- External API domains for CSP allowlists
- Hosting target and local dev approach
- Org ownership/verification readiness (for submission tasks)

## Classify The App Before Choosing Code

Before choosing examples, repo shape, or scaffolds, classify the request into one primary archetype and state it.

- `tool-only`
- `vanilla-widget`
- `react-widget`
- `interactive-decoupled`
- `submission-ready`

Infer the archetype unless a missing detail is truly blocking. Use the archetype to choose:

- whether a UI is needed at all
- whether to preserve a split `server/` + `web/` layout
- whether to prefer official OpenAI examples, ext-apps examples, or the local fallback scaffold
- which validation checks matter most
- whether `search` and `fetch` should be the default read-only tool surface

Read `references/app-archetypes.md` for the decision rubric.

## Default Starting-Point Order

For greenfield apps, prefer these starting points in order:

1. **Official OpenAI examples** when a close example already matches the requested stack or interaction pattern.
2. **Version-matched `@modelcontextprotocol/ext-apps` examples** when the user needs a lower-level or more portable MCP Apps baseline.
3. **`scripts/scaffold_node_ext_apps.mjs`** only when no close example fits, the user wants a tiny Node + vanilla starter, or network access/example retrieval is undesirable.

Do not generate a large custom scaffold from scratch if a close upstream example already exists.
Copy the smallest matching example, remove unrelated demo code, then patch it to the current docs and the user request.

## Build Workflow

### 0. Classify The App Archetype

Pick one primary archetype before planning tools or choosing a starting point.

- Prefer a single primary archetype instead of mixing several.
- If the request is broad, infer the smallest archetype that can still satisfy it.
- Escalate to `submission-ready` only when the user asks for public launch, directory submission, or review-ready deployment.
- Call out the chosen archetype in your response so the user can correct it early if needed.

### 1. Plan Tools Before Code

Define the tool surface area from user intents.

- Use one job per tool.
- Write tool descriptions that start with "Use this when..." behavior cues.
- Make inputs explicit and machine-friendly (enums, required fields, bounds).
- Decide whether each tool is data-only, render-only, or both.
- Set annotations accurately (`readOnlyHint`, `destructiveHint`, `openWorldHint`; add `idempotentHint` when true).
- If the app is connector-like, data-only, sync-oriented, or intended for company knowledge or deep research, default to the standard `search` and `fetch` tools instead of inventing custom read-only equivalents.
- For educational/demo apps, prefer one concept per tool so the model can pick the right example cleanly.
- Group demo tools by learning objective: data into the widget, widget actions back into the conversation or tools, host/layout environment signals, and lifecycle/streaming behavior.

Read `references/search-fetch-standard.md` when `search` and `fetch` may be relevant.

### 2. Choose an App Architecture

Choose the simplest structure that fits the goal.

- Use a **minimal demo pattern** for quick prototypes, workshops, or proofs of concept.
- Use a **decoupled data/render pattern** for production UX so the widget does not re-render on every tool call.

Prefer the decoupled pattern for non-trivial apps:

- Data tools return reusable `structuredContent`.
- Render tools attach `_meta.ui.resourceUri` and optional `_meta["openai/outputTemplate"]`.
- Render tool descriptions state prerequisites (for example, "Call `search` first").

### 2a. Start From An Upstream Example When One Fits

Default to upstream examples for greenfield work when they are close to the requested app.

- Check the official OpenAI examples first for ChatGPT-facing apps, polished UI patterns, React components, file upload flows, modal flows, or apps that resemble the docs examples.
- Use `@modelcontextprotocol/ext-apps` examples when the request is closer to raw MCP Apps bridge/server wiring, or when version-matched package patterns matter more than ChatGPT-specific polish.
- Pick the smallest matching example and copy only the relevant files; do not transplant an entire showcase app unchanged.
- After copying, reconcile the example with the current docs you fetched: tool names/descriptions, annotations, `_meta.ui.*`, CSP, URI versioning, and local run instructions.
- State which example you chose and why in one sentence.

Read `references/upstream-example-workflow.md` for the selection and adaptation rubric.

### 2b. Use the Starter Script When a Low-Dependency Fallback Helps

Use `scripts/scaffold_node_ext_apps.mjs` only when the user wants a quick, greenfield Node starter and a vanilla HTML widget is acceptable, and no upstream example is a better starting point.

- Run it only after fetching current docs, then reconcile the generated files with the docs you fetched.
- If you choose the script instead of an upstream example, say why the fallback is better for that request.
- Skip it when a close official example exists, when the user already has an existing app structure, when they need a non-Node stack, when they explicitly want React first, or when they only want a plan/review instead of code.
- The script generates a minimal `@modelcontextprotocol/ext-apps` server plus a vanilla HTML widget that uses the MCP Apps bridge by default.
- The generated widget keeps follow-up messaging on the standard `ui/message` bridge and only uses `window.openai` for optional host signals/extensions.
- After running it, patch the generated output to match the current docs and the user request: adjust tool names/descriptions, annotations, resource metadata, URI versioning, and README/run instructions.

### 3. Scaffold the MCP Server

Generate a server that:

- Registers a widget resource/template with the MCP Apps UI MIME type (`text/html;profile=mcp-app`) or the SDK constant (`RESOURCE_MIME_TYPE`) when using `@modelcontextprotocol/ext-apps/server`
- Registers tools with clear names, schemas, titles, and descriptions
- Returns `structuredContent` (model + widget), `content` (model narration), and `_meta` (widget-only data) intentionally
- Keeps handlers idempotent or documents non-idempotent behavior explicitly
- Includes tool status strings (`openai/toolInvocation/*`) when helpful in ChatGPT

Keep `structuredContent` concise. Move large or sensitive widget-only payloads to `_meta`.

### 4. Scaffold the Widget UI

Use the MCP Apps bridge first for portability, then add ChatGPT-specific `window.openai` APIs when they materially improve UX.

- Listen for `ui/notifications/tool-result` (JSON-RPC over `postMessage`)
- Render from `structuredContent`
- Use `tools/call` for component-initiated tool calls
- Use `ui/update-model-context` only when UI state should change what the model sees

Use `window.openai` for compatibility and extensions (file upload, modal, display mode, etc.), not as the only integration path for new apps.

#### API Surface Guardrails

- Some examples wrap the bridge with an `app` object (for example, `@modelcontextprotocol/ext-apps/react`) and expose helper names like `app.sendMessage()`, `app.callServerTool()`, `app.openLink()`, or host getter methods.
- Treat those wrappers as implementation details or convenience layers, not the canonical public API to teach by default.
- For ChatGPT-facing guidance, prefer the current documented surface: `window.openai.callTool(...)`, `window.openai.sendFollowUpMessage(...)`, `window.openai.openExternal(...)`, `window.openai.requestDisplayMode(...)`, and direct globals like `window.openai.theme`, `window.openai.locale`, `window.openai.displayMode`, `window.openai.toolInput`, `window.openai.toolOutput`, `window.openai.toolResponseMetadata`, and `window.openai.widgetState`.
- If you reference wrapper helpers from repo examples, map them back to the documented `window.openai` or MCP Apps bridge primitives and call out that the wrapper is not the normative API surface.
- Use `references/window-openai-patterns.md` for the wrapper-to-canonical mapping and for React helper extraction patterns.

### 5. Add Resource Metadata and Security

Set resource metadata deliberately on the widget resource/template:

- `_meta.ui.csp` with exact `connectDomains` and `resourceDomains`
- `_meta.ui.domain` for app submission-ready deployments
- `_meta.ui.prefersBorder` (or OpenAI compatibility alias when needed)
- Optional `openai/widgetDescription` to reduce redundant narration

Avoid `frameDomains` unless iframe embeds are core to the product.

### 5a. Enforce A Minimum Working Repo Contract

Every generated repo should satisfy a small, stable contract before you consider it done.

- The repo shape matches the chosen archetype.
- The MCP server and tools are wired to a reachable `/mcp` endpoint.
- Tools have clear descriptions, accurate annotations, and UI metadata where needed.
- Connector-like, data-only, sync-oriented, and company-knowledge-style apps use the standard `search` and `fetch` tool shapes when relevant.
- The widget uses the MCP Apps bridge correctly when a UI exists.
- The repo includes enough scripts or commands for a user to run and check it locally.
- The response explicitly says what validation was run and what was not run.

Read `references/repo-contract-and-validation.md` for the detailed checklist and validation ladder.

### 6. Validate the Local Loop

Validate against the minimum working repo contract, not just “did files get created.”

- Run the lowest-cost checks first:
  - static contract review
  - syntax or compile checks when feasible
  - local `/mcp` health check when feasible
- Then move up to runtime checks:
  - verify tool descriptors and widget rendering in MCP Inspector
  - test the app in ChatGPT developer mode through HTTPS tunneling
  - exercise retries and repeated tool calls to confirm idempotent behavior
  - check widget updates after host events and follow-up tool calls
- If you are only delivering a scaffold and are not installing dependencies, still run low-cost checks and say exactly what you did not run.

Read `references/repo-contract-and-validation.md` for the validation ladder.

### 7. Connect and Test in ChatGPT (Developer Mode)

For local development, include explicit ChatGPT setup steps (not just code/run commands).

- Run the MCP server locally on `http://localhost:<port>/mcp`
- Expose the local server with a public HTTPS tunnel (for example `ngrok http <port>`)
- Use the tunneled HTTPS URL plus `/mcp` path when connecting from ChatGPT
- In ChatGPT, enable Developer Mode under **Settings → Apps & Connectors → Advanced settings**
- In ChatGPT app settings, create a new app for the remote MCP server and paste the public MCP URL
- Tell users to refresh the app after MCP tool/metadata changes so ChatGPT reloads the latest descriptors

Note: Some docs/screenshots still use older "connector" terminology. Prefer current product wording ("app") while acknowledging both labels when giving step-by-step instructions.

### 8. Plan Production Hosting and Deployment

When the user asks to deploy or prepare for launch, generate hosting guidance for the MCP server (and widget assets if hosted separately).

- Host behind a stable public HTTPS endpoint (not a tunnel) with dependable TLS
- Preserve low-latency streaming behavior on `/mcp`
- Configure secrets outside the repo (environment variables / secret manager)
- Add logging, request latency tracking, and error visibility for tool calls
- Add basic observability (CPU, memory, request volume) and a troubleshooting path
- Re-test the hosted endpoint in ChatGPT Developer Mode before submission

### 9. Prepare Submission and Publish (Public Apps Only)

Only include these steps when the user intends a public directory listing.

- Use `apps-sdk/deploy/submission` for the submission flow and `apps-sdk/app-submission-guidelines` for review requirements
- Keep private/internal apps in Developer Mode instead of submitting
- Confirm org verification and Owner-role prerequisites before submission work
- Ensure the MCP server uses a public production endpoint (no localhost/testing URLs) and has submission-ready CSP configured
- Prepare submission artifacts: app metadata, logo/screenshots, privacy policy URL, support contact, test prompts/responses, localization info
- If auth is required, include review-safe demo credentials and test the login path end-to-end
- Submit for review in the Platform dashboard, monitor review status, and publish only after approval

## Interactive State Guidance

Read `references/interactive-state-sync-patterns.md` when the app has long-lived widget state, repeated interactions, or component-initiated tool calls (for example, games, boards, maps, dashboards, editors).

Use it to choose patterns for:

- State snapshots plus monotonic event tokens (`stateVersion`, `resetCount`, etc.)
- Idempotent retry-safe handlers
- `structuredContent` vs `_meta` partitioning
- MCP Apps bridge-first update flows with optional `window.openai` compatibility
- Decoupled data/render tool architecture for more complex interactive apps

## Output Expectations

When using this skill to scaffold code, produce output in this order unless the user asks otherwise:

- For direct scaffold requests, do not stop at the plan: give the brief plan, then create the files immediately.

1. Primary app archetype chosen and why
2. Tool plan and architecture choice (minimal vs decoupled)
3. Upstream starting point chosen (official example, ext-apps example, or local fallback scaffold) and why
4. Doc pages/URLs used from `$openai-docs`
5. File tree to create or modify
6. Implementation (server + widget)
7. Validation performed against the minimum working repo contract
8. Local run/test instructions (including tunnel + ChatGPT Developer Mode app setup)
9. Deployment/hosting guidance (if requested or implied)
10. Submission-readiness checklist (for public launch requests)
11. Risks, gaps, and follow-up improvements

## References

- `references/app-archetypes.md` for classifying requests into a small number of supported app shapes
- `references/apps-sdk-docs-workflow.md` for doc queries, page targets, and code-generation checklist
- `references/interactive-state-sync-patterns.md` for reusable patterns for stateful or highly interactive widget apps
- `references/repo-contract-and-validation.md` for the minimum working repo contract and lightweight validation ladder
- `references/search-fetch-standard.md` for when and how to default to the standard `search` and `fetch` tools
- `references/upstream-example-workflow.md` for choosing between official examples, ext-apps examples, and the local fallback scaffold
- `references/window-openai-patterns.md` for ChatGPT-specific extensions, wrapper API translation, and React helper patterns
- `scripts/scaffold_node_ext_apps.mjs` for a minimal Node + `@modelcontextprotocol/ext-apps` fallback starter scaffold


================================================
FILE: skills/.curated/chatgpt-apps/agents/openai.yaml
================================================
interface:
  display_name: "ChatGPT Apps"
  short_description: "Build and scaffold ChatGPT apps"
  default_prompt: "Use $chatgpt-apps to classify the app archetype first, fetch current OpenAI Apps SDK docs before generating code, default to the standard `search` and `fetch` tools when the app is connector-like or sync-oriented, adapt the closest upstream example when one fits, and only fall back to the local Node scaffold for minimal `@modelcontextprotocol/ext-apps` starters. Produce a working repo shape, then report what validation was actually run."
dependencies:
  tools:
    - type: "mcp"
      value: "openaiDeveloperDocs"
      description: "OpenAI developer docs MCP server for current Apps SDK guidance"
      transport: "streamable_http"
      url: "https://developers.openai.com/mcp"
policy:
  allow_implicit_invocation: true


================================================
FILE: skills/.curated/chatgpt-apps/references/app-archetypes.md
================================================
# App Archetypes

Load this reference before choosing a starting point for a new ChatGPT app. The goal is to keep the skill inside a small number of supported app shapes instead of inventing a custom structure for every prompt.

## Rule

Choose one primary archetype per request and state it.

Do not combine several archetypes unless the user explicitly asks for a hybrid app and the extra complexity is necessary.

## Archetypes

### `tool-only`

Use when:

- The user does not need an in-ChatGPT UI
- The task is mainly search, fetch, retrieval, or background actions

Default shape:

- MCP server only

Best starting point:

- Official docs and MCP server examples

Validation emphasis:

- `/mcp` route works
- tool schemas and annotations are correct
- no unnecessary UI resource is registered
- if the app is connector-like or sync-oriented, `search` and `fetch` should be the default read-only tools

### `vanilla-widget`

Use when:

- The user wants a small demo, workshop starter, or simple inline widget
- A single HTML widget is enough
- The user wants the fastest path to a working repo

Default shape:

- Root-level server plus `public/` widget assets

Best starting point:

- Apps SDK quickstart first
- Local fallback scaffold if the quickstart is not a good fit

Validation emphasis:

- bridge initialization
- `ui/notifications/tool-result`
- `tools/call` only when the widget is interactive

### `react-widget`

Use when:

- The user wants a polished UI
- The UI is clearly component-based
- The user mentions React, TypeScript frontend tooling, or richer design requirements

Default shape:

- Split `server/` + `web/` layout when the example already uses it

Best starting point:

- Official OpenAI examples

Validation emphasis:

- build output is wired into the server correctly
- bundle references resolve
- widget renders from `structuredContent`

### `interactive-decoupled`

Use when:

- The app has repeated user interaction
- The widget should stay mounted while tools are called repeatedly
- The app is a board, map, editor, game, dashboard, or other stateful experience

Default shape:

- Split `server/` + `web/`
- data tools plus render tools

Best starting point:

- Official OpenAI examples plus `references/interactive-state-sync-patterns.md`

Validation emphasis:

- tool retries are safe
- widget does not remount unnecessarily
- state sync is intentional
- UI tool calls work independently of model reruns

### `submission-ready`

Use when:

- The user asks for public launch, review readiness, or directory submission

Default shape:

- Smallest viable repo that still includes deployment and review requirements

Best starting point:

- Closest official example that matches the requested stack

Validation emphasis:

- `_meta.ui.domain`
- accurate CSP
- auth and review-safe flows
- submission prerequisites and artifacts

## Selection Heuristic

- If the prompt does not mention a UI, choose `tool-only`.
- If the prompt is about a knowledge source, sync app, connector-like integration, or deep research, strongly prefer `tool-only` plus the standard `search` and `fetch` tools unless the user clearly needs a widget.
- If the prompt asks for a simple demo or starter, choose `vanilla-widget`.
- If the prompt asks for a polished UI or React, choose `react-widget`.
- If the prompt implies long-lived client state or repeated interaction, choose `interactive-decoupled`.
- Only choose `submission-ready` when the user explicitly asks for launch or review-readiness work.


================================================
FILE: skills/.curated/chatgpt-apps/references/apps-sdk-docs-workflow.md
================================================
# Apps SDK Docs Workflow

Use this reference to keep code generation aligned with current OpenAI Apps SDK docs.

## Always Fetch These Pages (Baseline)

- `https://developers.openai.com/apps-sdk/build/mcp-server/`
- `https://developers.openai.com/apps-sdk/build/chatgpt-ui/`
- `https://developers.openai.com/apps-sdk/build/examples/`
- `https://developers.openai.com/apps-sdk/plan/tools/`
- `https://developers.openai.com/apps-sdk/reference/`

## Fetch Conditionally (Greenfield / First Pass)

- `https://developers.openai.com/apps-sdk/quickstart/` for first implementation scaffolds and happy-path wiring
- `https://developers.openai.com/apps-sdk/deploy/` when the task includes local ChatGPT testing via tunnel, hosting, or production deployment planning
- `https://developers.openai.com/apps-sdk/deploy/submission/` when the task includes public launch, app review, or publishing steps
- `https://developers.openai.com/apps-sdk/app-submission-guidelines/` when the task includes submission readiness, policy/reliability checks, or review-risk reduction

## Suggested `openai-docs` / MCP Queries

Use focused searches before fetching:

- `ChatGPT Apps SDK build MCP server register resource template resourceUri outputTemplate`
- `ChatGPT Apps SDK build ChatGPT UI MCP Apps bridge ui/notifications/tool-result`
- `ChatGPT Apps SDK examples React widget upload modal Pizzaz`
- `Apps SDK define tools annotations readOnlyHint destructiveHint openWorldHint`
- `Apps SDK reference tool descriptor _meta ui.resourceUri openai/outputTemplate`
- `ChatGPT Apps SDK quickstart build web component tools/call`
- `ChatGPT app company knowledge compatibility search fetch tools`
- `platform MCP search tool fetch tool schema`
- `ChatGPT Apps SDK deploy app local development tunnel ngrok refresh connector`
- `ChatGPT Apps SDK submit app review prerequisites app submission guidelines`

## Docs-Derived Checklist (Current Guidance)

### Archetype / Shape

- Classify the request into one primary app archetype before choosing examples or scaffolds
- Keep the repo shape consistent with that archetype instead of inventing a new structure for each prompt

### Server

- Register the widget resource/template with the MCP Apps UI MIME type (`text/html;profile=mcp-app`) or `RESOURCE_MIME_TYPE` when using `@modelcontextprotocol/ext-apps/server`
- Version template URIs when widget HTML or JS or CSS changes in a breaking way (treat URI as cache key)
- Set `_meta.ui.resourceUri` on render tools; optionally mirror `_meta["openai/outputTemplate"]` for ChatGPT compatibility
- Design tool handlers to be idempotent because the model may retry calls
- Keep `structuredContent` concise and move widget-only payloads to `_meta`

### Tool Design

- Plan one user intent per tool
- Use action-oriented names and precise descriptions
- Set tool impact hints accurately (`readOnlyHint`, `destructiveHint`, `openWorldHint`)
- Split data and render tools so that the model can fetch the data and look at it before choosing to render the widget UI or not
- Make the widget input a list of unique identifiers (e.g. `propertyIds` for a render property map widget that takes IDs returned from the fetch properties nearby tool) if you want to make sure the widget only renders 1p data; make the widget input semantically relevant if you want to allow the model to render the widget with generated data (e.g. `questionAndAnswerPairs` for a flashcards widget)
- For connector-like, data-only, sync-oriented, or company-knowledge-style apps, prefer the standard `search` and `fetch` tools by default

### UI

- Prefer the MCP Apps bridge (`ui/*` notifications + `tools/call`) for new apps
- Prefer `ui/message` for follow-up messaging in baseline examples; treat `window.openai.sendFollowUpMessage` as optional ChatGPT-specific compatibility
- Treat `window.openai` as compatibility plus optional ChatGPT extensions
- Render from `structuredContent` and treat host-delivered data as untrusted input
- Use `ui/update-model-context` only for UI state the model should reason about

### Starting Point Selection

- Check `apps-sdk/build/examples` and the official examples repo before generating a greenfield scaffold from scratch
- Prefer the smallest upstream example that matches the requested stack and interaction pattern
- Use the local fallback scaffold only when upstream examples are a poor fit or undesirable for the request

### Resource Metadata / Security

- Set `_meta.ui.csp.connectDomains` and `_meta.ui.csp.resourceDomains` exactly
- Avoid `frameDomains` unless iframe embedding is central to the experience
- Set `_meta.ui.domain` for submission-ready apps
- Always set `openai/widgetDescription` to inform the model what the widget is to be used for

### Developer Mode / Local Testing

- Run the MCP server locally on `http://localhost:<port>/mcp`
- Expose it with a public HTTPS tunnel for ChatGPT access during development
- Use the public URL + `/mcp` when adding the app in ChatGPT settings
- Include ChatGPT Developer Mode setup and app creation steps in implementation handoff
- Remind users to refresh the app after MCP tool/metadata changes
- Note terminology differences when relevant: some docs/screenshots may still say "connector" while product UI uses "app"

### Validation

- Validate against a minimum working repo contract, not just file creation
- Run the cheapest useful syntax or compile check first
- If feasible, confirm the local `/mcp` route responds before calling the result “working”
- If you cannot run a deeper check, say so explicitly
- If the app is connector-like or sync-oriented, verify the `search` and `fetch` tool shapes against the standard

### Production Hosting / Deploy

- Prefer a stable public HTTPS endpoint with reliable TLS and low-latency streaming `/mcp`
- Document platform-specific secrets handling and environment variables
- Include logging/metrics expectations for debugging production tool calls
- Re-test the hosted endpoint in ChatGPT Developer Mode before submission

### Submission / Review

- Read `deploy/submission` and `app-submission-guidelines` together (process + policy requirements)
- Check org verification and Owner-role prerequisites before generating submission steps
- Ensure the endpoint is public production infrastructure (not localhost/tunnel/testing URLs)
- Ensure CSP is defined and accurate for submission
- Prepare submission artifacts (metadata, screenshots, privacy policy/support contacts, test prompts/responses)
- If auth is required, prepare review-safe demo credentials and validate them outside internal networks

## Generation Pattern

1. Classify the app archetype.
2. Fetch docs with `$openai-docs`.
3. Check official examples before inventing a scaffold from scratch.
4. Summarize relevant constraints and metadata keys.
5. Propose tool plan and architecture.
6. Adapt the closest example or use the local fallback scaffold.
7. Generate or patch the server scaffold.
8. Generate or patch the widget scaffold.
9. Validate the repo against the minimum working contract.
10. Add local run + tunnel + ChatGPT Developer Mode app setup instructions.
11. Add hosting/deployment guidance when the task implies go-live.
12. Add submission/readiness steps when the user intends public distribution.
13. Call out compatibility aliases vs MCP Apps standard fields.

## Starter Scaffold Script

- Use `./scripts/scaffold_node_ext_apps.mjs <output-dir> --app-name <name>` only when the user wants a greenfield Node + `@modelcontextprotocol/ext-apps` starter and no upstream example is the better fit.
- If the file is not executable in the current environment, fall back to `node scripts/scaffold_node_ext_apps.mjs <output-dir> --app-name <name>`.
- The script generates `package.json`, `tsconfig.json`, `public/widget.html`, and `src/server.ts`.
- It intentionally uses the MCP Apps bridge by default, keeps follow-up messaging on `ui/message`, and limits `window.openai` to optional host signals/extensions.
- After generation, compare the output against the docs you fetched and adjust package versions, metadata, transport details, or URI/versioning if the docs changed.


================================================
FILE: skills/.curated/chatgpt-apps/references/interactive-state-sync-patterns.md
================================================
# Interactive State Sync Patterns

Use this reference when building ChatGPT apps with long-lived widget state, repeated interactions, or component-initiated tool calls (for example: games, boards, maps, dashboards, editors, or realtime-ish UIs).

Do not load this file for simple read-only render apps unless state sync behavior is part of the task.

## When This Reference Helps

Read this file when the app needs one or more of these patterns:

- Repeated actions that may return similar data (retry, refresh, reset, reroll)
- UI controls that trigger tool calls after the initial render
- Local widget behavior that should also work outside ChatGPT during development
- Multiple tool calls updating one mounted widget over time
- Clear separation between model-visible state and widget-only state

## Reusable Patterns

### 1. Snapshot + Event Token

Return a stable state snapshot in `structuredContent` and add a monotonic event token for repeated actions that may not change other fields.

Examples:

- `stateVersion`
- `refreshCount`
- `resetCount`
- `lastMutationId`

Use this when the widget must detect "same shape, new event" updates reliably.

### 2. Intent-Focused Tool Surface

Prefer small, explicit tools that map to user-visible actions or data operations.

- Keep names action-oriented
- Use enums and bounded schemas where possible
- Avoid kitchen-sink tools that mix unrelated reads and writes

This improves model tool selection and reduces malformed calls.

### 3. Idempotent Handlers (or Explicitly Non-Idempotent)

Design handlers to tolerate retries. If a tool is not idempotent, make the side effect explicit and confirm intent in the flow.

- Reads and pure transforms should usually be idempotent
- Writes should include clear impact hints and current-turn confirmation where needed
- Repeated calls with the same input should not corrupt widget state

### 4. `structuredContent` / `_meta` Partitioning

Partition payloads intentionally:

- `structuredContent`: concise model-visible state the widget also uses
- `content`: short narration/status text
- `_meta`: large maps, caches, or sensitive widget-only hydration data

Keep `structuredContent` small enough for follow-up reasoning and chaining.

### 5. MCP Apps Bridge First, `window.openai` Second

For new scaffolds:

- Prefer MCP Apps bridge notifications and `tools/call` (portable across hosts)
- Use `window.openai` as a compatibility layer plus optional ChatGPT extensions

This keeps the app portable while still enabling ChatGPT-specific capabilities when helpful.

### 6. Component-Initiated Tool Calls Without Remounting

For interactive widgets, allow the UI to call data/action tools directly and update the existing widget state instead of forcing a full re-render/remount every time.

This is especially useful for:

- Refresh
- Retry
- Rerun
- Toggle/filter actions
- Incremental interactions inside one widget session

### 7. Standalone / No-Host Fallback Mode

When feasible, make the widget usable without ChatGPT during development:

- If host APIs are unavailable, apply local state directly
- Preserve basic interactions in a normal browser

This speeds up front-end iteration and reduces dependence on connector setup for every UI tweak.

### 8. Decouple Data Tools from Render Tools (When Complexity Grows)

Use separate data and render tools when the app has multi-step reasoning or frequent updates.

- Data tools fetch/compute/mutate and return reusable `structuredContent`
- Render tools attach the widget template and focus on presentation

This reduces unnecessary remounts and gives the model a chance to refine data before rendering.

## Common Anti-Patterns

- Putting large widget-only blobs into `structuredContent`
- Attaching a widget template to every tool when only one render tool needs it
- Using hidden client-side state as the source of truth for critical actions
- Depending only on `window.openai` APIs for baseline app behavior
- Using ambiguous tool names that do not match user intent

## Example App Types That Benefit From These Patterns

- Multiplayer or turn-based games
- Collaborative boards / task views
- Maps with filters and repeated searches
- Dashboards with refresh and drill-down actions
- Editors or builders with iterative tool calls


================================================
FILE: skills/.curated/chatgpt-apps/references/repo-contract-and-validation.md
================================================
# Repo Contract And Validation

Load this reference when scaffolding or reviewing a generated ChatGPT app repo.

The goal is not “files were created.” The goal is “the repo is plausibly runnable and follows a stable working-app contract.”

## Minimum Working Repo Contract

Every generated repo should satisfy the relevant parts of this contract.

### 1. Shape

- The repo shape matches the chosen archetype.
- The repo structure is simple enough that a user can identify where the server and widget live.

### 2. Server

- There is a clear MCP server entry point.
- The server exposes `/mcp`.
- The server registers tools intentionally.
- If a UI exists, the server registers a resource/template with the MCP Apps UI MIME type.

### 3. Tools

- Each tool maps to one user intent.
- Descriptions help the model choose the tool.
- Required annotations are present and accurate.
- UI-linked tools use `_meta.ui.resourceUri`.
- `_meta["openai/outputTemplate"]` is treated as optional compatibility, not the primary contract.
- When the app is connector-like, data-only, sync-oriented, or intended for company knowledge or deep research, it implements standard `search` and `fetch` tools instead of custom substitutes.

### 4. Widget

- The widget initializes the MCP Apps bridge when needed.
- The widget can receive `ui/notifications/tool-result`.
- The widget renders from `structuredContent`.
- Interactive widgets use `tools/call`.
- Baseline follow-up messaging uses `ui/message`.
- `window.openai` is optional and additive.

### 5. Local Developer Experience

- There is a clear way to start the app locally.
- There is at least one low-cost check command when the stack supports it.
- The response explains how to connect the app in ChatGPT Developer Mode when relevant.

## Validation Ladder

Run the highest level you can without overfitting to a single stack.

### Level 0: Static contract review

Check for:

- chosen archetype is sensible
- repo shape matches archetype
- `/mcp` route is present
- tool/resource/widget responsibilities are coherent
- if the app is connector-like or sync-oriented, `search` and `fetch` are present with the expected standard shape

### Level 1: Syntax or compile checks

Use the stack-appropriate cheapest check available, for example:

- Python syntax check
- TypeScript compile check
- framework-specific lint or build sanity check if already installed

### Level 2: Local runtime sanity

If feasible:

- start the server
- confirm the health route or `/mcp` endpoint responds

### Level 3: Host loop validation

If feasible:

- inspect with MCP Inspector
- test through ChatGPT Developer Mode
- confirm widget updates after tool results

## Reporting Rule

Always say which validation level was reached and what was not run.

That makes the skill more reliable because it separates:

- “repo shape looks right”
- “syntax is valid”
- “server starts”
- “host integration was actually exercised”


================================================
FILE: skills/.curated/chatgpt-apps/references/search-fetch-standard.md
================================================
# Search And Fetch Standard

Load this reference when the app is connector-like, data-only, sync-oriented, or meant to work well with company knowledge or deep research.

## Default Rule

If the app is primarily a read-only knowledge source, do not invent custom equivalents to `search` and `fetch`.

Default to implementing the standard `search` and `fetch` tools exactly, then add other tools only if the use case clearly needs them.

## When This Applies

Use the standard by default when the request is about:

- a data-only app
- a sync app
- a company knowledge source
- deep research compatibility
- a connector-like integration over documents, tickets, wiki pages, CRM records, or similar read-only data

## Tool Requirements

### `search`

- Read-only tool
- Takes a single query string
- Returns exactly one MCP content item with `type: "text"`
- That text is a JSON-encoded object with:
  - `results`
  - each result has `id`, `title`, and `url`

### `fetch`

- Read-only tool
- Takes a single document/item id string
- Returns exactly one MCP content item with `type: "text"`
- That text is a JSON-encoded object with:
  - `id`
  - `title`
  - `text`
  - `url`
  - optional `metadata`

## Implementation Rules

- Match the schema exactly when the app is intended for company knowledge or deep research compatibility.
- Use canonical `url` values for citations.
- Mark these tools as read-only.
- Prefer these names exactly: `search` and `fetch`.
- If you add other read-only tools, they should complement the standard rather than replace it.

## Validation Checks

When `search` and `fetch` are relevant, verify:

- both tools exist
- they are read-only
- their input shapes match the standard
- their returned payloads are wrapped as one `content` item with JSON-encoded `text`
- result URLs are canonical enough for citation use

## Source

This standard is described in:

- `https://developers.openai.com/apps-sdk/build/mcp-server/#company-knowledge-compatibility`
- `https://platform.openai.com/docs/mcp`


================================================
FILE: skills/.curated/chatgpt-apps/references/upstream-example-workflow.md
================================================
# Upstream Example Workflow

Load this reference when starting a greenfield ChatGPT app or when deciding whether to adapt an upstream example or use the local fallback scaffold.

## Default Order

Prefer these starting points in order:

1. Official OpenAI Apps SDK examples
2. Version-matched `@modelcontextprotocol/ext-apps` examples
3. Local `scripts/scaffold_node_ext_apps.mjs` fallback

This keeps the skill aligned with current docs and maintained example code while still preserving a low-dependency fallback when examples are not a good fit.

## Choose The Right Source

### 1. Official OpenAI examples

Prefer these when:

- The app is clearly ChatGPT-facing
- The user wants a polished UI or React component
- The task involves file upload, modal flows, display-mode changes, or other ChatGPT extensions
- The docs/examples page already shows a similar interaction pattern

Typical sources:

- `https://developers.openai.com/apps-sdk/build/examples/`
- `https://github.com/openai/openai-apps-sdk-examples`
- `https://developers.openai.com/apps-sdk/quickstart/` for the smallest vanilla baseline

### 2. `@modelcontextprotocol/ext-apps` examples

Prefer these when:

- The user needs a lower-level MCP Apps baseline
- Portability across MCP Apps-compatible hosts matters more than ChatGPT-specific polish
- You want version-matched examples close to the installed `@modelcontextprotocol/ext-apps` package shape

This follows the same basic idea as the upstream `create-mcp-app` skill: use maintained examples as the starting point, then adapt them.

Typical examples from upstream flows:

- `examples/demo-vanilla-html`
- `examples/demo-react-simple`
- `examples/demo-connectors-api`

### 3. Local fallback scaffold

Use `scripts/scaffold_node_ext_apps.mjs` when:

- No close upstream example exists
- The user wants a tiny Node + vanilla HTML starter
- Network/example retrieval is undesirable
- You need a throwaway starter to patch quickly during a live coding task

Do not prefer the local scaffold just because it is available. It is the fallback, not the default.

## Adaptation Rules

- Copy the smallest matching example, not the entire showcase app.
- Remove unrelated demo tools, assets, and routes immediately.
- Keep the upstream file structure when it is already clean and docs-aligned.
- Reconcile the copied example with the current docs before finishing:
  - tool names and descriptions
  - annotations (`readOnlyHint`, `destructiveHint`, `openWorldHint`, `idempotentHint` when true)
  - `_meta.ui.resourceUri` and optional `_meta["openai/outputTemplate"]`
  - resource `_meta.ui.csp`, `_meta.ui.domain`, and `openai/widgetDescription`
  - URI versioning for template changes
  - local run/test instructions
- State which example you chose and why.
- If you rely on upstream code, note the source repo and branch/tag/commit when practical; avoid silently depending on a floating example shape for long-lived work.

## Minimal Selection Heuristic

- If the user asks for **React + polished UI**, start with official OpenAI examples.
- If the user asks for **vanilla HTML + tiny demo**, start with the quickstart example; use the local fallback scaffold only if the quickstart is still too opinionated or unavailable.
- If the user asks for **portable MCP Apps wiring**, start with `@modelcontextprotocol/ext-apps` examples.
- If the user already has an app, adapt their code directly instead of importing a new example.


================================================
FILE: skills/.curated/chatgpt-apps/references/window-openai-patterns.md
================================================
# Window.openai Patterns

Load this reference when a task needs ChatGPT-only widget features, when translating older examples that use an `app` wrapper, or when a React widget should read host globals safely.

## Core Rule

- Build baseline widget behavior on the MCP Apps bridge: `ui/*` notifications, `tools/call`, `ui/message`, and `ui/update-model-context`.
- Use `window.openai` only when the task specifically benefits from ChatGPT-only runtime conveniences.
- Treat `window.openai` as additive. The app should still have a coherent baseline path on the MCP Apps standard when possible.

## Canonical `window.openai` Surface

### State And Data

- `window.openai.toolInput`: tool arguments supplied by the host
- `window.openai.toolOutput`: current `structuredContent`
- `window.openai.toolResponseMetadata`: current `_meta` payload (widget-only)
- `window.openai.widgetState`: persisted widget-local snapshot
- `window.openai.setWidgetState(state)`: persist widget-local snapshot after meaningful UI changes

### Runtime APIs

- `window.openai.callTool(name, args)`: call another MCP tool from the widget
- `window.openai.sendFollowUpMessage({ prompt, scrollToBottom? })`: ask ChatGPT to post a widget-authored follow-up message
- `window.openai.openExternal({ href, redirectUrl? })`: open an external URL through ChatGPT's vetted flow
- `window.openai.requestDisplayMode({ mode })`: request `inline`, `pip`, or `fullscreen`
- `window.openai.requestModal({ params, template? })`: open a host-owned modal
- `window.openai.requestClose()`: ask ChatGPT to close the widget
- `window.openai.uploadFile(file)`: upload a file from the widget
- `window.openai.getFileDownloadUrl({ fileId })`: resolve a temporary download URL
- `window.openai.notifyIntrinsicHeight(...)`: report dynamic height changes
- `window.openai.setOpenInAppUrl({ href })`: override the fullscreen punch-out target

### Context Signals

- `window.openai.theme`
- `window.openai.displayMode`
- `window.openai.maxHeight`
- `window.openai.safeArea`
- `window.openai.view`
- `window.openai.userAgent`
- `window.openai.locale`

## Mapping From Repo Wrapper Examples

- `app.callServerTool({ name, arguments })`:
  Use `window.openai.callTool(name, args)` when you intentionally want the ChatGPT compatibility layer.
  Use `tools/call` over the bridge when you want the portable MCP Apps path.
- `app.sendMessage(...)`:
  Use `ui/message` for portable bridge messaging.
  If the task is intentionally ChatGPT-specific, `window.openai.sendFollowUpMessage({ prompt })` is the closest supported path.
- `app.updateModelContext(...)`:
  Use `ui/update-model-context` over the bridge.
  This is part of the standard bridge, not a `window.openai` feature.
- `app.openLink({ url })`:
  Use `window.openai.openExternal({ href: url })` when you intentionally want ChatGPT's external navigation flow.
- `app.requestDisplayMode({ mode })`:
  Use `window.openai.requestDisplayMode({ mode })`.
- `app.getHostContext()`:
  Read the documented globals directly (`theme`, `displayMode`, `locale`, `maxHeight`, `safeArea`, `userAgent`).
- `app.getHostCapabilities()` / `app.getHostVersion()`:
  These are wrapper-level convenience APIs.
  Prefer feature detection (`if (window.openai?.requestModal)`) and the documented globals instead of teaching these as the primary public surface.

## React Helper Extraction

- The repo's `src/use-openai-global.ts` is a good baseline for subscribing to host global changes without scattering direct `window.openai` reads through components.
- The repo's `src/use-widget-state.ts` is a good baseline for mirroring React state into `window.openai.setWidgetState(...)`.
- The repo's `src/use-widget-props.ts` is a good baseline for reading typed `toolOutput` with a local fallback.
- Keep these helpers optional. Do not force a React abstraction when a simple vanilla widget is enough.


================================================
FILE: skills/.curated/chatgpt-apps/scripts/scaffold_node_ext_apps.mjs
================================================
#!/usr/bin/env node

import { mkdirSync, writeFileSync, existsSync, readdirSync, lstatSync } from "node:fs";
import path from "node:path";

function toSlug(value) {
  const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
  return normalized || "example-chatgpt-app";
}

function toToolName(value) {
  const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
  return normalized || "show_example";
}

function toTitle(value) {
  const parts = value.split(/[-_]+/).filter(Boolean);
  return parts.map((part) => part[0].toUpperCase() + part.slice(1)).join(" ") || "Example";
}

function fillTemplate(template, mapping) {
  let result = template;
  for (const [key, value] of Object.entries(mapping)) {
    result = result.replaceAll(key, value);
  }
  return result;
}

function writeFile(filePath, content) {
  mkdirSync(path.dirname(filePath), { recursive: true });
  writeFileSync(filePath, content, "utf8");
}

function ensureTargetDir(targetPath, force) {
  if (existsSync(targetPath)) {
    if (!lstatSync(targetPath).isDirectory()) {
      throw new Error(`Output path exists and is not a directory: ${targetPath}`);
    }
    if (readdirSync(targetPath).length > 0 && !force) {
      throw new Error(
        `Refusing to write into non-empty directory: ${targetPath}\nRe-run with --force to overwrite generated files.`
      );
    }
  }

  mkdirSync(targetPath, { recursive: true });
}

function buildPackageJson(appSlug) {
  const packageJson = {
    name: appSlug,
    private: true,
    type: "module",
    scripts: {
      dev: "tsx watch src/server.ts",
      start: "tsx src/server.ts",
      check: "tsc --noEmit",
    },
    dependencies: {
      "@modelcontextprotocol/ext-apps": "^1.0.1",
      "@modelcontextprotocol/sdk": "^1.20.2",
      zod: "^3.25.76",
    },
    devDependencies: {
      "@types/node": "^24.3.0",
      tsx: "^4.19.4",
      typescript: "^5.9.2",
    },
  };

  return `${JSON.stringify(packageJson, null, 2)}\n`;
}

function buildTsconfig() {
  return `{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "types": ["node"],
    "outDir": "dist"
  },
  "include": ["src/**/*.ts"]
}
`;
}

const WIDGET_TEMPLATE = `<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>__APP_TITLE__</title>
    <style>
      :root {
        color: #0b0f19;
        font-family: "Inter", system-ui, sans-serif;
      }

      * {
        box-sizing: border-box;
      }

      body {
        margin: 0;
        min-height: 100vh;
        padding: 16px;
        background:
          radial-gradient(circle at top right, #d8f3ff 0, transparent 40%),
          linear-gradient(180deg, #f7fbff 0%, #edf3fb 100%);
      }

      main {
        width: 100%;
        max-width: 420px;
        margin: 0 auto;
        padding: 20px;
        border-radius: 18px;
        background: rgba(255, 255, 255, 0.92);
        border: 1px solid rgba(11, 15, 25, 0.08);
        box-shadow: 0 14px 32px rgba(11, 15, 25, 0.08);
      }

      .eyebrow {
        margin: 0 0 8px;
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0.12em;
        text-transform: uppercase;
        color: #4f5d75;
      }

      h1 {
        margin: 0 0 10px;
        font-size: 24px;
        line-height: 1.15;
      }

      p {
        margin: 0;
        line-height: 1.5;
      }

      .stack {
        display: grid;
        gap: 12px;
      }

      button {
        border: 0;
        border-radius: 999px;
        padding: 10px 14px;
        font: inherit;
        font-weight: 600;
        color: white;
        background: #0f62fe;
        cursor: pointer;
      }

      button[hidden] {
        display: none;
      }

      button.secondary {
        background: #0b0f19;
      }

      .meta {
        padding: 12px;
        border-radius: 14px;
        background: #f5f8fc;
        color: #4f5d75;
        font-size: 13px;
      }
    </style>
  </head>
  <body>
    <main class="stack">
      <p class="eyebrow">__APP_TITLE__ starter</p>
      <h1 id="headline">Waiting for tool output</h1>
      <p id="message">Call the __TOOL_NAME__ tool to hydrate this widget.</p>
      <button id="tool-button" type="button">Call __TOOL_NAME__ from the widget</button>
      <button id="follow-up-button" class="secondary" type="button">
        Ask the host to explain this app
      </button>
      <div class="meta" id="meta">
        This widget uses the MCP Apps bridge by default.
      </div>
    </main>

    <script type="module">
      const headlineEl = document.querySelector("#headline");
      const messageEl = document.querySelector("#message");
      const metaEl = document.querySelector("#meta");
      const toolButtonEl = document.querySelector("#tool-button");
      const followUpButtonEl = document.querySelector("#follow-up-button");

      let toolOutput = null;
      let rpcId = 0;
      const pendingRequests = new Map();

      const render = () => {
        const headline = toolOutput?.headline ?? "__APP_TITLE__";
        const message =
          toolOutput?.message ??
          "Call the __TOOL_NAME__ tool to hydrate this widget.";

        headlineEl.textContent = headline;
        messageEl.textContent = message;

        const theme = window.openai?.theme ?? "bridge-only";
        metaEl.textContent =
          "Runtime: " +
          (window.openai ? "MCP Apps bridge + optional window.openai" : "MCP Apps bridge only") +
          " | Theme: " +
          theme;
      };

      const rpcNotify = (method, params) => {
        window.parent.postMessage({ jsonrpc: "2.0", method, params }, "*");
      };

      const rpcRequest = (method, params) =>
        new Promise((resolve, reject) => {
          const id = ++rpcId;
          pendingRequests.set(id, { resolve, reject });
          window.parent.postMessage({ jsonrpc: "2.0", id, method, params }, "*");
        });

      window.addEventListener(
        "message",
        (event) => {
          if (event.source !== window.parent) {
            return;
          }

          const message = event.data;
          if (!message || message.jsonrpc !== "2.0") {
            return;
          }

          if (typeof message.id === "number") {
            const pending = pendingRequests.get(message.id);
            if (!pending) {
              return;
            }

            pendingRequests.delete(message.id);
            if (message.error) {
              pending.reject(message.error);
              return;
            }

            pending.resolve(message.result);
            return;
          }

          if (message.method === "ui/notifications/tool-result") {
            toolOutput = message.params?.structuredContent ?? null;
            render();
          }
        },
        { passive: true }
      );

      const initializeBridge = async () => {
        await rpcRequest("ui/initialize", {
          appInfo: { name: "__APP_SLUG__-widget", version: "0.1.0" },
          appCapabilities: {},
          protocolVersion: "2026-01-26",
        });
        rpcNotify("ui/notifications/initialized", {});
      };

      const bridgeReady = initializeBridge();

      toolButtonEl.addEventListener("click", async () => {
        await bridgeReady;

        const response = await rpcRequest("tools/call", {
          name: "__TOOL_NAME__",
          arguments: {
            message: "Tool call triggered from the widget.",
          },
        });

        toolOutput = response?.structuredContent ?? toolOutput;
        render();
      });

      followUpButtonEl.addEventListener("click", async () => {
        await bridgeReady;

        rpcNotify("ui/message", {
          role: "user",
          content: [
            {
              type: "text",
              text: "Explain how the __TOOL_NAME__ widget works.",
            },
          ],
        });
      });

      render();
    </script>
  </body>
</html>
`;

const SERVER_TEMPLATE = `import { createServer } from "node:http";
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

import {
  registerAppResource,
  registerAppTool,
  RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { z } from "zod";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT_DIR = path.resolve(__dirname, "..");
const WIDGET_URI = "__WIDGET_URI__";
const WIDGET_HTML = readFileSync(
  path.join(ROOT_DIR, "public", "widget.html"),
  "utf8"
);

function createAppServer(): McpServer {
  const server = new McpServer({
    name: "__APP_SLUG__",
    version: "0.1.0",
  });

  registerAppResource(
    server,
    "main-widget",
    WIDGET_URI,
    {},
    async () => ({
      contents: [
        {
          uri: WIDGET_URI,
          mimeType: RESOURCE_MIME_TYPE,
          text: WIDGET_HTML,
          _meta: {
            ui: {
              prefersBorder: true,
              csp: {
                connectDomains: [],
                resourceDomains: [],
              },
            },
            "openai/widgetDescription":
              "__APP_TITLE__ starter widget rendered by the MCP server.",
          },
        },
      ],
    })
  );

  registerAppTool(
    server,
    "__TOOL_NAME__",
    {
      title: "__APP_TITLE__",
      description:
        "Use this when the user wants to render the __APP_TITLE__ starter widget or inspect a minimal Apps SDK tool result.",
      inputSchema: {
        message: z
          .string()
          .optional()
          .describe("Optional message to show inside the widget."),
      },
      annotations: {
        readOnlyHint: true,
        destructiveHint: false,
        openWorldHint: false,
        idempotentHint: true,
      },
      _meta: {
        ui: { resourceUri: WIDGET_URI },
        "openai/toolInvocation/invoking": "Loading __APP_TITLE__",
        "openai/toolInvocation/invoked": "__APP_TITLE__ ready",
      },
    },
    async ({ message }) => {
      const resolvedMessage =
        message?.trim() ||
        "This starter uses the MCP Apps bridge first, keeps follow-up messaging on ui/message, and limits window.openai to optional host signals.";

      return {
        content: [
          {
            type: "text" as const,
            text: "Rendered the __APP_TITLE__ starter widget.",
          },
        ],
        structuredContent: {
          headline: "__APP_TITLE__",
          message: resolvedMessage,
          source: "__TOOL_NAME__",
          themeHint:
            "Read window.openai.theme in the widget if you need ChatGPT theme information.",
        },
        _meta: {
          "openai/outputTemplate": WIDGET_URI,
        },
      };
    }
  );

  return server;
}

const port = Number(process.env.PORT ?? "__PORT__");
const MCP_PATH = "/mcp";

createServer(async (req, res) => {
  if (!req.url) {
    res.writeHead(400).end("Missing URL");
    return;
  }

  const url = new URL(req.url, "http://" + (req.headers.host ?? "localhost"));
  const isMcpRoute = url.pathname === MCP_PATH || url.pathname.startsWith(MCP_PATH + "/");

  if (req.method === "OPTIONS" && isMcpRoute) {
    res.writeHead(204, {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "POST, GET, DELETE, OPTIONS",
      "Access-Control-Allow-Headers": "content-type, mcp-session-id",
      "Access-Control-Expose-Headers": "Mcp-Session-Id",
    });
    res.end();
    return;
  }

  if (req.method === "GET" && url.pathname === "/") {
    res.writeHead(200, { "content-type": "text/plain" }).end("__APP_TITLE__ MCP server");
    return;
  }

  const transportMethods = new Set(["GET", "POST", "DELETE"]);
  if (isMcpRoute && req.method && transportMethods.has(req.method)) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id");

    const server = createAppServer();
    const transport = new StreamableHTTPServerTransport({
      sessionIdGenerator: undefined,
      enableJsonResponse: true,
    });

    res.on("close", () => {
      transport.close();
      server.close();
    });

    try {
      await server.connect(transport);
      await transport.handleRequest(req, res);
    } catch (error) {
      console.error("Failed to handle MCP request:", error);
      if (!res.headersSent) {
        res.writeHead(500).end("Internal server error");
      }
    }
    return;
  }

  res.writeHead(404).end("Not Found");
}).listen(port, () => {
  console.log("__APP_TITLE__ MCP server listening on http://localhost:" + port + MCP_PATH);
});
`;

function buildWidgetHtml(appSlug, appTitle, toolName) {
  return fillTemplate(WIDGET_TEMPLATE, {
    "__APP_SLUG__": appSlug,
    "__APP_TITLE__": appTitle,
    "__TOOL_NAME__": toolName,
  });
}

function buildServerTs(appSlug, appTitle, toolName, widgetUri, port) {
  return fillTemplate(SERVER_TEMPLATE, {
    "__APP_SLUG__": appSlug,
    "__APP_TITLE__": appTitle,
    "__TOOL_NAME__": toolName,
    "__WIDGET_URI__": widgetUri,
    "__PORT__": String(port),
  });
}

function usage() {
  return [
    "Generate a minimal Node + @modelcontextprotocol/ext-apps starter with a vanilla widget that uses the MCP Apps bridge by default.",
    "Prefer upstream examples first; use this scaffold as the fallback.",
    "",
    "Usage:",
    "  ./scripts/scaffold_node_ext_apps.mjs <output_dir> [--app-name <name>] [--tool-name <name>] [--port <number>] [--force]",
    "",
    "If the executable bit is unavailable, run:",
    "  node scripts/scaffold_node_ext_apps.mjs <output_dir> [--app-name <name>] [--tool-name <name>] [--port <number>] [--force]",
  ].join("\\n");
}

function parseArgs(argv) {
  const args = {
    outputDir: null,
    appName: "example-chatgpt-app",
    toolName: null,
    port: 8787,
    force: false,
  };

  const tokens = [...argv];
  while (tokens.length > 0) {
    const token = tokens.shift();

    if (!args.outputDir && !token.startsWith("--")) {
      args.outputDir = token;
      continue;
    }

    if (token === "--app-name") {
      args.appName = tokens.shift() ?? "";
      continue;
    }

    if (token === "--tool-name") {
      args.toolName = tokens.shift() ?? "";
      continue;
    }

    if (token === "--port") {
      const value = Number(tokens.shift());
      if (!Number.isInteger(value) || value <= 0) {
        throw new Error("Expected a positive integer after --port");
      }
      args.port = value;
      continue;
    }

    if (token === "--force") {
      args.force = true;
      continue;
    }

    if (token === "--help" || token === "-h") {
      console.log(usage());
      process.exit(0);
    }

    throw new Error(`Unknown argument: ${token}`);
  }

  if (!args.outputDir) {
    throw new Error(`Missing required output directory.\\n\\n${usage()}`);
  }

  return args;
}

function main() {
  const args = parseArgs(process.argv.slice(2));

  const appSlug = toSlug(args.appName);
  const toolName = toToolName(args.toolName || appSlug);
  const appTitle = toTitle(appSlug);
  const widgetUri = "ui://widget/main-v1.html";

  const outputDir = path.resolve(args.outputDir);
  ensureTargetDir(outputDir, args.force);

  const files = new Map([
    [path.join(outputDir, "package.json"), buildPackageJson(appSlug)],
    [path.join(outputDir, "tsconfig.json"), buildTsconfig()],
    [path.join(outputDir, "public", "widget.html"), buildWidgetHtml(appSlug, appTitle, toolName)],
    [path.join(outputDir, "src", "server.ts"), buildServerTs(appSlug, appTitle, toolName, widgetUri, args.port)],
  ]);

  for (const [filePath, content] of files) {
    writeFile(filePath, content);
  }

  console.log("Generated starter scaffold:");
  for (const filePath of files.keys()) {
    console.log(" -", path.relative(outputDir, filePath));
  }
}

try {
  main();
} catch (error) {
  console.error(error instanceof Error ? error.message : String(error));
  process.exit(1);
}


================================================
FILE: skills/.curated/cloudflare-deploy/LICENSE.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

   "License" shall mean the terms and conditions for use, reproduction,
   and distribution as defined by Sections 1 through 9 of this document.

   "Licensor" shall mean the copyright owner or entity authorized by
   the copyright owner that is granting the License.

   "Legal Entity" shall mean the union of the acting entity and all
   other entities that control, are controlled by, or are under common
   control with that entity. For the purposes of this definition,
   "control" means (i) the power, direct or indirect, to cause the
   direction or management of such entity, whether by contract or
   otherwise, or (ii) ownership of fifty percent (50%) or more of the
   outstanding shares, or (iii) beneficial ownership of such entity.

   "You" (or "Your") shall mean an individual or Legal Entity
   exercising permissions granted by this License.

   "Source" form shall mean the preferred form for making modifications,
   including but not limited to software source code, documentation
   source, and configuration files.

   "Object" form shall mean any form resulting from mechanical
   transformation or translation of a Source form, including but
   not limited to compiled object code, generated documentation,
   and conversions to other media types.

   "Work" shall mean the work of authorship, whether in Source or
   Object form, made available under the License, as indicated by a
   copyright notice that is included in or attached to the work
   (an example is provided in the Appendix below).

   "Derivative Works" shall mean any work, whether in Source or Object
   form, that is based on (or derived from) the Work and for which the
   editorial revisions, annotations, elaborations, or other modifications
   represent, as a whole, an original work of authorship. For the purposes
   of this License, Derivative Works shall not include works that remain
   separable from, or merely link (or bind by name) to the interfaces of,
   the Work and Derivative Works thereof.

   "Contribution" shall mean any work of authorship, including
   the original version of the Work and any modifications or additions
   to that Work or Derivative Works thereof, that is intentionally
   submitted to Licensor for inclusion in the Work by the copyright owner
   or by an individual or Legal Entity authorized to submit on behalf of
   the copyright owner. For the purposes of this definition, "submitted"
   means any form of electronic, verbal, or written communication sent
   to the Licensor or its representatives, including but not limited to
   communication on electronic mailing lists, source code control systems,
   and issue tracking systems that are managed by, or on behalf of, the
   Licensor for the purpose of discussing and improving the Work, but
   excluding communication that is conspicuously marked or otherwise
   designated in writing by the copyright owner as "Not a Contribution."

   "Contributor" shall mean Licensor and any individual or Legal Entity
   on behalf of whom a Contribution has been received by Licensor and
   subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   copyright license to reproduce, prepare Derivative Works of,
   publicly display, publicly perform, sublicense, and distribute the
   Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
   this License, each Contributor hereby grants to You a perpetual,
   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
   (except as stated in this section) patent license to make, have made,
   use, offer to sell, sell, import, and otherwise transfer the Work,
   where such license applies only to those patent claims licensable
   by such Contributor that are necessarily infringed by their
   Contribution(s) alone or by combination of their Contribution(s)
   with the Work to which such Contribution(s) was submitted. If You
   institute patent litigation against any entity (including a
   cross-claim or counterclaim in a lawsuit) alleging that the Work
   or a Contribution incorporated within the Work constitutes direct
   or contributory patent infringement, then any patent licenses
   granted to You under this License for that Work shall terminate
   as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
   Work or Derivative Works thereof in any medium, with or without
   modifications, and in Source or Object form, provided that You
   meet the following conditions:

   (a) You must give any other recipients of the Work or
       Derivative Works a copy of this License; and

   (b) You must cause any modified files to carry prominent notices
       stating that You changed the files; and

   (c) You must retain, in the Source form of any Derivative Works
       that You distribute, all copyright, patent, trademark, and
       attribution notices from the Source form of the Work,
       excluding those notices that do not pertain to any part of
       the Derivative Works; and

   (d) If the Work includes a "NOTICE" text file as part of its
       distribution, then any Derivative Works that You distribute must
       include a readable copy of the attribution notices contained
       within such NOTICE file, excluding those notices that do not
       pertain to any part of the Derivative Works, in at least one
       of the following places: within a NOTICE text file distributed
       as part of the Derivative Works; within the Source form or
       documentation, if provided along with the Derivative Works; or,
       within a display generated by the Derivative Works, if and
       wherever such third-party notices normally appear. The contents
       of the NOTICE file are for informational purposes only and
       do not modify the License. You may add Your own attribution
       notices within Derivative Works that You distribute, alongside
       or as an addendum to the NOTICE text from the Work, provided
       that such additional attribution notices cannot be construed
       as modifying the License.

   You may add Your own copyright statement to Your modifications and
   may provide additional or different license terms and conditions
   for use, reproduction, or distribution of Your modifications, or
   for any such Derivative Works as a whole, provided Your use,
   reproduction, and distribution of the Work otherwise complies with
   the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
   any Contribution intentionally submitted for inclusion in the Work
   by You to the Licensor shall be under the terms and conditions of
   this License, without any additional terms or conditions.
   Notwithstanding the above, nothing herein shall supersede or modify
   the terms of any separate license agreement you may have executed
   with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
   names, trademarks, service marks, or product names of the Licensor,
   except as required for reasonable and customary use in describing the
   origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
   agreed to in writing, Licensor provides the Work (and each
   Contributor provides its Contributions) on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied, including, without limitation, any warranties or conditions
   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
   PARTICULAR PURPOSE. You are solely responsible for determining the
   appropriateness of using or redistributing the Work and assume any
   risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
   whether in tort (including negligence), contract, or otherwise,
   unless required by applicable law (such as deliberate and grossly
   negligent acts) or agreed to in writing, shall any Contributor be
   liable to You for damages, including any direct, indirect, special,
   incidental, or consequential damages of any character arising as a
   result of this License or out of the use or inability to use the
   Work (including but not limited to damages for loss of goodwill,
   work stoppage, computer failure or malfunction, or any and all
   other commercial damages or losses), even if such Contributor
   has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
   the Work or Derivative Works thereof, You may choose to offer,
   and charge a fee for, acceptance of support, warranty, indemnity,
   or other liability obligations and/or rights consistent with this
   License. However, in accepting such obligations, You may act only
   on Your own behalf and on Your sole responsibility, not on behalf of
   any other Contributor, and only if You agree to indemnify,
   defend, and hold each Contributor harmless for any liability
   incurred by, or claims asserted against, such Contributor by reason
   of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

   To apply the Apache License to your work, attach the following
   boilerplate notice, with the fields enclosed by brackets "[]"
   replaced with your own identifying information. (Don\'t include
   the brackets!)  The text should be enclosed in the appropriate
   comment syntax for the file format. We also recommend that a
   file or class name and description of purpose be included on the
   same "printed page" as the copyright notice for easier
   identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


================================================
FILE: skills/.curated/cloudflare-deploy/SKILL.md
================================================
---
name: cloudflare-deploy
description: Deploy applications and infrastructure to Cloudflare using Workers, Pages, and related platform services. Use when the user asks to deploy, host, publish, or set up a project on Cloudflare.
---

# Cloudflare Deploy

Consolidated skill for building on the Cloudflare platform. Use decision trees below to find the right product, then load detailed references.

## Prerequisites

- When sandboxing blocks the deployment network calls, rerun with `sandbox_permissions=require_escalated`.
- The deployment might take a few minutes. Use appropriate timeout values.

## Authentication (Required Before Deploy)

Verify auth before `wrangler deploy`, `wrangler pages deploy`, or `npm run deploy`:

```bash
npx wrangler whoami    # Shows account if authenticated
```

Not authenticated? → `references/wrangler/auth.md`
- Interactive/local: `wrangler login` (one-time OAuth)
- CI/CD: Set `CLOUDFLARE_API_TOKEN` env var

## Quick Decision Trees

### "I need to run code"

```
Need to run code?
├─ Serverless functions at the edge → workers/
├─ Full-stack web app with Git deploys → pages/
├─ Stateful coordination/real-time → durable-objects/
├─ Long-running multi-step jobs → workflows/
├─ Run containers → containers/
├─ Multi-tenant (customers deploy code) → workers-for-platforms/
├─ Scheduled tasks (cron) → cron-triggers/
├─ Lightweight edge logic (modify HTTP) → snippets/
├─ Process Worker execution events (logs/observability) → tail-workers/
└─ Optimize latency to backend infrastructure → smart-placement/
```

### "I need to store data"

```
Need storage?
├─ Key-value (config, sessions, cache) → kv/
├─ Relational SQL → d1/ (SQLite) or hyperdrive/ (existing Postgres/MySQL)
├─ Object/file storage (S3-compatible) → r2/
├─ Message queue (async processing) → queues/
├─ Vector embeddings (AI/semantic search) → vectorize/
├─ Strongly-consistent per-entity state → durable-objects/ (DO storage)
├─ Secrets management → secrets-store/
├─ Streaming ETL to R2 → pipelines/
└─ Persistent cache (long-term retention) → cache-reserve/
```

### "I need AI/ML"

```
Need AI?
├─ Run inference (LLMs, embeddings, images) → workers-ai/
├─ Vector database for RAG/search → vectorize/
├─ Build stateful AI agents → agents-sdk/
├─ Gateway for any AI provider (caching, routing) → ai-gateway/
└─ AI-powered search widget → ai-search/
```

### "I need networking/connectivity"

```
Need networking?
├─ Expose local service to internet → tunnel/
├─ TCP/UDP proxy (non-HTTP) → spectrum/
├─ WebRTC TURN server → turn/
├─ Private network connectivity → network-interconnect/
├─ Optimize routing → argo-smart-routing/
├─ Optimize latency to backend (not user) → smart-placement/
└─ Real-time video/audio → realtimekit/ or realtime-sfu/
```

### "I need security"

```
Need security?
├─ Web Application Firewall → waf/
├─ DDoS protection → ddos/
├─ Bot detection/management → bot-management/
├─ API protection → api-shield/
├─ CAPTCHA alternative → turnstile/
└─ Credential leak detection → waf/ (managed ruleset)
```

### "I need media/content"

```
Need media?
├─ Image optimization/transformation → images/
├─ Video streaming/encoding → stream/
├─ Browser automation/screenshots → browser-rendering/
└─ Third-party script management → zaraz/
```

### "I need infrastructure-as-code"

```
Need IaC? → pulumi/ (Pulumi), terraform/ (Terraform), or api/ (REST API)
```

## Product Index

### Compute & Runtime
| Product | Reference |
|---------|-----------|
| Workers | `references/workers/` |
| Pages | `references/pages/` |
| Pages Functions | `references/pages-functions/` |
| Durable Objects | `references/durable-objects/` |
| Workflows | `references/workflows/` |
| Containers | `references/containers/` |
| Workers for Platforms | `references/workers-for-platforms/` |
| Cron Triggers | `references/cron-triggers/` |
| Tail Workers | `references/tail-workers/` |
| Snippets | `references/snippets/` |
| Smart Placement | `references/smart-placement/` |

### Storage & Data
| Product | Reference |
|---------|-----------|
| KV | `references/kv/` |
| D1 | `references/d1/` |
| R2 | `references/r2/` |
| Queues | `references/queues/` |
| Hyperdrive | `references/hyperdrive/` |
| DO Storage | `references/do-storage/` |
| Secrets Store | `references/secrets-store/` |
| Pipelines | `references/pipelines/` |
| R2 Data Catalog | `references/r2-data-catalog/` |
| R2 SQL | `references/r2-sql/` |

### AI & Machine Learning
| Product | Reference |
|---------|-----------|
| Workers AI | `references/workers-ai/` |
| Vectorize | `references/vectorize/` |
| Agents SDK | `references/agents-sdk/` |
| AI Gateway | `references/ai-gateway/` |
| AI Search | `references/ai-search/` |

### Networking & Connectivity
| Product | Reference |
|---------|-----------|
| Tunnel | `references/tunnel/` |
| Spectrum | `references/spectrum/` |
| TURN | `references/turn/` |
| Network Interconnect | `references/network-interconnect/` |
| Argo Smart Routing | `references/argo-smart-routing/` |
| Workers VPC | `references/workers-vpc/` |

### Security
| Product | Reference |
|---------|-----------|
| WAF | `references/waf/` |
| DDoS Protection | `references/ddos/` |
| Bot Management | `references/bot-management/` |
| API Shield | `references/api-shield/` |
| Turnstile | `references/turnstile/` |

### Media & Content
| Product | Reference |
|---------|-----------|
| Images | `references/images/` |
| Stream | `references/stream/` |
| Browser Rendering | `references/browser-rendering/` |
| Zaraz | `references/zaraz/` |

### Real-Time Communication
| Product | Reference |
|---------|-----------|
| RealtimeKit | `references/realtimekit/` |
| Realtime SFU | `references/realtime-sfu/` |

### Developer Tools
| Product | Reference |
|---------|-----------|
| Wrangler | `references/wrangler/` |
| Miniflare | `references/miniflare/` |
| C3 | `references/c3/` |
| Observability | `references/observability/` |
| Analytics Engine | `references/analytics-engine/` |
| Web Analytics | `references/web-analytics/` |
| Sandbox | `references/sandbox/` |
| Workerd | `references/workerd/` |
| Workers Playground | `references/workers-playground/` |

### Infrastructure as Code
| Product | Reference |
|---------|-----------|
| Pulumi | `references/pulumi/` |
| Terraform | `references/terraform/` |
| API | `references/api/` |

### Other Services
| Product | Reference |
|---------|-----------|
| Email Routing | `references/email-routing/` |
| Email Workers | `references/email-workers/` |
| Static Assets | `references/static-assets/` |
| Bindings | `references/bindings/` |
| Cache Reserve | `references/cache-reserve/` |

## Troubleshooting

### Escalated Network Access

If deployment fails due to network issues (timeouts, DNS errors, connection resets), rerun the deploy with escalated permissions (use `sandbox_permissions=require_escalated`). The deploy requires escalated network access when sandbox networking blocks outbound requests.

Example guidance to the user:

```
The deploy needs escalated network access to deploy to Cloudflare. I can rerun the command with escalated permissions—want me to proceed?
```


================================================
FILE: skills/.curated/cloudflare-deploy/agents/openai.yaml
================================================
interface:
  display_name: "Cloudflare Deploy"
  short_description: "Deploy Workers, Pages, and platform services on Cloudflare"
  icon_small: "./assets/cloudflare-small.svg"
  icon_large: "./assets/cloudflare.png"
  default_prompt: "Deploy this app to Cloudflare (Workers or Pages) and return URL, config, and required env vars."


================================================
FILE: skills/.curated/cloudflare-deploy/references/agents-sdk/README.md
================================================
# Cloudflare Agents SDK

Cloudflare Agents SDK enables building AI-powered agents on Durable Objects with state, WebSockets, SQL, scheduling, and AI integration.

## Core Value
Build stateful, globally distributed AI agents with persistent memory, real-time connections, scheduled tasks, and async workflows.

## When to Use
- Persistent state + memory required
- Real-time WebSocket connections
- Long-running workflows (minutes/hours)
- Chat interfaces with AI models
- Scheduled/recurring tasks with state
- DB queries with agent state

## What Type of Agent?

| Use Case | Class | Key Features |
|----------|-------|--------------|
| AI chat interface | `AIChatAgent` | Auto-streaming, tools, message history, resumable |
| MCP tool provider | `Agent` + MCP | Expose tools to AI systems |
| Custom logic/routing | `Agent` | Full control, WebSockets, email, SQL |
| Real-time collaboration | `Agent` | WebSocket state, broadcasts |
| Email processing | `Agent` | `onEmail()` handler |

## Quick Start

**AI Chat Agent:**
```typescript
import { AIChatAgent } from "agents";
import { openai } from "@ai-sdk/openai";

export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    return this.streamText({
      model: openai("gpt-4"),
      messages: this.messages,
      onFinish,
    });
  }
}
```

**Base Agent:**
```typescript
import { Agent } from "agents";

export class MyAgent extends Agent<Env> {
  onStart() {
    this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY)`;
  }
  
  async onRequest(request: Request) {
    return Response.json({ state: this.state });
  }
}
```

## Reading Order

| Task | Files to Read |
|------|---------------|
| Quick start | README only |
| Build chat agent | README → api.md (AIChatAgent) → patterns.md |
| Setup project | README → configuration.md |
| Add React frontend | README → api.md (Client Hooks) → patterns.md |
| Build MCP server | api.md (MCP) → patterns.md |
| Background tasks | api.md (Scheduling, Task Queue) → patterns.md |
| Debug issues | gotchas.md |

## Package Entry Points

| Import | Purpose |
|--------|---------|
| `agents` | Server-side Agent classes, lifecycle |
| `agents/react` | `useAgent()` hook for WebSocket connections |
| `agents/ai-react` | `useAgentChat()` hook for AI chat UIs |

## In This Reference
- [configuration.md](./configuration.md) - SDK setup, wrangler config, routing
- [api.md](./api.md) - Agent classes, lifecycle, client hooks
- [patterns.md](./patterns.md) - Common workflows, best practices
- [gotchas.md](./gotchas.md) - Common issues, limits

## See Also
- durable-objects - Agent infrastructure
- d1 - External database integration
- workers-ai - AI model integration
- vectorize - Vector search for RAG patterns

================================================
FILE: skills/.curated/cloudflare-deploy/references/agents-sdk/api.md
================================================
# API Reference

## Agent Classes

### AIChatAgent

For AI chat with auto-streaming, message history, tools, resumable streaming.

```ts
import { AIChatAgent } from "agents";
import { openai } from "@ai-sdk/openai";

export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    return this.streamText({
      model: openai("gpt-4"),
      messages: this.messages, // Auto-managed message history
      tools: {
        getWeather: {
          description: "Get weather",
          parameters: z.object({ city: z.string() }),
          execute: async ({ city }) => `Sunny, 72°F in ${city}`
        }
      },
      onFinish, // Persist response to this.messages
    });
  }
}
```

### Agent (Base Class)

Full control for custom logic, WebSockets, email, and SQL.

```ts
import { Agent } from "agents";

export class MyAgent extends Agent<Env, State> {
  // Lifecycle methods below
}
```

**Type params:** `Agent<Env, State, ConnState>` - Env bindings, agent state, connection state

## Lifecycle Hooks

```ts
onStart() { // Init/restart
  this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT, name TEXT)`;
}

async onRequest(req: Request) { // HTTP
  const {pathname} = new URL(req.url);
  if (pathname === "/users") return Response.json(this.sql<{id,name}>`SELECT * FROM users`);
  return new Response("Not found", {status: 404});
}

async onConnect(conn: Connection<ConnState>, ctx: ConnectionContext) { // WebSocket
  conn.accept();
  conn.setState({userId: ctx.request.headers.get("X-User-ID")});
  conn.send(JSON.stringify({type: "connected", state: this.state}));
}

async onMessage(conn: Connection<ConnState>, msg: WSMessage) { // WS messages
  const m = JSON.parse(msg as string);
  this.setState({messages: [...this.state.messages, m]});
  this.connections.forEach(c => c.send(JSON.stringify(m)));
}

async onEmail(email: AgentEmail) { // Email routing
  this.sql`INSERT INTO emails (from_addr,subject,body) VALUES (${email.from},${email.headers.get("subject")},${await email.text()})`;
}
```

## State, SQL, Scheduling

```ts
// State
this.setState({count: 42}); // Auto-syncs
this.setState({...this.state, count: this.state.count + 1});

// SQL (parameterized queries prevent injection)
this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, name TEXT)`;
this.sql`INSERT INTO users (id,name) VALUES (${userId},${name})`;
const users = this.sql<{id,name}>`SELECT * FROM users WHERE id = ${userId}`;

// Scheduling
await this.schedule(new Date("2026-12-25"), "sendGreeting", {msg:"Hi"}); // Date
await this.schedule(60, "checkStatus", {}); // Delay (sec)
await this.schedule("0 0 * * *", "dailyCleanup", {}); // Cron
await this.cancelSchedule(scheduleId);
```

## RPC Methods (@callable)

```ts
import { Agent, callable } from "agents";

export class MyAgent extends Agent<Env> {
  @callable()
  async processTask(input: {text: string}): Promise<{result: string}> {
    return { result: await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt: input.text}) };
  }
}
// Client: const result = await agent.processTask({ text: "Hello" });
// Must return JSON-serializable values
```

## Connections & AI

```ts
// Connections (type: Agent<Env, State, ConnState>)
this.connections.forEach(c => c.send(JSON.stringify(msg))); // Broadcast
conn.setState({userId:"123"}); conn.close(1000, "Goodbye");

// Workers AI
const r = await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt});

// Manual streaming (prefer AIChatAgent)
const stream = await client.chat.completions.create({model: "gpt-4", messages, stream: true});
for await (const chunk of stream) conn.send(JSON.stringify({chunk: chunk.choices[0].delta.content}));
```

**Type-safe state:** `Agent<Env, State, ConnState>` - third param types `conn.state`

## MCP Integration

Model Context Protocol for exposing tools:

```ts
// Register & use MCP server
await this.mcp.registerServer("github", {
  url: env.MCP_SERVER_URL,
  auth: { type: "oauth", clientId: env.GITHUB_CLIENT_ID, clientSecret: env.GITHUB_CLIENT_SECRET }
});
const tools = await this.mcp.getAITools(["github"]);
return this.streamText({ model: openai("gpt-4"), messages: this.messages, tools, onFinish });
```

## Task Queue

```ts
await this.queue("processVideo", { videoId: "abc123" }); // Add task
const tasks = await this.dequeue(10); // Process up to 10
```

## Context & Cleanup

```ts
const agent = getCurrentAgent<MyAgent>(); // Get current instance
async destroy() { /* cleanup before agent destroyed */ }
```

## AI Integration

```ts
// Workers AI
const r = await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt});

// Manual streaming (prefer AIChatAgent for auto-streaming)
const stream = await client.chat.completions.create({model: "gpt-4", messages, stream: true});
for await (const chunk of stream) {
  if (chunk.choices[0]?.delta?.content) conn.send(JSON.stringify({chunk: chunk.choices[0].delta.content}));
}
```

## Client Hooks (React)

```ts
// useAgent() - WebSocket connection + RPC
import { useAgent } from "agents/react";
const agent = useAgent({ agent: "MyAgent", name: "user-123" }); // name for idFromName
const result = await agent.processTask({ text: "Hello" }); // Call @callable methods
// agent.readyState: 0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED

// useAgentChat() - AI chat UI
import { useAgentChat } from "agents/ai-react";
const agent = useAgent({ agent: "ChatAgent" });
const { messages, input, handleInputChange, handleSubmit, isLoading, stop, clearHistory } = 
  useAgentChat({ 
    agent, 
    maxSteps: 5,        // Max tool iterations
    resume: true,       // Auto-resume on disconnect
    onToolCall: async (toolCall) => {
      // Client tools (human-in-the-loop)
      if (toolCall.toolName === "confirm") return { ok: window.confirm("Proceed?") };
    }
  });
// status: "ready" | "submitted" | "streaming" | "error"
```


================================================
FILE: skills/.curated/cloudflare-deploy/references/agents-sdk/configuration.md
================================================
# Configuration

## Wrangler Setup

```jsonc
{
  "name": "my-agents-app",
  "durable_objects": {
    "bindings": [
      {"name": "MyAgent", "class_name": "MyAgent"}
    ]
  },
  "migrations": [
    {"tag": "v1", "new_sqlite_classes": ["MyAgent"]}
  ],
  "ai": {
    "binding": "AI"
  }
}
```

## Environment Bindings

**Type-safe pattern:**

```typescript
interface Env {
  AI?: Ai;                              // Workers AI
  MyAgent?: DurableObjectNamespace<MyAgent>;
  ChatAgent?: DurableObjectNamespace<ChatAgent>;
  DB?: D1Database;                      // D1 database
  KV?: KVNamespace;                     // KV storage
  R2?: R2Bucket;                        // R2 bucket
  OPENAI_API_KEY?: string;              // Secrets
  GITHUB_CLIENT_ID?: string;            // MCP OAuth credentials
  GITHUB_CLIENT_SECRET?: string;
  QUEUE?: Queue;                        // Queues
}
```

**Best practice:** Define all DO bindings in Env interface for type safety.

## Deployment

```bash
# Local dev
npx wrangler dev

# Deploy production
npx wrangler deploy

# Set secrets
npx wrangler secret put OPENAI_API_KEY
```

## Agent Routing

**Recommended: Use route helpers**

```typescript
import { routeAgent } from "agents";

export default {
  fetch(request: Request, env: Env) {
    return routeAgent(request, env);
  }
}
```

Helper routes requests to agents automatically based on URL patterns.

**Manual routing (advanced):**

```typescript
export default {
  async fetch(request: Request, env: Env) {
    const url = new URL(request.url);
    
    // Named ID (deterministic)
    const id = env.MyAgent.idFromName("user-123");
    
    // Random ID (from URL param)
    // const id = env.MyAgent.idFromString(url.searchParams.get("id"));
    
    const stub = env.MyAgent.get(id);
    return stub.fetch(request);
  }
}
```

**Multi-agent setup:**

```typescript
import { routeAgent } from "agents";

export default {
  fetch(request: Request, env: Env) {
    const url = new URL(request.url);
    
    // Route by path
    if (url.pathname.startsWith("/chat")) {
      return routeAgent(request, env, "ChatAgent");
    }
    if (url.pathname.startsWith("/task")) {
      return routeAgent(request, env, "TaskAgent");
    }
    
    return new Response("Not found", { status: 404 });
  }
}
```

## Email Routing

**Code setup:**

```typescript
import { routeAgentEmail } from "agents";

export default {
  fetch: (req: Request, env: Env) => routeAgent(req, env),
  email: (message: ForwardableEmailMessage, env: Env) => {
    return routeAgentEmail(message, env);
  }
}
```

**Dashboard setup:**

Configure email routing in Cloudflare dashboard:

```
Destination: Workers with Durable Objects
Worker: my-agents-app
```

Then handle in agent:

```typescript
export class EmailAgent extends Agent<Env> {
  async onEmail(email: AgentEmail) {
    const text = await email.text();
    // Process email
  }
}
```

## AI Gateway (Optional)

```typescript
// Enable caching/routing through AI Gateway
const response = await this.env.AI.run(
  "@cf/meta/llama-3.1-8b-instruct",
  { prompt },
  {
    gateway: {
      id: "my-gateway-id",
      skipCache: false,
      cacheTtl: 3600
    }
  }
);
```

## MCP Configuration (Optional)

For exposing tools via Model Context Protocol:

```typescript
// wrangler.jsonc - Add MCP OAuth secrets
{
  "vars": {
    "MCP_SERVER_URL": "https://mcp.example.com"
  }
}

// Set secrets via CLI
// npx wrangler secret put GITHUB_CLIENT_ID
// npx wrangler secret put GITHUB_CLIENT_SECRET
```

Then register in agent code (see api.md MCP section).


================================================
FILE: skills/.curated/cloudflare-deploy/references/agents-sdk/gotchas.md
================================================
# Gotchas & Best Practices

## Common Errors

### "setState() not syncing"

**Cause:** Mutating state directly or not calling `setState()` after modifications  
**Solution:** Always use `setState()` with immutable updates:
```ts
// ❌ this.state.count++
// ✅ this.setState({...this.state, count: this.state.count + 1})
```

### "Message history grows unbounded (AIChatAgent)"

**Cause:** `this.messages` in `AIChatAgent` accumulates all messages indefinitely  
**Solution:** Manually trim old messages periodically:
```ts
export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    // Keep only last 50 messages
    if (this.messages.length > 50) {
      this.messages = this.messages.slice(-50);
    }
    
    return this.streamText({ model: openai("gpt-4"), messages: this.messages, onFinish });
  }
}
```

### "SQL injection vulnerability"

**Cause:** Direct string interpolation in SQL queries
**Solution:** Use parameterized queries:
```ts
// ❌ this.sql`...WHERE id = '${userId}'`
// ✅ this.sql`...WHERE id = ${userId}`
```

### "WebSocket connection timeout"

**Cause:** Not calling `conn.accept()` in `onConnect`
**Solution:** Always accept connections:
```ts
async onConnect(conn: Connection, ctx: ConnectionContext) { conn.accept(); conn.setState({userId: "123"}); }
```

### "Schedule limit exceeded"

**Cause:** More than 1000 scheduled tasks per agent
**Solution:** Clean up old schedules and limit creation rate:
```ts
async checkSchedules() { if ((await this.getSchedules()).length > 800) console.warn("Near limit!"); }
```

### "AI Gateway unavailable"

**Cause:** AI service timeout or quota exceeded  
**Solution:** Add error handling and fallbacks:
```ts
try { 
  return await this.env.AI.run(model, {prompt}); 
} catch (e) { 
  console.error("AI error:", e);
  return {error: "Unavailable"}; 
}
```

### "@callable method returns undefined"

**Cause:** Method doesn't return JSON-serializable value, or has non-serializable types  
**Solution:** Ensure return values are plain objects/arrays/primitives:
```ts
// ❌ Returns class instance
@callable()
async getData() { return new Date(); }

// ✅ Returns serializable object
@callable()
async getData() { return { timestamp: Date.now() }; }
```

### "Resumable stream not resuming"

**Cause:** Stream ID must be deterministic for resumption to work  
**Solution:** Use AIChatAgent (automatic) or ensure consistent stream IDs:
```ts
// AIChatAgent handles this automatically
export class ChatAgent extends AIChatAgent<Env> {
  // Resumption works out of the box
}
```

### "MCP connection loss on hibernation"

**Cause:** MCP server connections don't survive hibernation  
**Solution:** Re-register servers in `onStart()` or check connection status:
```ts
onStart() {
  // Re-register MCP servers after hibernation
  await this.mcp.registerServer("github", { url: env.MCP_URL, auth: {...} });
}
```

### "Agent not found"

**Cause:** Durable Object binding missing or incorrect class name  
**Solution:** Verify DO binding in wrangler.jsonc and class name matches

## Rate Limits & Quotas

| Resource/Limit | Value | Notes |
|----------------|-------|-------|
| CPU per request | 30s (std), 300s (max) | Set in wrangler.jsonc |
| Memory per instance | 128MB | Shared with WebSockets |
| Storage per agent | 10GB | SQLite storage |
| Scheduled tasks | 1000 per agent | Monitor with `getSchedules()` |
| WebSocket connections | Unlimited | Within memory limits |
| SQL columns | 100 | Per table |
| SQL row size | 2MB | Key + value |
| WebSocket message | 32MiB | Max size |
| DO requests/sec | ~1000 | Per unique DO instance; rate limit if needed |
| AI Gateway (Workers AI) | Model-specific | Check dashboard for limits |
| MCP requests | Depends on server | Implement retry/backoff |

## Best Practices

### State Management
- Use immutable updates: `setState({...this.state, key: newValue})`
- Trim unbounded arrays (messages, logs) periodically
- Store large data in SQL, not state

### SQL Usage
- Create tables in `onStart()`, not `onRequest()`
- Use parameterized queries: `` sql`WHERE id = ${id}` `` (NOT `` sql`WHERE id = '${id}'` ``)
- Index frequently queried columns

### Scheduling
- Monitor schedule count: `await this.getSchedules()`
- Cancel completed tasks to stay under 1000 limit
- Use cron strings for recurring tasks

### WebSockets
- Always call `conn.accept()` in `onConnect()`
- Handle client disconnects gracefully
- Broadcast to `this.connections` efficiently

### AI Integration
- Use `AIChatAgent` for chat interfaces (auto-streaming, resumption)
- Trim message history to avoid token limits
- Handle AI errors with try/catch and fallbacks

### Production Deployment
- **Rate limiting:** Implement request throttling for high-traffic agents (>1000 req/s)
- **Monitoring:** Log critical errors, track schedule count, monitor storage usage
- **Graceful degradation:** Handle AI service outages with fallbacks
- **Message trimming:** Enforce max history length (e.g., 100 messages) in AIChatAgent
- **MCP reliability:** Re-register servers on hibernation, implement retry logic


================================================
FILE: skills/.curated/cloudflare-deploy/references/agents-sdk/patterns.md
================================================
# Patterns & Use Cases

## AI Chat w/Tools

**Server (AIChatAgent):**

```ts
import { AIChatAgent } from "agents";
import { openai } from "@ai-sdk/openai";
import { tool } from "ai";
import { z } from "zod";

export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    return this.streamText({
      model: openai("gpt-4"),
      messages: this.messages, // Auto-managed
      tools: {
        getWeather: tool({
          description: "Get current weather",
          parameters: z.object({ city: z.string() }),
          execute: async ({ city }) => `Weather in ${city}: Sunny, 72°F`
        }),
        searchDocs: tool({
          description: "Search documentation",
          parameters: z.object({ query: z.string() }),
          execute: async ({ query }) => JSON.stringify(
            this.sql<{title, content}>`SELECT title, content FROM docs WHERE content LIKE ${'%' + query + '%'}`
          )
        })
      },
      onFinish,
    });
  }
}
```

**Client (React):**

```tsx
import { useAgent } from "agents/react";
import { useAgentChat } from "agents/ai-react";

function ChatUI() {
  const agent = useAgent({ agent: "ChatAgent" });
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useAgentChat({ agent });
  
  return (
    <div>
      {messages.map(m => <div key={m.id}>{m.role}: {m.content}</div>)}
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} disabled={isLoading} />
        <button disabled={isLoading}>Send</button>
      </form>
    </div>
  );
}
```

## Human-in-the-Loop (Client Tools)

Server defines tool, client executes:

```ts
// Server
export class ChatAgent extends AIChatAgent<Env> {
  async onChatMessage(onFinish) {
    return this.streamText({
      model: openai("gpt-4"),
      messages: this.messages,
      tools: {
        confirmAction: tool({
          description: "Ask user to confirm",
          parameters: z.object({ action: z.string() }),
          execute: "client", // Client-side execution
        })
      },
      onFinish,
    });
  }
}

// Client
const { messages } = useAgentChat({
  agent,
  onToolCall: async (toolCall) => {
    if (toolCall.toolName === "confirmAction") {
      return { confirmed: window.confirm(`Confirm: ${toolCall.args.action}?`) };
    }
  }
});
```

## Task Queue & Scheduled Processing

```ts
export class TaskAgent extends Agent<Env> {
  onStart() { 
    this.schedule("*/5 * * * *", "processQueue", {}); // Every 5 min
    this.schedule("0 0 * * *", "dailyCleanup", {}); // Daily
  }
  
  async onRequest(req: Request) {
    await this.queue("processVideo", { videoId: (await req.json()).videoId });
    return Response.json({ queued: true });
  }
  
  async processQueue() {
    const tasks = await this.dequeue(10);
    for (const task of tasks) {
      if (task.name === "processVideo") await this.processVideo(task.data.videoId);
    }
  }
  
  async dailyCleanup() {
    this.sql`DELETE FROM logs WHERE created_at < ${Date.now() - 86400000}`;
  }
}
```

## Manual WebSocket Chat

Custom protocols (non-AI):

```ts
export class ChatAgent extends Agent<Env> {
  async onConnect(conn: Connection, ctx: ConnectionContext) {
    conn.accept();
    conn.setState({userId: ctx.request.headers.get("X-User-ID") || "anon"});
    conn.send(JSON.stringify({type: "history", messages: this.state.messages}));
  }
  
  async onMessage(conn: Connection, msg: WSMessage) {
    const newMsg = {userId: conn.state.userId, text: JSON.parse(msg as string).text, timestamp: Date.now()};
    this.setState({messages: [...this.state.messages, newMsg]});
    this.connections.forEach(c => c.send(JSON.stringify(newMsg)));
  }
}
```

## Email Processing w/AI

```ts
export class EmailAgent extends Agent<Env> {
  async onEmail(email: AgentEmail) {
    const [text, from, subject] = [await email.text(), email.from, email.headers.get("subject") || ""];
    this.sql`INSERT INTO emails (from_addr, subject, body) VALUES (${from}, ${subject}, ${text})`;
    
    const { text: summary } = await generateText({
      model: openai("gpt-4o-mini"), prompt: `Summarize: ${subject}\n\n${text}`
    });
    
    this.connections.forEach(c => c.send(JSON.stringify({type: "new_email", from, summary})));
    if (summary.includes("urgent")) await this.schedule(0, "sendAutoReply", { to: from });
  }
}
```

## Real-time Collaboration

```ts
export class GameAgent extends Agent<Env> {
  initialState = { players: [], gameStarted: false };
  
  async onConnect(conn: Connection, ctx: ConnectionContext) {
    conn.accept();
    const playerId = ctx.request.headers.get("X-Player-ID") || crypto.randomUUID();
    conn.setState({ playerId });
    
    const newPlayer = { id: playerId, score: 0 };
    this.setState({...this.state, players: [...this.state.players, newPlayer]});
    this.connections.forEach(c => c.send(JSON.stringify({type: "player_joined", player: newPlayer})));
  }
  
  async onMessage(conn: Connection, msg: WSMessage) {
    const m = JSON.parse(msg as string);
    
    if (m.type === "move") {
      this.setState({
        ...this.state,
        players: this.state.players.map(p => p.id === conn.state.playerId ? {...p, score: p.score + m.points} : p)
      });
      this.connections.forEach(c => c.send(JSON.stringify({type: "player_moved", playerId: conn.state.playerId})));
    }
    
    if (m.type === "start" && this.state.players.length >= 2) {
      this.setState({...this.state, gameStarted: true});
      this.connections.forEach(c => c.send(JSON.stringify({type: "game_started"})));
    }
  }
}
```


================================================
FILE: skills/.curated/cloudflare-deploy/references/ai-gateway/README.md
================================================
# Cloudflare AI Gateway

Expert guidance for implementing Cloudflare AI Gateway - a universal gateway for AI model providers with analytics, caching, rate limiting, and routing capabilities.

## When to Use This Reference

- Setting up AI Gateway for any AI provider (OpenAI, Anthropic, Workers AI, etc.)
- Implementing caching, rate limiting, or request retry/fallback
- Configuring dynamic routing with A/B testing or model fallbacks
- Managing provider API keys securely with BYOK
- Adding security features (guardrails, DLP)
- Setting up observability with logging and custom metadata
- Debugging AI Gateway requests or optimizing configurations

## Quick Start

**What's your setup?**

- **Using Vercel AI SDK** → Pattern 1 (recommended) - see [sdk-integration.md](./sdk-integration.md)
- **Using OpenAI SDK** → Pattern 2 - see [sdk-integration.md](./sdk-integration.md)
- **Cloudflare Worker + Workers AI** → Pattern 3 - see [sdk-integration.md](./sdk-integration.md)
- **Direct HTTP (any language)** → Pattern 4 - see [configuration.md](./configuration.md)
- **Framework (LangChain, etc.)** → See [sdk-integration.md](./sdk-integration.md)

## Pattern 1: Vercel AI SDK (Recommended)

Most modern pattern using official `ai-gateway-provider` package with automatic fallbacks.

```typescript
import { createAiGateway } from 'ai-gateway-provider';
import { createOpenAI } from '@ai-sdk/openai';
import { generateText } from 'ai';

const gateway = createAiGateway({
  accountId: process.env.CF_ACCOUNT_ID,
  gateway: process.env.CF_GATEWAY_ID,
});

const openai = createOpenAI({ 
  apiKey: process.env.OPENAI_API_KEY 
});

// Single model
const { text } = await generateText({
  model: gateway(openai('gpt-4o')),
  prompt: 'Hello'
});

// Automatic fallback array
const { text } = await generateText({
  model: gateway([
    openai('gpt-4o'),              // Try first
    anthropic('claude-sonnet-4-5'), // Fallback
  ]),
  prompt: 'Hello'
});
```

**Install:** `npm install ai-gateway-provider ai @ai-sdk/openai @ai-sdk/anthropic`

## Pattern 2: OpenAI SDK

Drop-in replacement for OpenAI API with multi-provider support.

```typescript
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/compat`,
  defaultHeaders: {
    'cf-aig-authorization': `Bearer ${cfToken}` // For authenticated gateways
  }
});

// Switch providers by changing model format: {provider}/{model}
const response = await client.chat.completions.create({
  model: 'openai/gpt-4o', // or 'anthropic/claude-sonnet-4-5'
  messages: [{ role: 'user', content: 'Hello!' }]
});
```

## Pattern 3: Workers AI Binding

For Cloudflare Workers using Workers AI.

```typescript
export default {
  async fetch(request, env, ctx) {
    const response = await env.AI.run(
      '@cf/meta/llama-3-8b-instruct',
      { messages: [{ role: 'user', content: 'Hello!' }] },
      { 
        gateway: { 
          id: 'my-gateway',
          metadata: { userId: '123', team: 'engineering' }
        } 
      }
    );
    
    return Response.json(response);
  }
};
```

## Headers Quick Reference

| Header | Purpose | Example | Notes |
|--------|---------|---------|-------|
| `cf-aig-authorization` | Gateway auth | `Bearer {token}` | Required for authenticated gateways |
| `cf-aig-metadata` | Tracking | `{"userId":"x"}` | Max 5 entries, flat structure |
| `cf-aig-cache-ttl` | Cache duration | `3600` | Seconds, min 60, max 2592000 (30 days) |
| `cf-aig-skip-cache` | Bypass cache | `true` | - |
| `cf-aig-cache-key` | Custom cache key | `my-key` | Must be unique per response |
| `cf-aig-collect-log` | Skip logging | `false` | Default: true |
| `cf-aig-cache-status` | Cache hit/miss | Response only | `HIT` or `MISS` |

## In This Reference

| File | Purpose |
|------|---------|
| [sdk-integration.md](./sdk-integration.md) | Vercel AI SDK, OpenAI SDK, Workers binding patterns |
| [configuration.md](./configuration.md) | Dashboard setup, wrangler, API tokens |
| [features.md](./features.md) | Caching, rate limits, guardrails, DLP, BYOK, unified billing |
| [dynamic-routing.md](./dynamic-routing.md) | Fallbacks, A/B testing, conditional routing |
| [troubleshooting.md](./troubleshooting.md) | Debugging, errors, observability, gotchas |

## Reading Order

| Task | Files |
|------|-------|
| First-time setup | README + [configuration.md](./configuration.md) |
| SDK integration | README + [sdk-integration.md](./sdk-integration.md) |
| Enable caching | README + [features.md](./features.md) |
| Setup fallbacks | README + [dynamic-routing.md](./dynamic-routing.md) |
| Debug errors | README + [troubleshooting.md](./troubleshooting.md) |

## Architecture

AI Gateway acts as a proxy between your application and AI providers:

```
Your App → AI Gateway → AI Provider (OpenAI, Anthropic, etc.)
         ↓
    Analytics, Caching, Rate Limiting, Logging
```

**Key URL patterns:**
- Unified API (OpenAI-compatible): `https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/compat/chat/completions`
- Provider-specific: `https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/{provider}/{endpoint}`
- Dynamic routes: Use route name instead of model: `dynamic/{route-name}`

## Gateway Types

1. **Unauthenticated Gateway**: Open access (not recommended for production)
2. **Authenticated Gateway**: Requires `cf-aig-authorization` header with Cloudflare API token (recommended)

## Provider Authentication Options

1. **Unified Billing**: Use AI Gateway billing to pay for inference (keyless mode - no provider API key needed)
2. **BYOK (Store Keys)**: Store provider API keys in Cloudflare dashboard
3. **Request Headers**: Include provider API key in each request

## Related Skills

- [Workers AI](../workers-ai/README.md) - For `env.AI.run()` details
- [Agents SDK](../agents-sdk/README.md) - For stateful AI patterns
- [Vectorize](../vectorize/README.md) - For RAG patterns with embeddings

## Resources

- [Official Docs](https://developers.cloudflare.com/ai-gateway/)
- [API Reference](https://developers.cloudflare.com/api/resources/ai_gateway/)
- [Provider Guides](https://developers.cloudflare.com/ai-gateway/usage/providers/)
- [Discord Community](https://discord.cloudflare.com)


================================================
FILE: skills/.curated/cloudflare-deploy/references/ai-gateway/configuration.md
================================================
# Configuration & Setup

## Creating a Gateway

### Dashboard
AI > AI Gateway > Create Gateway > Configure (auth, caching, rate limiting, logging)

### API
```bash
curl -X POST https://api.cloudflare.com/client/v4/accounts/{account_id}/ai-gateway/gateways \
  -H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" \
  -d '{"id":"my-gateway","cache_ttl":3600,"rate_limiting_interval":60,"rate_limiting_limit":100,"collect_logs":true}'
```

**Naming:** lowercase alphanumeric + hyphens (e.g., `prod-api`, `dev-chat`)

## Wrangler Integration

```toml
[ai]
binding = "AI"

[[ai.gateway]]
id = "my-gateway"
```

```bash
wrangler secret put CF_API_TOKEN
wrangler secret put OPENAI_API_KEY  # If not using BYOK
```

## Authentication

### Gateway Auth (protects gateway access)
```typescript
const client = new OpenAI({
  baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/openai`,
  defaultHeaders: { 'cf-aig-authorization': `Bearer ${cfToken}` }
});
```

### Provider Auth Options

**1. Unified Billing (keyless)** - pay through Cloudflare, no provider key:
```typescript
const client = new OpenAI({
  baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/openai`,
  defaultHeaders: { 'cf-aig-authorization': `Bearer ${cfToken}` }
});
```
Supports: OpenAI, Anthropic, Google AI Studio

**2. BYOK** - store keys in dashboard (Provider Keys > Add), no key in code

**3. Request Headers** - pass provider key per request:
```typescript
const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/openai`,
  defaultHeaders: { 'cf-aig-authorization': `Bearer ${cfToken}` }
});
```

## API Token Permissions

- **Gateway management:** AI Gateway - Read + Edit
- **Gateway access:** AI Gateway - Read (minimum)

## Gateway Management API

```bash
# List
curl https://api.cloudflare.com/client/v4/accounts/{account_id}/ai-gateway/gateways \
  -H "Authorization: Bearer $CF_API_TOKEN"

# Get
curl .../gateways/{gateway_id}

# Update
curl -X PUT .../gateways/{gateway_id} \
  -d '{"cache_ttl":7200,"rate_limiting_limit":200}'

# Delete
curl -X DELETE .../gateways/{gateway_id}
```

## Getting IDs

- **Account ID:** Dashboard > Overview > Copy
- **Gateway ID:** AI Gateway > Gateway name column

## Python Example

```python
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
    base_url=f"https://gateway.ai.cloudflare.com/v1/{os.environ['CF_ACCOUNT_ID']}/{os.environ['GATEWAY_ID']}/openai",
    default_headers={"cf-aig-authorization": f"Bearer {os.environ['CF_API_TOKEN']}"}
)
```

## Best Practices

1. **Always authenticate gateways in production**
2. **Use BYOK or unified billing** - secrets out of code
3. **Environment-specific gateways** - separate dev/staging/prod
4. **Set rate limits** - prevent runaway costs
5. **Enable logging** - track usage, debug issues


================================================
FILE: skills/.curated/cloudflare-deploy/references/ai-gateway/dynamic-routing.md
================================================
# Dynamic Routing

Configure complex routing in dashboard without code changes. Use route names instead of model names.

## Usage

```typescript
const response = await client.chat.completions.create({
  model: 'dynamic/smart-chat', // Route name from dashboard
  messages: [{ role: 'user', content: 'Hello!' }]
});
```

## Node Types

| Node | Purpose | Use Case |
|------|---------|----------|
| **Conditional** | Branch on metadata | Paid vs free users, geo routing |
| **Percentage** | A/B split traffic | Model testing, gradual rollouts |
| **Rate Limit** | Enforce quotas | Per-user/team limits |
| **Budget Limit** | Cost quotas | Per-user spending caps |
| **Model** | Call provider | Final destination |

## Metadata

Pass via header (max 5 entries, flat only):
```typescript
headers: {
  'cf-aig-metadata': JSON.stringify({
    userId: 'user-123',
    tier: 'pro',
    region: 'us-east'
  })
}
```

## Common Patterns

**Multi-model fallback:**
```
Start → GPT-4 → On error: Claude → On error: Llama
```

**Tiered access:**
```
Conditional: tier == 'enterprise' → GPT-4 (no limit)
Conditional: tier == 'pro' → Rate Limit 1000/hr → GPT-4o
Conditional: tier == 'free' → Rate Limit 10/hr → GPT-4o-mini
```

**Gradual rollout:**
```
Percentage: 10% → New model, 90% → Old model
```

**Cost-based fallback:**
```
Budget Limit: $100/day per teamId
  < 80%: GPT-4
  >= 80%: GPT-4o-mini
  >= 100%: Error
```

## Version Management

- Save changes as new version
- Test with `model: 'dynamic/route@v2'`
- Roll back by deploying previous version

## Monitoring

Dashboard → Gateway → Dynamic Routes:
- Request count per path
- Success/error rates
- Latency/cost by path

## Limitations

- Max 5 metadata entries
- Values: string/number/boolean/null only
- No nested objects
- Route names: alphanumeric + hyphens


================================================
FILE: skills/.curated/cloudflare-deploy/references/ai-gateway/features.md
================================================
# Features & Capabilities

## Caching

Dashboard: Settings → Cache Responses → Enable

```typescript
// Custom TTL (1 hour)
headers: { 'cf-aig-cache-ttl': '3600' }

// Skip cache
headers: { 'cf-aig-skip-cache': 'true' }

// Custom cache key
headers: { 'cf-aig-cache-key': 'greeting-en' }
```

**Limits:** TTL 60s - 30 days. **Does NOT work with streaming.**

## Rate Limiting

Dashboard: Settings → Rate-limiting → Enable

- **Fixed window:** Resets at intervals
- **Sliding window:** Rolling window (more accurate)
- Returns `429` when exceeded

## Guardrails

Dashboard: Settings → Guardrails → Enable

Filter prompts/responses for inappropriate content. Actions: Flag (log) or Block (reject).

## Data Loss Prevention (DLP)

Dashboard: Settings → DLP → Enable

Detect PII (emails, SSNs, credit cards). Actions: Flag, Block, or Redact.

## Billing Modes

| Mode | Description | Setup |
|------|-------------|-------|
| **Unified Billing** | Pay through Cloudflare, no provider keys | Use `cf-aig-authorization` header only |
| **BYOK** | Store provider keys in dashboard | Add keys in Provider Keys section |
| **Pass-through** | Send provider key with each request | Include provider's auth header |

## Zero Data Retention

Dashboard: Settings → Privacy → Zero Data Retention

No prompts/responses stored. Request counts and costs still tracked.

## Logging

Dashboard: Settings → Logs → Enable (up to 10M logs)

Each entry: prompt, response, provider, model, tokens, cost, duration, cache status, metadata.

```typescript
// Skip logging for request
headers: { 'cf-aig-collect-log': 'false' }
```

**Export:** Use Logpush to S3, GCS, Datadog, Splunk, etc.

## Custom Cost Tracking

For models not in Cloudflare's pricing database:

Dashboard: Gateway → Settings → Custom Costs

Or via API: set `model`, `input_cost`, `output_cost`.

## Supported Providers (22+)

| Provider | Unified API | Notes |
|----------|-------------|-------|
| OpenAI | `openai/gpt-4o` | Full support |
| Anthropic | `anthropic/claude-sonnet-4-5` | Full support |
| Google AI | `google-ai-studio/gemini-2.0-flash` | Full support |
| Workers AI | `workersai/@cf/meta/llama-3` | Native |
| Azure OpenAI | `azure-openai/*` | Deployment names |
| AWS Bedrock | Provider endpoint only | `/bedrock/*` |
| Groq | `groq/*` | Fast inference |
| Mistral, Cohere, Perplexity, xAI, DeepSeek, Cerebras | Full support | - |

## Best Practices

1. Enable caching for deterministic prompts
2. Set rate limits to prevent abuse
3. Use guardrails for user-facing AI
4. Enable DLP for sensitive data
5. Use unified billing or BYOK for simpler key management
6. Enable logging for debugging
7. Use zero data retention when privacy required


================================================
FILE: skills/.curated/cloudflare-deploy/references/ai-gateway/sdk-integration.md
================================================
# AI Gateway SDK Integration

## Vercel AI SDK (Recommended)

```typescript
import { createAiGateway } from 'ai-gateway-provider';
import { createOpenAI } from '@ai-sdk/openai';
import { generateText } from 'ai';

const gateway = createAiGateway({
  accountId: process.env.CF_ACCOUNT_ID,
  gateway: process.env.CF_GATEWAY_ID,
  apiKey: process.env.CF_API_TOKEN // Optional for auth gateways
});

const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });

// Single model
const { text } = await generateText({
  model: gateway(openai('gpt-4o')),
  prompt: 'Hello'
});

// Automatic fallback array
const { text } = await generateText({
  model: gateway([
    openai('gpt-4o'),
    anthropic('claude-sonnet-4-5'),
    openai('gpt-4o-mini')
  ]),
  prompt: 'Complex task'
});
```

### Options

```typescript
model: gateway(openai('gpt-4o'), {
  cacheKey: 'my-key',
  cacheTtl: 3600,
  metadata: { userId: 'u123', team: 'eng' }, // Max 5 entries
  retries: { maxAttempts: 3, backoff: 'exponential' }
})
```

## OpenAI SDK

```typescript
const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/openai`,
  defaultHeaders: { 'cf-aig-authorization': `Bearer ${cfToken}` }
});

// Unified API - switch providers via model name
model: 'openai/gpt-4o'  // or 'anthropic/claude-sonnet-4-5'
```

## Anthropic SDK

```typescript
const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
  baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/anthropic`,
  defaultHeaders: { 'cf-aig-authorization': `Bearer ${cfToken}` }
});
```

## Workers AI Binding

```toml
# wrangler.toml
[ai]
binding = "AI"
[[ai.gateway]]
id = "my-gateway"
```

```typescript
await env.AI.run('@cf/meta/llama-3-8b-instruct', 
  { messages: [...] },
  { gateway: { id: 'my-gateway', metadata: { userId: '123' } } }
);
```

## LangChain / LlamaIndex

```typescript
// Use OpenAI SDK pattern with custom baseURL
new ChatOpenAI({
  configuration: {
    baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/openai`
  }
});
```

## HTTP / cURL

```bash
curl https://gateway.ai.cloudflare.com/v1/{account}/{gateway}/openai/chat/completions \
  -H "Authorization: Bearer $OPENAI_KEY" \
  -H "cf-aig-authorization: Bearer $CF_TOKEN" \
  -H "cf-aig-metadata: {\"userId\":\"123\"}" \
  -d '{"model":"gpt-4o","messages":[...]}'
```

## Headers Reference

| Header | Purpose |
|--------|---------|
| `cf-aig-authorization` | Gateway auth token |
| `cf-aig-metadata` | JSON object (max 5 keys) |
| `cf-aig-cache-ttl` | Cache TTL in seconds |
| `cf-aig-skip-cache` | `true` to bypass cache |


================================================
FILE: skills/.curated/cloudflare-deploy/references/ai-gateway/troubleshooting.md
================================================
# AI Gateway Troubleshooting

## Common Errors

| Error | Cause | Fix |
|-------|-------|-----|
| 401 | Missing `cf-aig-authorization` header | Add header with CF API token |
| 403 | Invalid provider key / BYOK expired | Check provider key in dashboard |
| 429 | Rate limit exceeded | Increase limit or implement backoff |

### 401 Fix

```typescript
const client = new OpenAI({
  baseURL: `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/openai`,
  defaultHeaders: { 'cf-aig-authorization': `Bearer ${CF_API_TOKEN}` }
});
```

### 429 Retry Pattern

```typescript
async function requestWithRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try { return await fn(); }
    catch (e) {
      if (e.status === 429 && i < maxRetries - 1) {
        await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
        continue;
      }
      throw e;
    }
  }
}
```

## Gotchas

| Issue | Reality |
|-------|---------|
| Metadata limits | Max 5 entries, flat only (no nesting) |
| Cache key collision | Use unique keys per expected response |
| BYOK + Unified Billing | Mutually exclusive |
| Rate limit scope | Per-gateway, not per-user (use dynamic routing for per-user) |
| Log delay | 30-60 seconds normal |
| Streaming + caching | **Incompatible** |
| Model name (unified API) | Prefix required: `openai/gpt-4o`, not `gpt-4o` |

## Cache Not Working

**Causes:**
- Different request params (temperature, etc.)
- Streaming enabled
- Caching disabled in settings

**Check:** `response.headers.get('cf-aig-cache-status')` → HIT or MISS

## Logs Not Appearing

1. Check logging enabled: Dashboard → Gateway → Settings
2. Remove `cf-aig-collect-log: false` header
3. Wait 30-60 seconds
4. Check log limit (10M default)

## Debugging

```bash
# Test connectivity
curl -v https://gateway.ai.cloudflare.com/v1/{account}/{gateway}/openai/models \
  -H "Authorization: Bearer $OPENAI_KEY" \
  -H "cf-aig-authorization: Bearer $CF_TOKEN"
```

```typescript
// Check response headers
console.log('Cache:', response.headers.get('cf-aig-cache-status'));
console.log('Request ID:', response.headers.get('cf-ray'));
```

## Analytics

Dashboard → AI Gateway → Select gateway

**Metrics:** Requests, tokens, latency (p50/p95/p99), cache hit rate, costs

**Log filters:** `status: error`, `provider: openai`, `cost > 0.01`, `duration > 1000`

**Export:** Logpush to S3/GCS/Datadog/Splunk


================================================
FILE: skills/.curated/cloudflare-deploy/references/ai-search/README.md
================================================
# Cloudflare AI Search Reference

Expert guidance for implementing Cloudflare AI Search (formerly AutoRAG), Cloudflare's managed semantic search and RAG service.

## Overview

**AI Search** is a managed RAG (Retrieval-Augmented Generation) pipeline that combines:
- Automatic semantic indexing of your content
- Vector similarity search
- Built-in LLM generation

**Key value propositions:**
- **Zero vector management** - No manual embedding, indexing, or storage
- **Auto-indexing** - Content automatically re-indexed every 6 hours
- **Built-in generation** - Optional AI response generation from retrieved context
- **Multi-source** - Index from R2 buckets or website crawls

**Data source options:**
- **R2 bucket** - Index files from Cloudflare R2 (supports MD, TXT, HTML, PDF, DOC, CSV, JSON)
- **Website** - Crawl and index website content (requires Cloudflare-hosted domain)

**Indexing lifecycle:**
- Automatic 6-hour refresh cycle
- Manual "Force Sync" available (30s rate limit)
- Not designed for real-time updates

## Quick Start

**1. Create AI Search instance in dashboard:**
- Go to Cloudflare Dashboard → AI Search → Create
- Choose data source (R2 or website)
- Configure instance name and settings

**2. Configure Worker:**

```jsonc
// wrangler.jsonc
{
  "ai": {
    "binding": "AI"
  }
}
```

**3. Use in Worker:**

```typescript
export default {
  async fetch(request, env) {
    const answer = await env.AI.autorag("my-search-instance").aiSearch({
      query: "How do I configure caching?",
      model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast"
    });
    
    return Response.json({ answer: answer.response });
  }
};
```

## When to Use AI Search

### AI Search vs Vectorize

| Factor | AI Search | Vectorize |
|--------|-----------|-----------|
| **Management** | Fully managed | Manual embedding + indexing |
| **Use when** | Want zero-ops RAG pipeline | Need custom embeddings/control |
| **Indexing** | Automatic (6hr cycle) | Manual via API |
| **Generation** | Built-in optional | Bring your own LLM |
| **Data sources** | R2 or website | Manual insert |
| **Best for** | Docs, support, enterprise search | Custom ML pipelines, real-time |

### AI Search vs Direct Workers AI

| Factor | AI Search | Workers AI (direct) |
|--------|-----------|---------------------|
| **Context** | Automatic retrieval | Manual context building |
| **Use when** | Need RAG (search + generate) | Simple generation tasks |
| **Indexing** | Built-in | Not applicable |
| **Best for** | Knowledge bases, docs | Simple chat, transformations |

### search() vs aiSearch()

| Method | Returns | Use When |
|--------|---------|----------|
| `search()` | Search results only | Building custom UI, need raw chunks |
| `aiSearch()` | AI response + results | Need ready-to-use answer (chatbot, Q&A) |

### Real-time Updates Consideration

**AI Search is NOT ideal if:**
- Need real-time content updates (<6 hours)
- Content changes multiple times per hour
- Strict freshness requirements

**AI Search IS ideal if:**
- Content relatively stable (docs, policies, knowledge bases)
- 6-hour refresh acceptable
- Prefer zero-ops over real-time

## Platform Limits

| Limit | Value |
|-------|-------|
| Max instances per account | 10 |
| Max files per instance | 100,000 |
| Max file size | 4 MB |
| Index frequency | Every 6 hours |
| Force Sync rate limit | Once per 30 seconds |
| Filter nesting depth | 2 levels |
| Filters per compound | 10 |
| Score threshold range | 0.0 - 1.0 |

## Reading Order

Navigate these references based on your task:

| Task | Read | Est. Time |
|------|------|-----------|
| **Understand AI Search** | README only | 5 min |
| **Implement basic search** | README → api.md | 10 min |
| **Configure data source** | README → configuration.md | 10 min |
| **Production patterns** | patterns.md | 15 min |
| **Debug issues** | gotchas.md | 10 
Download .txt
gitextract_f89akwzt/

├── .gitignore
├── README.md
├── contributing.md
└── skills/
    ├── .curated/
    │   ├── aspnet-core/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── _sections.md
    │   │       ├── apis-minimal-and-controllers.md
    │   │       ├── data-state-and-services.md
    │   │       ├── program-and-pipeline.md
    │   │       ├── realtime-grpc-and-background-work.md
    │   │       ├── security-and-identity.md
    │   │       ├── source-map.md
    │   │       ├── stack-selection.md
    │   │       ├── testing-performance-and-operations.md
    │   │       ├── ui-blazor.md
    │   │       ├── ui-mvc.md
    │   │       ├── ui-razor-pages.md
    │   │       └── versioning-and-upgrades.md
    │   ├── chatgpt-apps/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── app-archetypes.md
    │   │   │   ├── apps-sdk-docs-workflow.md
    │   │   │   ├── interactive-state-sync-patterns.md
    │   │   │   ├── repo-contract-and-validation.md
    │   │   │   ├── search-fetch-standard.md
    │   │   │   ├── upstream-example-workflow.md
    │   │   │   └── window-openai-patterns.md
    │   │   └── scripts/
    │   │       └── scaffold_node_ext_apps.mjs
    │   ├── cloudflare-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── agents-sdk/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── ai-gateway/
    │   │       │   ├── README.md
    │   │       │   ├── configuration.md
    │   │       │   ├── dynamic-routing.md
    │   │       │   ├── features.md
    │   │       │   ├── sdk-integration.md
    │   │       │   └── troubleshooting.md
    │   │       ├── ai-search/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── analytics-engine/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── api/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── api-shield/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── argo-smart-routing/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── bindings/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── bot-management/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── browser-rendering/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── c3/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── cache-reserve/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── containers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── cron-triggers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── d1/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── ddos/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── do-storage/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   ├── patterns.md
    │   │       │   └── testing.md
    │   │       ├── durable-objects/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── email-routing/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── email-workers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── hyperdrive/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── images/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── kv/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── miniflare/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── network-interconnect/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── observability/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pages/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pages-functions/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pipelines/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── pulumi/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── queues/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── r2/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── r2-data-catalog/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── r2-sql/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── realtime-sfu/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── realtimekit/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── sandbox/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── secrets-store/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── smart-placement/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── snippets/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── spectrum/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── static-assets/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── stream/
    │   │       │   ├── README.md
    │   │       │   ├── api-live.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── tail-workers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── terraform/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── tunnel/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   ├── networking.md
    │   │       │   └── patterns.md
    │   │       ├── turn/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── turnstile/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── vectorize/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── waf/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── web-analytics/
    │   │       │   ├── README.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   ├── integration.md
    │   │       │   └── patterns.md
    │   │       ├── workerd/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── frameworks.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-ai/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-for-platforms/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-playground/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workers-vpc/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── workflows/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       ├── wrangler/
    │   │       │   ├── README.md
    │   │       │   ├── api.md
    │   │       │   ├── auth.md
    │   │       │   ├── configuration.md
    │   │       │   ├── gotchas.md
    │   │       │   └── patterns.md
    │   │       └── zaraz/
    │   │           ├── IMPLEMENTATION_SUMMARY.md
    │   │           ├── README.md
    │   │           ├── api.md
    │   │           ├── configuration.md
    │   │           ├── gotchas.md
    │   │           └── patterns.md
    │   ├── develop-web-game/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   └── action_payloads.json
    │   │   └── scripts/
    │   │       └── web_game_playwright_client.js
    │   ├── doc/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── render_docx.py
    │   ├── figma/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── figma-mcp-config.md
    │   │       └── figma-tools-and-prompts.md
    │   ├── figma-implement-design/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── gh-address-comments/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── fetch_comments.py
    │   ├── gh-fix-ci/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── inspect_pr_checks.py
    │   ├── imagegen/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── cli.md
    │   │   │   ├── codex-network.md
    │   │   │   ├── image-api.md
    │   │   │   ├── prompting.md
    │   │   │   └── sample-prompts.md
    │   │   └── scripts/
    │   │       └── image_gen.py
    │   ├── jupyter-notebook/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── assets/
    │   │   │   ├── experiment-template.ipynb
    │   │   │   └── tutorial-template.ipynb
    │   │   ├── references/
    │   │   │   ├── experiment-patterns.md
    │   │   │   ├── notebook-structure.md
    │   │   │   ├── quality-checklist.md
    │   │   │   └── tutorial-patterns.md
    │   │   └── scripts/
    │   │       └── new_notebook.py
    │   ├── linear/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── netlify-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── cli-commands.md
    │   │       ├── deployment-patterns.md
    │   │       └── netlify-toml.md
    │   ├── notion-knowledge-capture/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── conversation-to-wiki.json
    │   │   │   └── decision-record.json
    │   │   ├── examples/
    │   │   │   ├── conversation-to-faq.md
    │   │   │   ├── decision-capture.md
    │   │   │   └── how-to-guide.md
    │   │   └── reference/
    │   │       ├── database-best-practices.md
    │   │       ├── decision-log-database.md
    │   │       ├── documentation-database.md
    │   │       ├── faq-database.md
    │   │       ├── how-to-guide-database.md
    │   │       ├── learning-database.md
    │   │       └── team-wiki-database.md
    │   ├── notion-meeting-intelligence/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── decision-meeting-prep.json
    │   │   │   └── status-meeting-prep.json
    │   │   ├── examples/
    │   │   │   ├── customer-meeting.md
    │   │   │   ├── executive-review.md
    │   │   │   ├── project-decision.md
    │   │   │   └── sprint-planning.md
    │   │   └── reference/
    │   │       ├── brainstorming-template.md
    │   │       ├── decision-meeting-template.md
    │   │       ├── one-on-one-template.md
    │   │       ├── retrospective-template.md
    │   │       ├── sprint-planning-template.md
    │   │       ├── status-update-template.md
    │   │       └── template-selection-guide.md
    │   ├── notion-research-documentation/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── basic-research.json
    │   │   │   └── research-to-database.json
    │   │   ├── examples/
    │   │   │   ├── competitor-analysis.md
    │   │   │   ├── market-research.md
    │   │   │   ├── technical-investigation.md
    │   │   │   └── trip-planning.md
    │   │   └── reference/
    │   │       ├── advanced-search.md
    │   │       ├── citations.md
    │   │       ├── comparison-format.md
    │   │       ├── comparison-template.md
    │   │       ├── comprehensive-report-format.md
    │   │       ├── comprehensive-report-template.md
    │   │       ├── format-selection-guide.md
    │   │       ├── quick-brief-format.md
    │   │       ├── quick-brief-template.md
    │   │       ├── research-summary-format.md
    │   │       └── research-summary-template.md
    │   ├── notion-spec-to-implementation/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── evaluations/
    │   │   │   ├── README.md
    │   │   │   ├── basic-spec-implementation.json
    │   │   │   └── spec-to-tasks.json
    │   │   ├── examples/
    │   │   │   ├── api-feature.md
    │   │   │   ├── database-migration.md
    │   │   │   └── ui-component.md
    │   │   └── reference/
    │   │       ├── milestone-summary-template.md
    │   │       ├── progress-tracking.md
    │   │       ├── progress-update-template.md
    │   │       ├── quick-implementation-plan.md
    │   │       ├── spec-parsing.md
    │   │       ├── standard-implementation-plan.md
    │   │       ├── task-creation-template.md
    │   │       └── task-creation.md
    │   ├── openai-docs/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── gpt-5p4-prompting-guide.md
    │   │       ├── latest-model.md
    │   │       └── upgrading-to-gpt-5p4.md
    │   ├── pdf/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── playwright/
    │   │   ├── LICENSE.txt
    │   │   ├── NOTICE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── cli.md
    │   │   │   └── workflows.md
    │   │   └── scripts/
    │   │       └── playwright_cli.sh
    │   ├── playwright-interactive/
    │   │   ├── LICENSE.txt
    │   │   ├── NOTICE.txt
    │   │   ├── SKILL.md
    │   │   └── agents/
    │   │       └── openai.yaml
    │   ├── render-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── assets/
    │   │   │   ├── docker.yaml
    │   │   │   ├── go-api.yaml
    │   │   │   ├── nextjs-postgres.yaml
    │   │   │   ├── node-express.yaml
    │   │   │   ├── python-django.yaml
    │   │   │   └── static-site.yaml
    │   │   └── references/
    │   │       ├── blueprint-spec.md
    │   │       ├── codebase-analysis.md
    │   │       ├── configuration-guide.md
    │   │       ├── deployment-details.md
    │   │       ├── direct-creation.md
    │   │       ├── error-patterns.md
    │   │       ├── post-deploy-checks.md
    │   │       ├── runtimes.md
    │   │       ├── service-types.md
    │   │       └── troubleshooting-basics.md
    │   ├── screenshot/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       ├── ensure_macos_permissions.sh
    │   │       ├── macos_display_info.swift
    │   │       ├── macos_permissions.swift
    │   │       ├── macos_window_info.swift
    │   │       ├── take_screenshot.ps1
    │   │       └── take_screenshot.py
    │   ├── security-best-practices/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── golang-general-backend-security.md
    │   │       ├── javascript-express-web-server-security.md
    │   │       ├── javascript-general-web-frontend-security.md
    │   │       ├── javascript-jquery-web-frontend-security.md
    │   │       ├── javascript-typescript-nextjs-web-server-security.md
    │   │       ├── javascript-typescript-react-web-frontend-security.md
    │   │       ├── javascript-typescript-vue-web-frontend-security.md
    │   │       ├── python-django-web-server-security.md
    │   │       ├── python-fastapi-web-server-security.md
    │   │       └── python-flask-web-server-security.md
    │   ├── security-ownership-map/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   └── neo4j-import.md
    │   │   └── scripts/
    │   │       ├── build_ownership_map.py
    │   │       ├── community_maintainers.py
    │   │       ├── query_ownership.py
    │   │       └── run_ownership_map.py
    │   ├── security-threat-model/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       ├── prompt-template.md
    │   │       └── security-controls-and-assets.md
    │   ├── sentry/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── sentry_api.py
    │   ├── slides/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── assets/
    │   │   │   └── pptxgenjs_helpers/
    │   │   │       ├── code.js
    │   │   │       ├── image.js
    │   │   │       ├── index.js
    │   │   │       ├── latex.js
    │   │   │       ├── layout.js
    │   │   │       ├── layout_builders.js
    │   │   │       ├── svg.js
    │   │   │       ├── text.js
    │   │   │       └── util.js
    │   │   ├── references/
    │   │   │   └── pptxgenjs-helpers.md
    │   │   └── scripts/
    │   │       ├── create_montage.py
    │   │       ├── detect_font.py
    │   │       ├── ensure_raster_image.py
    │   │       ├── render_slides.py
    │   │       └── slides_test.py
    │   ├── sora/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── cinematic-shots.md
    │   │   │   ├── cli.md
    │   │   │   ├── codex-network.md
    │   │   │   ├── prompting.md
    │   │   │   ├── sample-prompts.md
    │   │   │   ├── social-ads.md
    │   │   │   ├── troubleshooting.md
    │   │   │   └── video-api.md
    │   │   └── scripts/
    │   │       └── sora.py
    │   ├── speech/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   ├── accessibility.md
    │   │   │   ├── audio-api.md
    │   │   │   ├── cli.md
    │   │   │   ├── codex-network.md
    │   │   │   ├── ivr.md
    │   │   │   ├── narration.md
    │   │   │   ├── prompting.md
    │   │   │   ├── sample-prompts.md
    │   │   │   ├── voice-directions.md
    │   │   │   └── voiceover.md
    │   │   └── scripts/
    │   │       └── text_to_speech.py
    │   ├── spreadsheet/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── references/
    │   │       └── examples/
    │   │           └── openpyxl/
    │   │               ├── create_basic_spreadsheet.py
    │   │               ├── create_spreadsheet_with_styling.py
    │   │               ├── read_existing_spreadsheet.py
    │   │               └── styling_spreadsheet.py
    │   ├── transcribe/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── references/
    │   │   │   └── api.md
    │   │   └── scripts/
    │   │       └── transcribe_diarize.py
    │   ├── vercel-deploy/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   └── scripts/
    │   │       └── deploy.sh
    │   ├── winui-app/
    │   │   ├── LICENSE.txt
    │   │   ├── SKILL.md
    │   │   ├── agents/
    │   │   │   └── openai.yaml
    │   │   ├── config.yaml
    │   │   └── references/
    │   │       ├── _sections.md
    │   │       ├── accessibility-input-and-localization.md
    │   │       ├── build-run-and-launch-verification.md
    │   │       ├── community-toolkit-controls-and-helpers.md
    │   │       ├── controls-layout-and-adaptive-ui.md
    │   │       ├── foundation-environment-audit-and-remediation.md
    │   │       ├── foundation-setup-and-project-selection.md
    │   │       ├── foundation-template-first-recovery.md
    │   │       ├── foundation-winui-app-structure.md
    │   │       ├── motion-animations-and-polish.md
    │   │       ├── performance-diagnostics-and-responsiveness.md
    │   │       ├── sample-source-map.md
    │   │       ├── shell-navigation-and-windowing.md
    │   │       ├── styling-theming-materials-and-icons.md
    │   │       ├── testing-debugging-and-review-checklists.md
    │   │       └── windows-app-sdk-lifecycle-notifications-and-deployment.md
    │   └── yeet/
    │       ├── LICENSE.txt
    │       ├── SKILL.md
    │       └── agents/
    │           └── openai.yaml
    └── .system/
        ├── openai-docs/
        │   ├── LICENSE.txt
        │   ├── SKILL.md
        │   ├── agents/
        │   │   └── openai.yaml
        │   └── references/
        │       ├── gpt-5p4-prompting-guide.md
        │       ├── latest-model.md
        │       └── upgrading-to-gpt-5p4.md
        ├── skill-creator/
        │   ├── LICENSE.txt
        │   ├── SKILL.md
        │   ├── agents/
        │   │   └── openai.yaml
        │   ├── references/
        │   │   └── openai_yaml.md
        │   └── scripts/
        │       ├── generate_openai_yaml.py
        │       ├── init_skill.py
        │       └── quick_validate.py
        └── skill-installer/
            ├── LICENSE.txt
            ├── SKILL.md
            ├── agents/
            │   └── openai.yaml
            └── scripts/
                ├── github_utils.py
                ├── install-skill-from-github.py
                └── list-skills.py
Download .txt
SYMBOL INDEX (513 symbols across 40 files)

FILE: skills/.curated/chatgpt-apps/scripts/scaffold_node_ext_apps.mjs
  function toSlug (line 6) | function toSlug(value) {
  function toToolName (line 11) | function toToolName(value) {
  function toTitle (line 16) | function toTitle(value) {
  function fillTemplate (line 21) | function fillTemplate(template, mapping) {
  function writeFile (line 29) | function writeFile(filePath, content) {
  function ensureTargetDir (line 34) | function ensureTargetDir(targetPath, force) {
  function buildPackageJson (line 49) | function buildPackageJson(appSlug) {
  function buildTsconfig (line 74) | function buildTsconfig() {
  constant WIDGET_TEMPLATE (line 91) | const WIDGET_TEMPLATE = `<!DOCTYPE html>
  constant SERVER_TEMPLATE (line 314) | const SERVER_TEMPLATE = `import { createServer } from "node:http";
  function buildWidgetHtml (line 485) | function buildWidgetHtml(appSlug, appTitle, toolName) {
  function buildServerTs (line 493) | function buildServerTs(appSlug, appTitle, toolName, widgetUri, port) {
  function usage (line 503) | function usage() {
  function parseArgs (line 516) | function parseArgs(argv) {
  function main (line 573) | function main() {

FILE: skills/.curated/develop-web-game/scripts/web_game_playwright_client.js
  function parseArgs (line 5) | function parseArgs(argv) {
  function sleep (line 69) | async function sleep(ms) {
  function ensureDir (line 73) | function ensureDir(p) {
  function makeVirtualTimeShim (line 77) | function makeVirtualTimeShim() {
  function getCanvasHandle (line 127) | async function getCanvasHandle(page) {
  function captureCanvasPngBase64 (line 143) | async function captureCanvasPngBase64(canvas) {
  function isCanvasTransparent (line 152) | async function isCanvasTransparent(canvas) {
  function captureScreenshot (line 177) | async function captureScreenshot(page, canvas, outPath) {
  class ConsoleErrorTracker (line 207) | class ConsoleErrorTracker {
    method constructor (line 208) | constructor() {
    method ingest (line 213) | ingest(err) {
    method drain (line 220) | drain() {
  function doChoreography (line 227) | async function doChoreography(page, canvas, steps) {
  function main (line 262) | async function main() {

FILE: skills/.curated/doc/scripts/render_docx.py
  function ensure_system_tools (line 19) | def ensure_system_tools() -> None:
  function calc_dpi_via_ooxml_docx (line 31) | def calc_dpi_via_ooxml_docx(input_path: str, max_w_px: int, max_h_px: in...
  function calc_dpi_via_pdf (line 69) | def calc_dpi_via_pdf(input_path: str, max_w_px: int, max_h_px: int) -> int:
  function run_cmd_no_check (line 100) | def run_cmd_no_check(cmd: list[str]) -> None:
  function convert_to_pdf (line 110) | def convert_to_pdf(
  function rasterize (line 172) | def rasterize(
  function main (line 227) | def main() -> None:

FILE: skills/.curated/gh-address-comments/scripts/fetch_comments.py
  function _run (line 95) | def _run(cmd: list[str], stdin: str | None = None) -> str:
  function _run_json (line 102) | def _run_json(cmd: list[str], stdin: str | None = None) -> dict[str, Any]:
  function _ensure_gh_authenticated (line 110) | def _ensure_gh_authenticated() -> None:
  function gh_pr_view_json (line 118) | def gh_pr_view_json(fields: str) -> dict[str, Any]:
  function get_current_pr_ref (line 123) | def get_current_pr_ref() -> tuple[str, str, int]:
  function gh_api_graphql (line 135) | def gh_api_graphql(
  function fetch_all (line 170) | def fetch_all(owner: str, repo: str, number: int) -> dict[str, Any]:
  function main (line 229) | def main() -> None:

FILE: skills/.curated/gh-fix-ci/scripts/inspect_pr_checks.py
  class GhResult (line 51) | class GhResult:
    method __init__ (line 52) | def __init__(self, returncode: int, stdout: str, stderr: str):
  function run_gh_command (line 58) | def run_gh_command(args: Sequence[str], cwd: Path) -> GhResult:
  function run_gh_command_raw (line 68) | def run_gh_command_raw(args: Sequence[str], cwd: Path) -> tuple[int, byt...
  function parse_args (line 78) | def parse_args() -> argparse.Namespace:
  function main (line 96) | def main() -> int:
  function find_git_root (line 138) | def find_git_root(start: Path) -> Path | None:
  function ensure_gh_available (line 150) | def ensure_gh_available(repo_root: Path) -> bool:
  function resolve_pr (line 162) | def resolve_pr(pr_value: str | None, repo_root: Path) -> str | None:
  function fetch_checks (line 182) | def fetch_checks(pr_value: str, repo_root: Path) -> list[dict[str, Any]]...
  function is_failing (line 227) | def is_failing(check: dict[str, Any]) -> bool:
  function analyze_check (line 238) | def analyze_check(
  function extract_run_id (line 288) | def extract_run_id(url: str) -> str | None:
  function extract_job_id (line 298) | def extract_job_id(url: str) -> str | None:
  function fetch_run_metadata (line 310) | def fetch_run_metadata(run_id: str, repo_root: Path) -> dict[str, Any] |...
  function fetch_check_log (line 333) | def fetch_check_log(
  function fetch_run_log (line 358) | def fetch_run_log(run_id: str, repo_root: Path) -> tuple[str, str]:
  function fetch_job_log (line 366) | def fetch_job_log(job_id: str, repo_root: Path) -> tuple[str, str]:
  function fetch_repo_slug (line 380) | def fetch_repo_slug(repo_root: Path) -> str | None:
  function normalize_field (line 394) | def normalize_field(value: Any) -> str:
  function parse_available_fields (line 400) | def parse_available_fields(message: str) -> list[str]:
  function is_log_pending_message (line 418) | def is_log_pending_message(message: str) -> bool:
  function is_zip_payload (line 423) | def is_zip_payload(payload: bytes) -> bool:
  function extract_failure_snippet (line 427) | def extract_failure_snippet(log_text: str, max_lines: int, context: int)...
  function find_failure_index (line 444) | def find_failure_index(lines: Sequence[str]) -> int | None:
  function tail_lines (line 452) | def tail_lines(text: str, max_lines: int) -> str:
  function render_results (line 459) | def render_results(pr_number: str, results: Iterable[dict[str, Any]]) ->...
  function indent_block (line 504) | def indent_block(text: str, prefix: str = "  ") -> str:

FILE: skills/.curated/imagegen/scripts/image_gen.py
  function _die (line 37) | def _die(message: str, code: int = 1) -> None:
  function _warn (line 42) | def _warn(message: str) -> None:
  function _ensure_api_key (line 46) | def _ensure_api_key(dry_run: bool) -> None:
  function _read_prompt (line 56) | def _read_prompt(prompt: Optional[str], prompt_file: Optional[str]) -> str:
  function _check_image_paths (line 70) | def _check_image_paths(paths: Iterable[str]) -> List[Path]:
  function _normalize_output_format (line 82) | def _normalize_output_format(fmt: Optional[str]) -> str:
  function _validate_size (line 91) | def _validate_size(size: str) -> None:
  function _validate_quality (line 98) | def _validate_quality(quality: str) -> None:
  function _validate_background (line 103) | def _validate_background(background: Optional[str]) -> None:
  function _validate_transparency (line 108) | def _validate_transparency(background: Optional[str], output_format: str...
  function _validate_generate_payload (line 113) | def _validate_generate_payload(payload: Dict[str, Any]) -> None:
  function _build_output_paths (line 128) | def _build_output_paths(
  function _augment_prompt (line 162) | def _augment_prompt(args: argparse.Namespace, prompt: str) -> str:
  function _augment_prompt_fields (line 167) | def _augment_prompt_fields(augment: bool, prompt: str, fields: Dict[str,...
  function _fields_from_args (line 199) | def _fields_from_args(args: argparse.Namespace) -> Dict[str, Optional[st...
  function _print_request (line 215) | def _print_request(payload: dict) -> None:
  function _decode_and_write (line 219) | def _decode_and_write(images: List[str], outputs: List[Path], force: boo...
  function _derive_downscale_path (line 231) | def _derive_downscale_path(path: Path, suffix: str) -> Path:
  function _downscale_image_bytes (line 237) | def _downscale_image_bytes(image_bytes: bytes, *, max_dim: int, output_f...
  function _decode_write_and_downscale (line 273) | def _decode_write_and_downscale(
  function _create_client (line 306) | def _create_client():
  function _create_async_client (line 314) | def _create_async_client():
  function _slugify (line 328) | def _slugify(value: str) -> str:
  function _normalize_job (line 335) | def _normalize_job(job: Any, idx: int) -> Dict[str, Any]:
  function _read_jobs_jsonl (line 349) | def _read_jobs_jsonl(path: str) -> List[Dict[str, Any]]:
  function _merge_non_null (line 374) | def _merge_non_null(dst: Dict[str, Any], src: Dict[str, Any]) -> Dict[st...
  function _job_output_paths (line 382) | def _job_output_paths(
  function _extract_retry_after_seconds (line 415) | def _extract_retry_after_seconds(exc: Exception) -> Optional[float]:
  function _is_rate_limit_error (line 431) | def _is_rate_limit_error(exc: Exception) -> bool:
  function _is_transient_error (line 439) | def _is_transient_error(exc: Exception) -> bool:
  function _generate_one_with_retries (line 449) | async def _generate_one_with_retries(
  function _run_generate_batch (line 477) | async def _run_generate_batch(args: argparse.Namespace) -> int:
  function _generate_batch (line 612) | def _generate_batch(args: argparse.Namespace) -> None:
  function _generate (line 618) | def _generate(args: argparse.Namespace) -> None:
  function _edit (line 666) | def _edit(args: argparse.Namespace) -> None:
  function _open_files (line 735) | def _open_files(paths: List[Path]):
  function _open_mask (line 739) | def _open_mask(mask_path: Optional[Path]):
  class _NullContext (line 745) | class _NullContext:
    method __enter__ (line 746) | def __enter__(self):
    method __exit__ (line 749) | def __exit__(self, exc_type, exc, tb):
  class _SingleFile (line 753) | class _SingleFile:
    method __init__ (line 754) | def __init__(self, path: Path):
    method __enter__ (line 758) | def __enter__(self):
    method __exit__ (line 762) | def __exit__(self, exc_type, exc, tb):
  class _FileBundle (line 771) | class _FileBundle:
    method __init__ (line 772) | def __init__(self, paths: List[Path]):
    method __enter__ (line 776) | def __enter__(self):
    method __exit__ (line 780) | def __exit__(self, exc_type, exc, tb):
  function _add_shared_args (line 789) | def _add_shared_args(parser: argparse.ArgumentParser) -> None:
  function main (line 826) | def main() -> int:

FILE: skills/.curated/jupyter-notebook/scripts/new_notebook.py
  function slugify (line 10) | def slugify(text: str) -> str:
  function find_repo_root (line 17) | def find_repo_root(start: Path) -> Path:
  function load_template (line 24) | def load_template(skill_dir: Path, kind: str) -> dict[str, Any]:
  function update_title (line 36) | def update_title(notebook: dict[str, Any], kind: str, title: str) -> None:
  function default_output (line 73) | def default_output(repo_root: Path, title: str) -> Path:
  function parse_args (line 78) | def parse_args() -> argparse.Namespace:
  function main (line 105) | def main() -> None:

FILE: skills/.curated/screenshot/scripts/take_screenshot.py
  function parse_region (line 33) | def parse_region(value: str) -> tuple[int, int, int, int]:
  function test_mode_enabled (line 46) | def test_mode_enabled() -> bool:
  function normalize_platform (line 51) | def normalize_platform(value: str) -> str:
  function test_platform_override (line 62) | def test_platform_override() -> str | None:
  function parse_int_list (line 69) | def parse_int_list(value: str) -> list[int]:
  function test_window_ids (line 82) | def test_window_ids() -> list[int]:
  function test_display_ids (line 88) | def test_display_ids() -> list[int]:
  function write_test_png (line 94) | def write_test_png(path: Path) -> None:
  function timestamp (line 99) | def timestamp() -> str:
  function default_filename (line 103) | def default_filename(fmt: str, prefix: str = "screenshot") -> str:
  function mac_default_dir (line 107) | def mac_default_dir() -> Path:
  function default_dir (line 124) | def default_dir(system: str) -> Path:
  function ensure_parent (line 145) | def ensure_parent(path: Path) -> None:
  function resolve_output_path (line 153) | def resolve_output_path(
  function multi_output_paths (line 180) | def multi_output_paths(base: Path, suffixes: list[str]) -> list[Path]:
  function run (line 191) | def run(cmd: list[str]) -> None:
  function swift_json (line 200) | def swift_json(script: Path, extra_args: list[str] | None = None) -> dict:
  function macos_screen_capture_granted (line 224) | def macos_screen_capture_granted(request: bool = False) -> bool:
  function ensure_macos_permissions (line 230) | def ensure_macos_permissions() -> None:
  function activate_app (line 244) | def activate_app(app: str) -> None:
  function macos_window_payload (line 250) | def macos_window_payload(args: argparse.Namespace, frontmost: bool, incl...
  function macos_display_indexes (line 263) | def macos_display_indexes() -> list[int]:
  function macos_window_ids (line 277) | def macos_window_ids(args: argparse.Namespace, capture_all: bool) -> lis...
  function list_macos_windows (line 306) | def list_macos_windows(args: argparse.Namespace) -> None:
  function list_test_macos_windows (line 322) | def list_test_macos_windows(args: argparse.Namespace) -> None:
  function resolve_macos_windows (line 333) | def resolve_macos_windows(args: argparse.Namespace) -> list[int]:
  function resolve_test_macos_windows (line 340) | def resolve_test_macos_windows(args: argparse.Namespace) -> list[int]:
  function capture_macos (line 347) | def capture_macos(
  function capture_linux (line 369) | def capture_linux(args: argparse.Namespace, output: Path) -> None:
  function main (line 420) | def main() -> None:

FILE: skills/.curated/security-ownership-map/scripts/build_ownership_map.py
  function parse_args (line 65) | def parse_args() -> argparse.Namespace:
  function load_sensitive_rules (line 206) | def load_sensitive_rules(path: str | None) -> list[tuple[str, str, float]]:
  function parse_date (line 225) | def parse_date(value: str) -> dt.datetime:
  function offset_minutes (line 232) | def offset_minutes(timestamp: dt.datetime) -> int | None:
  function format_offset (line 239) | def format_offset(minutes: int) -> str:
  function recency_weighted (line 245) | def recency_weighted(now: dt.datetime, when: dt.datetime, half_life_days...
  function match_sensitive (line 252) | def match_sensitive(path: str, rules: Iterable[tuple[str, str, float]]) ...
  function matches_glob (line 266) | def matches_glob(path: str, pattern: str) -> bool:
  function is_excluded (line 274) | def is_excluded(path: str, patterns: Iterable[str]) -> bool:
  function author_excluded (line 278) | def author_excluded(name: str, email: str, patterns: Iterable[re.Pattern...
  function compute_community_owners (line 285) | def compute_community_owners(
  function run_git_log (line 340) | def run_git_log(
  function iter_commits (line 384) | def iter_commits(lines: Iterable[list[str]]) -> Iterable[tuple[dict[str,...
  function ensure_out_dir (line 407) | def ensure_out_dir(path: str) -> Path:
  function write_csv (line 413) | def write_csv(path: Path, header: list[str], rows: Iterable[list[str]]) ...
  function build_ownership_map (line 421) | def build_ownership_map(args: argparse.Namespace) -> Path:
  function main (line 943) | def main() -> int:

FILE: skills/.curated/security-ownership-map/scripts/community_maintainers.py
  function parse_args (line 19) | def parse_args() -> argparse.Namespace:
  function parse_date (line 127) | def parse_date(value: str) -> dt.datetime:
  function month_key (line 137) | def month_key(timestamp: dt.datetime) -> str:
  function quarter_key (line 141) | def quarter_key(timestamp: dt.datetime) -> str:
  function month_end (line 146) | def month_end(timestamp: dt.datetime) -> dt.datetime:
  function quarter_start (line 156) | def quarter_start(timestamp: dt.datetime) -> dt.datetime:
  function quarter_end (line 162) | def quarter_end(timestamp: dt.datetime) -> dt.datetime:
  function add_months (line 173) | def add_months(timestamp: dt.datetime, months: int) -> dt.datetime:
  function recency_weight (line 179) | def recency_weight(age_days: float, half_life_days: float) -> float:
  function read_csv (line 185) | def read_csv(path: Path) -> Iterable[dict[str, str]]:
  function load_people (line 191) | def load_people(data_dir: Path) -> dict[str, dict[str, str]]:
  function load_graph_json (line 203) | def load_graph_json(data_dir: Path) -> dict[str, object] | None:
  function find_file_node (line 213) | def find_file_node(nodes: list[dict[str, object]], query: str) -> dict[s...
  function load_community_files (line 226) | def load_community_files(
  function iter_commits_from_json (line 261) | def iter_commits_from_json(
  function iter_commits_from_git (line 304) | def iter_commits_from_git(
  function parse_git_block (line 350) | def parse_git_block(block: list[str]) -> Iterable[dict[str, object]]:
  function main (line 378) | def main() -> int:

FILE: skills/.curated/security-ownership-map/scripts/query_ownership.py
  function parse_args (line 15) | def parse_args() -> argparse.Namespace:
  function to_int (line 78) | def to_int(value: str) -> int:
  function to_float (line 85) | def to_float(value: str) -> float:
  function read_csv (line 92) | def read_csv(path: Path) -> Iterable[dict[str, str]]:
  function load_people (line 98) | def load_people(data_dir: Path) -> list[dict[str, object]]:
  function load_files (line 110) | def load_files(data_dir: Path) -> list[dict[str, object]]:
  function load_summary (line 125) | def load_summary(data_dir: Path) -> dict[str, object]:
  function load_communities (line 131) | def load_communities(data_dir: Path) -> list[dict[str, object]]:
  function load_cochange_edges (line 139) | def load_cochange_edges(data_dir: Path) -> Iterable[dict[str, object]]:
  function select_single (line 152) | def select_single(records: list[dict[str, object]], key: str, query: str...
  function top_edges_for_person (line 165) | def top_edges_for_person(data_dir: Path, person_id: str) -> list[dict[st...
  function top_edges_for_file (line 183) | def top_edges_for_file(data_dir: Path, file_id: str) -> list[dict[str, o...
  function sort_records (line 201) | def sort_records(records: list[dict[str, object]], key: str) -> list[dic...
  function handle_people (line 205) | def handle_people(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_files (line 227) | def handle_files(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_person (line 252) | def handle_person(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_file (line 286) | def handle_file(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_cochange (line 321) | def handle_cochange(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_tag (line 361) | def handle_tag(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_summary (line 408) | def handle_summary(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_communities (line 419) | def handle_communities(args: argparse.Namespace, data_dir: Path) -> None:
  function handle_community (line 433) | def handle_community(args: argparse.Namespace, data_dir: Path) -> None:
  function main (line 447) | def main() -> int:

FILE: skills/.curated/security-ownership-map/scripts/run_ownership_map.py
  function parse_args (line 12) | def parse_args() -> argparse.Namespace:
  function main (line 133) | def main() -> int:

FILE: skills/.curated/sentry/scripts/sentry_api.py
  function redact_string (line 21) | def redact_string(value):
  function redact_data (line 27) | def redact_data(value):
  function next_cursor (line 43) | def next_cursor(link_header):
  function request_json (line 54) | def request_json(url, token, retries=1):
  function build_url (line 81) | def build_url(base_url, path, params=None):
  function paged_get (line 89) | def paged_get(base_url, path, params, token, limit):
  function require_org_project (line 108) | def require_org_project(org, project):
  function handle_list_issues (line 115) | def handle_list_issues(args, token, base_url):
  function handle_issue_detail (line 130) | def handle_issue_detail(args, token, base_url):
  function handle_issue_events (line 137) | def handle_issue_events(args, token, base_url):
  function handle_event_detail (line 144) | def handle_event_detail(args, token, base_url):
  function build_parser (line 155) | def build_parser():
  function main (line 206) | def main():

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/code.js
  constant THEME_MAP (line 6) | let THEME_MAP;
  function loadPrismLanguage (line 8) | function loadPrismLanguage(lang) {
  function buildThemeMap (line 48) | function buildThemeMap(themeCssModule = "prismjs/themes/prism-okaidia.cs...
  function getThemeMap (line 63) | function getThemeMap() {
  function run (line 68) | function run(text, type = "plain") {
  function tokensToRuns (line 80) | function tokensToRuns(tokens) {
  function codeToRuns (line 90) | function codeToRuns(code, lang) {

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/image.js
  function readInputAsBuffer (line 8) | function readInputAsBuffer(source) {
  function isPng (line 41) | function isPng(buf) {
  function isJpeg (line 55) | function isJpeg(buf) {
  function isGif (line 61) | function isGif(buf) {
  function isWebp (line 73) | function isWebp(buf) {
  function isSvg (line 87) | function isSvg(buf) {
  function readPngSize (line 92) | function readPngSize(buf) {
  function readGifSize (line 99) | function readGifSize(buf) {
  function readWebpSize (line 105) | function readWebpSize(buf) {
  function readJpegSize (line 148) | function readJpegSize(buf) {
  function parseSvgSize (line 175) | function parseSvgSize(buf) {
  function getImageDimensions (line 231) | function getImageDimensions(pathOrData) {
  function imageSizingCrop (line 257) | function imageSizingCrop(source, x, y, w, h, cx, cy, cw, ch) {
  function imageSizingContain (line 310) | function imageSizingContain(source, x, y, w, h) {

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/index.js
  constant VERSION (line 4) | const VERSION = "1.2.0";

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/latex.js
  function ensureMathJax (line 8) | function ensureMathJax() {
  function latexToSvgDataUri (line 31) | function latexToSvgDataUri(latex, display = true) {

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/layout.js
  function inferElementType (line 4) | function inferElementType(obj) {
  constant TEXT_OVERLAP_ERROR_THRESHOLD (line 20) | const TEXT_OVERLAP_ERROR_THRESHOLD = 0.1;
  constant RECTIFY_DIRECTION_EQUALITY_TOLERANCE (line 21) | const RECTIFY_DIRECTION_EQUALITY_TOLERANCE = 0.15;
  function warnIfSlideHasOverlaps (line 23) | function warnIfSlideHasOverlaps(slide, pptx, options = {}) {
  function compareElementPosition (line 234) | function compareElementPosition(slide, firstIndex, secondIndex) {
  constant VALID_ALIGNMENTS (line 347) | const VALID_ALIGNMENTS = new Set([
  function alignSlideElements (line 462) | function alignSlideElements(slide, indices, alignment) {
  function distributeSlideElements (line 519) | function distributeSlideElements(slide, indices, direction) {
  function warnIfSlideElementsOutOfBounds (line 575) | function warnIfSlideElementsOutOfBounds(slide, pptx) {

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/layout_builders.js
  function addImageTextCard (line 14) | function addImageTextCard(slide, opts = {}) {
  function addCardRow (line 136) | function addCardRow(slide, region, cards = [], options = {}) {
  function addThreeLevelTree (line 174) | function addThreeLevelTree(slide, opts = {}) {
  function addConnector (line 342) | function addConnector(slide, x1, y1, x2, y2, line = {}) {
  function toNumberOr (line 355) | function toNumberOr(v, fallback) {

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/svg.js
  function toDataUri (line 4) | function toDataUri(svg) {
  function sanitizeSvg (line 8) | function sanitizeSvg(svg) {
  function svgToDataUri (line 28) | function svgToDataUri(svg) {

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/text.js
  constant TEXT_MEASURER (line 9) | const TEXT_MEASURER = getTextMeasurer();
  function calcTextBoxHeightSimple (line 18) | function calcTextBoxHeightSimple(
  function autoFontSize (line 42) | function autoFontSize(textOrRuns, fontFace, opts = {}) {
  function calcTextBox (line 206) | function calcTextBox(fontSizePt, opts = {}) {
  function layoutGivenWidth (line 363) | function layoutGivenWidth(paragraphs, boxW) {
  function greedyWrap (line 380) | function greedyWrap(paragraph, maxWidthIn) {
  function splitTextIntoTokens (line 423) | function splitTextIntoTokens(text) {
  function trimLineEnd (line 429) | function trimLineEnd(value) {
  function measureRunWidth (line 433) | function measureRunWidth(paragraph, text) {
  function forceBreakSegment (line 455) | function forceBreakSegment(text, start, maxWidthIn, paragraph) {
  function skipTextWhitespace (line 481) | function skipTextWhitespace(text, index) {
  function buildParagraphModels (line 487) | function buildParagraphModels(textOrRuns, baseStyle) {
  function collectParagraphEntries (line 495) | function collectParagraphEntries(textOrRuns) {
  function pushParagraphSegments (line 511) | function pushParagraphSegments(text, options, target) {
  function resolveParagraphStyle (line 523) | function resolveParagraphStyle(entry, baseStyle) {
  function getFontData (line 579) | function getFontData(face, fontStyle, fontWeight) {
  function makeFontCacheKey (line 606) | function makeFontCacheKey(face, fontStyle, fontWeight) {
  function registerCanvasFontVariant (line 613) | function registerCanvasFontVariant(
  function findFontPath (line 633) | function findFontPath(face, fontStyle, fontWeight) {
  function selectCollectionFont (line 658) | function selectCollectionFont(collection, fontStyle, fontWeight) {
  function scoreFontVariant (line 676) | function scoreFontVariant(font, wantItalic, wantBold) {
  function getWidthScaleForParagraph (line 692) | function getWidthScaleForParagraph(paragraph) {
  function buildPassthroughOptions (line 714) | function buildPassthroughOptions(opts, fontSizePt, margins) {
  function getTextMeasurer (line 733) | function getTextMeasurer() {
  function normalizeMargins (line 750) | function normalizeMargins(m) {
  function normalizeText (line 767) | function normalizeText(textOrRuns) {
  function toNumber (line 780) | function toNumber(v, fallback) {

FILE: skills/.curated/slides/assets/pptxgenjs_helpers/util.js
  function safeOuterShadow (line 5) | function safeOuterShadow(

FILE: skills/.curated/slides/scripts/create_montage.py
  function _make_placeholder (line 21) | def _make_placeholder(w: int, h: int) -> Image.Image:
  function _load_images_with_placeholders (line 31) | def _load_images_with_placeholders(
  function _natural_key (line 58) | def _natural_key(s: str) -> list:
  function create_montage (line 63) | def create_montage(
  function main (line 201) | def main() -> None:

FILE: skills/.curated/slides/scripts/detect_font.py
  function normalize_font_family_name (line 102) | def normalize_font_family_name(name: str) -> str:
  function _or_dummy (line 109) | def _or_dummy(node: ET.Element | None) -> ET.Element:
  function _build_fc_synonym_map (line 118) | def _build_fc_synonym_map() -> dict[str, set[str]]:
  function _expand_via_fontconfig (line 149) | def _expand_via_fontconfig(family_base_norm: str) -> set[str]:
  function parse_font_family_base_and_styles (line 161) | def parse_font_family_base_and_styles(name_norm: str) -> tuple[str, set[...
  function _split_odf_family_list (line 233) | def _split_odf_family_list(value: str) -> list[str]:
  function extract_used_fonts_from_pptx (line 242) | def extract_used_fonts_from_pptx(pptx_path: str) -> dict[int, set[str]]:
  function _detect_script_tag (line 282) | def _detect_script_tag(text: str) -> str:
  function _collect_default_font_faces (line 324) | def _collect_default_font_faces(root: ET.Element) -> dict[str, set[str]]:
  function _run_soffice_convert (line 337) | def _run_soffice_convert(cmd: list[str]) -> None:
  function _export_to_odp (line 347) | def _export_to_odp(pptx_path: str, user_profile: str, out_dir: str, stem...
  function _collect_face_map (line 366) | def _collect_face_map(root: ET.Element, ns: dict[str, str]) -> dict[str,...
  function _families_from_text_properties (line 382) | def _families_from_text_properties(
  function _extract_styles_from_container (line 420) | def _extract_styles_from_container(
  function _build_style_map (line 447) | def _build_style_map(
  function _lookup_style_families (line 514) | def _lookup_style_families(
  function _collect_slide_families (line 550) | def _collect_slide_families(
  function _build_style_map_text (line 589) | def _build_style_map_text(xml_text: str) -> dict[str, set[str]]:
  function _extract_slide_families_from_odp (line 616) | def _extract_slide_families_from_odp(odp_path: str) -> dict[int, set[str]]:
  function _build_master_page_map (line 689) | def _build_master_page_map(
  function detect_missing_fonts_odp (line 733) | def detect_missing_fonts_odp(pptx_path: str) -> tuple[set[str], dict[int...
  function main (line 765) | def main() -> None:

FILE: skills/.curated/slides/scripts/ensure_raster_image.py
  function _imagemagick_convert (line 71) | def _imagemagick_convert(src_path: str, dst_path: str) -> None:
  function ensure_raster_image (line 76) | def ensure_raster_image(path: str, out_dir: str | None = None) -> str:
  function main (line 162) | def main() -> None:

FILE: skills/.curated/slides/scripts/render_slides.py
  function calc_dpi_via_ooxml (line 19) | def calc_dpi_via_ooxml(input_path: str, max_w_px: int, max_h_px: int) ->...
  function calc_dpi_via_pdf (line 37) | def calc_dpi_via_pdf(input_path: str, max_w_px: int, max_h_px: int) -> int:
  function run_cmd_no_check (line 98) | def run_cmd_no_check(cmd: list[str]) -> None:
  function convert_to_pdf (line 108) | def convert_to_pdf(
  function rasterize (line 173) | def rasterize(
  function main (line 226) | def main() -> None:

FILE: skills/.curated/slides/scripts/slides_test.py
  function px_to_emu (line 29) | def px_to_emu(px: int, dpi: int) -> Emu:
  function calc_tol (line 33) | def calc_tol(dpi: int) -> int:
  function enlarge_deck (line 42) | def enlarge_deck(src: str, dst: str, pad_emu: Emu) -> tuple[int, int]:
  function inspect_images (line 83) | def inspect_images(
  function main (line 133) | def main() -> None:

FILE: skills/.curated/sora/scripts/sora.py
  function _die (line 49) | def _die(message: str, code: int = 1) -> None:
  function _warn (line 54) | def _warn(message: str) -> None:
  function _ensure_api_key (line 58) | def _ensure_api_key(dry_run: bool) -> None:
  function _read_prompt (line 68) | def _read_prompt(prompt: Optional[str], prompt_file: Optional[str]) -> str:
  function _normalize_model (line 82) | def _normalize_model(model: Optional[str]) -> str:
  function _normalize_size (line 89) | def _normalize_size(size: Optional[str], model: str) -> str:
  function _normalize_seconds (line 98) | def _normalize_seconds(seconds: Optional[Union[int, str]]) -> str:
  function _normalize_variant (line 110) | def _normalize_variant(variant: Optional[str]) -> str:
  function _normalize_order (line 117) | def _normalize_order(order: Optional[str]) -> Optional[str]:
  function _normalize_poll_interval (line 126) | def _normalize_poll_interval(interval: Optional[float]) -> float:
  function _normalize_timeout (line 133) | def _normalize_timeout(timeout: Optional[float]) -> Optional[float]:
  function _default_out_path (line 142) | def _default_out_path(variant: str) -> Path:
  function _normalize_out_path (line 150) | def _normalize_out_path(out: Optional[str], variant: str) -> Path:
  function _normalize_json_out (line 162) | def _normalize_json_out(out: Optional[str], default_name: str) -> Option...
  function _normalize_input_reference_object (line 176) | def _normalize_input_reference_object(value: Any) -> Dict[str, str]:
  function _normalize_input_reference (line 191) | def _normalize_input_reference(
  function _normalize_characters (line 223) | def _normalize_characters(raw: Any) -> Optional[List[Dict[str, str]]]:
  function _open_input_reference (line 259) | def _open_input_reference(path: Optional[str]):
  function _open_video_upload (line 270) | def _open_video_upload(path: Optional[str], *, label: str) -> Any:
  function _create_client (line 281) | def _create_client():
  function _create_async_client (line 289) | def _create_async_client():
  function _make_request_options (line 303) | def _make_request_options(*, multipart: bool) -> Dict[str, Any]:
  function _video_post (line 310) | def _video_post(
  function _async_video_post (line 326) | async def _async_video_post(
  function _to_dict (line 342) | def _to_dict(obj: Any) -> Any:
  function _print_json (line 354) | def _print_json(obj: Any) -> None:
  function _print_request (line 358) | def _print_request(payload: Dict[str, Any]) -> None:
  function _slugify (line 362) | def _slugify(value: str) -> str:
  function _normalize_job (line 369) | def _normalize_job(job: Any, idx: int) -> Dict[str, Any]:
  function _read_jobs_jsonl (line 383) | def _read_jobs_jsonl(path: str) -> List[Dict[str, Any]]:
  function _merge_non_null (line 408) | def _merge_non_null(dst: Dict[str, Any], src: Dict[str, Any]) -> Dict[st...
  function _job_output_path (line 416) | def _job_output_path(out_dir: Path, idx: int, prompt: str, explicit_out:...
  function _extract_retry_after_seconds (line 427) | def _extract_retry_after_seconds(exc: Exception) -> Optional[float]:
  function _is_rate_limit_error (line 442) | def _is_rate_limit_error(exc: Exception) -> bool:
  function _is_transient_error (line 450) | def _is_transient_error(exc: Exception) -> bool:
  function _fields_from_args (line 460) | def _fields_from_args(args: argparse.Namespace) -> Dict[str, Optional[st...
  function _augment_prompt_fields (line 479) | def _augment_prompt_fields(augment: bool, prompt: str, fields: Dict[str,...
  function _augment_prompt (line 518) | def _augment_prompt(args: argparse.Namespace, prompt: str) -> str:
  function _get_status (line 523) | def _get_status(video: Any) -> Optional[str]:
  function _get_video_id (line 541) | def _get_video_id(video: Any) -> Optional[str]:
  function _poll_video (line 553) | def _poll_video(
  function _download_content (line 576) | def _download_content(client: Any, video_id: str, variant: str) -> Any:
  function _write_download (line 589) | def _write_download(data: Any, out_path: Path, *, force: bool) -> None:
  function _build_create_payload (line 604) | def _build_create_payload(args: argparse.Namespace, prompt: str) -> Dict...
  function _prepare_job_payload (line 629) | def _prepare_job_payload(
  function _write_json (line 698) | def _write_json(path: Path, obj: Any) -> None:
  function _write_json_out (line 704) | def _write_json_out(out_path: Optional[Path], obj: Any) -> None:
  function _create_one_with_retries (line 710) | async def _create_one_with_retries(
  function _run_create_batch (line 739) | async def _run_create_batch(args: argparse.Namespace) -> int:
  function _create_batch (line 815) | def _create_batch(args: argparse.Namespace) -> None:
  function _cmd_create (line 821) | def _cmd_create(args: argparse.Namespace) -> int:
  function _cmd_create_and_poll (line 850) | def _cmd_create_and_poll(args: argparse.Namespace) -> int:
  function _cmd_poll (line 924) | def _cmd_poll(args: argparse.Namespace) -> int:
  function _cmd_status (line 951) | def _cmd_status(args: argparse.Namespace) -> int:
  function _cmd_list (line 960) | def _cmd_list(args: argparse.Namespace) -> int:
  function _cmd_delete (line 978) | def _cmd_delete(args: argparse.Namespace) -> int:
  function _cmd_remix (line 987) | def _cmd_remix(args: argparse.Namespace) -> int:
  function _cmd_download (line 1006) | def _cmd_download(args: argparse.Namespace) -> int:
  function _cmd_create_character (line 1016) | def _cmd_create_character(args: argparse.Namespace) -> int:
  function _cmd_extend (line 1042) | def _cmd_extend(args: argparse.Namespace) -> int:
  function _cmd_edit (line 1069) | def _cmd_edit(args: argparse.Namespace) -> int:
  class _NullContext (line 1091) | class _NullContext:
    method __enter__ (line 1092) | def __enter__(self):
    method __exit__ (line 1095) | def __exit__(self, exc_type, exc, tb):
  class _SingleFile (line 1099) | class _SingleFile:
    method __init__ (line 1100) | def __init__(self, path: Path):
    method __enter__ (line 1104) | def __enter__(self):
    method __exit__ (line 1108) | def __exit__(self, exc_type, exc, tb):
  function _add_prompt_args (line 1117) | def _add_prompt_args(parser: argparse.ArgumentParser) -> None:
  function _add_create_args (line 1140) | def _add_create_args(parser: argparse.ArgumentParser) -> None:
  function _add_poll_args (line 1152) | def _add_poll_args(parser: argparse.ArgumentParser) -> None:
  function _add_download_args (line 1157) | def _add_download_args(parser: argparse.ArgumentParser) -> None:
  function _add_json_out (line 1164) | def _add_json_out(parser: argparse.ArgumentParser) -> None:
  function main (line 1168) | def main() -> int:

FILE: skills/.curated/speech/scripts/text_to_speech.py
  function _die (line 46) | def _die(message: str, code: int = 1) -> None:
  function _warn (line 51) | def _warn(message: str) -> None:
  function _ensure_api_key (line 55) | def _ensure_api_key(dry_run: bool) -> None:
  function _read_text (line 65) | def _read_text(text: Optional[str], text_file: Optional[str], label: str...
  function _validate_input (line 79) | def _validate_input(text: str) -> None:
  function _normalize_voice (line 88) | def _normalize_voice(voice: Optional[str]) -> str:
  function _normalize_format (line 99) | def _normalize_format(fmt: Optional[str]) -> str:
  function _normalize_speed (line 108) | def _normalize_speed(speed: Optional[float]) -> Optional[float]:
  function _normalize_output_path (line 120) | def _normalize_output_path(out: Optional[str], response_format: str) -> ...
  function _create_client (line 135) | def _create_client():
  function _extract_retry_after_seconds (line 143) | def _extract_retry_after_seconds(exc: Exception) -> Optional[float]:
  function _is_rate_limit_error (line 158) | def _is_rate_limit_error(exc: Exception) -> bool:
  function _is_transient_error (line 166) | def _is_transient_error(exc: Exception) -> bool:
  function _maybe_drop_instructions (line 176) | def _maybe_drop_instructions(model: str, instructions: Optional[str]) ->...
  function _print_payload (line 183) | def _print_payload(payload: Dict[str, Any]) -> None:
  function _write_audio (line 187) | def _write_audio(
  function _slugify (line 232) | def _slugify(value: str) -> str:
  function _read_jobs_jsonl (line 239) | def _read_jobs_jsonl(path: str) -> List[Dict[str, Any]]:
  function _job_input (line 263) | def _job_input(job: Dict[str, Any]) -> str:
  function _merge_non_null (line 271) | def _merge_non_null(base: Dict[str, Any], extra: Dict[str, Any]) -> Dict...
  function _enforce_rpm (line 279) | def _enforce_rpm(rpm: int) -> int:
  function _sleep_for_rate_limit (line 288) | def _sleep_for_rate_limit(last_ts: Optional[float], rpm: int) -> float:
  function _list_voices (line 299) | def _list_voices() -> None:
  function _run_speak (line 304) | def _run_speak(args: argparse.Namespace) -> int:
  function _run_speak_batch (line 354) | def _run_speak_batch(args: argparse.Namespace) -> int:
  function _add_common_args (line 438) | def _add_common_args(parser: argparse.ArgumentParser) -> None:
  function main (line 486) | def main() -> int:

FILE: skills/.curated/spreadsheet/references/examples/openpyxl/create_basic_spreadsheet.py
  function main (line 16) | def main() -> None:

FILE: skills/.curated/spreadsheet/references/examples/openpyxl/create_spreadsheet_with_styling.py
  function apply_header_style (line 21) | def apply_header_style(cell, fill_hex: str) -> None:
  function apply_highlight_style (line 27) | def apply_highlight_style(cell, fill_hex: str) -> None:
  function populate_game_sheet (line 33) | def populate_game_sheet(ws) -> None:
  function main (line 71) | def main() -> None:

FILE: skills/.curated/spreadsheet/references/examples/openpyxl/read_existing_spreadsheet.py
  function create_sample (line 16) | def create_sample(path: Path) -> Path:
  function main (line 32) | def main() -> None:

FILE: skills/.curated/spreadsheet/references/examples/openpyxl/styling_spreadsheet.py
  function main (line 16) | def main() -> None:

FILE: skills/.curated/transcribe/scripts/transcribe_diarize.py
  function _die (line 24) | def _die(message: str, code: int = 1) -> None:
  function _warn (line 29) | def _warn(message: str) -> None:
  function _ensure_api_key (line 33) | def _ensure_api_key(dry_run: bool) -> None:
  function _normalize_response_format (line 43) | def _normalize_response_format(value: Optional[str]) -> str:
  function _normalize_chunking_strategy (line 55) | def _normalize_chunking_strategy(value: Optional[str]) -> Any:
  function _guess_mime_type (line 67) | def _guess_mime_type(path: Path) -> str:
  function _encode_data_url (line 74) | def _encode_data_url(path: Path) -> str:
  function _parse_known_speakers (line 81) | def _parse_known_speakers(raw_items: List[str]) -> Tuple[List[str], List...
  function _output_extension (line 101) | def _output_extension(response_format: str) -> str:
  function _build_output_path (line 105) | def _build_output_path(
  function _create_client (line 126) | def _create_client():
  function _format_output (line 134) | def _format_output(result: Any, response_format: str) -> str:
  function _validate_audio (line 145) | def _validate_audio(path: Path) -> None:
  function _build_payload (line 155) | def _build_payload(
  function _run_one (line 177) | def _run_one(
  function main (line 189) | def main() -> None:

FILE: skills/.system/skill-creator/scripts/generate_openai_yaml.py
  function yaml_quote (line 52) | def yaml_quote(value):
  function format_display_name (line 57) | def format_display_name(skill_name):
  function generate_short_description (line 76) | def generate_short_description(display_name):
  function read_frontmatter_name (line 106) | def read_frontmatter_name(skill_dir):
  function parse_interface_overrides (line 132) | def parse_interface_overrides(raw_overrides):
  function write_openai_yaml (line 155) | def write_openai_yaml(skill_dir, skill_name, raw_overrides):
  function main (line 189) | def main():

FILE: skills/.system/skill-creator/scripts/init_skill.py
  function normalize_skill_name (line 197) | def normalize_skill_name(skill_name):
  function title_case_skill_name (line 206) | def title_case_skill_name(skill_name):
  function parse_resources (line 211) | def parse_resources(raw_resources):
  function create_resource_dirs (line 230) | def create_resource_dirs(skill_dir, skill_name, skill_title, resources, ...
  function init_skill (line 258) | def init_skill(skill_name, path, resources, include_examples, interface_...
  function main (line 333) | def main():

FILE: skills/.system/skill-creator/scripts/quick_validate.py
  function validate_skill (line 15) | def validate_skill(skill_path):

FILE: skills/.system/skill-installer/scripts/github_utils.py
  function github_request (line 10) | def github_request(url: str, user_agent: str) -> bytes:
  function github_api_contents_url (line 20) | def github_api_contents_url(repo: str, path: str, ref: str) -> str:

FILE: skills/.system/skill-installer/scripts/install-skill-from-github.py
  class Args (line 22) | class Args:
  class Source (line 33) | class Source:
  class InstallError (line 41) | class InstallError(Exception):
  function _codex_home (line 45) | def _codex_home() -> str:
  function _tmp_root (line 49) | def _tmp_root() -> str:
  function _request (line 55) | def _request(url: str) -> bytes:
  function _parse_github_url (line 59) | def _parse_github_url(url: str, default_ref: str) -> tuple[str, str, str...
  function _download_repo_zip (line 80) | def _download_repo_zip(owner: str, repo: str, ref: str, dest_dir: str) -...
  function _run_git (line 99) | def _run_git(args: list[str]) -> None:
  function _safe_extract_zip (line 105) | def _safe_extract_zip(zip_file: zipfile.ZipFile, dest_dir: str) -> None:
  function _validate_relative_path (line 115) | def _validate_relative_path(path: str) -> None:
  function _validate_skill_name (line 120) | def _validate_skill_name(name: str) -> None:
  function _git_sparse_checkout (line 128) | def _git_sparse_checkout(repo_url: str, ref: str, paths: list[str], dest...
  function _validate_skill (line 164) | def _validate_skill(path: str) -> None:
  function _copy_skill (line 172) | def _copy_skill(src: str, dest_dir: str) -> None:
  function _build_repo_url (line 179) | def _build_repo_url(owner: str, repo: str) -> str:
  function _build_repo_ssh (line 183) | def _build_repo_ssh(owner: str, repo: str) -> str:
  function _prepare_repo (line 187) | def _prepare_repo(source: Source, method: str, tmp_dir: str) -> str:
  function _resolve_source (line 209) | def _resolve_source(args: Args) -> Source:
  function _default_dest (line 243) | def _default_dest() -> str:
  function _parse_args (line 247) | def _parse_args(argv: list[str]) -> Args:
  function main (line 269) | def main(argv: list[str]) -> int:

FILE: skills/.system/skill-installer/scripts/list-skills.py
  class ListError (line 19) | class ListError(Exception):
  class Args (line 23) | class Args(argparse.Namespace):
  function _request (line 30) | def _request(url: str) -> bytes:
  function _codex_home (line 34) | def _codex_home() -> str:
  function _installed_skills (line 38) | def _installed_skills() -> set[str]:
  function _list_skills (line 50) | def _list_skills(repo: str, path: str, ref: str) -> list[str]:
  function _parse_args (line 68) | def _parse_args(argv: list[str]) -> Args:
  function main (line 86) | def main(argv: list[str]) -> int:
Condensed preview — 644 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,589K chars).
[
  {
    "path": ".gitignore",
    "chars": 75,
    "preview": "# macOS system files\n.DS_Store\n\n# Python bytecode files\n__pycache__/\n*.pyc\n"
  },
  {
    "path": "README.md",
    "chars": 1478,
    "preview": "# Agent Skills\n\nAgent Skills are folders of instructions, scripts, and resources that AI agents can discover and use to "
  },
  {
    "path": "contributing.md",
    "chars": 527,
    "preview": "## Contributing\n\n### Community values\n\n- **Be kind and inclusive.** Treat others with respect; we follow the [Contributo"
  },
  {
    "path": "skills/.curated/aspnet-core/LICENSE.txt",
    "chars": 11357,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "skills/.curated/aspnet-core/SKILL.md",
    "chars": 5544,
    "preview": "---\nname: aspnet-core\ndescription: Build, review, refactor, or architect ASP.NET Core web applications using current off"
  },
  {
    "path": "skills/.curated/aspnet-core/agents/openai.yaml",
    "chars": 222,
    "preview": "interface:\n  display_name: \"ASP.NET Core\"\n  short_description: \"[Windows only] Build and review ASP.NET Core web apps\"\n "
  },
  {
    "path": "skills/.curated/aspnet-core/references/_sections.md",
    "chars": 2412,
    "preview": "# Reference Sections\n\nUse this file as the routing table for the rest of the skill.\n\n## Start Here\n\n- New app or major r"
  },
  {
    "path": "skills/.curated/aspnet-core/references/apis-minimal-and-controllers.md",
    "chars": 3040,
    "preview": "# APIs: Minimal And Controllers\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis\n- htt"
  },
  {
    "path": "skills/.curated/aspnet-core/references/data-state-and-services.md",
    "chars": 2422,
    "preview": "# Data, State, And Services\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/data/\n- https://learn.microsoft.com"
  },
  {
    "path": "skills/.curated/aspnet-core/references/program-and-pipeline.md",
    "chars": 4182,
    "preview": "# Program And Pipeline\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/fundamentals/\n- https://learn.microsoft."
  },
  {
    "path": "skills/.curated/aspnet-core/references/realtime-grpc-and-background-work.md",
    "chars": 1896,
    "preview": "# Realtime, gRPC, And Background Work\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/signalr/introduction\n- ht"
  },
  {
    "path": "skills/.curated/aspnet-core/references/security-and-identity.md",
    "chars": 2941,
    "preview": "# Security And Identity\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/security/\n- https://learn.microsoft.com"
  },
  {
    "path": "skills/.curated/aspnet-core/references/source-map.md",
    "chars": 2040,
    "preview": "# ASP.NET Core Source Map\n\nThis skill is synthesized from the official ASP.NET Core documentation tree and overview page"
  },
  {
    "path": "skills/.curated/aspnet-core/references/stack-selection.md",
    "chars": 3700,
    "preview": "# Stack Selection\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/\n- https://learn.microsoft.com/aspnet/core/bl"
  },
  {
    "path": "skills/.curated/aspnet-core/references/testing-performance-and-operations.md",
    "chars": 2698,
    "preview": "# Testing, Performance, And Operations\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/test/integration-tests\n-"
  },
  {
    "path": "skills/.curated/aspnet-core/references/ui-blazor.md",
    "chars": 2478,
    "preview": "# Blazor\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/blazor/\n- https://learn.microsoft.com/aspnet/core/blaz"
  },
  {
    "path": "skills/.curated/aspnet-core/references/ui-mvc.md",
    "chars": 1954,
    "preview": "# MVC\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/mvc/overview\n- https://learn.microsoft.com/aspnet/core/mv"
  },
  {
    "path": "skills/.curated/aspnet-core/references/ui-razor-pages.md",
    "chars": 1937,
    "preview": "# Razor Pages\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/razor-pages/\n- https://learn.microsoft.com/aspnet"
  },
  {
    "path": "skills/.curated/aspnet-core/references/versioning-and-upgrades.md",
    "chars": 2085,
    "preview": "# Versioning And Upgrades\n\nPrimary docs:\n- https://learn.microsoft.com/aspnet/core/release-notes/\n- https://learn.micros"
  },
  {
    "path": "skills/.curated/chatgpt-apps/LICENSE.txt",
    "chars": 10774,
    "preview": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AN"
  },
  {
    "path": "skills/.curated/chatgpt-apps/SKILL.md",
    "chars": 19614,
    "preview": "---\nname: chatgpt-apps\ndescription: Build, scaffold, refactor, and troubleshoot ChatGPT Apps SDK applications that combi"
  },
  {
    "path": "skills/.curated/chatgpt-apps/agents/openai.yaml",
    "chars": 842,
    "preview": "interface:\n  display_name: \"ChatGPT Apps\"\n  short_description: \"Build and scaffold ChatGPT apps\"\n  default_prompt: \"Use "
  },
  {
    "path": "skills/.curated/chatgpt-apps/references/app-archetypes.md",
    "chars": 3514,
    "preview": "# App Archetypes\n\nLoad this reference before choosing a starting point for a new ChatGPT app. The goal is to keep the sk"
  },
  {
    "path": "skills/.curated/chatgpt-apps/references/apps-sdk-docs-workflow.md",
    "chars": 8139,
    "preview": "# Apps SDK Docs Workflow\n\nUse this reference to keep code generation aligned with current OpenAI Apps SDK docs.\n\n## Alwa"
  },
  {
    "path": "skills/.curated/chatgpt-apps/references/interactive-state-sync-patterns.md",
    "chars": 4281,
    "preview": "# Interactive State Sync Patterns\n\nUse this reference when building ChatGPT apps with long-lived widget state, repeated "
  },
  {
    "path": "skills/.curated/chatgpt-apps/references/repo-contract-and-validation.md",
    "chars": 2938,
    "preview": "# Repo Contract And Validation\n\nLoad this reference when scaffolding or reviewing a generated ChatGPT app repo.\n\nThe goa"
  },
  {
    "path": "skills/.curated/chatgpt-apps/references/search-fetch-standard.md",
    "chars": 2021,
    "preview": "# Search And Fetch Standard\n\nLoad this reference when the app is connector-like, data-only, sync-oriented, or meant to w"
  },
  {
    "path": "skills/.curated/chatgpt-apps/references/upstream-example-workflow.md",
    "chars": 3443,
    "preview": "# Upstream Example Workflow\n\nLoad this reference when starting a greenfield ChatGPT app or when deciding whether to adap"
  },
  {
    "path": "skills/.curated/chatgpt-apps/references/window-openai-patterns.md",
    "chars": 3872,
    "preview": "# Window.openai Patterns\n\nLoad this reference when a task needs ChatGPT-only widget features, when translating older exa"
  },
  {
    "path": "skills/.curated/chatgpt-apps/scripts/scaffold_node_ext_apps.mjs",
    "chars": 16371,
    "preview": "#!/usr/bin/env node\n\nimport { mkdirSync, writeFileSync, existsSync, readdirSync, lstatSync } from \"node:fs\";\nimport path"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/LICENSE.txt",
    "chars": 10776,
    "preview": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AN"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/SKILL.md",
    "chars": 7125,
    "preview": "---\nname: cloudflare-deploy\ndescription: Deploy applications and infrastructure to Cloudflare using Workers, Pages, and "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/agents/openai.yaml",
    "chars": 331,
    "preview": "interface:\n  display_name: \"Cloudflare Deploy\"\n  short_description: \"Deploy Workers, Pages, and platform services on Clo"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/agents-sdk/README.md",
    "chars": 2751,
    "preview": "# Cloudflare Agents SDK\n\nCloudflare Agents SDK enables building AI-powered agents on Durable Objects with state, WebSock"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/agents-sdk/api.md",
    "chars": 5861,
    "preview": "# API Reference\n\n## Agent Classes\n\n### AIChatAgent\n\nFor AI chat with auto-streaming, message history, tools, resumable s"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/agents-sdk/configuration.md",
    "chars": 3575,
    "preview": "# Configuration\n\n## Wrangler Setup\n\n```jsonc\n{\n  \"name\": \"my-agents-app\",\n  \"durable_objects\": {\n    \"bindings\": [\n     "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/agents-sdk/gotchas.md",
    "chars": 5096,
    "preview": "# Gotchas & Best Practices\n\n## Common Errors\n\n### \"setState() not syncing\"\n\n**Cause:** Mutating state directly or not ca"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/agents-sdk/patterns.md",
    "chars": 5594,
    "preview": "# Patterns & Use Cases\n\n## AI Chat w/Tools\n\n**Server (AIChatAgent):**\n\n```ts\nimport { AIChatAgent } from \"agents\";\nimpor"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-gateway/README.md",
    "chars": 6292,
    "preview": "# Cloudflare AI Gateway\n\nExpert guidance for implementing Cloudflare AI Gateway - a universal gateway for AI model provi"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-gateway/configuration.md",
    "chars": 2954,
    "preview": "# Configuration & Setup\n\n## Creating a Gateway\n\n### Dashboard\nAI > AI Gateway > Create Gateway > Configure (auth, cachin"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-gateway/dynamic-routing.md",
    "chars": 1811,
    "preview": "# Dynamic Routing\n\nConfigure complex routing in dashboard without code changes. Use route names instead of model names.\n"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-gateway/features.md",
    "chars": 2698,
    "preview": "# Features & Capabilities\n\n## Caching\n\nDashboard: Settings → Cache Responses → Enable\n\n```typescript\n// Custom TTL (1 ho"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-gateway/sdk-integration.md",
    "chars": 2684,
    "preview": "# AI Gateway SDK Integration\n\n## Vercel AI SDK (Recommended)\n\n```typescript\nimport { createAiGateway } from 'ai-gateway-"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-gateway/troubleshooting.md",
    "chars": 2410,
    "preview": "# AI Gateway Troubleshooting\n\n## Common Errors\n\n| Error | Cause | Fix |\n|-------|-------|-----|\n| 401 | Missing `cf-aig-"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-search/README.md",
    "chars": 4509,
    "preview": "# Cloudflare AI Search Reference\n\nExpert guidance for implementing Cloudflare AI Search (formerly AutoRAG), Cloudflare's"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-search/api.md",
    "chars": 2519,
    "preview": "# AI Search API Reference\n\n## Workers Binding\n\n```typescript\nconst answer = await env.AI.autorag(\"instance-name\").aiSear"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-search/configuration.md",
    "chars": 1746,
    "preview": "# AI Search Configuration\n\n## Worker Setup\n\n```jsonc\n// wrangler.jsonc\n{\n  \"ai\": { \"binding\": \"AI\" }\n}\n```\n\n```typescrip"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-search/gotchas.md",
    "chars": 2133,
    "preview": "# AI Search Gotchas\n\n## Type Safety\n\n**Timestamp precision:** Use seconds (10-digit), not milliseconds.\n```typescript\nco"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ai-search/patterns.md",
    "chars": 2008,
    "preview": "# AI Search Patterns\n\n## search() vs aiSearch()\n\n| Use | Method | Returns |\n|-----|--------|---------|\n| Custom UI, anal"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/analytics-engine/README.md",
    "chars": 3161,
    "preview": "# Cloudflare Workers Analytics Engine Reference\n\nExpert guidance for implementing unlimited-cardinality analytics at sca"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/analytics-engine/api.md",
    "chars": 3161,
    "preview": "# Analytics Engine API Reference\n\n## Writing Data\n\n### `writeDataPoint()`\n\nFire-and-forget (returns `void`, not Promise)"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/analytics-engine/configuration.md",
    "chars": 2361,
    "preview": "# Analytics Engine Configuration\n\n## Setup\n\n1. Add binding to `wrangler.jsonc`\n2. Deploy Worker\n3. Dataset created autom"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/analytics-engine/gotchas.md",
    "chars": 1994,
    "preview": "# Analytics Engine Gotchas\n\n## Critical Issues\n\n### Sampling at High Volumes\n\n**Problem:** Queries return fewer points t"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/analytics-engine/patterns.md",
    "chars": 2308,
    "preview": "# Analytics Engine Patterns\n\n## Use Cases\n\n| Use Case | Key Metrics | Index On |\n|----------|-------------|----------|\n|"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api/README.md",
    "chars": 2349,
    "preview": "# Cloudflare API Integration\n\nGuide for working with Cloudflare's REST API - authentication, SDK usage, common patterns,"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api/api.md",
    "chars": 4300,
    "preview": "# API Reference\n\n## Client Initialization\n\n### TypeScript\n\n```typescript\nimport Cloudflare from 'cloudflare';\n\nconst cli"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api/configuration.md",
    "chars": 3748,
    "preview": "# Configuration\n\n## Environment Variables\n\n### Set Variables\n\n| Platform | Command |\n|----------|---------|\n| Linux/macO"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api/gotchas.md",
    "chars": 5370,
    "preview": "# Gotchas & Troubleshooting\n\n## Rate Limits & 429 Errors\n\n**Actual Limits:**\n- **1200 requests / 5 minutes** per user/to"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api/patterns.md",
    "chars": 4639,
    "preview": "# Common Patterns\n\n## List All with Auto-Pagination\n\n**Problem:** API returns paginated results. Default page size is 20"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api-shield/README.md",
    "chars": 1746,
    "preview": "# Cloudflare API Shield Reference\n\nExpert guidance for API Shield - comprehensive API security suite for discovery, prot"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api-shield/api.md",
    "chars": 3900,
    "preview": "# API Reference\n\nBase: `/zones/{zone_id}/api_gateway`\n\n## Endpoints\n\n```bash\nGET /operations                    # List\nG"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api-shield/configuration.md",
    "chars": 5012,
    "preview": "# Configuration\n\n## Schema Validation 2.0 Setup\n\n> ⚠️ **Classic Schema Validation deprecated.** Use Schema Validation 2."
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api-shield/gotchas.md",
    "chars": 4939,
    "preview": "# Gotchas & Troubleshooting\n\n## Common Errors\n\n### \"Schema Validation 2.0 not working after migration\"\n\n**Cause:** Class"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/api-shield/patterns.md",
    "chars": 5840,
    "preview": "# Patterns & Use Cases\n\n## Protect API with Schema + JWT\n\n```bash\n# 1. Upload OpenAPI schema\nPOST /zones/{zone_id}/api_g"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/argo-smart-routing/README.md",
    "chars": 4042,
    "preview": "# Cloudflare Argo Smart Routing Skill Reference\n\n## Overview\n\nCloudflare Argo Smart Routing is a performance optimizatio"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/argo-smart-routing/api.md",
    "chars": 6579,
    "preview": "## API Reference\n\n**Note on Smart Shield:** Argo Smart Routing is being integrated into Cloudflare's Smart Shield produc"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/argo-smart-routing/configuration.md",
    "chars": 4455,
    "preview": "## Configuration Management\n\n**Note on Smart Shield Evolution:** Argo Smart Routing is being integrated into Smart Shiel"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/argo-smart-routing/gotchas.md",
    "chars": 4325,
    "preview": "## Best Practices Summary\n\n**Smart Shield Note:** Argo Smart Routing evolving into Smart Shield. Best practices below re"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/argo-smart-routing/patterns.md",
    "chars": 3043,
    "preview": "# Integration Patterns\n\n## Enable Argo + Tiered Cache\n\n```typescript\nasync function enableOptimalPerformance(client: Clo"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bindings/README.md",
    "chars": 4022,
    "preview": "# Cloudflare Bindings Skill Reference\n\nExpert guidance on Cloudflare Workers Bindings - the runtime APIs that connect Wo"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bindings/api.md",
    "chars": 5195,
    "preview": "# Bindings API Reference\n\n## TypeScript Types\n\nCloudflare generates binding types via `npx wrangler types`. This creates"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bindings/configuration.md",
    "chars": 4496,
    "preview": "# Binding Configuration Reference\n\n## Storage Bindings\n\n```jsonc\n{\n  \"kv_namespaces\": [{ \"binding\": \"MY_KV\", \"id\": \"...\""
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bindings/gotchas.md",
    "chars": 6147,
    "preview": "# Binding Gotchas and Troubleshooting\n\n## Critical: Global Scope Mutation\n\n### ❌ THE #1 GOTCHA: Caching env in Global Sc"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bindings/patterns.md",
    "chars": 5028,
    "preview": "# Binding Patterns and Best Practices\n\n## Service Binding Patterns\n\n### RPC via Service Bindings\n\n```typescript\n// auth-"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bot-management/README.md",
    "chars": 3698,
    "preview": "# Cloudflare Bot Management\n\nEnterprise-grade bot detection, protection, and mitigation using ML/heuristics, bot scores,"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bot-management/api.md",
    "chars": 5803,
    "preview": "# Bot Management API\n\n## Workers: BotManagement Interface\n\n```typescript\ninterface BotManagement {\n  score: number;     "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bot-management/configuration.md",
    "chars": 5742,
    "preview": "# Bot Management Configuration\n\n## Product Tiers\n\n**Note:** Dashboard paths differ between old and new UI:\n- **New:** Se"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bot-management/gotchas.md",
    "chars": 5647,
    "preview": "# Bot Management Gotchas\n\n## Common Errors\n\n### \"Bot Score = 0\"\n\n**Cause:** Bot Management didn't run (internal Cloudfla"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/bot-management/patterns.md",
    "chars": 4970,
    "preview": "# Bot Management Patterns\n\n## E-commerce Protection\n\n```txt\n# High security for checkout\n(cf.bot_management.score lt 50 "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/browser-rendering/README.md",
    "chars": 3084,
    "preview": "# Cloudflare Browser Rendering Skill Reference\n\n**Description**: Expert knowledge for Cloudflare Browser Rendering - con"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/browser-rendering/api.md",
    "chars": 2976,
    "preview": "# Browser Rendering API\n\n## REST API\n\n**Base:** `https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rende"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/browser-rendering/configuration.md",
    "chars": 1802,
    "preview": "# Configuration & Setup\n\n## Installation\n\n```bash\nnpm install @cloudflare/puppeteer  # or @cloudflare/playwright\n```\n\n**"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/browser-rendering/gotchas.md",
    "chars": 2512,
    "preview": "# Browser Rendering Gotchas\n\n## Tier Limits\n\n| Limit | Free | Paid |\n|-------|------|------|\n| Daily browser time | 10 m"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/browser-rendering/patterns.md",
    "chars": 2647,
    "preview": "# Browser Rendering Patterns\n\n## Basic Worker\n\n```typescript\nimport puppeteer from \"@cloudflare/puppeteer\";\n\nexport defa"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/c3/README.md",
    "chars": 3282,
    "preview": "# C3 (create-cloudflare)\n\nOfficial CLI for scaffolding Cloudflare Workers and Pages projects with templates, TypeScript,"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/c3/api.md",
    "chars": 2286,
    "preview": "# C3 CLI Reference\n\n## Invocation\n\n```bash\nnpm create cloudflare@latest [name] [-- flags]  # NPM requires --\nyarn create"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/c3/configuration.md",
    "chars": 1607,
    "preview": "# C3 Generated Configuration\n\n## Output Structure\n\n```\nmy-app/\n├── src/index.ts          # Worker entry point\n├── wrangl"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/c3/gotchas.md",
    "chars": 2307,
    "preview": "# C3 Troubleshooting\n\n## Deployment Issues\n\n### Placeholder IDs\n\n**Error:** \"Invalid namespace ID\"  \n**Fix:** Replace pl"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/c3/patterns.md",
    "chars": 2203,
    "preview": "# C3 Usage Patterns\n\n## Quick Workflows\n\n```bash\n# TypeScript API Worker\nnpm create cloudflare@latest my-api -- --type=h"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cache-reserve/README.md",
    "chars": 5535,
    "preview": "# Cloudflare Cache Reserve\n\n**Persistent cache storage built on R2 for long-term content retention**\n\n## Smart Shield In"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cache-reserve/api.md",
    "chars": 5704,
    "preview": "# Cache Reserve API\n\n## Workers Integration\n\n```\n┌────────────────────────────────────────────────────────────────┐\n│ CR"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cache-reserve/configuration.md",
    "chars": 3660,
    "preview": "# Cache Reserve Configuration\n\n## Dashboard Setup\n\n**Minimum steps to enable:**\n\n```bash\n# Navigate to dashboard\nhttps:/"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cache-reserve/gotchas.md",
    "chars": 5757,
    "preview": "# Cache Reserve Gotchas\n\n## Common Errors\n\n### \"Assets Not Being Cached in Cache Reserve\"\n\n**Cause:** Asset is not cache"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cache-reserve/patterns.md",
    "chars": 6259,
    "preview": "# Cache Reserve Patterns\n\n## Best Practices\n\n### 1. Always Enable Tiered Cache\n\n```typescript\n// Cache Reserve is design"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/containers/README.md",
    "chars": 3511,
    "preview": "# Cloudflare Containers Skill Reference\n\n**APPLIES TO: Cloudflare Containers ONLY - NOT general Cloudflare Workers**\n\nUs"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/containers/api.md",
    "chars": 4288,
    "preview": "## Container Class API\n\n```typescript\nimport { Container } from \"@cloudflare/containers\";\n\nexport class MyContainer exte"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/containers/configuration.md",
    "chars": 5424,
    "preview": "## Wrangler Configuration\n\n### Basic Container Config\n\n```jsonc\n{\n  \"name\": \"my-worker\",\n  \"main\": \"src/index.ts\",\n  \"co"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/containers/gotchas.md",
    "chars": 4447,
    "preview": "## Critical Gotchas\n\n### ⚠️ WebSocket: fetch() vs containerFetch()\n\n**Problem:** WebSocket connections fail silently\n\n**"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/containers/patterns.md",
    "chars": 4917,
    "preview": "## Routing Patterns\n\n### Session Affinity (Stateful)\n\n```typescript\nexport class SessionBackend extends Container {\n  de"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cron-triggers/README.md",
    "chars": 2849,
    "preview": "# Cloudflare Cron Triggers\n\nSchedule Workers execution using cron expressions. Runs on Cloudflare's global network durin"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cron-triggers/api.md",
    "chars": 5866,
    "preview": "# Cron Triggers API\n\n## Basic Handler\n\n```typescript\nexport default {\n  async scheduled(controller: ScheduledController,"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cron-triggers/configuration.md",
    "chars": 4246,
    "preview": "# Cron Triggers Configuration\n\n## wrangler.jsonc\n\n```jsonc\n{\n  \"$schema\": \"./node_modules/wrangler/config-schema.json\",\n"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cron-triggers/gotchas.md",
    "chars": 6302,
    "preview": "# Cron Triggers Gotchas\n\n## Common Errors\n\n### \"Timezone Issues\"\n\n**Problem:** Cron runs at wrong time relative to local"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/cron-triggers/patterns.md",
    "chars": 6974,
    "preview": "# Cron Triggers Patterns\n\n## API Data Sync\n\n```typescript\nexport default {\n  async scheduled(controller, env, ctx) {\n   "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/d1/README.md",
    "chars": 4711,
    "preview": "# Cloudflare D1 Database\n\nExpert guidance for Cloudflare D1, a serverless SQLite database designed for horizontal scale-"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/d1/api.md",
    "chars": 6802,
    "preview": "# D1 API Reference\n\n## Prepared Statements (Required for Security)\n\n```typescript\n// ❌ NEVER: Direct string interpolatio"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/d1/configuration.md",
    "chars": 5378,
    "preview": "# D1 Configuration\n\n## wrangler.jsonc Setup\n\n```jsonc\n{\n  \"name\": \"your-worker-name\",\n  \"main\": \"src/index.ts\",\n  \"compa"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/d1/gotchas.md",
    "chars": 4310,
    "preview": "# D1 Gotchas & Troubleshooting\n\n## Common Errors\n\n### \"SQL Injection Vulnerability\"\n\n**Cause:** Using string interpolati"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/d1/patterns.md",
    "chars": 7241,
    "preview": "# D1 Patterns & Best Practices\n\n## Pagination\n\n```typescript\nasync function getUsers({ page, pageSize }: { page: number;"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ddos/README.md",
    "chars": 2004,
    "preview": "# Cloudflare DDoS Protection\n\nAutonomous, always-on protection against DDoS attacks across L3/4 and L7.\n\n## Protection T"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ddos/api.md",
    "chars": 4170,
    "preview": "# DDoS API\n\n## Endpoints\n\n### HTTP DDoS (L7)\n\n```typescript\n// Zone-level\nPUT /zones/{zoneId}/rulesets/phases/ddos_l7/en"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ddos/configuration.md",
    "chars": 2999,
    "preview": "# DDoS Configuration\n\n## Dashboard Setup\n\n1. Navigate to Security > DDoS\n2. Select HTTP DDoS or Network-layer DDoS\n3. Co"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ddos/gotchas.md",
    "chars": 3890,
    "preview": "# DDoS Gotchas\n\n## Common Errors\n\n### \"False positives blocking legitimate traffic\"\n\n**Cause**: Sensitivity too high, wr"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/ddos/patterns.md",
    "chars": 5680,
    "preview": "# DDoS Protection Patterns\n\n## Allowlist Trusted IPs\n\n```typescript\nconst config = {\n  description: \"Allowlist trusted I"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/do-storage/README.md",
    "chars": 2749,
    "preview": "# Cloudflare Durable Objects Storage\n\nPersistent storage API for Durable Objects with SQLite and KV backends, PITR, and "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/do-storage/api.md",
    "chars": 3571,
    "preview": "# DO Storage API Reference\n\n## SQL API\n\n```typescript\nconst cursor = this.sql.exec('SELECT * FROM users WHERE email = ?'"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/do-storage/configuration.md",
    "chars": 2235,
    "preview": "# DO Storage Configuration\n\n## SQLite-backed (Recommended)\n\n**wrangler.jsonc:**\n```jsonc\n{\n  \"migrations\": [\n    {\n     "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/do-storage/gotchas.md",
    "chars": 5198,
    "preview": "# DO Storage Gotchas & Troubleshooting\n\n## Concurrency Model (CRITICAL)\n\nDurable Objects use **input/output gates** to p"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/do-storage/patterns.md",
    "chars": 5278,
    "preview": "# DO Storage Patterns & Best Practices\n\n## Schema Migration\n\n```typescript\nexport class MyDurableObject extends DurableO"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/do-storage/testing.md",
    "chars": 4912,
    "preview": "# DO Storage Testing\n\nTesting Durable Objects with storage using `vitest-pool-workers`.\n\n## Setup\n\n**vitest.config.ts:**"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/durable-objects/README.md",
    "chars": 6455,
    "preview": "# Cloudflare Durable Objects\n\nExpert guidance for building stateful applications with Cloudflare Durable Objects.\n\n## Re"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/durable-objects/api.md",
    "chars": 6142,
    "preview": "# Durable Objects API\n\n## Class Structure\n\n```typescript\nimport { DurableObject } from \"cloudflare:workers\";\n\nexport cla"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/durable-objects/configuration.md",
    "chars": 4264,
    "preview": "# Durable Objects Configuration\n\n## Basic Setup\n\n```jsonc\n{\n  \"name\": \"my-worker\",\n  \"main\": \"src/index.ts\",\n  \"compatib"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/durable-objects/gotchas.md",
    "chars": 7296,
    "preview": "# Durable Objects Gotchas\n\n## Common Errors\n\n### \"Hibernation Cleared My In-Memory State\"\n\n**Problem:** Variables lost a"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/durable-objects/patterns.md",
    "chars": 6689,
    "preview": "# Durable Objects Patterns\n\n## When to Use Which Pattern\n\n| Need | Pattern | ID Strategy |\n|------|---------|-----------"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-routing/README.md",
    "chars": 3333,
    "preview": "# Cloudflare Email Routing Skill Reference\n\n## Overview\n\nCloudflare Email Routing enables custom email addresses for you"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-routing/api.md",
    "chars": 5311,
    "preview": "# Email Routing API Reference\n\n## Worker Runtime API\n\n### Email Handler Interface\n\n```typescript\ninterface ExportedHandl"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-routing/configuration.md",
    "chars": 3571,
    "preview": "# Email Routing Configuration\n\n## Wrangler Configuration\n\n### Basic Email Worker\n\n```jsonc\n// wrangler.jsonc\n{\n  \"name\":"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-routing/gotchas.md",
    "chars": 4094,
    "preview": "# Gotchas & Troubleshooting\n\n## Critical Pitfalls\n\n### Stream Consumption (MOST COMMON)\n\n**Problem:** \"stream already co"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-routing/patterns.md",
    "chars": 5480,
    "preview": "# Common Patterns\n\n## 1. Allowlist/Blocklist\n\n```typescript\n// Allowlist\nconst allowed = [\"user@example.com\", \"trusted@c"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-workers/README.md",
    "chars": 5288,
    "preview": "# Cloudflare Email Workers\n\nProcess incoming emails programmatically using Cloudflare Workers runtime.\n\n## Overview\n\nEma"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-workers/api.md",
    "chars": 6078,
    "preview": "# Email Workers API Reference\n\nComplete API reference for Cloudflare Email Workers runtime.\n\n## ForwardableEmailMessage "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-workers/configuration.md",
    "chars": 2705,
    "preview": "# Email Workers Configuration\n\n## wrangler.jsonc\n\n```jsonc\n{\n  \"name\": \"email-worker\",\n  \"main\": \"src/index.ts\",\n  \"comp"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-workers/gotchas.md",
    "chars": 3029,
    "preview": "# Email Workers Gotchas\n\n## Critical Issues\n\n### ReadableStream Single-Use\n\n```typescript\n// ❌ WRONG: Stream consumed tw"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/email-workers/patterns.md",
    "chars": 2783,
    "preview": "# Email Workers Patterns\n\n## Parse Email\n\n```typescript\nimport PostalMime from 'postal-mime';\n\nexport default {\n  async "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/hyperdrive/README.md",
    "chars": 2903,
    "preview": "# Hyperdrive\n\nAccelerates database queries from Workers via connection pooling, edge setup, query caching.\n\n## Key Featu"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/hyperdrive/api.md",
    "chars": 3859,
    "preview": "# API Reference\n\nSee [README.md](./README.md) for overview, [configuration.md](./configuration.md) for setup.\n\n## Bindin"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/hyperdrive/configuration.md",
    "chars": 3899,
    "preview": "# Configuration\n\nSee [README.md](./README.md) for overview.\n\n## Create Config\n\n**PostgreSQL:**\n```bash\n# Basic\nnpx wrang"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/hyperdrive/gotchas.md",
    "chars": 3926,
    "preview": "# Gotchas\n\nSee [README.md](./README.md), [configuration.md](./configuration.md), [api.md](./api.md), [patterns.md](./pat"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/hyperdrive/patterns.md",
    "chars": 5958,
    "preview": "# Patterns\n\nSee [README.md](./README.md), [configuration.md](./configuration.md), [api.md](./api.md).\n\n## High-Traffic R"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/images/README.md",
    "chars": 2886,
    "preview": "# Cloudflare Images Skill Reference\n\n**Cloudflare Images** is an end-to-end image management solution providing storage,"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/images/api.md",
    "chars": 2574,
    "preview": "# API Reference\n\n## Workers Binding API\n\n```toml\n# wrangler.toml\n[images]\nbinding = \"IMAGES\"\n```\n\n### Transform Images\n\n"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/images/configuration.md",
    "chars": 4116,
    "preview": "# Configuration\n\n## Wrangler Integration\n\n### Workers Binding Setup\n\nAdd to `wrangler.toml`:\n\n```toml\nname = \"my-image-w"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/images/gotchas.md",
    "chars": 2474,
    "preview": "# Gotchas & Best Practices\n\n## Fit Modes\n\n| Mode | Best For | Behavior |\n|------|----------|----------|\n| `cover` | Hero"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/images/patterns.md",
    "chars": 3582,
    "preview": "# Common Patterns\n\n## URL Transform Options\n\n```\nwidth=<PX>   height=<PX>   fit=scale-down|contain|cover|crop|pad\nqualit"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/kv/README.md",
    "chars": 2853,
    "preview": "# Cloudflare Workers KV\n\nGlobally-distributed, eventually-consistent key-value store optimized for high read volume and "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/kv/api.md",
    "chars": 4327,
    "preview": "# KV API Reference\n\n## Read Operations\n\n```typescript\n// Single key (string)\nconst value = await env.MY_KV.get(\"user:123"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/kv/configuration.md",
    "chars": 3083,
    "preview": "# KV Configuration\n\n## Create Namespace\n\n```bash\nwrangler kv namespace create MY_NAMESPACE\n# Output: { binding = \"MY_NAM"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/kv/gotchas.md",
    "chars": 4433,
    "preview": "# KV Gotchas & Troubleshooting\n\n## Common Errors\n\n### \"Stale Read After Write\"\n\n**Cause:** Eventual consistency means wr"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/kv/patterns.md",
    "chars": 4730,
    "preview": "# KV Patterns & Best Practices\n\n## Multi-Tier Caching\n\n```typescript\n// Memory → KV → Origin (3-tier cache)\nconst memory"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/miniflare/README.md",
    "chars": 2880,
    "preview": "# Miniflare\n\nLocal simulator for Cloudflare Workers development/testing. Runs Workers in workerd sandbox implementing ru"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/miniflare/api.md",
    "chars": 4606,
    "preview": "# Programmatic API\n\n## Miniflare Class\n\n```typescript\nclass Miniflare {\n  constructor(options: MiniflareOptions);\n  \n  /"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/miniflare/configuration.md",
    "chars": 3525,
    "preview": "# Configuration\n\n## Script Loading\n\n```js\n// Inline\nnew Miniflare({ modules: true, script: `export default { ... }` });\n"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/miniflare/gotchas.md",
    "chars": 3720,
    "preview": "# Gotchas & Troubleshooting\n\n## Miniflare Limitations\n\n**Not supported:**\n- Analytics Engine (use mocks)\n- Cloudflare Im"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/miniflare/patterns.md",
    "chars": 4254,
    "preview": "# Testing Patterns\n\n## Choosing a Testing Approach\n\n| Approach | Use Case | Speed | Setup | Runtime |\n|----------|------"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/network-interconnect/README.md",
    "chars": 3194,
    "preview": "# Cloudflare Network Interconnect (CNI)\n\nPrivate, high-performance connectivity to Cloudflare's network. **Enterprise-on"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/network-interconnect/api.md",
    "chars": 5626,
    "preview": "# CNI API Reference\n\nSee [README.md](README.md) for overview.\n\n## Base\n\n```\nhttps://api.cloudflare.com/client/v4\nAuth: A"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/network-interconnect/configuration.md",
    "chars": 4235,
    "preview": "# CNI Configuration\n\nSee [README.md](README.md) for overview.\n\n## Workflow (2-4 weeks)\n\n1. **Submit request** (Week 1): "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/network-interconnect/gotchas.md",
    "chars": 5542,
    "preview": "# CNI Gotchas & Troubleshooting\n\n## Common Errors\n\n### \"Status: Pending\"\n\n**Cause:** Cross-connect not installed, RX/TX "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/network-interconnect/patterns.md",
    "chars": 4013,
    "preview": "# CNI Patterns\n\nSee [README.md](README.md) for overview.\n\n## High Availability\n\n**Critical:** Design for resilience from"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/observability/README.md",
    "chars": 3795,
    "preview": "# Cloudflare Observability Skill Reference\n\n**Purpose**: Comprehensive guidance for implementing observability in Cloudf"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/observability/api.md",
    "chars": 3480,
    "preview": "## API Reference\n\n### GraphQL Analytics API\n\n**Endpoint**: `https://api.cloudflare.com/client/v4/graphql`\n\n**Query Worke"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/observability/configuration.md",
    "chars": 3580,
    "preview": "## Configuration Patterns\n\n### Enable Workers Logs\n\n```jsonc\n{\n  \"observability\": {\n    \"enabled\": true,\n    \"head_sampl"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/observability/gotchas.md",
    "chars": 3754,
    "preview": "## Common Errors\n\n### \"Logs not appearing\"\n\n**Cause:** Observability disabled, Worker not redeployed, no traffic, low sa"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/observability/patterns.md",
    "chars": 2481,
    "preview": "# Observability Patterns\n\n## Usage-Based Billing\n\n```typescript\nenv.ANALYTICS.writeDataPoint({\n  blobs: [customerId, req"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages/README.md",
    "chars": 2824,
    "preview": "# Cloudflare Pages\n\nJAMstack platform for full-stack apps on Cloudflare's global network.\n\n## Key Features\n\n- **Git-base"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages/api.md",
    "chars": 5958,
    "preview": "# Functions API\n\n## File-Based Routing\n\n```\n/functions/index.ts              → example.com/\n/functions/api/users.ts     "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages/configuration.md",
    "chars": 5855,
    "preview": "# Configuration\n\n## wrangler.jsonc\n\n```jsonc\n{\n  \"name\": \"my-pages-project\",\n  \"pages_build_output_dir\": \"./dist\",\n  \"co"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages/gotchas.md",
    "chars": 7988,
    "preview": "# Gotchas\n\n## Functions Not Running\n\n**Problem**: Function endpoints return 404 or don't execute  \n**Causes**: `_routes."
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages/patterns.md",
    "chars": 5978,
    "preview": "# Patterns\n\n## API Routes\n\n```typescript\n// functions/api/todos/[id].ts\nexport const onRequestGet: PagesFunction<Env> = "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages-functions/README.md",
    "chars": 3206,
    "preview": "# Cloudflare Pages Functions\n\nServerless functions on Cloudflare Pages using Workers runtime. Full-stack dev with file-b"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages-functions/api.md",
    "chars": 4677,
    "preview": "# Function API\n\n## EventContext\n\n```typescript\ninterface EventContext<Env = any> {\n  request: Request;              // I"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages-functions/configuration.md",
    "chars": 2996,
    "preview": "# Configuration\n\n## TypeScript Setup\n\n**Generate types from wrangler.jsonc** (replaces deprecated `@cloudflare/workers-t"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages-functions/gotchas.md",
    "chars": 3842,
    "preview": "# Gotchas & Debugging\n\n## Error Diagnosis\n\n| Symptom | Likely Cause | Solution |\n|---------|--------------|----------|\n|"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pages-functions/patterns.md",
    "chars": 4214,
    "preview": "# Common Patterns\n\n## Background Tasks (waitUntil)\n\nNon-blocking tasks after response sent (analytics, cleanup, webhooks"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pipelines/README.md",
    "chars": 3360,
    "preview": "# Cloudflare Pipelines\n\nETL streaming platform for ingesting, transforming, and loading data into R2 with SQL transforma"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pipelines/api.md",
    "chars": 5099,
    "preview": "# Pipelines API Reference\n\n## Pipeline Binding Interface\n\n```typescript\n// From @cloudflare/workers-types\ninterface Pipe"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pipelines/configuration.md",
    "chars": 2735,
    "preview": "# Pipelines Configuration\n\n## Worker Binding\n\n```jsonc\n// wrangler.jsonc\n{\n  \"pipelines\": [\n    { \"pipeline\": \"<STREAM_I"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pipelines/gotchas.md",
    "chars": 2427,
    "preview": "# Pipelines Gotchas\n\n## Critical Issues\n\n### Events Silently Dropped\n\n**Most common issue.** Events accepted (HTTP 200) "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pipelines/patterns.md",
    "chars": 2080,
    "preview": "# Pipelines Patterns\n\n## Fire-and-Forget\n\n```typescript\nexport default {\n  async fetch(request, env, ctx) {\n    const ev"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pulumi/README.md",
    "chars": 3231,
    "preview": "# Cloudflare Pulumi Provider\n\nExpert guidance for Cloudflare Pulumi Provider (@pulumi/cloudflare).\n\n## Overview\n\nProgram"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pulumi/api.md",
    "chars": 5761,
    "preview": "# API & Data Sources\n\n## Outputs and Exports\n\nExport resource identifiers:\n\n```typescript\nexport const kvId = kv.id;\nexp"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pulumi/configuration.md",
    "chars": 5657,
    "preview": "# Resource Configuration\n\n## Workers (cloudflare.WorkerScript)\n\n```typescript\nimport * as cloudflare from \"@pulumi/cloud"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pulumi/gotchas.md",
    "chars": 6536,
    "preview": "# Troubleshooting & Best Practices\n\n## Common Errors\n\n### \"No bundler/build step\" - Pulumi uploads raw code\n\n**Problem:*"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/pulumi/patterns.md",
    "chars": 6974,
    "preview": "# Architecture Patterns\n\n## Component Resources\n\n```typescript\nclass WorkerApp extends pulumi.ComponentResource {\n    co"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/queues/README.md",
    "chars": 3044,
    "preview": "# Cloudflare Queues\n\nFlexible message queuing for async task processing with guaranteed at-least-once delivery and confi"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/queues/api.md",
    "chars": 5559,
    "preview": "# Queues API Reference\n\n## Producer: Send Messages\n\n```typescript\n// Basic send\nawait env.MY_QUEUE.send({ url: request.u"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/queues/configuration.md",
    "chars": 3820,
    "preview": "# Queues Configuration\n\n## Create Queue\n\n```bash\nwrangler queues create my-queue\nwrangler queues create my-queue --reten"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/queues/gotchas.md",
    "chars": 7217,
    "preview": "# Queues Gotchas & Troubleshooting\n\n## CRITICAL: Top Production Mistakes\n\n### 1. \"Entire Batch Retried After Single Erro"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/queues/patterns.md",
    "chars": 5494,
    "preview": "# Queues Patterns & Best Practices\n\n## Async Task Processing\n\n```typescript\n// Producer: Accept request, queue work\nexpo"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2/README.md",
    "chars": 2819,
    "preview": "# Cloudflare R2 Object Storage\n\nS3-compatible object storage with zero egress fees, optimized for large file storage and"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2/api.md",
    "chars": 5649,
    "preview": "# R2 API Reference\n\n## PUT (Upload)\n\n```typescript\n// Basic\nawait env.MY_BUCKET.put(key, value);\n\n// With metadata\nawait"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2/configuration.md",
    "chars": 3654,
    "preview": "# R2 Configuration\n\n## Workers Binding\n\n**wrangler.jsonc:**\n```jsonc\n{\n  \"r2_buckets\": [\n    {\n      \"binding\": \"MY_BUCK"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2/gotchas.md",
    "chars": 5014,
    "preview": "# R2 Gotchas & Troubleshooting\n\n## List Truncation\n\n```typescript\n// ❌ WRONG: Don't compare object count when using incl"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2/patterns.md",
    "chars": 5844,
    "preview": "# R2 Patterns & Best Practices\n\n## Streaming Large Files\n\n```typescript\nconst object = await env.MY_BUCKET.get(key);\nif "
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2-data-catalog/README.md",
    "chars": 6359,
    "preview": "# Cloudflare R2 Data Catalog Skill Reference\n\nExpert guidance for Cloudflare R2 Data Catalog - Apache Iceberg catalog bu"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2-data-catalog/api.md",
    "chars": 5981,
    "preview": "# API Reference\n\nR2 Data Catalog exposes standard [Apache Iceberg REST Catalog API](https://github.com/apache/iceberg/bl"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2-data-catalog/configuration.md",
    "chars": 5281,
    "preview": "# Configuration\n\nHow to enable R2 Data Catalog and configure authentication.\n\n## Prerequisites\n\n- Cloudflare account wit"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2-data-catalog/gotchas.md",
    "chars": 6086,
    "preview": "# Gotchas & Troubleshooting\n\nCommon problems → causes → solutions.\n\n## Permission Errors\n\n### 401 Unauthorized\n\n**Error:"
  },
  {
    "path": "skills/.curated/cloudflare-deploy/references/r2-data-catalog/patterns.md",
    "chars": 5871,
    "preview": "# Common Patterns\n\nPractical patterns for R2 Data Catalog with PyIceberg.\n\n## PyIceberg Connection\n\n```python\nimport os\n"
  }
]

// ... and 444 more files (download for full content)

About this extraction

This page contains the full source code of the openai/skills GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 644 files (3.2 MB), approximately 887.9k tokens, and a symbol index with 513 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!