From tools
Use when about to recommend "the standard / idiomatic / canonical / de facto way" or "best practice" for a tool, library, framework, or workflow — OR when user invokes /defacto — OR when auditing the user's setup (workflow, Dockerfile, config) against industry convention. Triggers: "standard way to X", "how do most teams configure Y", "is my setup best practice", "audit my use of Z", "idiomatic structure for X", "set up X in CI". Symptoms: about to say "industry standard..." / "everyone does..." / "the convention is..." without checking the tool's docs this session; attributing community patterns to the vendor; recommending from memory; claiming "the standard" with no source; recommending a pattern deprecated in the current major; fusing multi-part questions into one answer; flattening a multi-way community split; inventing community-de-facto from demo forks. Skip ONLY when user cited a source, wants subjective preference over convention, or topic is universally stable (POSIX, git, ECMAScript) with no drift.
How this skill is triggered — by the user, by Claude, or both
Slash command
/tools:defactoThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
When someone asks "how should I use tool X" — or asks you to audit their setup against best practice — you must check **multiple distinct sources** and **never conflate them**:
When someone asks "how should I use tool X" — or asks you to audit their setup against best practice — you must check multiple distinct sources and never conflate them:
action.yml/official tutorials, scoped to the version the user actually targets.The central failure mode this skill prevents: flattening these tiers into "the standard." Each tier answers a different question. The user's choice depends on which question they're asking.
Core principle: Name your source. Every claim is labeled with one of the tiers above. No claim escapes labeling.
defacto orchestrates other skills; it does not re-implement them.
REQUIRED SUB-SKILL: [[verify]] — every claim must be primary-source-grounded. No memory-only quotes, no Stack Overflow as primary source, no hedging in place of fetching.
REQUIRED SUB-SKILL (conditional): [[superpowers:dispatching-parallel-agents]] — dispatch sub-agents only when each source needs reasoning (reading + summarizing many files, traversing a docs tree). For 3 single gh api calls of ~1 second each, parallel Bash calls in one tool block are cheaper and faster than dispatching agents. Rule of thumb: file-or-page fetch → parallel Bash; "read this repo and tell me what they do" → sub-agent.
RELATED: [[dig]] — when neither vendor docs nor adopter examples have a pre-published answer to a sub-question (partial coverage is normal), invoke dig for that sub-question only. Label the reconstruction Inferred: with named parts and confidence.
RELATED: [[test]] — when the question is "does this tool actually work this way" rather than "how do people use it", test is the right tool.
NOT RELATED (do not invoke): [[try-all]] — try-all is for implementing 2+ competing code approaches in worktrees. defacto is research-only.
/defacto <tool> or /defacto <question> directly.git, ECMAScript core) — no convention drift exists.test directly.Before any fetch:
1a. Pin the version OR the API generation. Two distinct triggers, both mandatory:
Trigger A — recent major bump. For any tool with a major SemVer bump in the last 18 months (Zod 3→4, pnpm pre/post-9.5 catalogs, React 18/19, Tailwind 3/4, Vite 5/6/7, Renovate's preset renames).
Trigger B — documented API rename or "replaced by" notice in the changelog even without a SemVer bump (PowerSync Sync Rules → Sync Streams, Zero definePermissions → mutators-and-context, Cosign COSIGN_EXPERIMENTAL flag removal). These are version-axis-like without being SemVer events — they cause the same wrong-major content problem.
Resolution order:
package.json / pnpm-lock.yaml / go.mod / Cargo.toml / lockfile to see what they actually run.apps/web on Zod 4, packages/shared on Zod 3 via pnpm catalog drift), pin per-package and label findings per-version.1a.1 — Fetch budget. If you're under a hard word/turn/budget cap that prevents per-claim fetching, do NOT silently emit findings from memory as if they were Vendor-official:. Silent unfetched claims labeled as vendor-grounded is the failure mode this rule prevents.
Degraded-mode output format (mandatory when fetch budget bites):
⚠️ DEGRADED MODE — no fetches performed this turn. All claims below are
best-effort recall, downgraded to `Inferred:`. Verify before acting.
Inferred (medium): <claim 1>
Inferred (medium): <claim 2>
...
The "⚠️ DEGRADED MODE" banner is non-optional and must be the first line of the response, before any labeled findings. Burying it in a preamble note is exactly the silent-unfetched failure mode the rule exists to prevent.
1b. Decompose compound questions. "How should I use Tailscale in GHA" is really three sub-questions (auth method + tags + triggers). Don't try to fuse them. List the sub-questions; label findings per sub-question.
1c. Narrow scope on bare tool names. /defacto k3s with no narrowing is too broad — pick the most common framing (install / setup) and state the scope explicitly, or ask one clarifying question.
Fetch the vendor's own primary sources. Each fetch is grounded per [[verify]].
Source selection by tool type:
| Tool type | Primary source(s) |
|---|---|
| GitHub Action | gh api repos/<o>/<r>/contents/README.md -H "Accept: application/vnd.github.raw" + action.yml and action.yaml (try both — trivy-action uses .yaml) |
| CLI tool | Official docs site (docs.<tool>.io / <tool>.dev) + <binary> --help empirically |
| Library | Official docs site + the lib's own tests/ for canonical usage + lib's CHANGELOG for version-gated features |
| Framework / platform | Canonical docs site (kubernetes.io, react.dev, helm.sh, argoproj.github.io) — not gh api |
| Container image | Image's own GitHub README + any examples/ directory |
Parallelize multi-page docs. When the vendor publishes a multi-page docs site (Helm's chart_best_practices/, ArgoCD's docs/operator-manual/, K8s's concepts/workloads/), fan out relevant page fetches in parallel — don't sequentialize them.
For competing-vendor questions ("Renovate vs Dependabot", "Yarn vs pnpm"), fetch both vendors' positioning pages in parallel. Vendor silence about the competitor is itself a finding (Vendor-silent:).
Quote with version applicability. If a recommendation is version-gated, record Vendor-official (since v9.5): so the user knows the floor.
If vendor sources contradict each other (README shows pattern A, companion cosign-installer shows pattern B), report both with their respective source paths. The vendor's internal inconsistency is the finding.
Fetch what the maintainer's own production code does:
gh api repos/<o>/<tool>/contents/.github/workflows/ to list workflow files, then fetch the user-facing ones (skip linting/release-internal CI)..github/workflows/ (which is just their build pipeline).examples/ directory or the maintainer's flagship app built on the lib (e.g., rocicorp/mono/apps/zbugs/ for Zero).Important caveats:
Look at independent adopter convergence. Source list by question domain:
| Question domain | Primary community sources | Search recipes |
|---|---|---|
| CI / GitHub Actions | actions/starter-workflows, github/codeql-action workflows, 2–3 CNCF projects' deploy workflows | gh api repos/actions/starter-workflows/contents/ci; gh api repos/<cncf-project>/contents/.github/workflows |
| Runtime / install / deploy | Awesome-X lists, homelab writeups, GitOps reference repos (kubefirst, okami101), Terraform registry | gh search repos "awesome-<tool>"; WebSearch "<tool> homelab production" site:github.com; WebSearch "<tool>" site:reddit.com/r/homelab; WebSearch "terraform-<tool>" site:registry.terraform.io |
| Architectural (workload kind, schema shape, multi-env) | Canonical Helm charts (Bitnami, prometheus-community, ingress-nginx), operator manifests (Strimzi, CloudNativePG, Cilium), CNCF projects' install/ or config/ | gh api repos/bitnami/charts/contents/bitnami/<app>/templates; gh api repos/<operator>/contents/config |
| Library API usage | Official examples/ + 2–3 major dependents (pin to same major first) | gh api repos/<owner>/<lib>/contents/examples; for dependents — gh search code "<lib>" extension:json filename:package.json then filter top results |
| Config file structure | 2–3 dogfooded configs of major adopters | gh api repos/<owner>/<adopter>/contents/<config-file> for known adopters |
| Young SDK ecosystem (<3yrs, sparse adopters) | Vendor's own demos/ directory + gh search repos <tool> adopter sample | gh api repos/<vendor>/<tool>/contents/demos; gh search repos "<tool>" --sort=stars --limit=20. Expect Vendor-saturated: as a likely finding |
Plus, when applicable: dominant-publisher house style. When one org ships 50+ artifacts under a single style guide, their conventions become de facto by sheer mass: Bitnami for Helm, HashiCorp for Terraform modules, Strimzi for Kafka operators, Argoproj-Labs for ArgoCD extensions. Treat as a fifth source category.
Dispatch strategy:
gh api calls → parallel Bash in one tool block.[[superpowers:dispatching-parallel-agents]].gh search code rate-limits at ~2–3 queries unauthenticated. Batch searches within one agent rather than fanning out one search per agent. If rate-limited, fall back to WebSearch + treat top-ranked recent blog posts/CNCF docs as the adopter set.gh api .../contents/<file> returns 404 when the file doesn't exist. Don't assume "no data" — try listing the directory first (gh api .../contents/.github), then gh search code repo:<o>/<r> <tool-name>, then conclude "adopter does not use the tool" as a finding.WebFetch on github.com URLs (raw.githubusercontent.com, /blob/) consistently 404s. Hard rule: github.com → gh api, never WebFetch. Use WebFetch only for non-GitHub URLs (docs sites, blog posts)..github/workflows/ first rather than guessing release.yml vs release.yaml, main vs master. One gh api .../contents/.github/workflows listing saves multiple guess-and-miss fetches.If steps 2–4 don't produce a clean answer for any sub-question (vendor doesn't address it, adopters diverge with no convergence, no template canonicalizes it), invoke [[dig]] for that sub-question only. Label its reconstruction Inferred: with named parts and confidence.
Partial coverage is the norm, not the exception. Label per-sub-question, not per-report.
Use one of these labels. Never invent a 7th category — if a claim doesn't fit, it's Inferred: with appropriate confidence.
| Label | When to use |
|---|---|
Vendor-official (current): | Current docs/README recommendation, version-pinned |
Vendor-official (legacy): | Previously-recommended, now deprecated, still echoed in third-party material |
Vendor-dogfooded: | What the maintainer's own code does (separate from docs) |
Vendor-saturated: | All findable adopters are vendor demo forks — no independent community yet (typically ecosystems <3 years old) |
Vendor-silent: | Vendor docs explicitly do not address the question; the silence itself is the finding |
Community-de-facto: | Requires ≥2 independent adopters showing convergence, OR one canonical template (actions/starter-workflows, helm create, cargo new, npm init) — see Step 6 cross-reference. A single non-template adopter is Inferred: (single-source, low) |
Anti-pattern-but-common: | De facto choice contradicts naive reading of vendor guidance but is universally followed (replicas=1 Deployment instead of StatefulSet for stateless singletons) |
Inferred (high/medium/low): | Synthesized from parts. High = 3+ corroborating sources, Medium = 1–2, Low = pure analogy |
Coexistence-pattern: | For intersection/"can I run both" questions where neither vendor endorses coexistence and no single tier-label fits — name the community-observed coexistence pattern itself (e.g., "Dependabot for security-only + Renovate for version updates, with Dependabot's version-updates muted"). Always pair with Inferred: confidence if not directly attested by adopters |
Community-de-facto: sub-forms — flag which one:
When tiers diverge, name every gap explicitly as bullets, not prose. Common gap shapes:
gh search repos topic:<tool> --sort=stars, (b) explicit count of adopter examples sampled ("3 of 4 sampled CNCF projects use pattern A"), (c) blog-hit ranking on first-page WebSearch. If no anchor is available, use ordinal language only ("more visible in homelab writeups", "predominant in cloud-IaaS samples") — never invent quantities.appendonly no in HA). Name the vendor constraint, name the user's scope, name the mismatch. This is a gap with the user, not a gap between tiers.Vendor-saturated: and state the cause.If the user provided their setup (workflow, Dockerfile, config), compare per-key/per-step against the labeled baselines.
For multi-key configs (renovate.json, Dockerfile, large workflows): produce one labeled finding per key. Group adjacent keys only when they share a single source citation. Don't write a single prose block summarizing 14 keys.
Do not recommend which to follow. Present the gaps, let the user choose. Stating "you should keep the cron" is out-of-scope unless the user explicitly asks "which should I follow?" — at which point you may recommend, citing their stated constraints.
For highly-configurable tools (Renovate, ESLint, Webpack), vendor silence on most knobs is the norm — don't belabor every Vendor-silent: finding for a knob the docs simply don't address.
After research, evaluate against [[html]]'s trigger criteria — unless overridden:
html.The artifact decision is on the labeled findings alone — skill-meta sections (pain points, methodology) stay in chat regardless.
Terse style (default in this user's env): no preamble, no trailing recap, no "Summary" sections, no hedging filler. Lead with labeled findings. The findings ARE the output; do not append a "Conclusion."★ Insight ─ blocks per the style's requirement, but still lead with labeled findings.When a strict word/char cap pushes against full labels, abbreviate inline: [V-cur], [V-leg], [V-dog], [V-sat], [V-sil], [C], [A], [I-hi/med/lo]. Use only when necessary; full labels are clearer.
Single-question case:
Vendor-official (current): <recommendation> (source: <path/url>).
Vendor-dogfooded: <what maintainer actually does> (source: <repo/path>).
Community-de-facto: <convention> (sources: <adopter 1>, <adopter 2>).
Gap: <one bullet per gap shape>.
Compound (multi-sub-question) case — when Step 1b decomposed into 2+ sub-questions, use per-sub-question section headers, NOT inline splits:
### Sub-question 1 — <name>
Vendor-official (current): ...
Community-de-facto: ...
Gap: ...
### Sub-question 2 — <name>
Vendor-official (current): ...
...
### Cross-cutting gaps
- <gaps that span multiple sub-questions>
Section headers per sub-question are required, not optional — they keep the report scannable and prevent the failure mode where a multi-question answer reads as one prose blob with embedded labels.
Three lines is fine if three lines suffice for a single-question case. Long output is fine only when each additional line is load-bearing.
Community-de-facto: reporting.Community-de-facto: when all "adopters" are vendor demo forks. → That's Vendor-saturated:, not community.Community-de-facto: from a single adopter. → Single-source is Inferred: (single-source, low).WebFetch a github.com URL. → Use gh api instead.| Mistake | Fix |
|---|---|
| Memory-only recommendation | Fetch the README via gh api; quote the exact line |
| Conflating community pattern with vendor recommendation | Label both separately with their tier labels |
| Treating "Vendor-official" as monolithic when docs ≠ dogfood ≠ blog | Split into Vendor-official (current/legacy), Vendor-dogfooded:, report each separately |
| Skipping version-pinning before fetching | Step 1a is mandatory for any tool with a major bump in 18 months |
| Self-dogfooded CI is "strongest signal" — universally true? | No. Strong for invocation mechanics. Often weak for user-facing convention (Sigstore KMS) or when the maintainer's CI doesn't exercise the user's use case (Tailscale smoke test) |
| Treating one ecosystem's template as universal | CodeQL convention ≠ Trivy convention ≠ Snyk convention. Check the target tool's own ecosystem |
Inventing Community-de-facto: from demo forks | Label Vendor-saturated: and state the cause (young ecosystem) |
Claiming Community-de-facto: from one adopter | One adopter = Inferred: (single-source, low) |
| Sequential fetches for independent multi-page docs sites | Parallelize vendor doc-page fetches the same way community sources are parallelized |
| Dispatching sub-agents for trivial parallel fetches | Use parallel Bash in one tool block; reserve agents for reasoning-heavy sources |
WebFetch on github.com URLs | Hard rule: github.com → gh api. WebFetch only for non-GitHub sources |
| Flattening multi-modal community splits | Report as multi-modal with rough population breakdown by user-segment |
| Adding a recommendation when user didn't ask "which should I follow?" | Don't. Present the gap, let them choose |
Writing "Summary" / "Conclusion" in Terse style | The labeled-findings block IS the output |
Treating Inferred: as equivalent to vendor or community labels | Third-tier. Anchor confidence to corroboration count (3+ = high, 1–2 = medium, analogy = low) |
| One-prose-block audit of a 14-key config | One labeled finding per key |
User: "What's the de facto way to sign container images with cosign — keyless OIDC or keyed?"
Wrong (memory-only, conflates tiers):
"Keyless OIDC is the industry standard; cosign defaults to it."
Wrong because it (a) ignores that cosign's own release pipeline uses keyed-via-KMS, (b) treats one vendor doc surface as monolithic when multiple vendor docs conflict, and (c) attributes the "default" without naming which tier.
Right (multi-tier with intra-vendor gap named):
Step 1: Question pins to a recent generation (cosign v2+ removed COSIGN_EXPERIMENTAL and made keyless the documented default). Trigger B applies — record current generation explicitly.
Step 2 — Vendor-official check (parallel fetches of multiple vendor surfaces):
gh api repos/sigstore/cosign/contents/README.md → "Keyless signing with the Sigstore public good Fulcio certificate authority and Rekor transparency log (default)."WebFetch docs.sigstore.dev/cosign/signing/overview → "Identity-based signing is the default because managing and distributing keys can be challenging."gh api repos/sigstore/cosign-installer/contents/README.md → flagship workflow example uses --key env://COSIGN_PRIVATE_KEY (the keyed path) with permissions: id-token: write annotated.Step 3 — Vendor-dogfooded check: gh api repos/sigstore/cosign/contents/.github/workflows/cut-release.yml → Sigstore signs their own cosign releases with a GCP KMS key (_KEY_RING=release-cosign, _KEY_NAME=cosign, WIF-authed GCP). The maintainers do not dogfood pure keyless for canonical release artifacts.
Step 4 — Community-de-facto check (parallel Bash):
gh api repos/kyverno/kyverno/contents/.github/workflows/release.yaml → cosign sign --yes (no --key) → keyless.gh api repos/falcosecurity/falco/contents/.github/workflows/reusable_publish_docker.yaml → COSIGN_YES: "true", permissions.id-token: write, no key → keyless.Labeled report:
Vendor-official (current, README): keyless OIDC (Fulcio + Rekor) is the default;
`cosign sign $IMAGE` triggers identity-based signing
(sigstore/cosign/README.md).
Vendor-official (current, companion action): keyed example via `--key env://`
in cosign-installer's flagship workflow example
(sigstore/cosign-installer/README.md).
Vendor-dogfooded: KMS-backed keyed signing for Sigstore's own release artifacts
(sigstore/cosign/.github/workflows/cut-release.yml — GCP KMS via WIF).
Community-de-facto: keyless `cosign sign --yes` with `id-token: write` —
Kyverno's release.yaml and Falco's reusable_publish_docker.yaml both use this.
Gap:
- Intra-vendor: cosign README leads with keyless; cosign-installer's lead
example shows keyed. Both vendor-official.
- Vendor-dogfood vs vendor-docs: docs say "keyless is default"; Sigstore signs
themselves keyed-via-KMS. Different threat models — per-build provenance vs
canonical release-key semantics.
No recommendation issued unless user asks "which should I follow?"
User: "What's the de facto way to install k3s for a small production cluster (1–3 nodes)?"
Labeled findings:
Vendor-official (current): bare install script `curl -sfL https://get.k3s.io | sh -`
(docs.k3s.io/quick-start). sqlite default datastore; HA requires 3+ servers
with embedded etcd (docs.k3s.io/datastore/ha-embedded).
Vendor-silent: vendor docs don't acknowledge k3sup, Terraform modules, or
GitOps wrappers — those are entirely community.
Community-de-facto (multi-modal, splits ~3 ways):
- Homelab / bare-metal: bare script + sqlite (n=1) or embedded etcd (n=3),
often with k3sup for SSH automation (alexellis/k3sup, 7.4k stars).
- Cloud-IaaS: Terraform modules — rancher/terraform-k3s-aws-cluster (vendor-adjacent),
x00real/terraform-k3s, vietanhduong/terraform-k3s.
- Reference GitOps stacks: okami101's "Beautiful GitOps Day" series, kubefirst.
Inferred (medium): GitOps layer (Argo CD / Flux) applied after bootstrap is
near-universal in "production"-labeled writeups, regardless of install method.
Gap: vendor's "official" path is bare script; everything beyond is community
convenience-layer convention added by the ecosystem.
User: "What's the de facto way to define permissions in rocicorp's Zero sync engine?"
Right (Trigger-B version-pinning + saturated + legacy-drift):
Step 1a (Trigger B): Zero's definePermissions / RLS-style API is deprecated in current docs. Pin to current generation (mutators-and-context model) before fetching.
Step 2 — Vendor-official check:
WebFetch zero.rocicorp.dev/docs/permissions → "Zero does not have (or need) a first-class permission system like RLS. Instead, you implement permissions by authenticating the user in your queries and mutators endpoints."WebFetch zero.rocicorp.dev/docs/deprecated/rls-permissions → "This API is deprecated: It will be removed in a future release of Zero."Step 3 — Vendor-dogfooded check: gh api repos/rocicorp/mono/contents/apps/zbugs/shared → splits into auth.ts (Role type), queries.ts (ctx-filtered reads), mutators.ts (authz on writes). The file layout is dogfooded — not prescribed by docs.
Step 4 — Community check: gh search repos "@rocicorp/zero" → all hits are either schema-generation tooling (drizzle-zero, prisma-generator-zero) or intro tutorials mirroring vendor demos. No independent layout convention.
Labeled report:
Vendor-official (current): permissions via authenticated queries + custom
mutators with a Context object — no first-class permission API
(zero.rocicorp.dev/docs/permissions).
Vendor-official (legacy): `definePermissions` / `ANYONE_CAN` / ZQL-rule API
deployed via `zero-deploy-permissions` — DEPRECATED, scheduled for removal
(zero.rocicorp.dev/docs/deprecated/rls-permissions).
Vendor-dogfooded: `shared/{auth,queries,mutators}.ts` file split in zbugs;
this is the maintainer's file-layout convention, not prescribed in docs
(rocicorp/mono/apps/zbugs/shared/).
Vendor-saturated: no independent adopters with non-vendor schema/permissions
conventions; third-party content is generators or tutorials.
Gap:
- Temporal (deprecation drift): most third-party tutorials (incl. Feb 2025
marmelab post, prisma-generator-zero) still teach the deprecated
`definePermissions` API. Users copying older guides will land on
removed-soon code.
- None at vendor-vs-community level — ecosystem too young.
Because the gap is the answer the user needs. If they're optimizing for:
All four are valid optimizations; the choice depends on user context the user owns. Your job is to make the choice visible — never collapse the tiers.
npx claudepluginhub pandoks/.dotfiles --plugin toolsCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.