HAPCTL(8) System Manager's Manual HAPCTL(8)

hapctlcontrol utility for openhapd

hapctl [-c file] [-s socket] command

hapctl is the control utility of the openhapd(8) daemon. It checks the configuration file, it reports what the running daemon is doing, and it lists the devices.

status and devices ask the daemon over its control socket. The daemon answers from what it holds in memory. A file on disk holds what the daemon wrote at some earlier time, and the two disagree whenever the answer matters.

With no control socket, hapctl falls back to the PID file and to the configuration file, and it says which of the two answered. An operator thus always knows whether the report is live.

The options are:

file
Read the configuration from file. The default is /etc/openhapd.conf.
socket
Reach the daemon at socket. The default is /var/run/openhapd/control.sock. Use this when the control directive of openhapd.conf(5) names another path.

These commands are available:

Parse openhapd.conf(5) and report what it holds. The command needs no daemon. It reports the line of the first error, and it exits 3 when the file does not parse.

An absent configuration file is not an error. A fresh install has none, and the daemon then runs on its defaults.

Report on the daemon: its name, its HAP port, its uptime, its pairing state and controller count, its configuration number, the number of loaded devices, the number of open connections, and the state of mDNS and MQTT.

With no control socket, the command reports only whether a process is alive, from /var/run/openhapd.pid, and it names that file in its output.

List the devices. With a control socket, the command lists the accessories that the daemon really loaded, with the HomeKit accessory ID of each. Without one, it lists the device blocks of the configuration file, which is what the daemon would load at its next start.
Show the usage message. Each command also takes -h.

/etc/openhapd.conf
The default configuration file.
/var/run/openhapd/control.sock
The control socket of the running daemon, mode 0600 in a directory of mode 0700.
/var/run/openhapd.pid
The process ID of the daemon, read only when the control socket is not there.

hapctl opens no other file. It does not read /var/db/openhapd, and it creates nothing.

The hapctl utility exits 0 on success, and >0 if an error occurs. The commands exit 0 on success.

check and devices exit 3 when the configuration file does not parse. Both read the same file through the same grammar.

An unknown command and a bad option exit 2.

status always exits 0. A stopped daemon is an answer, not a failure of the tool.

Check the configuration file:

$ hapctl check
Configuration file /etc/openhapd.conf is valid
  Configured devices: 3

Ask the running daemon what it is doing:

$ hapctl status
openhapd is running (Home Bridge)
  HAP port:          51827
  Uptime:            3d 4h 12m
  Pairing status:    paired (2 controllers)
  Configuration num: 7
  Devices:           3
  Connections:       1
  mDNS:              published
  MQTT:              connected

The same command with the daemon stopped:

$ hapctl status
openhapd is not running
  (read from /var/run/openhapd.pid: no control socket)

List the devices:

$ hapctl devices
Loaded devices: 2

  Bedroom Thermostat
    AID:   2
    Class: App::OpenHAP::Tasmota::Thermostat
    Topic: tasmota_AABBCC
    ID:    bedroom

Use a different configuration file:

$ hapctl -c /etc/openhapd.test.conf check

hapctl writes configuration errors to . A line that the grammar does not accept names the file, the line number, and the reason:

Configuration error: /etc/openhapd.conf:14: cannot parse: hap_prt 51827

status names the reason it could not reach the daemon. An absent socket and a refused connection are different problems:

  (read from /var/run/openhapd.pid: no control socket)
  (read from /var/run/openhapd.pid: Cannot reach /var/run/openhapd/control.sock: Permission denied)

The first is a stopped daemon, or one with control off in its configuration. The second is a running daemon that the caller may not reach. A caller who is neither root nor “_openhap” cannot search the directory of the socket, and thus cannot even see that the socket is there.

openhapd.conf(5), openhapd(8), rc(8)

The hapctl utility was first available with openhapd(8) in 2025. The control socket was added in 2026. Before that, status guessed the pairing state from the files under /var/db/openhapd.

Dick Olsson <hi@senzilla.io>

The control socket is mode 0600 in a directory of mode 0700, both owned by the “_openhap” user. A user who is neither root nor “_openhap” cannot reach it, and status then reports from the PID file only. That is the intended boundary: the reply names the devices and the controller count of the home.

August 2, 2026 OpenBSD