⭐️ Working with Environments

Moment manages environment variables and secrets through named environments (like production or staging) that you can switch between from the environment selector in the top right of the app.

Values are referenced in request pages and code cells using Mustache syntax like {{env.GITHUB_TOKEN}}, and are injected at runtime. Environment variables and secrets solve the same problem — getting configuration into a running process without hardcoding it — but they live in different places and have different security properties.

An environment is a named bundle of values that any page in the document can read. When you switch environments, every {{env.X}} reference in the document resolves against the new bundle, so the same request page can hit your staging API one moment and production the next without editing a single line.

Moment resolves an {{env.X}} reference by looking through three tiers, in order:

Document Overrides — per-document values stored on your local filesystem. They override anything else for the current document only.

Environment Variables — per-environment values stored on your local filesystem in .env files (e.g., default.env). Never stored in the cloud, and unique to each user.

Workspace Secrets — values stored in the cloud and scoped to the workspace, so every member resolves the same value.

Outbound requests are signed and substituted at the network layer by a built-in proxy, so your JavaScript code never sees the underlying credentials — pages reference {{env.GITHUB_TOKEN}} and the real value is only spliced in once a request leaves the runtime.

Some credentials are handled uniquely as long-lived Integrations. Today, Moment supports AWS as a first-class integration; other integrations, such as for Kubernetes, are under development.

How to Select an Environment

The environment selector at the top right of the Moment window shows the current named environment. When you first start using Moment, the environment is default. Click the selector to open the environments popover, which lists every environment in the current workspace alongside the count of variables and secrets each one provides.

Each row shows a status badge: a green count like 0 vars + 6 secrets means every required value is populated, while a red 1 missing badge means the current document references an {{env.X}} value that is not set in this environment. Click the row to make it active, the pencil icon to edit it, or + New environment to create a new one.

The same popover surfaces Integrations. AWS appears here with a Configure button when you are signed out, or with your account details once you sign in via SSO.

How to Create and Edit Moment Environments

Click the pencil icon next to an environment to open the editor. The dialog is divided into three stacked sections, separated by labeled dividers (↑ OVERRIDES | VARIABLES ↓ and ↑ VARIABLES | CLOUD ↓) so it is always clear where each value lives.

Document Overrides

Document Overrides are values that apply only to the current document and only on your machine. They sit at the top of the resolution order, so an override always wins over an environment variable or workspace secret of the same name. Use them to point a single document at a different backend, swap in a personal token while debugging, or stub a value that a teammate has set as a workspace secret.

Where they live: on your local filesystem, scoped to this document.

How to reference them: with the same {{env.NAME}} syntax used everywhere else.

When to use them: short-lived per-document tweaks, or a deliberate override of a workspace-wide value.

A red error indicator next to an override means the field is empty or references a missing shell variable — the row that drives the 1 missing badge in the environment selector.

Environment Variables

Environment Variables are the per-user, per-environment values you will reach for most often: API keys, bearer tokens, database URLs, and anything else you do not want sitting in JavaScript memory or in a screen recording. They are stored locally in plaintext .env files (for example, default.env) on your filesystem and are never stored in the cloud, so your GITHUB_TOKEN never collides with a teammate's and never leaves your machine.

Where they live: on your local filesystem, in a .env file per environment.

How to reference them: {{env.NAME}} anywhere in a request page (URL, headers, params, body, auth block) or inside a fetch call in a code cell.

When to use them: personal API keys, bearer tokens, database URLs, and any other credential that should belong to you and not the workspace.

The eye icon on each row toggles whether the value is masked in the UI; the trash icon removes the variable.

Workspace Secrets

Workspace Secrets are environment variables shared across the entire workspace. They use the same {{env.NAME}} syntax as the other tiers — a page does not need to know whether a value came from a document override, a local environment variable, or a workspace secret. The difference is where they are stored: workspace secrets live encrypted in the cloud, scoped to the workspace, so every member resolves the same value.

Where they live: in Moment's cloud, scoped to the workspace (the editor displays the workspace name, e.g. moment-eng).

