Stack-agnostic playbook for the native, non-custom way to do something before writing a script or wrapper. Use when tempted to add a dependency or build a helper, or content-guards blocks a write. Climbs a fixed ladder; ends against silent fallback.
Scanned 9/23/2026
npx -y skills add dryvist/claude-code-plugins --skill native-first --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Native First?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/dryvist-native-first)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: native-first
description: "Stack-agnostic playbook for the native, non-custom way to do something before writing a script or wrapper. Use when tempted to add a dependency or build a helper, or content-guards blocks a write. Climbs a fixed ladder; ends against silent fallback."
---
# Native-First
Find the way something is *meant* to be done before building a custom way. Most
"I need a script" moments have a native answer that is smaller, already tested,
and maintained by someone else. This skill is the search for that answer.
It pairs with the script-guard hooks in this plugin. The hooks **block** an unnecessary
script; this skill **supplies the native path** that makes the block irrelevant.
`ponytail` decides *what rung* to reach for; native-first does the *research* that
rung needs when the answer is not already in front of you.
## When to use
- You are about to write a shell/python/glue script or a custom helper function.
- You are about to add a dependency for something small.
- A script-guard hook just blocked a script write. Do not route around it —
run this ladder instead.
- You catch yourself thinking "there's probably a flag for this, but it's faster
to just script it." That thought is the trigger.
## The ladder — stop at the first rung that holds
Climb in order. Each rung is cheaper to maintain than the one below it.
1. **The tool's own config, flag, or built-in module.**
The single most-skipped rung. Check `--help`, `man <tool>`, `tldr <tool>`, and
the tool's config-file reference before anything else. A `--format`, a config
key, a built-in subcommand, or a stdlib module usually exists.
*Examples:* `jq`/`--json` output instead of parsing text with `awk`;
`git config` instead of editing `.git/config`; a language's stdlib
(`pathlib`, `datetime`) instead of shelling out.
2. **A native platform feature.**
The OS, runtime, or data layer often does it declaratively.
*Examples:* a `launchd`/`systemd` unit instead of a cron-and-pidfile script;
a database `CHECK`/`UNIQUE` constraint instead of app-side validation; CSS
instead of JS; an HTML input type instead of a date-picker library.
3. **Official docs — via Context7 MCP, not memory.**
Look up the current, versioned docs for the tool or library. Memory is stale;
APIs move. Use the Context7 MCP (`resolve-library-id` then `query-docs`) or the
vendor's own docs site. Never assert an API exists from recall — verify it.
4. **A package/module registry.**
Someone published the thing. Search the ecosystem registry before writing glue:
Ansible Galaxy (a role/collection/module), Terraform Registry (a provider/
module), nixpkgs (a package/option), the language package index. A maintained
module beats a bespoke script.
5. **The issue tracker.**
Ask the source: search the tool's GitHub issues/discussions for
"how do I do X natively" or "is X supported". The answer — including "not
supported, here's the workaround" — is often already written down.
## Ordering rule: supported before bespoke
When more than one native path exists, prefer in this order:
**vendor-supported → community-supported → bespoke.**
A first-party feature outranks a popular plugin, which outranks anything you write.
## Terminal rule — no silent script fallback
If you climb the whole ladder and find no native path, the output is **not** a
script by default. The output is an **evidenced conclusion**:
> "No native path exists. I checked: `<tool> --help` (no relevant flag), the
> `<platform>` feature set (nothing declarative for this), Context7 docs for
> `<library>` vX (no API), the `<registry>` (no module), and issue `#<n>`
> (maintainer confirms unsupported). A small script is the remaining option —
> here it is, scoped to just this gap."
### Sanctioned helper
A helper that survives the terminal rule is **sanctioned, not incidental**: record
it in the project's own docs alongside the evidence that justified it — the rungs
checked and what each returned — and re-check that evidence when the underlying
tool ships its next major version. A native path that did not exist at v2 often
exists at v3, and the helper should retire the moment it does.
Only after that evidence is a custom script the right call. A script written
*without* that evidence is the thing this skill and the script-guard hooks
exist to stop. "I couldn't find one" is not evidence; "I checked these five
places and here is what each returned" is.
## Applying it
Report which rung the answer came from, so the next reader learns the native path
too: *"Used the tool's own `--output json` flag (rung 1)."* When you reach the
terminal rule, list the rungs checked and what each returned — that list is the
justification the script needs to exist.
## Related
- **script-guard hooks** (this plugin) — block unnecessary script writes; this
skill supplies the native alternative they assume exists.
- **native-first is stack-agnostic** — it is not Nix-specific. On a Nix machine,
a repo's `nix-tool-policy` rule adds the Nix-specific rungs on top of this ladder.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!