Directory layout
config.json holds the bcrypt hash of each agent’s access key. A hash verifies a
key; it cannot be turned back into one, and the raw key is shown once at creation
and never stored. control-token holds the credential the CLI uses to talk to a
running daemon — stored raw, because the CLI has to present it, and owner-only
like everything else here. The daemon creates it when it first starts, so it is
absent until then. .pre-migration is the state as it was before the last
upgrade changed its format — see
Upgrading.
Set STEERHOLM_CONFIG_DIR to override the config directory (both the CLI and
the daemon read it) — useful for isolated setups or testing:
File permissions
The config directory and files are created owner-only —0700 on
~/.steerholm and its policies/ directory, and 0600 on config.json, each
policy file, and each audit log file — so --env
secrets, agent policies, grants, and recorded activity aren’t readable by
other users on the machine. Steerholm re-applies these permissions on startup, so
an existing install is tightened automatically after an upgrade. On Windows,
per-user AppData already provides this isolation via ACLs.
config.json
Top-level fields
Server fields
Set
env from the CLI: holm add server <name> --command "..." --env KEY=VALUE
(repeatable). It’s stored here in config.json, and holm show server masks the
values so secrets don’t print back.Variable names must be letters, digits, _, -, or ., and can’t start
with a digit — the same rule Kubernetes and Docker use, so a config stays
portable across Linux, macOS, and Windows. Values are unrestricted (they may
contain =, spaces, or anything else); only the name is validated, and repeating
a name is an error.Agent fields
The
id is what distinguishes two agents that have shared a name — the
audit log records it, and holm log --agent <id>
isolates one of them.
Audit fields
Set these with
holm log set --max-files N --max-age-days N; a running daemon
picks them up without a restart. Segment size is fixed at 10 MB.