api-bind
Skill2 starsChanged 8 months agoUnlicenseView on GitHub
Generate typed API client + query hook from OpenAPI spec or Protobuf (.proto) file. Requires framework parameter [react|vue]. Output: types + client function + TanStack Query hook. Do not use without an OpenAPI spec file or .proto file.
- Reads credentials
In this repository70 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/00-project-context.mdcCursor rule
- .cursor/rules/01b-component-gen-next.mdcCursor rule
- .cursor/rules/01-component-gen.mdcCursor rule
- .cursor/rules/02-component-tests.mdcCursor rule
- .cursor/rules/03b-vue-doctor.mdcCursor rule
- .cursor/rules/03-react-doctor.mdcCursor rule
- .cursor/rules/04-ui-tweak.mdcCursor rule
- .cursor/rules/05-refactor.mdcCursor rule
- .cursor/rules/06-frontend-code-review.mdcCursor rule
- .cursor/rules/07-fe-repo-scout.mdcCursor rule
- .cursor/rules/08-be-repo-scout.mdcCursor rule
- .cursor/rules/09-web-vitals.mdcCursor rule
- .cursor/rules/10-browser-check.mdcCursor rule
- .cursor/rules/11-api-bind.mdcCursor rule
- .cursor/rules/12-e2e-tests.mdcCursor rule
- .cursor/rules/13-api-mocks.mdcCursor rule
- agents-checkerSkill
- api-bindSkill
- api-mocksSkill
- be-repo-scoutSkill
- browser-checkSkill
- component-gen-nextSkill
- component-genSkill
- component-testsSkill
- curate-lessonsSkill
- e2e-testsSkill
- fe-repo-scoutSkill
- fix-markdownSkill
- frontend-code-reviewSkill
- init-agentSkill
- init-projectSkill
- init-skillSkill
- prSkill
- react-doctorSkill
- refactorSkill
- setup-configsSkill
- skill-auditSkill
- spec-auditSkill
- ui-tweakSkill
- update-ai-setupSkill
- vue-doctorSkill
- web-vitalsSkill
- agents-checkerSkill
- api-mocksSkill
- be-repo-scoutSkill
- browser-checkSkill
- component-gen-nextSkill
- component-genSkill
- component-testsSkill
- curate-lessonsSkill
- e2e-testsSkill
- fe-repo-scoutSkill
- fix-markdownSkill
- frontend-code-reviewSkill
- init-agentSkill
- init-projectSkill
- init-skillSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 14
Before execution the agent MUST load: .claude/protocols/gardener.md
- Distinctive: line 54
No spec provided (OpenAPI or proto)
- Very specific: line 75
If the endpoint has path params, query params, or a request body — the client function MUST accept a typed params object.
- Very specific: line 104
Use discovered base URL pattern and auth header conventions in generated client.
- Very specific: line 256
Gardener Protocol: Call .claude/protocols/gardener.md before SKILL COMPLETE.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SYSTEM REQUIREMENTS
Before execution the agent MUST load: .claude/protocols/gardener.md
API Bind — OpenAPI / Protobuf → Types + Client + Hook
<purpose>
Given an OpenAPI specification (URL or local file) or a Protobuf (.proto) file, generates:
1. TypeScript types (request/response)
2. Typed client function (fetch for OpenAPI, Connect for proto)
3. TanStack Query hook (react-query or vue-query)
The hook is ready to drop into a component with all 4 states.
For proto input, uses `@connectrpc/connect-web` (Connect protocol) by default.
</purpose>Phase Checkpoints
STOP if: framework param missing or not react/vue | no spec provided | spec file not found | .proto file has no service block
WARN if: .claude/conventions/api-layer.md stub unfilled (no VITE_API_BASE_URL / VITE_GRPC_BASE_URL defined)
INFORM: framework=[react|vue], source=[openapi|proto], endpoint=[METHOD /path | RPC name], output-path=[resolved path]Input Validation (MANDATORY)
Usage: /api-bind [react|vue] [spec-path-or-url] [endpoint-or-rpc]
Example: /api-bind react ./openapi.json GET /users
/api-bind vue ./swagger.yaml POST /orders
/api-bind react ./proto/user.proto UserService.GetUser
/api-bind vue ./proto/order.proto OrderService.ListOrders --transport=grpc-webAuto-detect format by file extension: .json/.yaml/.yml → OpenAPI, .proto → Protobuf.
Optional flags: --transport=connect (default) | --transport=grpc-web | --transport=rest
BLOCKER if:
- Framework not
reactorvue - No spec provided (OpenAPI or proto)
- Spec file does not exist (check with Glob)
- Proto file has no
serviceblock
Protocol
BANNED
- Raw
fetchin component body — FORBIDDEN (use hook) axioswithout type generation — use HeyAPI or typed fetch: anyfor request/response types — FORBIDDEN- Catching errors silently — errors MUST propagate to query state
- Hardcoded base URLs — use env var
import.meta.env.VITE_API_BASE_URL(OpenAPI) orVITE_GRPC_BASE_URL(proto) - Hardcoded gRPC URL — FORBIDDEN, use
import.meta.env.VITE_GRPC_BASE_URL - Raw
grpc-webcalls without typed stubs — use Connect client with typed service definition
MANDATORY
- OpenAPI:
@hey-api/openapi-tsis used ONLY to extract TypeScript interfaces into{feature}Types.ts. The fetch client{feature}Api.tsMUST be written manually per the reference templates. - Proto: Types are parsed from proto
messageblocks (no openapi-ts). Enums useas constobject pattern. Type mapping fromreferences/proto-grpc.md. - Assume
import.meta.env.VITE_API_BASE_URL(OpenAPI) orVITE_GRPC_BASE_URL(proto) exists. NEVER create or modify.envfiles unless explicitly instructed. - If the endpoint has path params, query params, or a request body — the client function MUST accept a typed params object. The hook MUST include params in
queryKeyand pass them to the client function.
Hook Routing
OpenAPI — Map HTTP method to TanStack Query hook type
| HTTP Method | Hook | Notes |
| GET | useQuery | see references/react-query.md or vue-query.md |
| POST | PUT | PATCH | DELETE | useMutation | with queryClient.invalidateQueries on success |
Proto — Map RPC pattern to TanStack Query hook type
| RPC Pattern | Hook | Notes |
Get* / List* / Fetch* / Search* (unary) | useQuery | Read operations |
Create* / Update* / Delete* / Set* / Remove* (unary) | useMutation | Write operations |
| Server streaming RPC | useServerStream | Custom hook — see references/proto-grpc.md |
| Client streaming / Bidi streaming | WARN | Not supported in browser — emit warning and skip |
Workflow
Validate — framework param + spec file exists. Apply Phase Checkpoints above. 1a. Pre-Load Context — read API layer conventions before generating:
cat .claude/conventions/api-layer.md 2>/dev/null || trueUse discovered base URL pattern and auth header conventions in generated client. 1b. Detect format — auto-detect by file extension:
.json/.yaml/.yml→ OpenAPI (step 2),.proto→ Protobuf (step 2p).
OpenAPI Branch
- Parse spec — read OpenAPI JSON/YAML, extract endpoint schema (request/response)
- Generate types —
{Feature}Types.tswith request and response interfaces - Generate client —
{feature}Api.tstyped fetch function - Generate hook —
use{Feature}.tsTanStack Query hook for the framework
Proto Branch
2p. Parse proto — read .proto file, extract service block + message definitions. STOP if no service found.
3p. Generate types — {Feature}Types.ts from message blocks using type mapping from references/proto-grpc.md. Enums → as const objects. oneof → discriminated unions. Nested messages → separate interfaces.
4p. Generate client — {feature}Api.ts with Connect transport setup + typed client functions. Use --transport flag to select transport (default: connect).
5p. Generate hook — use{Feature}.ts TanStack Query hook. Unary RPCs → useQuery/useMutation per Hook Routing table. Server streaming → useServerStream custom hook.
Common
- Type check —
npx tsc --noEmit - Gardener → SKILL COMPLETE
Output Structure
src/{layer}/{feature}/api/
├── {feature}Api.ts # Typed fetch (OpenAPI) or Connect client (proto) function
├── {feature}Types.ts # Request/response TypeScript types
└── use{Feature}.ts # TanStack Query hookGenerated Hook Template (React)
// useUsers.ts
import { useQuery } from '@tanstack/react-query';
import { getUsers } from './usersApi';
import type { User, UsersParams } from './usersTypes';
export function useUsers(params?: UsersParams) {
return useQuery<User[], Error>({
queryKey: ['users', params],
queryFn: () => getUsers(params),
staleTime: 5 * 60 * 1000,
});
}Generated Hook Template (Vue)
// useUsers.ts
import { useQuery } from '@tanstack/vue-query';
import { computed, unref, type MaybeRef } from 'vue';
import { getUsers } from './usersApi';
import type { User, UsersParams } from './usersTypes';
export function useUsers(params?: MaybeRef<UsersParams>) {
return useQuery<User[], Error>({
queryKey: computed(() => ['users', unref(params)]),
queryFn: () => getUsers(unref(params)),
staleTime: 5 * 60 * 1000,
});
}Generated Hook Template — Proto Unary (React)
// useUser.ts (proto + Connect)
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { getUser, createUser } from './userApi';
import type { CreateUserRequest } from './userTypes';
const userKeys = {
all: ['users'] as const,
details: () => [...userKeys.all, 'detail'] as const,
detail: (id: string) => [...userKeys.details(), id] as const,
};
export function useUser(userId: string) {
return useQuery({
queryKey: userKeys.detail(userId),
queryFn: () => getUser(userId),
enabled: Boolean(userId),
});
}
export function useCreateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateUserRequest) => createUser(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: userKeys.all });
},
});
}Generated Hook Template — Proto Unary (Vue)
// useUser.ts (proto + Connect)
import { useQuery, useMutation, useQueryClient } from '@tanstack/vue-query';
import { computed, unref, type MaybeRef } from 'vue';
import { getUser, createUser } from './userApi';
import type { CreateUserRequest } from './userTypes';
const userKeys = {
all: ['users'] as const,
details: () => [...userKeys.all, 'detail'] as const,
detail: (id: string) => [...userKeys.details(), id] as const,
};
export function useUser(userId: MaybeRef<string>) {
return useQuery({
queryKey: computed(() => userKeys.detail(unref(userId))),
queryFn: () => getUser(unref(userId)),
enabled: computed(() => Boolean(unref(userId))),
});
}
export function useCreateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateUserRequest) => createUser(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: userKeys.all });
},
});
}References
- React hook patterns:
references/react-query.md - Vue hook patterns:
references/vue-query.md - Proto/gRPC patterns:
references/proto-grpc.md
Quality Gate
- Framework param validated (
react/vue) - Spec file found and parsed (OpenAPI or proto)
- Types file generated with no
: any - Client function uses
import.meta.env.VITE_API_BASE_URL(OpenAPI) orVITE_GRPC_BASE_URL(proto) - Hook uses correct TanStack Query hook for HTTP method (OpenAPI) or RPC pattern (proto)
tsc --noEmitPASS- (Proto) Service block extracted from
.protofile - (Proto) All
messagetypes mapped to TypeScript interfaces - (Proto) Enums use
as constobject pattern - (Proto) Connect transport configured with env var
Gardener Protocol: Call .claude/protocols/gardener.md before SKILL COMPLETE.
Completion Contract
✅ SKILL COMPLETE: /api-bind
├─ Framework: [react | vue]
├─ Source: [openapi | proto]
├─ Transport: [fetch | connect | grpc-web]
├─ Artifacts: [{feature}Types.ts, {feature}Api.ts, use{Feature}.ts]
├─ Endpoint: [METHOD /path | ServiceName.RpcName]
├─ Type Check: [PASS | FAIL]
└─ Coverage: [types + client + hook]Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

