CLI Usage Reference
Command quick reference
| Command | Synopsis | Passphrase? |
|---|---|---|
init |
amulet init [--file <vault>] |
No |
seal |
amulet seal [--portable] <key> [--file <vault>] |
Yes (TTY) |
unseal |
amulet unseal [--tty] <key> [--file <vault>] |
Yes (stdin or TTY) |
verify |
amulet verify [--tty] <key> [--file <vault>] |
Yes (stdin or TTY) |
re-seal |
amulet re-seal <key> [--file <vault>] |
Yes (old + new, TTY) |
import |
amulet import --env-file <path> [--portable] [--manifest <path>] [--wipe] [--wipe-comment] [--file <vault>] |
Yes (TTY) |
list |
amulet list [--file <vault>] |
No |
delete |
amulet delete <key> [--file <vault>] |
No |
rename |
amulet rename <old> <new> [--file <vault>] |
No |
probe |
amulet probe |
No |
version |
amulet version |
No |
help |
amulet help | -h | --help |
No |
--file <vault> defaults to amulet.vault in the current directory when omitted.
init
amulet init --file secrets.vaultCreates an empty vault file (mode 0600 on Unix). Does not ask for a passphrase. Fails with exit code 1 if the file already exists.
seal
# Locked Mode (default): binds to this machine's OS-reported identifier
echo -n "your-secret-value" | amulet seal OPENAI_API_KEY --file secrets.vault
# Portable Mode: passphrase only, no machine identifier binding
echo -n "your-secret-value" | amulet seal --portable OPENAI_API_KEY --file secrets.vault- Passphrase is prompted from
/dev/tty(echo off). The secret comes from stdin only — never from argv. - If the key already exists, the entry is overwritten.
--portableprints a warning to stderr and sets a flag in the vault header thatunsealreads automatically.
Shell history:
echo 'secret' | …may leave the secret in shell history. For production, prefer stdin from your CI secret store. In bash, prefixing the command with a space suppresses recording whenHISTCONTROLis set toignorespaceorignoreboth— but this is shell-specific and depends on user configuration, not a universal guarantee. The equivalent in zsh issetopt HIST_IGNORE_SPACE. For sensitive values, prefer a secret store or file-based source overecho. If unsure, runecho testin your shell and checkhistoryto confirm what actually gets recorded.
unseal
# Interactive: passphrase prompted from /dev/tty with echo off
amulet unseal --tty OPENAI_API_KEY --file secrets.vault
# Script / CI: passphrase from stdin first line
printf "mypassphrase\n" | amulet unseal OPENAI_API_KEY --file secrets.vault
# Capture to a shell variable
SECRET=$(printf "mypassphrase\n" | amulet unseal OPENAI_API_KEY --file secrets.vault)- Locked vs Portable mode is auto-detected from the vault header — no flag needed on unseal.
- On success: secret written to stdout (no trailing newline), exit code 0.
- On any failure: no output, exit code 1.
Checking exit code in scripts:
if ! printf "mypassphrase\n" | amulet unseal OPENAI_API_KEY --file secrets.vault > /dev/null; then
echo "unseal failed" >&2; exit 1
fiUnseal prints nothing? Check in order:
- Passphrase — same as at
seal, trailing newline included when piping. - Vault path —
--filepoints to the correct file and it exists. - Key name — exact spelling (case-sensitive). Use
amulet listto confirm. - Locked mode — entry was sealed on a machine with the same machine_id. A vault copied to a host with a different machine_id fails.
- Exit code —
echo $?(Unix) orecho $LASTEXITCODE(PowerShell) should be1.
verify
# Passphrase from stdin
printf "mypassphrase\n" | amulet verify OPENAI_API_KEY --file secrets.vault
# Passphrase from /dev/tty with echo off
amulet verify --tty OPENAI_API_KEY --file secrets.vaultDecrypts and immediately discards the plaintext — no output on success, exit code 0. Exit code 1 on any failure. Useful for CI health checks without exposing the secret value.
re-seal
amulet re-seal OPENAI_API_KEY --file secrets.vaultPrompts for the current passphrase, a new passphrase, and a confirmation — all from /dev/tty with echo off. The Locked/Portable mode of the entry is preserved; the re-encrypted blob replaces the original.
import
# Basic import
amulet import --env-file .env --file secrets.vault
# Write a key-names-only manifest for git
amulet import --env-file .env --file secrets.vault --manifest .env.example
# Wipe .env values after a successful import
amulet import --env-file .env --file secrets.vault --wipe
# Same, plus append a comment line so readers know values were wiped on purpose
amulet import --env-file .env --file secrets.vault --wipe --wipe-comment
# Portable mode
amulet import --env-file .env --file secrets.vault --portable- Reads
KEY=VALUElines (blank lines and#comments are skipped). - Existing keys are overwritten.
Note: Quotes and
export KEY=…syntax are not supported. A line likeexport API_KEY=foowill be skipped silently — remove theexportprefix before importing.
- The passphrase is prompted once for all entries.
--manifest <path> writes one key name per line (truncates if it exists). Commit this file instead of .env so teammates know which secrets are required.
--wipe overwrites the value portion of each line with spaces after the vault write succeeds. Best-effort — on SSDs, physical erasure is not guaranteed.
--wipe-comment may only be used with --wipe. After a successful wipe it appends one # … line (LF) to the end of the .env file if that exact line is not already present — useful so teammates do not mistake wiped values for file corruption. This leaves a small informational trace that Amulet was used.
list
amulet list --file secrets.vaultPrints one key name per line. No passphrase required. Exit code 1 if the vault is missing, unreadable, or corrupt.
delete
amulet delete OPENAI_API_KEY --file secrets.vaultRemoves the entry from the vault without a passphrase. Exit code 1 if the key is missing or the vault is invalid.
rename
amulet rename OLD_KEY_NAME NEW_KEY_NAME --file secrets.vaultRenames a key in the vault index without a passphrase and without re-encrypting the blob. Exit code 1 if the old key is missing, the new key already exists, or the vault is invalid.
probe
amulet probePrints the machine identifier used for Locked-mode sealing. Useful for troubleshooting cross-machine failures. Exit code 2 if the ID cannot be read.
version / help
amulet version # prints the release tag, e.g. v0.1.2
amulet help # same as -h or --helpNode.js / TypeScript
Copy wrappers/node/amulet.ts into your project. It spawns amulet unseal and passes the result as an opaque Buffer to your callback, then zeros it on exit.
import { withSecret } from './wrappers/node/amulet';
const passphraseBuf = Buffer.from(process.env.VAULT_PASSPHRASE!, 'utf8');
await withSecret('OPENAI_API_KEY', 'secrets.vault', passphraseBuf, async (secret) => {
// secret is a Buffer — do not cast to string, do not store outside this callback.
await callExternalApi(secret);
});
// Buffer is zeroed automatically after the callback returns, even if it throws.Use the binaryPath option to specify a non-PATH location for the amulet binary.
File naming conventions
| File | Example | Notes |
|---|---|---|
| Vault (encrypted) | secrets.vault, prod.vault |
Safe to commit to git. |
| Temporary .env | .env.tmp, .secrets.env |
Add to .gitignore. Plaintext briefly exists on disk. |
If you generate a plaintext .env as a development bridge, enforce trap-based deletion and .gitignore registration.