Get Started

Three commands to go from zero to generated, type-safe code.

1. Install the CLI

npm install -g @xrpckit/cli

Requires Node.js >= 18. Also works with npx @xrpckit/cli, pnpm dlx @xrpckit/cli, or bunx xrpc.

2. Initialize your project

xrpc init

The init wizard handles the entire setup for you:

  • Detects your project structure — monorepo, single app, framework
  • Creates a contract file with a working starter template
  • Lets you pick targets — Go server, TypeScript client, Kotlin Spring Boot, Swift, and more
  • Writes xrpc.toml so every future run is just xrpc generate
  • Optionally sets up the TypeScript language-service plugin for go-to-definition on generated code

3. Generate code

xrpc generate

That's it. The CLI reads your xrpc.toml, parses the contract, and writes type-safe code into each target's output directory.

From here on, the workflow is: edit your contract → run xrpc generate → ship.

What init creates

After running init, your project will have two new things: a contract file that defines your API, and an xrpc.toml that tells the CLI what to generate and where.

Contract file

The contract is a regular TypeScript file that serves as the single source of truth for your API. You use xRPC's own DSL — createRouter, group, query, and mutation — to define the structure of your API. Zod is used for the data layer: describing the shape and validation rules of each endpoint's input and output. xRPC reads both to generate type-safe, validated code for every target language.

import { z } from "zod";
import { createRouter, group, query, mutation } from "xrpckit";

const user = group("user", {
  getUser: query({
    input: z.object({ id: z.string().uuid() }),
    output: z.object({ id: z.string(), name: z.string(), email: z.string().email() })
  }),
  createUser: mutation({
    input: z.object({ name: z.string().min(1).max(100), email: z.string().email() }),
    output: z.object({ id: z.string().uuid() })
  })
});

export const router = createRouter({ user });

A contract is structured as Router → Endpoint Groups → Endpoints. Each endpoint is either a query (read) or a mutation (write), with typed input and output schemas. Zod constraints like .min(), .max(), .email(), and .uuid() carry over into the generated code as runtime validation — in every language.

For the full contract API, see API Contract.

xrpc.toml

The config file maps your contract to the targets you want to generate. Each key is a target name, and the value is the output directory where generated code will be written.

# xRPC Configuration
# Run "xrpc generate" to generate type-safe code for your targets

contract = "./src/contract.ts"
go-server = "./apps/backend"
ts-client = "./apps/web"
swift-client = "./apps/ios"

With this config in place, xrpc generate is all you need — no flags, no arguments. The generated code is self-contained with zero runtime dependencies, using each language's standard library.

For monorepos with multiple APIs, you can define separate modules. See Configuration for multi-module setups and advanced options.

Where next?