kogutdocs

Reference

CLI

Commands, flags, and exit codes of the kogut binary.

The same binary runs the server and the agent. Settings come from environment variables and kogut.toml; no flag sets the config path or the port.

kogut <command> [options]
CommandPurpose
serveStart the server.
agentReport this host to a server. Accepts --server and --token.
agent check-file [<file>]Check the agent’s command checks file.
backup <file>Write a consistent SQLite backup.
restore <file> [--force]Restore a backup.
exportPrint what was created in the panel as kogut.toml.
run -- <command>Run a command and send its heartbeat a ping with the exit code.
healthcheckCheck the local server’s health.
check [<url>]Run one check now and print what it found.
statusPrint open incidents and what is not up, from a running server.
incidents [<id>]List incidents, or print one, from a running server.
checksList checks and heartbeats with their status, from a running server.
config check [<file>]Check kogut.toml without starting the server.
version, --version, -VPrint the version as kogut <version>.
completions <shell>Print a completion script for bash, zsh, or fish.
help [<command> | <topic>], --help, -h, no commandPrint help, or a page of these docs.

-h or --help on any command prints its usage, flags, the environment variables they override, exit codes, and examples. kogut help <command> prints the same text.

A flag that takes a value accepts a space or =, as in --token <token> or --token=<token>. -- ends the options, so kogut backup -- -odd.db writes to -odd.db.

The agent-only build

Releases also ship a smaller build for monitored hosts: the kogut-agent-<target>.tar.gz archives and the ghcr.io/piotrkowski/kogut-agent image. Its binary is also named kogut and has the same agent, but only these commands: agent, agent check-file, run, version, completions, and help. Its kogut help has no docs pages. Any other command exits with code 2:

kogut: this build only contains the agent; 'serve' needs the full kogut binary

The full binary can replace it on any host. Install the agent says which one the install script downloads.

Shared flags

These flags can come before or after the command, as in kogut -q backup x.db. Other commands refuse them.

FlagCommandsEffect
--jsonversion, healthcheck, check, status, incidents, checks, config check, help topicsPrint one JSON object on standard output. See Machine-readable output.
-q, --quietagent check-file, backup, restore, config checkPrint no confirmations or warnings. Errors still go to standard error.
--no-colorserve, agent, config checkWrite no colour codes.

--quiet changes neither exit codes nor results. serve and agent take no --quiet; RUST_LOG sets what they log.

kogut writes colour codes only to a terminal, so logs in a file, journald, or docker logs and JSON never have them. NO_COLOR set to a non-empty value, TERM=dumb, or --no-color turns them off. The only colour in command output is the ok of config check and the bold headings of the help.

Usage errors

A mistake on the command line prints the error, the usage line, and where to find help to standard error, and exits with code 2:

kogut: unknown option --verbose for 'agent'
usage: kogut agent [--server <url>] [--token <token>] [--no-color]
run 'kogut agent --help' for more
  see https://docs.kogut.dev/reference/cli/#kogut-agent

An unknown command shows usage: kogut <command> [options], points to kogut --help, and names the closest command when one is near.

Errors in kogut.toml, environment variables, and the command line end with a see <url> line that links to the docs section about them. serve logs the same link in the docs field of its startup error.

Exit codes

The codes are the same for every command and stable across releases. Each command’s --help lists the ones it returns. Once its command has started, kogut run exits with the command’s code.

CodeMeaning
0Success, or the answer is yes.
1The answer is no, or the command failed, such as an unreadable file, a refused restore, or an unhealthy server.
2Usage error.
3kogut’s server cannot be reached or did not answer in time.
4The server refused the token.
5What the command line names, such as an incident id, does not exist on the server.

Machine-readable output

