Skip to main content
AI apps need a lot of API keys. Sharing .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

This generates a random 256-bit encryption key at config/credentials.key and an encrypted YAML file at config/credentials.yml.enc with a starter template.

2. Add your secrets

This decrypts the file, opens it in $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

The credentials 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.
Credentials are loaded and decrypted once per scope (global or per-workflow), then cached for the process lifetime.

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:
  1. Environment variable OUTPUT_CREDENTIALS_KEY (or OUTPUT_CREDENTIALS_KEY_{ENVIRONMENT} for env-specific files)
  2. Key file at config/credentials.key (or config/credentials/{environment}.key)
  3. Throws MissingKeyError if neither is found
Workflow credentials:
  1. Environment variable OUTPUT_CREDENTIALS_KEY_{WORKFLOW_NAME} (uppercased)
  2. Key file at src/workflows/{name}/credentials.key
  3. Falls back to the global key resolution chain
Use environment variables for keys in CI/CD and production deployments. Use key files for local development.

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):
Workflow credentials (src/workflows/my_workflow/credentials.yml.enc):
Merged result (what 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>:
When the worker starts, these references are resolved before any workflow code runs. 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

  1. Worker loads .envANTHROPIC_API_KEY is set to "credential:anthropic.api_key"
  2. Worker reads outputai.hookFiles from package.json and imports each listed file at startup. Including node_modules/@outputai/credentials/dist/hooks.js registers the credential resolution hook:
package.json
  1. Worker calls runStartupHooks()resolveCredentialRefs() scans process.env for credential: prefixed values and replaces each with the decrypted credential
  2. ANTHROPIC_API_KEY is now the real API key string
  3. LLM SDK reads it normally when a workflow activity runs
The worker logs the resolved variable names on startup:

Precedence

Real environment variable values are never overwritten. If ANTHROPIC_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:
The _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.
Never commit .key files to version control. Add *.key to your .gitignore. The encrypted .yml.enc files are safe to commit — they cannot be decrypted without the key.
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) using setProvider():
Returning null from loadForWorkflow means the workflow has no overrides — global credentials are used as-is.

API Reference

For complete TypeScript API documentation, see the Credentials Module API Reference.