How to reference them: identical to environment variables — {{env.NAME}} in request pages and code cells.

When to use them: shared service accounts, team-wide API tokens, staging database URLs, or any credential that the whole team should hit the same backend with.

A workspace secret is overridden by an environment variable of the same name, which is in turn overridden by a document override — so individual users can shadow team-wide values without changing them for everyone else.

Integrations

Some credentials are handled as long-lived integrations rather than as {{env.X}} variables. AWS is the first-class case today: click Configure in the Integrations section of the environment popover to sign in via SSO. The proxy then signs every outbound AWS call on your behalf using SigV4 — no access keys ever touch an environment. Inside JavaScript request pages, AWS credentials are exposed through env._aws (a runtime object), not through the Mustache namespace.

See ⭐️ Integrating with AWS for the sign-in flow, the shape of env._aws, and worked examples for STS, S3, and other AWS SDK v3 clients. Other integrations, such as Kubernetes, are under development.

Identifying and Providing Missing Variables

When a page in your document references an {{env.X}} value that the active environment cannot resolve, Moment surfaces this in three places, each more specific than the last:

Top bar. A small red dot appears next to the environment name in the top right (e.g. next to Default). It reveals a callout like 1 env var missing, telling you how many references are unresolved without naming them.

Environments popover. Click the selector to open the popover. The offending environment row shows a red 1 missing pill in place of the usual 0 vars + 6 secrets count. Other environments in the same workspace may resolve the value cleanly, in which case switching environments is the fastest fix.

Editor dialog. Click the pencil icon on the row with the red pill. The missing variables appear pre-populated in the Document Overrides section as red-bordered rows, with the variable name (e.g. GITHUB_TOKEN) on the left and an empty value field on the right. The red exclamation icon at the end of the row marks the field as unresolved.

To fix a missing variable, type its value into the right-hand field. The field accepts two forms:

A literal value — paste the API key, token, or URL directly. It will be stored on your local filesystem in this document's override file.

A shell-variable reference — use ${ENV_VAR} (the placeholder text in the field hints at this) to pull the value from the shell environment Moment was launched with. This is the recommended form for credentials you already keep in ~/.zshrc, direnv, or a secret manager that injects into your shell, since the literal value never lands in any Moment-managed file.

Click Save (or press ⌘↵). The red dot in the top bar and the 1 missing pill in the popover will clear once every reference resolves.

If a variable should be available to every document you open, add it as an Environment Variable instead (in the middle section of the editor) so it is shared across all documents in this environment. If it should be available to your whole team, add it as a Workspace Secret in the bottom section.

Why this design

The architectural payoff of routing credentials through the proxy is that secrets stay out of the parts of the system most likely to leak them. A pasted screenshot, a shared .moment directory, an exported HAR file, a console log — none of these contain anything more than {{env.GITHUB_TOKEN}}. The actual secret only exists at the moment a request is on its way to the network, and only inside a process you control.

Splitting values across document overrides, local environment variables, and workspace secrets means each value lives at the smallest reasonable scope. Personal credentials never get committed to a workspace; team credentials never get duplicated into every teammate's .env; and per-document tweaks never leak back into the shared environment.

Combined with version-controlled Markdown pages, this means you can commit and share an entire document — request pages, code cells, dashboards — and collaborators can run it against their own environment without ever seeing yours.

Programming with secrets

Using values in request pages

In a request page, reference any value with {{env.NAME}}. It works in URLs, headers, query params, request bodies, and the auth block:

When the request fires, the proxy walks the resolution order — document override, then environment variable, then workspace secret — and substitutes the real token on its way out. The token never reaches the browser, never appears in DevTools, and never lands in a code cell's value.

Using values in code cells

JavaScript code cells can interpolate {{env.X}} inside fetch calls the same way request pages do — the proxy still handles substitution at the network layer:

The string {{env.GITHUB_TOKEN}} is what the cell sees; the real token is only spliced in once the request leaves the runtime.