With --json:

  • Standard output carries exactly one JSON object on one line. Logs, warnings, and other messages go to standard error.
  • The exit code is the same as without --json.
  • Every object has a boolean ok. When it is false, error has a code, a message, and a docs_url.
  • A usage error is JSON too, with code usage and exit code 2, including --json on a command that does not take it.
  • Times are UTC epoch milliseconds. Durations are integers in fields ending in _ms, as in the HTTP API.
  • Key order is not significant.
{"ok":false,"error":{"code":"usage","message":"unknown option --json for 'backup'","docs_url":"https://docs.kogut.dev/reference/cli/#kogut-backup"}}
error.codeMeaningCommands
usageThe command line is wrong.All
config_invalidkogut.toml or an environment variable is invalid.config check, healthcheck, check
not_foundA file named on the command line, or an incident or service, does not exist.config check, incidents, checks
ioA file cannot be read.config check
check_failedThe check is down or unknown.check
unhealthyThe server answered but is unhealthy.healthcheck
unreachablekogut’s server cannot be reached or did not answer in time.healthcheck, status, incidents, checks
unauthorizedThe server refused the token.status, incidents, checks

Fields may be added in any release. Within a minor version, no field is renamed or removed. See Versioning.

kogut serve

Runs the panel, API, checks, ingest, and notifications.

KOGUT_DATA=/var/lib/kogut KOGUT_URL=https://kogut.acme.com kogut serve

With no account, it logs a setup token and writes it to $KOGUT_DATA/setup-token; see Passwords. With KOGUT_LOCAL_AGENT=1, it also runs the agent for its own host.

On SIGTERM or SIGINT, the server stops that agent, stops accepting requests, allows 10 seconds for open requests and tasks, flushes queued writes, and exits with code 0.

FlagOverridesMeaning
--no-colorNO_COLORWrite logs without colour codes.
Exit codeMeaning
0Stopped on SIGTERM or SIGINT.
1Cannot start: invalid settings or kogut.toml, or the data directory is in use.
2Usage error.

kogut agent

kogut agent --server https://kogut.acme.com --token <token>
FlagOverridesMeaning
--server <url>KOGUT_SERVERThe server’s URL, or comma-separated URLs tried in order.
--token <token>KOGUT_TOKEN, KOGUT_TOKEN_FILEThe host token from the panel.
--no-colorNO_COLORWrite logs without colour codes.

Other settings are environment variables. The agent needs no inbound port. See Installing the agent.

Exit codeMeaning
0Stopped on SIGTERM or SIGINT.
1Invalid settings, or the agent stopped on an error.
2Usage error.

kogut agent check-file

kogut agent check-file /etc/kogut-agent/checks.toml

Checks a command checks file as the agent does at start, without starting it. Without a path, it checks the file in KOGUT_CHECKS, or /etc/kogut-agent/checks.toml. It prints each check’s name, service, interval, and timeout. A mistake prints the line and key. A file its group or others can write is refused too. The owner is not checked, since this command may run as another user than the agent. A missing default file means no command checks.

FlagMeaning
-q, --quietPrint only errors.
Exit codeMeaning
0The agent can use the file, or there is no default file.
1The file is invalid, cannot be read, or others can change it.
2Usage error.

kogut backup

kogut backup /var/backups/kogut.db

Writes a complete, consistent copy of the SQLite database in KOGUT_DATA while the server runs, and prints kogut: wrote <file>. See Backups and restore.

FlagMeaning
-q, --quietPrint no confirmation.
Exit codeMeaning
0The copy is written.
1The database cannot be read or the file cannot be written.
2Usage error.

kogut export

kogut export >> /var/lib/kogut/kogut.toml
kogut export --checks --heartbeats

Prints what was created in the panel as kogut.toml: [[service]], [[check]], and [[heartbeat]] blocks, named [[alert]] blocks for channels, and [edge] and [server] heartbeat_url when the panel set them. After the text is added to the file, the next reload takes each object over with its history.

It opens the database in KOGUT_DATA read-only, so it can run beside a live server, and reads the file serve reads to leave out what that file already defines. A second export after the move prints none of the moved objects. Only the TOML goes to standard output.

FlagPrints only
--checksChecks, and the services they need.
--heartbeatsHeartbeats, and the services they need.
--channelsNotification channels.
--edge[edge] and [server] heartbeat_url.

