Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

What it is

cred is a command-line tool that stores encrypted secrets locally and pushes them to deployment platforms on demand.

⚠️ Status: Early Preview (v0.16.0)

cred is currently in active development. The on-disk format, CLI surface, and security model may change between minor versions. Do not rely on it as your sole secrets backup yet.

What it is not

  • A hosted secrets manager
  • A multi-user or multi-machine tool
  • A replacement for HashiCorp Vault or AWS Secrets Manager
  • A runtime secret injector for applications

Who is this for

  • Solo developers managing secrets on a single machine
  • Open-source maintainers who push secrets to deployment platforms
  • Anyone who wants local-first secrets without running infrastructure

Why cred exists

Managing secrets in projects and deployment platforms is a mess and a chore.

cred solves this by giving you:

1. An Encrypted Vault per Project

Your secrets live inside .cred/vault.enc as an encrypted store with per-secret metadata (format, timestamps, description, source, version history).

2. Environment Namespacing

Organize secrets by deployment context:

cred env create prod
cred secret set DATABASE_URL "postgres://prod..." --env prod
cred push github --env prod

3. Version History & Rollback

Every secret update is tracked. Roll back to any of the last 10 versions:

cred secret history API_KEY
cred secret rollback API_KEY --version 0 --yes

4. Sources and Targets

cred distinguishes between sources (where credentials come from) and targets (where secrets are pushed to):

  • Sources: Platforms that can programmatically generate credentials (e.g., Resend API keys)
  • Targets: Platforms where you push secrets for deployment (e.g., GitHub Actions secrets)

5. Secure Key Storage

Your encryption key is stored in your OS credential store (Keychain, GNOME Keyring, Windows Credential Manager). Nothing sensitive is written to plaintext files.

Supported sources:

  • Resend (API key generation)

Supported targets:

  • GitHub (Actions secrets)
  • Vercel (Environment variables)
  • Fly.io (App secrets)

Installation

Homebrew (macOS)

brew tap edneedham/cred
brew install edneedham/cred/cred

Quick install (shell)

curl -fsSL https://raw.githubusercontent.com/edneedham/cred/main/scripts/install.sh | sh -s

Install with Cargo:

cargo install cred

Pre-built binaries

Download the latest release for your platform from GitHub Releases.

Available binary targets:

  • cred-vX.Y.Z-aarch64-apple-darwin - macOS Apple Silicon
  • cred-vX.Y.Z-x86_64-apple-darwin - macOS Intel
  • cred-vX.Y.Z-x86_64-unknown-linux-gnu - Linux x86_64
  • cred-vX.Y.Z-x86_64-pc-windows-msvc.exe - Windows

Make the binary executable and move it to your PATH:

chmod +x cred-*
sudo mv cred-* /usr/local/bin/cred

Check installation:

cred --version

Getting Started

Get from zero to your first secret push in under 5 minutes.

1. Initialize your project

cred init

This creates .cred/vault.enc in your project and stores the encryption key in your OS credential store.

cred automatically detects targets from your project:

Initialized new cred project at .cred/
πŸ”‘ Encryption key generated and stored in the System Credential Store
πŸ“ Detected targets:
   github: owner/repo

   Run 'cred target set <target>' to authenticate each target.

2. Authenticate a target

cred target set github

You’ll be prompted for a fine-grained PAT with Actions secrets permission. The token is stored per-project, so each project can use different tokens (important for fine-grained PATs scoped to specific repos).

3. Store a secret

cred secret set DATABASE_URL "postgres://user:pass@localhost/db"

4. Push to GitHub

Preview first:

cred push github --dry-run

Then push:

cred push github

No --repo flag needed β€” cred uses the target binding saved during init.

Done! Your secret is now in GitHub Actions.


Working with Environments

Organize secrets by environment (dev, staging, prod):

# Create environments
cred env create staging
cred env create prod

# Set secrets in specific environments
cred secret set DATABASE_URL "postgres://prod..." --env prod

# Push prod secrets to GitHub
cred push github --env prod

See env command for more details.


Next steps:

Migrating

Upgrading from v0.13.x to v0.14.0

v0.14.0 introduces first-class target scoping for secrets.

What Changed

  • Secrets can now be scoped to specific targets via cred secret set --targets ...
  • cred push / cred prune respect those scopes by default
  • Existing secrets are unscoped by default (no behavior change until you add scopes)

For projects where some targets are β€œfrontend only” (e.g. Vercel), start scoping the relevant secrets:

# Public frontend variables (Vercel only)
cred secret set NEXT_PUBLIC_API_URL "https://..." --targets vercel

# Backend secrets (GitHub only)
cred secret set DATABASE_URL "postgres://..." --targets github

If you ever need to override scoping for a one-off push/prune, use --force.

Upgrading from v0.12.x to v0.13.0

v0.13.0 introduces per-project target tokens. Your existing vaults and secrets are unchanged, but target authentication needs to be re-configured.

What Changed

Before (v0.12.x)After (v0.13.0)
One global token per targetPer-project tokens
cred target set stored globallycred target set stores per-project
--repo/--app flags often neededTarget bindings saved in project

Migration Steps

In each of your cred projects:

cd your-project

# Re-authenticate targets (tokens now stored per-project)
cred target set github --token <your-fine-grained-pat>

# Verify target bindings were auto-detected or set them manually
cred target list

# If needed, bind targets manually
cred target bind github owner/repo
cred target bind fly my-app

Why This Change?

