vial

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2026 License: MIT

README ยถ


Go MIT License Platform

๐Ÿงช Vial

The centralized secret vault for vibe coders.
Store your API keys once. Pour them everywhere.

one-vial.org


The Problem

You're vibe coding. You've spun up 30 projects this month. Every single one needs some combination of OPENAI_API_KEY, STRIPE_SECRET_KEY, SUPABASE_URL, and a dozen more. You're copy-pasting from a password manager, a Notion doc, three old .env files, and that one Slack DM to yourself.

Then you rotate a key. Good luck updating all 30 projects.

The Fix

brew install cheesejaguar/tap/vial    # use the tap; "brew install vial" is a different package
go install github.com/cheesejaguar/vial/cmd/vial@latest

vial init            # create your encrypted vault
vial key set OPENAI_API_KEY
# โ†’ paste value (hidden)
# โ†’ โœ“ Stored.

cd ~/projects/my-new-app
vial pour
# โ†’ โœ“ OPENAI_API_KEY โ†’ matched from vault
# โ†’ โœ“ STRIPE_SECRET_KEY โ†’ matched from vault
# โ†’ โœ“ NEXT_PUBLIC_SUPABASE_URL โ†’ matched (prefix-stripped: SUPABASE_URL)
# โ†’ โœ— DATABASE_URL โ†’ not found in vault
# โ†’ .env created with 3/4 keys populated

That's it. Your .env.example is the template. Your vault is the source of truth. Vial pours the secrets in.


๐Ÿ”ฎ Features

Encrypted Vault

Your secrets live in a single encrypted file. Argon2id key derivation โ†’ AES-256-GCM per-value encryption. Key names stay readable for diffing; values are individually encrypted. Secured in memory with memguard.

๐Ÿซ— Pour

The core ritual. Reads your .env.example, matches each variable against your vault, and writes a .env. Handles conflicts intelligently โ€” prompts you when an existing value differs from the vault.

vial pour                    # populate .env from vault
vial pour --dry-run          # preview without writing
vial pour --force            # overwrite without asking
vial pour --all              # pour every registered project at once

๐Ÿง  Smart Matching (5-Tier Engine)

Vial doesn't just do exact matches. It understands your keys.

Tier Method Example
1 Exact match OPENAI_API_KEY = OPENAI_API_KEY
2 Normalize NEXT_PUBLIC_SUPABASE_URL โ†’ SUPABASE_URL
3 Alias & variants OPENAI_KEY โ†’ OPENAI_API_KEY
4 Comment-informed # Your Stripe secret key โ†’ STRIPE_SECRET_KEY
5 LLM-assisted Calls an inference API for truly ambiguous cases

Framework prefixes like NEXT_PUBLIC_, VITE_, REACT_APP_ are automatically stripped. Common suffix variants (_KEY โ†” _API_KEY โ†” _SECRET_KEY) are auto-detected.

๐Ÿท๏ธ Aliases

vial label set OPENAI_KEY=OPENAI_API_KEY
# Now any project asking for OPENAI_KEY gets your OPENAI_API_KEY

๐Ÿงช Distill

Already have secrets scattered in .env files? Import them.

vial distill .env            # import keys from an existing .env
vial distill --overwrite     # update existing vault keys

๐Ÿบ Brew

Run a command with secrets injected โ€” no .env file needed.

vial brew -- node server.js
vial brew -- python manage.py runserver

๐Ÿ“‚ Shelf (Project Registry)

Register projects for batch operations.

vial shelf add ~/projects/my-app
vial shelf add ~/projects/api-server
vial pour --all              # pour every shelved project

๐Ÿ”„ Key Rotation

Rotate once, propagate everywhere.

vial key set OPENAI_API_KEY  # update the value
vial pour --all              # re-pour all projects
# โ†’ 12 projects updated

๐Ÿ” Scaffold

Auto-generate .env.example from your source code.

vial scaffold                # scan current project for env var references
vial scaffold ./my-project   # scan specific directory
# โ†’ Generates .env.example with all discovered variables

