calmapi@2.0.0-beta.1Node.js 22 · Express 5 · MongoDB

The backend framework you own, line by line.

CalmAPI copies a small, readable framework into your project. Declare a resource once and get routes, validation, access rules and an OpenAPI document. Then prove the rules hold with a built-in security audit, and watch your coding agent work in devtools.

$npm create calmapi@latest
Get started GitHub
Runtime dependencies
express, mongoose
Framework source in your repo
8,600 lines
CLI dependencies
none
Framework tests, on real MongoDB
443
Tools for coding agents (MCP)
29
localhost:5001/_calmActivity
CalmAPI devtools Activity panel: an AI agent's tool calls, a server crash with its error, the agent's one-line fix as a diff, restarts, and a file edited by a personCalmAPI devtools Activity panel: an AI agent's tool calls, a server crash with its error, the agent's one-line fix as a diff, restarts, and a file edited by a person
fig. 1Devtools, served by your own app at /_calm, while Claude Code adds a route. Its edit crashes the server, it reads the crash with calm_activity, fixes the line and tests again. Your own edit sits in the same feed. Violet marks the agent.
app/resources/post/post.resource.js20 lines

Declare a resource once. The rest follows.

Fields and access rules live in one file. CalmAPI turns them into the Mongoose schema, input validation, output filtering, query rules, five routes and the API reference. Business logic goes in a service with hooks, custom endpoints in a routes file. Both are optional.

