Skip to content

Using stripekit

stripekit is a CLI that (1) reconciles a declarative stripe.config.ts into the user's own Stripe account and (2) scaffolds correct billing code into a Next.js App Router app. It's plain Stripe underneath — no hosted service, no runtime dependency.

Install-free: every command runs via npx stripekit@latest <command>. Always check npm for the latest version.

Prerequisites

  • Node.js 20+.
  • A Stripe test secret key (sk_test_…) available as STRIPE_SECRET_KEY in the environment or .env.local. Never enter real keys on the user's behalf — ask them to add it.

Full setup in a Next.js app

  1. npx stripekit@latest init — detects the framework + auth library, writes stripe.config.ts, and scaffolds lib/stripe/* (client, sync, customer helpers, storage adapter) and app/api/stripe/* (webhook, checkout, portal). Flags: --adapter kv|drizzle, --auth clerk|authjs|better-auth|none, --yes.
  2. Edit stripe.config.ts to define products, prices, and features.
  3. npx stripekit plan — preview what will change on the Stripe account (read-only).
  4. npx stripekit push — create/update products, prices, webhook endpoint, and portal; writes STRIPE_WEBHOOK_SECRET and STRIPE_PORTAL_CONFIGURATION_ID back to .env.local.
  5. npx stripekit dev — forward Stripe webhooks to localhost during development (wraps stripe listen).
  6. npx stripekit check — verify keys, config, drift, and webhook/portal wiring.

Any stack (catalog only)

Running init in a non-Next.js project sets up only stripe.config.ts. Use plan / push / pull to manage the catalog from any stack.

Config shape

ts
import { defineConfig } from 'stripekit'

export default defineConfig({
  products: {
    pro: {
      name: 'Pro',
      prices: {
        monthly: { amount: 2000, currency: 'usd', interval: 'month' }, // amount in cents
        yearly: { amount: 19200, currency: 'usd', interval: 'year' },
      },
      features: { seats: 5, projects: 'unlimited' },
    },
  },
  portal: { cancellations: true, planSwitching: true },
  webhooks: { path: '/api/stripe/webhook' },
})

Reference prices in app code by their stable lookup keyproduct_price, e.g. pro_monthly — never a Stripe price ID. Amounts can change without touching app code.

Machine-readable output (for agents/CI)

Every command accepts --json.

  • plan --json / push --json{ mode, summary: { create, update, replace, destroy, total }, actions: [{ kind, effect, description }], applied, appliedCount?, envUpdated? }.
  • check --json{ ok, items: [{ label, status, detail }] }.
  • pull --json{ productCount, priceCount, warnings, source }.

Use --yes to skip prompts. To apply to a live account you must pass both --live and --yes; do this only with explicit user confirmation.

Safety invariants

  • push only reads/mutates objects stripekit created (tagged via metadata). Anything the user made by hand in the Stripe dashboard is never touched.
  • Prices are immutable in Stripe: an amount/interval change creates a new price, moves the lookup key onto it, and archives the old one. Existing subscriptions are never disrupted.
  • Removed items are archived, never deleted. Reconciliation is idempotent (apply then re-plan → zero changes).

More

Docs: https://stripe.rafael.ltd/ · Machine index: https://stripe.rafael.ltd/llms.txt · Source: https://github.com/rafaelcg/stripekit

Released under the MIT License.