Detects env vars in JavaScript, TypeScript, Python, Go, Ruby, Rust, and PHP.

๐Ÿš€ Setup (Zero-Config Onboarding)

One command to set up a new project โ€” scan, scaffold, register, pour, and hook.

cd ~/projects/my-new-app
vial setup                   # does everything below in one step:
# โ‘  Scans source code for env var references
# โ‘ก Generates .env.example if missing
# โ‘ข Registers project in shelf
# โ‘ฃ Pours secrets from vault
# โ‘ค Installs git pre-commit hook

๐Ÿ›ก๏ธ Secret Leak Prevention

Git pre-commit hook that scans staged files for leaked vault secrets.

vial hook install            # install pre-commit hook
vial hook check --staged     # manually check staged files
vial hook uninstall          # remove the hook

Create a .vialignore file to suppress false positives.

๐Ÿฉบ Secret Health

Track the age, rotation status, and health of your secrets.

vial health                                  # show health report
vial health --set-rotation STRIPE_SECRET_KEY=90  # rotate every 90 days
vial health --json                           # machine-readable output

๐Ÿค– MCP Server (AI Tool Integration)

Model Context Protocol server for Claude Code, Cursor, and other AI coding tools.

vial mcp                     # start read-only MCP server
vial mcp --allow-writes      # enable write operations

Configure in your MCP client (e.g. Claude Code settings.json):

{
  "mcpServers": {
    "vial": { "command": "vial", "args": ["mcp"] }
  }
}

๐Ÿ“ฆ Export Formats

Export secrets in various formats for containers, CI/CD, and scripts.

vial export --confirm-plaintext --format=docker-env-file  # Docker
vial export --confirm-plaintext --format=k8s-secret       # Kubernetes
vial export --confirm-plaintext --format=github-actions    # GitHub Actions
vial export --confirm-plaintext --format=shell             # Shell exports
vial export --confirm-plaintext --format=json --keys="STRIPE_*"  # Filtered

๐Ÿ“ฅ Import from External Sources

Import secrets from popular secret managers.

vial distill --from=json secrets.json        # JSON file
vial distill --from=1password                # 1Password CLI
vial distill --from=doppler                  # Doppler
vial distill --from=vercel                   # Vercel

๐Ÿ”— Secret Sharing

Create encrypted, time-limited secret bundles for teammates.

vial share OPENAI_API_KEY STRIPE_*           # create a bundle
vial share --all --expires=1h                # share everything, 1-hour expiry
vial share receive team-secrets.bundle       # import from a bundle

๐Ÿ“‹ Audit Log

Track all vault activity.

vial audit                   # show last 20 entries
vial audit --limit 50        # show more
vial audit --csv             # export for compliance

โšก GitHub Actions

Use vial in CI/CD workflows with the included GitHub Action.

- uses: cheesejaguar/vial@v1
  env:
    VIAL_MASTER_KEY: ${{ secrets.VIAL_MASTER_KEY }}

๐Ÿ–ฅ๏ธ Dashboard

A local web UI for browsing your vault, managing aliases, and checking secret health.

vial dashboard
# โ†’ Opens http://localhost:9876 in your browser

Dark-themed Svelte SPA with vault browser, alias management, project registry, and secret health indicators (age, rotation status, staleness).

๐Ÿ” Sync

Keep your vault in sync across machines.

vial sync push --backend filesystem --remote ~/iCloud/vial/vault.json
vial sync pull --backend filesystem --remote ~/iCloud/vial/vault.json
vial sync status --backend filesystem --remote ~/iCloud/vial/vault.json

Supports filesystem sync (iCloud, Dropbox, any mounted path). Git-based sync is experimental.


๐Ÿช„ Command Reference

Vial uses alchemical command names with standard aliases for the conventionally-minded.

