From agent-toolkit
Read a cached OpenAPI / Swagger spec under a cache-first policy and emit a `fetch` or `axios` call snippet (TypeScript) for one endpoint. Auto-trigger when the user supplies an OpenAPI spec URL, a 16-hex cache key, or a `host:env:spec` registry handle (configured in `agent-toolkit.json`) together with phrases like "이 endpoint 호출 코드 만들어줘" / "axios 로 작성해줘" / "fetch snippet 줘" / "POST /pets 호출 코드 / acme:dev:users 의 …".
How this skill is triggered — by the user, by Claude, or both
Slash command
/agent-toolkit:openapi-clientThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
* Locate a single endpoint inside a cached OpenAPI / Swagger JSON spec and emit a TypeScript call snippet using either `fetch` (default) or `axios`, with path / query / body parameters and a response type when the spec defines one.
fetch (default) or axios, with path / query / body parameters and a response type when the spec defines one.agent (you)
├── 0. openapi_envs ← list registered host:env:spec handles (no remote call)
├── 1. openapi_status ← cache metadata only (no remote call)
├── 2. openapi_get ← cache hit → spec / miss → GET URL + JSON-validate + cache write (one shot)
├── 3. openapi_search ← search across cached specs (optionally scoped) to locate the endpoint
└── 4. openapi_refresh ← only when the user explicitly asks for "최신화" / refresh
The cache is a thin TTL layer in front of the spec URL. openapi_get already handles cache miss by downloading the spec, validating its shape (openapi 3.x or swagger 2.x), and persisting it — no separate write step is needed. JSON-only in this version: YAML specs throw, document the limitation when the user hits it.
openapi_get / openapi_status / openapi_refresh accept any of:
https://… or file://…) — direct download source.openapi_status / openapi_search. Resolves via cache metadata; when the metadata is gone, the tool throws with a clear "no recoverable spec URL" message.host:env:spec handle — symbolic name registered in agent-toolkit.json (./.opencode/agent-toolkit.json overrides ~/.config/opencode/agent-toolkit/agent-toolkit.json). Resolves to a spec URL via the registry. Unregistered handles throw.openapi_search accepts an optional scope:
host — search inside every spec under one hosthost:env — search inside one environmenthost:env:spec — search inside one specUse openapi_envs first when the user does not name a specific handle but talks about "이 환경 / 그 spec".
openapi_get / openapi_refresh / openapi_status / openapi_search / openapi_envs. No direct fetch, Read, or Bash to download the spec yourself.openapi_status when the input (URL / key / handle) is given.exists=true && expired=false, use openapi_get (it returns instantly from cache) and openapi_search to locate the endpoint.openapi_get once — it hits the remote on cache miss automatically.openapi_refresh only when the user explicitly asks to re-download.host:env:spec handles when the user works with multiple environments. Resolve the user's environment / service intent by calling openapi_envs once, presenting the matching handles, and asking which one when ambiguous. Pass the handle as-is to the openapi_* tools — never expand it to a URL yourself.openapi_search scope when the user has multiple environments cached. A scope of acme:dev keeps results inside that environment. When the user does not name an environment, leave scope off and search across everything.Given an ambiguous request ("POST /pets 호출 코드 만들어줘"):
host:env:spec handle, run openapi_get for that input, then look up the endpoint by (method, path) in spec.paths.openapi_envs once, identify the matching specs under that scope, and run openapi_search with scope: "acme:dev". When multiple candidates remain, surface them (specTitle + method path + summary) and ask the user which one.openapi_search (no scope) with the path and/or operationId substring across every cached spec. When multiple matches come back, surface the candidates and ask the user which one — including the specTitle so the environment / service is clear.// <method> <path> — <summary if present>
// spec: <specTitle> @ <specUrl>
type <PascalCaseOperationId>Response = /* response shape from spec, or `unknown` if not declared */;
export async function <camelCaseOperationId>(
// path params, then query, then body — only ones the spec declares
): Promise<<PascalCaseOperationId>Response> {
const url = `${BASE_URL}<path with ${pathParam} substitutions>`;
const res = await fetch(url, {
method: "<METHOD>",
headers: { "content-type": "application/json", accept: "application/json" },
body: /* JSON.stringify(body) when there is a body, else undefined */,
});
if (!res.ok) {
throw new Error(`<operationId> failed: ${res.status} ${res.statusText}`);
}
return res.json() as Promise<<PascalCaseOperationId>Response>;
}
// Example
// const u = await <camelCaseOperationId>(/* … */);
// <method> <path> — <summary if present>
// spec: <specTitle> @ <specUrl>
import axios from "axios";
type <PascalCaseOperationId>Response = /* … */;
export async function <camelCaseOperationId>(
// path params, then query, then body
): Promise<<PascalCaseOperationId>Response> {
const { data } = await axios.<method-lowercase>(
`${BASE_URL}<path>`,
/* body OR config — depends on method */,
);
return data as <PascalCaseOperationId>Response;
}
operationId to derive both the function name (camelCase) and response type (PascalCase). When operationId is absent, fall back to <method>_<path-slug> and call this out in one sentence.query?: { … } arg with optional fields by default; required ones explicitly typed as required.body: <type> arg when the operation declares a body; type pulled from requestBody.content["application/json"].schema if present, else unknown.2xx response's application/json schema. When the spec does not declare it, type as unknown and say so in one inline comment.BASE_URL is a placeholder constant; do not bake a hostname into the snippet.openapi_* tools — that defeats the cache and skips the shape validation.unknown and surface the gap in one inline comment.openapi_get rejects with a non-JSON body, tell the user the spec is YAML and that this skill is JSON-only in MVP.acme:dev, acme:staging, …). Ask which one before running openapi_get.openapi_envs, surface the available handles and ask the user to pick — do not guess "this looks like dev so I'll try acme:dev".openapi_get throws on timeout / network error / non-JSON body / missing openapi / swagger field → surface the error in one sentence and ask the user to verify the spec URL and AGENT_TOOLKIT_OPENAPI_DOWNLOAD_TIMEOUT_MS.openapi_get / openapi_status throws when a host:env:spec handle is unregistered → ask the user to add it under openapi.registry in agent-toolkit.json, or quote the available handles from openapi_envs.openapi_search throws on a scope that matches no entries (typo in host / host:env) → quote the scope and the available handles from openapi_envs, ask the user to correct it.openapi_search returns 0 matches with a valid scope → quote the query and ask which spec / path, do not hallucinate.operationId / response schema → emit the snippet with the documented fallback (path-slug name, unknown response) and call out the gap in one inline comment.npx claudepluginhub minjun0219/agent-toolkitGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.