npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

contrakt

v0.1.7

Published

Auto-infer API contracts from vibe-coded apps, detect schema drift, generate MCP server configs

Readme

Contrakt

Auto-infer API contracts from vibe-coded apps, detect schema drift, and generate MCP server configs so AI agents can call your endpoints.

The problem

You ship a Next.js app with Cursor or Lovable. Two sessions later, an AI assistant silently changes a response shape. Your consumers break. You had no contract to catch it.

Contrakt scans your actual handler code, infers the contract, and tells you exactly what changed — without a single line of hand-written spec.

Install

npm install -g contrakt

Quickstart

cd my-nextjs-app

# 1. Infer contract + generate MCP config (run once)
contrakt init

# 2. Check for drift anytime — static analysis + live sampling if server is running
contrakt check

# 3. See what setup step is missing
contrakt doctor

# 4. Intentionally changed the API? Accept it as the new baseline
contrakt check --update

# 5. Publish your contract to the public registry
contrakt publish --name my-app

# 6. Optional: charge AI agents per API call with x402
contrakt monetize --receiver 0xYourWallet --price 0.001 --free-calls 5
contrakt monetize --publish

# 7. Watch a contract you depend on
contrakt watch https://contrakt-registry.vercel.app/u/username/my-app --depend

That's the whole workflow. Commit contrakt.lock to your repo. Run contrakt check in CI.

Commands

contrakt init

Scans your Next.js API routes, infers request/response schemas, writes contrakt.lock, and generates an MCP server stub.

