The CLI looks for secrets.config.json (or .secretsrc.json) in the working directory, then in each parent directory up to the repository root. Pass --config <path> to use a specific file. Relative paths in the config resolve against the config file’s directory.
A full example
{
"$schema": "https://secrets.rin.ci/schema.json",
"envFiles": [".env.infisical", ".env.doppler"],
"sources": [
{
"provider": "infisical",
"projectId": "your-project-id",
"environment": "${SECRETS_ENV:-dev}",
"path": "/api"
},
{ "provider": "doppler", "name": "shared", "optional": true },
{ "provider": "dotenv", "name": "local", "path": ".env.local", "required": false }
],
"override": true,
"pure": false,
"keepCredentials": false
}
Top-level keys
| Key | Default | Meaning |
|---|---|---|
sources |
required | Where to read secrets from. At least one. |
envFiles |
[] |
Files holding provider credentials. Missing files are skipped. |
override |
true |
Replace variables already set in the environment. |
pure |
false |
Start the command from a minimal environment plus the secrets. |
keepCredentials |
false |
Pass provider credentials through to the command. |
Unknown keys are an error, so a typo does not silently do nothing.
Sources
Every source has a provider and that provider’s options, listed on its provider page. Four options work on any source:
name: a label for logs and--source. It defaults to the provider name, and must be unique when a provider appears twice.optional: whentrue, a failure is logged and the source is skipped. Otherwise any failure stops the run before the command starts.timeoutMs: the per-request timeout, 15 seconds by default.withhold: extra variable names to remove from your command’s environment, on top of the provider’s own credentials. Use it for the token of a CLI read throughexec.
Merge order
Sources are read in parallel, then merged in the order they are listed. When two sources set the same key, the later one wins. A common layout puts shared values first, the app’s own values next, and a local override file last.
rinci-secrets list shows which source each key came from, and marks the ones another source replaced.
Picking sources per run
rinci-secrets run --source infisical -- bun dev
rinci-secrets run -s infisical -s local -- bun dev
Environments and interpolation
Any string in a source can reference environment variables:
${NAME}is replaced by the variable’s value. If it is unset or empty, that is an error, so a typo cannot point the fetch at the wrong project.${NAME:-fallback}usesfallbackwhen the variable is unset or empty.$$is a literal$.
-e / --env sets SECRETS_ENV for interpolation. That gives one switch for every provider, whatever it calls an environment:
{
"sources": [
{ "provider": "infisical", "projectId": "abc", "environment": "${SECRETS_ENV:-dev}" },
{ "provider": "aws", "region": "eu-west-1", "secretId": "myapp/${SECRETS_ENV:-dev}" },
{ "provider": "doppler", "config": "${SECRETS_ENV:-dev}" }
]
}
Interpolation reads the real environment plus the envFiles, so a credentials file can also hold settings like INFISICAL_PROJECT_ID.
Credential files
envFiles lists dotenv files that hold what the providers log in with. They are read before anything else and follow two rules:
- The real environment wins. A variable already set is not replaced by a file. CI can set credentials directly and skip the files.
- Their contents are only visible to providers and interpolation. They are never added to your command’s environment.
--env-file <path> adds more files from the command line. Unlike config entries, a file passed this way must exist.
The config itself must never contain credentials. Source options named like token, password, clientSecret or privateKey are rejected with an error.
The child environment
The command starts with the current environment, plus the secrets, minus provider credentials.
override(--no-overrideto turn off): whenfalse, a variable that is already set keeps its value, and the run reports which secrets were skipped.pure(--pure): start from a minimal set (PATH,HOME, locale, temp directories and the Windows system variables) instead of everything. Useful to prove an app gets nothing it should not.keepCredentials(--keep-credentials): by default, variables such asINFISICAL_CLIENT_SECRET,DOPPLER_TOKENandVAULT_TOKEN, plus anything a source lists inwithhold, are removed before the command starts. Your app needs the secrets, not the identity that fetched them. General cloud credentials such asAWS_ACCESS_KEY_IDare never removed, because apps often use them directly.
On Windows, variable names are matched without regard to case, as Windows does.
Without a config file
For one provider and a few options, flags are enough:
rinci-secrets run -p doppler -- bun dev
rinci-secrets run -p infisical --set projectId=abc --set environment=prod -- bun start
--set only takes string values. Use a config file for lists and maps.
Editor support
The $schema line gives autocomplete and validation in VS Code, Cursor and any editor that reads JSON Schema. The schema is served at /schema.json and ships in the package as @rinci/secrets/schema.json.