apps/linear-clone, name linear) is an API-only clone of
the Linear GraphQL API. Unlike the other
templates, Linear is not REST — its public API is a single GraphQL endpoint,
and the clone mirrors that exactly: one POST /graphql that accepts
{ query, variables, operationName }, returns the GraphQL { data, errors }
transport envelope, dispatches Linear’s literal camelCase operation names
(issueCreate, issues, teamCreate, …), and paginates with Relay
connections. It’s faithful enough at the shape level that an agent built for
Linear can operate it.
What’s inside
This template is API-only — there is no frontend.
Modes
Seeding
password123 (e.g. dana@acme.test). AI seeding
generates users, teams, issues, and projects (the template’s declared
entities). See Seeding.
Tokens and auth
Two credential types both resolve to the same principal:- a JWT access token from
POST /api/auth/signup/login/refresh(the web/control-plane path), and - a Linear-shaped personal API key (
lin_api_…) minted atPOST /api/api-keys. Onlysha256(key)is stored; the plaintext is returned in thetokenfield once at creation.
Authorization header (no Bearer prefix) — this is exactly how Linear
authenticates a personal API key. An OAuth-style Bearer token is also accepted.
A
lin_api_ key authenticates but its scopes are not enforced — any valid key
acts with its principal’s full access. OAuth app installs and scope enforcement
are out of scope for this slice. Clones bind to localhost by default, so a key is
not reachable off your machine unless you --expose.API tour — it’s GraphQL
Every data-plane operation is aPOST /graphql. Mutations return Linear’s
{ success, <entity>, lastSyncId } payload; queries that return lists are Relay
connections (nodes, edges { node, cursor }, pageInfo { hasNextPage, endCursor })
with first / after args.
ENG-42
(team.key + a monotonic counter). Entity ids are UUIDs, matching Linear.
Realtime
Connect a Socket.io client withauth: { token } (JWT or API key). You’re joined
to an org:<id> room and receive every domain event (issue.created,
issue.updated, comment.created, project.*, cycle.*).
Webhooks
Register a target withPOST /api/webhooks (optionally scoped to a team and to
specific resource types). Deliveries are HTTP POSTs signed with a
Linear-Signature header = hex HMAC-SHA256(rawBody, secret), carrying Linear’s
webhook envelope:
updatedFrom is present only on update actions, and url is derived per entity
type — matching Linear.
Rate limiting
The GraphQL endpoint enforces Linear’s published budgets per principal: 5,000 requests/hour, 3,000,000 complexity points/hour, and a 10,000-point cap on a single query (complexity is estimated from the selection set). When a budget is exhausted the response is HTTP 400 witherrors[].extensions.code = "RATELIMITED", and every response carries
X-RateLimit-Requests-* and X-RateLimit-Complexity-* headers
(Limit / Remaining / Reset).
API shape — read this before pointing an agent at it
Linear’s real API is GraphQL, and the clone reproduces that paradigm exactly: a singlePOST /graphql, the { data, errors } transport envelope, Linear’s
literal operation names, { success, <entity>, lastSyncId } mutation payloads,
and Relay-style connection pagination. So this template matches Linear at the
shape level, not by URL paths.
The template ships an API_PARITY.md that scores it against Linear’s live GraphQL
docs. On the representative core set of 30 Linear operations (issues, comments,
projects, teams, labels, workflow states, cycles, org, users/viewer, webhooks):
That’s 100% capability and 100% exact-shape coverage of the targeted core
surface. Linear’s full schema is hundreds of operations; the long tail
(attachments, documents, project updates, reactions, favorites, roadmaps,
notifications, team-membership mutations, …) is unimplemented by design — this is
a core slice, not the whole schema. See
apps/linear-clone/API_PARITY.md for the
per-operation breakdown.
A small REST control plane stays under the /api prefix for bootstrap that
sits outside Linear’s GraphQL surface: auth/{signup,login,refresh,logout},
api-keys, and health.
The
verify command will fold live fidelity scoring into the
CLI. Until then, API_PARITY.md and the /verify-api linear workflow are how
fidelity is tracked.MCP server
mcp-server/ exposes the clone to MCP clients with a personal API key. It ships a
core subset of Linear’s MCP tools: list_teams, list_issues, get_issue,
create_issue, update_issue, create_comment, and list_projects.
Inspect a running clone
001_initial_schema.sql — read it to know what’s queryable.