Skip to content

Environment variables

Set a variable on an App and every Function in that App reads it. Variables belong to the App rather than to any one Function, so a key you set today is there for the Function you add next week.

We read them when a Function runs, not when you deploy. Set a value now and the next request has it. No build runs and no version is made. That is also why rolling a Function back to last week’s code does not take last week’s API key with it.

npx wawesome env set GREETING hello
[wawesome] ✅ Set variable 'GREETING' on app 'demo'.

The App comes from wawesome-function.json in the current directory. None of these commands take --app, so you run them from the project, or you use the dashboard.

Your handler reads the value off process.env:

export default {
  async fetch(): Promise<Response> {
    return Response.json({ message: process.env.GREETING });
  },
};

Your Function does not run on Node, and the engine underneath has no process at all. We install process.env before your module is evaluated, so the line above works even though the rest of process is still missing. A key nobody set reads as undefined rather than throwing.

npx wawesome env list
📋 Environment variables for 'demo'

KEY               | VALUE            | SECRET
------------------|- ---------------- |-------
GREETING          | hello            | false
STRIPE_SECRET_KEY | ****4242         | true
SUPPORT_EMAIL     | support@hello.co | false

A readable variable prints in full. A secret prints as a mask of its last four characters, and only when the value is longer than eight. Anything shorter comes back as **** and nothing else, because four characters of a six-character value is most of it. Those four characters let you tell a live Stripe key from a test one without reading either.

An App with nothing on it prints one line instead of a table:

[wawesome] No environment variables set for app 'demo'.
npx wawesome env rm GREETING
[wawesome] ✅ Deleted variable 'GREETING' from app 'demo'.

The next invocation reads undefined. A key that was not there to begin with is an error, so a typo does not report success:

[wawesome] Error: Variable 'GREETNIG' not found on app 'demo'.

--secret stores the value write-only:

npx wawesome env set STRIPE_SECRET_KEY sk_live_51NxAbCdEfGh4242 --secret
[wawesome] ✅ Set secret variable 'STRIPE_SECRET_KEY' on app 'demo'.

🔒 Secret Notice:
  • Encrypted at rest using AES-256
  • This value can't be viewed again after you save it — only updated or deleted
  • Only decrypted at the moment your function runs — never returned by the CLI, dashboard, or API after creation.

That notice comes from the gateway, not from the CLI, so it says what we do rather than what a client believes. The value is encrypted under a key belonging to that one App. A running Function is the only thing we ever hand it back to. The response to the write above is already masked, and so are the listing, the dashboard and the API. No flag reveals it.

--secret describes the write rather than the key. Setting the same key again without the flag stores the new value readable, so keep the flag on every write of a value that should stay write-only.

Your Function has not lost it. The copy we hold still runs, and goes on running until you replace it. What you lost is your own copy, and that is the one to replace.

Go back to whoever issued the value and have them issue another. Then set it again under the same key. env set on a key that already exists overwrites it, and the request after that carries the new value. There is no step where we hand the old one back.

env list shows every readable value in full to anyone who can run it against the App. The dashboard shows the same thing under the Secrets tab on the App’s page, split into Secrets and Environment Variables.

An agent holding write:env can set a variable over MCP. The value travels through the conversation, and through whatever the chat product keeps of it. That is fine for a feature flag and wrong for an API key. Type a real secret in at the dashboard yourself.

An agent holding read:env can list an App’s variables over MCP. It sees every key and when it was set, and the value of each plain variable. It never sees any part of a secret’s value, not even the last characters the dashboard shows.

A template declares the variables its code reads. It ships no .env.example and no placeholder to find and replace. npx wawesome init --template <name> asks you for each one before it deploys, rather than after the first request fails:

[wawesome] This template needs a few values before it can run.

  STRIPE_WEBHOOK_SECRET (required, stored write-only)
    Signing secret for this webhook endpoint. Every request is rejected unless it carries a signature made with it.
    Where to find it: Stripe Dashboard → Developers → Webhooks → your endpoint → "Signing secret" → Reveal. It starts with whsec_.
  STRIPE_WEBHOOK_SECRET?:

The description and the Where to find it line are the template’s own words. That is how the CLI can point you at a screen in somebody else’s dashboard.

Press enter and it moves on. Blank is the right answer more often than it sounds. A Stripe webhook secret does not exist until the endpoint does, and you create that endpoint with the URL this command is about to print. You get the command to run once the value exists:

[wawesome] STRIPE_WEBHOOK_SECRET left blank. Set it with: wawesome env set STRIPE_WEBHOOK_SECRET <value> --secret

A value you did type is stored before the deploy, under the flag the template declared for it:

[wawesome] ✅ Stored OPENAI_API_KEY (secret).
[wawesome] ✅ Enabled outbound calls to 'openai'.

A variable holding somebody’s API address does not make the call to it allowed. An App reaches the providers it subscribes to and the hosts on its allowlist. Both live under Egress on the App’s page in the dashboard. init --template subscribes the App to the providers a template declared, which is the Enabled outbound calls line above. For a variable the template marks as naming a host, it also adds that host to the allowlist, and so does a later env set on that variable. Outbound calls is the page for the rest of it.