How fnox works
fnox maps a named secret in fnox.toml to a resolved value, then passes that value to a command, a shell, or stdout. Providers decide where values come from; profiles and config layering decide which definitions apply.
From configuration to command
When you run fnox exec -- npm start:
- Load configuration. Merge the global configuration and project files, including applicable profile and local files.
- Select definitions. Apply the selected profiles and their inheritance in order.
- Resolve values. Decrypt ciphertext, fetch provider references, or use defaults and existing environment variables.
- Prepare the environment. Apply field selectors, create temporary files for
as_filesecrets, and obtain configured credential leases. - Run the command. Start
npm startwith the resolved environment and clean up temporary resources when it exits.
fnox exec does not change the parent shell. It inherits the existing environment and adds the configured values according to each secret's env setting.
Providers and references
A provider has an instance name, such as op, and a type, such as 1password:
[providers.op]
type = "1password"
vault = "Engineering"
[secrets]
DATABASE_URL = { provider = "op", value = "Database/url" }
LOG_LEVEL = { default = "info" }DATABASE_URL is the environment variable name. op selects the configured provider. Database/url identifies the item and field in 1Password.
For encryption providers such as age, the value field holds ciphertext generated by fnox set, rather than an item reference. You do not need to construct ciphertext by hand.
Local stores such as the OS keychain and KeePass also use references; a reference does not necessarily imply a network request. Conversely, a cloud KMS provider needs network access even though its ciphertext lives in your config.
Resolution order
For an individual secret, fnox tries:
- Provider value. When a
synccache exists, its encryption provider and ciphertext take the place of the original provider lookup. - Default. A
defaultvalue can also supply a fallback when a provider fails. Defaults can reference other secrets. - Existing environment variable. Used when no provider value or default is available.
An individual provider error without a default returns an error before the environment fallback. Commands that resolve multiple secrets apply each secret's if_missing policy to decide whether to stop, warn, or skip it.
After resolution, json_path or line can select part of a provider value. These selectors are mutually exclusive.
Three kinds of cache
| Cache | Stores | Lifetime | Refresh |
|---|---|---|---|
| Sync | Encrypted values in a local config file | Survives restarts | Run fnox sync again |
| Daemon | Resolved values in process memory | Until cleared, invalidated, or the daemon exits | fnox daemon clear |
| Lease ledger | Temporary credentials and lease metadata | Until expiry or revocation | A new lease is created as needed |
These serve different purposes. Sync supports offline use with a local encryption provider. The opt-in daemon avoids repeated reads during a session. Leases replace long-lived credentials with temporary ones when the backend supports expiry.
Inspect a configuration
fnox config-files # Which files are loaded?
fnox profiles # Which profiles exist?
fnox list --sources # Where was each secret defined?
fnox check --all # Can the configured secrets be resolved?See troubleshooting when the result differs from what you expect.