xenvsync

Command Reference

Complete reference for all xenvsync commands, flags, and usage examples.

Quick Reference

CommandAliasDescription
initGenerates a cryptographically secure 256-bit AES key, saves it to
pushencryptReads the plaintext
pulldecryptReads the encrypted
runDecrypts the vault in-memory and spawns a child process with the decrypted variables merged into the environment
diffDecrypts the vault and compares its contents to the current
statusReports the presence and last-modified time of
envsScans the current directory for
exportDecrypts the vault and writes variables to stdout in the specified format
team addRegisters a team member by name and their X25519 public key (base64-encoded, as shown by 'xenvsync whoami')
team removeRemoves a team member from the project roster by name, revoking their ability to decrypt future vaults
team listDisplays all team members in the project roster with their public keys and the date they were added
doctorAudits the local xenvsync setup for security issues
verifyValidates vault file structural integrity, performs GCM authentication to detect tampering, checks for duplicate keys in
logParses Git history for commits that modified the vault file and displays a timeline of changes
rotateRotates the encryption key and re-encrypts the vault in one atomic step
keygenGenerates an X25519 keypair and stores the private key in ~/
whoamiReads your X25519 private key from ~/
completionGenerates shell completion scripts for bash, zsh, fish, or powershell
versionPrints the version, commit hash, and build date

init

Generates a cryptographically secure 256-bit AES key, saves it to .xenvsync.key with owner-only permissions (0600), and ensures the key file and .env are in .gitignore.

Usage

xenvsync init [flags]

Flags

--force, -fOverwrite existing key file (regenerate key)
--passphraseEncrypt the key file with a passphrase (requires XENVSYNC_PASSPHRASE env var)

Example

$ xenvsync init
Generated encryption key → .xenvsync.key (mode 0600)
Updated .gitignore (added .xenvsync.key, .env)

# Regenerate key
$ xenvsync init --force

# Passphrase-protected key
$ export XENVSYNC_PASSPHRASE="my-secret-passphrase"
$ xenvsync init --passphrase
Generated passphrase-protected encryption key → .xenvsync.key (mode 0600)

push

alias: encrypt

Reads the plaintext .env file, encrypts it using AES-256-GCM, and writes the ciphertext to .env.vault. The vault file is safe to commit to version control.

Usage

xenvsync push [flags]

Flags

--envEnvironment name (e.g., staging, production)
--file, -ePath to the .env file (default: .env)
--out, -oPath to the output vault file (default: .env.vault)
--no-fallbackDisable .env.shared and .env.local merging

Example

$ xenvsync push
Encrypted 5 variable(s) → .env.vault

# Named environment (merges .env.shared < .env.staging < .env.local)
$ xenvsync push --env staging
Encrypted 7 variable(s) → .env.staging.vault

# Disable fallback merging
$ xenvsync push --env staging --no-fallback
Encrypted 3 variable(s) → .env.staging.vault

pull

alias: decrypt

Reads the encrypted .env.vault, decrypts it using the local .xenvsync.key, and writes the plaintext variables to .env.

Usage

xenvsync pull [flags]

Flags

--envEnvironment name (e.g., staging, production)
--vault, -vPath to the vault file (default: .env.vault)
--out, -oPath to the output .env file (default: .env)

Example

$ xenvsync pull
Decrypted 5 variable(s) → .env

# Named environment
$ xenvsync pull --env staging
Decrypted 3 variable(s) → .env.staging

# Custom paths
$ xenvsync pull -v .env.staging.vault -o .env.staging

run

Decrypts the vault in-memory and spawns a child process with the decrypted variables merged into the environment. Plaintext secrets never touch disk — they exist only in the child process's memory.

Usage

xenvsync run [flags] -- <command> [args...]

Flags

--envEnvironment name (e.g., staging, production)
--vault, -vPath to the vault file (default: .env.vault)

Example

$ xenvsync run -- npm start
$ xenvsync run --env staging -- npm start
$ xenvsync run -- python manage.py runserver
$ xenvsync run -- docker compose up

diff

Decrypts the vault and compares its contents to the current .env file. Shows added, removed, and changed variables. Values are hidden by default for security — use --show-values to reveal them.

Usage

xenvsync diff [flags]

Flags

--envEnvironment name (e.g., staging, production)
--file, -ePath to the .env file (default: .env)
--vault, -vPath to the vault file (default: .env.vault)
--show-valuesDisplay actual values in output (sensitive)

Example

$ xenvsync diff
+ NEW_KEY  (in .env only, not yet pushed)
- OLD_KEY  (in vault only, not yet pulled)
~ API_KEY  (changed)
3 change(s): 1 added, 1 modified, 1 removed.