Modern fine-grained tokens (like GitHub PATs) are scoped to specific repos. A token for repo-a cannot access repo-b. Per-project token storage properly supports this security model.


Migrating Existing Secrets to cred

If you choose to migrate to cred instead of continuing with manual .env files you’ll need the original values from wherever you stored them (password manager, .env files, etc.).

Migration Steps

1. Initialize cred:

cred init

2. Import your secrets:

From a .env file:

cred import .env

Or add individually:

cred secret set DATABASE_URL "postgres://..."
cred secret set API_KEY "sk-..."

Tip: Use environments to organize secrets by deployment context:

cred env create prod
cred import prod.env --env prod

3. Set up the GitHub target:

cred target set github

4. Push to GitHub:

Preview first:

cred push github --dry-run

Then push:

cred push github

Your existing workflows continue working unchanged β€” they reference secrets by name, and cred pushes to the same location.

Why Migrate?

Before (manual)After (cred)
Secrets in .env files or notesSingle encrypted vault
Copy-paste into GitHub UIcred push github
No visibility into what’s deployedcred status shows everything
Hard to sync across reposPush to multiple targets

Concepts

cred is built around three core concepts that work together to manage your secrets.

Vault

The vault is your local encrypted secrets store. Each project has its own vault at .cred/vault.enc containing all your secrets with metadata like format, timestamps, and descriptions.

Learn more about the Vault β†’

Sources

Sources are platforms that can programmatically generate credentials. Instead of manually creating API keys, you can have cred generate them for you with the appropriate permissions.

Currently supported:

  • Resend β€” Email API key generation

Learn more about Sources β†’

Targets

Targets are platforms where you push secrets for deployment. cred uploads your vault secrets to these platforms so your workflows can access them directly.

Currently supported:

  • GitHub β€” Actions secrets
  • Vercel β€” Environment variables
  • Fly.io β€” App secrets

Learn more about Targets β†’


How They Work Together

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     generate      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      push       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Source    β”‚ ───────────────►  β”‚    Vault    β”‚ ──────────────► β”‚   Target    β”‚
β”‚  (Resend)   β”‚                   β”‚ (encrypted) β”‚                 β”‚  (GitHub)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β–²
                                        β”‚ manual set
                                        β”‚
                                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                  β”‚     You     β”‚
                                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. Sources generate credentials and store them in your vault
  2. You can also manually add secrets to the vault
  3. Targets receive secrets when you push from the vault

Sources

Sources are platforms that can programmatically generate credentials. Unlike targets (which only receive secrets), sources create new API keys on demand.

Why Use Sources?

Instead of manually creating API keys in a web dashboard and copy-pasting them, sources let you:

  • Generate keys directly from the command line
  • Automatically store them in your vault with proper metadata
  • Track which keys came from which source
  • Revoke all generated keys at once when needed

Adding a Source

Add your master API key:

cred source add resend --token "$RESEND_API_KEY"

Or interactively (will prompt for token):

cred source add resend

The master token is stored securely in your OS credential store (keyring), not in plaintext files.

Generating Credentials

Generate a new API key from the source:

cred source generate resend RESEND_EMAIL_KEY --permission sending_access -d "Email service key"

This creates a new API key via Resend’s API and stores it in your vault with source: resend metadata.

Managing Source Keys

List API keys at the source:

cred source keys resend

Delete a generated key (removes from source AND local vault):

cred source delete resend RESEND_EMAIL_KEY --yes

List configured sources:

cred source list

Revoking a Source

Revoke source authentication (deletes all generated keys and removes master key):

cred source revoke resend --yes

This will:

  1. Delete all API keys generated from this source at Resend
  2. Remove them from the local vault
  3. Remove the stored master key

Resend

Resend is an email API service. cred can generate API keys with specific permission levels.

Permission Levels

PermissionDescription
full_accessCan create, delete, get, and update any resource
sending_accessCan only send emails (recommended for most use cases)

Example

# Add your master key (needs full_access to create other keys)
cred source add resend

# Generate a restricted key for your app
cred source generate resend EMAIL_API_KEY --permission sending_access

# Push to GitHub Actions
cred push github

Why Sources Use Master Keys

Sources authenticate with a master API key that has permission to create additional keys. The generated keys can have narrower scopes (e.g., sending_access only), following the principle of least privilege.

Your application never sees the master key β€” it only gets the restricted key you generated.

Targets

Targets are platforms where you push secrets for deployment. cred uploads your vault secrets to these platforms so your workflows can access them directly.

How It Works

Your machine              Target platform          Your workflow
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚  cred   │──push───────►│   GitHub     │◄────────│ workflow β”‚
 β”‚ (vault) β”‚               β”‚   Secrets    β”‚  reads  β”‚          β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. You run cred push github on your dev machine
  2. cred uploads secrets to GitHub Actions
  3. Your workflows read secrets directly from GitHub β€” no cred involved

Per-Project Tokens

As of v0.13.0, target tokens are stored per-project, not globally. This properly supports fine-grained tokens (like GitHub PATs scoped to specific repos).

Each project has its own:

  • Target bindings β€” the identifier for each target (repo, app, project ID)
  • Target tokens β€” authentication credentials stored in OS keyring

This means:

  • Project A can use a GitHub PAT scoped to owner/repo-a
  • Project B can use a different PAT scoped to owner/repo-b
  • No token conflicts or accidental cross-project access

Target Bindings

Target bindings are saved in .cred/project.toml during cred init (auto-detected) or via cred target bind:

# .cred/project.toml
[targets]
github = "owner/repo"
fly = "my-app"
vercel = "prj_xxxxx"

