A secure CLI tool for managing secrets in a private Git repository (GitHub or GitLab) with client-side encryption.
- Overview
- Installation
- GitHub Token Setup
- Quick Start
- Commands
- Profiles
- Security
- Examples
- Requirements
- Contributing
In ancient Athens, an ostrakon was a piece of pottery used as a scrap for everyday writing, tax receipts, and secret voting. It was the ancient world's equivalent of a Gist or a pastebin.
Ostrakon provides client-side encryption, ensuring your secrets are encrypted before they leave your computer. This approach provides several key advantages:
- Zero-knowledge architecture: Your master password is never sent to GitHub
- End-to-end encryption: All secrets are encrypted locally before upload
- Password-derived keys: Uses Argon2id for secure key derivation
- Authenticated encryption: AES-256-GCM ensures integrity and confidentiality
brew tap PapaDanielVi/homebrew-tap
brew install ostrakongo install github.com/PapaDanielVi/ostrakon@latestOne-line installation using the script (automatically detects and installs the latest version):
curl -sSL https://raw.githubusercontent.com/PapaDanielVi/ostrakon/main/scripts/linux-install.sh | bashThe script installs to /usr/local/bin by default. Set INSTALL_DIR to change the installation location:
curl -sSL https://raw.githubusercontent.com/PapaDanielVi/ostrakon/main/scripts/linux-install.sh | INSTALL_DIR="$HOME/.local/bin" bashOne-line installation using the script (automatically detects and installs the latest version):
iwr -useb https://raw.githubusercontent.com/PapaDanielVi/ostrakon/main/scripts/windows-install.ps1 | iexBefore initializing, create a GitHub Fine-Grained Personal Access Token with read and write permissions for the target repository:
- Go to Settings → Developer settings → Personal access tokens → Fine-grained tokens in GitHub
- Click Generate new token
- Configure the token:
- Token name: Give it a descriptive name (e.g., "ostrakon-secrets")
- Token expiration: Set an appropriate expiration (recommend 90 days or less)
- Repository permissions:
- Select Only select repositories and choose your vault repository
- Contents: Read and write
- Click Generate token and copy the token immediately (you won't see it again)
Note: Fine-grained tokens with "Contents: Read and write" are preferred over classic tokens with
reposcope because they provide more limited access to just the specific repository.
For GitLab, create a Personal Access Token with api scope:
- Go to User Settings → Access Tokens in GitLab
- Click Add new token
- Configure the token:
- Token name: Give it a descriptive name (e.g., "ostrakon-secrets")
- Expiration: Set an appropriate expiration
- Scope: Select
api
- Click Create token and copy the token immediately
You can also optionally provide a numeric project ID during initialization for faster API lookups.
-
Initialize your vault:
ostrakon init
This will prompt you for:
- Repository URL (e.g.,
https://github.com/owner/repoorowner/repo) - GitHub Personal Access Token (with Contents read/write permission)
- Master password for encryption
- Repository URL (e.g.,
-
Add a secret:
ostrakon add secret.txt # or with piped data echo "abc123" | ostrakon add API_KEY
-
List secrets:
ostrakon ls
-
Get a secret:
ostrakon get secret.txt
Initialize Ostrakon by setting up the repository and master password.
--no-keyring: Do not store master password in keyring (will prompt for password on each operation)-p, --provider: Git provider to use (githuborgitlab, default:github)
The master password is automatically stored in the OS keyring during init for convenience. Use --no-keyring to opt out of this behavior.
For GitLab, use --provider gitlab and provide a project URL like https://gitlab.com/namespace/project or namespace/project. You can optionally provide a numeric project ID for faster API lookups.
Encrypt and upload a file to the vault. Reads from stdin if data is piped.
-n, --name: Name for the file in the vault-p, --profile: Profile/namespace for the file-v, --verbose: Log actions for user (steps only, no sensitive data)
The master password is retrieved from the keyring (stored during init). If not in keyring, you'll be prompted.
Note: For file paths, only the last two path components are used as the vault name (e.g.,
/Users/mk/Documents/secret.txtbecomesDocuments/secret.txtin the vault).
Download and decrypt a secret from the vault.
-o, --output: Output file (default: stdout)-p, --profile: Profile/namespace for the file
Note: Always prompts for master password for security (keyring is ignored for read operations).
List all secrets stored in the vault.
<path>: Filter by path prefix (supports hierarchical paths likeprod/db/)-t, --tree: Show secrets as a tree structure-p, --profile: Filter by profile/namespace (deprecated, use path instead)
Securely delete a secret by overwriting it with random data before deletion. This provides deniability by destroying the encrypted file's history.
--all: Reset all Ostrakon data (clear keychain)--hard: Wipe commit history along with data (only with--all, requires additional API permissions)
Download and decrypt a secret to a file. Always prompts for master password.
-o, --output: Output file (default: uses the secret name as filename)
Download, decrypt, edit in $EDITOR, and re-encrypt a secret. Always prompts for master password before editing.
Execute a local script using decrypted secrets as environment variables.
-e, --env: Secret name(s) to inject as environment variables
Profiles provide namespacing for your secrets. Use the -p flag to organize secrets:
ostrakon add config.env -p production
ostrakon get config.env -p production
ostrakon ls -p production- All secrets are encrypted client-side before being sent to GitHub
- Master password is stored in the OS keyring during
initfor convenience on write operations (add,shred) - For read operations (
get,run), the master password is always prompted for maximum security - Use
ostrakon init --no-keyringto opt out of keyring storage for master password - Tokens and passwords are stored in the OS keychain (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux)
shredprovides secure deletion by overwriting files before removal
# Initialize your vault
ostrakon init
# Repository URL: https://github.com/owner/repo
# Enter your GitHub Fine-Grained Personal Access Token (with Contents: Read and write permission)
# Enter master password
# Add a secret file
ostrakon add secret.txt
# Add with a custom name
ostrakon add -n myapp.env config.env
# Add with piped data (useful for env files)
echo "DATABASE_URL=postgres://localhost:5432/mydb" | ostrakon add db.env
# List all secrets
ostrakon ls
# Get and decrypt a secret
ostrakon get secret.txt
ostrakon get secret.txt -o output.txt
# Write secret to a file
ostrakon write secret.txt
ostrakon write prod/db/password -o ./secrets/db.env
# Delete a secret
ostrakon shred secret.txtSecrets can be organized using paths with slashes:
# Add secrets with hierarchical paths
ostrakon add prod/database/password
ostrakon add prod/api/key
ostrakon add staging/database/password
# List all secrets
ostrakon ls
# List only production secrets
ostrakon ls prod/
# List as a tree
ostrakon ls --tree
# Get a secret by its full path
ostrakon get prod/database/passwordProfiles provide namespacing for different environments:
# Add production secrets
ostrakon add -p production database.env
ostrakon add -p production api-key.txt
# Add development secrets
ostrakon add -p development database.env
# List production secrets only
ostrakon ls -p production
# Get a production secret
ostrakon get database.env -p productionExecute scripts with decrypted secrets as environment variables:
# Create a script that uses secrets
cat > deploy.sh << 'EOF'
#!/bin/bash
echo "Deploying to $ENVIRONMENT with API key: $API_KEY"
# Your deployment logic here
EOF
# Run the script with secrets injected
ostrakon run deploy.sh -e api-key.txt -e environment.envThe master password workflow is designed for security and convenience:
- During init: You're prompted for a master password, which is stored in the OS keyring by default
- On
add/shred/edit: Password is retrieved from keyring silently (no prompt) - On
get/run/write: Always prompts for password (keyring is ignored for security)
List secrets with different views:
# List all secrets
ostrakon ls
# List with tree view
ostrakon ls --tree
# Filter by path prefix
ostrakon ls prod/
# Search for secrets containing a pattern
ostrakon ls --search api# Write a secret to a file
ostrakon write prod/db/password
# Write with custom output filename
ostrakon write prod/db/password -o ./secrets/db.env
# Edit a secret in your editor
ostrakon edit prod/db/password
# Opens $EDITOR (or vim) to edit the decrypted secret# Initialize with keyring storage (default)
ostrakon init
# Password will be stored in keyring for add/shred operations
# Initialize without keyring storage
ostrakon init --no-keyring
# You'll be prompted for password on each operation
# Adding secrets uses keyring silently
ostrakon add secret.txt # No password prompt (uses keyring)
# Getting secrets always asks for password
ostrakon get secret.txt
# Enter master password: [always prompts]- Go 1.21 or later (if installing via
go install) - GitHub Fine-Grained Personal Access Token with Contents: Read and write permission for your vault repository
- A private GitHub repository for storing secrets
We welcome contributions! Please see our Contributing Guide for details.
If you find Ostrakon useful, please consider starring the repository to show your support!