Command Alias Description
vial init Create a new encrypted vault
vial cork lock Lock the vault, clear session
vial uncork unlock Unlock with master password
vial key set NAME set Store a secret (value via stdin)
vial key get NAME get Retrieve a secret
vial key list list, ls List all stored key names
vial key rm NAME rm Remove a secret
vial pour Populate .env from vault
vial distill [FILE] import Import keys from .env file or external source
vial brew -- CMD run Run command with injected secrets
vial diff Compare .env.example vs vault
vial scaffold Auto-generate .env.example from source code
vial setup Zero-config project onboarding
vial health Secret health report & rotation policies
vial hook install/uninstall/check Git pre-commit hook for leak prevention
vial mcp Start MCP server for AI coding tools
vial export Export secrets in various formats
vial share Create encrypted secret bundles
vial share receive Import from a shared bundle
vial audit View vault audit log
vial shelf add/list/rm project Manage project registry
vial label set/list/rm alias Manage key aliases
vial dashboard Launch web dashboard
vial sync push/pull/status Sync vault to/from remote
vial completion bash/zsh/fish Generate shell completions

๐Ÿ” Security Model

What we protect against:

  • Disk theft without master password โ€” vault encrypted at rest with AES-256-GCM
  • Shell history leaks โ€” secret values never accepted as CLI arguments
  • Swap exposure โ€” memguard uses mlock() to prevent secrets in swap
  • Backup exposure โ€” vault file contains only ciphertext

What we don't protect against:

  • Active malware with root access on a running system
  • Plaintext .env files (these are on you โ€” use .gitignore and full-disk encryption)

Encryption stack:

Master Password
  โ†’ Argon2id (64 MiB, 3 iterations, 1 parallelism)
  โ†’ 256-bit KEK
  โ†’ Encrypts randomly-generated DEK
  โ†’ DEK encrypts individual values via AES-256-GCM

Accepted trade-off: Reusing API keys across projects increases blast radius if the vault is compromised, in exchange for zero-friction deployment. This is the reality of solo developer workflows. Vial embraces it while providing the strongest practical encryption for the vault itself.


โš™๏ธ Configuration

Config lives at ~/.config/vial/config.yaml:

vault_path: ~/.local/share/vial/vault.json
session_timeout: 4h
env_example: .env.example
log_level: warn

# LLM-assisted matching (optional)
# llm:
#   provider: openrouter
#   endpoint: https://openrouter.ai/api/v1
#   model: anthropic/claude-sonnet-4-6
#   vault_key_ref: OPENROUTER_API_KEY

Override with environment variables (VIAL_VAULT_PATH, VIAL_SESSION_TIMEOUT, etc.) or the --config flag.

CI/CD

Set VIAL_MASTER_KEY to unlock the vault non-interactively:

export VIAL_MASTER_KEY="your-master-password"
vial pour  # no prompt needed

๐Ÿ—๏ธ Architecture

cmd/vial/main.go              โ†’ entry point
internal/
  vault/                       โ†’ Argon2id KDF, AES-256-GCM, CRUD, atomic storage
  parser/                      โ†’ .env parser (quotes, escapes, interpolation, multi-line)
  matcher/                     โ†’ 5-tier matching engine
  alias/                       โ†’ alias store, pattern rules, auto-detection
  project/                     โ†’ project registry
  llm/                         โ†’ LLM provider abstraction (OpenAI, Anthropic, OpenRouter)
  scanner/                     โ†’ source code env var extraction (JS, Python, Go, Ruby, Rust, PHP)
  dashboard/                   โ†’ embedded Svelte web dashboard
  keyring/                     โ†’ OS keychain session caching
  config/                      โ†’ YAML config via Viper
  sync/                        โ†’ vault sync (filesystem, git)
web/                           โ†’ SvelteKit dashboard SPA
vscode/                        โ†’ VS Code extension (coming soon)

Single static binary. No runtime dependencies. ~9 MB with the embedded dashboard.


๐Ÿ“„ License

MIT โ€” do whatever you want with it.


Potent secrets, safely contained.

Directories ยถ

Path Synopsis
cmd
vial command
internal
cli
llm
mcp

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL