Profile
A profile is a named set of secrets.
Every secret monkeys remembers sits under one, as <profile>/<KEY>, and a
project's .monkeys file lists its keys under the profiles they belong to:
+foo
@test
DATABASE_URL
STRIPE_SECRET_KEY
OPENROUTER_API_KEYThe @ line names the profile and the + line the namespace it sits in, so
these three are remembered as foo.test/DATABASE_URL and so on. The keys are the
project's and the secrets are yours. Everyone who clones the repository gets
the same profile and the same keys, and each of them fills their own vault.
That is why the file can be committed and a vault never has to be.
The default profile
The first profile a .monkeys file mentions is the default, the one every
command uses in that project when none is given. Inside the checkout, run
takes only the command, remember writes under the profile, and preview with no
keys shows the file's keys:
monkeys run ./hello.sh
monkeys remember STRIPE_SECRET_KEY # remembers foo.test/STRIPE_SECRET_KEY
monkeys previewlist shows the whole vault as blocks by profile, so you can see what each
one holds.
Several profiles
A profile line can name several profiles, and a file can hold several blocks:
+foo
@test,production
DATABASE_URL
STRIPE_SECRET_KEY
@production
SENTRY_DSNA profile's keys are those of every block that lists it: both profiles here
need DATABASE_URL and STRIPE_SECRET_KEY, and production also needs
SENTRY_DSN. The default is still the first, test, so production is
something you say.
A secret missing in one profile stops only that profile, and only when it is
used: production can be half filled while test runs. doctor shows the
whole picture.
The usual names
A name is yours to choose, and monkeys never checks one against a list.
These four are what projects tend to mean, and a name the reader already
knows needs no explanation:
+foo
@test,staging,production
DATABASE_URL
@production
SENTRY_DSN
@personal
OPENROUTER_API_KEYtest holds the keys that can leak without anyone being woken, production
the real ones, and staging a deployment that is not production, for the
projects that have one.
test goes at the top, and goes there even when it arrives after the others,
unless whoever asked for it says where it belongs. The first profile is the
one a command takes when none is given, so the default is the harmless one
and production is something you say.
personal is a key each person holds their own copy of rather than one the
team shares, a seat on an API they pay for themselves. It belongs in the file
because the project needs it, so doctor names it in a fresh checkout, and
pack asks before a bundle carries it away. A key that is yours in every
project rather than in this one has no profile at all.
Write the names in full, not prod or dev. A prefix is enough to type, so
@p already reaches @production, and the file stays readable for whoever
did not write it.
Choosing a profile
Any command takes a leading @profile, which picks another declared one. A
prefix that fits only one of them is enough, the way a short git hash is:
monkeys run @production ./deploy
monkeys remember @production SENTRY_DSN
monkeys run @prod ./deploy # production, by its prefixA profile the file does not declare is refused with the declared ones listed,
and a prefix that fits several is refused with those, so a typo never becomes
a new profile. A profile name is words of letters, digits, _ and -,
joined by ., and the namespace supplies the part before the dot.
No profile
A key remembered outside any project has no profile and needs no @. That is
where a secret that belongs to you rather than to a project lives, such as
the one a tool you start from anywhere reads:
monkeys remember ANTHROPIC_API_KEY
monkeys run ANTHROPIC_API_KEY claudeA project profile never reads from the keys with no profile. A key missing
in @production is missing there even when a copy with no profile exists,
so a project cannot quietly pick up a secret meant for another.
Inside a project every command is scoped to that project's profile, so the
keys with no profile are out of reach there: monkeys run reads foo.test/,
and monkeys remember ANTHROPIC_API_KEY would write foo.test/ANTHROPIC_API_KEY.
A bare @ means no profile. It sets the project file aside, so keys are
given again, and reaches those keys without leaving the directory:
monkeys run @ ANTHROPIC_API_KEY claude
monkeys remember @ ANTHROPIC_API_KEY
monkeys preview @ ANTHROPIC_API_KEYIt is the same secret either way; the @ only says which profile to look in
when a file would otherwise decide.