Bind a target manually:

cred target bind github owner/repo
cred target bind fly my-app
cred target bind vercel prj_xxxxx

Once bound, you don’t need --repo, --app, or --project flags when pushing.

Target-Scoped Secrets (v0.14.0+)

Secrets can optionally be scoped to specific targets. This is useful when, for example, your Vercel target is β€œfrontend only” and you want to avoid pushing backend secrets there.

  • Unscoped secrets (default): eligible for all targets
  • Scoped secrets: only eligible for the listed targets

Set scopes when writing a secret:

cred secret set NEXT_PUBLIC_API_URL "https://..." --targets vercel
cred secret set DATABASE_URL "postgres://..." --targets github,fly

cred push <target> and cred prune <target> respect these scopes by default. Use --force to override.

Adding a Target

Authenticate a deployment target (must be inside a cred project):

cred target set github

You will be securely prompted for a token. The token is stored in your OS credential store, scoped to this project.

Managing Targets

List configured targets for this project:

cred target list

Output shows binding and authentication status:

Project Targets:
  βœ“ github = owner/repo
  βœ— fly = my-app

Run 'cred target set <target>' to authenticate.

Revoke a target:

cred target revoke github --yes

GitHub

GitHub Actions secrets are the primary target for cred. Secrets you push become available to your workflows.

Setup

  1. Create a fine-grained Personal Access Token at github.com/settings/tokens
  2. Select only the repository you want to manage
  3. Grant only the Actions secrets permission (read and write)
  4. Add the token to cred:
cred target set github

Pushing Secrets

# Push all secrets
cred push github

# Push specific secrets
cred push github DATABASE_URL API_KEY

cred automatically detects your repository from git metadata. If you’re not in a git repository, specify it explicitly:

cred push github --repo owner/repo

Using Secrets in Workflows

Once pushed, secrets are available in your GitHub Actions:

jobs:
    deploy:
        runs-on: ubuntu-latest
        env:
            DATABASE_URL: ${{ secrets.DATABASE_URL }}
        steps:
            - run: echo "Secret is available"

Vercel

Push environment variables to Vercel projects. Secrets you push become available to your deployments.

Setup

  1. Create an Access Token at vercel.com/account/tokens
  2. Grant Full Account scope (required for environment variable management)
  3. Add the token to cred:
cred target set vercel

Linking Your Project

cred auto-detects your Vercel project from .vercel/project.json (created by vercel link). If you haven’t linked:

vercel link

Or specify the project ID explicitly:

cred push vercel --project prj_xxxxxxxxxxxxx

Environment Mapping

cred environments map to Vercel targets:

cred envVercel target
prodproduction
defaultdevelopment
otherspreview
# Push to Vercel production
cred push vercel --env prod

# Push to Vercel development (default)
cred push vercel

Using Secrets in Deployments

Once pushed, environment variables are automatically available in your Vercel deployments:

// Next.js example
const apiKey = process.env.API_KEY;

Fly.io

Push secrets to Fly.io apps. Secrets you push become available to your deployed applications.

Setup

  1. Create a Personal Access Token at fly.io/user/personal_access_tokens
  2. Add the token to cred:
cred target set fly

Linking Your App

cred auto-detects your Fly.io app from fly.toml (created by fly launch). If you haven’t launched:

fly launch

Or specify the app name explicitly:

cred push fly --app my-app-name

Pushing Secrets

# Push all secrets
cred push fly

# Push specific secrets
cred push fly DATABASE_URL API_KEY

# Push to a specific app
cred push fly --app my-app-name

Applying Secrets

After pushing secrets, Fly.io requires a deployment to apply them:

fly deploy
# or
fly secrets deploy

Using Secrets in Your App

Once deployed, secrets are available as environment variables:

// Node.js example
const apiKey = process.env.API_KEY;
# Python example
import os
api_key = os.environ.get("API_KEY")

Why Targets Use Simple Tokens

Targets need minimal permissions β€” just enough to write secrets. This follows the principle of least privilege.

Unlike sources (which need elevated permissions to generate new credentials), targets only need write access to a specific resource (e.g., GitHub Actions secrets for one repository, Vercel environment variables for one project).

Vault

The vault is your local encrypted secrets store. Each cred project has its own vault containing all secrets with rich metadata, organized by environment.

Structure

When you run cred init, cred creates:

.cred/
β”œβ”€β”€ project.toml    # Project metadata
└── vault.enc       # Encrypted secrets

Global configuration lives at:

~/.config/cred/global.toml

Environments

Secrets are organized into environments (e.g., default, staging, prod). This allows you to manage different configurations for different deployment contexts.

# List environments
cred env list

# Create an environment
cred env create prod

# Set a secret in an environment
cred secret set DATABASE_URL "postgres://..." --env prod

By default, secrets are stored in the default environment.

See cred env for more details.

Secret Metadata

Each secret in the vault includes:

FieldDescription
keyThe secret name (e.g., DATABASE_URL)
valueThe encrypted secret value
formatContent format (raw, json, pem, etc.)
created_atWhen the secret was first added
updated_atWhen the secret was last modified
descriptionOptional human-readable description
sourceWhere it came from (manual or a source name)
historyUp to 10 previous versions (for rollback)

Secret Formats

cred auto-detects the format of your secrets:

FormatDetectionExample
pemStarts with -----BEGINCertificates, private keys
jsonValid JSON object or array{"key": "value"}
base64Single-line base64 contentSGVsbG8gV29ybGQ=
multilineContains newlinesMulti-line text
rawEverything else (default)super-secret-value

