monkeys

Spending a value

Storing one looks like this:

monkeys set OPENROUTER_API_KEY
Value:
stored OPENROUTER_API_KEY
give it to a command with:
  monkeys run OPENROUTER_API_KEY <command>

A command that needs two gets both, and nothing else:

monkeys run OPENROUTER_API_KEY,GITHUB_TOKEN ./deploy

Where the variable is expanded

run sets the variable for the command it starts, so that command is what expands it. Written into the monkeys run line itself, your own shell gets there first, and yours does not have the value:

monkeys run OPENROUTER_API_KEY curl -H "Authorization: Bearer $OPENROUTER_API_KEY" ...
# sends: Authorization: Bearer

Single quotes pass the text through untouched, so a shell that run starts is the one that expands it:

monkeys run OPENROUTER_API_KEY sh -c 'curl -H "Authorization: Bearer $OPENROUTER_API_KEY" ...'

A script file works for the same reason, and reads better.

What comes back

run stays between the command and your terminal, and a stored value in the command's output comes back as [redacted NAME]:

monkeys run OPENROUTER_API_KEY sh -c 'echo "key=$OPENROUTER_API_KEY"'
key=[redacted OPENROUTER_API_KEY]

That is the reflex this exists for. An agent that meets an empty variable will echo it, and now the echo says which value was there and nothing else. The exit status and the signals are still the command's own, and the output is streamed as it arrives: a byte is held back only while it could still be the start of a value, and on a terminal that moment shows as * until the next byte settles it.

It catches the value written whole or in pieces, on stdout or stderr. It does not catch the value transformed, so echo $KEY | base64 goes through; this is for the reflex, not for someone trying.

--no-redact turns it off and runs the command in monkeys's place, for the one case that needs the value in the output, such as writing it into a file a program will read:

monkeys run --no-redact OPENROUTER_API_KEY envsubst < template > config

A short stored value is redacted wherever it appears, so store secrets here and keep PORT=3000 in the repository.

A name you have not stored stops the run before it starts:

monkeys run OPENROUTER_API_KEY,ANTHROPIC_API_KEY ./hello.sh
monkeys: ANTHROPIC_API_KEY is not stored yet
nothing ran. a human has to store it, then try again:
  monkeys set ANTHROPIC_API_KEY

That message is written to be passed on. An agent that meets it knows which values are missing, that nothing happened, and what a human has to store.

On this page