.env files is risky, and coding agents shouldn’t see your secrets. The @outputai/credentials package keeps API keys, database passwords, and third-party tokens encrypted at rest in your repository. Secrets are stored as encrypted YAML files that you commit alongside your code — no more .env files drifting out of sync between developers, no more external vault subscriptions. At runtime, a single encryption key decrypts everything. Each workflow can have its own scoped credentials that override shared defaults, so you get both team-wide consistency and per-workflow flexibility.
You manage credentials through the CLI and read them in your steps with a simple dot-notation API.
What’s in the Package
Quick Start
1. Initialize credentials
config/credentials.key and an encrypted YAML file at config/credentials.yml.enc with a starter template.
2. Add your secrets
$EDITOR, and re-encrypts on save. Fill in your secrets:
config/credentials.yml.enc (decrypted content)
3. Read credentials in a step
steps.ts
The credentials Object
Thecredentials object is the primary API for reading secrets at runtime.
The
path argument uses dot-notation to navigate nested YAML. For example, 'anthropic.api_key' reads the api_key field under the anthropic key.
Credential Scopes
Credentials are organized into three levels. More specific scopes override broader ones. Global — shared across all workflows:
Environment-specific — per
NODE_ENV (production or development):
Per-workflow — scoped to a single workflow:
Environment is auto-detected from
NODE_ENV. Only "production" and "development" are recognized — other values are ignored. If an environment-specific file doesn’t exist, the system falls back to the default config/credentials.yml.enc.Key Resolution
The system resolves decryption keys using a fallback chain: Global credentials:- Environment variable
OUTPUT_CREDENTIALS_KEY(orOUTPUT_CREDENTIALS_KEY_{ENVIRONMENT}for env-specific files) - Key file at
config/credentials.key(orconfig/credentials/{environment}.key) - Throws
MissingKeyErrorif neither is found
- Environment variable
OUTPUT_CREDENTIALS_KEY_{WORKFLOW_NAME}(uppercased) - Key file at
src/workflows/{name}/credentials.key - Falls back to the global key resolution chain
Credential Merging
When a step runs inside a workflow that has its own credentials file, the workflow credentials are deep-merged over the global credentials. Workflow values override global values at the same path. Global credentials (config/credentials.yml.enc):
src/workflows/my_workflow/credentials.yml.enc):
credentials.get() sees inside the workflow):
CLI Commands
The CLI provides four commands for managing credentials. See CLI for the full reference.Shared Flags
--environment and --workflow are mutually exclusive.Examples
Environment Variable Convention
Many libraries read their API keys from environment variables. Rather than duplicating secrets between your.env file and encrypted credentials, you can wire credentials directly into environment variables using the credential: prefix.
In your .env file, set any environment variable value to credential:<dot.path>:
ANTHROPIC_API_KEY becomes the actual decrypted value from config/credentials.yml.enc, so LLM SDKs and any library reading from process.env work without changes.
How Resolution Works
- Worker loads
.env—ANTHROPIC_API_KEYis set to"credential:anthropic.api_key" - Worker reads
outputai.hookFilesfrompackage.jsonand imports each listed file at startup. Includingnode_modules/@outputai/credentials/dist/hooks.jsregisters the credential resolution hook:
package.json
- Worker calls
runStartupHooks()—resolveCredentialRefs()scansprocess.envforcredential:prefixed values and replaces each with the decrypted credential ANTHROPIC_API_KEYis now the real API key string- LLM SDK reads it normally when a workflow activity runs
Precedence
Real environment variable values are never overwritten. IfANTHROPIC_API_KEY is already set to a non-credential: value (from the shell, CI secret injection, etc.), it is left unchanged. This lets you override credentials at deploy time without modifying files.
The _env Section
New projects are scaffolded with an _env section in the credentials template that documents the intended mapping:
_env section is metadata only — it documents the intent but doesn’t drive resolution. Resolution is driven by the credential: values in .env. Keep both in sync when you add credentials.
Programmatic Access
To call resolution outside the worker startup context:Security
The credentials system uses AES-256-GCM encryption via the@noble/ciphers library. Each encryption generates a unique random nonce, so the same plaintext produces different ciphertext every time.
Additional protections:
- Key files are created with file mode
0o600(owner read/write only) - During
credentials edit, the temporary plaintext file is overwritten with null bytes before deletion
Custom Providers
The default provider reads encrypted YAML files from disk. You can replace it with a custom provider for alternative backends (e.g., AWS Secrets Manager, HashiCorp Vault) usingsetProvider():
Returning
null from loadForWorkflow means the workflow has no overrides — global credentials are used as-is.