You can also specify format explicitly:

cred secret set MY_KEY "value" --format json

Viewing the Vault

List all secrets:

cred secret list

Output:

Vault content:
  API_KEY = ***** (OpenAI production key)
  DATABASE_URL = *****
  JWT_SECRET = ***** [modified]

Get a specific secret:

cred secret get JWT_SECRET

With full metadata (JSON):

cred secret get JWT_SECRET --json
{
    "data": {
        "key": "JWT_SECRET",
        "value": "super-secret",
        "format": "raw",
        "created_at": "2025-12-11T12:00:00Z",
        "updated_at": "2025-12-11T12:00:00Z",
        "description": null
    }
}

Version History

cred automatically tracks up to 10 previous versions of each secret. View history and rollback:

# View version history
cred secret history DATABASE_URL

# Rollback to previous version (0 = most recent)
cred secret rollback DATABASE_URL --version 0 --yes

See cred secret history for more details.

Hub-and-Spoke Status

For a complete overview of your project:

cred status
Vault: 5 secrets (2 environments)

Environment: default
  RESEND_API_KEY       [resend]
  DATABASE_URL         [manual]

Environment: prod
  DATABASE_URL         [manual]
  JWT_SECRET           [manual]
  API_KEY              [manual]

Sources: resend βœ“
Targets: github βœ“

Encryption

The vault is encrypted at rest using ChaCha20-Poly1305. The encryption key is generated on cred init and stored in your OS credential store (Keychain, GNOME Keyring, etc.). See Security Model for details.

Best Practices

  1. Add .cred/ to .gitignore β€” Never commit your vault
  2. Use descriptions β€” Document what each secret is for
  3. Use environments β€” Separate dev/staging/prod secrets
  4. Keep backups β€” Export periodically with cred export
  5. Use sources when possible β€” Generated keys have better audit trails
  6. Review history before rollback β€” Use cred secret history first

Commands

Complete reference for all cred commands.

Project Management

CommandDescription
cred initInitialize a new cred project
cred statusShow vault, sources, and targets overview
cred doctorCheck project health

Secrets

CommandDescription
cred secret setAdd or update a secret
cred secret getRetrieve a secret value
cred secret listList all secrets
cred secret removeDelete a secret from vault
cred secret describeUpdate a secret’s description
cred secret historyView version history for a secret
cred secret rollbackRestore a previous version
cred importImport from .env file
cred exportExport to .env file

Environments

CommandDescription
cred env listList all environments
cred env createCreate a new environment
cred env deleteDelete an environment and its secrets

Deployment

CommandDescription
cred pushPush secrets to a target
cred pruneDelete secrets from a target

Sources

CommandDescription
cred source addAdd a credential source
cred source generateGenerate a new credential
cred source keysList keys at the source
cred source deleteDelete a generated key
cred source listList configured sources
cred source revokeRemove source and all its keys

Targets

CommandDescription
cred target setAuthenticate with a target
cred target bindBind target identifier to project
cred target listList configured targets
cred target revokeRemove a target’s token

Configuration

CommandDescription
cred config listView all configuration
cred config getGet a config value
cred config setSet a config value
cred config unsetRemove a config value

Global Flags

All commands support these flags:

FlagDescription
--jsonMachine-readable JSON output
--non-interactiveFail instead of prompting for input
--dry-runPreview changes without applying them
--helpShow help for any command

init

Initialize a cred project.

Usage

Initialize a new cred project in the current directory:

cred init

This creates:

.cred/
β”œβ”€β”€ project.toml    # Project configuration (includes target bindings)
└── vault.enc       # Encrypted secrets vault

Run this once per project, typically at the repository root.

What Happens

  1. Creates the .cred/ directory
  2. Generates a random 32-byte encryption key
  3. Stores the key in your OS credential store (Keychain, GNOME Keyring, etc.)
  4. Creates an empty encrypted vault
  5. Adds .cred/ to .gitignore
  6. Auto-detects target bindings from your project

Auto-Detection

cred automatically detects and saves target bindings during init:

TargetDetection Source
GitHubGit remote (git@github.com:owner/repo.git)
Fly.iofly.toml (app = "my-app")
Vercel.vercel/project.json (projectId)

Example output:

Initialized new cred project at .cred/
πŸ”‘ Encryption key generated and stored in the System Credential Store
πŸ“ Detected targets:
   github: owner/repo
   fly: my-app

   Run 'cred target set <target>' to authenticate each target.

These bindings are saved in .cred/project.toml:

name = "my-project"
version = "0.1.0"
id = "..."
git_repo = "owner/repo"

[targets]
github = "owner/repo"
fly = "my-app"

Project Name

The project name defaults to the directory name where you run cred init.

Next Steps

After init, authenticate your targets:

cred target set github    # Prompts for fine-grained PAT
cred target set fly       # Prompts for Fly.io token

Then you can push without specifying --repo or --app:

cred push github    # Uses saved binding
cred push fly       # Uses saved binding

Important Notes

  • cred is single-machine only β€” the vault and encryption key stay on your dev machine
  • Use cred push to deploy secrets to platforms like GitHub Actions
  • Your CI/CD reads secrets from the target platform directly, not from cred
  • Target tokens are stored per-project to support fine-grained tokens

See Security Model for more details.

target

Manage deployment targets for this project.

Overview

Target commands manage:

  • Authentication β€” tokens for each target platform
  • Bindings β€” identifiers (repo, app, project ID) for each target