Flags can be combined. Without any, everything is printed, and what has no form in kogut.toml is listed as comments at the end: silences, maintenance windows, sites, people, API tokens, and the ping URLs, which keep working after the move.

No secret is printed. Channel URLs, tokens, and passwords, request header values, the kogut edge token, and the heartbeat URL become ${NAME} placeholders, such as ${OPS_PHONE_TOKEN} for the token of the channel ops-phone, each listed at the top as # NAME: what it is. Set those variables for kogut before the reload.

The output is checked with kogut’s config parser before it is printed. A check whose json assertion compares with null, which TOML cannot write, is left out with a note.

Exit codeMeaning
0The TOML is printed.
1There is no database, it cannot be read, or another kogut version wrote it.
2Usage error.

kogut restore

kogut restore /var/backups/kogut.db --force

Refuses to run while a server uses the same data directory. The source must be a kogut database no newer than the binary. Prints kogut: restored <file> into <data directory>.

FlagMeaning
--forceReplace an existing database. It can come before or after the path.
-q, --quietPrint no confirmation.
Exit codeMeaning
0The database is restored.
1A server uses the data directory, a database exists without --force, or the file is not a kogut backup.
2Usage error.

kogut run

KOGUT_PING_URL=https://kogut.acme.com/ping/btp_... kogut run -- /usr/local/bin/backup.sh
kogut run --timeout 30s -- pg_dump -Fc -f /var/backups/acme.dump acme

Runs a command for a heartbeat: GET <url>/start, then the command with this process’s standard input, output, error, and environment, then GET <url>/<exit code>. Everything after -- is the command and its arguments.

FlagOverridesMeaning
--ping <url>KOGUT_PING_URLThe heartbeat’s ping URL, https://<kogut>/ping/<token>, from Ping URL in the panel.
--timeout <duration>How long each ping may take, retries included, such as 10s or 500ms. 10s by default.

Prefer KOGUT_PING_URL: other users on the host can see a --ping URL in ps.

A ping is tried up to 5 times within its timeout when the server cannot be reached, times out, or answers 429 or 5xx. A 404 means no heartbeat has the URL and is not retried. A failed ping prints kogut: ping <signal> failed: <reason> to standard error, without the token. The command still runs, and its exit code stays the result.

Result of the commandPingExit code of kogut run
Exits with a code/<code>The command’s code.
Cannot be found/fail127
Found but cannot be run/fail126
Ended by a signal/fail128 plus the signal number

These cases print kogut: cannot run <command>: <reason> or kogut: <command> was stopped by signal <n>. SIGINT and SIGTERM sent to kogut run are passed on to the command, and kogut run waits for it so the last ping is sent.

Only the command writes to standard output. kogut’s own messages go to standard error and start with kogut:. There is no --json, no log capture, and no request body.

Exit codeMeaning
0The command exited with 0.
2Usage error, such as a missing --, command, or ping URL. Nothing ran and no /start was sent.
Any otherThe command’s own code, or 126, 127, or 128 plus a signal as above.

kogut healthcheck

Sends GET /healthz to the local server, at the address from KOGUT_LISTEN or PORT, then [server] listen, then the default. 0.0.0.0 and :: mean the local machine.

FlagMeaning
--jsonPrint the result as one JSON object.
Exit codeMeaning
0/healthz returned 200.
1The server answered but is unhealthy, or a setting such as KOGUT_LISTEN is invalid. The message says which; with --json, error.code is unhealthy or config_invalid.
2Usage error.
3The request failed or timed out after 5 seconds.

Docker reserves exit code 2 for HEALTHCHECK commands, so healthcheck returns 3 when nothing answers.

--json prints what it found, with the same exit codes:

{"ok":false,"state":"unhealthy","address":"127.0.0.1:8484","reason":"the database writer is not keeping up","error":{"code":"unhealthy","message":"the server at 127.0.0.1:8484 answered but is unhealthy","docs_url":"https://docs.kogut.dev/reference/cli/#kogut-healthcheck"}}

state is healthy, unhealthy, or unreachable. address is the address asked. reason is what an unhealthy server said in its /healthz reply, or null.