import { resource, f } from '#calm';​export default resource('post', {  fields: {    title: f.string().required().max(200).searchable().sortable(),    slug: f.string().readOnly().unique().filterable(),    body: f.text().required().max(50_000),    status: f.enum(['draft', 'published']).default('draft').filterable(),    tags: f.array(f.string().max(30)).max(10).default([]).filterable(),    author: f.ref('user').owner(), // set from the session; powers the 'owner' policy    publishedAt: f.date().readOnly().sortable(),  },  policy: {    list: 'public', // drafts are filtered out in post.service.js scope()    read: 'public',    create: 'authenticated',    update: 'owner | admin',    delete: 'owner | admin',  },});

from that one file

  • Five routes, each with the policy you wrote. calm routes lists them with their source file.
  • Validation that rejects unknown, read-only and hidden fields with a 422, before your code runs.
  • Filtering, sorting and search on the fields you mark, and a 400 for anything else.
  • Responses filtered per caller. A field with visibleTo('owner | admin') never reaches anyone else.
  • Owner scoping. With an owner policy, lists only return the caller's own records.
  • OpenAPI 3.1, generated from the same definition, so the docs cannot drift.
npx calm routesthe post routes of a new project
METHOD  PATH                     POLICY          FROM
GET     /api/posts/featured      public          post.routes.js
POST    /api/posts/:id/publish   owner | admin   post.routes.js
GET     /api/posts               public          post.resource.js
GET     /api/posts/:id           public          post.resource.js
POST    /api/posts               authenticated   post.resource.js
PATCH   /api/posts/:id           owner | admin   post.resource.js
DELETE  /api/posts/:id           owner | admin   post.resource.js
calm/security/audit.js312 lines

Access rules you can prove.

Every route says who may call it and every field says who may see it. Rules only matter if they hold, so calm audit boots your app on a throwaway database, signs in as every role and calls every route. On the starter app that is 54 checks in under two seconds, and --ci fails the build when one breaks.

a list override an agent might write to add sorting

note.service.jsskips the owner rule
import { ResourceService } from '#calm';​export default class NoteService extends ResourceService {  // Newest first, with a larger page.  async list({ filter = {}, skip = 0, limit = 50 } = {}) {    const [items, total] = await Promise.all([      this.model.find(filter).sort({ _id: -1 })        .skip(skip).limit(limit).lean(),      this.model.countDocuments(filter),    ]);    return { items, total };  }}

Notes are owner-only, but lines 7 and 8 query the model directly. Every unit test for the service still passes. The fix is one line: return super.list(...) and let the framework apply the rule.

what the audit says

npx calm audit1.7 s
  note /notes
    action  Anonymous  Signed-in user  Owner        Admin
    list    ✔ deny     ✖ own (200)     ✖ own (200)  ✔ allow
    read    ✔ deny     ✔ deny          ✔ allow      ✔ allow
    create  ✔ deny     ✔ allow         ✔ allow      ✔ allow
    update  ✔ deny     ✔ deny          ✔ allow      ✔ allow
    delete  ✔ deny     ✔ deny          ✔ allow      ✔ allow
    ✖ list as Signed-in user: returned 2 record(s) owned by someone else
    ✖ list as Owner: returned 1 record(s) owned by someone else

  Probes
  ✔ mass assignment: note.owner rejected with 422
  ✔ operator injection: note x[$ne]=1 -> 400
  ✔ forged session token -> 401
  ✔ login does not reveal accounts 401 / 401
  ...

  2 failed · 75 passed · 2 skipped (custom scope or policy) · 79 checks

calm/security/exposure.js

The audit checks against a matrix computed from your code.

Who can list, read, change and delete each resource, and which fields each caller sees. Devtools shows it, calm doctor warns when personal data is public, and coding agents read it through the calm_security tool. This is the matrix of a new project.

How the audit works

Who can do what in the starter app, per resource and caller
actionanonymoussigned inowneradmin
post /api/posts
listallowallowallowallow
readallowallowallowallow
createdenyallowallowallow
updatedenydenyallowallow
deletedenydenyallowallow
user /api/users
listdenydenydenyallow
readdenydenyallowallow
updatedenydenyallowallow
read emailpiinonoyesyes
read rolesnonoyesyes
read passwordnevernevernevernever

access control

  • A policy on every route, listed by calm routes and checked by calm doctor.
  • Field rules for reading and writing, per role and for the owner.
  • 401, 403 or 404 chosen so a caller who cannot read a record never learns it exists.
  • No mass assignment: unknown, read-only, hidden and owner fields are rejected with 422.

accounts

  • Opaque sessions stored as SHA-256 hashes. List them, end one, end all.
  • scrypt passwords from node:crypto. Common passwords and ones with your name or email are refused.
  • Lockout: 5 failed logins in 15 minutes locks that account for 15 minutes.
  • Two-factor login with the totp block: RFC 6238, replay protection, hashed recovery codes.

data and input

  • .encrypted() fields: AES-256-GCM with key ids, rotated with calm keygen --write.
  • Query allowlists: x[$ne]=1 is a 400, and page size is capped.
  • JSON guard: 1 MB body, depth 20, 10,000 keys.
  • Production by default: devtools can never run there, security headers on, CORS closed.
localhost:5001/_calmSecurity
CalmAPI devtools Security panel after running the audit, with one failed cell highlighted in redCalmAPI devtools Security panel after running the audit, with one failed cell highlighted in red
fig. 2The same audit from devtools: Run audit marks every cell of the matrix as passed or failed. Here a custom route let any signed-in user update someone else's note.
.calm/activity.jsonlwritten by calm dev and calm mcp

Your agent writes the code. You see every step.

Coding agents connect to calm mcp and get 29 tools for this project. Everything they do lands in one activity log that devtools streams live: tool calls, file diffs, restarts, crashes and the requests they send. The agent reads the same log, so it notices when an edit breaks the server, yours or its own.

the agent

Claude Code, Cursor, Codex

Reads AGENTS.md for the project's rules. Scaffolds with calm_make_resource, calls the API as any user with calm_http, then runs calm_test and calm_audit.

calm dev + calm mcp

One activity log

Every tool call is logged with its arguments, result and duration. Every file change is diffed and credited to the agent: Claude Code's edit hook names each file before it writes, other agents are known by their MCP calls. Its API calls carry an X-Calm-Agent header.

you

Devtools at /_calm

Activity shows each step with its diff, live. Requests marks the agent's calls with their queries. When it says it is done, run the audit yourself in one click.

localhost:5001/_calmRequests
CalmAPI devtools Requests panel with violet markers on requests made by an AI agent, and the timeline of one of themCalmAPI devtools Requests panel with violet markers on requests made by an AI agent, and the timeline of one of them
fig. 3Requests the agent sent through calm_http carry a violet marker in the list and in the header, next to the user it acted as. Each has its headers, body, queries and logs, like your own requests.

understand

  • calm_projectresources, blocks, server state
  • calm_routesevery route and its policy
  • calm_resourceone full definition
  • calm_openapithe API document
  • calm_blockswhat can be added
  • calm_clienta typed client for the frontend

change

  • calm_make_resourcescaffold from field specs
  • calm_add_blockwith a dry run first
  • calm_proposea diff for you to apply
  • calm_checkpointsnapshot the dev data
  • calm_restoreput it back
  • calm_declaresay what it will change, first

run and observe

  • calm_httpcall the API as anyone
  • calm_recent_requestswhat just happened
  • calm_requestqueries, logs, stack
  • calm_logsserver log lines
  • calm_mailsemails the app sent
  • calm_pushespush notifications sent
  • calm_activitydiffs, restarts, crashes
  • calm_explainwhy a request got its answer

verify

  • calm_testpass and fail per test
  • calm_doctorfindings to fix
  • calm_auditthe authorization check
  • calm_securitymatrix and events
  • calm_diffwhat changed in behavior
  • calm_reviewwhat the developer will sign
  • calm_replayrecorded traffic, sent again
  • calm_budgetswhat each route costs
  • calm_aboutwhat the framework does

Connect your agent in one line.

Any MCP client works the same way. New projects include AGENTS.md and CLAUDE.md, so the agent knows the conventions before it writes a line. Working with agents

inside your project
$ claude mcp add calm -- npx calm mcp
calm/behavior.jssee · prove · bound · undo

Agents write it. You can read it, prove it, and take it back.

The person who ships the code answers for it, whoever typed it. So the framework tells you what a change does, holds you to the promises you made, limits what an agent may touch, and lets you undo it. Every check is plain code in your repo, and nothing calls a model or leaves your machine: calm about lists everything the framework does, and proves calm/ makes no network requests.

See

Review behavior, not lines.

calm diff main lists what changed in what the app does: routes, who may call them, which fields more people can now read, new env vars and hosts. --ci fails the build when access widens. Every request in devtools also shows its path through your code, down to the policy clause that denied it.

npx calm diff main
  Behavior changes since main (4)
  +  POST  /api/refunds      admin
  ~  PATCH /api/posts/:id    looser
       owner | admin -> authenticated
  ~  user.email             looser
       the owner and admins -> everyone
  +  calls api.stripe.com   app/routes.js

  2 of 4 widen access.
The behavior diff

Prove

Promises the framework holds you to.

Write invariants once in calm.config.js: no public write routes, personal data never public, auth routes rate limited, or your own check. Doctor reports a broken one as an error, and in production the app refuses to start. Removing a promise shows up in the diff.

npx calm doctor
  ✖ error  Invariant broken: no public write routes
           POST /api/contact is public (app/routes.js)
           In production the app refuses to start.
Invariants

Bound

An agent reaches as far as you let it.

calm mcp --scope read, scaffold or full. A refused call tells the agent what to ask you for, and edits to protected paths or access rules are flagged for review. Claude Code's edits are recognized as its own through a hook new projects ship with.

activity
claude-code  calm_restore
  Refused: scope "scaffold" cannot run calm_restore.
  Ask the developer for calm mcp --scope full,
  or describe the change with calm_propose.
Scopes

Undo

Take the data back too.

Git keeps your code. calm checkpoint keeps your development data, and calm restore puts it back exactly. One is taken automatically when an agent connects, with a Restore button in devtools.

npx calm restore
  Restore 20261013-141500-before-claude-code-session
    posts   12 documents  (15 now)
    users    3 documents  (3 now)
  ✔ Restored: 2 collections, 15 documents
Checkpoints
calm/review.jsnew in 2.0.0-beta.1

The agent changes it. A person signs it.

The first beta asks a person to accept each change, holds the API to what was accepted, keeps an agent's experiments away from your data, and gives your frontend a typed client. Like everything else, it runs on your machine and lives in your repo.

Review and sign

A person signs what the agent changed.

calm review shows what changed since the last signature: the behavior diff, the files AI agents changed that nobody has signed, the last test run, and what the agent declared it would change next to what it did. --sign records your name, a note and the commit in .calm/reviews/, and refuses to run in an agent's shell. Devtools has the same review in a Review panel with a Sign form, and marks unsigned routes and resources. --ci fails when access widened since the last signature.

npx calm review
  CalmAPI review · since Ada Lovelace signed 2026-10-13 19:29

  Behavior (7)
    ~  GET    /api/products      policy: authenticated -> public          looser
    ~  GET    /api/products/:id  policy: authenticated -> public          looser
    ~  product.price             visible to: signed-in users -> everyone  looser
    -  product.tags              was visible to: signed-in users
    6 widen access.

  Written by agents, not signed (1)
    app/resources/product/product.resource.js  claude-code  2026-10-13 19:30  access rules

  Declared by agents (1 declaration, 2 changes)
    claude-code Show the product catalog to visitors
    ✖ not declared  route GET /api/products/:id policy: authenticated -> public
    ✖ not declared  field product.tags was visible to: signed-in users
    ! declared, not made  route POST /api/refunds

  Sign it with calm review --sign, or in devtools: Review.
Review and sign

Exposure budget

Access only widens on purpose.

calm audit --accept --reason "..." writes who may do what to security.snapshot.json. From then on, wider access is an error in calm audit --ci, calm doctor and the Doctor panel until a person accepts it again, with the reason next to their name.

npx calm doctor --ci
  ✖ error  Access widened beyond security.snapshot.json in 2 places
           product list anonymous: no -> yes
           product read anonymous: no -> yes
           If it is intended: npx calm audit --accept --reason "why".
           Otherwise fix the policy or field rule.

  1 error · 0 warnings · 0 info
The exposure budget

API contract diff

Know when a change breaks your clients.

calm diff main --api compares the OpenAPI contract your apps rely on and sorts every change into breaking, minor or patch: removed routes and fields, new required fields, narrowed enums, tighter limits. It suggests the version bump, and --ci fails on a breaking change.

npx calm diff --api
  API contract changes since HEAD (3783ab9) (8)
    breaking  GET /api/products         response.data[].tags: removed from the response
    breaking  POST /api/products        body.tags: no longer accepted (sending it is a 422)
    breaking  PATCH /api/products/{id}  body.tags: no longer accepted (sending it is a 422)
    patch     GET /api/products         now public

  6 breaking · 0 added · 2 other
  Suggested version 0.1.0 -> 0.2.0 (breaking: before 1.0 that is a minor bump)
The behavior diff

Replay and recorded tests

Yesterday's traffic, against today's code.

The dev server records the shape of each answer, never its values. calm replay sends the requests again as the same users and reports changed statuses and shapes: a field newly returned is a possible leak. Save as test in devtools turns a request into a plain node --test file.

npx calm replay --writes
  Replayed 8 recorded requests
  against the code as it is now (0.1 s, writes restored from a checkpoint)
       1 identical
       5 changed

  ~ POST /api/products as user 6ace86d4 [user]
      status 201 -> 422

  ~ GET /api/products as user 6ace86d4 [user] (3 times)
      body.data[].tags: no longer returned
Replay

Budgets

A cost limit for every route.

Give routes a budget in calm.config.js: MongoDB queries, p95 time and response size. The dev server measures every request (a Budgets panel, an over-budget tag in Requests), and calm budgets --ci runs your tests with the meter on. Production never measures.

calm.config.js
budgets: {  'GET /api/products': { queries: 2, response: '10kb' },  'POST /api/**': { p95: '2s' },  '*': { queries: 12 },},
npx calm budgets --ci
  Tests: 8 passed

  ROUTE                    MAX QUERIES  P95            BUDGET
  GET /api/products        4 / 2        13ms           GET /api/products
  POST /api/auth/register  3            43ms / 2000ms  POST /api/**

  1 route over budget
    GET /api/products: queries 4 > 2
Budgets

Agent database

Let the agent break a copy.

calm dev --agent-db runs the app on a copy of your development database, indexes included, and drops it when calm dev stops. The agent creates, changes and deletes data freely, yours stays as it was, and devtools marks the database as a copy.

npx calm dev --agent-db
  Copying the development database for the agent...
✔ Running on e2e_shop_agent, a copy of e2e_shop
  (14 collections, 38 documents). It is dropped when calm dev stops.
  ...
  Dropped e2e_shop_agent.
Working with agents

Typed client

One typed file for your web and mobile apps.

calm client writes a client from the API itself: every route a function with its input and output types, typed CalmApiErrors, no dependencies. TypeScript, or JavaScript with a .d.ts. With client: { out } in calm.config.js, calm dev writes it again whenever the API changes.

npx calm client --out ../web/src/api/calm-client.ts
✔ Wrote ../web/src/api/calm-client.ts (28 routes in 3 groups)
web/src/posts.ts
import { createClient } from './api/calm-client';​const api = createClient({ baseUrl: 'http://localhost:5001' });const page = await api.posts.list({ sort: '-publishedAt' }); // Page<Post>
Typed client
calm/devtools/index.js984 lines · development only

Devtools that ship inside your app.

Run npm run dev and open /_calm. No extra service, no browser extension. It only runs in development, only answers on localhost, and can never be turned on in production. Every panel explained

localhost:5001/_calmRequests
CalmAPI devtools Requests panelCalmAPI devtools Requests panel
fig. 4Every request with each MongoDB query on a timeline, and its Path: each step through your code down to the policy clause that allowed or denied it. Repeated queries with the same shape are flagged as N+1 with a hint on how to batch them. Copy as curl, replay, or open in the playground.
calm.locka sha256 for every framework file

Every line is yours. Upgrades still work.

The framework is copied into calm/: about 8,600 lines of commented JavaScript on Express 5 and Mongoose. Read it, step through it, change it. calm.lock remembers what you started from, so calm upgrade replaces the files you never touched and three-way merges the ones you did.

my-api/
calm/                the framework, yours to read and edit
  app.js  config.js  testing.js  openapi.js
  auth/  resource/  http/  security/  devtools/
app/
  resources/post/      post.resource.js, .service.js, .routes.js
  resources/user/
  blocks/              blocks you add, as source
  routes.js
test/                  node:test with createTestApp
AGENTS.md  CLAUDE.md    rules for coding agents
calm.config.js  calm.lock  .env  Dockerfile
npx calm upgradeexample output
  calm upgrade 2.0.0-alpha.2 → 2.0.0-beta.1

  update    calm/http/router.js
  update    calm/resource/query.js
  merge     calm/auth/index.js
  conflict  calm/config.js
  add       calm/review.js

  Apply? yes
  ✔ calm/ upgraded to 2.0.0-beta.1
  ! Resolve conflict markers in: calm/config.js

Untouched files are replaced, edited files are merged with your changes kept, and conflicts get the usual markers. The test suite runs a real upgrade over an edited project for each case. Upgrading

npx calm add <block>35 official blocks

Add features as source code.

A block is copied into app/blocks/ with its dependencies and environment variables, then it is yours to edit like everything else. Every block brings links to the official documentation of what it integrates and instructions for AI agents, in an AGENTS.md next to its code that devtools shows too. Your own blocks take one command to start and one to share, and anyone can install them from GitHub after a plain-language review of what the code does. Browse blocks · Build your own

notificationsno deps
One call for the in-app inbox, push and email, following each user's preferences and quiet hours.
oauthno deps
Sign in with Google, GitHub or any OpenID Connect provider: PKCE, state and nonce, ID tokens checked against the provider's keys.
payments-stripeno deps
Stripe Checkout, subscriptions and the customer portal without the SDK. Signed webhooks run once, and routes can require a plan.
teamsno deps
Teams with owner, admin, member and your own roles, email invitations and transfers. Records of team-scoped resources stay in their team.
webhooksno deps
Signed webhooks for resource events, retried from a MongoDB queue, with a delivery log and SSRF protection.
api-keysno deps
API keys with scopes for scripts and integrations: shown once, hashed at rest, with expiry and revoke.
magic-linkno deps
Passwordless sign-in by email. Links work once, expire, and only in the browser that asked.
email-verificationno deps
A single use link after sign-up and every address change, a verified policy, and optional enforcement at sign-in or on every route.
captchano deps
Cloudflare Turnstile, hCaptcha or reCAPTCHA v3 on sign-up, sign-in and password reset, failing closed when the provider is down.
feature-flagsno deps
Kill switches, gradual rollouts, per user and per role targeting, variants and route gates.
cacheno deps
GET answers cached in MongoDB or memory, per identity, invalidated by resource events and tags, with ETags and stampede protection.
privacyno deps
Users download everything they own and delete their account: delete, anonymize or keep per resource.
idempotencyno deps
The Idempotency-Key header: a retried payment or order runs once and replays the stored response.
totpno deps
Authenticator-app codes on login: setup by QR link, hashed single-use recovery codes, replay protection.
jobsno deps
Background jobs and cron on MongoDB, without Redis: retries with backoff, schedules, a devtools panel.
mcp-serverno deps
Your resources as MCP tools for AI agents, behind the same policies and validation as the REST API.
realtime-sseno deps
Live changes over Server-Sent Events, filtered per subscriber by the same rules as the API.
search-meilisearchno deps
Full-text search with Meilisearch. Results load through each resource's own policy, so search never leaks a record or a field.
audit-logno deps
Who changed what and when, with field-level diffs. Private fields are never recorded.
soft-deleteno deps
DELETE marks records deleted, queries hide them, admins list and restore them.
exportno deps
Admins export any resource as streamed CSV, NDJSON or JSON, and import through the resource's own validation, with a dry run.
waitlistno deps
A launch waitlist: a place in line, referral codes that move people up, invites in batches and an optional invite-only gate.
maintenanceno deps
Maintenance and read-only modes switched at runtime by admins: 503 with Retry-After, scheduled windows and an allowlist.
storage-s3@aws-sdk
Direct uploads to S3, R2 or MinIO with presigned URLs, type and size allowlists.
storage-localmulter
Uploads to disk with type and size allowlists, magic-byte checks and safe downloads.
api-docsno deps
An interactive API reference at /docs, built from the generated OpenAPI document.
rate-limit-mongono deps
Rate limit counters in MongoDB, so limits hold across every instance.
mail-resendno deps
Send email through the Resend HTTP API with plain fetch.
mail-postmarkno deps
Send email through the Postmark HTTP API: message streams, tags and attachments, with plain fetch.
mail-smtpnodemailer
Send email through any SMTP server.
sms-twiliono deps
SMS through the Twilio Messages API, and phone verification with 6-digit codes stored hashed, with expiry and attempt limits.
push-expono deps
Push notifications to Expo and React Native apps, with receipts. Dead tokens are removed for you.
push-fcmno deps
Push notifications to Android, iOS and the web through Firebase Cloud Messaging, signed with node:crypto.
slackno deps
App events and security alerts in Slack. Values are escaped so user data cannot ping @channel, and bursts become one digest.
sentryno deps
Unhandled errors and failed background work to Sentry without the SDK, with secrets scrubbed and bursts deduplicated.
npm create calmapi@latestNode.js 22.12+ · MongoDB

Start in a minute.

  1. Create a project

    Choose the api template for sign-up, users and posts, or minimal for an empty app.

    $npm create calmapi@latest my-api
  2. Run it

    The API answers on localhost:5001/api and devtools on localhost:5001/_calm.

    $cd my-api && npm run dev
  3. Hand it to your agent

    Ask for a resource, then watch the Activity panel while it works.

    $claude mcp add calm -- npx calm mcp
  4. Check the result

    Tests, then the authorization audit. Both run against a throwaway database.

    $npm test && npx calm audit

the calm command

calm create
New project from the api or minimal template.
calm dev
Watch mode, devtools and the activity log, optionally on a copy of the data.
calm make resource
Scaffold a resource from field specs.
calm add
Add blocks, from the registry or GitHub, with a safety review.
calm make block
Start your own block, then check and pack it to share.
calm seed
Sample records that look real, built from your fields.
calm routes
Every route, its policy and its source file.
calm audit
Every route as every role, on a throwaway database. Also sets the exposure budget.
calm review
What changed since the last signature, for a person to read and sign.
calm doctor
Configuration, exposure, secrets, advisories and your invariants.
calm diff
What changed in behavior or in the API contract since a git ref. Fails CI when access widens.
calm replay
Recorded requests, sent again against the code as it is now.
calm budgets
Queries, p95 and response size per route, against your budgets.
calm about
Everything the framework does that you did not write.
calm checkpoint
Snapshot the dev database; calm restore puts it back.
calm openapi
Write the OpenAPI 3.1 document.
calm client
A typed, dependency-free client for your web or mobile app.
calm keygen
Keys for encrypted fields, with rotation.
calm admin
Give a user the admin role, or take it away.
calm upgrade
Merge a new framework release into calm/.
calm mcp
MCP server for coding agents, with read, scaffold and full scopes.

Coming from CalmAPI 1.x? Run npx calmapi@next doctor in your 1.x project first, then follow the migration guide. The 1.x documentation stays online at docs.calmapi.dev/v1.

Read every line. Prove every rule.

$npm create calmapi@latest
Get started