From harness-claude
Advises on REST, GraphQL, gRPC API design. Produces OpenAPI specs, GraphQL schemas, proto definitions with versioning strategies and consistency validation. Use for new endpoints in Express, Fastify, NestJS, Hono.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Advisory guide for REST, GraphQL, and gRPC API design. Produces OpenAPI specs, GraphQL schemas, or proto definitions with versioning strategies and consistency validation.
Provides decision trees, patterns, and guidance for REST, gRPC, GraphQL API design including resource naming, schema, versioning, pagination, rate limiting, auth, and OpenAPI.
Designs REST and GraphQL APIs including endpoint design, authentication, versioning, documentation, and best practices. Use for backend API creation, contracts, or third-party integrations.
Share bugs, ideas, or general feedback.
Advisory guide for REST, GraphQL, and gRPC API design. Produces OpenAPI specs, GraphQL schemas, or proto definitions with versioning strategies and consistency validation.
Detect the API style. Scan the project for stack signals. WHERE openapi.* or swagger.* files exist, THEN classify as REST. WHERE *.graphql or schema.graphql exists, THEN classify as GraphQL. WHERE *.proto files exist, THEN classify as gRPC. If the --style argument is provided, use that instead of auto-detection.
Map existing endpoints. For REST projects, scan route files (src/**/routes/**, src/**/controllers/**) and extract HTTP method, path, request body, and response shape. For GraphQL, parse schema.graphql or code-first schema definitions. For gRPC, parse .proto files for service and rpc definitions.
Identify the framework. Detect Express (app.get, router.post), Fastify (fastify.route), NestJS (@Controller, @Get), Hono (app.get), Apollo (typeDefs, resolvers), or gRPC libraries (@grpc/grpc-js, grpc-node). Framework detection drives phase 2 recommendations.
Catalog existing conventions. Record naming patterns (camelCase vs kebab-case paths), response envelope structure (e.g., { data, error, meta }), pagination style (cursor vs offset), and error format (RFC 7807, custom). These become the baseline that new endpoints must follow.
Check for an existing OpenAPI spec. If openapi.yaml or openapi.json exists, parse it and compare against the actual route definitions. Flag any drift where the spec does not match the implementation.
Define resource models. For each new resource, produce a schema with required fields, types, nullable markers, and validation constraints. Use JSON Schema for REST, GraphQL type definitions for GraphQL, or message definitions for gRPC.
Design endpoint signatures. For REST: define method, path, path parameters, query parameters, request body schema, and response schema. Follow the conventions cataloged in phase 1. For GraphQL: define queries, mutations, and input types. For gRPC: define service RPCs with request and response messages.
Apply versioning strategy. WHERE a versioning strategy is already in use, THEN follow it. WHERE no strategy exists, THEN recommend URL-path versioning (/v1/resources) for REST, schema evolution with @deprecated for GraphQL, or package versioning for gRPC. Document the strategy for future endpoints.
Design error responses. For REST: use RFC 7807 Problem Details unless the project already uses a different format. Include type, title, status, detail, and instance. For GraphQL: use the errors array with extensions.code. For gRPC: use standard status codes with detailed error metadata.
Define pagination. WHERE the endpoint returns a collection, THEN include pagination. Recommend cursor-based pagination for real-time data and offset-based for static datasets. Define the pagination envelope: { data: [], pagination: { cursor, hasMore } } or equivalent.
Specify rate limiting and caching headers. For each endpoint, recommend Cache-Control, ETag, and Vary headers where applicable. Identify endpoints that should be rate-limited and suggest X-RateLimit-* headers.
Verify naming consistency. All resource names must follow the same convention (plural nouns for REST collections, singular for GraphQL types). Path segments must use the same casing throughout. Flag any deviation from the conventions cataloged in phase 1.
Check HTTP method correctness. WHERE a REST endpoint modifies state, THEN it must not use GET. WHERE an endpoint is idempotent, THEN it should use PUT over POST. WHERE an endpoint creates a resource, THEN it must return 201 with a Location header.
Validate schema completeness. Every endpoint must have a defined request schema (if it accepts input) and response schema. No any types. No untyped response bodies. For GraphQL, every field must have an explicit type. For gRPC, no google.protobuf.Any unless justified.
Check backward compatibility. WHERE this is an update to an existing API, THEN verify that no required fields were added to request schemas, no fields were removed from response schemas, no endpoint paths changed, and no response status codes changed. Flag breaking changes explicitly.
Verify OpenAPI spec validity. Run the OpenAPI spec through structural validation. Check for missing descriptions, missing examples, and undefined $ref targets. For GraphQL, validate the schema parses without errors. For gRPC, verify proto files compile with protoc.
Generate the OpenAPI spec. For REST APIs, produce or update an openapi.yaml file with all endpoints, schemas, examples, and security definitions. Use OpenAPI 3.1 unless the project already uses 3.0. Include operationId for every endpoint.
Generate GraphQL schema documentation. For GraphQL APIs, ensure every type, field, query, and mutation has a description. Produce a schema file that can be used for introspection. Add deprecation notices to fields being phased out.
Generate proto documentation. For gRPC APIs, ensure every service, rpc, message, and field has a comment. Verify the proto file includes package name, syntax version, and appropriate options.
Produce a changelog entry. For updates to existing APIs, write a changelog entry listing new endpoints, modified endpoints, deprecated endpoints, and breaking changes (if any). Follow the project's changelog format.
Create request/response examples. For every new endpoint, include at least one success example and one error example in the spec. Examples must use realistic data, not placeholders like "string" or 0.
harness validate -- Run after generating specs to confirm project healthharness scan -- Refresh the knowledge graph after adding new route filesquery_graph -- Trace dependencies between routes, controllers, and servicesget_impact -- Understand blast radius when modifying shared API schemasInput: "Design CRUD endpoints for a blog posts resource in our Express app."
Phase 1 -- DISCOVER:
Detected: REST API (Express 4.x)
Routes directory: src/routes/
Existing endpoints: GET /v1/users, POST /v1/users, GET /v1/users/:id
Conventions: kebab-case paths, plural nouns, /v1/ prefix
Response envelope: { data, meta, error }
Pagination: cursor-based ({ cursor, limit })
Error format: RFC 7807 Problem Details
OpenAPI spec: openapi.yaml (last updated 2 weeks ago, 1 drift: missing GET /v1/users/:id/settings)
Phase 2 -- DESIGN:
paths:
/v1/posts:
get:
operationId: listPosts
parameters:
- name: cursor
in: query
schema: { type: string }
- name: limit
in: query
schema: { type: integer, default: 20, maximum: 100 }
- name: status
in: query
schema: { type: string, enum: [draft, published, archived] }
responses:
200:
content:
application/json:
schema:
type: object
properties:
data: { type: array, items: { $ref: '#/components/schemas/Post' } }
meta:
type: object
properties:
cursor: { type: string, nullable: true }
hasMore: { type: boolean }
post:
operationId: createPost
requestBody:
content:
application/json:
schema: { $ref: '#/components/schemas/CreatePostInput' }
responses:
201:
headers:
Location: { schema: { type: string } }
content:
application/json:
schema:
type: object
properties:
data: { $ref: '#/components/schemas/Post' }
Phase 3 -- VALIDATE:
Naming: PASS -- /v1/posts follows plural noun convention
Methods: PASS -- GET for reads, POST for creation
Schemas: PASS -- all endpoints have request/response schemas
Compatibility: N/A -- new resource, no existing contract
OpenAPI: WARN -- existing spec drift detected (1 endpoint missing)
Phase 4 -- DOCUMENT:
Updated openapi.yaml with 5 new endpoints, 3 new schemas, and examples. Fixed existing drift for GET /v1/users/:id/settings.
Input: "Add a comments system to our GraphQL API."
Phase 1 -- DISCOVER:
Detected: GraphQL (Apollo Server 4, code-first with typeDefs)
Schema: src/schema/typeDefs.ts
Existing types: User, Post, Category
Resolvers: src/resolvers/
Conventions: PascalCase types, camelCase fields, relay-style connections for pagination
Phase 2 -- DESIGN:
type Comment {
id: ID!
body: String!
author: User!
post: Post!
createdAt: DateTime!
updatedAt: DateTime!
parentComment: Comment
replies(first: Int, after: String): CommentConnection!
}
type CommentConnection {
edges: [CommentEdge!]!
pageInfo: PageInfo!
}
type CommentEdge {
node: Comment!
cursor: String!
}
input CreateCommentInput {
postId: ID!
body: String!
parentCommentId: ID
}
extend type Query {
comments(postId: ID!, first: Int, after: String): CommentConnection!
}
extend type Mutation {
createComment(input: CreateCommentInput!): Comment!
updateComment(id: ID!, body: String!): Comment!
deleteComment(id: ID!): Boolean!
}
extend type Post {
comments(first: Int, after: String): CommentConnection!
commentCount: Int!
}
Phase 3 -- VALIDATE:
Naming: PASS -- PascalCase types, camelCase fields
Pagination: PASS -- relay-style connections with PageInfo
Types: PASS -- all fields explicitly typed, no Any
Compatibility: PASS -- uses extend, no modifications to existing types
Input: "Define a notification service for our microservices platform."
Phase 1 -- DISCOVER:
Detected: gRPC (proto3, @grpc/grpc-js)
Proto directory: proto/
Existing services: UserService, OrderService
Package: platform.v1
Conventions: PascalCase services and messages, snake_case fields
Phase 2 -- DESIGN:
syntax = "proto3";
package platform.v1;
import "google/protobuf/timestamp.proto";
service NotificationService {
// Send a notification to a specific user.
rpc SendNotification(SendNotificationRequest) returns (SendNotificationResponse);
// List notifications for a user with cursor pagination.
rpc ListNotifications(ListNotificationsRequest) returns (ListNotificationsResponse);
// Mark a notification as read.
rpc MarkAsRead(MarkAsReadRequest) returns (MarkAsReadResponse);
// Stream real-time notifications for a user.
rpc StreamNotifications(StreamNotificationsRequest) returns (stream Notification);
}
message Notification {
string id = 1;
string user_id = 2;
string title = 3;
string body = 4;
NotificationType type = 5;
bool is_read = 6;
google.protobuf.Timestamp created_at = 7;
}
enum NotificationType {
NOTIFICATION_TYPE_UNSPECIFIED = 0;
NOTIFICATION_TYPE_ORDER_UPDATE = 1;
NOTIFICATION_TYPE_SYSTEM_ALERT = 2;
NOTIFICATION_TYPE_PROMOTION = 3;
}
protoc. An invalid spec is worse than no spec.When this skill makes claims about existing code, architecture, or behavior, it MUST cite evidence using one of:
file:line format (e.g., src/auth.ts:42)file with description (e.g., src/utils/hash.ts —
"existing bcrypt wrapper")evidence session section via manage_stateUncited claims: Technical assertions without citations MUST be prefixed with
[UNVERIFIED]. Example: [UNVERIFIED] The auth middleware supports refresh tokens.
These apply to ALL skills. If you catch yourself doing any of these, STOP.
These reasoning patterns sound plausible but lead to bad outcomes. Reject them.
| Rationalization | Reality |
|---|---|
| "It's an internal API, breaking changes are fine" | Internal consumers break too. Version the change or coordinate the migration explicitly. |
| "The field name is obvious enough" | API field names are a public contract. Follow existing naming conventions and document the semantics. |
| "Nobody uses that endpoint anyway" | Verify with access logs or usage data. Assumptions about usage without evidence lead to silent breakages. |
legacyField from the response. Recommend a deprecation period: add newField in v1, remove legacyField in v2."