The distroless image has no curl and no built-in HEALTHCHECK. The Compose templates use this command:

compose.yml
healthcheck:
  test: ["CMD", "/usr/local/bin/kogut", "healthcheck"]

kogut check

kogut check https://acme.com
kogut check https://acme.com/health --expect 'status = "2xx"' --expect 'json = "$.db", equals = "ok"'
kogut check --tcp db.internal:5432 --timeout 2s
kogut check --name "API health" --json

Runs one check now from this machine and prints what it found, judged by the same rules as scheduled checks. It needs no server and changes nothing.

FlagMeaning
<url>An HTTP check of this URL.
--tcp <host:port>A TCP check.
--dns <name>A DNS check.
--ping <host>A ping check.
--domain <name>A domain registration check.
--name <check>The [[check]] with this name in kogut.toml, exactly as defined, request headers and ${NAME} secrets included.
--method <method>The HTTP method. GET by default.
--timeout <duration>As in kogut.toml, such as 5s or 800ms, between 100ms and 1m. 10s by default.
--expect <assertion>One assertion, written as the inside of an expect inline table, so it can be copied into the file. Repeat it for more.
--jsonPrint the result as one JSON object.

Give exactly one target: a URL, --tcp, --dns, --ping, --domain, or --name. Only HTTP checks take --method, and only HTTP and ping checks take --expect. A mistake, such as a bad URL or a timeout out of range, is a usage error with the message the panel shows.

--name reads the file serve reads, KOGUT_CONFIG or $KOGUT_DATA/kogut.toml, with ${NAME} values from the environment or $CREDENTIALS_DIRECTORY. Checks created in the panel cannot be run by name. A check with from runs here anyway, with a note; to see what the agent sees, run kogut check --name <check> on that agent host. --name takes no other options.

The result is one line, then one indented line for each failed assertion or the probe’s error:

down  https://acme.com/health  200 in 142 ms, certificate expires in 61 days
  $.db is "degraded", expected "ok"

A certificate within 14 days of expiry gets its own line. It changes the certificate’s state, not the check’s, as on the server. A domain check is degraded 30 days before the registration expires, down once it has, and unknown when the registry gives no date.

Exit codeMeaning
0The check is up or degraded.
1The check is down or unknown, or kogut.toml cannot be read for --name.
2Usage error, including a --name that kogut.toml does not define.

--json prints one object:

{"ok":false,"state":"down","type":"http","target":"https://acme.com/health","status":200,"duration_ms":142,"failures":["$.db is \"degraded\", expected \"ok\""],"assertions":[{"expect":"status = \"2xx\"","ok":true,"message":null},{"expect":"json = \"$.db\", equals = \"ok\"","ok":false,"message":"$.db is \"degraded\", expected \"ok\""}],"certificate_expires_at":1767225600000,"certificate_state":"up","registration_expires_at":null,"error":{"code":"check_failed","message":"$.db is \"degraded\", expected \"ok\"","docs_url":"https://docs.kogut.dev/monitoring/checks/"}}
FieldMeaning
stateup, degraded, down, or unknown.
typehttp, tcp, dns, ping, or domain.
statusThe HTTP status, or null.
duration_msHow long the probe took.
failuresThe failed assertions and the probe’s error, as the panel shows them.
assertionsEach assertion in order, with ok and the failure message. ok is null when it was not judged: the probe failed, or a 429 or 503 skipped the body assertions.
certificate_expires_at, certificate_stateFor HTTPS: when the certificate expires, and its state by the 14-day and 7-day rule.
registration_expires_atFor domain checks: when the registration expires.

kogut status

KOGUT_API_TOKEN_FILE=/run/secrets/kogut-read kogut status
kogut status --url https://kogut.acme.com --token "$TOKEN" --json

Reads a running server over its HTTP API and prints the open incidents, then the services and hosts that are not up. It sends only GET requests. The text matches the MCP status tool:

1 open incident(s)
  #12 API is down (id 0123456789abcdef), since 2026-10-17 14:07 UTC, open for 5 min; likely cause: the deploy of api v42

