monkeys

.monkeys

A .monkeys file is a project's list of the environment variables it needs, kept next to the code and committed with it.

It is .env.example with the secrets left out: every key the program reads, and the values that were never secret. Commit it. The name is the whole of it, the way .env is: nothing comes before the dot, so .monkeys is the file's name rather than an extension on some other name.

Format

+foo
@test,production
DATABASE_URL
STRIPE_SECRET_KEY
@production
SENTRY_DSN
PORT=80
linemeaning
+foothe namespace, first and at most once
@test,productionopens a block for one profile or several
DATABASE_URLa key whose secret is in the vault, for every profile of the block above it
PORT=80a key with its value set right here, kept in the file and never in the vault
# ...a comment

The first profile mentioned is the default. Three things are refused, with the line quoted: a key listed twice for one profile, a line that comes before any @ line, and a name that is not a key.

Values

A line with = is a value: everything after the =, kept as it is, with no quoting, no ${OTHER} expansion and no second line. That is the part of the dotenv grammar every library agrees on, and anything else is refused with its line number rather than read one library's way. A value belongs to every profile of the block above it, so one that differs by profile goes in that profile's own block:

@test,production
DATABASE_URL
@test
PORT=3000
@production
PORT=80

For one profile a key is a secret or a value, never both; the second line is a duplicate and is refused.

Where it is looked for

From the current directory upward, nearest first, stopping at the root of the git checkout, so a file above the checkout is never read. Outside a checkout only the current directory counts.

A checkout with no file of its own, such as a worktree on a branch cut before the file was committed, reads the one on the default branch: origin/HEAD, then main, then master. That file is only read. A command that would change it says so and changes nothing, the vault included, because the change belongs on the branch that has the file.

Where no file is found either way the commands take keys on the line, as they do anywhere else.

What it replaces

The twelve-factor habit of a .env that is never committed, a .env.example that lists the same keys again by hand, and a .gitignore line that keeps the two apart. .monkeys is one file, it is committed, and the secrets are somewhere a repository cannot reach.

Who writes it

You, or unpack, which writes it at the root of the checkout from a bundle; remember --public adds a value line, and eat fills it from a .env. doctor reads it whole and says what each profile still lacks.

On this page