# Show actual values
$ xenvsync diff --show-values
+ NEW_KEY=value     (in .env only, not yet pushed)
- OLD_KEY=removed   (in vault only, not yet pulled)
~ API_KEY  (changed)
    .env:   sk-new-key
    vault:  sk-old-key
3 change(s): 1 added, 1 modified, 1 removed.

status

Reports the presence and last-modified time of .xenvsync.key, .env, and .env.vault. Warns about insecure key file permissions and suggests whether to push or pull.

Usage

xenvsync status [flags]

Flags

--envEnvironment name (e.g., staging, production)

Example

$ xenvsync status
xenvsync status
───────────────────────────────────────
  Key file  .xenvsync.key     2026-03-21 10:00:00  (0600)
  Env file  .env              2026-03-21 10:05:00  (0644)
  Vault     .env.vault        2026-03-21 09:30:00  (0644)
───────────────────────────────────────
  .env is newer than vault → consider running: xenvsync push

# Named environment
$ xenvsync status --env staging

envs

Scans the current directory for .env.* and .env.*.vault files and displays all discovered environments with their sync status.

Usage

xenvsync envs

Example

$ xenvsync envs
Discovered environments:
───────────────────────────────────────
  (default)      .env + .env.vault                    synced
  staging        .env.staging + .env.staging.vault     synced
  production     .env.production.vault                 not pulled

export

Decrypts the vault and writes variables to stdout in the specified format. Output is always written to stdout (never to disk) to preserve the security model.

Usage

xenvsync export [flags]

Flags

--envEnvironment name (e.g., staging, production)
--format, -fOutput format: dotenv, json, yaml, shell, tfvars (default: dotenv)
--vault, -vPath to the vault file (default: .env.vault)

Example

# Export as JSON
$ xenvsync export --format=json
{
  "DB_HOST": "localhost",
  "API_KEY": "sk-secret"
}

# Inject into current shell
$ eval $(xenvsync export --format=shell)

# Pipe to other tools
$ xenvsync export -f yaml | kubectl create configmap

team add

Registers a team member by name and their X25519 public key (base64-encoded, as shown by 'xenvsync whoami'). The roster is stored in .xenvsync-team.json and should be committed to version control.

Usage

xenvsync team add <name> <public-key>

Example

$ xenvsync team add alice dGhpcyBpcyBhIGJhc2U2NCBwdWJsaWMga2V5...
Added alice to team roster (.xenvsync-team.json)
  Public key: dGhpcyBpcyBhIGJhc2U2NCBwdWJsaWMga2V5...

Roster now has 2 member(s).

team remove

Removes a team member from the project roster by name, revoking their ability to decrypt future vaults.

Usage

xenvsync team remove <name>

Example

$ xenvsync team remove alice
Removed alice from team roster
Roster now has 1 member(s).

team list

Displays all team members in the project roster with their public keys and the date they were added.

Usage

xenvsync team list

Example

$ xenvsync team list
Team roster (2 member(s)):
  NAME     PUBLIC KEY                                    ADDED
  alice    dGhpcyBpcyBhIGJhc2U2NCBwdWJsaWMga2V5...      2026-03-30
  bob      Ym9iJ3MgcHVibGljIGtleQ==...                   2026-03-30

doctor

Audits the local xenvsync setup for security issues. Checks key file existence, permissions, strength, .gitignore entries, vault structure and decryptability, stale vault detection, and X25519 identity configuration.

Usage

xenvsync doctor [flags]

Flags

--envEnvironment name (e.g., staging, production)

Example

$ xenvsync doctor
xenvsync doctor
───────────────────────────────────────
  OK  Key file .xenvsync.key exists
  OK  Key file permissions: 0600
  OK  Key strength: 256 bits
  OK  .xenvsync.key in .gitignore
  OK  .env in .gitignore
  OK  Vault structure: valid V1
  OK  Vault decrypt: OK (45 bytes)
  OK  Vault is up to date
  OK  Identity: /home/you/.xenvsync/identity
───────────────────────────────────────
  9 passed, 0 warning(s), 0 failed, 0 skipped

# Named environment
$ xenvsync doctor --env staging

verify

Validates vault file structural integrity, performs GCM authentication to detect tampering, checks for duplicate keys in .env files, and warns about stale vaults. Without a key, only structural checks run; with a key, full decrypt and authenticate is performed.

Usage

xenvsync verify [flags]

Flags

--envEnvironment name (e.g., staging, production)

Example

