Skip to content

Latest commit

 

History

History
312 lines (245 loc) · 14.2 KB

services.md

File metadata and controls

312 lines (245 loc) · 14.2 KB

Run Cohall as a service

Interactive use should use npx -y @akshar5/cohall. Unattended services install the same npm package so the operating system has a stable executable path.

Startup behavior

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.

Linux device daemon

Install and pair as the user that will run the daemon:

npm install --global --prefix "$HOME/.local" @akshar5/cohall
cohall doctor

Install and start the current user's service:

cohall service install
journalctl --user -u cohall-device -f

The 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 Linger

Linux relay

Create 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/cohall

Install 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 -f

Verify both units are enabled and active:

systemctl is-enabled cohall-relay.socket cohall-relay.service
systemctl is-active cohall-relay.socket cohall-relay.service

Expose 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.

Move a relay

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-backup

Run 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-backup

The 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 doctor

relay 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-http

Keeping 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.

macOS

Run npm install --global @akshar5/cohall, then install and start the LaunchAgent:

cohall service install

The 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.device

The 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.

Windows

Run npm install --global @akshar5/cohall, pair and verify the machine from PowerShell, then run:

cohall service install

The 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.

Upgrade running services

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.

Troubleshooting

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> --follow

Traces 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.