Both tokens and bindings are stored per-project, enabling fine-grained tokens scoped to specific resources.


target set

Authenticate with a target platform.

cred target set <target>

Examples

# Authenticate with GitHub (prompts for token)
cred target set github

# Provide token directly (for automation)
cred target set github --token ghp_xxxxx

Supported Targets

TargetToken Type
githubFine-grained PAT with Actions secrets permission
vercelAccess Token from vercel.com/account/tokens
flyPersonal Access Token from fly.io/user/personal_access_tokens

Notes

  • Must be inside a cred project (cred init first)
  • Tokens are stored in OS credential store, scoped to this project
  • Each project can have different tokens for the same target
  • target set also ensures a binding exists (repo/app/projectId):
    • If a binding is already present in .cred/project.toml, it is kept.
    • Otherwise cred tries to auto-detect from project files.
    • If detection fails, cred prompts you for the identifier.
    • With --non-interactive, cred errors and tells you to run cred target bind <target> <identifier>.

target bind

Bind a target identifier to this project.

cred target bind <target> <identifier>

Examples

# Bind GitHub repo
cred target bind github owner/repo

# Bind Fly.io app
cred target bind fly my-app-name

# Bind Vercel project
cred target bind vercel prj_xxxxxxxxxxxxx

When to Use

  • When auto-detection during cred init didn’t find your target
  • When you want to override the auto-detected binding
  • When setting up a new target after init

Bindings are saved in .cred/project.toml:

[targets]
github = "owner/repo"
fly = "my-app-name"

target list

List targets configured for this project.

cred target list

Output

Project Targets:
  βœ“ github = owner/repo
  βœ— fly = my-app

Run 'cred target set <target>' to authenticate.
  • βœ“ = authenticated (token stored)
  • βœ— = binding exists but not authenticated

JSON Output

cred target list --json
{
    "api_version": "1",
    "status": "ok",
    "data": {
        "targets": [
            {
                "name": "github",
                "identifier": "owner/repo",
                "authenticated": true
            },
            { "name": "fly", "identifier": "my-app", "authenticated": false }
        ]
    }
}

target revoke

Remove a target’s authentication token.

cred target revoke <target> --yes

Examples

# Revoke GitHub token
cred target revoke github --yes

# Dry-run to preview
cred target revoke github --dry-run

Notes

  • Requires --yes flag (destructive operation)
  • Only removes the token; the binding remains in project.toml
  • For some targets (GitHub), attempts remote token revocation first

Workflow Example

# Initialize project (auto-detects GitHub from git remote)
cred init

# Authenticate GitHub with fine-grained PAT
cred target set github

# Add a Fly.io app binding
cred target bind fly my-app

# Authenticate Fly.io
cred target set fly

# List all targets
cred target list

# Push to GitHub (no --repo needed)
cred push github

# Push to Fly.io (no --app needed)
cred push fly

config

Manage global cred configuration.

Configuration is stored at ~/.config/cred/global.toml. Sensitive values (tokens) are stored in your OS keyring, not in this file.

list

View all configuration:

cred config list

get

Get a specific value:

cred config get preferences.default_target

set

Set a configuration value:

cred config set preferences.default_target github

unset

Remove a configuration value:

cred config unset preferences.default_target

Available Settings

KeyDescription
preferences.default_targetDefault target for push/prune commands

doctor

Check project health and diagnose issues in machine readable JSON:

cred doctor

Output:

{
  "api_version": "1",
  "data": {
    "cred_installed": true,
    "global_config": true,
    "keychain_access": true,
    "project_detected": false,
    "ready_for_push": false,
    "targets": [],
    "vault_accessible": false,
    "version": "0.4.0"
  },
  "status": "ok"
}

This verifies:

  • Vault file exists and is readable
  • Configuration is valid
  • Keyring access works
  • Sources and targets are reachable

status

Show a hub-and-spoke overview of your project:

cred status

Output:

Vault: 5 secrets (2 environments)

Environment: default
  RESEND_API_KEY       [resend]
  DATABASE_URL         [manual]

Environment: prod
  DATABASE_URL         [manual]
  JWT_SECRET           [manual]
  API_KEY              [manual]

Sources: resend βœ“
Targets: github βœ“
Git: edneedham/cred

This shows:

  • Total secrets and environment count
  • Secrets grouped by environment
  • Each secret’s source (manual or generated)
  • Configured sources and targets
  • Git repository (if detected)

JSON Output

For machine-readable output:

cred status --json

secret

Manage secrets in your local vault.

set

Add or update a secret:

cred secret set DATABASE_URL "postgres://user:pass@localhost:5432/db"

Target Scopes (v0.14.0+)

Scope a secret to specific deployment targets. This helps prevent accidentally pushing backend-only secrets to frontend targets.

Unscoped secrets (default) are eligible for all targets.

# Only push this to Vercel
cred secret set NEXT_PUBLIC_API_URL "https://..." --targets vercel

# Push this to GitHub and Fly only
cred secret set DATABASE_URL "postgres://..." --targets github,fly

Clear scopes (make unscoped again):

cred secret set DATABASE_URL "postgres://..." --clear-targets

With a description:

cred secret set API_KEY "sk-xxx" --description "OpenAI production key"
cred secret set CERT_PEM "-----BEGIN..." -d "TLS certificate"

In a specific environment:

cred secret set DATABASE_URL "postgres://prod..." --env prod

Format Detection

cred auto-detects the format of your secrets:

