@contract-kit/cli
v1.0.0
Published
CLI for creating and maintaining Contract Kit apps.
Maintainers
Readme
@contract-kit/cli
Command-line tools for creating and maintaining Contract Kit apps.
Create an app
bunx -p @contract-kit/cli contract-kit create my-appOr use the package binary directly:
bunx -p @contract-kit/cli create-contract-kit my-appBy default the CLI creates a Next.js app with:
- Contract-first todos API routes
- App-owned ports and in-memory infra adapters
- Validated application use cases
- A Contract Kit server wired through Next.js route handlers
- App error helpers, auth helpers, env validation, health checks, and devtools
- A typed client
- TanStack Query
- React Hook Form
- OpenAPI output
The CLI writes files only. After creation:
cd my-app
bun install
cp .env.example .env.local
bun run devCommon follow-up commands:
# in another terminal, from my-app
bunx -p @contract-kit/cli contract-kit make resource projects
bunx -p @contract-kit/cli contract-kit routes
bunx -p @contract-kit/cli contract-kit doctorOptions
contract-kit create <directory> [options]
contract-kit make contract <name> [options]
contract-kit make port <name> [options]
contract-kit make policy <name> [options]
contract-kit make provider <name> [options]
contract-kit make resource <name> [options]
contract-kit make test <feature>/<action> [options]
contract-kit make use-case <feature>/<action> [options]
contract-kit routes [--json]
contract-kit doctor [--json] [--strict] [--fix]
Options:
--template next Template to use. Currently only `next`.
--preset standard `minimal` or `standard`.
--package-manager bun Package manager shown in next steps.
--feature react-query Add a starter feature. Repeatable.
--features client,openapi Add features from a comma-separated list.
--integration inngest Add an integration. Repeatable.
--integrations inngest,pino Add integrations from a comma-separated list.
--force Write into a non-empty directory.
--dry-run Preview make writes without changing files.
--json Print machine-readable output.
--strict Include CI-oriented doctor warnings and fail on warnings.
--fix Apply low-risk doctor fixes before reporting.
-h, --help Show help.App conventions
Contract Kit CLI commands are convention-aware. routes, doctor, and
generators work best in the Next.js layout created by contract-kit create:
contracts/
app/api/
server/index.tsThe standard preset adds the files resource generators expect:
app-context.ts
infra/ports.ts
ports/index.ts
use-cases/builder.tsExisting apps can adopt these conventions incrementally. Until the recommended
architecture is in place, the runtime packages still work, but the CLI has less
information to inspect or update safely. contract-kit doctor reports when a
directory does not match the app layout.
Use contract-kit.config.ts, contract-kit.config.mjs, or
contract-kit.config.json when your app keeps the same architecture under
different paths:
// contract-kit.config.ts
import { defineConfig } from "@contract-kit/cli/config";
export default defineConfig({
paths: {
contracts: "src/contracts",
routes: "src/app/api",
server: "src/server/index.ts",
},
});Config values are optional overrides. Omitted paths fall back to the generated
defaults. routes, doctor, and make generators all load the same resolved
config before inspecting or writing files.
Generate a contract
Use make contract when you want to start with the HTTP contract only:
contract-kit make contract projectsThe command honors contract-kit.config.* path overrides and writes
contracts/projects.ts. It creates a self-contained contract group with a
starter list endpoint, schema, standard error response, and exported contract
list. It does not wire route handlers, use cases, ports, or OpenAPI; use
make resource when you want the full path from contract to tests.
Like make resource, make contract skips identical files and stops on
divergent files unless you pass --force.
Generate a use case
Use make use-case inside a Contract Kit app when you want a focused
application workflow without generating HTTP contracts or ports:
contract-kit make use-case projects/archive-projectThe name uses feature/action format. The command writes
use-cases/projects/archive-project.ts and creates or updates
use-cases/projects/index.ts. Read-style actions that start with get, list,
find, search, or count generate .query(...); other actions generate
.command(...).
Generate a test
Use make test after generating a use case:
contract-kit make use-case projects/archive-project
contract-kit make test projects/archive-projectThe command writes tests/projects/archive-project.test.ts, builds the
app context through createUseCaseTester, and asserts the starter
{ ok: true } response. It also adds a test script when the app does not
already define one. Treat the output as a compiling starting point: replace the
input, context setup, and assertion with behavior-specific coverage as the use
case grows.
Generate a port
Use make port inside a Contract Kit app when a use case needs a new
application boundary:
contract-kit make port emailThe command writes ports/email.ts, adds the port to AppPorts, creates a
small fake adapter for tests, and wires a throwing infra stub so the app still
typechecks until you replace it with a real port adapter. The generated port
starts with a generic execute method; rename it to the domain operation your
use case needs.
Generate a policy
Use make policy when repeated authorization rules need a named home:
contract-kit make policy postsThe command writes policies/posts.ts with a definePolicy(...) starter.
Register the policy with createGate(...), install the gate as a port, and
bind it into request context so use cases can call ctx.gate.authorize(...).
Generate a port adapter
Use make provider after generating a port. The command name reflects the
Contract Kit workflow, but the generated code is a direct port factory, not a
Contract Kit lifecycle provider.
contract-kit make port email
contract-kit make provider emailThe command writes infra/email/email-port.ts and replaces the generated
inline infra stub with email: createEmailPort(). The adapter still
throws by default; replace its implementation with real infrastructure code
while keeping use cases behind the port interface. If the infra wiring
was already customized, the command stops instead of guessing.
Generate a resource
Inside a Contract Kit app, scaffold a new vertical slice with:
contract-kit make resource projectsThe command honors contract-kit.config.* path overrides. It writes a contract,
list/create use cases, a repository port, an in-memory repository, a Next.js
route handler, and a starter test. It also wires the resource into
ports/index.ts, infra/ports.ts, the OpenAPI route when present, and
adds a test script if the app does not already have one.
The generated resource uses a small name field by default so the app stays
typecheckable immediately. Rename the fields in the generated schemas,
repository, and tests to match your domain.
make resource is idempotent for unchanged generated files: repeated runs skip
identical files and avoid duplicate wiring. If a generated file exists with
different content, the command stops unless you pass --force.
Preview writes without changing files:
contract-kit make resource projects --dry-runUse JSON output when another tool needs the exact planned changes:
contract-kit make resource projects --dry-run --jsonInspect app routes
Inside an app, list the contracts the CLI can match to Next.js route handlers:
contract-kit routesUse JSON output when you want to feed the route catalog into another tool:
contract-kit routes --jsonCheck for drift
Run doctor when you want quick feedback on contract wiring drift:
contract-kit doctorToday it detects:
- Contracts without a matching Next.js route handler
- Next.js route handlers that do not map to known contracts
- OpenAPI drift in direct arrays and common exported contract lists
- Partially wired generated resource slices
- Provider packages without matching canonical app ports
- Generated ports without test fakes
Use contract-kit doctor --strict for CI-oriented checks that may be noisy
locally, such as missing generated resource tests or vendor imports inside use
cases. Use contract-kit doctor --json in CI or custom scripts.
Use contract-kit doctor --fix for low-risk maintenance fixes. Today it can add
a missing test script and repair direct createOpenAPIHandler([...]) arrays
when the missing contracts are already imported in the OpenAPI route.
Available presets:
minimal- choose this when you want the small contract/server/use-case loop without the full app conventions.standard- choose this when you want the full app layout with app errors, env validation, devtools, provider wiring, health checks, and separatedports/+infra/.
Integrations are orthogonal to presets. Add only the services you want:
bunx -p @contract-kit/cli contract-kit create my-app --preset standard --integrations drizzle-turso,inngest,resendAvailable features:
clientreact-queryformsopenapi
Available integrations:
better-authdrizzle-tursoinngestpinoresendupstash-rate-limit
With --preset standard, drizzle-turso also scaffolds a Drizzle schema, repository adapter, drizzle.config.ts, database scripts, and TURSO_* env examples so the generated todo resource uses durable persistence instead of the in-memory repository.
With --preset standard, the starter includes a provider-neutral AuthPort,
anonymous auth adapter, typed UNAUTHORIZED and FORBIDDEN errors, a
request-bound authorization gate, and requireUser(ctx). Use hooks for HTTP
boundary authentication and use cases or policies for business authorization.
The better-auth integration adds dependencies and setup notes, then you
replace the anonymous adapter once your app has a real Better Auth
session/database setup.
License
MIT
