Salakala
Generate environment variables from various secret providers via URIs in JSON files, checked into your repository
Install / Use
/learn @auth70/SalakalaREADME
salakala
<p> <a href="https://github.com/auth70/salakala/actions"><img src="https://img.shields.io/github/actions/workflow/status/auth70/salakala/publish.yml?logo=github" alt="build"></a> <a href="https://www.npmjs.com/package/salakala"><img src="https://img.shields.io/npm/v/salakala" alt="npm"></a> <a href="https://www.npmjs.com/package/salakala"><img src="https://img.shields.io/npm/types/salakala" alt="npm type definitions"></a> </p>Generate environment variables from (multiple) secret providers using a JSON configuration file checked into your repository. Output to .env files or export directly to your shell, or use in CI environments. Supports JSON field access, secret synchronization between providers, and more. Contains an extensive test suite with full end-to-end coverage.
{
"DATABASE_URL": "op://application-secrets/db/url",
"API_KEY": "awssm://us-east-1/prod/api-key"
}
Integrates with 1Password, Bitwarden, AWS Secrets Manager, Google Cloud Secret Manager, Azure Key Vault, KeePass, and LastPass.
Installation
Install globally to use as a regular CLI:
npm install -g salakala
Or install in your project:
npm install --save-dev salakala
and then add a script to your package.json:
"scripts": {
"salakala": "salakala"
}
Usage
Create a salakala.json configuration file in your project root, then run salakala to fetch secrets and generate environment variables.
Basic Commands
salakala # Generate .env file from salakala.json
salakala -s # Export variables to current shell
salakala -e staging # Use specific environment configuration
salakala -i config.json # Use alternative input file
salakala -o .env.local # Write to alternative output file
salakala -w # Overwrite existing file instead of merging
salakala import # Import variables to secret provider (interactive)
salakala import -i .env.prod # Import from specific file
salakala sync # Synchronize secrets between providers
salakala sync --dry-run # Preview sync without writing
salakala --help # Show help
Configuration
<details> <summary><b>Basic Configuration</b></summary>Flat structure for single-environment setups:
{
"DATABASE_URL": "op://vault/database/url",
"API_KEY": "awssm://us-east-1/prod/api-key"
}
</details>
<details>
<summary><b>Multi-Environment Configuration</b></summary>
Nested structure for environment-specific secrets:
{
"development": {
"DATABASE_URL": "op://vault/dev-database/url",
"API_KEY": "awssm://us-east-1/dev/api-key"
},
"production": {
"DATABASE_URL": "op://vault/prod-database/url",
"API_KEY": "awssm://us-east-1/prod/api-key"
}
}
</details>
<details>
<summary><b>Environment Variable Substitution</b></summary>
Use ${VARIABLE_NAME} syntax to reference environment variables in secret paths:
{
"development": {
"API_KEY": "gcsm://projects/${PROJECT_ID}/secrets/api-key/versions/latest"
}
}
Ensure variables are set before execution:
PROJECT_ID=my-project salakala
</details>
<details>
<summary><b>Non-Secret Values</b></summary>
Include static configuration alongside secrets. Values without provider prefixes are passed through unchanged:
{
"DB_PASSWORD": "op://vault/database/password",
"APP_NAME": "My Application",
"LOG_LEVEL": "info"
}
</details>
<details>
<summary><b>JSON Field Access</b></summary>
Extract specific fields from JSON-structured secrets using the :: separator.
Syntax:
provider://path/to/secret::jsonKey
The :: separator instructs salakala to fetch the secret, parse it as JSON, extract the specified field, and return it as a string.
Supported patterns:
- Simple key:
::username - Nested object:
::database.hostor::api.credentials.key - Array index:
::servers[0]or::endpoints[1].url - First array item:
::items[]
Example:
Given a secret containing:
{
"database": {
"host": "localhost",
"credentials": {
"username": "admin",
"password": "secret123"
}
},
"servers": ["web1", "web2", "api"]
}
Extract specific fields:
{
"DB_HOST": "op://vault/config::database.host",
"DB_USER": "op://vault/config::database.credentials.username",
"DB_PASS": "op://vault/config::database.credentials.password",
"WEB_SERVER": "op://vault/config::servers[0]"
}
</details>
Secret Synchronization
Synchronize secrets across multiple providers using src and dst configuration.
Configuration
{
"production": {
"src": {
"API_KEY": "op://vault/api-key/password",
"DATABASE_URL": "op://vault/database/connection-string"
},
"dst": {
"API_KEY": [
"gcsm://projects/my-project/secrets/api-key/versions/latest"
],
"DATABASE_URL": [
"gcsm://projects/my-project/secrets/db-url/versions/latest",
"awssm://us-east-1/prod/database-url"
]
}
}
}
src: Source provider URIs for reading secretsdst: Destination provider URIs for writing secrets (supports multiple destinations per secret)- Only secrets defined in
dstwill be synchronized
Sync Commands
salakala sync # Sync all secrets in dst
salakala sync -e production # Sync specific environment
salakala sync -s API_KEY # Sync single secret
salakala sync --dry-run # Preview changes without writing
salakala sync -y # Skip prompts and overwrite (for CI/automation)
Conflict Resolution
When a secret exists at the destination, you will be prompted unless using the -y flag:
- Y - Overwrite this secret
- N - Skip this secret
- D - Show diff between current and new value
- A - Overwrite all remaining conflicts
- Q - Quit synchronization
Use salakala sync -y in CI/CD pipelines to automatically overwrite without prompts.
Importing from .env Files
Import existing environment variables from .env files into secret providers. The interactive wizard guides you through selecting variables, choosing a provider, and configuring storage.
Import Command
salakala import # Interactive wizard (prompts for file or paste)
salakala import -i .env.prod # Import from specific file
You will be walked through the import process.
Storage Modes
<details> <summary><b>JSON Bundle Storage (Recommended)</b></summary>Stores all variables as JSON in a single secret field. Ideal for providers supporting multiple fields (1Password, Bitwarden, KeePass, LastPass).
Advantages:
- Fewer secrets to manage
- Atomic updates
- Better organization
- Reduced API calls
Example output:
{
"production": {
"src": {
"API_KEY": "op://vault/app-config/config::API_KEY",
"DATABASE_URL": "op://vault/app-config/config::DATABASE_URL",
"SECRET_KEY": "op://vault/app-config/config::SECRET_KEY"
},
"dst": {}
}
}
The JSON bundle is stored in op://vault/app-config/config and individual fields are extracted using :: syntax.
Stores each variable as a separate field (1Password, Bitwarden, etc.) or separate secret (AWS, GCP, etc.).
Advantages:
- Granular access control per secret
- Independent versioning
- Works with all providers
Example output (multi-field provider):
{
"production": {
"src": {
"API_KEY": "op://vault/app-config/API_KEY",
"DATABASE_URL": "op://vault/app-config/DATABASE_URL"
},
"dst": {}
}
}
Example output (single-value provider):
{
"production": {
"src": {
"API_KEY": "awssm://us-east-1/prod/API_KEY",
"DATABASE_URL": "awssm://us-east-1/prod/DATABASE_URL"
},
"dst": {}
}
}
</details>
Example Workflow
# Import production secrets from .env.production
salakala import -i .env.production
# Interactive prompts:
# ✓ Select variables: [x] DATABASE_URL [x] API_KEY [x] SECRET_KEY
# ✓ Provider: 1Password (op://)
# ✓ Vault: production-vault
# ✓ Item: app-secrets
# ✓ Store as JSON? Yes
# ✓ Field name: config
# ✓ Environment: production
# Creates salakala.json and writes secrets to 1Password
# Use the generated config:
salakala -e production
Tips
- JSON bundle storage is recommended for better organization and fewer API calls
- For cloud providers (AWS, GCP), JSON bundle creates one secret with all variables
- Use
dstconfiguration later to sync imported secrets to other providers - The import wizard validates all inputs before writing
Providers
<details> <summary><b>1Password</b> <code>op://</code></summary>Requirements: 1Password CLI (op)
Features:
- Tested in CI
- Interactive login
- Non-interactive login via environment variables
- Write support
- JSON field access
Format:
op://vault-name/item-name/[section-name/]field-name[::jsonKey]
Example:
op://Personal/AWS/access-key
op://Development/config/database::host
</details>
<details>
<summary><b>Bitwarden</b> <code>bw://</code></summary>
Requirements: Bitwarden CLI (bw)
Features:
- Tested in CI
- Interactive login
- Non-interactive login via environment variables
- Write support
Format:
bw://[folder]/item-name-or-id/field[::json-key]
Examples:
Access by item ID:
bw://1c9448b3-3d30-4f01-8d3c-3a4b8d14d00a/password
Access by item name and folder:
bw://my-folder/my-item/password
Access JSON field in notes:
bw://my-folder/my-item/notes::foo.bar[1]
Access login URIs:
bw://my-folder/my-item/uris/0
</details>
<details>
<summary><b>KeePassXC</b> <code>kp://</code></summary>
Requirements: KeePassXC CLI (keepassxc-cli)
Features:
- Tested in CI
- Interactive login
Related Skills
node-connect
347.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
347.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
347.0kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
