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 safely pushes them to target platforms on demand.

⚠️ Status: Early Preview (v0.4.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 access control system
  • A replacement for HashiCorp Vault or AWS Secrets Manager
  • A bidirectional secrets sync tool
  • A runtime secret injector for applications

Who is this for

  • Open-source maintainers
  • Small teams
  • Solo developers
  • People who don’t need enterprise infrastructure yet

Why cred exists

Managing secrets across projects, targets, and sources is a mess and a chore.

cred solves this by giving you:

1. A Matrix Vault per Project

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

2. 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)

3. A global configuration store

Metadata and preferences live in ~/.config/cred/global.toml, while source and target tokens are stored securely in the OS credential store (keyring). Nothing sensitive is written to the TOML.

4. Target-agnostic secret pushing

You manage secrets locally, but cred can upload them to specified targets.

Supported sources:

  • Resend (API key generation)

Supported targets:

  • GitHub (Actions 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.

2. Add a target

cred target set github

You’ll be prompted for a fine-grained PAT with Actions secrets permission.

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

Done! Your secret is now in GitHub Actions.


Next steps:

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 CI/CD pipelines can access them.

Currently supported:

  • GitHub — Actions 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 CI/CD pipelines can access them.

Adding a Target

Authenticate a deployment target:

cred target set github

You will be securely prompted for a token. The token is stored in your OS credential store, not in plaintext on disk.

For non-interactive use (CI):

cred target set github --token "$GITHUB_TOKEN" --non-interactive

Managing Targets

List configured targets:

cred target list

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"

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).

Vault

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

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

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)

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
    }
}

Hub-and-Spoke Status

For a complete overview of your project:

cred status
Vault: 3 secrets

  RESEND_API_KEY       [resend]
  DATABASE_URL         [manual]
  JWT_SECRET           [manual] [modified]

Sources: resend ✓
Targets: github ✓

Encryption

The vault is encrypted at rest using ChaCha20-Poly1305. The encryption key is derived from your project and stored securely. 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. Keep backups — Export periodically with cred export
  4. Use sources when possible — Generated keys have better audit trails

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 importImport from .env file
cred exportExport to .env file

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 setConfigure a deployment target
cred target listList configured targets
cred target revokeRemove a target

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.

cred init

Initialize a new cred project in the current directory:

cred init

This creates:

.cred/
├── project.toml    # Project configuration
└── vault.enc       # Encrypted secrets vault

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

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: 3 secrets

  RESEND_API_KEY       [resend]
  DATABASE_URL         [manual]
  JWT_SECRET           [manual]

Sources: resend ✓
Targets: github ✓
Git: edneedham/cred

This shows:

  • Number of secrets in vault
  • 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"

With a description:

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

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

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:

cred secret list

Output:

Vault content:
  API_KEY = ***** (OpenAI production key)
  JWT_SECRET = *****

Descriptions are shown inline when present.


remove

Delete a secret from the local vault:

cred secret remove JWT_SECRET --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

import

Import KEY=VALUE pairs from a .env file:

cred import .env

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

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

cred export .env --force

Preview:

cred export .env --dry-run

push

Push secrets from your vault to a target platform.

Basic Usage

Push all secrets to GitHub:

cred push github

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.

Options

FlagDescription
--dry-runPreview changes without pushing
--jsonMachine-readable output
--non-interactiveFail instead of prompting

Repository Detection

cred automatically detects your repository from git metadata when you’re inside a git repository.

If you’re not in a git repository, or need to push to a different repo:

cred push github --repo owner/repo

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.

Options

FlagDescription
--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

CI/CD Integration

cred is designed to work well in automated environments. All commands support flags for non-interactive use.

Automation Flags

FlagDescription
--jsonMachine-readable JSON output
--non-interactiveFail instead of prompting for input
--dry-runPreview changes without applying

Setting Up Targets in CI

cred target set github \
  --token "$CRED_GITHUB_TOKEN" \
  --non-interactive

Then push secrets:

cred push github --non-interactive

Example: GitHub Actions

Use cred in a workflow to sync secrets:

name: Sync Secrets

on:
    workflow_dispatch: # Manual trigger

jobs:
    sync:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4

            - name: Install cred
              run: cargo install cred

            - name: Configure target
              run: |
                  cred target set github \
                    --token "${{ secrets.CRED_GITHUB_TOKEN }}" \
                    --non-interactive

            - name: Push secrets
              run: cred push github --non-interactive --json

Note: This requires your vault to be accessible in CI. Consider whether this fits your security model.

Machine-Readable Output

All commands support --json for parsing:

cred push github --non-interactive --json
{
    "success": true,
    "pushed": ["DATABASE_URL", "API_KEY"],
    "skipped": [],
    "errors": []
}

Dry Run in CI

Use --dry-run to validate changes in PR checks:

cred push github --dry-run --json

This reports what would change without making modifications.

Best Practices

  1. Use dedicated tokens — Create a separate PAT for CI with minimal permissions
  2. Prefer dry-run in PRs — Validate changes before merging
  3. Log JSON output — Makes debugging easier
  4. Fail fast — Always use --non-interactive in CI

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.

Token Storage

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

OSBackend
macOSKeychain
LinuxSecret Service (GNOME Keyring, KWallet)
WindowsCredential Manager

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

Added to .gitignore on cred init otherwise check and add manually if needed:

echo .cred >> .gitignore

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. Rotation (coming soon)

4. Keep Backups

Export your vault periodically:

cred export secrets-backup.env

Store backups securely (encrypted, offline).

5. 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:

  • Individual developers
  • Small teams with trusted members
  • Projects that don’t require enterprise-grade access control

It is not designed for:

  • Multi-tenant environments
  • Compliance-heavy industries (healthcare, finance) without additional controls
  • Scenarios requiring audit trails or approval workflows