Headless multihost daemon for coding agents

I herd.
They code.

A headless, multihost backbone for coding agents. One small daemon per machine, one durable terminal per agent, one JSON contract.

$ pohunek host list
Engraving of a farmhand boy with a whip steering a plow pulled by three server cabinets labelled codex, claude and hermes.
A pohunek drives the draft animals. He does not plow himself. Plate I
The idea

Your agents need a farmhand, not an IDE

Tenet 1

No agentic IDE

Your agent already has a shell. Give it pohunek and it can start, feed, watch and review other agents on any of your machines.

Tenet 2

Don't watch the field

You are not meant to stare at it. When an agent waits for an approval or is blocked, the notification reaches you from every host at once.

Tenet 3

Every machine, one contract

Laptop, workstation, build box. One daemon each, one versioned JSON contract for everything you build on top.

Agent first

The agent drives. You don't.

Every automation command returns one versioned JSON envelope with typed errors. An agent, or your script, starts work on another machine, feeds it, waits, and reviews the result.

an agent working buildbox --json
  1. $ pohunek session new --host buildbox --project myapp --agent codex --branch feat/parser --yes --json Start Codex on the build box, in its own worktree.
  2. $ printf '%s' 'Run the focused tests.' | pohunek session input buildbox/s-01J… --stdin --json Send a prompt from stdin, framed the way this agent expects.
  3. $ pohunek session wait buildbox/s-01J… --activity idle --timeout-ms 8000 --json Wake up when the agent goes idle, or report a timeout.
  4. $ pohunek session diff buildbox/s-01J… Review what it changed in the remote worktree, untracked files included.
  5. $ pohunek notifications watch --all-hosts Hear about it only when an agent needs you.
The herd

Every agent CLI, one contract

Each agent has its own TUI quirks, prompt framing, hooks, session ids and resume rules. pohunek absorbs them once, through signed runtime packages, so your tooling talks to one contract.

  • Codex Shipped · official
  • Claude Code Shipped · official
  • Hermes Shipped · official
  • Pi Shipped · official
  • shell Shipped · built in
  • OpenCode Planned · 2.x

More agents are on the way. Any agent CLI can join as a runtime package: a runtime manifest plus TOML detection rules, no recompile. How plugins work

Architecture

One small daemon per machine

Every host is authoritative for its own sessions. Clients talk to each daemon directly: an owner-only Unix socket locally, a NetBird/WireGuard overlay remotely. No central server, no SaaS, no state sync.

Each session lives in its own pohunek-sessiond worker (a systemd unit on Linux, a launchd job on macOS), which owns the PTY. Close the terminal, restart or upgrade the daemon: the session keeps the same PTY and child process.

Comparison

Why not a multiplexer and ssh?

A multiplexer keeps a shell alive. It does not know that the process inside is an agent, so every agent-aware need lands on whoever writes the tool. pohunek handles it once.

You need topohunek gives you
Know whether the agent is working, blocked or idle Live detection from OSC titles, screen patterns and PTY activity, driven by TOML manifests.
Submit a multi-line prompt without it being half-swallowed Per-agent framing (bracketed paste, delayed submit); prompts can come from stdin and never touch argv or logs.
Hear about it when something needs you, on any machine Durable, deduplicated notification records fed by agent hooks and daemon detection, fanned out across hosts.
Keep two agents out of one working tree A worktree per session off the base branch, with ownership checked before any reuse or cleanup.
Get a conversation back, or branch it The agent's own session id is captured for an explicit resume; Claude Code conversations can be forked.
Watch without stealing the terminal Screen snapshots, paged output with exact cursors, and bounded waits for change.
Drive it from a script or another agent One versioned --json envelope, typed errors with recovery hints, event streams, Rust and TypeScript SDKs.
Install

Install with your agent

Open Claude Code, Codex or another agent with shell access on the machine that should become a pohunek host, and paste this. It verifies every download and asks before changing anything.

prompt for your agent
Install pohunek (https://github.com/zajca/pohunek) on this machine and set it up
so you can drive it.

Read these first and follow them, they are the source of truth:
- https://raw.githubusercontent.com/zajca/pohunek/main/docs/install.md
- https://raw.githubusercontent.com/zajca/pohunek/main/docs/knowledge/guides/setup.md
- on macOS also https://raw.githubusercontent.com/zajca/pohunek/main/docs/knowledge/runbooks/install-on-macos.md

Rules:
1. Detect the OS and CPU. Linux x86_64 uses the latest release's
   pohunek-daemon-<version>-x86_64-unknown-linux-gnu.tar.gz (or -musl).
   macOS 14+ on Apple Silicon uses `brew install zajca/pohunek/pohunek`;
   tell me that macOS support is not declared final yet. For anything else,
   stop and tell me.
2. Verify every download with its .sha256 file and, when `gh` is available,
   `gh attestation verify <file> --repo zajca/pohunek`. Stop on any mismatch.
3. Before changing anything, run `pohunek service check --json` (from the
   extracted archive on Linux), show me what will be installed where, and wait
   for my approval. Then install the login service (`./packaging/install-daemon.sh`
   on Linux, `pohunek service install` on macOS). Never pass
   --accept-runtime-loss, --stop-sessions, or --purge. When an upgrade refuses
   with `service_upgrade_sessions_at_risk`, show me the listed sessions and
   reason codes instead of overriding it.
4. Verify with `pohunek doctor --json`, `pohunek service status --json`,
   `pohunek health --json`, and `pohunek host inspect local --json`. Report
   every warning; fix only what I approve.
5. Ask me before running `pohunek integration install --agent <runtime>`: it
   has no dry run and installs a SessionStart hook into that runtime's config
   home (for Claude Code `~/.claude`, for Codex `~/.codex`). Claude Code and
   Codex are served only by their official packages, so their hooks install
   only after the package does. Tell me which runtimes and configuration files
   it will touch and wait for my approval.
6. Run `pohunek agent-skill` and save its output as a skill or instruction file
   in your own harness, so later sessions know how to drive pohunek. Tell me
   where you saved it.
7. If this machine is in a NetBird network, run
   `pohunek host discover --refresh --json` and list the hosts that already run
   pohunek.
8. Never put secrets into commands, logs, or your summary. End with the
   installed version, paths, open warnings, and next steps.

Or start the desktop companion: without a daemon it offers to install pohunek and verifies the download first. By hand: Linux x86_64 release archives with checksums and build attestations, or brew install zajca/pohunek/pohunek on Apple Silicon. Manual installation