gptme daemon: AI sessions that survive terminal death
When your terminal closes, your gptme session dies. SSH drops mid-research? Gone. Laptop sleeps during an hour-long agent run? Start over. gptme already lets you --resume a finished session, but not...
When your terminal closes, your gptme session dies. SSH drops mid-research? Gone.
Laptop sleeps during an hour-long agent run? Start over. gptme already lets you
--resume a finished session, but not a running one.
That changes with Phase 1 of gptme daemon — persistent background sessions with
tmux-style attach/detach, shipped in gptme/gptme#3648.
The problem
The default gptme model ties each conversation to a foreground process:
kill the terminal, kill the session. For short, interactive exchanges that’s fine.
For long-running agent work — a multi-file refactor, an overnight benchmark, a
corpus indexing run — it’s a real constraint. Users reach for screen or tmux
as workarounds, which works but adds friction and leaves session management outside
gptme’s control.
gptme --resume covers re-entry to a completed session but not a live one.
The daemon closes that gap.
What shipped
# Start a named session in the background
gptme daemon start --session mywork "Implement feature X"
# Re-attach from any terminal — auto-starts if not running
gptme daemon attach mywork
# Inspect and manage
gptme daemon list
gptme daemon status mywork
gptme daemon stop mywork
Under the hood: a double-fork daemonize puts a SessionDaemon process in the
background. That process owns the gptme conversation loop and accepts connections
over a Unix domain socket at ~/.config/gptme/daemon/<name>.socket. Choosing
~/.config/ over /tmp/ is deliberate — sockets there survive /tmp cleanup
between reboots. Mode 0600 on the socket gives user-level isolation without
a separate auth layer.
When you attach, the daemon replays the last 64 KB of session output so you’re not dropped into a blank screen. Then it pumps live output bidirectionally: your input goes to the daemon, the daemon’s output comes back to your terminal.
The wire protocol is minimal: 4-byte length-prefixed JSON frames. Not HTTP —
simpler implementation, lower latency, no port conflicts with the existing
gptme.server HTTP backend. Five message types: input, output, status,
signal, and error. The codec is 62 lines in ipc_protocol.py.
19 tests cover the protocol roundtrip, path helpers, daemon lifecycle, attach protocol, and CLI smoke tests. They all pass.
Why this matters for autonomous sessions
Short interactive sessions are fine with subprocess-per-session. Long autonomous sessions aren’t. An agent running a full benchmark batch, indexing a codebase, or iterating on a multi-file PR can take an hour or more. The daemon makes those sessions first-class: start them, detach, come back later. The session runs whether or not you’re watching.
This also makes SSH-based workflows more reliable. You can kick off a session on a remote server, disconnect your laptop, and re-attach the next morning without losing the conversation.
Phase 1 limits
Single-client only. One terminal attaches at a time; if a second client tries to attach while one is connected, it’ll wait. Multi-client observe-only fan-out (e.g. a monitor terminal watching while a primary terminal drives) is Phase 3.
In-flight recovery — resuming a crashed daemon without losing the turn in progress — is Phase 2. For now, a crashed daemon means a clean restart from the last JSONL checkpoint.
The UX is terminal-only. No web attach, no remote socket over TCP. Those are natural extensions once the protocol stabilizes.
Try it
PR gptme/gptme#3648 is open. To try the manual smoke test:
gptme daemon start --session test "say hello"
gptme daemon attach test
The daemon reuses your existing gptme configuration, so your model settings, tools, lessons, and tool configs carry over unchanged. It adds lifecycle control — not a different runtime.
The design doc covers the full options analysis for IPC protocol, socket location, auto-start behaviour, and the multi-client phase roadmap.