Skip to main content
AI apps need a lot of API keys, database passwords, and third-party tokens. Sharing .env files is risky, and coding agents shouldn’t see your secrets. The credentials system keeps these secrets encrypted at rest in your repository as YAML files that you commit alongside your code — no external vault subscription needed. At runtime, a single encryption key decrypts everything. Each workflow can have its own scoped credentials that override shared defaults, giving you 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.

Setting Up Credentials

Initialize credentials for your project:
This generates two files:
  • config/credentials.key — your 256-bit encryption key (never commit this)
  • config/credentials.yml.enc — the encrypted YAML file (safe to commit)
Add your secrets by opening the encrypted file in your editor:
The CLI decrypts the file, opens it in $EDITOR, and re-encrypts when you save. Fill in your secrets:
Then read them in any step:
credentials.require() throws a MissingCredentialError if the path doesn’t exist. Use credentials.get(path, defaultValue) when you want a safe fallback instead:

Wiring LLM Keys to Environment Variables

LLM SDKs like the Anthropic and OpenAI clients read their API keys from environment variables. Rather than duplicating these keys in both your .env file and your encrypted credentials, you can wire credentials directly into environment variables using the credential: prefix. In your .env file, set the variable to credential:<dot.path> instead of the actual key:
When the worker starts, it scans process.env for any values starting with credential: and replaces them with the decrypted values from config/credentials.yml.enc. By the time your first workflow runs, ANTHROPIC_API_KEY contains the real key — no code changes needed. This resolution is triggered by the outputai.hookFiles entry in your package.json:
package.json
See Error Hooks for more on the hookFiles mechanism. The worker logs confirmation on startup:
Real environment variable values are never overwritten. If ANTHROPIC_API_KEY is already set in the shell or injected by your CI/CD pipeline, the credential reference is ignored. This gives you a safe override path for production deployments without touching files.

Scoping Credentials to Environments

You likely need different API keys for development and production. The credentials system supports environment-specific files that sit alongside the global defaults:
This creates a config/credentials/ directory with per-environment files:
At runtime, the system checks NODE_ENV and loads the matching environment file. Only "production" and "development" are recognized — other values fall back to the global file. Edit environment-specific credentials the same way:

Scoping Credentials to Workflows

Sometimes a single workflow needs its own secrets — a dedicated API key with different permissions, or a third-party token that only one workflow uses. You can scope credentials to a specific workflow:
This creates credentials files inside the workflow directory:
When a step runs inside this workflow, its credentials are deep-merged over the global ones. Workflow values win at the same path; global values fill in the rest. Global credentials:
Workflow credentials (payment_processing):
What credentials.get() sees inside the workflow:
--environment and --workflow are mutually exclusive flags. Environment scoping applies at the global level; workflow scoping applies per-workflow.

Deploying to Production

In local development, the .key files on disk handle decryption. In production, CI/CD, and Docker — where you don’t have key files — set the decryption key as an environment variable. The system resolves keys with a fallback chain: The resolution order is: environment variable first, then key file. Workflow keys fall back to the global key if neither a workflow-specific env var nor a key file is found.

Docker

The encrypted credentials file must be present in the image — the key alone isn’t enough. Make sure your Dockerfile includes:
The config/ directory is not cleaned up after the build because the encrypted file is read at runtime, not build time. Pass the decryption key as an environment variable in your Docker Compose or container config:

CI/CD

Store the key in your CI provider’s secrets and expose it as an environment variable:

Key Management

Never commit key files

Add this to your .gitignore:
The encrypted .yml.enc files are safe to commit — they can’t be decrypted without the key.

Sharing keys with your team

Key files are created with 0o600 permissions (owner read/write only). Share keys with teammates through a secure channel — a password manager, encrypted messaging, or your organization’s secret sharing tool. Each developer needs the key file at the expected path, or the matching environment variable set.

Rotating keys

To rotate a key:
  1. Decrypt your current credentials: output credentials show > /tmp/creds.yml
  2. Re-initialize with --force to generate a new key: output credentials init --force
  3. Edit and paste your secrets back: output credentials edit
  4. Distribute the new key to your team and update environment variables in production
  5. Securely delete the temporary file: rm /tmp/creds.yml

Verifying credentials

Use the CLI to check that credentials are correctly set up:
For the full API reference, see the @outputai/credentials package documentation.