SKIT (Security Kit) is a command-line utility for securely managing development secrets. It stores encrypted secrets in a simple .env-style format that's safe to commit to git, providing a secure alternative to plaintext .env files.
β οΈ Platform Note: SKIT is primarily designed for Linux and macOS. While it can be compiled for Windows, some features (such as secure file permissions and shell detection) may have limited functionality on Windows systems.
- π Secure encryption using AES-256-GCM with Argon2 password hashing
- π .env-style format familiar to developers with safe commit capability
- π₯ Import existing files - convert
.envfiles to encrypted safes instantly - π Direct execution with
execcommand - inject secrets without exposing them - π Salt rotation for forward secrecy and security maintenance
- ποΈ Mixed storage - store both encrypted secrets and plain text variables
- π Safe key management - remember passwords for seamless authentication
- π― Multiple output formats - table, JSON, environment, and Terraform formats
- β‘ Auto-generated passwords - create secure 20-character shell-safe passwords
- π‘οΈ Security-first design - never store plaintext passwords or keys in project directories
cargo install --path .# Convert your existing .env file to encrypted safe
skit import -f .env
# Or import with mixed encryption (some keys plain, others encrypted)
skit import -f .env --plain NODE_ENV,PORT
# View the imported secrets
skit print
# Execute your app with injected secrets
skit exec -- npm start# Initialize a new safe with auto-generated password (recommended)
skit init -g -r
# Add secrets manually
skit set API_KEY your-secret-key
skit set PORT 3000 -p
# View all secrets (default table format)
skit print
# View as JSON or environment format using shorthand
skit -o json print
skit -o env print
# Execute command with secrets injected
skit exec -- npm startThese options affect multiple commands and must be placed before the command:
-s, --safe <name>- Specify safe file name (default:.env.safe)-o, --format <format>- Output format:table,json,env, orterraform(default:table)
Set these environment variables to customize default behavior:
SKIT_FORMAT- Default output format (jsonorenv). Overridden by--formatflag.SKIT_SAFEKEY- Safe key for authentication (use with-sto specify which safe)
Usage Pattern: skit [GLOBAL_OPTIONS] <COMMAND> [COMMAND_OPTIONS]
All major options support shorthand flags for faster typing:
| Long Form | Short | Description |
|---|---|---|
--safe |
-s |
Specify safe file |
--format |
-o |
Output format (table, json, env, terraform) |
--file |
-f |
Input file path (import) |
--generate |
-g |
Generate secure password (init) |
--remember |
-r |
Remember safe key (init) |
--description |
-d |
Set safe description (init) |
--plain |
-p |
Plain text mode (set/print) |
--plain-keys |
Comma-separated list of plain text keys (import) | |
--enc |
-e |
Encrypted only mode (print) |
Examples with Environment Variables:
# Set default format to JSON
export SKIT_FORMAT=json
skit print # Uses JSON format
skit keys # Uses JSON format
skit status # Uses JSON format
# Override with command-line flag (long or short form)
skit --format env print # Uses env format, ignores SKIT_FORMAT
skit -o env print # Same using shorthand
# Set default format to env for shell integration
export SKIT_FORMAT=env
skit print > .env # Direct shell format output
eval "$(skit env)" # Already outputs shell format
# Clear environment variable to return to default
unset SKIT_FORMAT
skit print # Back to default table formatCreates a new safe file with password protection.
Usage:
skit init [-g] [-r] [-d <description>] [--ssm-prefix <prefix>]
skit -s myproject init [-g] [-r] [-d <description>] [--ssm-prefix <prefix>]Options:
-g, --generate- Generate a secure random password automatically (20 characters, shell-safe)-r, --remember- Remember the safe key for automatic authentication (works with both manual and generated passwords)-d, --description <description>- Set description for the safe (skips interactive prompt)--ssm-prefix <prefix>(alias:--ssm) - Store a default AWS SSM parameter prefix (e.g.,/myapp/dev/) with the safe metadata
Examples:
# Manual password entry with confirmation
skit init
# Auto-generate secure password (recommended)
skit init -g
# Auto-generate password and remember it for easy access (most convenient)
skit init -g -r
# Create named safe with description using shorthand flags
skit -s myproject init -g -r -d "My project secrets"
# Long form still works
skit --safe myproject init --generate --remember --description "My project secrets"
# Initialize and associate a default SSM prefix
skit init --ssm-prefix /myapp/dev/Password Generation Features:
- Generates 20-character passwords
- Uses shell-safe characters:
a-z A-Z 0-9 ^ - _ . * + = : , - Avoids problematic characters like quotes,
$, backticks, etc. - Guarantees at least one character from each category
- Displays password for secure storage
Default Storage Location: ~/.config/skit/keys/
SKIT automatically stores safe keys in ~/.config/skit/keys/ when you:
- Use the
remember-safekeycommand - Choose to save the safe key during
importorinitoperations
Keys are stored as ~/.config/skit/keys/<uuid>.key with restricted permissions (600), where <uuid> is the unique identifier for each safe. This default location ensures your keys are:
- Stored outside your project directory - never accidentally committed
- Protected with secure file permissions - only your user can read them (600)
- Automatically loaded - SKIT finds them when you run commands
Method 1: System Keychain/Credential Manager
# macOS Keychain
security add-generic-password -a $(whoami) -s "skit-myproject" -w "password"
# Linux Secret Service
secret-tool store --label="SKIT myproject" application skit project myproject
# Then retrieve when needed
SKIT_SAFEKEY=$(secret-tool lookup application skit project myproject) skit -s myproject printMethod 2: Separate Private Directory
# Create directory OUTSIDE any git repos
mkdir -p ~/.skit-passwords
echo 'your-generated-password' > ~/.skit-passwords/myproject.key
chmod 600 ~/.skit-passwords/myproject.key
# Use with:
SKIT_SAFEKEY=$(cat ~/.skit-passwords/myproject.key) skit -s myproject printβ NEVER do this:
# DON'T: These will be committed to git!
echo 'password123' > .env.safe.password
echo 'password123' > password.txt
echo 'password123' > secrets/mypasswordβ Don't store in project directory:
- Any file in your project can accidentally be committed
- Even
.gitignorecan be misconfigured or overridden
Stores a secret with encryption (default) or as plain text.
Usage:
skit set <KEY> <VALUE> [--plain]Arguments:
<KEY>- Secret key name<VALUE>- Secret value to store
Options:
-p, --plain- Store as plain text instead of encrypted (no password required)
Examples:
# Store encrypted secret (prompts for password)
skit set API_KEY sk-1234567890abcdef
skit set DATABASE_URL postgres://user:pass@localhost/db
# Store plain text values (no password required)
skit set PORT 3000 -p
skit set BASE_URL https://api.example.com --plain
# Use with different safe using shorthand
skit -s myproject set SECRET_KEY myvalueConverts cleartext files (like .env) into encrypted safe files, perfect for onboarding or migrating existing projects.
Usage:
skit import -f <FILE> [--plain-keys <KEYS>]Arguments:
-f, --file <FILE>- Path to the input file to import (required)
Options:
--plain-keys <KEYS>- Comma-separated list of keys to store as plain text (default: all keys are encrypted)
Behavior:
- Default: All keys are encrypted if no flags specified
- Auto-password generation: Hit enter at password prompt to auto-generate secure password
- Key saving: Option to save safe key for passwordless future access
- Safe naming: Uses default
.env.safeor specify with--safe <name>
Examples:
# Import all keys as encrypted (default behavior)
skit import -f .env
# Import to custom safe name
skit --safe myproject import -f .env
# Import with specific keys as plain text, others encrypted
skit import -f .env --plain-keys NODE_ENV,PORT,BASE_URL
# Import from different file types
skit import -f config.env --plain-keys NODE_ENVSample Import Flow:
$ skit import -f .env --plain-keys NODE_ENV,PORT
skit (Security Kit) - Finally safe to commit your secrets!
Let's convert your cleartext secrets to a secure safe.
π Found 4 secrets in .env
π 2 keys will stay as plain text: NODE_ENV, PORT
π Creating your secure safe...
Enter password for new safe (or hit enter to generate one automatically):
π² Generated Password: Kx3^mP.N.a25.X=rxfzt
Please save this password securely - you'll need it to access your safe!
β
Import complete!
4 secrets imported (2 encrypted, 2 plain text)
Safe created: .env.safe
Save safe key for easy access? (y/N): y
β
Safe key saved to ~/.config/skit/keys/uuid.key! No more password prompts needed.
π Your secrets are now secure and safe to commit to git!
π Try: skit printMigration Benefits:
- Zero setup time - converts existing
.envfiles instantly - Selective encryption - choose which values need encryption
- Git-safe immediately - resulting
.env.safefiles are safe to commit - Team onboarding - perfect for converting team projects to SKIT
- Backwards compatible - maintains
.envformat with encrypted values
Displays the decrypted value of a specific secret.
Usage:
skit get <KEY>Arguments:
<KEY>- Secret key name to retrieve
Examples:
# Get encrypted secret (prompts for password)
skit get API_KEY
# Get from specific safe using shorthand
skit -s myproject get DATABASE_URLDisplays all secrets in organized format with filtering options.
Usage:
skit print [--plain | --enc]Options:
-p, --plain- Show only plain text values (no password required)-e, --enc- Show only encrypted values (requires password)
Global Options (use before print):
--format <format>- Output format:table,json,env, orterraform(default:table)
Examples:
# Show all secrets (default) - prompts for password if encrypted values exist
skit print
# Show only plain text values (no password required)
skit print -p
# Show only encrypted values (requires password)
skit print -e
# JSON format with filtering using shorthand
skit -o json print -p
skit -o json print -e
# Environment format for shell sourcing
skit -o env print > .env
skit -o env print -p > .env.plain
# Combined with different safe using shorthand
skit -s myproject print -eBehavior:
- Default: Shows both encrypted and plain text values (prompts for password)
-p, --plain: Shows only plain text values (no password prompt)-e, --enc: Shows only encrypted values (requires password)- Cannot combine:
-pand-eflags cannot be used together
Shows only the keys without values, organized by type (encrypted/plain).
Usage:
skit keysGlobal Options (use before keys):
--format <format>- Output format:tableorjson(default:table)
Examples:
# Default table format with type indicators
skit keys
# JSON format for scripts using shorthand
skit -o json keys
# List keys from specific safe using shorthand
skit -s myproject keysRuns a command with secrets injected as environment variables without exposing them in process lists.
Usage:
skit exec -- <COMMAND> [ARGS...]Arguments:
--- Separates SKIT options from the command to execute (required)<COMMAND>- Command to execute with injected secrets[ARGS...]- Arguments to pass to the command
Examples:
# Run Node.js application with secrets
skit exec -- npm start
skit exec -- node server.js
# Run Python application
skit exec -- python app.py
# Run with specific safe using shorthand
skit -s myproject exec -- docker-compose up
# Complex command with arguments
skit exec -- curl -H "Authorization: Bearer $API_KEY" https://api.example.comSecurity Features:
- Secrets don't appear in
psoutput - Environment variables are only available to the executed process
- Both encrypted and plain text variables are injected
Checks that all secrets can be decrypted and displays safe statistics.
Usage:
skit statusGlobal Options (use before status):
--format <format>- Output format:tableorjson(default:table)
Examples:
# Default format with integrity check
skit status
# JSON format for scripts and automation using shorthand
skit -o json status
# Check specific safe using shorthand
skit -s myproject statusWhat it checks:
- All encrypted secrets can be decrypted
- Password hash integrity
- Safe file format validity
- Statistics (total secrets, encrypted vs plain)
Rotates encryption keys and re-encrypts all secrets for forward secrecy.
Usage:
skit rotateExamples:
# Rotate encryption for default safe
skit rotate
# Rotate specific safe using shorthand
skit -s myproject rotateWhat it does:
- Prompts for current password
- Prompts for new password (or generates one)
- Re-encrypts all secrets with new salt
- Updates password hash
- Maintains all secret values
Deletes a secret from the safe (prompts for password if removing encrypted secrets).
Usage:
skit rm <KEY>Arguments:
<KEY>- Secret key name to remove
Examples:
# Remove secret (prompts for password)
skit rm API_KEY
# Remove from specific safe using shorthand
skit -s myproject rm OLD_SECRETShows all .safe files in the current directory with statistics.
Usage:
skit lsGlobal Options (use before ls):
--format <format>- Output format:tableorjson(default:table)
Examples:
# Default format with statistics
skit ls
# JSON format for scripts using shorthand
skit -o json lsOutput includes:
- Safe file names
- Total number of secrets
- Number of encrypted vs plain text secrets
- Last modification time
Outputs secrets in shell-compatible format for direct sourcing into your shell.
Usage:
skit envExamples:
# Source all secrets into current shell
eval "$(skit env)"
# Save to .env file for other tools
skit env > .env
# Use with specific safe using shorthand
eval "$(skit -s myproject env)"
# Pipe to other tools
skit env | grep DATABASEOutput Format:
Produces shell-compatible KEY=VALUE lines:
API_KEY=sk-1234567890abcdef
PORT=3000
NODE_ENV=developmentSaves your safe key securely for automatic authentication, eliminating the need to enter passwords repeatedly.
Usage:
skit remember-safekeyExamples:
# Remember safe key for default safe
skit remember-safekey
# Remember safe key for specific safe using shorthand
skit -s myproject remember-safekey
# Remember safe key for production safe using shorthand
skit -s .production.safe remember-safekeyWhat it does:
- Prompts for your safe password to verify access
- Stores the password in
~/.config/skit/keys/<uuid>.key - Uses the safe's unique UUID for secure file naming
- Enables passwordless access for subsequent commands
Security:
- Keys are stored outside your project directory
- Each safe has a unique UUID-based filename
- Files are created with restricted permissions (600)
- Password verification ensures only valid keys are stored
SKIT can pull parameters from AWS SSM Parameter Store, enabling teams to share secrets via AWS IAM while maintaining local encrypted storage for development.
- Team Collaboration: Share secrets across team members using AWS IAM permissions instead of distributing safe keys
- Production Secrets: Pull production/staging parameters to local development environment
- CI/CD Integration: Access centralized secrets stored in SSM while keeping them encrypted locally
- Multi-Environment: Maintain separate SSM parameter paths for dev/staging/prod environments
-
AWS Credentials: Configure AWS credentials using one of these methods:
- Environment variables:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY - AWS credentials file:
~/.aws/credentials - IAM role (when running on EC2, ECS, Lambda, etc.)
- Environment variables:
-
IAM Permissions: Your AWS user/role needs these permissions:
{ "Effect": "Allow", "Action": [ "ssm:GetParametersByPath", "ssm:GetParameter" ], "Resource": "arn:aws:ssm:*:*:parameter/your-prefix/*" }
Pull parameters from AWS SSM Parameter Store into your local safe.
Usage:
skit ssm pull [--prefix <PATH>] [OPTIONS]Options:
--prefix <PATH>- SSM parameter path prefix (e.g.,/myapp/dev/). If omitted, SKIT uses the safe's stored#@SSM_PREFIX.--region <REGION>- AWS region (default: from AWS config)--replace- Replace all existing secrets (default: merge with existing)--no-overwrite- Don't overwrite existing keys (skip conflicts)--dry-run- Show what would be pulled without actually pulling
Examples:
# Pull all parameters from /myapp/dev/ prefix
skit ssm pull --prefix /myapp/dev/
# Pull from specific region
skit ssm pull --prefix /myapp/dev/ --region us-west-2
# Preview what would be pulled (dry run)
skit ssm pull --prefix /myapp/dev/ --dry-run
# Replace entire safe with SSM parameters
skit ssm pull --prefix /myapp/prod/ --replace
# Merge without overwriting existing keys
skit ssm pull --prefix /myapp/dev/ --no-overwrite
# Pull to a specific safe file
skit --safe .env.staging.safe ssm pull --prefix /myapp/staging/
# If a default prefix is stored (e.g., via `skit init --ssm-prefix /myapp/dev/`), you can simply run:
skit ssm pullSKIT preserves SSM's security model by mapping parameter types:
| SSM Type | SKIT Storage | Description |
|---|---|---|
SecureString |
Encrypted | KMS-encrypted in SSM β Re-encrypted with skit encryption locally |
String |
Plain text | Plain in SSM β Stored as plain text locally |
StringList |
Plain text | Comma-separated values treated as plain text |
Example:
If your SSM parameters are:
/myapp/dev/API_KEY (SecureString)
/myapp/dev/DATABASE_URL (SecureString)
/myapp/dev/NODE_ENV (String)
/myapp/dev/PORT (String)
After running skit ssm pull --prefix /myapp/dev/:
# Your .env.safe will contain:
#@SSM_PREFIX=/myapp/dev/
#@SSM_REGION=us-east-1
# SecureStrings are encrypted
API_KEY=ENC~v1~abc123...
DATABASE_URL=ENC~v1~def456...
# Strings are plain text
NODE_ENV=development
PORT=3000When you pull from SSM, SKIT stores metadata in the safe file:
#@SSM_PREFIX=/myapp/dev/
#@SSM_REGION=us-east-1This metadata:
- Tracks where parameters came from
- Enables future bidirectional sync features
- Documents the SSM source for team members
- Can be set upfront during initialization via
skit init --ssm-prefix /myapp/dev/
Scenario: Your team stores production secrets in AWS SSM, and you want to pull them for local development.
# 1. Configure AWS credentials (if not already configured)
aws configure
# 2. Pull parameters from SSM
skit ssm pull --prefix /myapp/dev/
# 3. Enter safe password to re-encrypt SecureString parameters
# (or use --remember during init to avoid password prompts)
# 4. View pulled secrets
skit print
# 5. Use secrets in your application
skit exec -- npm startSKIT strips the prefix from SSM parameter names by default:
| SSM Parameter Path | SKIT Key Name |
|---|---|
/myapp/dev/API_KEY |
API_KEY |
/myapp/dev/database/host |
database/host |
/myapp/dev/database/port |
database/port |
Note: Nested paths (e.g., database/host) are preserved in the key name. This is valid in skit but results in keys with slashes.
-
Re-encryption: SecureString parameters are decrypted from SSM (using AWS KMS) and immediately re-encrypted using skit's AES-256-GCM encryption with your safe password.
-
Local Storage: After pulling, secrets are stored locally in encrypted form. This allows offline access and version control while maintaining security.
-
AWS Credentials: SKIT uses the AWS SDK's default credential provider chain. Ensure your AWS credentials are properly secured.
-
IAM Permissions: Grant least-privilege access. Only provide
ssm:GetParameter*permissions for the specific parameter paths your team needs. -
Password Protection: You'll need your safe password to re-encrypt SecureString parameters. Consider using
remember-safekeyfor convenience.
Error: "No parameters found under prefix"
- Verify the prefix exists in SSM:
aws ssm get-parameters-by-path --path /myapp/dev/ - Ensure your prefix starts with
/ - Check you're in the correct AWS region
Error: "AWS authentication failed"
- Verify AWS credentials:
aws sts get-caller-identity - Check IAM permissions for
ssm:GetParametersByPath - Ensure credentials match the region where parameters are stored
Error: "Failed to decrypt SecureString"
- Verify KMS key permissions in SSM Parameter Store
- Check your IAM role has
kms:Decryptpermission for the KMS key
Planned features for SSM integration:
ssm push- Push local secrets to SSM Parameter Storessm sync- Bidirectional sync with conflict resolutionssm diff- Compare local safe with SSM parameters- Tag-based filtering for selective sync
SKIT supports multiple output formats for better integration:
Grouped display separating encrypted and plain text secrets:
π ENCRYPTED SECRETS (2)
ββ API_KEY: sk-1234567890abcdef
ββ DATABASE_URL: postgres://...
π PLAIN TEXT VALUES (2)
ββ PORT: 3000
ββ NODE_ENV: development
Structured output for scripts and automation:
{
"items": [
{
"key": "API_KEY",
"value": "sk-1234567890abcdef",
"type": "ENC"
},
{
"key": "PORT",
"value": "3000",
"type": "PLAIN"
}
]
}Shell-compatible output for sourcing:
API_KEY=sk-1234567890abcdef
PORT=3000
NODE_ENV=developmentHashiCorp Configuration Language (HCL) output for Terraform integration:
variable "API_KEY" {
type = string
sensitive = true
default = "sk-1234567890abcdef"
}
variable "PORT" {
type = string
default = "3000"
}
variable "NODE_ENV" {
type = string
default = "development"
}Safes use a simple .env-style format with metadata stored in comments:
# ========================================
# SKIT SAFE METADATA - DO NOT EDIT
# ========================================
#@VERSION=1.0
#@DESCRIPTION=My project secrets
#@CREATED=2025-08-21 16:15:00 UTC
#@UPDATED=2025-08-21 16:25:00 UTC
#@PASS_HASH=$argon2id$v=19$m=19456,t=2,p=1$salt$hash
# ========================================
# SECRETS (KEY=VALUE or KEY=ENC~<data>)
# ========================================
PORT=3000
BASE_URL=https://api.example.com
API_KEY=ENC~salt123~dGVzdGVuY3J5cHRlZHZhbHVl
DATABASE_PASSWORD=ENC~salt456~YW5vdGhlcmVuY3J5cHRlZHZhbA==- Plain text variables are stored as
KEY=value - Encrypted secrets are stored as
KEY=ENC~<salt>~<base64-encrypted-data> - Metadata uses
#@FIELD=valueformat to avoid conflicts with user comments - Files are safe to commit to version control
The examples/ directory contains demo applications:
A basic server that displays injected environment variables:
# Initialize safe with generated password (recommended for security)
skit init --generate
# Setup secrets
skit set API_KEY "sk-1234567890abcdef"
skit set API_URL "https://api.example.com" --plain
# Run server with injected secrets
skit exec -- node examples/server.jsVisit http://localhost:3000 to see how SKIT securely injects secrets into your application.
- Argon2 password hashing for verification
- AES-256-GCM encryption for secrets with per-secret salts
- Salt rotation capability for forward secrecy
- Encryption-first design - secrets never stored as plaintext
- Safe process execution - secrets don't appear in
psoutput - Git-safe format - encrypted values safe to commit
- Rust toolchain (install from https://rustup.rs)
- Git
# Clone the repository
git clone https://github.com/zstrikehq/skit.git
cd skit
# Build release version
cargo build --release
# Install locally
cargo install --path .
# Run tests
cargo test
# Run linter
cargo clippy
β οΈ Limited Windows Support: SKIT is primarily designed for Unix-like systems (Linux/macOS). Windows builds are possible but come with the following limitations:
- Secure file permissions (600) may not work as expected
- Shell detection features have limited functionality
- Some commands may behave differently due to platform differences
We recommend using SKIT on Linux or macOS for the best experience, or via WSL (Windows Subsystem for Linux) on Windows.
For Windows, cross-compilation is supported from Linux:
# Install Windows target
rustup target add x86_64-pc-windows-gnu
# Install MinGW
sudo apt-get install gcc-mingw-w64-x86-64 # Ubuntu/Debian
# or
sudo dnf install mingw64-gcc # Fedora
# Build Windows binary
cargo build --release --target x86_64-pc-windows-gnuNote on Windows Antivirus: The release build profile is optimized to reduce false positives:
- Size optimization (
opt-level = "z") - Link-time optimization (
lto = true) - Debug symbol stripping (
strip = true)
For production Windows releases, consider code signing with a certificate from DigiCert, Sectigo, or GlobalSign to eliminate antivirus warnings.
Contributions are welcome! Please feel free to submit issues, fork the repository, and create pull requests.
# Clone and setup
git clone https://github.com/zstrikehq/skit.git
cd skit
# Build and test
cargo build
cargo test
cargo clippy
# Format code
cargo fmt- Keep the code simple and focused
- Handle all error cases (avoid
.unwrap()) - Write tests for new features
- Follow Rust best practices
- Maintain backward compatibility with the .env format
This project is licensed under the MIT License - see the LICENSE file for details.
Built with Rust using:
clapfor CLI parsingaes-gcmfor encryptionargon2for password hashingcrosstermfor secure password input