$ xenvsync verify
PASS  vault structure — valid V1 vault
PASS  vault decrypt — GCM authenticated, 5 variable(s)
PASS  duplicate keys — no duplicates in .env
PASS  vault freshness — .env.vault is up to date

Verification complete: 4 passed

# With warnings
$ xenvsync verify
PASS  vault structure — valid V1 vault
PASS  vault decrypt — GCM authenticated, 5 variable(s)
WARN  duplicate key "API_KEY" appears 2 times in .env
WARN  stale vault — .env is newer than .env.vault (consider running: xenvsync push)

Verification complete: 2 passed, 2 warning(s)

# Named environment
$ xenvsync verify --env staging

log

Parses Git history for commits that modified the vault file and displays a timeline of changes. For each commit, shows which keys were added, modified, or removed. Values are hidden by default.

Usage

xenvsync log [flags]

Flags

--envEnvironment name (e.g., staging, production)
--show-valuesDisplay actual decrypted values (sensitive)
-n, --limitMaximum number of commits to show (default: 10)

Example

$ xenvsync log
Vault history for .env.vault (3 commit(s)):

commit a1b2c3d (2026-04-01, alice)
  Update API keys for v2
  ~ API_KEY  (changed)
  + NEW_SERVICE_URL  (in new only, not yet pushed)
  2 change(s): 1 added, 1 modified.

commit d4e5f6a (2026-03-30, bob)
  Initial secrets
  + DB_HOST  (in new only, not yet pushed)
  + API_KEY  (in new only, not yet pushed)
  2 change(s): 2 added.

# Show values (sensitive)
$ xenvsync log --show-values

# Limit to last 5 commits
$ xenvsync log -n 5

# Named environment
$ xenvsync log --env staging

rotate

Rotates the encryption key and re-encrypts the vault in one atomic step. In V1 mode, generates a new symmetric key. In V2 (team) mode, re-encrypts for all current roster members with fresh ephemeral keys. Use --revoke to remove a member and rotate simultaneously.

Usage

xenvsync rotate [flags]

Flags

--envEnvironment name (e.g., staging, production)
--revokeRemove a team member and rotate in one step

Example

# V1: rotate symmetric key
$ xenvsync rotate
Rotated key → .xenvsync.key (mode 0600)
Rotated vault → .env.vault
Rotation complete. 5 variable(s) re-encrypted.

# V2: re-encrypt for all team members
$ xenvsync rotate
Rotated vault → .env.vault (V2, 3 recipient(s))
Rotation complete. 5 variable(s) re-encrypted.

# Revoke a member and rotate
$ xenvsync rotate --revoke exmember
Revoked exmember from team roster
Rotated vault → .env.vault (V2, 2 recipient(s))

# Rotate a named environment
$ xenvsync rotate --env staging

keygen

Generates an X25519 keypair and stores the private key in ~/.xenvsync/identity with restricted permissions (0600). The public key is printed to stdout for sharing with teammates. This identity is user-global (not per-project).

Usage

xenvsync keygen [flags]

Flags

--force, -fOverwrite existing identity (regenerate keypair)

Example

$ xenvsync keygen
Generated X25519 identity → /home/you/.xenvsync/identity (mode 0600)

Your public key:
  dGhpcyBpcyBhIGJhc2U2NCBwdWJsaWMga2V5...

Share this public key with your team to be added to project vaults.

# Regenerate identity
$ xenvsync keygen --force

whoami

Reads your X25519 private key from ~/.xenvsync/identity, derives the public key, and prints it in a copy-paste-friendly format.

Usage

xenvsync whoami

Example

$ xenvsync whoami
Identity:   /home/you/.xenvsync/identity
Public key: dGhpcyBpcyBhIGJhc2U2NCBwdWJsaWMga2V5...

completion

Generates shell completion scripts for bash, zsh, fish, or powershell. Source the output in your shell profile for tab completion of commands and flags.

Usage

xenvsync completion [bash|zsh|fish|powershell]

Example

# Bash (add to ~/.bashrc)
$ source <(xenvsync completion bash)

# Zsh (add to ~/.zshrc)
$ source <(xenvsync completion zsh)

# Fish
$ xenvsync completion fish > ~/.config/fish/completions/xenvsync.fish

# PowerShell
$ xenvsync completion powershell | Out-String | Invoke-Expression

version

Prints the version, commit hash, and build date. Build info is injected at compile time via ldflags.

Usage

xenvsync version

Example

$ xenvsync version
xenvsync v1.1.0
  commit: abc1234
  built:  2026-03-29T00:00:00Z

Global Help

Every command supports --help for inline documentation.

$ xenvsync --help
$ xenvsync push --help