holecard-cli 0.2.6

A secure CLI password manager with dual-key encryption and TOTP support
# Holecard

Secure CLI password manager with dual-key encryption.

## Features

- **Dual-key encryption**: Master password + secret key for enhanced security
- **Strong cryptography**: Argon2id key derivation + AES-256-GCM encryption
- **System keyring integration**: Secret key stored securely in OS keyring
- **Biometric authentication**: Touch ID, Face ID, Apple Watch, Passkey support on macOS 🆕
- **Session caching**: Avoid repeated password entry with configurable timeout
- **Flexible entries**: Custom key-value fields per entry
- **SSH key management**: Store and manage SSH keys with ssh-agent integration
- **SSH wrapper**: Auto-load keys and connect with aliases (`hc ssh connect git@github.com`)
- **File loading**: Load fields directly from files with `--file` option
- **TOTP support**: Dedicated TOTP entry for 2FA code generation with auto-clipboard copy
- **Smart clipboard**: Copy specific fields with auto-clear after 30 seconds
- **Template injection**: Render templates with entry fields
- **Environment variables**: Run commands with secrets as env vars
- **Vault reinitialization**: Safe vault reset with confirmation prompt

## Installation

### From source (recommended)

```bash
git clone https://github.com/shabarba/holecard
cd holecard
cargo build --release
cp target/release/hc /usr/local/bin/  # or ~/.local/bin/
```

### From crates.io

```bash
cargo install holecard-cli
```

### From binary releases (coming soon)

