Local file sync
run, export, import, status, and sync — moving secrets between the server and your filesystem.
vaultic run
vaultic run -- <command...>
vaultic run --command "<shell command>"Fetches secrets and injects them as env vars directly into a subprocess — nothing touches disk.
| Flag | Description |
|---|---|
-e, --env <environment> | |
--watch | Poll for secret changes and restart the subprocess when they change |
--poll-interval <ms> | Watch poll interval in milliseconds (default 2000, floor 500) |
-c, --command <command> | Shell command string to run instead of -- <command> |
vaultic run -- printenv FOO
vaultic run --env production --watch -- node server.jsFlags after -- pass straight through to the child command. In --watch mode it diffs the
resolved secret set on each poll and restarts the child on any change, forwarding
SIGINT/SIGTERM to it.
Chaining multiple commands
-- <command...> spawns the command directly, without a shell, so shell operators like &&
aren't available. To chain multiple commands, pass a single string to --command instead — it's
handed to /bin/sh -c (or cmd.exe /c on Windows), so &&, ||, and ; all work:
vaultic run --command "npm run build && npm run migrate && npm start"-- <command...> and --command are mutually exclusive.
vaultic export
Writes a local secrets file from the server — dotenv by default, with a checksum header.
| Flag | Description |
|---|---|
-e, --env <environment> | |
--format <format> | dotenv | json | yaml | shell | appsettings |
--path <path> | Output file path |
--no-header | Omit the generated-by header/checksum |
--check | Fail (exit 1) if the local file is stale vs. the server — for CI |
--section <path> | appsettings only: namespace exported secrets under one top-level key |
--delimiter <sep> | appsettings only: section-separator for nested keys (default __) |
Defaults come from .vaultic.yaml's export block (see Configuration). If
--format is given without --path, output goes to stdout instead of a file.
--format appsettings (.NET appsettings.json)
Turns Vaultic's flat secret keys into a nested appsettings.{Environment}.json, matching how
IConfiguration/IOptions<T> binds hierarchical config. __ (double underscore) is the section
separator — the same convention .NET's own env-var configuration provider uses — so
CONNECTIONSTRINGS__DEFAULTCONNECTION becomes:
{ "CONNECTIONSTRINGS": { "DEFAULTCONNECTION": "..." } }Keys are written uppercase, as-is — IConfiguration binds case-insensitively, so this works
functionally even though it doesn't match hand-written .NET casing.
Unlike the other four formats, this one merges into an existing file instead of overwriting
it, since appsettings.json is normally a checked-in file the team already partly owns
(Logging, AllowedHosts, feature flags, etc.).
- If the target file doesn't exist yet, it's written fresh.
- If it exists, it's parsed as JSON and Vaultic's generated tree is deep-merged into it. A key that's a nested object on one side and a scalar value on the other is a hard error — Vaultic never guesses which side should win.
- The merge does not preserve comments, if the existing file has any.
Default output path is appsettings.{Environment}.json (e.g. appsettings.Production.json),
Pascal-cased from the Vaultic environment name — override with --path / export.path as usual.
--check can't diff the whole file (part of it may be hand-authored), so the staleness checksum
is embedded as a reserved __checksum key inside the scope Vaultic manages (root, or under
--section if set) instead of the comment header the other formats use.
--section vaultic namespaces every exported secret under one top-level key, so it's structurally
impossible for a secret to collide with an unrelated hand-authored section:
vaultic export --format appsettings --section Vaultic{
"Logging": { "LogLevel": { "Default": "Information" } },
"Vaultic": {
"CONNECTIONSTRINGS": { "DEFAULTCONNECTION": "..." },
"__checksum": "..."
}
}vaultic import
vaultic import <file>Imports an existing .env, flat JSON, or nested appsettings.json file into Vaultic.
| Flag | Description |
|---|---|
<file> | Required — path to a .env, JSON, or appsettings.json file |
-e, --env <environment> | Environment to import into |
--prefix <prefix> | Prefix to prepend to every imported key |
--dry-run | Show what would be created/changed without writing |
--format <format> | dotenv | json | appsettings (default: inferred from filename) |
--from-json | Deprecated, use --format json |
--overwrite | Overwrite existing keys instead of skipping them |
--section <path> | appsettings only: read secrets from under this top-level key |
--delimiter <sep> | appsettings only: section-separator for nested keys (default __) |
The format is inferred from the filename when --format is omitted: files matching
appsettings*.json are treated as nested appsettings, other .json files as flat JSON, and
everything else as dotenv. Nested appsettings keys are flattened back into DELIMITER-joined flat
keys — the inverse of vaultic export --format appsettings — so a round trip through both commands
preserves key names.
Reports created/updated/skipped counts. If run interactively against a non-JSON file, offers to
delete the local file afterward and switch you over to vaultic run.
vaultic status
Compares your local secrets file against the server.
| Flag | Description |
|---|---|
-e, --env <environment> |
Reports added/removed/changed keys, plus lifecycle warnings — [expired], [expiring soon],
[rotation due] — based on each secret's expiry/reminder metadata.
vaultic sync
Pulls from the server, regenerates your local secrets file, then runs the hooks.post_sync
command from .vaultic.yaml if one is set.
| Flag | Description |
|---|---|
-e, --env <environment> |
Equivalent to vaultic export followed by your post_sync hook.