passkc
passkc is a Unix-style command-line tool for storing and retrieving credentials from the macOS Keychain. It follows Unix philosophy by doing one thing well, working with text streams, and being composable with other tools.
Features
π Secure: Uses macOS Keychain for secure credential storage
π Text Streams: Read from stdin, output to stdout, pipe with other commands
π§ Multiple Formats: Support for text, JSON, and CSV output
π Filtering & Sorting: Pattern matching and sorting capabilities
π Batch Operations: Import credentials from files
π€ Quiet Mode: Script-friendly operation with minimal output
π§ͺ Well Tested: Comprehensive test coverage with dependency injection
Installation
Homebrew
brew install e6a5/tap/passkc
From Source
# Using Go
go install github.com/e6a5/passkc@latest
# Using Task (recommended for development)
git clone https://github.com/e6a5/passkc.git
cd passkc
task build
Requirements
- macOS (uses macOS Keychain)
- Go 1.21+ (for building from source)
Usage
Basic Commands
# Store credentials (interactive password prompt)
passkc set domain.com username
# Retrieve credentials
passkc get domain.com
# List all credentials
passkc show
# Modify credentials
passkc modify domain.com new-username
# Remove credentials
passkc remove domain.com
Unix Philosophy Examples
Text Stream Processing:
# Read domain from stdin
echo "domain.com" | passkc get
# Pipe password to clipboard
passkc get domain.com -q | pbcopy
# Filter and search
passkc show | grep "google"
Structured Output:
# JSON output for programmatic use
passkc show -o json | jq '.[] | select(.domain == "google.com")'
# CSV export
passkc show -o csv > credentials.csv
# Quiet mode for scripts
PASSWORD=$(passkc get domain.com -q)
Batch Operations:
# Import from file (format: domain username [password])
echo "google.com user1 pass1" > creds.txt
echo "github.com user2 pass2" >> creds.txt
passkc set -f creds.txt
# Bulk export
passkc show -o json > backup.json
Filtering and Sorting:
# Filter by pattern
passkc show --pattern "google"
# Sort by domain or username
passkc show --sort domain
passkc show --sort username
# Combine filtering and output formats
passkc show --pattern "*.com" --sort username -o json
Command Reference
Global Flags
-o, --output string: Output format (text|json|csv) (default: text)
-q, --quiet: Suppress prompts and non-essential output
-c, --config string: Config file (default: $HOME/.passkc.yaml)
Commands
passkc show
List all stored credentials with filtering and sorting options.
Flags:
--pattern string: Filter credentials by pattern
--sort string: Sort by field (domain|username)
Examples:
passkc show
passkc show -o json
passkc show --pattern "google" --sort username
passkc get [domain]
Retrieve credentials for a domain. Can read domain from stdin if not provided.
Flags:
-p, --password-only: Output only the password
Examples:
passkc get domain.com
passkc get domain.com -o json
echo "domain.com" | passkc get
passkc set [domain] [username]
Store credentials for a domain. Supports file input and stdin.
Flags:
-f, --file string: Read credentials from file
Examples:
passkc set domain.com username
passkc set -f credentials.txt
echo "domain.com username password" | passkc set
passkc modify [domain] [new-username]
Update the username for a domain.
Examples:
passkc modify domain.com new-username
passkc remove [domain]
Remove credentials for a domain.
Examples:
passkc remove domain.com
Development
Prerequisites
- Go 1.21+
- Task (task runner)
- Git
Setup
git clone https://github.com/e6a5/passkc.git
cd passkc
task deps # Download dependencies
Available Tasks
task # List all available tasks
task build # Build the binary
task test # Run tests
task test-coverage # Run tests with coverage report
task lint # Run linters
task clean # Clean build artifacts
task install # Install binary to /usr/local/bin
task demo # Showcase Unix philosophy features
Testing
The project has comprehensive test coverage using dependency injection for mocking:
# Run all tests
task test
# Run tests with coverage
task test-coverage
# Run benchmarks
task test-bench
Architecture
cmd/ # CLI commands with dependency injection
βββ keychain.go # KeychainManager interface and implementation
βββ show.go # List credentials command
βββ get.go # Retrieve credentials command
βββ set.go # Store credentials command
βββ modify.go # Modify credentials command
βββ remove.go # Remove credentials command
βββ cli_test.go # Comprehensive tests with mocks
kc/ # Keychain abstraction layer
βββ kc.go # Core keychain operations
main.go # Application entry point
Unix Philosophy Compliance
passkc follows Unix philosophy principles:
- Do one thing well: Manage credentials in macOS Keychain
- Work together: Pipe and chain with other Unix tools
- Handle text streams: Read from stdin, write to stdout
- Plain text interface: No captive user interfaces
- Composability: Every command can be a filter
Examples in Action
Daily Workflow:
# Quick password copy
passkc get work-email -q | pbcopy
# Search and filter
passkc show | grep -i "github\|gitlab" | head -5
# Backup to JSON
passkc show -o json > ~/backups/credentials-$(date +%Y%m%d).json
# Import from CSV
cat exported-passwords.csv | tail -n +2 | while IFS=, read domain user pass; do
echo "$domain $user $pass" | passkc set
done
Scripting:
#!/bin/bash
# Check if credentials exist for multiple domains
DOMAINS=("github.com" "gitlab.com" "work.com")
for domain in "${DOMAINS[@]}"; do
if passkc get "$domain" -q > /dev/null 2>&1; then
echo "β $domain: credentials found"
else
echo "β $domain: no credentials"
fi
done
License
This project is licensed under the MIT License. See the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature)
- Run tests (
task test)
- Commit your changes (
git commit -m 'Add amazing feature')
- Push to the branch (
git push origin feature/amazing-feature)
- Open a Pull Request