Interactive use should use npx -y @akshar5/cohall. Unattended services
install the same npm package so the operating system has a stable executable
path.
| Component | Starts again | Offline behavior |
|---|---|---|
| Linux relay | At boot when its systemd socket and service are enabled | Cannot accept new tasks while down; persisted tasks resume after startup |
| Linux device | With the user's systemd manager; at boot without login when lingering is enabled | Accepted tasks wait on the relay and dispatch after reconnect |
| macOS device | At user login through launchd | Accepted tasks wait while the Mac is off, asleep, or logged out |
| Windows device | At user logon through Task Scheduler | Accepted tasks wait while the PC is off or logged out |
The relay's data directory must be persistent. Cohall uses at-least-once delivery: work interrupted during execution can run again after recovery, so consequential tasks should be idempotent.
Device workers retry the connection after two seconds if the relay does not accept it within ten seconds. Once connected, workers reconnect if no relay ping arrives for 45 seconds. The relay sends a ping every 30 seconds. This also recovers connections that go silent without closing the socket. Active work continues during a disconnect, and pending results are sent after reconnecting.
On macOS and Linux, cohall device handles SIGINT and SIGTERM by stopping active
coding providers and waiting for their process cleanup. It starts no queued work
during shutdown. Forced termination, including SIGKILL, cannot run that cleanup;
a custom supervisor must stop the worker's entire process tree. The Linux
systemd service does this through its default control-group termination.
Install and pair as the user that will run the daemon:
npm install --global --prefix "$HOME/.local" @akshar5/cohall
cohall doctorInstall and start the current user's service:
cohall service install
journalctl --user -u cohall-device -fThe user unit is written under $XDG_CONFIG_HOME/systemd/user when that variable
is an absolute path, or $HOME/.config/systemd/user otherwise.
The generated service uses the exact Cohall executable and puts the current
Node.js directory first on PATH. For npm installations, Linux and macOS services
also include the verified global prefix's bin directory so providers installed
alongside Cohall remain available, including with a custom prefix. Linux and macOS
services also include the pnpm home and its bin subdirectory, using PNPM_HOME,
then $XDG_DATA_HOME/pnpm, then the platform default, regardless of how Cohall
was installed. For pnpm installations,
services also save the selected pnpm executable, global package directory, global
bin directory, and store directory.
This preserves custom paths supplied through shell configuration and prevents a
Corepack shim on the service PATH from redirecting upgrades. Global pnpm operations
ignore the current project’s Corepack manager specification.
The service records the resolved configuration file, including COHALL_CONFIG or
XDG_CONFIG_HOME overrides. Reinstall it after moving that file or replacing a
Node.js or pnpm executable at a different path. Reinstalling restarts an existing
worker to apply the changes.
Some Grok Bot cloud computers have no systemd user manager. On those hosts,
follow Grok Bot computer setup for a supported supervisor or
recovery routine; cohall service install cannot register a service there.
Other environment overrides are not copied from your shell. Save device settings
with cohall configure, or set them explicitly in the service environment.
Linger is optional. Without it, the user service starts after login and stops with the user's service manager. With it, the service starts at boot and remains after logout:
loginctl enable-linger "$USER"Verify the configuration with:
systemctl --user is-enabled cohall-device
systemctl --user is-active cohall-device
loginctl show-user "$USER" -p LingerCreate a dedicated cohall user, install the npm package globally so
command -v cohall returns /usr/local/bin/cohall, and place the relay
environment at /etc/cohall/relay.env with mode 0600. Generate the token with
openssl rand -hex 32; do not use the placeholder literally.
COHALL_RELAY_HOST=0.0.0.0
COHALL_RELAY_PORT=8787
COHALL_RELAY_ALLOW_REMOTE=true
COHALL_TOKEN=replace-with-the-output-of-openssl-rand-hex-32
COHALL_DATA_DIR=/var/lib/cohallInstall deploy/systemd/cohall-relay.service and
deploy/systemd/cohall-relay.socket. The packaged socket listens on loopback;
change ListenStream to the relay's private Tailscale address when devices
connect directly over Tailscale. Then:
systemctl daemon-reload
systemctl enable --now cohall-relay.socket
systemctl enable --now cohall-relay
journalctl -u cohall-relay -fVerify both units are enabled and active:
systemctl is-enabled cohall-relay.socket cohall-relay.service
systemctl is-active cohall-relay.socket cohall-relay.serviceExpose the relay only through a private network such as Tailscale or an HTTPS reverse proxy. Device connections are outbound WebSockets. The socket unit keeps the listener available across relay service restarts: new connections wait for the replacement process instead of failing. Existing WebSockets reconnect, and durable tasks resume after the replacement relay starts.
A relay's SQLite database and owner credential are its portable state. Use the
supported command instead of copying a live cohall.db: it uses SQLite's online
backup API so the snapshot is consistent while the old relay is running.
cohall relay backup ./cohall-relay-backupRun that command with the same COHALL_DATA_DIR and operating-system account
as the relay service. The destination must be new and its parent must be
operator-owned or a sticky shared directory. Copy the resulting directory to
the new host over a private channel.
The backup contains exactly three files:
cohall.db: devices, workspaces advertised by those devices, threads, prompts, context, results, trace history, provider-session references, durable upgrades, pairings, and hashed client/device session credentials;owner-token: the plaintext relay owner credential;manifest.json: format/version metadata and SHA-256 checksums.
It does not contain device-local Cohall configuration or bearer tokens, workspace files, provider logins, service definitions, logs, DNS, reverse-proxy configuration, or TLS keys. Back up those host-level pieces separately when they are part of the deployment. Anyone who obtains this directory gets the owner credential and sensitive task history, so encrypt it at rest when the storage or transfer channel is not already protected.
On the new host, install Cohall and restore into the new service's data directory before starting it:
COHALL_DATA_DIR=/var/lib/cohall cohall relay restore ./cohall-relay-backupThe target data directory must not already exist. Restore refuses to overwrite
one, rejects symlinked members, copies into a private staging directory, verifies
the staged file checksums and SQLite integrity, and publishes the restored
directory atomically. Run the command as the service account so the resulting
files have the correct owner. The restored owner-token file supplies the
owner credential when COHALL_TOKEN is unset; if the new service explicitly
sets that variable, it must use the same value.
Configure the private network or HTTPS endpoint, start the relay, and check its health. If its address changed, update every client and device:
cohall relay use https://new-relay.example.com
cohall doctorrelay use first proves that every stored client and device credential works
against the new relay. If configuration changes during verification, it asks you
to retry without overwriting those changes. Only then does it save the address.
It restarts an active managed device service automatically and leaves stopped workers stopped.
Repeat the command to retry a failed restart or apply a previously saved address;
credentials are verified again, and an unchanged address is not rewritten.
Current relays verify device credentials without claiming the running worker's
connection, so changing an address for the same relay works while it is active.
Older relays use a WebSocket check; stop that worker first when changing its
address to the same relay, or upgrade the relay before switching.
Use --no-restart when another supervisor owns the process.
Environment-based configurations must update
COHALL_RELAY_URL in their service environment instead.
HTTPS is required for non-loopback addresses because verification sends the stored credentials to the new endpoint. When a private network such as Tailscale provides the encrypted transport and the relay intentionally uses HTTP, make that assumption explicit:
cohall relay use http://cohall-vps.tailnet-name.ts.net:8787 --allow-httpKeeping the same stable DNS or Tailscale name avoids the final per-device step. Only change where that name resolves after the restored relay is healthy.
Run npm install --global @akshar5/cohall, then install and start the
LaunchAgent:
cohall service installThe generated LaunchAgent uses RunAtLoad and KeepAlive: it starts at login,
restarts after failure, and reconnects when the network returns. It cannot run
before that user logs in. As on Linux, it records the current Node.js directory
and configuration file, so custom Node installations and COHALL_CONFIG work
after login. Reinstall it when either path changes. Check it with:
launchctl print gui/"$(id -u)"/com.cohall.deviceThe relay and device worker may run on the same machine. Configure the worker with the relay's private Tailscale URL and install both services independently.
Run npm install --global @akshar5/cohall, pair and verify the machine from
PowerShell, then run:
cohall service installThe script registers a per-user scheduled task that starts cohall device at
logon and restarts it after failures. The task uses PowerShell to set the selected
configuration file and start the exact Node.js and Cohall executables, without
depending on a cohall.cmd or cohall.ps1 shim. Reinstall the task if these paths
change. It does not run before that user logs on.
Run cohall upgrade from a verified global npm, Bun, or pnpm installation.
Project-local dependencies and package-runner caches cannot upgrade or install a
device service; use the global cohall command. pnpm shared-store entrypoints
must be reached through their stable global package link. It updates
that installation and restarts only active managed Cohall services, with relays
restarted before device workers. Active services restart even when the installed
files already match the requested version. Socket-activated relays keep accepting
new connections while their process is replaced, and delegated upgrades finish
through durable restart recovery.
Bun upgrades verify and retain the selected manager's configured global directory.
If that directory is set only by shell environment variables, set
BUN_INSTALL_GLOBAL_DIR in the service environment too; shell overrides are not
copied when installing a service. A mismatched Bun global directory stops the
upgrade before installation.
If a restart fails, inactive or missing services remain listed in
services_pending_restart and their recovery state is preserved. Repair or start
the affected service, then rerun the same upgrade command. Recovery verifies each
active service's installation before restarting it. Changing the target version
retains unfinished restarts under the new version, including with --no-restart.
Before changing files, Cohall verifies that active systemd jobs, launchd jobs,
and Windows scheduled tasks use the same global installation as the invoked
CLI. If they differ, use the executable named in the error or reinstall the
device service with cohall service install. Windows tasks with unrecognized or
multiple actions must also be reinstalled before upgrading.
pnpm device services use the stable global package link so replacing or removing
an old package directory does not leave the worker on the old version. Services
installed by older Cohall versions may be pinned to a version-specific directory.
After updating the global CLI, run cohall service install through pnpm's
global cohall command once to replace the saved executable. Cohall rejects
pinned active services before changing
packages. This applies to systemd, launchd, and Windows scheduled tasks. For a
manually configured pnpm relay, change its service executable to the stable
package path named in the error.
Direct npm install --global, bun add --global, or pnpm add --global
replaces files on disk but cannot replace code already loaded by a running Node
process. Use cohall upgrade, or restart the service manager job manually, to
move a running relay or device to the new version.
Start with cohall doctor. It reports relay reachability, device connectivity,
provider selection, executable discovery, and version information without
printing credentials.
Inspect a task's lifecycle, including dispatches, reconnect-driven requeues, execution, clarification, cancellation, and completion:
cohall trace <task-id>
cohall trace <task-id> --followTraces omit prompts, final results, credentials, and provider session IDs. They include progress and clarification text; inspect those fields before sharing.
Use journalctl --user -u cohall-device -f for a Linux device and
journalctl -u cohall-relay -f for a system relay. The trace is durable and
portable; service logs remain machine-local.