Thruk, NagVis and Checkmk are part of a whole ecosystem of consoles that speaks MK Livestatus (LQL) to read a monitoring engine's state without caring what that engine actually is. jaque implements that protocol, so those tools point at it without a single config change on their side. What it costs: Livestatus inherits the protocol's own gaps, the wait headers (WaitTrigger, WaitCondition, WaitObject, WaitTimeout) and the statehist table.

1. Turning it on

Two flags, both empty (protocol off) by default:

-livestatus-listen 127.0.0.1:6557   # TCP
-livestatus-socket /tmp/jaque-livestatus.sock  # UNIX socket

Either or both can be set at once.

printf 'GET status\nOutputFormat: json\n\n' | nc -U /tmp/jaque-livestatus.sock

2. What it reads from

Its own projection of the event log, in parallel with the dashboard's: same mechanism, separate consumer, so a Livestatus client never blocks or is blocked by the dashboard.

3. The tables

Eleven tables: hosts, services, hostgroups, servicegroups, contacts, downtimes, comments, status, timeperiods, log, plus the meta-table columns describing all of them. Filtering, Stats: aggregation (sum/min/max/avg), and both output formats (csv, the Nagios default, and json) are supported.

hosts and services carry notifications_enabled; contacts carries host_notifications_enabled and service_notifications_enabled; status.enable_notifications reports the program-wide toggle.

hosts and services also carry active_checks_enabled (0 for a passive object or one with active checks stopped), accept_passive_checks (always 1), flap_detection_enabled (its own check configured with flap detection on, and not stopped) and event_handler_enabled (a handler configured, and not stopped), each folding the object's own switch into its configuration. status reads execute_host_checks, execute_service_checks, enable_flap_detection and enable_event_handlers from the program-wide switches, and check_host_freshness and check_service_freshness from the configuration. accept_passive_host_checks, accept_passive_service_checks, check_external_commands and process_performance_data have no switch, so they always read 1. obsess_over_hosts and obsess_over_services always read 0.

comments carries user comments (entry_type 1) beside the acknowledgement (4) and downtime (2) rows. timeperiods carries one row per configured timeperiod (name, alias, in); hosts and services gain check_period, notification_period, in_check_period and in_notification_period, and contacts gains host_notification_period and service_notification_period, the contact's one notification_period reported under both.

downtimes gains fixed (1 for a fixed downtime, 0 for any other kind), duration (seconds, set only on a flexible downtime), triggered_by (the downtime ID a triggered downtime names, empty otherwise) and type (0 while the downtime is currently in effect, 1 otherwise), on top of the Nagios columns the table already carried. A recurring downtime is not scheduled, so it has no row of its own to read back; instead the table adds one row per object per recurring downtime, for whichever occurrence is currently in effect or the next one. scheduled_downtime_depth on hosts and services counts downtimes actually in effect right now, scheduled and recurring alike, rather than every downtime on file for the object.

GET services
Filter: state = 2
Stats: state = 2
OutputFormat: json

4. The log table

log holds twelve kinds of row, each in Nagios's own message format, so a console that already parses Nagios's log understands jaque's rows unchanged:

Class Type Message
0 HOST EVENT HANDLER / SERVICE EVENT HANDLER host;svc;STATE;trigger;handler;status
1 HOST ALERT / SERVICE ALERT host;svc;STATE;HARD or SOFT;attempt;output
1 HOST FLAPPING ALERT / SERVICE FLAPPING ALERT host;svc;STARTED; or host;svc;STOPPED;
1 HOST ACKNOWLEDGE ALERT / SERVICE ACKNOWLEDGE ALERT host;svc;STARTED;author;comment
1 HOST ACKNOWLEDGE ALERT / SERVICE ACKNOWLEDGE ALERT host;svc;EXPIRED;author;
1 HOST DOWNTIME ALERT / SERVICE DOWNTIME ALERT host;svc;STARTED;
1 HOST DOWNTIME ALERT / SERVICE DOWNTIME ALERT host;svc;STOPPED;
2 CONFIG RELOAD generation;added;removed;changed
2 CONFIG RELOAD REJECTED the rejection reason
3 HOST NOTIFICATION / SERVICE NOTIFICATION contact;host;svc;STATE;;output
4 PASSIVE HOST CHECK / PASSIVE SERVICE CHECK host;svc;code;output
5 EXTERNAL COMMAND or EXTERNAL COMMAND REJECTED the verb, then the command's fields or the rejection reason

A host row's service slot is empty and the separator stays, so a parser built for Nagios's own log still finds the field it expects. STATE is the Nagios word (UP, DOWN, OK, WARNING, CRITICAL, UNKNOWN).

log is a ring of -livestatus-log-cache entries, refilled from the event log every time the process starts and kept current after that. History older than the ring holds is not here: it lives in the events sink, when one is configured. Class 5, the EXTERNAL COMMAND rows, comes from the audit log rather than the ring, so it goes back as far as the audit log itself retains.

5. Commands

A COMMAND line is the same one line the external command FIFO accepts: [<unix_ts>] VERB;field;field, parsed the same way, with the same verbs and the same field validation. A successful command gets an empty answer, as Nagios's own Livestatus does. A line that fails to parse answers 400 with the parse error; a process with no command sink wired (-read-only set) answers 403; an audit log that cannot take the record answers 503, since a command with no audit record does not run.

Every COMMAND, accepted or not, is written to the audit log with the connection's peer address and no principal: the protocol carries no identity. Section 8 covers what accepting commands means for a listener reachable beyond a trusted network.

6. Verified against a real client

The status table implements all 20 columns Thruk's connect probe (get_processinfo) actually requests, taken from Thruk's own traffic rather than inferred from reading the LQL spec. The exact request/response sequence Thruk sends on connect is pinned in a replay test against real Thruk traffic: it is checked against what a production Nagios console does the moment it connects.

7. Who can read it

Any console that already knows how to talk Livestatus, such as Thruk, NagVis, Checkmk or WOCU, can point at a jaque instance and read its state without modifying its own configuration at all. Combined with the exec plugin protocol and the FIFO, this is the third leg that lets an existing Nagios-adjacent toolchain keep functioning unmodified while the engine underneath changes.

8. Security considerations

As in the original Livestatus protocol, the wire format carries no authentication: anything that can reach the socket can read full state. -livestatus-listen should bind a trusted interface rather than 0.0.0.0, and -livestatus-socket should rely on filesystem permissions to keep the socket restricted: the protocol offers no door of its own to lock.

Both listeners accept COMMAND too, so a reachable TCP listener is a command surface. See Security considerations for what that means and how -read-only removes it.