Api skill builder
Skill aditya-m-bharadwaj/APIskillBuilderSkill/.claude/skills/api-skill-builder
A Claude Code skill that turns a third-party REST API into a safe, single-file Python CLI + matching runtime skill — credential never enters AI context, every mutation is classifier-gated (read / mutating / destructive / billable / financial / privilege) and audit-logged.
npx -y skills add aditya-m-bharadwaj/APIskillBuilderSkill --skill api-skill-builderAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Bootstrap a new "<vendor>-api-skill" project — a safe, cross-platform single-file Python CLI that mediates a third-party REST API, plus a matching Claude skill that drives it under explicit AI-safety constraints (token never enters AI context; every mutation passes through a six-tier safety classifier; every mutation is recorded in a local audit log). Trigger when the user asks to "build a CLI / skill for <some API>", "wrap the <X> API safely", or to mirror the linode-api-skill pattern for a new vendor.
SKILL.md
30.0 KB, as published. Nobody here has run it
API Skill Builder — bootstrap a vendor-API CLI + Claude skill with AI-safety baked in
This skill takes you from "I want to drive the <X> REST API safely from a Claude session" to a published alpha that:
- never lets the AI read the API credential,
- classifies every endpoint into a six-tier risk taxonomy and refuses to send a mutation without the matching operator-supplied flag,
- stores the credential in the strongest OS-native secret store available, with file fallback at mode
0600, - writes an append-only audit log of every mutation,
- ships with cross-platform installers, MIT license, full doc set, CI, issue/discussion templates, and a tracked project-memory layer.
The canonical reference implementation is linode-api-skill at https://github.com/aditya-m-bharadwaj/linode-api-skill. Whenever this skill says "mirror the pattern", read the corresponding file there and adapt it. Do not invent variations of the safety contract — copy it.
Hard rules (non-negotiable for every generated skill)
When you generate a new <vendor>-api-skill repo, the resulting tool MUST satisfy all of these. If a target API makes one of them impossible (e.g. mandatory query-string auth), surface the conflict to the operator and stop — do not silently weaken the contract.
- The API credential never enters the AI's context. Not via env, not via
cat, not via argv, not via dialog stdout the AI can see. Entry path is<bin> setup(TTY-only, hidden prompt) or<bin> gui-setup(native OS password dialog, AI-runnable but renders out-of-band of any pipe the AI reads). - Storage is OS-native first, file fallback at mode
0600only. macOS Keychain → Linux Secret Service (libsecret) → file at~/.<vendor>-api-skill/token(mode0600, refuses to read if broader). Single-string-secret backends only — if the vendor uses a key+secret pair, store the pair as one URL-encoded or JSON blob in one keystore entry. - Verify before store. A new credential is validated against a known-good read endpoint (
whoami-equivalent for the API) BEFORE replacing whatever is already in the keystore. A bad credential never overwrites a working one. - Six-tier safety classifier with required-flag matrix. Every mutation passes through
classify(method, path)which returns one of:read,mutating,destructive,billable,financial,privilege. The CLI itself enforces the required flags; the matrix is the same aslinode-api-skill's. Unrecognized endpoints fall through to the strictest applicable default (GET → read, DELETE → destructive, anything else → mutating). - Append-only audit log of every mutation.
~/.<vendor>-api-skill/audit.log, mode0600, one JSON line per mutation, with timestamp / user / action / target / parameter metadata — never the token, never request body values, never generated secrets. - Path / argument hardening. Validate paths against a tight regex; reject
../.traversal segments and URL-encoded%-sequences pre-classification. Refuse--body @filepaths that resolve inside the config dir. Strip a leading API-version prefix (e.g./v4,/v3) at the boundary if the docs canonically include it. - Stdlib-only Python, single file.
bin/<vendor>-api-skillis one Python 3.8+ file using only the stdlib. Norequests, noclick, nopydantic, nokeyring. This eliminates supply-chain risk on a privileged tool. - Every mutation needs human confirmation in chat AND the machine
--yesflag.--yesalone is never enough; the AI must obtain explicit human confirmation in chat before sending. - MIT license, AI-authorship disclosure, commit-trailer convention.
AUTHORS.mddiscloses the model that wrote the code. Commits carryPrompted-By: <operator>+Co-Authored-By: <model>trailers. Seelinode-api-skill/CONTRIBUTING.mdfor the exact format. - Threat model documented.
SECURITY.mdlists what the tool defends and what it does NOT defend; reporting goes through GitHub private security advisories.
The build process
Follow these steps in order. Do not skip "in-flight" steps to land a partial alpha — the safety contract is most useful when complete.
Step 0 — Confirm scope with the operator
Before writing code, agree on:
- API name and slug. Slug is
<vendor>-api-skill(kebab-case, no doubling). Used as the binary name, repo name, and Claude skillname:field. - Auth model. Bearer token?
apikey+secretpair? OAuth? HMAC-signed requests? This shapes the token storage andgui-setupflow. - API base URL and version. e.g.
https://api.linode.com/v4,https://api.porkbun.com/api/json/v3, etc. Note whether the canonical docs paths include the version segment (you'll want to strip it at the boundary if so — see_strip_v4inlinode-api-skill). - The "billable" endpoints. Which paths cost real money when called? Get a list from the operator or the vendor's pricing page. These are the ones that need
--i-understand-billing. - The "financial" and "privilege" prefixes (if any). Some APIs don't have these tiers — that's fine; leave the prefix lists empty.
Step 1 — Init the repo
mkdir ~/Code/<slug>
cd ~/Code/<slug>
git init -b main
Drop in the LICENSE (MIT, copyright "<slug> contributors"), .gitignore (mirror linode-api-skill), and the dir skeleton:
.claude/
├── skills/<slug>/SKILL.md ← the runtime skill (will be authored after the CLI exists)
├── commands/{resume,save}.md ← project-level slash commands
└── settings.json ← graphify PreToolUse hook (installed by `graphify claude install`)
.github/
├── workflows/{ci,codeql}.yml
├── ISSUE_TEMPLATE/{bug_report,feature_request,config}.{md,yml}
├── DISCUSSION_TEMPLATE/{q-and-a,ideas,show-and-tell}.yml
└── FUNDING.yml
bin/<slug> ← the CLI (Python 3.8+, stdlib only)
tests/test_classify.py ← offline classifier tests
docs/
├── README.md
├── progress/{TEMPLATE.md,YYYY-MM-DD-initial-alpha.md}
├── decisions/{TEMPLATE.md,NNNN-*.md}
└── settings.local.json.template ← harness deny-rules template
install.sh
install.ps1
AUTHORS.md
CHANGELOG.md
CLAUDE.md
CONTRIBUTING.md
LICENSE
README.md
SECURITY.md
Step 2 — Design the safety classifier
Author the classifier table in bin/<slug> with five collections (mirror linode-api-skill line ~620+):
_FINANCIAL_PREFIXES— tuple of path prefixes under which any non-GET isfinancial. Leave empty()if the API has no money-movement endpoints._PRIVILEGE_PREFIXES— tuple of path prefixes under which any non-GET isprivilege(token/user/oauth management)._BILLABLE_EXACT— set of(METHOD, normalized_path)tuples that allocate a paid resource._MUTATING_EXACT— set of(METHOD, normalized_path)for explicitly-mutating-but-free endpoints (clearer than relying on the default)._DESTRUCTIVE_EXACT— optional, for non-DELETE destructive endpoints (e.g.POST /…/disable).
Implement _normalize_path(path) — strips the API-version prefix if applicable, then maps numeric segments to {id} for table lookup. Implement classify(method, path) returning (tier, [required_flags], explanation).
Test the classifier offline for every entry. Cross-check each _BILLABLE_EXACT entry against the vendor's pricing page — over-cautious is safe; under-cautious is dangerous.
Step 3 — Implement token storage
Mirror the storage layer from linode-api-skill (look for _kc_get_macos, _kc_set_macos, _kc_get_linux, _file_get, _file_set):
- macOS:
security add-generic-password -U(in-place update, no delete-then-add race). - Linux:
secret-tool store/secret-tool lookup(libsecret). Falls through to file if not present. - Windows / fallback: file at
~/.<slug>/token, mode0600. Refuse to read if POSIX mode is broader than0600.
For multi-part credentials (apikey + secret), serialize as one JSON blob before storage so each backend stays a single-string store. Encode/decode at the boundary; the rest of the CLI sees one opaque string and decodes inside _request.
Step 4 — Implement gui-setup and setup
setupreads viagetpass(hidden prompt) from a TTY. AI agents cannot run this. The install script'scurl … | shinvocation re-attaches stdin to/dev/ttyso it still works when invoked through a pipe.gui-setuppops a native OS password dialog:- macOS:
osascriptwithdisplay dialog "..." with hidden answer. - Linux: try
zenity --password, fall back tokdialog --password. - Windows: PowerShell
Get-Credential(returns aSecureString; convert to plain inside the PS one-liner and emit to stdout).
- macOS:
- The dialog process's stdout is captured into Python memory via
subprocess.run(..., capture_output=True). The token bytes never re-enter stdout that any pipe / observer can see. - Validate the captured token by calling the API's
whoami-equivalent BEFORE writing it to the keystore (Step 3 contract). - On rotation: tell the user to revoke the old token at the vendor's dashboard. Local replacement does not invalidate the old token server-side.
Step 5 — Implement named commands + generic api gateway
- Named commands for the most common, highest-value workflows. For a domain registrar (Porkbun), this is
domains,dns-list <domain>,dns-create,dns-delete <id> --confirm-id,pricing, etc. Each named command performs the classification check inline and audits on success. - Generic
apicommand for full API coverage:<slug> api <METHOD> <path> [--data …] [--body @file] [--query k=v] [--paginate] [--dry-run] [--json] [--yes] [--confirm-id …] [--i-understand-billing] [--allow-financial] [--allow-privilege]. Filter outAuthorization-header overrides in--header-style flags. Refuse--body @filepaths that resolve inside the config dir. - Audit-log every non-read call after success (or after a 4xx that did mutation work).
Step 6 — Write tests
tests/test_classify.py loads bin/<slug> via importlib.machinery.SourceFileLoader (no install needed) and exercises:
- One test per
_BILLABLE_EXACT/_FINANCIAL_PREFIXES/_PRIVILEGE_PREFIXESentry — assert classification and flags. _normalize_path: numeric segments →{id}, string segments preserved, version-prefix stripping, edge cases (/v40/fooand/foo/v4/barshould NOT be stripped)._validate_path: traversal rejection, URL-encoded%rejection, ASCII path-char whitelist.- Method case-insensitivity.
- Default fallback: unknown GET → read, unknown DELETE → destructive, anything else → mutating.
- Platform helpers (
_has_display,_platform).
Aim for ≥25 tests; ≥30 once you've covered all classifier-table entries.
Step 7 — Author the runtime SKILL.md
Author .claude/skills/<slug>/SKILL.md. Use linode-api-skill/.claude/skills/linode-api-skill/SKILL.md as the template. Sections to mirror:
- Frontmatter (
name,description). - Hard rules.
- How the safety classifier works (the same six-tier table).
- Named commands table.
- Generic
apigateway examples for each tier. - Resource-category checklist (one row per major API category — what to confirm with the user before calling).
- Token management workflows (add, rotate, remove, diagnose).
- Workflow recipes (the 4–8 most common multi-step operations for this vendor).
- Things you should NOT do.
- When something goes wrong (error → action table).
Step 8 — Author the supporting docs
For each, copy the corresponding file from linode-api-skill and rewrite for the new vendor:
README.md— install one-liners, token management, classifier reference, common workflows, file map, uninstall. Status banner at top:Status: v0.1.0-alpha.1.AUTHORS.md— AI-authorship attribution + AI-generated-code disclaimer.SECURITY.md— threat model: defended vs. not-defended, hardening recommendations, private-advisory reporting link.CONTRIBUTING.md— stdlib-only rule, classifier-extension procedure, test pattern, full commit-message format (Prompted-By + Co-Authored-By trailers).CHANGELOG.md— one[0.1.0-alpha.1]entry describing the alpha; future work goes under[Unreleased].CLAUDE.md— project-level hard rules for any AI agent in the repo. Defers to.claude/skills/<slug>/SKILL.mdas authoritative.
Step 9 — .github/ metadata
Copy from linode-api-skill/.github/:
workflows/ci.yml— 3 OS × Python 3.8–3.12 matrix (exclude macOS 3.8/3.9 — runner images don't ship them). Steps:py_compile,unittest discover tests, smoke<slug> classifyon a read and a destructive path. Separateshellcheck install.shjob on Ubuntu.workflows/codeql.yml— GitHub's CodeQL static analysis. Matrix overpython(the CLI is Python; rules catch path-traversal, injection, weak crypto, etc.) andactions(lints the workflow files themselves for token-scope and untrusted-input issues). Triggers on push tomain, PR tomain, and a weekly cron.build-mode: none— the CLI is stdlib-only so there's nothing to compile. Pair with "Code scanning" enabled in repo settings (Step 14). The canonical template lives in this skill's own repo atAPIskillBuilderSkill/.github/workflows/codeql.yml; for a generated vendor skill, copy it and addpythonalongsideactionsin the language matrix.ISSUE_TEMPLATE/{bug_report,feature_request}.mdandconfig.yml—config.ymldisables blank issues and points contact links at the private security advisory page,SECURITY.md, and Discussions.DISCUSSION_TEMPLATE/{q-and-a,ideas,show-and-tell}.yml.FUNDING.yml— fill ingithub: [<operator-username>]; comment out the rest.
Step 10 — Memory layer
Set up the same docs/ layer that linode-api-skill uses:
docs/README.md— human-facing index of the memory layer.docs/progress/TEMPLATE.mdanddocs/progress/YYYY-MM-DD-initial-alpha.md— seed entry covering this scaffolding session.docs/decisions/TEMPLATE.mdand ADRs0001-N. At minimum write:0001-stdlib-only-python.md— why no requests/click/keyring.0002-safety-classifier-six-tiers.md— the tier taxonomy.0003-cross-platform-token-storage.md— backend selection.0004-ai-safe-token-entry-gui-dialog.md— the out-of-band entry pattern.0005-prompted-by-trailer-convention.md— commit-trailer rationale.0006-monolithic-cli-file.md— single-file rationale.0007-versioning-semver.md— SemVer with-alpha.N.- One ADR per vendor-specific decision (auth flow, version-prefix, billable-list source).
docs/settings.local.json.template— harness deny-rules template using~/paths (NOT/Users/<operator>).
Step 11 — Project-level slash commands + graphify
.claude/commands/resume.md— readsdocs/progress/(most recent),graphify-out/GRAPH_REPORT.md, three most recentdocs/decisions/. Adapt fromlinode-api-skill/.claude/commands/resume.md..claude/commands/save.md— writes a newdocs/progress/YYYY-MM-DD-<slug>.md, optionally creates an ADR, routes reusable cross-project concepts to~/.claude/vault/zettel/concepts/. Adapt fromlinode-api-skill/.claude/commands/save.md.- After at least one code file exists, run
graphify update .once to populategraphify-out/. Install the post-commit hook:graphify hook install. Install the Claude PreToolUse hook:graphify claude install(writes.claude/settings.json).
Step 12 — Install scripts
install.sh(POSIX) — verify Python 3.8+, clone the repo (or use existing checkout), symlinkbin/<slug>into${LINODE_CTL_PREFIX:-~/.local/bin}(rename the env var to match the vendor slug). Optionally install the Claude skill into~/.claude/skills/<slug>/. Re-attach stdin to/dev/ttyfor the optional immediate-setup prompt socurl … | shstill works.install.ps1(Windows) — Python check,.cmdshim onPATH,icacls-locked-down ACL for the file fallback if used.- Verify with
shellcheck install.shbefore commit.
Step 13 — Initial commit
One commit with the entire alpha. Subject form: feat: initial public alpha (v0.1.0-alpha.1). Body: 1-sentence summary + bullet list of every major surface (CLI commands, classifier tiers, storage backends, install scripts, skill, docs). Trailers:
Prompted-By: <operator name> <operator email> # from `git config user.name`/`user.email`
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]> # actual model id you are running as
Do NOT bypass hooks (--no-verify, --no-gpg-sign). Do NOT commit if the operator has not explicitly told you to — draft the message and stop.
Step 14 — Push and configure the GitHub repo
After the operator authorizes the push and the commit lands on origin/main, configure the GitHub repo. These settings are the alpha default; the operator can tighten them later (e.g. add branch protection) once the project has external contributors.
About panel (top of the repo page):
- Description — one sentence covering what the tool does and the safety pitch. Form: "
<vendor>-api-skill— a safe, single-file Python CLI mediating the<Vendor>API, plus a matching Claude skill. Credential never enters AI context; every mutation is classifier-gated and audit-logged." - Website — leave blank, or point to the canonical reference (
https://github.com/aditya-m-bharadwaj/linode-api-skill). - Topics — pick ~12 from:
claude-code,claude-skill,claude-agent-sdk,ai-safety,ai-agents,api-wrapper,cli,python,<vendor>(e.g.linode,porkbun),<vendor>-api,credential-management,audit-log,safety-classifier.
Features (Settings → General → Features):
| Feature | Default | Why |
|---|---|---|
| Issues | on | issue templates ship in .github/ISSUE_TEMPLATE/ |
| Discussions | on | discussion templates ship in .github/DISCUSSION_TEMPLATE/ |
| Wikis | on | enabled by default; the in-repo docs/ memory layer is canonical, but leaving wikis on costs nothing and gives external contributors a low-friction surface |
| Projects | on | enabled by default; same reasoning — no cost, optional surface for issue triage |
| Sponsorships | on | .github/FUNDING.yml is in place |
| Preserve this repository | on if eligible (Arctic Code Vault opt-in) | free, no downside |
Pull Requests (Settings → General → Pull Requests):
- Allow squash merging: on.
- Allow merge commits / rebase merging: off for a solo alpha.
- Always suggest updating PR branches: on.
- Allow auto-merge: on.
- Automatically delete head branches: on.
Code security (Settings → Code security):
- Private vulnerability reporting: enable — this is what
SECURITY.mdandISSUE_TEMPLATE/config.ymldirect reporters to. - Dependabot alerts: enable — catches
actions/*version bumps even though the CLI has no Python deps. - Dependabot security updates: enable.
- Secret scanning (free on public repos): enable.
- Push protection (blocks pushes containing detected secrets): enable.
- Code scanning (CodeQL): enable. The workflow ships at
.github/workflows/codeql.yml(Step 9) and analyzes the Python CLI and the workflow files themselves. Even on a stdlib-only single-file CLI, CodeQL catches path-traversal, command-injection, weak-crypto, and untrusted-input-into-action patterns that the classifier doesn't see. The weekly cron also re-scans against updated rule packs.
Branch protection (Settings → Branches):
- For a solo v0.x alpha: skip. The operator pushes directly to
mainper the established pattern. - Revisit once external contributors arrive: enable "Require a pull request before merging" + "Require status checks to pass" (CI green) on
main.
Pages / Webhooks / Actions secrets: leave as default. No docs site is published; no secrets are needed by CI.
Bootstrap the wiki. The wiki is a separate git repository (<repo>.wiki.git) that GitHub provisions only after a first page is saved through the web UI. You (the AI) cannot create this repo via gh or any other automated path — gh repo create <slug>.wiki fails with "The repository <slug>.wiki cannot end in .wiki" because GitHub reserves the .wiki suffix for auto-provisioned wiki repos. Cloning <slug>.wiki.git returns "Repository not found" until the operator has saved a page.
→ Stop here and ask the operator to bootstrap the wiki manually. Direct them to:
- Open
https://github.com/<owner>/<slug>/wikiin a browser. - Click "Create the first page" and save anything (the default "Welcome to the wiki!" body is fine — it will be overwritten in a moment).
- Confirm back to you that the page saved.
Only after the operator confirms can you proceed. Then clone the now-existing wiki repo, replay starter pages over GitHub's placeholder, and push:
# In the project root, AFTER the operator has saved the first wiki page:
git clone https://github.com/<owner>/<slug>.wiki.git wiki
echo 'wiki/' >> .gitignore # main repo never tracks the nested .git
cd wiki
# GitHub-provisioned wikis default to the `master` branch, not `main`.
# Don't fight it; commit on master so push succeeds without surgery.
# Author / copy in the starter pages (this overwrites GitHub's auto Home.md):
# ... write Home.md, _Sidebar.md, _Footer.md, Getting-Started.md, etc.
git add -A
git commit -m "wiki: initial seed (v0.1.0-alpha.1 surface)"
git push -u origin master
The minimum-viable starter page set (mirror the APIskillBuilderSkill wiki):
Home.md— landing page with the safety pitch in one paragraph + navigation._Sidebar.md— right-side nav (Concepts / Reference / Contribute / Links)._Footer.md— short repo / license footer.Getting-Started.md— install, prerequisites, first invocation.How-It-Works.md— conceptual overview of how the CLI + runtime skill relate.Hard-Rules.md— annotated version of the safety contract.Six-Tier-Safety-Classifier.md— tier table + classification logic.Build-Process.md— annotated build/use steps if relevant for downstream users.ADR-Index.md— one-line summaries linking to eachdocs/decisions/<NNNN>-*.mdfile.FAQ.md— open questions and deliberate non-goals.Roadmap.md— near / medium / long-term + explicitly out-of-scope items.Contributing-to-the-Wiki.md— clone-edit-push workflow + page conventions.
Page conventions: filenames are Page-Name.md at the wiki root (no subdirectories — GitHub wikis are flat); internal links use [[Page Name]]; links from wiki to the main repo use absolute https://github.com/<owner>/<slug>/blob/main/... URLs because the two repos are separate. Wiki pages summarize and link to canonical content in docs/; they do not replace it. When the wiki and docs/ disagree, docs/ wins.
Add a "Contributing to the wiki" section to the generated project's CONTRIBUTING.md describing the local workflow and the docs/ vs. wiki split — so a future contributor knows how to clone, edit, push, and where canonical content lives.
Run this step right after the first push lands. The default GitHub presets for a brand-new repo are not what the safety contract assumes — at minimum, private vulnerability reporting must be on (or SECURITY.md's instructions are a dead link), and the description / topics must be set so users discover the project at all.
After configuring, paste the live About-panel description and the comma-separated topic list back to the operator for verification.
Step 15 — Live smoke test (if a token is available)
If the operator provides a scoped test credential, exercise the alpha end-to-end before declaring v0.1 done:
- Install via the published
curl … | shone-liner against a sandbox prefix (LINODE_CTL_PREFIX=/tmp/...-style) so you don't pollute the operator's real install. <slug> gui-setupvia the OS dialog. Confirmwhoamiworks.- Inventory all existing resources and record them so you can verify nothing got touched.
- Exercise one workflow per tier:
read— list a resource type.mutating— a reversible change (e.g. toggle a setting).destructive— delete a test-tagged resource only.billable— create the cheapest possible resource, tagged for cleanup.financial/privilege—--dry-runonly, do not actually call.
- Verify the safety contract: try a billable call without
--i-understand-billing(expect refusal); try a destructive call with mismatched--confirm-id(expect refusal). - Clean up all test-tagged resources via the named cleanup command.
- Confirm pre-existing resources are untouched.
- Review the audit log — every mutation should appear, no secrets should appear.
Any defects surfaced by the smoke test are blockers for v0.1, not follow-up issues. Land the fixes (with tests and the corresponding CHANGELOG / SKILL.md / docs updates in the same commit) before tagging.
Safety guarantees the generated skill MUST provide
A reader looking at the generated repo for the first time should be able to verify the following by reading the code, with no external trust:
- The token is never in argv. Search
bin/<slug>for the token variable name — it should only appear in: storage read/write helpers, theAuthorizationheader construction, and the verify-before-store call. - The token is never in stdout / stderr / log files / audit entries. Search for the token variable name in
print,_emit,_audit,logger, etc. — should appear in none. - The OS-dialog stdout is captured into Python memory by
subprocess.run(..., capture_output=True)and never re-printed. The CLI prints success metadata (Authenticated as: <username>) and nothing else from that call. - Every mutation is guarded by an
if not args.yes: raise CtlError(...)check OR the genericapicommand's flag-check loop. There are no code paths that POST/PUT/PATCH/DELETE without classification + flag gating. - The audit log only records body keys for generic
apicalls — not values. Grep_audit(...)calls; the onlybody_keys=...shape is keys-only.
Things you should NOT do
- Do not import third-party Python packages. Stdlib only. Even
keyringis out — the CLI's storage layer is intentionally re-implemented against the OS-native CLIs (security,secret-tool,cmdkey). - Do not support an
LINODE_TOKEN-style environment variable as the primary credential path. The operator can opt-in via documented escape hatches, but the default is keystore-only. - Do not invent a "lighter" safety classifier with fewer tiers because the target API "seems mostly free". Even free APIs have privilege escalation (issuing scoped tokens), and the tier system is the operator's mental model — don't change it across vendors.
- Do not add a fancy interactive prompt for token entry beyond
setup(TTY) andgui-setup(OS dialog). No browser-based OAuth flows, no QR codes, noexpectscripts. The TTY/dialog out-of-band requirement is the contract. - Do not auto-classify unrecognized endpoints as
read. The default fallback for non-GET ismutating; for DELETE,destructive. Conservative is correct. - Do not publish to PyPI yet. The default install path is the one-liner
curl … | shfrom raw.githubusercontent.com, which can't smuggle in a dependency. If PyPI publishing is added later, switch the version string to PEP 440 (0.1.0a1instead of0.1.0-alpha.1). - Do not create the generated repo as a "monorepo" of multiple vendors. One vendor = one repo. The skill is independent per vendor; cross-vendor sharing happens at the doc level (this skill).
Reference implementation
https://github.com/aditya-m-bharadwaj/linode-api-skill is the canonical implementation. When in doubt, read the corresponding file there. Specifically:
| Concern | File |
|---|---|
| Safety classifier | bin/linode-api-skill lines ~620–740 |
| Token storage | bin/linode-api-skill _kc_* and _file_* helpers |
| GUI dialog | bin/linode-api-skill _has_display, _prompt_token_gui, _confirm_gui |
| Audit log | bin/linode-api-skill _audit |
| Verify-before-store | cmd_setup and cmd_gui_setup (call /profile before persisting) |
| Path validation | PATH_RE and _validate_path |
| Header / body hardening | _request (filters Authorization); _load_body (refuses paths under CONFIG_DIR) |
| Skill template | .claude/skills/linode-api-skill/SKILL.md |
| Memory layer | docs/ and .claude/commands/{resume,save}.md |
| CI | .github/workflows/ci.yml |
| Install scripts | install.sh, install.ps1 |
| Commit-trailer convention | CONTRIBUTING.md §"Commit message format" |
Open issues / things the build process does not yet automate
These are honest gaps you should surface to the operator rather than fake:
- Pricing introspection. This skill assumes you'll get the billable-endpoint list from a human or the vendor's pricing page. There's no automatic mapping from an OpenAPI spec to "this endpoint costs money".
- OAuth-flow APIs. The
setup/gui-setuppattern assumes a paste-once-and-store credential. For APIs requiring OAuth dance + refresh tokens, you'll need additional design (similar in spirit togh auth loginbut adapted). - Live smoke testing across all tiers. Step 14 prescribes the methodology but the actual recipe is per-vendor — you need to know which resource is cheapest, which can be safely deleted, etc.
- Generator tooling. This skill is markdown that guides an AI to build. There is no
api-skill-builder scaffold <slug> <spec.json>CLI. Building one is reasonable future work; for now, follow the steps by hand.