FormatDetectionExample
pemStarts with -----BEGINCertificates, keys
jsonValid JSON object/array{"key": "value"}
base64Single-line base64SGVsbG8gV29ybGQ=
multilineContains newlinesMulti-line text
rawDefaultSingle-line text

Override auto-detection:

cred secret set MY_KEY "value" --format json

get

Retrieve a secret value:

cred secret get JWT_SECRET

From a specific environment:

cred secret get JWT_SECRET --env prod

With full metadata:

cred secret get JWT_SECRET --json
{
    "data": {
        "key": "JWT_SECRET",
        "value": "super-secret",
        "format": "raw",
        "created_at": "2025-12-11T12:00:00Z",
        "updated_at": "2025-12-11T12:00:00Z",
        "description": null
    }
}

list

List all secrets in the vault (shows all environments by default):

cred secret list

Output:

Vault content (3 environments, 4 secrets):

  [default] (1 secrets)
    DEFAULT_KEY = *****

  [production] (2 secrets)
    PROD_KEY = *****
    API_KEY = ***** (OpenAI production key)

  [staging] (1 secrets)
    STAGING_KEY = *****

List secrets in a specific environment:

cred secret list --env prod

Output:

Vault content (env: production):
  PROD_KEY = *****
  API_KEY = ***** (OpenAI production key)

Descriptions are shown inline when present.


remove

Delete a secret from the local vault:

cred secret remove JWT_SECRET --yes

From a specific environment:

cred secret remove JWT_SECRET --env prod --yes

Output:

βœ“ Removed 'JWT_SECRET' from local vault (3 days old)

Note: This only removes from the local vault. To delete from a target, use cred prune.


describe

Update a secret’s description:

cred secret describe API_KEY "Updated: rotating quarterly"

Clear a description:

cred secret describe API_KEY

history

View the version history of a secret:

cred secret history DATABASE_URL

Output:

History for 'DATABASE_URL' in env 'default':

  [current] 2025-01-03 14:30:00 (manual)
  [0] 2025-01-02 10:15:00 (manual)
  [1] 2025-01-01 09:00:00 (manual)

Use 'cred secret rollback DATABASE_URL --version <N>' to restore

From a specific environment:

cred secret history DATABASE_URL --env prod

cred keeps up to 10 previous versions of each secret.


rollback

Restore a secret to a previous version:

cred secret rollback DATABASE_URL --version 0 --yes

The --version flag specifies which historical version to restore (0 = most recent previous value).

From a specific environment:

cred secret rollback DATABASE_URL --version 0 --env prod --yes

Preview before rolling back:

cred secret rollback DATABASE_URL --version 0 --dry-run

Note: Rollback is a destructive operation and requires --yes to confirm.


generate

Generate a cryptographic key pair locally using OpenSSL.

Basic Usage

Generate an RSA 2048-bit key pair:

cred secret generate API_KEY --type pem

