Core concepts
Secrets
Uses the Ahena CLI (beta). Install it with npm install -g @ahena/cli, or prefix commands with npx @ahena/cli. See Installation. The dashboard covers projects, connections, Doctor, the Stack Graph, plans and approvals without it.
ahena env secrets production # names, versions, masked hints
echo -n "$VALUE" | ahena env set production API_KEY
ahena env set production API_KEY # hidden prompt
ahena env unset production API_KEY
ahena env reveal production STRIPE_WEBHOOK_SECRET # prints the value in a terminal
ahena env reveal production STRIPE_WEBHOOK_SECRET --raw # value only, e.g. to pipe into your host
- Never from argv: values come from stdin or a hidden prompt, so they don't end up in shell history.
- Envelope encryption: each value gets its own AES-256-GCM key, wrapped by a master key kept outside the database. The ciphertext is bound to organization, project, environment and name, so it can't be copied to another scope.
- Lists show names only. Revealing a value is a separate, permission-checked, audited action.
- Rotation: setting a secret again creates a new version.
- Secrets created by providers (e.g. a Stripe webhook signing secret) are stored the same way, and only their names are shown in lists.
Revealing a value
ahena env reveal <environment> <name> prints one secret's value. Use it to deploy the webhook
signing secrets Ahena creates with ahena configure stripe / ahena configure resend
(STRIPE_WEBHOOK_SECRET, RESEND_WEBHOOK_SECRET) to your host; the generated webhook routes
return 500 until the variable is set there. You can also copy them from the Stripe or Resend
dashboard.
- Permission-checked by the API:
secrets.reveal(developers and up) outside production,secrets.reveal.production(owners and admins) in production. - Audited: every reveal writes a
secret.revealedevent with the name and version, never the value. - Production asks first in a terminal; without one, pass
--yes. - Terminal only by default: when stdout is a pipe or a file, the command refuses unless you
pass
--raw(the value alone) or--json({ name, environment, version, value }). The CLI never logs the value or puts it in an error. - Never for agents or CI: the API refuses reveal for agent sessions (
ahena mcp) whatever the developer's role, and CI tokens are read-only viewers. The MCP server has no reveal tool. An agent driving your own shell runs as you, so the CLI can't tell it apart from you; the terminal-only default is what keeps the value out of an agent's captured output unless the command explicitly asks for it. - Connection credentials (
provider.<id>.*, e.g.STRIPE_SECRET_KEYyou connected with) can't be revealed. - Connection credentials are stored with their connection and shown there, not as app secrets.
Doctor checks that the secrets your app needs exist (by name) and that environments don't share values.