ronner.dev

Running goose serve where my laptop can't kill it

Every time I put my laptop to sleep I had to stop what I was doing, tell Goose to finish its turn, and hope I remembered the thread when I opened the lid. Not because the session would die — it wouldn't — but because I couldn't leave the agent running while the laptop was closed. The agent runtime was tied to my shell.

Goose has a serve subcommand that decouples the two. It starts an ACP server over HTTP and WebSocket; the CLI connects remotely, sends prompts, and gets responses back. The agent loop — LLM calls, tool execution, session state — runs on the server. The CLI is just a remote control.

I have two of these ACP servers running on my k3s cluster. One is a general-purpose agent I connect to from my laptop. Another is scoped specifically to my Forgejo repos — it packages git, an SSH deploy key, and the internal CA certificate, and nothing else. I pick the one I need and connect.

Each server is a single-replica StatefulSet:

args:
  - serve
  - --host
  - 0.0.0.0
  - --port
  - "3284"

The CLI connects over WebSocket with the server's secret key:

wss://goose.home.arpa/acp?token=<server-secret-key>

Two PersistentVolumeClaims keep state and workspaces separate. State holds the session SQLite database (backed up). Workspaces hold files the agent creates (cleaned up). Two claims because they have different lifetimes.

That's it. Eighty lines of manifests in my infra repo under k8s/service-island/goose/. The agent runtime is no longer a process on my laptop — it's just infrastructure.