cred

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

`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:

- Commands Reference — all available commands
- Environments — organize secrets by environment
- Sources — generate credentials from APIs like Resend
- Security Model — how your secrets are protected

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

### Recommended Migration

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 target | Per-project tokens
`cred target set` stored globally | `cred target set` stores per-project
`--repo`/`--app` flags often needed | Target 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 notes | Single encrypted vault
Copy-paste into GitHub UI | `cred push github`
No visibility into what’s deployed | `cred status` shows everything
Hard to sync across repos | Push 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

Permission | Description
--- | ---
`full_access` | Can create, delete, get, and update any resource
`sending_access` | Can 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 env | Vercel target
--- | ---
`prod` | `production`
`default` | `development`
others | `preview`

    # 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:

Field | Description
--- | ---
`key` | The secret name (e.g., `DATABASE_URL`)
`value` | The encrypted secret value
`format` | Content format (raw, json, pem, etc.)
`created_at` | When the secret was first added
`updated_at` | When the secret was last modified
`description` | Optional human-readable description
`source` | Where it came from (`manual` or a source name)
`history` | Up to 10 previous versions (for rollback)

## Secret Formats

cred auto-detects the format of your secrets:

Format | Detection | Example
--- | --- | ---
`pem` | Starts with `-----BEGIN` | Certificates, private keys
`json` | Valid JSON object or array | `{"key": "value"}`
`base64` | Single-line base64 content | `SGVsbG8gV29ybGQ=`
`multiline` | Contains newlines | Multi-line text
`raw` | Everything 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

Command | Description
--- | ---
`cred init` | Initialize a new cred project
`cred status` | Show vault, sources, and targets overview
`cred doctor` | Check project health

## Secrets

Command | Description
--- | ---
`cred secret set` | Add or update a secret
`cred secret get` | Retrieve a secret value
`cred secret list` | List all secrets
`cred secret remove` | Delete a secret from vault
`cred secret describe` | Update a secret’s description
`cred secret history` | View version history for a secret
`cred secret rollback` | Restore a previous version
`cred import` | Import from .env file
`cred export` | Export to .env file

## Environments

Command | Description
--- | ---
`cred env list` | List all environments
`cred env create` | Create a new environment
`cred env delete` | Delete an environment and its secrets

## Deployment

Command | Description
--- | ---
`cred push` | Push secrets to a target
`cred prune` | Delete secrets from a target

## Sources

Command | Description
--- | ---
`cred source add` | Add a credential source
`cred source generate` | Generate a new credential
`cred source keys` | List keys at the source
`cred source delete` | Delete a generated key
`cred source list` | List configured sources
`cred source revoke` | Remove source and all its keys

## Targets

Command | Description
--- | ---
`cred target set` | Authenticate with a target
`cred target bind` | Bind target identifier to project
`cred target list` | List configured targets
`cred target revoke` | Remove a target’s token

## Configuration

Command | Description
--- | ---
`cred config list` | View all configuration
`cred config get` | Get a config value
`cred config set` | Set a config value
`cred config unset` | Remove a config value

## Global Flags

All commands support these flags:

Flag | Description
--- | ---
`--json` | Machine-readable JSON output
`--non-interactive` | Fail instead of prompting for input
`--dry-run` | Preview changes without applying them
`--help` | Show 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:

Target | Detection Source
--- | ---
GitHub | Git remote (`git@github.com:owner/repo.git`)
Fly.io | `fly.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

Target | Token Type
--- | ---
`github` | Fine-grained PAT with Actions secrets permission
`vercel` | Access Token from vercel.com/account/tokens
`fly` | Personal 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

Key | Description
--- | ---
`preferences.default_target` | Default 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:

Format | Detection | Example
--- | --- | ---
`pem` | Starts with `-----BEGIN` | Certificates, keys
`json` | Valid JSON object/array | `{"key": "value"}`
`base64` | Single-line base64 | `SGVsbG8gV29ybGQ=`
`multiline` | Contains newlines | Multi-line text
`raw` | Default | Single-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:

    cred secret list

Output:

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

List secrets in a specific environment:

    cred secret list --env prod

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.

## 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:

Environment | Purpose
--- | ---
`default` | Development/local secrets
`staging` | Pre-production testing
`prod` | Production 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

Argument | Description
--- | ---
`<path>` | Path to the `.env` file to import

## Options

Option | Description
--- | ---
`--overwrite` | Overwrite 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

Argument | Description
--- | ---
`<path>` | Path to write the exported file

## Options

Option | Description
--- | ---
`--force` | Overwrite the output file if it exists
`-e, --env <name>` | Export only this environment (exports full vault if omitted)
`--plain` | Plain `.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

Flag | Description
--- | ---
`--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)
`--force` | Ignore per-secret target scopes
`--dry-run` | Preview changes without pushing
`--json` | Machine-readable output
`--non-interactive` | Fail 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

Flag | Description
--- | ---
`--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)
`--force` | Ignore per-secret target scopes
`--dry-run` | Preview without deleting
`--yes` | Confirm destructive operation
`--all` | Prune all known secrets
`--json` | Machine-readable output

## Safety

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

This prevents accidental deletion of production secrets.

## Local vs Remote

Operation | Command
--- | ---
Delete from vault (local) | `cred secret remove KEY --yes`
Delete from target (remote) | `cred prune github KEY --yes`
Delete from both | Run 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

OS | Backend
--- | ---
macOS | Keychain
Linux | Secret Service (GNOME Keyring, KWallet)
Windows | Credential 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