Ship faster. Stop debugging missing keys.
Define required API keys, tokens, and connection strings — with context, descriptions and a nice dashboard UI. Claude & Codex will keep on shipping.
npm i secretdefWhich key? Where to get it? Good luck.
Name, description, link — fix it in seconds.
Not a vault. Not a secrets manager. Works alongside Doppler, Vault, Infisical, or plain .env files. A standard way for modules to declare what they need and where to get them. Zero dependencies. ~2KB.
I ship 10x faster now. So I spend 10x more time hunting missing keys.
AI agents write integrations in minutes. Stripe, Resend, a new database — done before lunch. But every deploy became the same loop: crash, check logs, guess which env var is missing, find the right dashboard, provision the key, redeploy. Again for staging. Again for the other project.
I started documenting secrets in infra.md, then CLAUDE.md, then Notion. None of it was there when I needed it — in the terminal, at the moment of failure. My agents couldn't read any of it. And I kept forgetting on which account I provisioned what, where.
So I put the documentation in the code. A spec that says: this app needs STRIPE_SECRET_KEY, here's what it looks like, here's where to get it. One call at startup validates everything. The error message is the documentation — for Claude, for me in 2 years, or the next dev working on this.
— Felix Menard, creator of secretdef
Install the skill, then tell your AI agent to create secret definitions. Works with Claude Code, Cursor, Codex, and more.
Installs the skill for all detected AI tools in your project. Then just say:
TypeError: Cannot read properties of undefined — you guess, redeploy, wait, repeat.
Which keys exist where? Who has the token? Where's the connection string? Nobody knows until it breaks.
It doesn't know which key is missing, where to find it, or how to provision it. Give it context and a good agent can browse the dashboard or run a CLI to get the key itself.
New dev. Stale .env.example. 40 keys. No descriptions. Half are for services you stopped using a year ago.
You list the secrets your app needs — the env var name, a description, and where to get the value. At startup, one call checks everything and tells you exactly what's missing.
// src/secrets.ts
import { defineSecrets } from 'secretdef';
import { secrets as openai } from '@secretdef/openai';
export const secrets = defineSecrets({
...openai,
DATABASE_URL: {
description: 'Postgres connection string',
dashboard: 'https://console.neon.tech',
validate: 'url',
devDefault: 'postgresql://localhost:5432/myapp_dev',
},
});// src/env.ts — validate everything at startup
import { validateSecrets } from 'secretdef';
import { secrets as app } from './secrets';
import { secrets as db } from './modules/db/secrets';
export const env = validateSecrets({
...app,
...db,
});// Or use auto-register — less wiring, same result
import { validateSecrets } from 'secretdef';
import './secrets';
import './modules/db/secrets';
const env = validateSecrets();Community @secretdef/* packages ship ready-made definitions for popular services. Install, import, done.
npm i openai @secretdef/openai secretdef// app entry point
import { validateSecrets } from 'secretdef';
import '@secretdef/openai';
// import '@secretdef/stripe';
// import '@secretdef/resend';
// Validates ALL secrets defined by the imports above
validateSecrets();That's it. All 7 OpenAI env vars — OPENAI_API_KEY, OPENAI_ORG_ID, and more — are now validated at startup with descriptions, dashboard links, and format hints.
secretdef adapts to the environment. You don't need every secret configured to start working locally.
Missing required secrets print an error table and exit the process. No surprises in prod.
Missing secrets print a warning. The server starts. They throw only when code actually reads the missing value.
useSecret() throws a structured error with the var name, description, and dashboard URL.
See all your secrets at a glance. One command.
npx secretdef ui| Name | Status |
|---|---|
OPENAI_API_KEY | ok |
STRIPE_SECRET_KEY | missing |
DATABASE_URL | ok |
RESEND_API_KEY | ok |
STRIPE_WEBHOOK_SECRET | missing |
SENTRY_DSN | ok |
REDIS_URL | ok |
CLERK_SECRET_KEY | invalid |
ANALYTICS_KEY | ok |
This is a preview — run npx secretdef ui for the real thing.
Most SDKs already read process.env internally. Add two lines and missing keys fail on server start — not when a user hits the code path.
Just import + useSecret()
import OpenAI from 'openai';
import { useSecret } from 'secretdef';
import '@secretdef/openai';
// useSecret() throws a rich error if OPENAI_API_KEY is missing
const openai = new OpenAI({ apiKey: useSecret('OPENAI_API_KEY') });process.env.KEY returns undefined silently. useSecret('KEY') tells you what's wrong, where to find the value, and which file declared it. Your agent reads the same output and knows exactly what to do.
import { useSecret } from 'secretdef';
const key = useSecret('STRIPE_SECRET_KEY');
//
// If missing → throws with:
// SecretNotAvailable: STRIPE_SECRET_KEY is not configured.
// Environment variable: STRIPE_SECRET_KEY
// Description: Stripe API secret key
// Where to find it: https://dashboard.stripe.com/apikeys
// Defined in: src/secrets.ts
// Current environment: development
// To fix: set STRIPE_SECRET_KEY in your environment or .env file.
//
// vs: TypeError: Cannot read properties of undefinedYour database module knows it needs DATABASE_URL. Your payment code knows it needs a Stripe key. When each module ships secret definitions, the whole app's requirements become discoverable, validated, and documented — automatically.
For services that don't ship their own definitions yet, the community maintains 1,319+ ready-made @secretdef/* packages. Here are some popular ones:
Plus 123 more verified packages:
Added secret definitions to your SDK or service? Open a PR to add it to the supported list — help others discover it.
Add your serviceThese libraries ship their own defineSecrets() calls natively — just install and import, no @secretdef/* package needed.
Ship your own secret definitions? Add your library to the list.
Add your libraryEvery service below has a ready-made @secretdef/* package you can install today. Each one declares the environment variables the service needs — descriptions, dashboard links, and validation rules included.
npm i secretdefZero dependencies. ~2KB. MIT licensed.