This creates two secrets:

  • API_KEY_PRIVATE β€” The RSA private key (PKCS#1 format)
  • API_KEY_PUBLIC β€” The RSA public key

Requirements

OpenSSL must be installed and available in your PATH.

Install OpenSSL:

  • macOS: brew install openssl
  • Ubuntu/Debian: sudo apt install openssl
  • Fedora: sudo dnf install openssl

Environment-Specific Generation

Generate keys in a specific environment:

cred secret generate JWT_SIGNING_KEY --type pem --env production

Creates JWT_SIGNING_KEY_PRIVATE and JWT_SIGNING_KEY_PUBLIC in the production environment.

Overwriting Existing Keys

By default, generate refuses to overwrite existing keys. Use --force to overwrite:

cred secret generate API_KEY --type pem --force

Dry Run

Preview what would be generated:

cred secret generate API_KEY --type pem --dry-run

Output:

(dry-run) Would generate RSA 2048-bit PEM key pair 'API_KEY' in env 'default'

Key Metadata

Generated keys include:

  • Format: pem (automatically detected)
  • Source: generated
  • Description: β€œRSA 2048-bit key pair (generated by cred)”

Pushing Generated Keys

Push both keys to a target:

cred push github

Or push only specific keys:

cred push github API_KEY_PRIVATE API_KEY_PUBLIC

Supported Key Types

TypeDescriptionFormat
pemRSA 2048-bit key pairPKCS#1 PEM

import

Import KEY=VALUE pairs from a .env file:

cred import .env

Import to a specific environment:

cred import prod.env --env prod

Existing keys are skipped by default to keep imports non-destructive.

Overwrite existing keys:

cred import .env --overwrite

Preview without writing:

cred import .env --dry-run

export

Write vault contents to a .env file:

cred export .env.backup

Export from a specific environment:

cred export prod.env --env prod

Keys are sorted alphabetically. Existing files are preserved unless forced:

cred export .env --force

Preview:

cred export .env --dry-run

env

Manage environments for organizing secrets. Environments allow you to separate secrets for different contexts (e.g., dev, staging, prod).

Overview

By default, all secrets are stored in the default environment. You can create additional environments to isolate secrets for different deployment contexts.

list

List all environments:

cred env list

Output:

Environments:
  default (3 secrets)
  staging (2 secrets)
  prod (5 secrets)

create

Create a new environment:

cred env create staging

Output:

βœ“ Created environment 'staging'

delete

Delete an environment and all its secrets:

cred env delete staging --yes

Output:

βœ“ Deleted environment 'staging' (2 secrets removed)

⚠️ This is a destructive operation β€” requires --yes to confirm.


Using Environments

Most secret commands accept an --env flag:

# Set a secret in the prod environment
cred secret set DATABASE_URL "postgres://prod..." --env prod

# Get a secret from staging
cred secret get API_KEY --env staging

# List secrets in a specific environment
cred secret list --env prod

# Push prod secrets to GitHub
cred push github --env prod

# Export prod secrets to a file
cred export prod.env --env prod

Environment Strategy

Common patterns:

EnvironmentPurpose
defaultDevelopment/local secrets
stagingPre-production testing
prodProduction secrets

Migration from v0.5.x

If you’re upgrading from a version without environments, your existing secrets are automatically migrated to the default environment. No action required.

import

Import secrets from a .env file into the local vault.

Usage

cred import <path> [OPTIONS]

Arguments

ArgumentDescription
<path>Path to the .env file to import

Options

OptionDescription
--overwriteOverwrite existing keys instead of skipping
-e, --env <name>Target environment (auto-detected from cred exports)

Behavior

Plain .env Files

When importing a standard .env file:

# Import to default environment
cred import .env

# Import to a specific environment
cred import .env --env prod

Secrets are imported as plain key-value pairs without metadata.

Cred Export Files

When importing a file created by cred export:

# Import preserving environments and metadata
cred import vault.env

Cred automatically detects export files by their header and:

  • Recreates environment structure from the file
  • Restores secret metadata (descriptions, timestamps)
  • Creates any environments that don’t exist

To force all secrets into a single environment:

# Override: import all secrets to staging environment
cred import vault.env --env staging

Examples

# Import from .env, skip existing keys
cred import .env

# Import and overwrite existing keys
cred import .env --overwrite

# Import to production environment
cred import prod.env --env prod

# Import a cred export file (auto-detects format)
cred import teammate-vault.env

# Preview what would be imported
cred import .env --dry-run

Output

βœ“ Imported .env (added 5, overwritten 0, skipped 2).

For cred export files with multiple environments:

βœ“ Imported vault.env (created 2 env(s)) (added 10, overwritten 0, skipped 0).

export

Export vault secrets to a .env file.

Usage

cred export <path> [OPTIONS]

Arguments

ArgumentDescription
<path>Path to write the exported file

Options

OptionDescription
--forceOverwrite the output file if it exists
-e, --env <name>Export only this environment (exports full vault if omitted)
--plainPlain .env format (no metadata, requires --env)

Export Formats

Full Vault Export (Default)

By default, cred export creates a rich export file containing all environments with metadata:

cred export vault.env

Output format:

# cred-export v1
# exported: 2025-01-07T10:30:00Z
#
# To import: cred import <this-file>

# [environment: default]

# [API_KEY]
# description: Development API key
# created: 2025-01-01T00:00:00Z
API_KEY=sk-dev-xxx

# [DATABASE_URL]
DATABASE_URL=postgres://localhost/dev

# [environment: prod]

# [API_KEY]
# description: Production API key
# created: 2025-01-05T00:00:00Z
API_KEY=sk-prod-xxx

This format:

  • Preserves all environments
  • Includes secret metadata (descriptions, timestamps)
  • Can be imported by cred import to recreate the full vault

Single Environment Export

Export just one environment with metadata:

cred export prod.env --env prod

Output format:

# cred-export v1
# environment: prod
# exported: 2025-01-07T10:30:00Z
#
# To import: cred import <this-file>

# [API_KEY]
# description: Production API key
API_KEY=sk-prod-xxx

Plain Export

Export as a standard .env file without metadata:

cred export .env --env default --plain

Output format:

API_KEY=sk-dev-xxx
DATABASE_URL=postgres://localhost/dev

Use this when you need a standard .env file for tools that don’t understand cred comments.

Examples

# Export full vault with metadata
cred export vault.env

# Export only production environment
cred export prod.env --env prod

# Export as plain .env (no metadata)
cred export .env --env default --plain

# Overwrite existing file
cred export vault.env --force

# Preview what would be exported
cred export vault.env --dry-run

Output

βœ“ Exported 10 secrets (3 environment(s)) to vault.env.

For single environment:

βœ“ Exported 5 secrets (env 'prod') to prod.env.

Use Cases

Sharing Secrets with Teammates

Export your vault and share the file securely:

cred export team-vault.env
# Transfer file securely (encrypted email, secure share, etc.)

Teammate imports:

cred import team-vault.env

Backup

Create a backup of your entire vault:

cred export backup-$(date +%Y%m%d).env

Integration with Other Tools

When you need a standard .env for other tools:

cred export .env --env default --plain

push

Push secrets from your vault to a target platform.

Basic Usage

Push all secrets to GitHub:

cred push github

Push all secrets to Vercel:

cred push vercel

Push all secrets to Fly.io:

cred push fly

No --repo, --app, or --project flags needed β€” cred uses the target bindings saved in your project.

Push specific secrets only:

cred push github DATABASE_URL JWT_SECRET

Dry Run

Preview what will change before pushing:

cred push github --dry-run

Preview specific keys:

cred push github DATABASE_URL JWT_SECRET --dry-run

Nothing is uploaded when --dry-run is used.

Environment-Specific Push

Push secrets from a specific environment:

cred push github --env prod

This pushes only secrets from the prod environment.


Options

FlagDescription
--env <name>Push from specific environment
--repo <owner/repo>Explicit repository (GitHub)
--project <id>Explicit project ID (Vercel)
--app <name>Explicit app name (Fly.io)
--forceIgnore per-secret target scopes
--dry-runPreview changes without pushing
--jsonMachine-readable output
--non-interactiveFail instead of prompting

Target Scopes (v0.14.0+)

If a secret is scoped to specific targets, cred push <target> will:

  • Include unscoped secrets
  • Include secrets scoped to <target>
  • Skip (or refuse, if explicitly requested) secrets scoped to other targets

If you explicitly request a key that isn’t scoped to the target, cred refuses by default. Use --force to override.

Target Resolution

cred resolves target identifiers in this order:

  1. CLI flag (--repo, --app, --project) β€” highest priority
  2. Project binding (saved in .cred/project.toml)
  3. Auto-detection (git remote, fly.toml, etc.) β€” fallback

GitHub

Target binding is auto-detected from git remote during cred init, or set manually:

cred target bind github owner/repo

Override with CLI flag if needed:

cred push github --repo different/repo

Vercel

Target binding is auto-detected from .vercel/project.json during cred init, or set manually:

cred target bind vercel prj_xxxxxxxxxxxxx

Override with CLI flag if needed:

cred push vercel --project prj_other

Fly.io

Target binding is auto-detected from fly.toml during cred init, or set manually:

cred target bind fly my-app-name

Override with CLI flag if needed:

cred push fly --app different-app

Note: After pushing secrets to Fly.io, run fly deploy or fly secrets deploy to apply changes.

Incremental Updates

cred tracks which secrets have changed since the last push. Only modified secrets are updated remotely, making pushes efficient.

Workflow Example

# Add a secret
cred secret set DATABASE_URL "postgres://..."

# Preview the push
cred push github --dry-run

# Push when ready
cred push github

Updating Secrets

To update a secret:

# Update locally
cred secret set JWT_SECRET "new-secret-value"

# Preview changes
cred push github --dry-run

# Apply
cred push github

Only the changed secret will be updated at the target.

prune

Delete secrets from a target platform. This is a remote-only operation β€” it does not affect your local vault.

Basic Usage

Remove a specific key from a target:

cred prune github JWT_SECRET --yes

Remove multiple keys:

cred prune github JWT_SECRET OLD_API_KEY --yes

Dry Run

Preview what will be deleted:

cred prune github JWT_SECRET --dry-run

Prune All

Remove all known keys from a target:

cred prune github --all --yes

This removes all secrets that cred has pushed to this target.

Environment-Specific Prune

Prune secrets from a specific environment:

cred prune github OLD_KEY --env prod --yes

Options

FlagDescription
--env <name>Prune from specific environment
--repo <owner/repo>Explicit repository (GitHub)
--project <id>Explicit project ID (Vercel)
--app <name>Explicit app name (Fly.io)
--forceIgnore per-secret target scopes
--dry-runPreview without deleting
--yesConfirm destructive operation
--allPrune all known secrets
--jsonMachine-readable output

Safety

⚠️ Destructive operations require --yes unless using --dry-run.

This prevents accidental deletion of production secrets.

Local vs Remote

OperationCommand
Delete from vault (local)cred secret remove KEY --yes
Delete from target (remote)cred prune github KEY --yes
Delete from bothRun both commands

Workflow Example

Remove a secret completely:

# Remove from GitHub first
cred prune github OLD_SECRET --yes

# Then remove from local vault
cred secret remove OLD_SECRET --yes

Security Model

cred is designed with security as a core concern. This page explains how your secrets are protected.

Encryption at Rest

Your vault (.cred/vault.enc) is encrypted using ChaCha20-Poly1305, a modern authenticated encryption algorithm. This provides both confidentiality and integrity protection.

Key Storage

The encryption key is:

  • Randomly generated on cred init (32 bytes)
  • Stored in your OS credential store
  • Never written to disk as plaintext
OSBackend
macOSKeychain
LinuxSecret Service (GNOME Keyring, KWallet)
WindowsCredential Manager

Token Storage

Source and target tokens (API keys, PATs) are also stored in your OS credential store.

Tokens are never written to plaintext files like ~/.config/cred/global.toml.

What cred Protects Against

  • Accidental exposure β€” Secrets aren’t in plaintext files that could be committed
  • Disk compromise β€” Vault is encrypted at rest
  • Clipboard history β€” Interactive prompts for sensitive input
  • Overprivileged keys β€” Sources generate restricted-scope credentials

What cred Does NOT Protect Against

  • Compromised machine β€” If an attacker has access to your running system, they can access your keyring
  • Memory attacks β€” Secrets exist in memory during operations
  • Malicious targets β€” cred trusts the platforms you push to

Safe Inspection

Use --dry-run to preview any operation before it executes:

cred push github --dry-run
cred prune github --all --dry-run

This is especially important for destructive operations.

Best Practices

1. Never Commit Your Vault

The .cred/ directory is added to .gitignore on init. Never commit it:

# Verify it's ignored
cat .gitignore | grep .cred

2. Use Least Privilege

  • For sources: Use master keys only for generation, deploy restricted keys
  • For targets: Create fine-grained PATs with minimal permissions

3. Keep Backups

Export your vault periodically:

cred export secrets-backup.env

Store backups securely (encrypted, offline).

4. Audit Your Secrets

Review what’s in your vault:

cred status
cred secret list

Remove secrets you no longer need.

Threat Model

cred is designed for:

  • Solo developers managing secrets on a single machine
  • Open-source maintainers who push secrets to deployment platforms
  • Projects that don’t require multi-user access control

It is not designed for:

  • Team environments with multiple users
  • Multi-machine environments (cred is single-machine only)
  • Compliance-heavy industries (healthcare, finance) without additional controls
  • Scenarios requiring audit trails or approval workflows