Project-scoping
Ringtail reads one project's .env.example as the manifest โ and fans each key out across the environment axis.
Ringtail is project-scoped. You point it at a local project and it reads that project's
.env.example as the manifest โ the shopping list of every credential the project needs.
The connection grid is built directly from it: providers ร environments.
Only names and paths cross the boundary during selection โ never file contents, nothing secret.
The .env.example format
Ringtail groups the keys in your .env.example into one provider row per section. You do
not need any special format โ the normal way you already write .env.example works. There are
three ways a key gets grouped, in order:
1. A plain section comment (what most projects already use):
# Database
DATABASE_URL=
## Auth
BETTER_AUTH_SECRET=
# ---- Email ----
RESEND_API_KEY=Each # Header, ## Header, or # ---- Header ---- comment starts a new row. Decorative
dashes/equals/asterisks around the label are ignored, and a prose comment (one containing a
URL, colon, or other sentence punctuation โ e.g. # get this from the dashboard โ) is left as
a plain comment, not treated as a header.
2. The box-drawing section comment (Ringtail's own repos use this โ still supported):
# โโ Cloudflare โโ
CLOUDFLARE_API_TOKEN=
CLOUDFLARE_ACCOUNT_ID=3. No header at all โ Ringtail recognizes the provider from the variable name so a bare
.env.example still splits into real provider rows:
DATABASE_URL= # โ neon
BETTER_AUTH_SECRET= # โ better-auth
RESEND_API_KEY= # โ resend
CLOUDFLARE_API_TOKEN= # โ cloudflare
STRIPE_SECRET_KEY= # โ creem (billing)Known prefixes: DATABASE_URL / POSTGRES* / PG* / NEON* โ neon, RESEND* โ
resend, BETTER_AUTH* โ better-auth, POSTHOG* / NEXT_PUBLIC_POSTHOG* โ posthog,
CLOUDFLARE* / CF_* โ cloudflare, CREEM* / STRIPE* / DODO* โ creem,
INFISICAL* โ infisical. Anything unrecognized and without a header lands in an other
row โ still on the grid, just not auto-mapped to a recipe.
As always, only names are read โ the right-hand side of .env.example holds no values, so
nothing secret is ever touched.
The environment axis
local ยท dev ยท staging ยท prod.
- local โ your machine,
.env.local, localhost. The only environment that touches your disk. - dev ยท staging ยท prod โ deployed. Secrets go to Infisical only, never your disk. Each environment gets its own scoped keys and resources (e.g. a Neon branch per env).
Sink routing follows the axis: local โ .env.local; dev / staging / prod โ Infisical.
syncCredential fans one acquired key out per environment so a single consent provisions the
whole row.
Local credential discovery
Before asking you for anything, Ringtail scans known credential stores โ .env.local,
~/.ringtail, ~/.aws/credentials, ~/.config/gh, ~/.wrangler / ~/.cloudflared, and the
environment โ validates what it finds, reuses complete root grants, and only prompts for real
gaps. Known locations only, local-only, and transparent about what it reused. It never scans
your whole disk.