Skip to content

V-Gutierrez/kc

kc logo

kc

A human-friendly CLI for macOS Keychain.
Because security find-generic-password -s service -a account -w is not human-friendly.

WhyHow It WorksInstallQuick StartCommandsTouch IDVaultsShell IntegrationSecurity

CI Version macOS


kc demo


Why

# Before
export OPENAI_API_KEY="sk-proj-abc123"  # in your .zshrc, visible to everything

# After
kc set OPENAI_API_KEY    # AES-256 in Secure Enclave, Touch ID to access

kc doesn't add security macOS doesn't already have. It makes the secure path the easy path.

How It Works

kc is a Go wrapper around macOS security CLI. No custom cryptography. No network calls. No config files. Your secrets stay in Apple's encryption stack.

Install

brew tap v-gutierrez/kc
brew install kc

Or build from source:

git clone https://github.com/v-gutierrez/kc.git
cd kc
go build -ldflags "-X github.com/v-gutierrez/kc/internal/cli.Version=v0.4.0" -o kc ./cmd/kc
sudo mv kc /usr/local/bin/

Quick Start

# Interactive TUI (recommended for secret entry)
kc

# Store a secret without putting the value in shell history
kc set OPENAI_API_KEY

# Read it (copies to clipboard, auto-clears in 30s)
kc get OPENAI_API_KEY

# Search across all vaults
kc search openai

# Import from .env file
kc import .env

# Load all secrets into your shell (single Touch ID prompt)
eval "$(kc env)"

# Compare vaults
kc diff prod staging

Commands

Command Description
kc get <key> Read a secret (copied to clipboard + printed masked)
kc set <key> [value] Store/update a secret — Touch ID protected by default
kc set <key> --no-protect Store without Touch ID protection
kc del <key> Delete a secret
kc list List all keys (values masked)
kc list --json List as JSON for scripting
kc search <query> Fuzzy search across all vaults
kc diff <vault1> <vault2> Compare keys between two vaults
kc import <file> Import from .env file → Keychain
kc export Export active vault as .env to stdout
kc export -o <file> Export to file
kc env Print export statements for shell integration
kc init <shell> Print the shell init snippet for zsh, bash, or fish
kc setup Migrate plaintext shell secrets into Keychain and install shell init
kc migrate --from <service> Migrate existing Keychain entries to kc format
kc vault list List all vaults
kc vault create <name> Create a new vault
kc vault switch <name> Set active vault

Touch ID

v0.4.0 keeps Touch ID protection on by default and adds a boot-session grace period for protected reads. After the first successful unlock, kc caches the current macOS boot session in $TMPDIR, so subsequent protected reads skip the prompt until you log out or restart.

# Default: Touch ID required
kc set DB_PASSWORD "super-secret"

# Opt out per key
kc set PUBLIC_KEY "not-sensitive" --no-protect

# First protected read prompts Touch ID
kc get DB_PASSWORD

# Later protected reads skip the prompt until logout or restart
eval "$(kc env)"

# Export follows the same protected-read rule
kc export > .env

Why this matters:

  • Physical presence required — no remote exfiltration
  • Enterprise-grade audit trail (who touched what, when)
  • If Touch ID is unavailable, falls back to system password prompt
  • Zero friction in daily workflow — one fingerprint per boot session

Vaults

Vaults are logical groups for your secrets. Under the hood, they map to Keychain "service" fields prefixed with kc:.

kc vault create prod
kc vault create staging
kc vault switch prod
kc set DB_PASS "super-secret"     # saved in vault "prod"
kc get DB_PASS --vault staging    # read from specific vault

Search

Find secrets across all vaults instantly:

# Fuzzy search
kc search api

# Search with JSON output
kc search openai --json

Shell Integration

Generate the right shell snippet:

kc init zsh
kc init bash
kc init fish

For zsh or bash, add to your shell rc file:

eval "$(kc env)"

For fish:

kc env | source

That's it. All secrets from your active vault are loaded as environment variables on shell startup.

One-command onboarding

If you already have plaintext secrets in ~/.zshrc, ~/.bash_profile, or fish config, run:

kc setup

kc setup detects your shell, shows the secrets it found, imports them into your active vault, comments the old lines with #kc-migrated#, and installs the correct init snippet.

Per-vault loading

eval "$(kc env --vault prod)"

Security

  • Offline only. No network calls. Ever.
  • Keychain-native. AES-256 encryption via macOS Secure Enclave.
  • Touch ID by default. Physical presence required to read secrets.
  • Clipboard auto-clear. After kc get, clipboard clears in 30s.
  • No plaintext config. Vault list is inferred from Keychain — no files to leak.
  • Prefer interactive entry for secrets. The TUI avoids putting secret values on the command line. Shells may record kc set KEY VALUE in history.
  • Audit logging. Every access logged with timestamp and context.

Data Model

macOS Keychain (AES-256 via Secure Enclave)
  └── Service = "kc:{vault_name}"
        └── Account = key_name
              └── Password = secret_value
              └── Access Control = Touch ID (default) | None (--no-protect)

License

MIT


Built with 🏈 by Victor Gutierrez