Not up:
  service api: down (status 503, expected 2xx)

status, incidents, and checks take the same two flags:

FlagOverridesMeaning
--url <url>KOGUT_URLThe server’s address, with http:// or https://.
--token <token>KOGUT_API_TOKEN, KOGUT_API_TOKEN_FILEA read or write token from Settings → Tokens.

The address comes from --url, then KOGUT_URL, then the address of a server on the same machine, found as healthcheck finds it. The token comes from --token, then KOGUT_API_TOKEN, then the file in KOGUT_API_TOKEN_FILE; the agent’s KOGUT_TOKEN is never read. The token is sent only in the Authorization header and never printed. Prefer the variables: other users see a token on the command line in ps.

Requests time out after 10 seconds and follow no redirects. A proxy with forward auth in front of kogut must let requests with an Authorization: Bearer header through.

Exit codeMeaning
0Nothing is open or down. Degraded, unknown, and maintenance are listed but count as fine.
1An incident is open, or a service or host is down.
2Usage error.
3The server cannot be reached, timed out, answered with an error, or is not kogut.
4The server refused the token: none was given, or its scope is wrong.

--json prints {"ok":true,"response":...}, where response is the body of GET /api/v1/overview as the server sent it; its fields may change between minor versions, as in the API. A failure prints {"ok":false,"error":{...}} with the code unreachable, unauthorized, or not_found.

kogut incidents

kogut incidents
kogut incidents --range 7d --json
kogut incidents 0123456789abcdef

Lists open incidents and those resolved in the range, open first, one per line. With an incident’s id, 16 hex characters, it prints that incident with its likely causes and its timeline, newest first, as the MCP incident tool does. --json prints the body of GET /api/v1/incidents or GET /api/v1/incidents/{id} as response.

It takes --url, --token, and --json as status does, and:

FlagMeaning
--range <range>Resolved incidents of the last 1h, 24h, 7d, 30d, or 1y. 30d by default. Only for the list.
Exit codeMeaning
0No incident shown is open.
1An incident shown is open.
2Usage error.
3The server cannot be reached or gave no usable answer.
4The server refused the token.
5No incident has the id.

kogut checks

kogut checks
kogut checks --service api --json

Lists every check and heartbeat with its status, service, type, target, last run, and where it runs, from GET /api/v1/services and GET /api/v1/services/{name}. --json prints the checks as an array under response, each object as in the service’s checks with its service added. It takes --url, --token, and --json as status does, and:

FlagMeaning
--service <name>Only the checks of this service.
Exit codeMeaning
0No check is down.
1A check is down.
2Usage error.
3The server cannot be reached or gave no usable answer.
4The server refused the token.
5No service has the name.

kogut config check

kogut config check
kogut config check --allow-unset ./kogut.toml

Checks kogut.toml as serve does at startup and on reload, without starting anything. It takes no lock, runs no migrations, and writes nothing, so it can run beside a live server. With no file, it checks the file serve reads: KOGUT_CONFIG, or $KOGUT_DATA/kogut.toml. - reads standard input. ${NAME} values come from the environment, then from $CREDENTIALS_DIRECTORY, as at startup; see Secrets.

FlagOverridesMeaning
<file>KOGUT_CONFIGThe file to check, or - for standard input.
--allow-unsetUse placeholders for unset ${NAME} variables.
--jsonPrint the result as one JSON object.
-q, --quietPrint errors only.
--no-colorNO_COLORWrite the ok without colour.

A valid file prints one line to standard output:

ok: /etc/kogut/kogut.toml (3 services, 5 checks, 2 heartbeats, 2 channels)

Services include those that only checks or heartbeats name. Errors go to standard error as <file>:<line>:<column>: <key>: <message>, as at startup. Warnings start with warning: .

Exit codeMeaning
0The file is valid. Warnings may be printed.
1The file is invalid or cannot be read, or an environment variable is invalid.
2Usage error.

A missing default file is valid, with a warning, because serve starts with the defaults. A missing file named on the command line is an error.

