monkeys
Concepts

Profile

A profile is a named set of secrets. Every secret monkeys stores sits under one, as <profile>/<KEY>, and a project's .monkeys file lists its keys under the…

A profile is a named set of secrets. Every secret monkeys stores 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_KEY

The @ line names the profile and the + line the namespace it sits in, so these three are stored 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, so a .monkeys 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, set stores under the profile, and preview with no keys shows the file's keys:

monkeys run ./hello.sh
monkeys set STRIPE_SECRET_KEY        # stores foo.test/STRIPE_SECRET_KEY
monkeys preview

list 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_DSN

A 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.

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 set @production SENTRY_DSN
monkeys run @prod ./deploy           # production, by its prefix

A 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 .; test, staging and production are the usual three, and the namespace supplies the part before the dot.

No profile

A key stored 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 set TYPESAFE_API_KEY
monkeys run TYPESAFE_API_KEY claude

A 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 set TYPESAFE_API_KEY would write foo.test/TYPESAFE_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 @ TYPESAFE_API_KEY claude
monkeys set @ TYPESAFE_API_KEY
monkeys preview @ TYPESAFE_API_KEY

It is the same secret either way; the @ only says which profile to look in when a file would otherwise decide.

On this page