ctl
Talk to a running agent: pause, silence, reload, trigger, fire.
nanook ctl is a thin client for the admin server of a running agent. Use it to pause a noisy collector, silence a rule during a deploy, or hot-reload the config without restarting.
How it connects
ctl reads the same nanook.toml to find the admin endpoint. Unix socket first (if [admin].socket is set), then HTTP.
Override per-invocation:
Operations
state
Print the current engine state: every collector and its status, every rule and its trigger count, every silence in effect.
reload
Re-read nanook.toml from disk and apply the diff. Collectors, adapters, channels, and rules hot-swap. No process restart. reload refuses a config that fails validation; nanook check surfaces the same diagnostics without touching the running agent.
silence <expr> [duration]
Mute a rule for the given duration (default 1h). Accepts s, m, h, d suffixes and combinations like 1h30m. The expr must match what's in nanook.toml (whitespace is normalized).
unsilence <expr>
Lift a silence early.
pause <name>
Stop a collector from polling. Existing samples stay in the window store; no new ones come in. Rules whose selectors only reference this collector go quiet.
resume <name>
Bring a paused collector back.
trigger <name>
Fire one read manually, regardless of interval. Useful for confirming a config change without waiting.
fire <name>
Force a rule to fire its action right now, regardless of the current metric state. Looks up the rule by its name field, falling back to the raw expression text. Bypasses eval, silences, and cooldown so the action layer runs even when the rule would not match. Use it to smoke-test a notification channel after wiring up a webhook, Discord ID, or exec script.
The fire counter on nanook ctl state ticks up, just as it does for an organic fire.
eval <expr>
Evaluate an expression against the engine's current state and print the typed result. Reuses the same parser, resolver, and window store the rule layer walks, so anything that works in a [[alerts]] expr is fair game — boolean comparisons, arithmetic, aggregates, label filters.
Output groups the expression and the typed value:
eval:
• expr cpu.usage > 90
• bool true
The verb is read-only — no rule state is touched, no silences are evaluated, no triggers fire. Rule-context selectors (with_trigger, with_firing, firing("...")) have no meaning outside a rule pass and return runtime errors.
Parse errors surface miette spans against your expression. Runtime errors (missing metric, ambiguous selector, dimensional mismatch) propagate from the resolver unchanged.
Patterns
Maintenance window
# silence anything that might page during the deploy
# do the work...
# bring them back early if it went well
Hot-edit the config
&&
Drain a collector before removing
# observe, edit config, remove the collector
Authorization
ctl signs every request with an Ed25519 key. Default key path is ~/.nanook/admin/id_ed25519, override with $NANOOK_IDENTITY or --identity (-i). The server gates signed requests against [admin].authorized / authorized_keys.
NANOOK_IDENTITY=/.nanook/ops_key Hand id_ed25519.pub to whoever runs the agent so they can add it to [admin].authorized or append it to the authorized_keys file.
The Unix socket is a fine alternative for loopback: set [admin].socket and lock the parent directory with filesystem perms. See Admin server for the full auth scheme, headers, and error codes.