Download pre-built binaries from [GitHub Releases](https://github.com/shabarba/holecard/releases).

**Supported platforms:**
- macOS Apple Silicon (aarch64)
- macOS Intel (x86_64)
- Linux x86_64

### With Homebrew (coming soon)

```bash
brew tap shabarba/tap
brew install hc
```

### With cargo-binstall (coming soon)

```bash
cargo binstall holecard-cli
```

## Quick Start

```bash
# Initialize vault (creates master password + secret key + totp entry)
hc init

# Add an entry
hc add github -f username=myuser -f password=mypass

# Or add interactively
hc add

# Add SSH key from file
hc add github-key --file private_key=~/.ssh/id_ed25519 -f alias="git@github.com"

# Connect via SSH (auto-loads key)
hc ssh connect git@github.com

# List entries
hc list

# Get an entry
hc get github

# Copy password to clipboard (auto-clears after 30s)
hc get github -c

# Copy specific field
hc get github -c username

# Add TOTP secret
hc totp add github JBSWY3DPEHPK3PXP

# Get TOTP code (displays + copies to clipboard)
hc totp get github
```

## Usage

### Managing Entries

```bash
# Add entry with custom fields
hc add aws -f access_key=AKIA... -f secret_key=...

# Add entry with fields from files
hc add github-key \
  --file private_key=~/.ssh/id_ed25519 \
  --file public_key=~/.ssh/id_ed25519.pub \
  -f alias="git@github.com"

# Edit existing entry
hc edit github -f password=newpass

# Edit with file field
hc edit github-key --file private_key=~/.ssh/id_rsa

# Remove entry
hc rm github

# Copy specific field to clipboard
hc get github -c password    # Copy password field
hc get github -c username    # Copy username field
hc get github -c             # Copy password field (or first field if no password)

# Export vault to JSON (plaintext - handle with care)
hc export backup.json

# Import from JSON
hc import backup.json
hc import backup.json --overwrite  # Replace existing entries
```

### SSH Key Management

Securely store SSH keys and manage ssh-agent with seamless integration.

```bash
# Add SSH key from file (recommended - preserves newlines)
hc add my-server \
  --file private_key=~/.ssh/id_rsa \
  -f alias="user@server.com,prod" \
  -f passphrase="optional"

# Connect via SSH (auto-loads key)
hc ssh connect user@server.com
hc ssh connect prod
hc ssh connect my-server

# Pass additional SSH arguments
hc ssh connect prod -- -p 2222 -v

# Manually load key into ssh-agent
hc ssh load my-server

# Load with lifetime (auto-expires after 8 hours)
hc ssh load my-server --lifetime 28800

# List loaded keys in ssh-agent
hc ssh list

# Unload key from ssh-agent
hc ssh unload my-server
```

**Why use `hc ssh` over plain `ssh-add`?**
- Store encrypted SSH keys in vault with Argon2id + AES-256-GCM
- Auto-load keys on connect with aliases (`git@github.com` → Entry name)
- Manage passphrases securely without typing them repeatedly
- Integrate with session management (`hc lock` clears both vault and ssh-agent)

### TOTP Support

All TOTP secrets are stored in a dedicated `totp` entry that is automatically created during initialization.

```bash
# Add TOTP secret for a service
hc totp add github JBSWY3DPEHPK3PXP
hc totp add aws KBSWY3DPEHPK3PXQ

# Get TOTP code (displays + copies to clipboard)
hc totp get github
# Output:
# TOTP Code: 123456 (valid for 28 seconds)
# ✓ Copied to clipboard (will clear in 30 seconds)

# Remove TOTP secret
hc totp rm github

# View all TOTP services
hc get totp
```

### Template Injection

```bash
# Render template with entry fields
hc inject github "https://{{username}}:{{password}}@github.com"

# Access specific fields
hc inject aws "AWS_ACCESS_KEY={{access_key}}"
```

### Running Commands with Secrets

```bash
# Entry fields become uppercase environment variables
hc run aws -- env | grep -E "^(ACCESS_KEY|SECRET_KEY)"

# Use with any command
hc run database -- psql -h localhost -U $USERNAME -d mydb
```

### Biometric Authentication (macOS only)

Touch ID, Face ID, Apple Watch, and Passkey authentication for seamless vault access.

```bash
# Enable/disable biometric authentication (enabled by default on macOS)
hc config enable-biometric true

# First unlock: Biometric + master password entry (cached in keyring)
# Subsequent unlocks: Biometric only (no password needed)

# Biometric authentication required for sensitive operations:
# - hc get --show/--clip
# - hc edit
# - hc rm
# - hc export
```

**Supported authentication methods:**
- Touch ID (MacBook Pro/Air, Magic Keyboard)
- Face ID (future Mac devices)
- Apple Watch unlock
- Passkey
- macOS login password (fallback)

### Session Management

```bash
# Check session status
hc status

# Lock vault (clear cached session)
hc lock

# Configure session timeout (minutes)
hc config session-timeout 30
```

### Configuration

```bash
# View current config
hc config

# Set vault file path
hc config vault-path ~/Dropbox/vault.enc

# Set session timeout
hc config session-timeout 120

# Reinitialize vault (WARNING: deletes all data)
hc init
# Output:
# âš  Vault already exists!
# âš  Vault already exists. Reinitialize? This will DELETE ALL existing data! (y/N):
```

## Security

### Encryption

- **Key derivation**: Argon2id with master password + secret key
- **Encryption**: AES-256-GCM with random nonce per save
- **Secret key**: 160-bit random key stored in system keyring

### Backup and Recovery

Use `hc export` to backup your entire vault:

```bash
hc export backup.json
```

The export file is encrypted with a password you choose. To restore:

```bash
hc import backup.json
```

**Important**:
- Store export files in a secure location (external drive, encrypted cloud storage, etc.)
- Use a strong password for export encryption
- You need BOTH the export file and its password to restore your vault
- Regular backups protect against data loss

### Session Caching

The derived encryption key is cached in the system keyring to avoid repeated password entry. Sessions automatically expire after the configured timeout (default: 60 minutes).

### Biometric Authentication (macOS)

On macOS, biometric authentication is enabled by default. After the initial setup:

1. **First unlock**: Touch ID/Face ID + master password entry (password cached in keyring)
2. **Subsequent unlocks**: Touch ID/Face ID only (password retrieved automatically)

Sensitive operations (`get --show`, `edit`, `rm`, `export`) require additional biometric verification for security.

**Security benefits:**
- No password typing (reduces shoulder surfing risk)
- Master password stored in macOS keyring with device-level encryption
- Biometric authentication uses system LocalAuthentication framework
- Automatic fallback to password if biometric unavailable

## File Locations

| File | Description |
|------|-------------|
| `~/.holecard/config.toml` | Configuration file (`enable_biometric`, `vault_path`, `session_timeout_minutes`) |
| `~/.holecard/vault.enc` | Encrypted vault (default) |
| `~/.holecard/session_*.json` | Session metadata |
| macOS Keychain | Master password (when biometric enabled), secret key, session key |

## Platform Support

- **macOS**: Apple Silicon (aarch64) and Intel (x86_64)
- **Linux**: x86_64 GNU

## Building from Source

```bash
# Clone repository
git clone https://github.com/shabarba/holecard
cd holecard

# Build
cargo build --release

# Run tests
cargo test

# Check
cargo check

# Lint
cargo clippy

# Format
cargo fmt

# Install locally
cargo install --path .
```

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

## Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

## Acknowledgments

Built with:
- [clap]https://github.com/clap-rs/clap - Command line argument parsing
- [argon2]https://github.com/RustCrypto/password-hashes - Key derivation
- [aes-gcm]https://github.com/RustCrypto/AEADs - Authenticated encryption
- [keyring]https://github.com/hwchen/keyring-rs - System keyring access
- [security-framework]https://github.com/kornelski/rust-security-framework - macOS keychain integration (macOS)
- [totp-lite]https://github.com/fosskers/totp-lite - TOTP implementation
- [sha2]https://github.com/RustCrypto/hashes - SSH key fingerprint calculation
- [tempfile]https://github.com/Stebalien/tempfile - Secure temporary file handling