creel · masked secret capture into a local .env
creel prompts for a secret in a masked field and writes it
straight into a local .env. The value goes from your keyboard to the file; the
agent that asked for it gets back only a status token saying the key was written — never the
secret itself.
$ creel OPENAI_API_KEY ───────────────────────────────────────────── name OPENAI_API_KEY dest .env value •••••••••••••••••••••••• ───────────────────────────────────────────── ✓ wrote OPENAI_API_KEY → .env
the problem
When a coding agent needs an API key, the obvious move — paste it into the conversation — is the wrong one: the secret lands in the transcript, the context window, and whatever logs sit behind them. creel is the small tool that closes that gap. The agent asks for a named key; you type it into creel; the agent never sees it.
two ways to run it
Run creel bare (or from a tmux keybind) and it prompts for the name, the destination, and the value in a masked field. A name given on the command line is pre-filled.
$ creel # prompts for everything $ creel STRIPE_SECRET # name pre-filled, prompts for the value
Given a name and a status file, creel runs non-interactively for a harness: it captures the
value, upserts it into --dest (default .env), and writes a
status token — added, updated, or an error — to --status-file. The value is
never printed, returned, or logged.
$ creel OPENAI_API_KEY --dest .env --status-file /tmp/creel.status
This is how the pi harness's
request_secret tool works: the agent names the key, creel opens for you to type it,
and the agent reads only the status token back.
then use it
The key is in .env, but a running agent shouldn't read it back: that
puts the value straight into the context creel kept it out of. creel exec runs a
command with the key in its environment only — the value goes from the file to the
child process, never to stdout, argv, or the agent.
$ creel exec OPENAI_API_KEY -- node run.mjs $ creel exec STRIPE_SECRET,OPENAI_API_KEY -- ./deploy.sh
Language-agnostic — it is just the process environment. Strict by default: a
missing key is an error, not an empty value. The command's exit code, signals, and TTY pass
straight through. Prior art: aws-vault exec, sops exec-env.
what it guarantees
The secret lives only in creel's memory and the destination file. It is never echoed to the terminal, returned to a caller, or written to any log.
creel rewrites the one NAME=value line — adding it or replacing it in place —
and leaves the rest of your .env untouched.
Driven by a harness, the destination is resolved against the working directory and rejected if it escapes it — an agent can't redirect your key somewhere unexpected.
The name must be a legal environment variable ([A-Za-z_][A-Za-z0-9_]*), so
the file it writes is always parseable.
install
One command downloads creel, verifies its checksum, and puts it on your PATH
(~/.local/bin). macOS and Linux, Apple silicon and x86-64.
$ curl -fsSL https://tackle.tools/install.sh | sh -s creel # then $ creel OPENAI_API_KEY
Run it again to upgrade; check your version with creel version.
Building from source instead?
go install github.com/subaud-tools/tackle/cmd/creel@latest.