@ketecode/loom 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +516 -2
- package/agents/accessibility-reviewer/AGENT.md +70 -0
- package/agents/accessibility-reviewer/evals/triggers.json +15 -0
- package/agents/agent-evaluator/AGENT.md +74 -0
- package/agents/agent-evaluator/evals/triggers.json +15 -0
- package/agents/architect/AGENT.md +82 -0
- package/agents/architect/evals/triggers.json +17 -0
- package/agents/billing-reviewer/AGENT.md +68 -0
- package/agents/billing-reviewer/evals/triggers.json +16 -0
- package/agents/code-reviewer/AGENT.md +51 -0
- package/agents/code-reviewer/evals/triggers.json +14 -0
- package/agents/code-simplifier/AGENT.md +74 -0
- package/agents/code-simplifier/evals/triggers.json +15 -0
- package/agents/cpp-build-resolver/AGENT.md +73 -0
- package/agents/cpp-build-resolver/evals/triggers.json +16 -0
- package/agents/cpp-reviewer/AGENT.md +59 -0
- package/agents/cpp-reviewer/evals/triggers.json +16 -0
- package/agents/csharp-build-resolver/AGENT.md +84 -0
- package/agents/csharp-build-resolver/evals/triggers.json +17 -0
- package/agents/csharp-reviewer/AGENT.md +88 -0
- package/agents/csharp-reviewer/evals/triggers.json +17 -0
- package/agents/dart-build-resolver/AGENT.md +80 -0
- package/agents/dart-build-resolver/evals/triggers.json +17 -0
- package/agents/dart-reviewer/AGENT.md +66 -0
- package/agents/dart-reviewer/evals/triggers.json +17 -0
- package/agents/database-reviewer/AGENT.md +72 -0
- package/agents/database-reviewer/evals/triggers.json +16 -0
- package/agents/django-reviewer/AGENT.md +61 -0
- package/agents/django-reviewer/evals/triggers.json +15 -0
- package/agents/doc-updater/AGENT.md +92 -0
- package/agents/doc-updater/evals/triggers.json +14 -0
- package/agents/e2e-runner/AGENT.md +88 -0
- package/agents/e2e-runner/evals/triggers.json +16 -0
- package/agents/fastapi-reviewer/AGENT.md +63 -0
- package/agents/fastapi-reviewer/evals/triggers.json +15 -0
- package/agents/flutter-reviewer/AGENT.md +70 -0
- package/agents/flutter-reviewer/evals/triggers.json +15 -0
- package/agents/fsharp-build-resolver/AGENT.md +81 -0
- package/agents/fsharp-build-resolver/evals/triggers.json +15 -0
- package/agents/fsharp-reviewer/AGENT.md +77 -0
- package/agents/fsharp-reviewer/evals/triggers.json +15 -0
- package/agents/go-build-resolver/AGENT.md +85 -0
- package/agents/go-build-resolver/evals/triggers.json +16 -0
- package/agents/go-reviewer/AGENT.md +66 -0
- package/agents/go-reviewer/evals/triggers.json +16 -0
- package/agents/healthcare-reviewer/AGENT.md +65 -0
- package/agents/healthcare-reviewer/evals/triggers.json +16 -0
- package/agents/i18n-reviewer/AGENT.md +64 -0
- package/agents/i18n-reviewer/evals/triggers.json +16 -0
- package/agents/infra-reviewer/AGENT.md +93 -0
- package/agents/infra-reviewer/evals/triggers.json +15 -0
- package/agents/java-build-resolver/AGENT.md +82 -0
- package/agents/java-build-resolver/evals/triggers.json +16 -0
- package/agents/java-reviewer/AGENT.md +64 -0
- package/agents/java-reviewer/evals/triggers.json +16 -0
- package/agents/kotlin-build-resolver/AGENT.md +89 -0
- package/agents/kotlin-build-resolver/evals/triggers.json +16 -0
- package/agents/kotlin-reviewer/AGENT.md +75 -0
- package/agents/kotlin-reviewer/evals/triggers.json +16 -0
- package/agents/mle-reviewer/AGENT.md +68 -0
- package/agents/mle-reviewer/evals/triggers.json +16 -0
- package/agents/network-config-reviewer/AGENT.md +68 -0
- package/agents/network-config-reviewer/evals/triggers.json +17 -0
- package/agents/payments-reviewer/AGENT.md +64 -0
- package/agents/payments-reviewer/evals/triggers.json +16 -0
- package/agents/performance-optimizer/AGENT.md +86 -0
- package/agents/performance-optimizer/evals/triggers.json +16 -0
- package/agents/perl-build-resolver/AGENT.md +84 -0
- package/agents/perl-build-resolver/evals/triggers.json +15 -0
- package/agents/perl-reviewer/AGENT.md +77 -0
- package/agents/perl-reviewer/evals/triggers.json +15 -0
- package/agents/php-build-resolver/AGENT.md +88 -0
- package/agents/php-build-resolver/evals/triggers.json +16 -0
- package/agents/php-reviewer/AGENT.md +61 -0
- package/agents/php-reviewer/evals/triggers.json +15 -0
- package/agents/planner/AGENT.md +75 -0
- package/agents/planner/evals/triggers.json +17 -0
- package/agents/pr-test-analyzer/AGENT.md +82 -0
- package/agents/pr-test-analyzer/evals/triggers.json +16 -0
- package/agents/python-build-resolver/AGENT.md +87 -0
- package/agents/python-build-resolver/evals/triggers.json +16 -0
- package/agents/python-reviewer/AGENT.md +63 -0
- package/agents/python-reviewer/evals/triggers.json +15 -0
- package/agents/rag-reviewer/AGENT.md +71 -0
- package/agents/rag-reviewer/evals/triggers.json +16 -0
- package/agents/react-reviewer/AGENT.md +70 -0
- package/agents/react-reviewer/evals/triggers.json +16 -0
- package/agents/refactor-cleaner/AGENT.md +82 -0
- package/agents/refactor-cleaner/evals/triggers.json +16 -0
- package/agents/ruby-build-resolver/AGENT.md +93 -0
- package/agents/ruby-build-resolver/evals/triggers.json +16 -0
- package/agents/ruby-reviewer/AGENT.md +62 -0
- package/agents/ruby-reviewer/evals/triggers.json +16 -0
- package/agents/rust-build-resolver/AGENT.md +98 -0
- package/agents/rust-build-resolver/evals/triggers.json +16 -0
- package/agents/rust-reviewer/AGENT.md +78 -0
- package/agents/rust-reviewer/evals/triggers.json +15 -0
- package/agents/security-reviewer/AGENT.md +84 -0
- package/agents/security-reviewer/evals/triggers.json +16 -0
- package/agents/silent-failure-hunter/AGENT.md +66 -0
- package/agents/silent-failure-hunter/evals/triggers.json +16 -0
- package/agents/solidity-reviewer/AGENT.md +70 -0
- package/agents/solidity-reviewer/evals/triggers.json +16 -0
- package/agents/swift-build-resolver/AGENT.md +85 -0
- package/agents/swift-build-resolver/evals/triggers.json +15 -0
- package/agents/swift-reviewer/AGENT.md +75 -0
- package/agents/swift-reviewer/evals/triggers.json +15 -0
- package/agents/typescript-build-resolver/AGENT.md +76 -0
- package/agents/typescript-build-resolver/evals/triggers.json +15 -0
- package/agents/typescript-reviewer/AGENT.md +76 -0
- package/agents/typescript-reviewer/evals/triggers.json +15 -0
- package/agents/vue-reviewer/AGENT.md +75 -0
- package/agents/vue-reviewer/evals/triggers.json +15 -0
- package/bin/kete-loom.js +683 -0
- package/commands/aside.md +19 -0
- package/commands/build-fix.md +26 -0
- package/commands/campaign.md +19 -0
- package/commands/changelog.md +36 -0
- package/commands/checkpoint.md +26 -0
- package/commands/codemap.md +25 -0
- package/commands/commit.md +26 -0
- package/commands/deps-audit.md +32 -0
- package/commands/epic-decompose.md +21 -0
- package/commands/explain.md +37 -0
- package/commands/feature-dev.md +22 -0
- package/commands/hookify.md +23 -0
- package/commands/i18n-check.md +39 -0
- package/commands/issue-sync.md +22 -0
- package/commands/jira.md +19 -0
- package/commands/learn.md +23 -0
- package/commands/loom.md +21 -0
- package/commands/loop.md +20 -0
- package/commands/model-route.md +27 -0
- package/commands/onboard.md +35 -0
- package/commands/orchestrate.md +21 -0
- package/commands/plan-feature.md +36 -0
- package/commands/postmortem.md +42 -0
- package/commands/pr-describe.md +39 -0
- package/commands/pr.md +22 -0
- package/commands/prd.md +41 -0
- package/commands/project-init.md +21 -0
- package/commands/refactor-clean.md +24 -0
- package/commands/resume-session.md +22 -0
- package/commands/review.md +35 -0
- package/commands/save-session.md +37 -0
- package/commands/security-scan.md +32 -0
- package/commands/sessions.md +21 -0
- package/commands/skill-create.md +21 -0
- package/commands/tdd.md +36 -0
- package/commands/test-coverage.md +24 -0
- package/commands/threat-model.md +36 -0
- package/commands/update-docs.md +25 -0
- package/commands/verify.md +21 -0
- package/hooks/block-dangerous-commands/HOOK.md +30 -0
- package/hooks/block-dangerous-commands/cases.json +50 -0
- package/hooks/block-dangerous-commands/hook.js +75 -0
- package/hooks/block-no-verify/HOOK.md +25 -0
- package/hooks/block-no-verify/cases.json +30 -0
- package/hooks/block-no-verify/hook.js +43 -0
- package/hooks/format-on-edit/HOOK.md +24 -0
- package/hooks/format-on-edit/hook.js +89 -0
- package/hooks/guard-secrets/HOOK.md +19 -0
- package/hooks/guard-secrets/cases.json +110 -0
- package/hooks/guard-secrets/hook.js +44 -0
- package/hooks/load-session-context/HOOK.md +20 -0
- package/hooks/load-session-context/hook.js +56 -0
- package/hooks/protect-files/HOOK.md +24 -0
- package/hooks/protect-files/cases.json +27 -0
- package/hooks/protect-files/hook.js +39 -0
- package/hooks/run.js +132 -0
- package/mcp/atlassian.json +11 -0
- package/mcp/chrome-devtools.json +18 -0
- package/mcp/cloudflare.json +11 -0
- package/mcp/context7.json +11 -0
- package/mcp/fetch.json +17 -0
- package/mcp/figma.json +11 -0
- package/mcp/git.json +17 -0
- package/mcp/github.json +11 -0
- package/mcp/linear.json +11 -0
- package/mcp/memory.json +18 -0
- package/mcp/notion.json +11 -0
- package/mcp/playwright.json +18 -0
- package/mcp/sentry.json +11 -0
- package/mcp/stripe.json +11 -0
- package/mcp/supabase.json +11 -0
- package/mcp/time.json +17 -0
- package/package.json +59 -4
- package/profiles.json +165 -0
- package/rules/common.md +21 -0
- package/rules/cpp.md +29 -0
- package/rules/csharp.md +25 -0
- package/rules/dart.md +29 -0
- package/rules/fsharp.md +28 -0
- package/rules/git.md +26 -0
- package/rules/go.md +29 -0
- package/rules/java.md +29 -0
- package/rules/kotlin.md +27 -0
- package/rules/perl.md +26 -0
- package/rules/php.md +28 -0
- package/rules/python.md +30 -0
- package/rules/ruby.md +27 -0
- package/rules/rust.md +26 -0
- package/rules/security.md +29 -0
- package/rules/swift.md +28 -0
- package/rules/testing.md +25 -0
- package/rules/typescript.md +29 -0
- package/schemas/skill-frontmatter.schema.json +52 -0
- package/scripts/lib/audit.js +96 -0
- package/scripts/lib/frontmatter.js +65 -0
- package/scripts/lib/hooks-install.js +292 -0
- package/scripts/lib/i18n.js +51 -0
- package/scripts/lib/inventory.js +85 -0
- package/scripts/lib/lint.js +158 -0
- package/scripts/lib/mcp-install.js +284 -0
- package/scripts/lib/profiles.js +128 -0
- package/scripts/lib/render.js +86 -0
- package/scripts/lib/rules-install.js +118 -0
- package/scripts/lib/skills.js +86 -0
- package/scripts/lib/targets.js +113 -0
- package/skills/accounting-api-integration/SKILL.md +81 -0
- package/skills/accounting-api-integration/evals/triggers.json +17 -0
- package/skills/accounting-api-integration/references/quickbooks.md +48 -0
- package/skills/accounting-api-integration/references/xero.md +45 -0
- package/skills/agent-harness-design/SKILL.md +125 -0
- package/skills/agent-harness-design/evals/triggers.json +21 -0
- package/skills/ai-media-generation/SKILL.md +89 -0
- package/skills/ai-media-generation/evals/triggers.json +16 -0
- package/skills/ai-media-generation/references/job-pipeline.md +76 -0
- package/skills/angular-patterns/SKILL.md +122 -0
- package/skills/angular-patterns/evals/triggers.json +16 -0
- package/skills/api-design/SKILL.md +96 -0
- package/skills/api-design/evals/triggers.json +18 -0
- package/skills/api-design/references/conventions.md +133 -0
- package/skills/architecture-decision-records/SKILL.md +98 -0
- package/skills/architecture-decision-records/evals/triggers.json +17 -0
- package/skills/article-writing/SKILL.md +108 -0
- package/skills/article-writing/evals/triggers.json +16 -0
- package/skills/aspnet-core-patterns/SKILL.md +149 -0
- package/skills/aspnet-core-patterns/evals/triggers.json +16 -0
- package/skills/auth-patterns/SKILL.md +104 -0
- package/skills/auth-patterns/evals/triggers.json +17 -0
- package/skills/auth-patterns/references/oauth-oidc.md +64 -0
- package/skills/autonomous-loops/SKILL.md +99 -0
- package/skills/autonomous-loops/evals/triggers.json +14 -0
- package/skills/aws-patterns/SKILL.md +91 -0
- package/skills/aws-patterns/evals/triggers.json +16 -0
- package/skills/azure-patterns/SKILL.md +86 -0
- package/skills/azure-patterns/evals/triggers.json +16 -0
- package/skills/benchmark-methodology/SKILL.md +88 -0
- package/skills/benchmark-methodology/evals/triggers.json +16 -0
- package/skills/benchmark-methodology/references/language-harnesses.md +130 -0
- package/skills/bgp-diagnostics/SKILL.md +84 -0
- package/skills/bgp-diagnostics/evals/triggers.json +18 -0
- package/skills/bgp-diagnostics/references/bgp-reference.md +81 -0
- package/skills/bioinformatics-workflows/SKILL.md +108 -0
- package/skills/bioinformatics-workflows/evals/triggers.json +16 -0
- package/skills/bioinformatics-workflows/references/commands.md +71 -0
- package/skills/bioinformatics-workflows/references/formats.md +24 -0
- package/skills/bioinformatics-workflows/references/workflow-managers.md +107 -0
- package/skills/brand-voice/SKILL.md +112 -0
- package/skills/brand-voice/evals/triggers.json +16 -0
- package/skills/browser-qa/SKILL.md +99 -0
- package/skills/browser-qa/evals/triggers.json +16 -0
- package/skills/bun-runtime/SKILL.md +93 -0
- package/skills/bun-runtime/evals/triggers.json +16 -0
- package/skills/cisco-ios-config/SKILL.md +101 -0
- package/skills/cisco-ios-config/evals/triggers.json +18 -0
- package/skills/cisco-ios-config/references/verification.md +63 -0
- package/skills/clickhouse-patterns/SKILL.md +101 -0
- package/skills/clickhouse-patterns/evals/triggers.json +18 -0
- package/skills/clickhouse-patterns/references/engines-and-views.md +138 -0
- package/skills/clinical-decision-support/SKILL.md +90 -0
- package/skills/clinical-decision-support/evals/triggers.json +16 -0
- package/skills/clinical-decision-support/references/cds-hooks.md +76 -0
- package/skills/clinical-decision-support/references/regulatory-boundaries.md +37 -0
- package/skills/code-tour/SKILL.md +97 -0
- package/skills/code-tour/evals/triggers.json +14 -0
- package/skills/codebase-onboarding/SKILL.md +112 -0
- package/skills/codebase-onboarding/evals/triggers.json +14 -0
- package/skills/cold-outreach-sequences/SKILL.md +90 -0
- package/skills/cold-outreach-sequences/evals/triggers.json +16 -0
- package/skills/content-repurposing/SKILL.md +82 -0
- package/skills/content-repurposing/evals/triggers.json +16 -0
- package/skills/context-budget/SKILL.md +84 -0
- package/skills/context-budget/evals/triggers.json +14 -0
- package/skills/conventional-commits/SKILL.md +144 -0
- package/skills/conventional-commits/evals/triggers.json +16 -0
- package/skills/cpp-patterns/SKILL.md +129 -0
- package/skills/cpp-patterns/evals/triggers.json +16 -0
- package/skills/cpp-patterns/references/cmake-and-tooling.md +88 -0
- package/skills/cpp-patterns/references/undefined-behaviour.md +75 -0
- package/skills/cpp-testing/SKILL.md +131 -0
- package/skills/cpp-testing/evals/triggers.json +16 -0
- package/skills/csharp-patterns/SKILL.md +110 -0
- package/skills/csharp-patterns/evals/triggers.json +17 -0
- package/skills/csharp-patterns/references/analyzers.md +59 -0
- package/skills/csharp-testing/SKILL.md +85 -0
- package/skills/csharp-testing/evals/triggers.json +17 -0
- package/skills/csharp-testing/references/integration-tests.md +77 -0
- package/skills/css-architecture/SKILL.md +143 -0
- package/skills/css-architecture/evals/triggers.json +16 -0
- package/skills/customs-trade-compliance/SKILL.md +95 -0
- package/skills/customs-trade-compliance/evals/triggers.json +16 -0
- package/skills/customs-trade-compliance/references/incoterms-2020.md +42 -0
- package/skills/dart-patterns/SKILL.md +157 -0
- package/skills/dart-patterns/evals/triggers.json +18 -0
- package/skills/dart-testing/SKILL.md +164 -0
- package/skills/dart-testing/evals/triggers.json +18 -0
- package/skills/data-analysis-notebooks/SKILL.md +113 -0
- package/skills/data-analysis-notebooks/evals/triggers.json +16 -0
- package/skills/data-analysis-notebooks/references/dataframe-pitfalls.md +49 -0
- package/skills/data-analysis-notebooks/references/statistics-pitfalls.md +24 -0
- package/skills/data-pipelines/SKILL.md +90 -0
- package/skills/data-pipelines/evals/triggers.json +16 -0
- package/skills/data-pipelines/references/orchestrators.md +64 -0
- package/skills/database-migrations/SKILL.md +102 -0
- package/skills/database-migrations/evals/triggers.json +16 -0
- package/skills/database-migrations/references/recipes.md +98 -0
- package/skills/database-migrations/references/tools.md +21 -0
- package/skills/dbt-patterns/SKILL.md +96 -0
- package/skills/dbt-patterns/evals/triggers.json +16 -0
- package/skills/dbt-patterns/references/yaml-examples.md +114 -0
- package/skills/deep-research/SKILL.md +107 -0
- package/skills/deep-research/evals/triggers.json +14 -0
- package/skills/dependency-audit/SKILL.md +103 -0
- package/skills/dependency-audit/evals/triggers.json +16 -0
- package/skills/dependency-audit/references/tools.md +124 -0
- package/skills/deployment-strategies/SKILL.md +108 -0
- package/skills/deployment-strategies/evals/triggers.json +16 -0
- package/skills/django-patterns/SKILL.md +123 -0
- package/skills/django-patterns/evals/triggers.json +16 -0
- package/skills/docker-patterns/SKILL.md +132 -0
- package/skills/docker-patterns/evals/triggers.json +16 -0
- package/skills/docker-patterns/references/dockerfiles.md +105 -0
- package/skills/e2e-testing-playwright/SKILL.md +94 -0
- package/skills/e2e-testing-playwright/evals/triggers.json +16 -0
- package/skills/e2e-testing-playwright/references/config-and-ci.md +129 -0
- package/skills/ef-core-patterns/SKILL.md +117 -0
- package/skills/ef-core-patterns/evals/triggers.json +16 -0
- package/skills/email-deliverability/SKILL.md +99 -0
- package/skills/email-deliverability/evals/triggers.json +17 -0
- package/skills/email-deliverability/references/dns-records.md +85 -0
- package/skills/error-handling-patterns/SKILL.md +112 -0
- package/skills/error-handling-patterns/evals/triggers.json +18 -0
- package/skills/error-handling-patterns/references/language-idioms.md +49 -0
- package/skills/estimation-and-scoping/SKILL.md +97 -0
- package/skills/estimation-and-scoping/evals/triggers.json +14 -0
- package/skills/evm-dapp-integration/SKILL.md +73 -0
- package/skills/evm-dapp-integration/evals/triggers.json +16 -0
- package/skills/fastapi-patterns/SKILL.md +127 -0
- package/skills/fastapi-patterns/evals/triggers.json +16 -0
- package/skills/ffmpeg-media-processing/SKILL.md +94 -0
- package/skills/ffmpeg-media-processing/evals/triggers.json +16 -0
- package/skills/ffmpeg-media-processing/references/recipes.md +112 -0
- package/skills/fhir-integration/SKILL.md +81 -0
- package/skills/fhir-integration/evals/triggers.json +16 -0
- package/skills/fhir-integration/references/search-and-bundles.md +73 -0
- package/skills/fhir-integration/references/smart-on-fhir.md +50 -0
- package/skills/flask-patterns/SKILL.md +132 -0
- package/skills/flask-patterns/evals/triggers.json +16 -0
- package/skills/flutter-patterns/SKILL.md +99 -0
- package/skills/flutter-patterns/evals/triggers.json +16 -0
- package/skills/flutterwave-integration/SKILL.md +75 -0
- package/skills/flutterwave-integration/evals/triggers.json +16 -0
- package/skills/flutterwave-integration/references/api.md +73 -0
- package/skills/flutterwave-integration/references/webhooks.md +49 -0
- package/skills/fsharp-patterns/SKILL.md +133 -0
- package/skills/fsharp-patterns/evals/triggers.json +16 -0
- package/skills/fsharp-testing/SKILL.md +136 -0
- package/skills/fsharp-testing/evals/triggers.json +16 -0
- package/skills/gcp-patterns/SKILL.md +86 -0
- package/skills/gcp-patterns/evals/triggers.json +16 -0
- package/skills/git-workflow/SKILL.md +114 -0
- package/skills/git-workflow/evals/triggers.json +16 -0
- package/skills/github-actions-ci/SKILL.md +117 -0
- package/skills/github-actions-ci/evals/triggers.json +16 -0
- package/skills/github-api-automation/SKILL.md +101 -0
- package/skills/github-api-automation/evals/triggers.json +17 -0
- package/skills/go-patterns/SKILL.md +118 -0
- package/skills/go-patterns/evals/triggers.json +17 -0
- package/skills/go-patterns/references/concurrency.md +162 -0
- package/skills/go-testing/SKILL.md +154 -0
- package/skills/go-testing/evals/triggers.json +17 -0
- package/skills/hexagonal-architecture/SKILL.md +89 -0
- package/skills/hexagonal-architecture/evals/triggers.json +17 -0
- package/skills/hipaa-compliance/SKILL.md +91 -0
- package/skills/hipaa-compliance/evals/triggers.json +18 -0
- package/skills/hipaa-compliance/references/safeguards.md +68 -0
- package/skills/hl7v2-integration/SKILL.md +69 -0
- package/skills/hl7v2-integration/evals/triggers.json +16 -0
- package/skills/hl7v2-integration/references/messages-and-ack.md +78 -0
- package/skills/homelab-network-setup/SKILL.md +125 -0
- package/skills/homelab-network-setup/evals/triggers.json +18 -0
- package/skills/homelab-network-setup/references/firewall-and-dns.md +45 -0
- package/skills/homelab-network-setup/references/wireguard.md +72 -0
- package/skills/hubtel-integration/SKILL.md +77 -0
- package/skills/hubtel-integration/evals/triggers.json +16 -0
- package/skills/hubtel-integration/references/api.md +92 -0
- package/skills/i18n-localization/SKILL.md +114 -0
- package/skills/i18n-localization/evals/triggers.json +16 -0
- package/skills/i18n-localization/references/libraries.md +52 -0
- package/skills/incident-postmortem/SKILL.md +118 -0
- package/skills/incident-postmortem/evals/triggers.json +14 -0
- package/skills/inventory-demand-planning/SKILL.md +89 -0
- package/skills/inventory-demand-planning/evals/triggers.json +16 -0
- package/skills/inventory-demand-planning/references/formulas.md +62 -0
- package/skills/investor-materials/SKILL.md +127 -0
- package/skills/investor-materials/evals/triggers.json +16 -0
- package/skills/investor-materials/references/templates.md +74 -0
- package/skills/invoicing-and-tax/SKILL.md +84 -0
- package/skills/invoicing-and-tax/evals/triggers.json +17 -0
- package/skills/invoicing-and-tax/references/e-invoicing.md +24 -0
- package/skills/invoicing-and-tax/references/invoice-fields.md +38 -0
- package/skills/invoicing-and-tax/references/rounding.md +26 -0
- package/skills/java-patterns/SKILL.md +141 -0
- package/skills/java-patterns/evals/triggers.json +17 -0
- package/skills/java-testing/SKILL.md +142 -0
- package/skills/java-testing/evals/triggers.json +16 -0
- package/skills/jetpack-compose-patterns/SKILL.md +88 -0
- package/skills/jetpack-compose-patterns/evals/triggers.json +16 -0
- package/skills/jira-integration/SKILL.md +92 -0
- package/skills/jira-integration/evals/triggers.json +17 -0
- package/skills/jpa-hibernate/SKILL.md +92 -0
- package/skills/jpa-hibernate/evals/triggers.json +18 -0
- package/skills/jpa-hibernate/references/mapping.md +99 -0
- package/skills/kotlin-multiplatform/SKILL.md +97 -0
- package/skills/kotlin-multiplatform/evals/triggers.json +16 -0
- package/skills/kotlin-patterns/SKILL.md +128 -0
- package/skills/kotlin-patterns/evals/triggers.json +16 -0
- package/skills/kotlin-testing/SKILL.md +117 -0
- package/skills/kotlin-testing/evals/triggers.json +16 -0
- package/skills/ktor-patterns/SKILL.md +135 -0
- package/skills/ktor-patterns/evals/triggers.json +18 -0
- package/skills/kubernetes-patterns/SKILL.md +106 -0
- package/skills/kubernetes-patterns/evals/triggers.json +16 -0
- package/skills/kubernetes-patterns/references/manifests.md +115 -0
- package/skills/laravel-patterns/SKILL.md +136 -0
- package/skills/laravel-patterns/evals/triggers.json +16 -0
- package/skills/linear-integration/SKILL.md +98 -0
- package/skills/linear-integration/evals/triggers.json +17 -0
- package/skills/literature-review/SKILL.md +109 -0
- package/skills/literature-review/evals/triggers.json +16 -0
- package/skills/literature-review/references/appraisal.md +41 -0
- package/skills/literature-review/references/search-sources.md +39 -0
- package/skills/llm-app-patterns/SKILL.md +97 -0
- package/skills/llm-app-patterns/evals/triggers.json +17 -0
- package/skills/llm-evals/SKILL.md +98 -0
- package/skills/llm-evals/evals/triggers.json +16 -0
- package/skills/llm-evals/references/graders.md +66 -0
- package/skills/logistics-exception-management/SKILL.md +90 -0
- package/skills/logistics-exception-management/evals/triggers.json +16 -0
- package/skills/manim-animations/SKILL.md +106 -0
- package/skills/manim-animations/evals/triggers.json +16 -0
- package/skills/market-research/SKILL.md +117 -0
- package/skills/market-research/evals/triggers.json +16 -0
- package/skills/marketing-campaign/SKILL.md +111 -0
- package/skills/marketing-campaign/evals/triggers.json +16 -0
- package/skills/mcp-server-patterns/SKILL.md +127 -0
- package/skills/mcp-server-patterns/evals/triggers.json +18 -0
- package/skills/mcp-server-patterns/references/protocol-notes.md +68 -0
- package/skills/metrics-dashboards/SKILL.md +113 -0
- package/skills/metrics-dashboards/evals/triggers.json +16 -0
- package/skills/ml-experiment-workflow/SKILL.md +125 -0
- package/skills/ml-experiment-workflow/evals/triggers.json +16 -0
- package/skills/mongodb-patterns/SKILL.md +115 -0
- package/skills/mongodb-patterns/evals/triggers.json +18 -0
- package/skills/mongodb-patterns/references/indexes-and-aggregation.md +94 -0
- package/skills/mpesa-daraja-integration/SKILL.md +70 -0
- package/skills/mpesa-daraja-integration/evals/triggers.json +16 -0
- package/skills/mpesa-daraja-integration/references/api.md +103 -0
- package/skills/mpesa-daraja-integration/references/callbacks.md +74 -0
- package/skills/mtn-momo-integration/SKILL.md +66 -0
- package/skills/mtn-momo-integration/evals/triggers.json +16 -0
- package/skills/mtn-momo-integration/references/api.md +153 -0
- package/skills/mtn-momo-integration/references/callbacks.md +92 -0
- package/skills/mtn-momo-integration/references/sandbox-and-go-live.md +51 -0
- package/skills/mtn-momo-integration/scripts/sandbox-setup.js +79 -0
- package/skills/mysql-patterns/SKILL.md +96 -0
- package/skills/mysql-patterns/evals/triggers.json +16 -0
- package/skills/mysql-patterns/references/explain.md +34 -0
- package/skills/mysql-patterns/references/online-ddl.md +41 -0
- package/skills/nestjs-patterns/SKILL.md +114 -0
- package/skills/nestjs-patterns/evals/triggers.json +16 -0
- package/skills/nestjs-patterns/references/testing.md +68 -0
- package/skills/network-automation/SKILL.md +107 -0
- package/skills/network-automation/evals/triggers.json +18 -0
- package/skills/network-automation/references/tool-snippets.md +153 -0
- package/skills/network-troubleshooting/SKILL.md +152 -0
- package/skills/network-troubleshooting/evals/triggers.json +18 -0
- package/skills/network-troubleshooting/references/commands.md +33 -0
- package/skills/nextjs-patterns/SKILL.md +150 -0
- package/skills/nextjs-patterns/evals/triggers.json +18 -0
- package/skills/nextjs-patterns/references/caching.md +87 -0
- package/skills/node-backend-patterns/SKILL.md +103 -0
- package/skills/node-backend-patterns/evals/triggers.json +16 -0
- package/skills/node-backend-patterns/references/templates.md +122 -0
- package/skills/nuxt-patterns/SKILL.md +103 -0
- package/skills/nuxt-patterns/evals/triggers.json +16 -0
- package/skills/parallel-agent-orchestration/SKILL.md +106 -0
- package/skills/parallel-agent-orchestration/evals/triggers.json +14 -0
- package/skills/paystack-integration/SKILL.md +59 -0
- package/skills/paystack-integration/evals/triggers.json +14 -0
- package/skills/paystack-integration/references/api.md +73 -0
- package/skills/paystack-integration/references/mobile-money.md +50 -0
- package/skills/paystack-integration/references/webhooks.md +80 -0
- package/skills/pci-dss-scope/SKILL.md +103 -0
- package/skills/pci-dss-scope/evals/triggers.json +18 -0
- package/skills/pci-dss-scope/references/saq-and-data.md +36 -0
- package/skills/perl-patterns/SKILL.md +135 -0
- package/skills/perl-patterns/evals/triggers.json +18 -0
- package/skills/perl-testing/SKILL.md +126 -0
- package/skills/perl-testing/evals/triggers.json +17 -0
- package/skills/php-patterns/SKILL.md +116 -0
- package/skills/php-patterns/evals/triggers.json +16 -0
- package/skills/php-testing/SKILL.md +123 -0
- package/skills/php-testing/evals/triggers.json +16 -0
- package/skills/postgres-patterns/SKILL.md +103 -0
- package/skills/postgres-patterns/evals/triggers.json +17 -0
- package/skills/postgres-patterns/references/explain.md +59 -0
- package/skills/postgres-patterns/references/locks.md +53 -0
- package/skills/prd-writing/SKILL.md +124 -0
- package/skills/prd-writing/evals/triggers.json +15 -0
- package/skills/prisma-patterns/SKILL.md +83 -0
- package/skills/prisma-patterns/evals/triggers.json +18 -0
- package/skills/prisma-patterns/references/prisma-8.md +46 -0
- package/skills/prisma-patterns/references/workflow.md +50 -0
- package/skills/privacy-compliance/SKILL.md +121 -0
- package/skills/privacy-compliance/evals/triggers.json +18 -0
- package/skills/privacy-compliance/references/jurisdictions.md +51 -0
- package/skills/production-scheduling/SKILL.md +98 -0
- package/skills/production-scheduling/evals/triggers.json +16 -0
- package/skills/prompt-engineering/SKILL.md +92 -0
- package/skills/prompt-engineering/evals/triggers.json +16 -0
- package/skills/python-patterns/SKILL.md +107 -0
- package/skills/python-patterns/evals/triggers.json +16 -0
- package/skills/python-patterns/references/tooling.md +101 -0
- package/skills/python-testing/SKILL.md +126 -0
- package/skills/python-testing/evals/triggers.json +16 -0
- package/skills/python-testing/references/mocking.md +71 -0
- package/skills/pytorch-patterns/SKILL.md +139 -0
- package/skills/pytorch-patterns/evals/triggers.json +16 -0
- package/skills/pytorch-patterns/references/debugging.md +39 -0
- package/skills/quarkus-patterns/SKILL.md +93 -0
- package/skills/quarkus-patterns/evals/triggers.json +18 -0
- package/skills/rag-pipeline-patterns/SKILL.md +117 -0
- package/skills/rag-pipeline-patterns/evals/triggers.json +18 -0
- package/skills/rag-pipeline-patterns/references/evaluation.md +37 -0
- package/skills/rag-pipeline-patterns/references/retrieval-recipes.md +78 -0
- package/skills/rails-patterns/SKILL.md +132 -0
- package/skills/rails-patterns/evals/triggers.json +16 -0
- package/skills/react-native-patterns/SKILL.md +101 -0
- package/skills/react-native-patterns/evals/triggers.json +16 -0
- package/skills/react-patterns/SKILL.md +140 -0
- package/skills/react-patterns/evals/triggers.json +18 -0
- package/skills/react-performance/SKILL.md +107 -0
- package/skills/react-performance/evals/triggers.json +18 -0
- package/skills/redis-patterns/SKILL.md +109 -0
- package/skills/redis-patterns/evals/triggers.json +18 -0
- package/skills/redis-patterns/references/operations.md +61 -0
- package/skills/refactoring-safely/SKILL.md +107 -0
- package/skills/refactoring-safely/evals/triggers.json +17 -0
- package/skills/release-management/SKILL.md +141 -0
- package/skills/release-management/evals/triggers.json +16 -0
- package/skills/remotion-video/SKILL.md +91 -0
- package/skills/remotion-video/evals/triggers.json +16 -0
- package/skills/remotion-video/references/lambda.md +66 -0
- package/skills/returns-reverse-logistics/SKILL.md +97 -0
- package/skills/returns-reverse-logistics/evals/triggers.json +16 -0
- package/skills/ruby-patterns/SKILL.md +127 -0
- package/skills/ruby-patterns/evals/triggers.json +18 -0
- package/skills/ruby-testing/SKILL.md +113 -0
- package/skills/ruby-testing/evals/triggers.json +18 -0
- package/skills/runbook-writing/SKILL.md +101 -0
- package/skills/runbook-writing/evals/triggers.json +14 -0
- package/skills/rust-patterns/SKILL.md +118 -0
- package/skills/rust-patterns/evals/triggers.json +16 -0
- package/skills/rust-patterns/references/cargo-and-clippy.md +105 -0
- package/skills/rust-patterns/references/errors-and-traits.md +97 -0
- package/skills/rust-testing/SKILL.md +148 -0
- package/skills/rust-testing/evals/triggers.json +16 -0
- package/skills/rust-testing/references/fakes-proptest-async.md +113 -0
- package/skills/search-first/SKILL.md +73 -0
- package/skills/search-first/evals/triggers.json +14 -0
- package/skills/security-review/SKILL.md +58 -0
- package/skills/security-review/evals/triggers.json +14 -0
- package/skills/security-review/references/checklist.md +54 -0
- package/skills/security-review/scripts/scan-secrets.js +79 -0
- package/skills/seo-audit/SKILL.md +111 -0
- package/skills/seo-audit/evals/triggers.json +16 -0
- package/skills/seo-audit/references/checks.md +65 -0
- package/skills/session-handoff/SKILL.md +101 -0
- package/skills/session-handoff/evals/triggers.json +14 -0
- package/skills/skill-authoring/SKILL.md +87 -0
- package/skills/skill-authoring/evals/triggers.json +14 -0
- package/skills/skill-authoring/references/frontmatter.md +40 -0
- package/skills/slack-app-integration/SKILL.md +108 -0
- package/skills/slack-app-integration/evals/triggers.json +17 -0
- package/skills/smart-contract-security/SKILL.md +110 -0
- package/skills/smart-contract-security/evals/triggers.json +16 -0
- package/skills/smart-contract-security/references/vulnerability-checklist.md +79 -0
- package/skills/social-media-publishing/SKILL.md +84 -0
- package/skills/social-media-publishing/evals/triggers.json +17 -0
- package/skills/social-media-publishing/references/platform-apis.md +116 -0
- package/skills/solidity-patterns/SKILL.md +95 -0
- package/skills/solidity-patterns/evals/triggers.json +16 -0
- package/skills/spring-boot-patterns/SKILL.md +128 -0
- package/skills/spring-boot-patterns/evals/triggers.json +18 -0
- package/skills/spring-boot-patterns/references/testing.md +72 -0
- package/skills/stripe-integration/SKILL.md +69 -0
- package/skills/stripe-integration/evals/triggers.json +16 -0
- package/skills/stripe-integration/references/api.md +71 -0
- package/skills/stripe-integration/references/billing.md +58 -0
- package/skills/stripe-integration/references/webhooks.md +76 -0
- package/skills/subscription-billing-ops/SKILL.md +118 -0
- package/skills/subscription-billing-ops/evals/triggers.json +17 -0
- package/skills/subscription-billing-ops/references/proration.md +47 -0
- package/skills/subscription-billing-ops/references/revenue-metrics.md +38 -0
- package/skills/svelte-patterns/SKILL.md +122 -0
- package/skills/svelte-patterns/evals/triggers.json +16 -0
- package/skills/swift-patterns/SKILL.md +113 -0
- package/skills/swift-patterns/evals/triggers.json +16 -0
- package/skills/swift-patterns/references/concurrency-migration.md +40 -0
- package/skills/swift-testing/SKILL.md +121 -0
- package/skills/swift-testing/evals/triggers.json +16 -0
- package/skills/swift-testing/references/swift-testing-cheatsheet.md +81 -0
- package/skills/swiftui-patterns/SKILL.md +102 -0
- package/skills/swiftui-patterns/evals/triggers.json +16 -0
- package/skills/tdd-workflow/SKILL.md +67 -0
- package/skills/tdd-workflow/evals/triggers.json +14 -0
- package/skills/technical-writing/SKILL.md +95 -0
- package/skills/technical-writing/evals/triggers.json +14 -0
- package/skills/terraform-patterns/SKILL.md +122 -0
- package/skills/terraform-patterns/evals/triggers.json +16 -0
- package/skills/terraform-patterns/references/backends.md +67 -0
- package/skills/test-coverage-improvement/SKILL.md +107 -0
- package/skills/test-coverage-improvement/evals/triggers.json +16 -0
- package/skills/threat-modeling/SKILL.md +113 -0
- package/skills/threat-modeling/evals/triggers.json +16 -0
- package/skills/typescript-patterns/SKILL.md +122 -0
- package/skills/typescript-patterns/evals/triggers.json +16 -0
- package/skills/typescript-testing/SKILL.md +101 -0
- package/skills/typescript-testing/evals/triggers.json +16 -0
- package/skills/verification-loop/SKILL.md +70 -0
- package/skills/verification-loop/evals/triggers.json +14 -0
- package/skills/verification-loop/scripts/detect-checks.js +102 -0
- package/skills/vite-patterns/SKILL.md +117 -0
- package/skills/vite-patterns/evals/triggers.json +16 -0
- package/skills/vue-patterns/SKILL.md +104 -0
- package/skills/vue-patterns/evals/triggers.json +16 -0
- package/skills/web-accessibility/SKILL.md +119 -0
- package/skills/web-accessibility/evals/triggers.json +16 -0
- package/skills/web-performance/SKILL.md +107 -0
- package/skills/web-performance/evals/triggers.json +16 -0
- package/skills/web-scraping/SKILL.md +80 -0
- package/skills/web-scraping/evals/triggers.json +16 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: network-troubleshooting
|
|
3
|
+
description: Layer-by-layer diagnosis of network faults on Linux, macOS and Windows, working up from link and IP routing through DNS resolution, TCP/UDP port reachability and firewalls, TLS certificates and SNI, to latency, packet loss and MTU black holes, with the exact command for each check and how to read its output. Use when a host, site or service is unreachable, name resolution fails, a connection times out or is refused, a TLS handshake errors, or a link is slow or drops large transfers.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host with a shell. Uses standard OS tools (ping, ip or ifconfig, dig or nslookup, nc, curl, openssl); mtr and tcpdump are optional.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: devops
|
|
9
|
+
kete-loom/risk: runs-commands
|
|
10
|
+
kete-loom/requires: "ping, curl"
|
|
11
|
+
kete-loom/owner: "Kete-org"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Network troubleshooting
|
|
15
|
+
|
|
16
|
+
Find the lowest layer that is broken, prove it with one command, then fix only that. Most "the network is down" reports are DNS, a firewall, or a wrong route, and guessing wastes hours.
|
|
17
|
+
|
|
18
|
+
Per-OS command equivalents are in `references/commands.md`. Read it when the user is not on Linux or a command below is missing.
|
|
19
|
+
|
|
20
|
+
## Ground rules
|
|
21
|
+
|
|
22
|
+
1. **Read-only first.** Every check in this skill observes state. Do not flush caches, restart services, change routes or edit firewall rules until you have shown which layer is broken, and ask the user before any change on a remote machine you are connected through: a wrong rule cuts you off.
|
|
23
|
+
2. **Pin down the symptom before testing.** Get: source host, destination (name and port), protocol, the exact error text, when it last worked, and what changed. "Connection refused" and "timed out" point to different layers.
|
|
24
|
+
3. **Test from where the failure is.** A check from your laptop proves nothing about the server's path. Run each command on the failing source, or say clearly where you ran it.
|
|
25
|
+
4. **One variable at a time.** Compare against a known-good target (`1.1.1.1`, another host on the same subnet) so each result splits the problem in half.
|
|
26
|
+
5. **Never paste secrets** (VPN keys, tokens in URLs, cookies from `curl -v`) into the report.
|
|
27
|
+
|
|
28
|
+
## Step 1: Local link and address
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
ip -br addr # interface up, has the expected IPv4/IPv6 address?
|
|
32
|
+
ip route # is there a default route, via the right gateway?
|
|
33
|
+
ip route get 1.1.1.1 # which interface and source address a packet would use
|
|
34
|
+
ping -c 3 <gateway>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- No address, or a `169.254.x.x` address: DHCP failed. Check cable/Wi-Fi association and the DHCP server, not DNS.
|
|
38
|
+
- Gateway does not answer but has an entry in `ip neigh` marked `FAILED`/`INCOMPLETE`: layer 2 problem (wrong VLAN, cable, switch port).
|
|
39
|
+
- Two default routes, or a VPN that installed `0.0.0.0/1` routes: traffic may be leaving by the wrong interface.
|
|
40
|
+
|
|
41
|
+
## Step 2: IP reachability beyond the gateway
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
ping -c 3 1.1.1.1 # internet by IP, no DNS involved
|
|
45
|
+
traceroute -n <dest-ip> # or: mtr -rwnc 50 <dest-ip>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- IP works but names fail: go to step 3.
|
|
49
|
+
- Path stops at a hop and never continues: routing or a firewall at that hop. Note the last hop that answered.
|
|
50
|
+
- Many networks drop ICMP. A failed ping alone does not prove a host is down; test the real port in step 4.
|
|
51
|
+
|
|
52
|
+
## Step 3: DNS
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
dig example.com # what the system's configured resolver says
|
|
56
|
+
dig @1.1.1.1 example.com # what a public resolver says
|
|
57
|
+
dig +trace example.com # walk from the root; shows which delegation breaks
|
|
58
|
+
getent hosts example.com # what applications see (honours /etc/hosts and nsswitch)
|
|
59
|
+
resolvectl status # systemd-resolved: which DNS server per interface
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Read the `status:` field in the dig header:
|
|
63
|
+
|
|
64
|
+
| Result | Meaning | Next |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `NOERROR` with answers | Name resolves | Check the answer is the IP you expect |
|
|
67
|
+
| `NOERROR`, no answers | Name exists, no record of that type | Query `A` and `AAAA` separately |
|
|
68
|
+
| `NXDOMAIN` | Name does not exist at that resolver | Typo, missing record, or split-horizon DNS |
|
|
69
|
+
| `SERVFAIL` | Resolver could not get an answer | DNSSEC failure or broken authoritative servers; try `dig +cd` |
|
|
70
|
+
| `connection timed out; no servers could be reached` | Resolver unreachable | Firewall on UDP/TCP 53, wrong resolver IP, or VPN DNS |
|
|
71
|
+
|
|
72
|
+
- `dig` and `getent` disagree: an `/etc/hosts` entry, a local cache, or search-domain expansion is involved.
|
|
73
|
+
- Public resolver right, local one wrong: stale cache or an internal zone overriding the public one. Compare TTLs.
|
|
74
|
+
- After a DNS change, the old answer lives until its TTL expires in every cache along the way.
|
|
75
|
+
|
|
76
|
+
## Step 4: Port reachability and firewalls
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
nc -vz -w 5 <host> <port> # TCP
|
|
80
|
+
curl -sv --connect-timeout 5 http://<host>:<port>/ -o /dev/null
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
| Error | What it means |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `Connection refused` | Packet reached the host; nothing listening on that port, or a firewall REJECT (TCP reset or ICMP port-unreachable) |
|
|
86
|
+
| Timed out | Packet or reply dropped silently: firewall DROP, security group, wrong route, or host down |
|
|
87
|
+
| `No route to host` | ARP failed on the local subnet, or a firewall REJECT with ICMP host-prohibited |
|
|
88
|
+
|
|
89
|
+
On the destination, check what listens and what filters:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
ss -tulpn # listening sockets; 127.0.0.1:port is local-only
|
|
93
|
+
sudo nft list ruleset # or: sudo iptables -S ; sudo ufw status verbose ; sudo firewall-cmd --list-all
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- `curl` fails but `nc` works: check `env | grep -i proxy` (`HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`); a proxy setting sends the request somewhere else.
|
|
97
|
+
- Service bound to `127.0.0.1` or `::1` only: it is not reachable from outside, whatever the firewall says.
|
|
98
|
+
- Check every filter on the path: host firewall, cloud security group or network ACL, router port forward, and the container runtime's own rules.
|
|
99
|
+
- Capture to settle it: `sudo tcpdump -ni any host <client-ip> and port <port>`. SYN arrives with no SYN-ACK: the host's firewall or the service. No SYN arrives: something upstream drops it.
|
|
100
|
+
|
|
101
|
+
## Step 5: TLS
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
openssl s_client -connect <host>:443 -servername <host> -showcerts </dev/null
|
|
105
|
+
openssl s_client -connect <host>:443 -servername <host> </dev/null 2>/dev/null \
|
|
106
|
+
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
|
|
107
|
+
curl -v https://<host>/ -o /dev/null
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`-ext` needs OpenSSL 1.1.1 or newer; on older OpenSSL or LibreSSL (macOS) use `-noout -text` and read the `Subject Alternative Name` block.
|
|
111
|
+
|
|
112
|
+
- `Verify return code: 0 (ok)` means the chain is trusted from this machine.
|
|
113
|
+
- `unable to get local issuer certificate`: the server does not send its intermediate certificate, or this client lacks the root. Browsers can hide this; `curl` and most libraries do not.
|
|
114
|
+
- `certificate has expired` or `notAfter` in the past: renew. Also check the client clock with `date`.
|
|
115
|
+
- Hostname mismatch: the name is not in `subjectAltName`. Without `-servername` (no SNI) many servers return a default certificate, so always pass it.
|
|
116
|
+
- To test one backend behind a load balancer or before DNS changes: `curl -v --resolve <host>:443:<ip> https://<host>/`.
|
|
117
|
+
|
|
118
|
+
## Step 6: Latency, loss and MTU
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
mtr -rwnc 100 <host>
|
|
122
|
+
curl -o /dev/null -s -w 'dns %{time_namelookup} connect %{time_connect} tls %{time_appconnect} ttfb %{time_starttransfer} total %{time_total}\n' https://<host>/
|
|
123
|
+
ping -M do -s 1472 -c 3 <host> # 1472 + 28 bytes of headers = 1500
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- In `mtr`, loss at one middle hop that does not continue to later hops is ICMP rate limiting, not real loss. Loss that starts at a hop and persists to the destination is real.
|
|
127
|
+
- The `curl -w` timings say which phase is slow: DNS, TCP connect, TLS, or the server itself (time to first byte).
|
|
128
|
+
- **MTU black hole** signs: ping and small requests work, but large downloads, `git clone`, TLS handshakes with big certificate chains, or SSH sessions after login hang. Lower `-s` until the do-not-fragment ping succeeds; the working size plus 28 is the path MTU. Typical culprits are VPNs (WireGuard commonly uses 1420), PPPoE (1492) and firewalls that block ICMP "fragmentation needed". Fix with a lower interface MTU or TCP MSS clamping on the router, and say which.
|
|
129
|
+
|
|
130
|
+
## Stop and ask the user
|
|
131
|
+
|
|
132
|
+
- Before any change that could drop your own session (firewall, routes, interface down, VPN restart) on a machine you reach over the network.
|
|
133
|
+
- When the fault is outside what you can see: ISP, cloud provider console, a corporate proxy, or a device you have no shell on. Say exactly what to check there.
|
|
134
|
+
- When a fix needs credentials or admin access you do not have.
|
|
135
|
+
|
|
136
|
+
## Never
|
|
137
|
+
|
|
138
|
+
- Never disable a firewall entirely "to test" on an internet-facing host.
|
|
139
|
+
- Never use `curl -k` or turn off certificate verification as the fix; it only hides the TLS fault.
|
|
140
|
+
- Never conclude "host is down" from ping alone.
|
|
141
|
+
|
|
142
|
+
## Report
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
Symptom: <source> → <destination:port/proto>: <exact error>
|
|
146
|
+
Broken layer: <link | IP/routing | DNS | port/firewall | TLS | MTU/latency>
|
|
147
|
+
Evidence: <command> → <the output line that proves it>
|
|
148
|
+
Cause: <one sentence>
|
|
149
|
+
Fix: <smallest change, and where to apply it> (applied | proposed, needs approval)
|
|
150
|
+
Checked and fine: <layers verified working>
|
|
151
|
+
Not checked: <what you could not test, and why>
|
|
152
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"My server can ping 8.8.8.8 but apt update says it can't resolve the mirror hostname",
|
|
4
|
+
"curl to our API on port 8443 just hangs and then times out, what's blocking it?",
|
|
5
|
+
"Users get 'unable to get local issuer certificate' when hitting our site from Python but Chrome is fine",
|
|
6
|
+
"Small web pages load over the VPN but large downloads and git clone stall forever",
|
|
7
|
+
"nc says connection refused on port 5432 from the app box, how do I figure out why",
|
|
8
|
+
"Why is the website slow only from the office, mtr shows loss at hop 6"
|
|
9
|
+
],
|
|
10
|
+
"should_not_trigger": [
|
|
11
|
+
"Help me split my home network into VLANs for IoT, guests and my servers",
|
|
12
|
+
"Review this nftables ruleset and WireGuard config for anything exposed to the internet",
|
|
13
|
+
"Write a Kubernetes NetworkPolicy that only lets the frontend reach the API pods",
|
|
14
|
+
"Set up a GitHub Actions workflow that deploys to staging on every merge",
|
|
15
|
+
"Profile this Node.js endpoint, the database query inside it takes 3 seconds",
|
|
16
|
+
"Write Terraform for an AWS VPC with public and private subnets"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Command equivalents by OS
|
|
2
|
+
|
|
3
|
+
Use the row for the user's OS. All are read-only unless marked.
|
|
4
|
+
|
|
5
|
+
| Check | Linux | macOS | Windows (PowerShell) |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| Addresses | `ip -br addr` | `ifconfig` or `ipconfig getifaddr en0` | `Get-NetIPAddress` or `ipconfig /all` |
|
|
8
|
+
| Routes | `ip route` | `netstat -rn` | `Get-NetRoute` or `route print` |
|
|
9
|
+
| Route for one destination | `ip route get <ip>` | `route -n get <ip>` | `Find-NetRoute -RemoteIPAddress <ip>` |
|
|
10
|
+
| Neighbour/ARP table | `ip neigh` | `arp -an` | `Get-NetNeighbor` |
|
|
11
|
+
| Trace path | `traceroute -n`, `tracepath`, `mtr` | `traceroute -n`, `mtr` (Homebrew) | `tracert -d`, `pathping` |
|
|
12
|
+
| DNS query | `dig`, `getent hosts` | `dig`, `dscacheutil -q host -a name <name>` | `Resolve-DnsName <name>`, `nslookup` |
|
|
13
|
+
| Resolver in use | `resolvectl status` or `/etc/resolv.conf` | `scutil --dns` | `Get-DnsClientServerAddress` |
|
|
14
|
+
| Flush DNS cache (changes state) | `resolvectl flush-caches` | `sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder` | `Clear-DnsClientCache` or `ipconfig /flushdns` |
|
|
15
|
+
| TCP port test | `nc -vz -w 5 <host> <port>` | `nc -vz -G 5 <host> <port>` | `Test-NetConnection <host> -Port <port>` |
|
|
16
|
+
| Listening sockets | `ss -tulpn` | `lsof -nP -iTCP -sTCP:LISTEN` | `Get-NetTCPConnection -State Listen` or `netstat -ano` |
|
|
17
|
+
| Host firewall | `nft list ruleset`, `iptables -S`, `ufw status verbose`, `firewall-cmd --list-all` | `sudo pfctl -sr`, `/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate` | `Get-NetFirewallProfile`, `Get-NetFirewallRule -Enabled True` |
|
|
18
|
+
| Don't-fragment ping (1500 path) | `ping -M do -s 1472 <host>` | `ping -D -s 1472 <host>` | `ping -f -l 1472 <host>` |
|
|
19
|
+
| Packet capture | `sudo tcpdump -ni any <filter>` | `sudo tcpdump -ni en0 <filter>` | `pktmon` or Wireshark |
|
|
20
|
+
|
|
21
|
+
## Reading traceroute
|
|
22
|
+
|
|
23
|
+
- `* * *` on one hop, later hops answer: that router does not reply to probes. Ignore it.
|
|
24
|
+
- `* * *` from some hop to the end: traffic is dropped there or the destination filters probes. Test the real port with `nc` before concluding anything.
|
|
25
|
+
- A sudden large latency jump that stays for every later hop is a real slow link; a jump at one hop only is the router deprioritising ICMP.
|
|
26
|
+
|
|
27
|
+
## UDP checks
|
|
28
|
+
|
|
29
|
+
`nc -vzu` cannot tell "open" from "filtered" because UDP has no handshake. Test UDP services with their own client instead: `dig @<server> <name>` for DNS, `wg show` handshake time for WireGuard, `ntpdate -q` or `sntp` for NTP, or capture with `tcpdump` on the server to see whether packets arrive.
|
|
30
|
+
|
|
31
|
+
## IPv6 versus IPv4
|
|
32
|
+
|
|
33
|
+
If a name has both `A` and `AAAA` records, clients usually try IPv6 first. When IPv6 is broken, connections stall then fall back. Force each family to compare: `curl -4 ...` and `curl -6 ...`, `ping -4` / `ping -6` (or `ping6`).
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-patterns
|
|
3
|
+
description: Next.js App Router conventions for the app/ directory - splitting Server and Client Components, async params and request APIs, fetch caching and revalidation (including Cache Components and "use cache"), Route Handlers, Server Actions with auth checks, the Metadata API, middleware/proxy, NEXT_PUBLIC_ environment variables and self-hosting or Vercel deployment traps. Use when adding routes, layouts or pages under app/, deciding where "use client" goes, fixing stale or over-cached data, writing a Server Action or route.ts, or upgrading a Next.js app across major versions.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Targets the Next.js App Router (15 and 16); Pages Router projects need different guidance. Needs Node.js 20.9+ for Next.js 16 and the project's package manager.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: coding
|
|
9
|
+
kete-loom/risk: runs-commands
|
|
10
|
+
kete-loom/requires: "node"
|
|
11
|
+
kete-loom/owner: "Kete-org"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Next.js App Router patterns
|
|
15
|
+
|
|
16
|
+
Keep data and secrets on the server, ship the least client JavaScript, and be explicit about what is cached. General component rules live in `react-patterns`; render speed in `react-performance`.
|
|
17
|
+
|
|
18
|
+
## 0. Before you change anything
|
|
19
|
+
|
|
20
|
+
1. Read `next` in `package.json`. Behaviour differs a lot between majors:
|
|
21
|
+
- 15: `params`, `searchParams`, `cookies()`, `headers()`, `draftMode()` became async (sync access still worked with warnings). `fetch` and `GET` Route Handlers stopped being cached by default.
|
|
22
|
+
- 16: sync access to those APIs is removed; `middleware.ts` is deprecated in favour of `proxy.ts`; `revalidateTag` takes a second `cacheLife` argument; Turbopack is the default bundler; `next lint` is removed; Node.js 20.9+ is required.
|
|
23
|
+
2. Check `next.config.*` for `cacheComponents: true`. It switches the app to a different caching model (`"use cache"`, no `dynamic`/`revalidate`/`fetchCache` segment config); see `references/caching.md` for both models. Write new code in the model the app uses.
|
|
24
|
+
3. Confirm the project uses `app/`. If it uses `pages/`, stop and tell the user this skill covers the App Router.
|
|
25
|
+
4. If the repo ships version-matched docs (an `AGENTS.md` pointing into `node_modules/next/dist/docs/`), read those before guessing.
|
|
26
|
+
|
|
27
|
+
## 1. Server vs Client Components
|
|
28
|
+
|
|
29
|
+
Everything in `app/` is a Server Component unless its module (or an importer) starts with `"use client"`.
|
|
30
|
+
|
|
31
|
+
Make a component a Client Component only if it needs one of: state or effects, event handlers, browser APIs, or a library that uses them. Then:
|
|
32
|
+
|
|
33
|
+
1. Push `"use client"` to the **leaves**: a `LikeButton`, not the whole page.
|
|
34
|
+
2. Pass Server Components into Client Components as `children` or props rather than importing them inside the client file.
|
|
35
|
+
3. Props crossing the boundary must be serialisable: plain objects, arrays, strings, numbers, Dates, Promises, Server Actions. No class instances, functions (other than Server Actions) or symbols.
|
|
36
|
+
4. Pass only the fields the client needs, never whole DB rows or user records. Everything you pass is visible in the page payload.
|
|
37
|
+
5. Mark server-only modules (DB, secrets, SDKs with keys) with `import "server-only"` so a client import fails the build.
|
|
38
|
+
6. Context providers are Client Components; render them as deep as possible and wrap `{children}`.
|
|
39
|
+
|
|
40
|
+
`"use server"` marks Server Actions (functions callable from the client). It is not the opposite of `"use client"` and is never needed to make a Server Component.
|
|
41
|
+
|
|
42
|
+
## 2. Request APIs and params
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
export default async function Page(props: PageProps<"/blog/[slug]">) {
|
|
46
|
+
const { slug } = await props.params;
|
|
47
|
+
const { q } = await props.searchParams;
|
|
48
|
+
const theme = (await cookies()).get("theme")?.value;
|
|
49
|
+
// ...
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- `PageProps`, `LayoutProps` and `RouteContext` helpers are generated by `next typegen` (15.5+) or during `next dev`/`next build`.
|
|
54
|
+
- In a Client Component, unwrap a passed `params` promise with React `use()`, or use `useParams()`/`useSearchParams()`.
|
|
55
|
+
- `useSearchParams()` in a client component needs a `<Suspense>` boundary above it, or the build may fail or bail out of static rendering.
|
|
56
|
+
- Treat `params` and `searchParams` as untrusted input; validate them (for example with zod) before using them in queries.
|
|
57
|
+
|
|
58
|
+
## 3. Data fetching and caching
|
|
59
|
+
|
|
60
|
+
1. Fetch in Server Components, close to where the data is used. Use `React.cache()` to dedupe a non-`fetch` call (ORM, SDK) within one request; identical `fetch` calls are memoised automatically.
|
|
61
|
+
2. Start independent requests together (`Promise.all`) or in sibling components behind separate `<Suspense>` boundaries. Avoid sequential `await`s in a layout.
|
|
62
|
+
3. Wrap slow or request-specific parts in `<Suspense fallback>` (or add `loading.tsx`) so the rest streams.
|
|
63
|
+
4. Choose caching on purpose, per data source: how stale may it be, and what event invalidates it? Then apply the matching model from `references/caching.md`.
|
|
64
|
+
5. After a mutation, invalidate what changed: `revalidatePath`, `revalidateTag(tag, profile)` (16) or `updateTag(tag)` for read-your-writes inside a Server Action (16).
|
|
65
|
+
6. Development never caches pages. Always confirm caching behaviour with `next build && next start`.
|
|
66
|
+
|
|
67
|
+
## 4. Route Handlers (`app/**/route.ts`)
|
|
68
|
+
|
|
69
|
+
- Export named functions per method: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`. Use the Web `Request`/`Response` (or `NextRequest`/`NextResponse`).
|
|
70
|
+
- A `route.ts` cannot sit in the same segment as a `page.tsx`.
|
|
71
|
+
- Use them for webhooks, public APIs consumed by other clients, file downloads and OAuth callbacks. For mutations from your own UI, prefer Server Actions.
|
|
72
|
+
- Webhooks: read the raw body with `await request.text()` before verifying a signature; don't `request.json()` first.
|
|
73
|
+
- Authenticate and authorise inside every handler; nothing upstream does it for you.
|
|
74
|
+
|
|
75
|
+
## 5. Server Actions
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
"use server";
|
|
79
|
+
import { z } from "zod";
|
|
80
|
+
import { revalidatePath } from "next/cache";
|
|
81
|
+
|
|
82
|
+
const Input = z.object({ title: z.string().min(1).max(200) });
|
|
83
|
+
|
|
84
|
+
export async function createPost(prev: State, formData: FormData): Promise<State> {
|
|
85
|
+
const session = await auth(); // 1. authenticate
|
|
86
|
+
if (!session) return { error: "Sign in first" };
|
|
87
|
+
const parsed = Input.safeParse({ title: formData.get("title") }); // 2. validate
|
|
88
|
+
if (!parsed.success) return { error: "Invalid title" };
|
|
89
|
+
await db.post.create({ data: { ...parsed.data, authorId: session.user.id } }); // 3. authorise by owner
|
|
90
|
+
revalidatePath("/posts"); // 4. invalidate
|
|
91
|
+
return { ok: true }; // 5. return only what the UI needs
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- Every exported action is a public POST endpoint. A page-level auth check does **not** protect the actions on that page. Check auth and resource ownership inside each action (or in a `server-only` data access layer it calls).
|
|
96
|
+
- Validate every argument; types are not runtime checks.
|
|
97
|
+
- Return small plain objects; never return raw DB records.
|
|
98
|
+
- `redirect()` throws to work: call it outside `try/catch`, or rethrow.
|
|
99
|
+
- Use with `useActionState` for errors and pending state, `useOptimistic` for instant feedback.
|
|
100
|
+
- Actions are rejected when the `Origin` host differs from the app host (`x-forwarded-host` or `host`). If a reverse proxy doesn't forward the public host, or the app is served from extra domains, list them in `experimental.serverActions.allowedOrigins`; when self-hosting several instances, set `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` so all instances share the key.
|
|
101
|
+
|
|
102
|
+
## 6. Metadata
|
|
103
|
+
|
|
104
|
+
- Export `metadata` (static) or `generateMetadata` (dynamic) from `layout.tsx`/`page.tsx`. Only in Server Components.
|
|
105
|
+
- Set `metadataBase` in the root layout so relative Open Graph URLs resolve.
|
|
106
|
+
- Use `title.template` in the root layout (`"%s | Site"`) and plain `title` in pages.
|
|
107
|
+
- File conventions: `opengraph-image.tsx`, `icon.tsx`, `sitemap.ts`, `robots.ts`. In 16 their `params` (and image `id`) are promises.
|
|
108
|
+
- `generateMetadata` and the page share fetches through memoisation or `React.cache()`; don't fetch twice deliberately.
|
|
109
|
+
- Viewport and theme colour go in `viewport`/`generateViewport`, not `metadata`.
|
|
110
|
+
|
|
111
|
+
## 7. Middleware / proxy
|
|
112
|
+
|
|
113
|
+
- 15: `middleware.ts` at the root (or `src/`), exporting `middleware` and `config.matcher`.
|
|
114
|
+
- 16: rename to `proxy.ts` exporting `proxy`; it runs on the Node.js runtime only. If you need the Edge runtime, keep `middleware.ts` and tell the user. Don't blindly rename.
|
|
115
|
+
- Keep it cheap: redirects, rewrites, header and cookie tweaks, optimistic auth redirects.
|
|
116
|
+
- Never rely on it as the only authorisation check; re-check in pages, Route Handlers and Server Actions.
|
|
117
|
+
- Always set a `matcher` that excludes `_next/static`, `_next/image` and static files.
|
|
118
|
+
|
|
119
|
+
## 8. Environment variables
|
|
120
|
+
|
|
121
|
+
- Only variables prefixed `NEXT_PUBLIC_` reach the browser, and they are **inlined at build time**. Changing them needs a rebuild; a Docker image built once can't pick up new public values at run time.
|
|
122
|
+
- Never prefix a secret with `NEXT_PUBLIC_`. Read secrets only in server-only modules.
|
|
123
|
+
- Load order: `.env.$(NODE_ENV).local`, `.env.local` (skipped when `NODE_ENV=test`), `.env.$(NODE_ENV)`, `.env`. Commit only non-secret defaults.
|
|
124
|
+
- To read a server variable at request time rather than at build, make the code dynamic (`await connection()` from `next/server` first, 15+).
|
|
125
|
+
- Validate required variables at startup (a small zod schema in `env.ts`) so a missing one fails loudly.
|
|
126
|
+
|
|
127
|
+
## 9. Deployment pitfalls
|
|
128
|
+
|
|
129
|
+
- Run `next build` locally before shipping; many errors (missing `Suspense` around `useSearchParams`, invalid segment config, missing `default.tsx` for parallel routes in 16) only appear there.
|
|
130
|
+
- Self-hosting: use `output: "standalone"` for Docker and copy `public/` and `.next/static` into the image. With several instances, configure a shared cache handler or ISR results diverge per instance.
|
|
131
|
+
- Images: configure `images.remotePatterns` (not the deprecated `domains`). In 16, `images.qualities` defaults to `[75]`.
|
|
132
|
+
- Edge runtime has no Node APIs (`fs`, most DB drivers); keep DB access on the Node runtime.
|
|
133
|
+
- Long work in a Server Action or Route Handler hits the host's function timeout; move it to a queue or background job.
|
|
134
|
+
|
|
135
|
+
## Never
|
|
136
|
+
|
|
137
|
+
- Never put `"use client"` on a layout or page just to make one hook work.
|
|
138
|
+
- Never import a server-only module from a client file, or read `process.env.SECRET` in one.
|
|
139
|
+
- Never trust that middleware/proxy or a hidden button protects a Server Action.
|
|
140
|
+
- Never use the single-argument `revalidateTag(tag)` on 16, or `"use cache"` without `cacheComponents` enabled.
|
|
141
|
+
|
|
142
|
+
## Stop and ask the user
|
|
143
|
+
|
|
144
|
+
- Before enabling `cacheComponents`, the React Compiler or a major-version upgrade; each changes behaviour app-wide.
|
|
145
|
+
- Before changing the runtime (`edge` vs `nodejs`) or the deployment output mode.
|
|
146
|
+
- When it's unclear how fresh a piece of data must be.
|
|
147
|
+
|
|
148
|
+
## Report back
|
|
149
|
+
|
|
150
|
+
End with: routes and files changed, which components are client and why, the caching decision for each data source (cached for how long, invalidated by what), the `next build` result, and anything not verified in a production build.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"My Next.js App Router page keeps showing old product prices after I update them in the admin",
|
|
4
|
+
"Where should I put 'use client' in this app/ layout so the header dropdown works?",
|
|
5
|
+
"Write a server action that creates a comment and revalidates the post page",
|
|
6
|
+
"We upgraded to Next 16 and now middleware.ts gives a deprecation warning, what do I change?",
|
|
7
|
+
"Add generateMetadata with Open Graph images to the app/blog/[slug] route",
|
|
8
|
+
"My NEXT_PUBLIC_API_URL is still the old value in the Docker deploy even though I changed the env var"
|
|
9
|
+
],
|
|
10
|
+
"should_not_trigger": [
|
|
11
|
+
"Where should the selected-tab state live in my plain Vite React app?",
|
|
12
|
+
"Our Next.js bundle is huge, help me find which client components to code-split and measure with the Profiler",
|
|
13
|
+
"Review my Next.js pull request for server/client boundary leaks and hook bugs",
|
|
14
|
+
"Write a GitHub Actions workflow that builds and deploys our app",
|
|
15
|
+
"Set up a NestJS controller with validation pipes for the orders API",
|
|
16
|
+
"Configure Nuxt server routes and useFetch caching"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Next.js caching: the two models
|
|
2
|
+
|
|
3
|
+
Pick the model from `next.config.*`. If `cacheComponents: true` is set (Next.js 16+), use model B. Otherwise use model A. Write new code in the app's model; under model B, existing `fetch` cache options and `unstable_cache` keep working and can be migrated later, but segment config does not.
|
|
4
|
+
|
|
5
|
+
Always check behaviour with `next build && next start`; `next dev` renders every request fresh.
|
|
6
|
+
|
|
7
|
+
## Model A: previous model (no `cacheComponents`)
|
|
8
|
+
|
|
9
|
+
Defaults (Next.js 15+):
|
|
10
|
+
- `fetch` is **not** cached unless you opt in.
|
|
11
|
+
- `GET` Route Handlers are not cached unless you opt in.
|
|
12
|
+
- A route is still prerendered at build time if it uses no request-time API (`cookies()`, `headers()`, `searchParams`, uncached data after those). Fetches reached before any request-time API run once at build.
|
|
13
|
+
|
|
14
|
+
Opt in per request:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
await fetch(url, { cache: "force-cache" }); // cache indefinitely
|
|
18
|
+
await fetch(url, { next: { revalidate: 3600 } }); // time-based
|
|
19
|
+
await fetch(url, { next: { tags: ["posts"] } }); // tag for on-demand invalidation
|
|
20
|
+
await fetch(url, { cache: "no-store" }); // always fresh
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Non-`fetch` sources (ORM, SDK):
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { unstable_cache } from "next/cache";
|
|
27
|
+
export const getUser = unstable_cache(
|
|
28
|
+
async (id: string) => db.user.findUnique({ where: { id } }),
|
|
29
|
+
["user"], // key prefix; args are added to the key
|
|
30
|
+
{ tags: ["user"], revalidate: 3600 },
|
|
31
|
+
);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Route segment config (export from `page`, `layout` or `route`):
|
|
35
|
+
|
|
36
|
+
| Export | Values | Use |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `dynamic` | `'auto'` (default), `'force-dynamic'`, `'error'`, `'force-static'` | Force the whole segment static or dynamic |
|
|
39
|
+
| `revalidate` | `false` (default), `0`, seconds | Default revalidation for the segment; must be a literal (`600`, not `60 * 10`) |
|
|
40
|
+
| `fetchCache` | `'auto'`, `'default-cache'`, `'only-cache'`, `'force-cache'`, `'default-no-store'`, `'only-no-store'`, `'force-no-store'` | Advanced override; avoid unless needed |
|
|
41
|
+
|
|
42
|
+
The lowest `revalidate` among a route's layouts, pages and fetches wins for the whole route.
|
|
43
|
+
|
|
44
|
+
## Model B: Cache Components (`cacheComponents: true`, Next.js 16+)
|
|
45
|
+
|
|
46
|
+
Nothing is cached unless marked. Uncached async work must sit inside `<Suspense>`, or the dev overlay and build report a blocking route.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { cacheLife, cacheTag } from "next/cache";
|
|
50
|
+
|
|
51
|
+
export async function getPosts() {
|
|
52
|
+
"use cache";
|
|
53
|
+
cacheLife("hours"); // always pair a directive with a lifetime
|
|
54
|
+
cacheTag("posts");
|
|
55
|
+
return db.post.findMany();
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `"use cache"` at the top of a function or component caches its return value; at the top of a file it caches every export.
|
|
60
|
+
- Arguments and closed-over values become part of the cache key. They must be serialisable.
|
|
61
|
+
- Don't read `cookies()`/`headers()`/`searchParams` inside a `"use cache"` scope. Read them outside and pass the value in as an argument, or use `"use cache: private"`.
|
|
62
|
+
- `"use cache: remote"` stores entries in a shared cache handler (durable across instances); the default store is in-memory per instance.
|
|
63
|
+
- `Math.random()`, `Date.now()`, `crypto.randomUUID()` during render must be either inside `"use cache"` (same value for everyone) or after `await connection()` inside `<Suspense>` (per request).
|
|
64
|
+
- Push `await params`/`await cookies()` down into the component that needs it, inside `<Suspense>`, so the rest of the layout stays in the static shell.
|
|
65
|
+
- Segment config `dynamic`, `revalidate`, `fetchCache`, `dynamicParams` and `runtime` error in this model. Replace them with `"use cache"` + `cacheLife`, or plain uncached code for always-fresh data.
|
|
66
|
+
- `generateStaticParams` must return at least one param; an empty array errors.
|
|
67
|
+
- `"use cache"` entries are in-memory by default and scoped to one deployment, unlike the old `fetch` Data Cache. Use `"use cache: remote"` or a cache handler when entries must survive instance teardown.
|
|
68
|
+
- Route state is preserved across navigations (React `<Activity>`), so `useState` and form values no longer reset when the user navigates away and back.
|
|
69
|
+
|
|
70
|
+
## On-demand invalidation (both models)
|
|
71
|
+
|
|
72
|
+
| API | Where | Effect |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `revalidatePath(path)` | Server Action, Route Handler | Invalidate everything cached for a path |
|
|
75
|
+
| `revalidateTag(tag, profile)` | Server Action, Route Handler | Mark tagged entries stale; next visitor gets stale data while it refreshes. Next.js 16 requires the second argument, for example `'max'`. On 15 it takes only the tag |
|
|
76
|
+
| `updateTag(tag)` | Server Action only (16, either model) | Expire and refresh within the same request so the user sees their own write |
|
|
77
|
+
| `refresh()` | Server Action only (16) | Refresh the client router without touching tags |
|
|
78
|
+
|
|
79
|
+
Pick `updateTag` for forms and settings the user just edited, `revalidateTag` for content where a short delay is fine (catalogue, blog).
|
|
80
|
+
|
|
81
|
+
## Debugging stale data
|
|
82
|
+
|
|
83
|
+
1. Reproduce with `next build && next start`, not `next dev`.
|
|
84
|
+
2. Find every cache layer between source and screen: the data cache entry, the route's prerendered output, the client router cache, a CDN in front.
|
|
85
|
+
3. Check whether the data was read before a request-time API (model A: cached at build) or inside a `"use cache"` scope (model B).
|
|
86
|
+
4. Check that the mutation calls the invalidation with the exact tag or path used when caching.
|
|
87
|
+
5. Self-hosted with several instances: without a shared cache handler, each instance has its own cache and invalidation reaches only one.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: node-backend-patterns
|
|
3
|
+
description: Production rules for Node.js HTTP services written directly on Express or Fastify, without a full framework, including app/server split, schema validation of request input, centralised error middleware, graceful SIGTERM shutdown, structured pino logging, streaming with pipeline, helmet security headers, CORS and rate limiting. Use when starting or hardening an Express or Fastify service, adding request validation or an error handler, fixing dropped requests on deploy, or streaming large uploads and downloads.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Any Agent Skills host. Needs Node.js 18+ (prefer the current LTS) and the project's package manager.
|
|
6
|
+
metadata:
|
|
7
|
+
kete-loom/version: "0.1.0"
|
|
8
|
+
kete-loom/category: coding
|
|
9
|
+
kete-loom/risk: writes-files
|
|
10
|
+
kete-loom/requires: "node"
|
|
11
|
+
kete-loom/owner: "Kete-org"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Node backend patterns (Express and Fastify)
|
|
15
|
+
|
|
16
|
+
A Node service is production-ready when bad input is rejected at the edge, every error ends in one handler, logs are structured, and a deploy never cuts a request in half.
|
|
17
|
+
|
|
18
|
+
## First, look at the project
|
|
19
|
+
|
|
20
|
+
1. Read `package.json`: framework and major (`express` 4 vs 5, `fastify`), `"type"` (ESM or CJS), Node `engines`, existing validation (zod, TypeBox, Joi, ajv) and logger.
|
|
21
|
+
2. Find the entry point and check whether app construction and `listen()` are separated.
|
|
22
|
+
3. Keep the existing framework and libraries. Stop and ask the user before migrating Express to Fastify (or the reverse), or Express 4 to 5.
|
|
23
|
+
|
|
24
|
+
If the project is NestJS, use the `nestjs-patterns` skill instead.
|
|
25
|
+
|
|
26
|
+
## Structure
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
src/
|
|
30
|
+
app.ts # builds and returns the app; no listen(), no process handlers
|
|
31
|
+
server.ts # reads config, calls listen(), wires signals and shutdown
|
|
32
|
+
config.ts # parses and validates env once at boot
|
|
33
|
+
routes/ # one router/plugin per resource
|
|
34
|
+
services/ # business logic, no req/res objects
|
|
35
|
+
errors.ts # AppError classes with status and code
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- `app.ts` exports a factory so tests can create the app without a port (`supertest(app)` for Express, `app.inject()` for Fastify).
|
|
39
|
+
- Route handlers parse input, call a service, shape the response. Services never see `req`/`res`.
|
|
40
|
+
- Validate config at boot (for example a zod schema over `process.env`) and exit with a clear message if anything is missing.
|
|
41
|
+
|
|
42
|
+
## Validation at the edge
|
|
43
|
+
|
|
44
|
+
- Validate `body`, `params`, `query` and relevant headers on every route that accepts input. Treat everything from the client as `unknown` until parsed.
|
|
45
|
+
- **Fastify**: declare a JSON `schema` on the route (`body`, `querystring`, `params`, `response`). Fastify validates with ajv and serializes the response with fast-json-stringify, so a `response` schema keeps undeclared fields out of the output and stops columns leaking. Use TypeBox or a type provider for static types.
|
|
46
|
+
- **Fastify's ajv defaults are not strict.** They are `removeAdditional: true`, `coerceTypes: 'array'` and `useDefaults: true`. So `additionalProperties: false` silently strips unknown fields instead of rejecting them, and `"5"` is coerced to `5`. If you need unknown fields rejected, set `ajv: { customOptions: { removeAdditional: false } }` on the Fastify instance. Never enable ajv `allErrors` on public routes, because it opens a DoS risk.
|
|
47
|
+
- **Express**: a small middleware that runs `schema.safeParse(req.body)`, returns `400` with field errors on failure, and replaces `req.body` with the parsed value.
|
|
48
|
+
- Set body limits explicitly (`express.json({ limit: '100kb' })`, Fastify `bodyLimit`) and reject unexpected content types.
|
|
49
|
+
|
|
50
|
+
## Errors
|
|
51
|
+
|
|
52
|
+
1. Define `AppError` subclasses with `status`, a stable `code` and a safe `message`.
|
|
53
|
+
2. One error handler, registered last: Express `app.use((err, req, res, next) => ...)` with four arguments; Fastify `app.setErrorHandler(...)`.
|
|
54
|
+
3. Known `AppError`: respond with its status and `{ error: { code, message } }`. Validation errors: `400` with field details. Anything else: log the full error with the request id and respond `500` with a generic message.
|
|
55
|
+
4. **Express 4 does not catch rejected promises** from async handlers; wrap them or upgrade. Express 5 and Fastify forward rejections to the error handler.
|
|
56
|
+
5. Also send a `404` JSON response for unmatched routes.
|
|
57
|
+
6. Register `process.on('unhandledRejection')` and `uncaughtException` only to log and exit non-zero; never to keep running.
|
|
58
|
+
|
|
59
|
+
## Graceful shutdown
|
|
60
|
+
|
|
61
|
+
On `SIGTERM` (and `SIGINT` locally):
|
|
62
|
+
|
|
63
|
+
1. Mark the service not ready so the readiness probe fails and the load balancer stops sending traffic. On Kubernetes, keep serving for a few seconds (or add a `preStop` sleep) so endpoint removal propagates before you close the listener.
|
|
64
|
+
2. Stop accepting new connections: `server.close()` (Express/`http`) or `await app.close()` (Fastify, which also runs `onClose` hooks).
|
|
65
|
+
3. Let in-flight requests finish; close idle keep-alive sockets with `server.closeIdleConnections()`.
|
|
66
|
+
4. Close database pools, queue consumers and caches.
|
|
67
|
+
5. Force exit with code 1 after a timeout shorter than the orchestrator's grace period (Kubernetes defaults to 30 seconds).
|
|
68
|
+
|
|
69
|
+
Template in `references/templates.md`. Never call `process.exit()` before the server has closed.
|
|
70
|
+
|
|
71
|
+
## Logging
|
|
72
|
+
|
|
73
|
+
- Use `pino` (Fastify's built-in logger; `pino-http` for Express). JSON to stdout; pretty-print only in development.
|
|
74
|
+
- Attach a request id to every log line (honour an incoming `x-request-id` or generate one) and return it in the response header.
|
|
75
|
+
- Redact secrets: `redact: ['req.headers.authorization', 'req.headers.cookie', '*.password']`.
|
|
76
|
+
- Never log full request bodies, tokens or card data. Never use `console.log` in request paths.
|
|
77
|
+
|
|
78
|
+
## Streaming
|
|
79
|
+
|
|
80
|
+
- Use `pipeline` from `node:stream/promises` to connect streams; it propagates errors and destroys every stream on failure. Never chain bare `.pipe()` without error handling.
|
|
81
|
+
- Stream large files and exports instead of buffering them into memory. Set `Content-Type` and `Content-Disposition` before writing.
|
|
82
|
+
- For uploads, use a streaming parser (`busboy`, `@fastify/multipart`) with size and file-count limits, and stream to storage.
|
|
83
|
+
- Stop work when the client disconnects (listen for `close` on the request, or pass an `AbortSignal` to downstream calls).
|
|
84
|
+
|
|
85
|
+
## Security
|
|
86
|
+
|
|
87
|
+
- Headers: `helmet` (Express) or `@fastify/helmet`. Disable `x-powered-by` in Express (`app.disable('x-powered-by')`; helmet does this).
|
|
88
|
+
- CORS: an explicit origin allowlist (`cors` / `@fastify/cors`). Never reflect any origin together with `credentials: true`.
|
|
89
|
+
- Rate limiting: `express-rate-limit` or `@fastify/rate-limit`, stricter on login, signup and password reset. Use a shared store (Redis) when running more than one instance.
|
|
90
|
+
- Behind a proxy, set `app.set('trust proxy', ...)` (Express) or `trustProxy` (Fastify) to the real hop count so client IPs and rate limits are correct; never `true` on a directly exposed server.
|
|
91
|
+
- Set timeouts: `server.headersTimeout`, `server.requestTimeout`, and timeouts on every outbound HTTP and database call.
|
|
92
|
+
- Run as a non-root user; keep `npm audit` or the `dependency-audit` skill in CI.
|
|
93
|
+
|
|
94
|
+
## Never
|
|
95
|
+
|
|
96
|
+
- Trust `req.body` types without validation.
|
|
97
|
+
- Return raw error messages, stack traces or SQL errors to clients.
|
|
98
|
+
- Do blocking CPU work (sync crypto, large `JSON.parse`, image processing) on the request thread; move it to a worker or queue.
|
|
99
|
+
- Read `process.env` inside handlers.
|
|
100
|
+
|
|
101
|
+
## Before you finish
|
|
102
|
+
|
|
103
|
+
Run the project's lint, type-check and tests. Check by hand, or with a test: an invalid body returns 400, an unknown route returns 404 JSON, a thrown error returns a generic 500 and is logged with the request id, and `SIGTERM` during a slow request lets it complete. Report what changed, any new dependency, and any env variable the user must set.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"should_trigger": [
|
|
3
|
+
"Our Express API drops in-flight requests every time Kubernetes redeploys the pod",
|
|
4
|
+
"Add zod request validation and a single JSON error handler to this Express app",
|
|
5
|
+
"Set up a Fastify service with schema validation, helmet and rate limiting on login",
|
|
6
|
+
"Stream a large CSV export from Node without loading it all into memory",
|
|
7
|
+
"Replace console.log with structured pino logging and request ids in our Node server"
|
|
8
|
+
],
|
|
9
|
+
"should_not_trigger": [
|
|
10
|
+
"Add a NestJS interceptor that maps every response into a data envelope",
|
|
11
|
+
"Write a Dockerfile with a multi-stage build for our Node service",
|
|
12
|
+
"Should we run our API on Bun instead of Node to speed up cold starts?",
|
|
13
|
+
"Design the versioning scheme and error format for our public REST API",
|
|
14
|
+
"Write Playwright tests for the checkout page"
|
|
15
|
+
]
|
|
16
|
+
}
|