Store secrets in the OS keychain
A regular env variable lives in plain text inside
envs/<env>.toml. That’s fine for BASE_URL, but not for
PAYMENTS_API_TOKEN or your Postgres password. Marking a variable
as secret changes where it’s stored: OS keychain (Keychain on
macOS, Credential Manager on Windows, Secret Service on Linux), with
only a sentinel value in the TOML / SQLite.
Mark a variable as secret
Section titled “Mark a variable as secret”In the Environment manager (sidebar LuLayers icon → pick env →
click a variable row):
- Click the 🔒 lock toggle next to the value field.
- The first time, httui prompts: “Enter the secret value for
PAYMENTS_API_TOKEN”. Type the real value, hit Enter. - httui stores the value in your OS keychain and writes the sentinel
__KEYCHAIN__toenvs/<env>.toml/ SQLite.
The TOML now looks like:
[vars]BASE_URL = "https://staging-api.example.com"PAYMENTS_API_TOKEN = "__KEYCHAIN__" # real value in keychainYou can safely commit this file — the actual token never touches git.
Reference the secret like any other variable
Section titled “Reference the secret like any other variable”Same {{KEY}} syntax:
```httpGET {{BASE_URL}}/paymentsAuthorization: Bearer {{PAYMENTS_API_TOKEN}}```At run time, httui:
- Sees the reference, looks up
PAYMENTS_API_TOKEN. - Finds the sentinel
__KEYCHAIN__. - Fetches the real value from the OS keychain.
- Substitutes and sends the request.
The Raw tab in the response panel does NOT show the resolved
secret — it’s masked as *** so screen recordings stay safe.
Connection passwords
Section titled “Connection passwords”Same flow for connections.toml. When you add a Postgres connection:
[connections.pg-staging]type = "postgres"host = "pg-staging.acme.local"port = 5432database = "payments"user = "{{keychain:pg-staging:user}}"password = "{{keychain:pg-staging:password}}"ssl_mode = "require"The {{keychain:<scope>:<key>}} syntax tells httui “look this up in
the keychain under <scope> namespace”. The first time a block uses
this connection, httui prompts for the values and stores them.
Sharing connections without sharing secrets
Section titled “Sharing connections without sharing secrets”The connections.toml above commits cleanly — host, port, database,
user/password as references. Your teammate clones the vault, opens
it, and httui sees the references but no keychain entries.
httui shows a “Resolve secrets” banner at the top of the editor:
⚠ This vault references 2 secrets not in your keychain:
pg-staging:user,pg-staging:password. Resolve →
Click → prompt for each → keychain populated. Both machines now run the same runbook against the same connection, but each developer’s password stays on their own machine.
What happens if the keychain is locked / unavailable
Section titled “What happens if the keychain is locked / unavailable”| Situation | Behavior |
|---|---|
| Keychain locked (macOS sleep / Linux not logged in) | First block hits prompt for system password; subsequent blocks in same session reuse the unlocked keychain |
| Keychain entry missing | ”Resolve secrets” banner appears; block won’t run until populated |
| Keychain backend unavailable (CI runner, headless) | httui falls back to plaintext value in TOML / SQLite, logs a warning |
The fallback is intentional — you’d rather have a CI runbook run with secrets injected via env vars than fail because there’s no Keychain.app on the runner.
Rotating a secret
Section titled “Rotating a secret”- Open Environment manager → pick the variable.
- Click the value field (still shows
***). - Type the new value, hit Enter.
- httui overwrites the keychain entry. The sentinel in TOML doesn’t change.
All blocks that reference the variable use the new value on next run — caches keyed on the old value invalidate automatically (the cache key includes a fingerprint of resolved secrets).
Removing a secret
Section titled “Removing a secret”In Environment manager, click the trash icon next to the variable row. httui:
- Removes the keychain entry.
- Removes the line from
envs/<env>.toml/ SQLite.
If a block still references the deleted key, the next run shows a “Resolve secrets” banner with the missing key listed.
Common gotchas
Section titled “Common gotchas”| Symptom | Cause | Fix |
|---|---|---|
Block sends Bearer __KEYCHAIN__ literally | Keychain entry missing; httui couldn’t resolve | Click “Resolve secrets” in the banner |
| Secret value changed but block still uses old value | Stale block cache (unlikely — cache invalidates on env change) | Toolbar gear → “Clear cache” |
| Want to see the actual secret for debugging | The UI masks values intentionally | Open the OS keychain UI (Keychain Access / Credential Manager) |