Options:
  --cwd <path>        Project directory (default: current directory)
  --base-url <url>    Base URL of your running app (default: http://localhost:3000)
  --force             Overwrite existing contrakt.lock without prompting
  --no-mcp            Skip MCP config generation
  --verbose           Debug logging

Outputs:

  • contrakt.lock — versioned contract file (commit this)
  • contrakt.config.json — local config (baseUrl, registry info)
  • .contrakt/mcp.json — Claude Desktop / MCP client config snippet
  • .contrakt/contrakt-mcp-server.ts — runnable MCP server stub

contrakt check

The main command. Re-scans your code for static drift, and if your dev server is running, also samples live endpoints to catch runtime schema changes.

Options:
  --cwd <path>        Project directory
  --update            Accept current state as new baseline and update contrakt.lock
  --base-url <url>    Override base URL for live sampling
  --watch             Watch for file changes and re-check continuously
  --verbose           Debug logging

Exit codes:
  0   No breaking changes
  1   Breaking changes detected (CI-friendly)

Change categories:

  • 🔴 Breaking — removed endpoint, removed field, changed field type, added required request field
  • 🟡 Non-breaking — added endpoint, added optional field, new status code
  • 🟢 Additive — description updates, JSDoc changes

Example output (server running):

Contrakt — check

Scanning /my-app
  GET /api/config

✓  No code changes.

Sampling live endpoints against http://localhost:3000
  ↓ GET /api/config 200 -1 field(s): showArchive

Breaking changes (1):
  ✗ Field "response.showArchive" was removed [GET /api/config]

Run 'contrakt check --update' to accept these changes as your new baseline.

If ANTHROPIC_API_KEY is set in your environment, Contrakt will also run an AI impact analysis after detecting breaking changes — it scans your codebase for consumers of the changed fields and explains what will break and how to fix it.

contrakt doctor

Checks your local setup and tells you the next best command to run.

contrakt doctor

It checks:

  • whether Next.js API routes are present
  • whether contrakt.lock exists
  • whether MCP artifacts were generated
  • whether the project has been published to the registry
  • whether CONTRAKT_TOKEN is available
  • whether monetization is enabled

contrakt publish

Publish your contrakt.lock to the public registry so AI agents and other developers can discover your API.

Options:
  --cwd <path>        Project directory
  --name <name>       Project name on the registry (default: directory name)
  --token <token>     API token (or set CONTRAKT_TOKEN env var)
  --registry <url>    Registry URL override
  --verbose           Debug logging

How to get a token:

  1. Go to contrakt-registry.vercel.app
  2. Sign in with GitHub
  3. Go to DashboardCreate Token
  4. Set export CONTRAKT_TOKEN=<token> in your shell (or pass --token)
export CONTRAKT_TOKEN=your-token
contrakt publish --name my-app
# ✓  Published → https://contrakt-registry.vercel.app/c/username/my-app

Run contrakt publish again after contrakt check --update to keep the registry in sync.

contrakt monetize

Configure x402 payment gating so AI agents can pay per API call in USDC on Base.

# Save local monetization settings and regenerate the MCP server
contrakt monetize \
  --receiver 0xYourBaseWalletAddress \
  --price 0.001 \
  --free-calls 5

# Publish payment metadata to the registry
contrakt publish --name my-app
contrakt monetize --publish
Options:
  --cwd <path>        Project directory
  --receiver <addr>   EVM wallet address on Base that receives USDC
  --price <usd>       Price per API call in USD, e.g. 0.001
  --free-calls <n>    Free calls per agent per day before payment
  --publish           Push monetization config to the registry
  --token <token>     API token for --publish (or set CONTRAKT_TOKEN)
  --registry <url>    Registry URL override
  --disable           Disable payment gating
  --base-url <url>    Override base URL for MCP regeneration
  --verbose           Debug logging

What it does:

  • Writes monetization settings into contrakt.config.json
  • Regenerates .contrakt/contrakt-mcp-server.ts
  • Wraps generated MCP tools with @contrakt/x402-middleware
  • Uses the registry to verify USDC payments and track free-tier usage after contrakt monetize --publish

The generated MCP server still proxies to your app. Your app must be running, and agents call the MCP server. Once the free tier is used, the MCP server requires a valid x402 payment before forwarding the request.

To turn it off:

contrakt monetize --disable
contrakt mcp

contrakt watch <registry-url>

Subscribe to a published registry contract. First run stores the current registry version in contrakt.config.json; future runs notify you when the publisher updates it.

contrakt watch https://contrakt-registry.vercel.app/u/username/my-app
contrakt watch https://contrakt-registry.vercel.app/u/username/my-app --once
Options:
  --cwd <path>              Project directory
  --interval <seconds>      Poll interval for continuous watch (default: 30)
  --once                    Check once and exit 1 if the contract changed
  --depend                  Declare this project as a consumer of the contract
  --consumer-name <name>    Consumer name for --depend
  --consumer-url <url>      Consumer URL for --depend
  --token <token>           API token for --depend (or set CONTRAKT_TOKEN)
  --verbose                 Debug logging

--depend tells the publisher “this project relies on your contract,” so they can see who might break before publishing a change.

contrakt webhook <registry-url> [webhook-url]

Create webhook notifications for a contract you own. The registry sends contract.created and contract.updated events whenever you publish.

contrakt webhook https://contrakt-registry.vercel.app/u/me/my-app https://example.com/contrakt-webhook
contrakt webhook https://contrakt-registry.vercel.app/u/me/my-app --list
contrakt webhook https://contrakt-registry.vercel.app/u/me/my-app --delete <webhook-id>
Options:
  --list              List configured webhooks
  --delete <id>       Delete a webhook by id
  --secret <secret>   HMAC secret for X-Contrakt-Signature
  --token <token>     API token (or set CONTRAKT_TOKEN)
  --verbose           Debug logging

README badges

Published contracts have a badge endpoint:

[![API contract](https://contrakt-registry.vercel.app/badge/username/my-app)](https://contrakt-registry.vercel.app/u/username/my-app)

It shows the current endpoint count and links readers to the live contract page.

contrakt diff <ref>

Diff the current codebase against contrakt.lock at any git ref.

contrakt diff main          # vs main branch
contrakt diff HEAD~1        # vs last commit
contrakt diff v1.2.0        # vs a tag
Options:
  --cwd <path>    Project directory
  --verbose       Debug logging

Exit codes:
  0   No breaking changes vs ref
  1   Breaking changes detected

contrakt mcp

Generates (or regenerates) the MCP server artifacts from contrakt.lock.

Options:
  --cwd <path>        Project directory
  --base-url <url>    Override base URL for this generation only
  --output <path>     Directory to write artifacts (default: .contrakt/)
  --verbose           Debug logging

CI usage

# .github/workflows/api-check.yml
- name: Check API drift
  run: contrakt check

contrakt check exits 1 on breaking changes. It only does static analysis in CI (no running server), which is fine — contrakt.lock is the agreed baseline, committed by a developer after running contrakt check --update locally.

AI impact analysis

Set ANTHROPIC_API_KEY to get automatic impact analysis after breaking changes are detected:

export ANTHROPIC_API_KEY=sk-ant-...
contrakt check

Contrakt will grep your codebase for consumers of the changed fields and call Claude to explain what will break and suggest how to fix it — inline, right after the diff output.

Base URL resolution

Priority order (highest first):

  1. CONTRAKT_BASE_URL env var
  2. --base-url flag
  3. contrakt.config.jsonbaseUrl
  4. Default: http://localhost:3000

Files

| File | Commit? | Purpose | |---|---|---| | contrakt.lock | ✅ Yes | Contract definition — diffed on every check | | contrakt.config.json | Optional | Local config (baseUrl, registry URL) — gitignore if env-specific | | .contrakt/mcp.json | Optional | Claude Desktop config snippet | | .contrakt/contrakt-mcp-server.ts | Optional | Runnable MCP server — regenerate with contrakt mcp |

Using the MCP server

# Start your Next.js app
pnpm dev

# In another terminal, start the MCP server
tsx .contrakt/contrakt-mcp-server.ts

# Override base URL at runtime
CONTRAKT_BASE_URL=https://staging.myapp.com tsx .contrakt/contrakt-mcp-server.ts

Add to Claude Desktop's claude_desktop_config.json:

// paste the contents of .contrakt/mcp.json here

What gets inferred

For each route file:

  • Path — derived from file location (app/api/users/[id]/route.ts/api/users/[id])
  • Methods — exported GET, POST, PUT, PATCH, DELETE functions
  • Path params[id], [...slug] segments
  • Query paramssearchParams.get("key") calls
  • Request body(await req.json()) as MyType → follows the type definition
  • ResponseNextResponse.json({ ... }) → infers from object literal or type
  • Status codes — collected from every NextResponse.json call
  • Description — first sentence of the handler's JSDoc comment

Anything that can't be confidently inferred is marked { "type": "unknown" } rather than guessed. Run contrakt check with your dev server running to fill in those gaps from live responses.

Supported stacks

  • ✅ Next.js App Router (app/api/**/route.ts)
  • ✅ Next.js Pages Router (pages/api/**/*.ts)
  • 🔜 Express
  • 🔜 FastAPI

Registry

Contracts published with contrakt publish are browsable at contrakt-registry.vercel.app.

The registry source is open at github.com/shouryasrivastava/contrakt-registry.

Local development

git clone https://github.com/shouryasrivastava/contrakt
cd contrakt
pnpm install
pnpm build            # compile to dist/
pnpm link --global    # make contrakt available globally
pnpm test             # run integration tests (26 tests)

See CONTRIBUTING.md for how to add framework support and submit PRs.

License

MIT