When $KOGUT_DATA/kogut.db exists, it is opened read-only to report checks, heartbeats, and channels whose names the panel uses with another definition, as at startup. With the same definition there is no error: the reload takes the object over. A database from another kogut version skips this with a warning.

--allow-unset replaces each unset ${NAME} with a placeholder and reports it as a warning, so CI can check kogut.toml without the secrets:

kogut config check --allow-unset kogut.toml

The placeholder is https://placeholder.invalid/ for names that contain URL or WEBHOOK, and placeholder otherwise. A key that expects another form, such as a duration, can still fail; set such variables to sample values in CI.

--json prints one object, valid or not:

{
  "ok": false,
  "file": "/etc/kogut/kogut.toml",
  "errors": [
    {
      "line": 14,
      "column": 3,
      "key": "check[2].every",
      "message": "5s is too often; checks run at most every 10s",
      "docs_url": "https://docs.kogut.dev/reference/configuration/#check"
    }
  ],
  "warnings": [],
  "error": {
    "code": "config_invalid",
    "message": "/etc/kogut/kogut.toml:14:3: check[2].every: 5s is too often; checks run at most every 10s",
    "docs_url": "https://docs.kogut.dev/reference/configuration/#check"
  }
}

file is null for standard input. Warnings have the same shape. line and column are null for a problem with the file itself, such as a missing file. errors holds the first problem in the file, then any names used in the panel.

kogut version

kogut version
kogut version --json

Prints kogut <version>. With --json:

{"ok":true,"version":"0.1.0","commit":"9c0e7f2b4d1a3e5f6a7b8c9d0e1f2a3b4c5d6e7f","agent_protocol":{"min":1,"max":1},"os":"linux","arch":"x86_64"}

commit is the Git commit a release was built from, or null in a local build. agent_protocol is the range of agent protocol versions the binary speaks. os and arch are the platform it was built for.

Exit codeMeaning
0The version is printed.
2Usage error.

kogut help

kogut help config check
kogut help heartbeats
kogut help installation/docker
kogut help topics --json

kogut help, kogut --help, and kogut alone print the same overview: the version, the docs at https://docs.kogut.dev and https://docs.kogut.dev/llms.txt for AI assistants, the commands grouped by purpose, the shared options, and the docs topics under the sections of the docs sidebar. Lines fit 80 columns. On a terminal, the headings are bold. kogut help <command> prints the same text as kogut <command> --help.

kogut help <topic> prints one page of these docs as Markdown to standard output, without a pager. The pages are built into the binary, so they match the installed version and need no network. The text is the page’s .md version on docs.kogut.dev, with links to other pages as full URLs, and a last line with the page’s URL.

A topic is the page’s path, such as monitoring/heartbeats, or its last part when no other page has it, as in kogut help heartbeats. The two docker pages need their full paths: installation/docker and agent/docker. env stands for reference/environment-variables and api for reference/http-api. Command names come first: kogut help config explains the config commands and kogut help checks the checks command; their pages are kogut help configuration and kogut help monitoring/checks.

FormPrints
kogut help topicsEvery topic and its title, under the sections of the docs sidebar. Each topic is named by the shortest word that prints it.
kogut help topics --json{"ok":true,"topics":[...]}, each topic with topic, title, description, url, and section, the sidebar section.
kogut help --allEvery page in sidebar order, each headed by its URL, as in llms-full.txt, and then the pages the sidebar leaves out.
FlagMeaning
--allPrint every page.
--jsonWith topics, print the list as one JSON object.

An unknown or ambiguous topic, or a word after the topic, is a usage error that lists the matching or closest topics:

kogut: 'docker' names more than one topic: installation/docker, agent/docker
Exit codeMeaning
0The help is printed.
2Usage error, including an unknown or ambiguous topic.

kogut completions

kogut completions bash > ~/.local/share/bash-completion/completions/kogut

Prints a completion script for bash, zsh, or fish. It completes commands, flags, file arguments, and the commands kogut help explains. Shell completion says where each shell looks for it.

Exit codeMeaning
0The script is printed.
2Usage error, such as a shell other than bash, zsh, or fish.