Discover API
rand/cc-polymath
Automatically discover API design skills when working with REST APIs, GraphQL schemas, API authentication, OAuth, JWT, rate limiting, API versioning, error handling, or endpoint design.
Stable consumer-facing API and interface design patterns. An agent skill from citypaul/.dotfiles.
$ npx skills add citypaul/.dotfiles --skill api-design -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install citypaul/.dotfiles api-design --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/citypaul/.dotfiles.git skills-src && mkdir -p .claude/skills && cp -r skills-src/claude/.claude/skills/api-design .claude/skills/api-design && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "api-design" agent skill from https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/api-design into .claude/skills/api-design/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-design", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/api-designType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add citypaul/.dotfiles --skill api-design -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install citypaul/.dotfiles api-design --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/citypaul/.dotfiles.git skills-src && mkdir -p .agents/skills && cp -r skills-src/claude/.claude/skills/api-design .agents/skills/api-design && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "api-design" agent skill from https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/api-design into .agents/skills/api-design/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-design", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add citypaul/.dotfiles --skill api-design -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install citypaul/.dotfiles api-design --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/citypaul/.dotfiles.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/claude/.claude/skills/api-design .cursor/skills/api-design && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "api-design" agent skill from https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/api-design into .cursor/skills/api-design/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-design", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/citypaul/.dotfiles.git --path claude/.claude/skills/api-design--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add citypaul/.dotfiles --skill api-design -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install citypaul/.dotfiles api-design --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/citypaul/.dotfiles.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/claude/.claude/skills/api-design .gemini/skills/api-design && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "api-design" agent skill from https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/api-design into .gemini/skills/api-design/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-design", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install citypaul/.dotfiles api-designInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add citypaul/.dotfiles --skill api-design -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/citypaul/.dotfiles.git skills-src && mkdir -p .github/skills && cp -r skills-src/claude/.claude/skills/api-design .github/skills/api-design && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "api-design" agent skill from https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/api-design into .github/skills/api-design/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-design", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add citypaul/.dotfiles --skill api-design -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install citypaul/.dotfiles api-design --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/citypaul/.dotfiles.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/claude/.claude/skills/api-design .opencode/skills/api-design && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "api-design" agent skill from https://github.com/citypaul/.dotfiles/tree/main/claude/.claude/skills/api-design into .opencode/skills/api-design/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-design", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
api-designStable consumer-facing API and interface design patterns. An agent skill from citypaul/.dotfiles.
API Design is an agent skill from citypaul/.dotfiles. Stable consumer-facing API and interface design patterns. Use when designing REST endpoints, cross-team boundaries, or any externally consumed or versioned service contract. Covers contract-first development, error semantics (RFC 9457), REST conventions, pagination, idempotency, rate limiting, and backward compatibility. For an in-process feature or module's coherent responsibility and interface depth, use codebase-design. For TypeScript type patterns and trust-boundary validation, see typescript-strict.
Its SKILL.md is about 6.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files (for example `resources/api-evolution.md`, `resources/api-security.md` and `resources/auth-security.md`).
It sits in Backend & APIs, covering API design, REST APIs and Type safety. It works with TypeScript. The licence is MIT.
Read from SKILL.md and the folder at commit cd4028d. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
API Design loads about 6.1k tokens when it runs. Until then it costs about 130 tokens; SKILL.md has 2,505 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from citypaul/.dotfiles at commit cd4028d, republished under its MIT licence (© citypaul). 2,505 words, ~6,126 tokens.
.claude/skills/api-design/SKILL.md (or your agent's skills folder). This skill also uses 7 other files; get the full folder from GitHub.Use this skill for consumer compatibility and protocol semantics. For an in-process module's responsibility, full caller burden, information hiding, and depth, load codebase-design; use both when an internal module also exposes a public or cross-team contract. Use evaluate-existing-solutions only when a material gateway, framework, SDK, provider, or protocol-implementation choice remains unresolved; API semantics and compatibility stay here.
For TypeScript type patterns (branded types, discriminated unions, schema-first), see the typescript-strict skill. For immutability patterns, see the functional skill. For testing API behavior, see the testing skill. For OAuth 2.0 or OpenID Connect, load the secure-oauth-oidc skill rather than treating authentication as an ordinary API-key decision. For browser-facing BFF entry points — public/protected access classification, session cookies, CSRF/Origin/Fetch Metadata policy, protected SSE/WebSocket registration, and endpoint-protection enforcement — load the bff-entry-points skill; error shape and REST semantics stay here. For the BFF pattern itself (adoption, granularity, aggregation, upstream identity), load bff-design — a single-consumer BFF deployed in lockstep with its frontend legitimately relaxes the versioning discipline this skill mandates for externally consumed contracts.
Supporting resources are in the resources/ directory. Load them on demand:
| Resource | Load when... |
|---|---|
problem-details.md | Implementing RFC 9457 error responses — member semantics, single-error and validation-error JSON examples, extension members, §5 security guidance |
api-evolution.md | Versioning strategies and deprecation patterns |
api-security.md | Securing the API boundary |
auth-security.md | JWT BCP security and routing to the dedicated OAuth/OIDC skill |
http-fundamentals.md | HTTP protocol fundamentals — caching directives, content negotiation, browser security, status codes, header design |
source-notes.md | Reviewing provenance, the immutable audit baseline, license scope, and local departures |
With a sufficient number of users of an API, all observable behaviors of your system will be depended on by somebody, regardless of what you promise in the contract.
Every public behavior — including undocumented quirks, error message text, timing, and ordering — becomes a de facto contract once users depend on it.
Deprecation/Sunset headers on responses that still carry it, and a line in the README or API docs naming the replacement. A supersession nobody recorded is an undocumented change — see resources/api-evolution.md for the header syntax and the deprecation checklist.Avoid forcing consumers to choose between multiple versions of the same dependency or API. Diamond dependency problems arise when different consumers need different versions of the same thing. Design for a world where only one version exists at a time — extend rather than fork.
Define the interface before implementing it. The contract is the spec — implementation follows.
type TaskAPI = {
readonly createTask: (input: CreateTaskInput) => Promise<Task>;
readonly listTasks: (params: ListTasksParams) => Promise<PaginatedResult<Task>>;
readonly getTask: (id: TaskId) => Promise<Task>;
readonly updateTask: (id: TaskId, input: UpdateTaskInput) => Promise<Task>;
readonly deleteTask: (id: TaskId) => Promise<void>;
};This aligns with TDD: define the contract (what you want), write tests against it, then implement.
Extend interfaces without breaking existing consumers.
This rule outranks the wording of the request. A request to rename, retype, narrow or remove something a shipped contract already publishes — a response field, a header, a status, a route — is a request for the new shape, not for the outage. Deliver the additive form: add the new name alongside the old, keep the old one working and carrying the same value, record the old one as superseded, and say in your reply that you added rather than replaced and what retiring the old name would take. Do not perform the break and note it afterwards, and do not stop to ask which was meant — the additive change delivers what was asked for, satisfies compatibility, and stays reversible if the requester did want the break.
Extend interfaces this way:
type CreateTaskInput = {
readonly title: string;
readonly description?: string;
readonly priority?: 'low' | 'medium' | 'high'; // Added later, optional
readonly labels?: ReadonlyArray<string>; // Added later, optional
};What breaks backward compatibility:
What preserves backward compatibility:
Pick one error strategy and use it everywhere. Don't mix patterns where some endpoints throw, others return null, and others return { error }.
Within one versioned API contract, use one documented error shape unless a protocol-specific endpoint requires another. Consistency matters more than which compatible format you choose.
For public APIs with external consumers, use RFC 9457 (Problem Details). It's the industry standard, machine-readable, and what third-party developers expect. Use application/problem+json as the Content-Type.
For internal APIs with a single frontend, a simpler consistent shape is a valid choice. The minimum viable error response needs: a machine-readable error code, an optional human-readable message, and the correct HTTP status code. This is less ceremony than RFC 9457 while still being consistent and actionable.
// Simpler shape — sufficient for internal APIs
type ApiError = {
readonly error: string; // Machine-readable code (UPPER_SNAKE_CASE)
readonly message?: string; // Human-readable description
readonly fieldErrors?: Record<string, string>; // For validation errors
};If you start with a simpler format, design it so it can evolve toward RFC 9457 later (e.g., error maps to title, message maps to detail). Don't paint yourself into a corner.
The standard format for machine-readable API errors for public APIs. Use application/problem+json as the Content-Type. Standard members: type (URI identifying the error type), title (stable, human-readable summary), status (must match the actual HTTP status), detail (occurrence-specific explanation), instance (optional occurrence URI). Extension members are allowed — clients must ignore extensions they don't recognize.
Errors should be actionable: the consumer should know what went wrong, why, and what to do about it. Error responses are not a debugging tool — never expose stack traces, internal paths, or implementation details.
Include a correlation identifier (the trace ID, or an opaque reference to it) as an extension member or via instance, so a user-reported error joins to its trace and canonical log event — see the observability skill. The trace ID reveals nothing internal; it is a lookup key, not a detail leak.
See resources/problem-details.md for full member semantics, single-error and validation-error JSON examples, extension member rules, when NOT to use Problem Details, and RFC 9457 §5 security guidance.
| Status | Meaning | When to use |
|---|---|---|
| 400 | Bad Request | Client sent malformed data |
| 401 | Unauthorized | Not authenticated |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate, version mismatch |
| 422 | Unprocessable Content | Validation failed (semantically invalid) |
| 429 | Too Many Requests | Rate limit exceeded; include Retry-After when a meaningful retry time is known |
| 500 | Internal Server Error | Server error (never expose internal details) |
Validate untrusted representation and endpoint-schema input where it enters the
system, then pass the derived type through internal code. This does not replace
domain smart constructors or transition checks: invariant enforcement remains
with the model that owns the value. See typescript-strict and
domain-driven-design.
Return 400 when the representation itself cannot be parsed (for example malformed JSON). Once parsing succeeds, return 422 when the value fails the endpoint schema or business validation. Pick and document a different house mapping only when every example, error translator, and consumer uses it consistently.
app.post('/api/tasks', async (req, res) => {
const result = CreateTaskSchema.safeParse(req.body);
if (!result.success) {
return res.status(422).json({
type: 'https://api.example.com/problems/validation-error',
title: 'Validation Error',
status: 422,
detail: 'Invalid task data',
errors: result.error.flatten(),
});
}
const task = await taskService.create(result.data);
return res.status(201).json(task);
});Third-party API responses are untrusted data — always validate their shape and content before use.
Network failures happen. Clients retry. Without idempotency, retries create duplicate charges, duplicate orders, duplicate records.
| Method | Safe | Idempotent | Notes |
|---|---|---|---|
| GET | Yes | Yes | Read-only requested semantics; incidental logging/metrics are allowed |
| PUT | No | Yes | Same request has the same intended effect; response status/body may differ |
| DELETE | No | Yes | Deleting twice = same outcome |
| POST | No | No | Needs explicit idempotency handling |
| PATCH | No | Not guaranteed | Depends on implementation |
For non-idempotent operations (especially those involving money, orders, or state changes), use client-provided idempotency keys:
app.post('/api/payments', async (req, res) => {
const rawIdempotencyKey = req.headers['idempotency-key'];
const idempotencyKey =
typeof rawIdempotencyKey === 'string' &&
/^[\x21-\x7e]{1,128}$/.test(rawIdempotencyKey)
? rawIdempotencyKey
: undefined;
if (!idempotencyKey) {
return res.status(400).json({
type: 'https://api.example.com/problems/invalid-idempotency-key',
title: 'Invalid Idempotency Key',
status: 400,
detail: 'POST /api/payments requires one visible-ASCII Idempotency-Key of at most 128 characters',
});
}
const result = CreatePaymentSchema.safeParse(req.body);
if (!result.success) {
return res.status(422).json(toValidationProblem(result.error));
}
const scope = req.user.id;
const fingerprint = stableHash(result.data);
const claim = await idempotencyStore.claim({
scope,
key: idempotencyKey,
fingerprint,
});
if (claim.status === 'parameters-mismatch') {
return res.status(409).json(toProblem('IDEMPOTENCY_PARAMETERS_MISMATCH'));
}
if (claim.status === 'completed') {
return res.status(claim.response.status).json(claim.response.body);
}
if (claim.status === 'in-progress') {
res.setHeader('Retry-After', '1');
return res.status(409).json(toProblem('IDEMPOTENCY_REQUEST_IN_PROGRESS'));
}
// createOnce durably owns operationId + fingerprint beyond response-cache
// expiry. For an external provider it also persists/reuses the provider's
// payment/intent ID, so recovery never depends on a time-limited request key.
const payment = await paymentService.createOnce({
operationId: claim.operationId,
input: result.data,
});
await idempotencyStore.complete(claim.id, { status: 201, body: payment });
return res.status(201).json(payment);
});Design principles:
DELETE must have an idempotent effect: repeating it does not delete anything
else or create a second side effect. The repeated response may remain 204,
or it may be 404 when absence is meaningful to clients. Choose and document
one contract:
app.delete('/api/tasks/:id', async (req, res) => {
const deleted = await taskService.delete(req.params.id);
// This API deliberately treats already-absent as success.
return res.status(204).send();
});When an API exposes a quota policy, communicate the applicable policy and remaining state consistently on responses where that information is useful to clients. Do not invent quota headers for endpoints without such a policy.
The IETF standardization effort is draft-ietf-httpapi-ratelimit-headers (version 11, May 2026 — still an active working group draft). Current drafts define two structured fields:
RateLimit-Policy: "hour";q=1000;w=3600 # Policy: quota of 1000 per 3600s window
RateLimit: "hour";r=742;t=60 # Current state: 742 remaining, resets in 60sEarlier drafts used a triplet — RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset — and many shipped APIs still use that triplet or the unstandardized X-RateLimit-* family. Expect any of these when consuming APIs. For new APIs, prefer the current draft fields; whichever names you choose, document them — header names are part of your contract, and the draft may still change before becoming an RFC.
On 429 responses, include Retry-After when the server can give a meaningful
retry time. It is a stable, standard HTTP header, but HTTP permits a 429
response without it:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Policy: "hour";q=1000;w=3600
RateLimit: "hour";r=0;t=30
Content-Type: application/problem+json
{
"type": "https://api.example.com/problems/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "You have exceeded 1000 requests per hour. Retry after 30 seconds."
}Assign explicit freshness lifetimes on responses. Don't rely on heuristic freshness.
Practical rules:
Cache-Control: max-age=N over Expires — even short freshness (e.g., max-age=5) enables reuse across multiple clientsVary on ALL responses from that resource (including the default)no-store for responses containing sensitive data — no-cache does NOT mean "don't cache" (it means "stored but revalidate before use")See resources/http-fundamentals.md for the full Cache-Control directive table plus content negotiation, header design, and protocol version independence.
| Pattern | Convention | Example |
|---|---|---|
| Endpoints | Plural nouns, no verbs | GET /api/tasks, POST /api/tasks |
| Query params | camelCase | ?sortBy=createdAt&pageSize=20 |
| Response fields | camelCase | { createdAt, updatedAt, taskId } |
| Boolean fields | is/has/can prefix | isComplete, hasAttachments |
| Enum values | UPPER_SNAKE | "IN_PROGRESS", "COMPLETED" |
| Headers | No X- prefix (RFC 6648/BCP 178) | Example-Request-Id |
GET /api/tasks → List tasks (with query params for filtering)
POST /api/tasks → Create a task
GET /api/tasks/:id → Get a single task
PATCH /api/tasks/:id → Update a task (partial)
DELETE /api/tasks/:id → Delete a task
GET /api/tasks/:id/comments → List comments for a task (sub-resource)
POST /api/tasks/:id/comments → Add a comment to a taskUse PATCH for partial updates (only provided fields change). Use PUT only when the client sends the complete object.
Paginate list endpoints whose result can grow beyond a bounded, safe response. Small closed enumerations may return the complete set when that bound is part of the contract:
// Request
// GET /api/tasks?page=1&pageSize=20&sortBy=createdAt&sortOrder=desc
// Response shape
type PaginatedResult<T> = {
readonly data: ReadonlyArray<T>;
readonly pagination: {
readonly page: number;
readonly pageSize: number;
readonly totalItems: number;
readonly totalPages: number;
};
};Use query parameters for filters:
GET /api/tasks?status=in_progress&assignee=user123&createdAfter=2025-01-01Separate what the caller provides from what the system returns:
// Input: what the caller provides
type CreateTaskInput = {
readonly title: string;
readonly description?: string;
};
// Output: includes server-generated fields
type Task = {
readonly id: TaskId;
readonly title: string;
readonly description: string | null;
readonly createdAt: Date;
readonly updatedAt: Date;
readonly createdBy: UserId;
};| Rationalization | Reality |
|---|---|
| "We'll document the API later" | The types ARE the documentation. Define them first. |
| "We don't need a bound for this growing list" | Define pagination or another documented safe bound before the result can grow beyond one response. Closed, contractually bounded lists do not need ceremonial pagination. |
| "PATCH is complicated, let's just use PUT" | PUT requires the full object every time. PATCH is what clients actually want. |
| "We'll version the API when we need to" | Breaking changes without versioning break consumers. Design for extension from the start. |
| "They asked for the rename, so the break is authorised" | A request for a clearer name is a request for the name, not for the breakage. Add the new name, keep the old one working, record it as superseded, and explain that choice in the reply — don't ship the break, and don't stall the work asking which was meant. |
| "Nobody uses that undocumented behavior" | Hyrum's Law: if it's observable, somebody depends on it. |
| "Internal APIs don't need contracts" | Internal consumers are still consumers. Contracts prevent coupling and enable parallel work. |
| "Retries are the client's problem" | Without idempotency, retries create duplicates. Design for at-least-once delivery. |
| "We'll add an abuse control after this expensive public operation is attacked" | Protect unauthenticated, costly, or abuse-prone operations from the start. Publish quota headers only when a client-visible quota is actually part of the contract. |
| "Error messages are just for debugging" | Errors are part of your API's developer experience. Make them actionable, not diagnostic. |
/api/createTask, /api/getUsers)X- prefixed headers (deprecated by RFC 6648)After designing an API:
application/problem+json for RFC 9457 responses, application/json for simpler formatsCache-Control, ETags for revalidation, Vary where needed)This skill adapts Addy Osmani's MIT-licensed api-and-interface-design skill. Local history records the adaptation but not the original upstream import revision. See resources/source-notes.md for the immutable audit baseline (which is not an import-revision claim), retained ideas, and local departures; see LICENSE for the applicable upstream notice.
© citypaul, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 7 other files in claude/.claude/skills/api-design of citypaul/.dotfiles.
Open the folder on GitHubat commit cd4028d
API Design next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| API Design this skillcitypaul/.dotfiles | 739 | — | ~6.1k | Automated safety check: Pass | MIT | |
| Discover APIrand/cc-polymath | 181 | 1 repos | ~1.5k | Automated safety check: Pass | MIT | |
| API DesignWrongStack/WrongStack | 370 | — | ~1.3k | Automated safety check: Pass | MIT | |
| API DesignProgrammerAnthony/Expert-Coding-Harness | 235 | 8 repos | ~3.3k | Automated safety check: Pass | MIT | |
| Convexopenclaw/clawhub | 9.5k | — | ~2.4k | Automated safety check: Pass | MIT | |
| API Architectcuriositech/some_claude_skills | 243 | 1 repos | ~1.4k | Automated safety check: Pass | MIT |
rand/cc-polymath
Automatically discover API design skills when working with REST APIs, GraphQL schemas, API authentication, OAuth, JWT, rate limiting, API versioning, error handling, or endpoint design.
WrongStack/WrongStack
A skill your agent uses when designing, implementing, or reviewing an HTTP API — endpoints, request and response shapes, errors, pagination, versioning, and authorization.
ProgrammerAnthony/Expert-Coding-Harness
REST API design patterns including resource naming, status codes, pagination, filtering, error responses, versioning, and rate limiting for production APIs.
openclaw/clawhub
Convex is the backend agents get right on the first try: an all-TypeScript reactive platform where the database, server functions, scheduling, file storage, auth, and realtime sync are one type-safe…
curiositech/some_claude_skills
Expert API designer for REST, GraphQL, gRPC architectures. An agent skill from curiositech/some_claude_skills.
aiskillstore/marketplace
Quick reference for RESTful API design patterns, HTTP semantics, caching, and rate limiting.
citypaul/.dotfiles
Discover and, with authorization, install agent skills from the open skills ecosystem.
citypaul/.dotfiles
Render the shape of code — module boundaries, the types that cross them, signatures, and a cited call graph — for code that already exists or a change about to be built.
citypaul/.dotfiles
Design, audit, and evolve physical source and package structures that expose real architectural boundaries while keeping related behavior together.
citypaul/.dotfiles
Review test quality using Dave Farley's eight properties of good tests.
citypaul/.dotfiles
A skill your agent uses when modifying existing code that lacks tests and you need to document its actual current behavior before making changes -- the legacy code dilemma where you need tests to…
citypaul/.dotfiles
Systematic CI/CD failure diagnosis using hypothesis-first investigation, local reproduction, and environment delta analysis.
Works with
Categories
Stable consumer-facing API and interface design patterns. An agent skill from citypaul/.dotfiles. dotfiles. Stable consumer-facing API and interface design patterns.
API Design fits situations like: designing REST endpoints; cross-team boundaries; any externally consumed; versioned service contract.
Run `npx skills add citypaul/.dotfiles --skill api-design -a claude-code`. Or copy the skill folder (claude/.claude/skills/api-design in citypaul/.dotfiles) into .claude/skills/api-design in your project. Claude Code loads it when a task matches its description.
Run `npx skills add citypaul/.dotfiles --skill api-design -a codex`. Or copy the skill folder (claude/.claude/skills/api-design in citypaul/.dotfiles) into .agents/skills/api-design in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add citypaul/.dotfiles --skill api-design -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/api-design, .gemini/skills/api-design, .github/skills/api-design and .opencode/skills/api-design in your project.
SKILL.md names no scripts, command-line tools or credentials: API Design is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
API Design is published under the MIT licence (from the LICENSE file in the skill folder). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.1k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with API Design: Discover API (rand/cc-polymath, 181 stars), API Design (WrongStack/WrongStack, 370 stars), API Design (ProgrammerAnthony/Expert-Coding-Harness, 235 stars) and Convex (openclaw/clawhub, 9.5k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
citypaul (a GitHub user) maintains it in citypaul/.dotfiles, which has 739 GitHub stars. The repository holds 44 skills in this directory. The repository was last updated on October 2, 2026.
Source: citypaul/.dotfiles on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.