Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cryochamber

Cryochamber is a hibernation chamber for AI agents (Claude, OpenCode, Codex). It hibernates an AI agent between sessions and wakes it at the right time — not on a fixed schedule. The agent checks the plan and log, completes a task, and decides when to wake next. Cryochamber empowers AI agents to run tasks that span days, weeks, or even years, like interstellar travelers in stasis.

Our goal is to automate long-running activities that are too irregular for cron. A conference deadline slips because submissions are low. A space probe’s next burn window depends on orbital mechanics. A code review depends on when the author pushes fixes. Cryochamber lets an AI agent reason about when to wake and what to do next, with a persistent daemon that manages the lifecycle.

How It Works

cryo start → spawn daemon → run agent → agent calls cryo-agent hibernate → sleep
                                                                                    ↓
                  inbox message → (immediate wake) ← ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
                                                                                    ↓
                                  (wake time reached) ← ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
                                       ↓
                                  run agent → agent calls cryo-agent hibernate → ...

The daemon (cryochamber) handles lifecycle: sleeping until wake time, watching the inbox for reactive wake, enforcing session timeout, retrying on failure, and executing fallback alerts if something goes wrong.

The agent (any AI coding agent — opencode, Claude Code, etc.) handles reasoning: reading the plan, doing the work, and deciding when to wake up next. It communicates with the daemon via cryo-agent CLI commands over a Unix domain socket.

Sessions are the unit of work. Each session gets the plan, any new inbox messages, and the previous session’s event log as context. The agent uses cryo-agent note to leave memory for future sessions.

Getting Started

Prerequisites

Install

cargo install cryochamber

This installs cryo, cryo-agent, cryo-gh, and cryo-zulip binaries.

Initialize a Project

mkdir my-project && cd my-project
cryo init                      # for opencode (writes AGENTS.md + cryo.toml + README.md)
cryo init --agent claude       # for Claude Code (writes CLAUDE.md + cryo.toml + README.md)

Write Your Plan

Edit plan.md — describe the goal, step-by-step tasks, and notes about persistent state. See the Mr. Lazy and Chess by Mail examples for reference.

Review cryo.toml and adjust the agent command, retry policy, and inbox settings as needed.

Recommended: Tell your AI coding agent to install the skill instead of editing files manually:

Add the make-plan skill from https://github.com/GiggleLiu/cryochamber

Then run /make-plan to create a new project interactively via guided Q&A.

Start the Daemon

cryo start                                                    # start the daemon
cryo-zulip init --config ./zuliprc --stream "my-stream"       # if using Zulip
cryo-zulip sync
cryo-gh init --repo owner/repo                                # if using GitHub Discussions
cryo-gh sync
cryo web                                                      # if using the web UI
cryo watch                                                    # follow the live log

What Happens

  1. Cryochamber installs an OS service (launchd/systemd) that survives reboots
  2. The daemon runs your agent with the plan and a task prompt
  3. The agent does its work and calls cryo-agent hibernate to schedule the next wake
  4. The daemon sleeps until the next wake time and repeats
  5. New messages in messages/inbox/ wake the daemon immediately

Session events are logged to cryo.log. Monitor progress with cryo watch. Check state with cryo status.

Verify It’s Working

After starting, confirm the first session completes:

cryo status    # should show "Daemon: running" with session number and PID
cryo watch     # follow the live log — look for "agent hibernated" to confirm success

Here’s what a successful session looks like in cryo.log:

--- CRYO SESSION 1 | 2026-02-25T01:13:12Z ---
task: Continue the plan
agent: opencode
inbox: 0 messages
[01:13:12] agent started (pid 75159)
[01:13:50] hibernate: wake=2026-02-25T01:16, exit=0,
           summary="Completed first task, scheduling next check"
[01:14:00] agent exited (code 0)
[01:14:00] session complete
--- CRYO END ---

Day-to-Day Usage

cryo status          # quick health check
cryo log             # read full session history
cryo web             # visual overview in the browser
cryo send "message"  # send a message to the agent's inbox
cryo receive         # read messages the agent sent you
cryo wake            # force an immediate wake
cryo restart         # restart the daemon
cryo cancel          # stop the daemon and clean up
cryo ps              # list all running daemons

Example Run

The examples/mr-lazy/ example demonstrates the full daemon lifecycle. The agent has a 25% chance of waking up each session — otherwise it complains and goes back to sleep.

cd examples/mr-lazy && cryo init && cryo start && cryo watch

Configuration

cryo init creates a cryo.toml file with project settings:

# cryo.toml — Cryochamber project configuration
agent = "opencode"        # Agent command (opencode, claude, codex, etc.)
max_retries = 1           # Max retry attempts on agent failure (1 = no retry)
max_session_duration = 0  # Session timeout in seconds (0 = no timeout)
watch_inbox = true        # Watch inbox for reactive wake

# Web UI host and port (for `cryo web`)
# web_host = "127.0.0.1"
# web_port = 3945

Fields

FieldDefaultDescription
agent"opencode"Agent command to run. Use "claude" for Claude Code, "codex" for Codex.
max_retries1Max retry attempts on agent failure. 1 means no retry.
max_session_duration0Session timeout in seconds. 0 disables timeout.
watch_inboxtrueWatch messages/inbox/ for new files and wake immediately.
web_host"127.0.0.1"Host for cryo web to listen on. Use "0.0.0.0" for remote access only behind an authenticated, TLS-terminating proxy.
web_port3945Port for cryo web to listen on.

CLI Overrides

CLI flags to cryo start override config values for that session:

cryo start --agent claude             # override agent
cryo start --max-retries 3            # override retries
cryo start --max-session-duration 3600  # override timeout

These overrides are stored in timer.json (runtime state) and do not modify cryo.toml.

Config vs State

FilePurposePersists
cryo.tomlProject configuration (checked into git)Yes
timer.jsonRuntime state (session number, PID lock, CLI overrides)No (ephemeral)

Commands

Operator (cryo)

cryo init [--agent <cmd>]           # Initialize working directory (writes cryo.toml)
cryo start [--agent <cmd>]          # Start the daemon (reads cryo.toml for config)
cryo start --max-retries 3          # Override max retries from cryo.toml
cryo start --max-session-duration 3600  # Override session timeout from cryo.toml
cryo status                         # Show current state
cryo ps [--kill-all]                # List (or kill) all running daemons
cryo restart                        # Kill running daemon and restart
cryo cancel                         # Stop the daemon and remove state
cryo watch [--all]                  # Watch session log in real-time
cryo log                            # Print session log
cryo send "<message>"               # Send a message to the agent's inbox
cryo receive                        # Read messages from the agent's outbox
cryo wake ["message"]               # Send a wake message to the daemon's inbox
cryo web [--host <ip>] [--port <n>] # Open browser chat UI
cryo clean [--force]                # Remove runtime files (logs, state, messages)

Agent IPC (cryo-agent)

These commands are used by the AI agent to communicate with the daemon. They send JSON messages over a Unix domain socket.

cryo-agent hibernate --summary "..."   # End session (more work to do)
cryo-agent hibernate --complete        # End session (plan done)
cryo-agent todo add "text" --at <TIME> # Schedule next wake via TODO
cryo-agent note "text"                 # Leave a note for next session
cryo-agent send "message"             # Send message to human (writes to outbox)
cryo-agent receive                     # Read inbox messages from human
cryo-agent time "+30 minutes"          # Compute a future timestamp
cryo-agent alert <action> <target> "msg"  # Set dead-man switch

GitHub Sync (cryo-gh)

Sync messages with a GitHub Discussion board for remote monitoring and two-way messaging. See the GitHub Sync page for commands, setup, and workflow.

Web UI

cryo web starts a local web server with a chat interface for sending messages to your agent and monitoring its activity.

Usage

cryo web                         # default: http://127.0.0.1:3945
cryo web --port 8080             # custom port
cryo web --host 0.0.0.0          # listen on all interfaces (see warning below)

Warning: The web UI has no authentication. Binding to 0.0.0.0 exposes all endpoints (status, messages, wake) to the network. Only do this behind an authenticated, TLS-terminating reverse proxy.

Or configure in cryo.toml:

web_host = "127.0.0.1"
web_port = 3945

Features

  • Chat interface — Send messages to the agent’s inbox and see outbox replies
  • Status bar — Shows daemon status (running/stopped), session number, and agent name
  • Wake button — Force the daemon to wake immediately (sends SIGUSR1)
  • Live log — Toggle the log panel to see cryo.log events in real-time
  • Real-time updates — Server-Sent Events (SSE) stream new messages, status changes, and log lines as they happen
  • Polling fallback — Periodic polling ensures messages from the daemon are never missed

API Endpoints

The web server exposes a JSON API:

EndpointMethodDescription
/GETChat UI (HTML)
/api/statusGETDaemon status (running, session, agent, log tail)
/api/messagesGETAll messages (inbox + archived inbox + outbox), sorted by time
/api/sendPOSTSend a message to inbox ({ "body": "...", "from": "...", "subject": "..." })
/api/wakePOSTWake the daemon ({ "message": "..." })
/api/eventsGETSSE stream (events: message, status, log)

GitHub Discussion Sync

cryo-gh bridges a cryochamber project with a GitHub Discussion, enabling remote monitoring and two-way messaging. Discussion comments become inbox messages for the agent; outbox messages from the agent become Discussion comments.

Prerequisites

  • GitHub CLI (gh) installed and authenticated (gh auth login)
  • A GitHub repository where you have write access
  • An initialized cryochamber project (cryo init)

Commands

cryo-gh init --repo owner/repo   # Create a Discussion and write gh-sync.json
cryo-gh sync [--interval N]      # Start background sync daemon (default from cryo.toml or 5s)
cryo-gh unsync                   # Stop the sync daemon
cryo-gh pull                     # One-shot: pull new comments → inbox
cryo-gh push                     # One-shot: push latest session log → Discussion
cryo-gh status                   # Show sync configuration

How Sync Works

cryo-gh sync spawns a background daemon (just like cryo start does). It does two things in a loop:

Discussion → Inbox (pull direction): Polls the GitHub Discussion for new comments every --interval seconds (default: gh_poll_interval in cryo.toml, or 5s). New comments are written to messages/inbox/ where the daemon picks them up on the next session.

Outbox → Discussion (push direction): Watches messages/outbox/ for new files. When the agent sends a message (via cryo-agent send), the sync daemon posts it as a Discussion comment and archives the file to messages/outbox/archive/.

GitHub Discussion                  Local filesystem
─────────────────                  ─────────────────
New comment        ──(pull)──→     messages/inbox/       → agent reads on wake
                   ←─(push)──     messages/outbox/      ← agent writes via cryo-agent send

The sync is managed as a system service (launchd on macOS, systemd on Linux) that survives reboots. Logs go to cryo-gh-sync.log.

1. Initialize the project

cryo init --agent claude
# edit plan.md with your task
cryo-gh init --repo owner/repo

This creates a Discussion in the repository (enabling Discussions automatically if needed) and writes gh-sync.json with the Discussion number and node ID.

3. Start the daemon and sync

cryo start
cryo-gh sync

Both run as background daemons. Monitor with cryo watch.

4. Send messages from GitHub

Post a comment on the Discussion from the GitHub web UI or mobile app. The sync daemon picks it up within 30 seconds and writes it to messages/inbox/. The daemon wakes the agent on the next session (or immediately if watch_inbox = true).

5. Read agent replies on GitHub

When the agent calls cryo-agent send "message", the outbox file is detected immediately by the sync watcher and posted as a Discussion comment.

6. Stop

cryo-gh unsync   # stop sync daemon
cryo cancel      # stop cryo daemon

One-Shot Usage

For manual or scripted use without the sync daemon:

cryo-gh pull    # fetch new Discussion comments into inbox
cryo-gh push    # post the latest session log to the Discussion

Rate Limits

The sync daemon uses the gh CLI which makes authenticated GitHub API requests. At the default 30-second interval, this is ~120 requests/hour — well within GitHub’s 5,000 requests/hour limit for authenticated users.

Files

FilePurpose
gh-sync.jsonSync state: repo, Discussion number/ID, cursor
cryo-gh-sync.logSync daemon log output
messages/inbox/Incoming messages (from Discussion comments)
messages/outbox/Outgoing messages (posted to Discussion)
messages/outbox/archive/Posted outbox messages (archived after sync)

Zulip Sync

cryo-zulip bridges a cryochamber project with a Zulip stream, enabling remote monitoring and two-way messaging. Stream messages become inbox messages for the agent; outbox messages from the agent are posted back to the stream.

Prerequisites

  • A Zulip server with a bot account
  • A zuliprc file with bot credentials (standard Zulip INI format with [api] section containing email, key, site)
  • A Zulip stream accessible by the bot
  • An initialized cryochamber project (cryo init)

Commands

cryo-zulip init --config ~/.zuliprc --stream my-stream  # Validate credentials, resolve stream, write zulip-sync.json
cryo-zulip init --config ~/.zuliprc --stream my-stream --topic mychannel  # Custom topic (default: "cryochamber")
cryo-zulip sync [--interval N]                           # Start background sync daemon (default from cryo.toml or 5s)
cryo-zulip unsync                                       # Stop the sync daemon
cryo-zulip pull                                         # One-shot: pull new messages → inbox
cryo-zulip push                                         # One-shot: push latest session log → stream
cryo-zulip status                                       # Show sync configuration

How Sync Works

cryo-zulip sync spawns a background daemon (just like cryo start does). It does two things in a loop:

Stream → Inbox (pull direction): Polls the Zulip stream for new messages every --interval seconds (default: zulip_poll_interval in cryo.toml, or 5s). New messages are written to messages/inbox/ where the cryo daemon picks them up on the next session. The bot’s own messages are filtered out to prevent echo loops.

Outbox → Stream (push direction): Watches messages/outbox/ for new files. When the agent sends a message (via cryo-agent send), the sync daemon posts it to the Zulip stream and archives the file to messages/outbox/archive/.

Zulip Stream                      Local filesystem
────────────                      ─────────────────
New message        ──(pull)──→    messages/inbox/       → agent reads on wake
                   ←─(push)──    messages/outbox/      ← agent writes via cryo-agent send

The sync is managed as a system service (launchd on macOS, systemd on Linux) that survives reboots. Logs go to cryo-zulip-sync.log.

1. Initialize the project

cryo init --agent claude
# edit plan.md with your task
cryo-zulip init --config ~/.zuliprc --stream my-stream

This validates the bot credentials, resolves the stream ID, and writes zulip-sync.json. The zuliprc is copied to .cryo/zuliprc for use by the sync daemon.

3. Start the daemon and sync

cryo start
cryo-zulip sync

Both run as background daemons. Monitor with cryo watch.

4. Send messages from Zulip

Post a message in the Zulip stream from the web UI or mobile app. The sync daemon picks it up within 30 seconds and writes it to messages/inbox/. The cryo daemon wakes the agent on the next session (or immediately if watch_inbox = true).

5. Read agent replies on Zulip

When the agent calls cryo-agent send "message", the outbox file is detected immediately by the sync watcher and posted to the Zulip stream.

6. Stop

cryo-zulip unsync   # stop sync daemon
cryo cancel         # stop cryo daemon

One-Shot Usage

For manual or scripted use without the sync daemon:

cryo-zulip pull    # fetch new stream messages into inbox
cryo-zulip push    # post the latest session log to the stream

Example: Chess by Mail over Zulip

Play correspondence chess against an AI agent, sending moves from the Zulip web UI:

cd examples/chess-by-mail
cryo-zulip init --config ~/.zuliprc --stream chess-game
cryo init && cryo start
cryo-zulip sync --interval 30
# Send your moves as messages in the Zulip stream!

See Chess by Mail for the full example.

Files

FilePurpose
zulip-sync.jsonSync state: site, stream, stream ID, bot email, cursor
.cryo/zuliprcBot credentials (copied from user’s zuliprc on init)
cryo-zulip-sync.logSync daemon log output
messages/inbox/Incoming messages (from Zulip stream)
messages/outbox/Outgoing messages (posted to Zulip stream)
messages/outbox/archive/Posted outbox messages (archived after sync)

FAQ

What happens if my computer sleeps or reboots?

Sleep: The daemon process is suspended along with everything else. When your machine wakes up, the daemon resumes and detects that the scheduled wake time has passed. It runs the session immediately and includes a “DELAYED WAKE” notice in the agent’s prompt with the original scheduled time and how late the session is.

Reboot: The daemon is installed as an OS service (launchd on macOS, systemd on Linux) and restarts automatically after reboot. Set CRYO_NO_SERVICE=1 before cryo start to disable this and use a plain background process instead.

How do I manually wake a sleeping daemon?

Use cryo wake to send a message to the daemon’s inbox. You can include a message: cryo wake "Please check the latest PR". If inbox watching is enabled (the default), the daemon wakes immediately. You can also use cryo send --wake for the same effect. If inbox watching is disabled, cryo wake sends a SIGUSR1 signal to force the daemon awake. If no daemon is running, the message is queued for the next cryo start.

Troubleshooting

Error: cryo.toml not found

You haven’t initialized the project. Run cryo init first.

Error: plan.md not found

cryo start requires a plan.md in the working directory. Create one or run cryo init to generate a template.

Error: agent command 'opencode' not found on PATH

The configured agent isn’t installed. Either install it or change the agent:

cryo start --agent claude       # use a different agent
# or edit cryo.toml: agent = "claude"

Error: daemon already running

A daemon is already active for this project. Check with cryo status, or stop it with cryo cancel before starting a new one.

Error: connection refused (from cryo-agent commands)

The daemon isn’t running. The cryo-agent CLI needs a running daemon to communicate with via the Unix socket. Start the daemon with cryo start.

cryo status shows “stale PID”

The daemon process died without cleaning up. Run cryo cancel to clear the stale state, then cryo start again.

Agent keeps crashing (retries exhausted)

Check cryo-agent.log for the agent’s raw output. Common causes:

  • Agent hitting rate limits (add max_session_duration to throttle)
  • Missing dependencies in the project
  • Agent doesn’t understand the cryo-agent protocol (check the generated AGENTS.md/CLAUDE.md)

cryo-gh: gh: command not found

Install the GitHub CLI and authenticate: gh auth login.

cryo-gh: no gh-sync.json found

Run cryo-gh init --repo owner/repo to create a Discussion and initialize sync state.

Mr. Lazy

The laziest cryochamber example: an AI agent that refuses to get out of bed.

Every time cryochamber wakes Mr. Lazy, he rolls a die — 25% chance he actually gets up. Otherwise, he delivers a dramatic, unique complaint and hits snooze for a few more minutes. Repeat until he finally rolls a 4.

Demonstrates: repeated wake cycles, cryo-agent time for scheduling, cryo-agent note for cross-session memory, probabilistic plan completion.

Quick Start

cd examples/mr-lazy
cryo init && cryo start
cryo web   # open the browser chat UI (port 3946)

Or use the Makefile target (runs in daemon mode, Ctrl-C to stop):

make check-agent

What You’ll See

Session 1: "What is the point of consciousness this early? It's only 09:15..."
  → cryo-agent todo add "complain again" --at 2026-03-08T09:18
  → cryo-agent hibernate --summary "Too early, going back to sleep"

Session 2: "No hobbit ever woke up before second breakfast... and it's 09:18."
  → cryo-agent todo add "maybe get up" --at 2026-03-08T09:22
  → cryo-agent hibernate --summary "Still not ready, snoozing again"

Session 3: "Fine. FINE. I'm up. Are you happy now?"
  → cryo-agent hibernate --complete --summary "Mr. Lazy finally got out of bed"

Use cryo cancel if you can’t wait for Mr. Lazy to roll a 4.

Chess by Mail

Play correspondence chess against an AI agent, powered by cryochamber.

The AI polls for your moves on a configurable interval. If you’re away too long, it goes to sleep — send a move and wake it when you’re ready to continue.

Why Cryochamber

A cron job can’t do this because:

  • The AI decides when to stop checking (adaptive patience, not fixed schedule)
  • Wake-up from deep sleep is event-driven (your next move), not time-driven
  • Board state and strategy notes persist across arbitrarily long gaps
  • Multiple moves can accumulate; the AI processes them all on wake

Prerequisites

  • uv (the chess engine script uses uv for dependency management)

Quick Start

cd examples/chess-by-mail
cryo init && cryo start
cryo web   # open the browser chat UI (port 3947)

Playing

# Send a move (algebraic or coordinate notation)
cryo send "e2e4"
cryo send "Nf3" --wake  # wake the AI immediately

# Or use the web UI
cryo web

How It Works

The AI uses chess_engine.py (powered by python-chess via uv) for all chess operations. After each move, the AI recommends 3 candidate moves for you with tactical explanations.

Playing via Zulip

You can play from the Zulip web UI instead of the terminal by connecting a Zulip stream. See Zulip Sync for full setup details.

cd examples/chess-by-mail
cryo-zulip init --config ~/.zuliprc --stream chess-game
cryo init && cryo start
cryo-zulip sync --interval 30

Now send your moves as messages in the Zulip stream. The sync daemon delivers them to the agent’s inbox and posts replies back to the stream.

To stop: cryo cancel && cryo-zulip unsync

Configuration

Edit plan.md to change:

  • Which color the AI plays (default: black)
  • Check interval (default: 10 minutes; set to 1 minute for a fast demo)
  • Patience threshold (default: 5 checks before sleeping)

Architecture

Core Loop

cmd_start() → spawn cryo daemon → event loop: spawn agent → listen on socket server for IPC commands → sleep until wake time or inbox event → run session → …

Binaries

BinaryPurpose
cryoOperator CLI — init, start, status, cancel, log, watch, send, receive, wake, ps, restart, daemon
cryo-agentAgent IPC CLI — hibernate, note, send, receive, alert, time (sends commands to daemon via socket; receive and time are local)
cryo-ghGitHub sync CLI — init, pull, push, sync, unsync, status (manages Discussion-based messaging via OS service)

Modules

ModulePurpose
socketUnix domain socket IPC — message types (Request/Response), client (send_request), server (SocketServer).
configTOML persistence for project config (cryo.toml). CryoConfig struct, load/save, apply_overrides merges CLI overrides from state.
stateJSON persistence to timer.json — runtime-only state (session number, PID lock, CLI overrides). PID-based locking via libc::kill(pid, 0).
logSession log manager. Sessions delimited by --- CRYO SESSION N --- / --- CRYO END ---. EventLogger writes timestamped events (agent start, notes, hibernate, exit).
protocolLoads templates from templates/ via include_str! (protocol, plan, cryo.toml). Written by init/start.
agentBuilds lightweight prompt with task + session context, spawns agent subprocess (stdout/stderr redirected to cryo-agent.log).
processProcess management utilities: send_signal, terminate_pid, spawn_daemon.
daemonPersistent event loop: socket server for agent IPC, watches messages/inbox/ via notify, handles SIGUSR1 for forced wake, enforces session timeout, EventLogger for structured logs, retries with backoff (5s/15s/60s), executes fallback actions on deadline, and detects delayed wakes (e.g. after machine suspend).
messageFile-based inbox/outbox message system. Inbox messages included in agent prompt on wake.
fallbackDead-man switch: writes alerts to messages/outbox/ for external delivery.
channelChannel abstraction. Submodules: file (local inbox/outbox), github (Discussions via GraphQL).
registryPID file registry for tracking running daemons. Uses $XDG_RUNTIME_DIR/cryo/ (fallback ~/.cryo/daemons/). Auto-cleans stale entries.
serviceOS service management: install/uninstall launchd (macOS) or systemd (Linux) user services. Used by cryo start and cryo-gh sync for reboot-persistent daemons. CRYO_NO_SERVICE=1 disables (falls back to direct spawn).
webAxum-based web server with chat UI, REST API, and SSE for real-time updates.
gh_syncGitHub Discussion sync state persistence (gh-sync.json).

Key Design Decisions

  • Daemon mode: cryo start installs an OS service (launchd on macOS, systemd on Linux) that survives reboots. The daemon sleeps until the scheduled wake time, watches messages/inbox/ for reactive wake, and enforces session timeout. Set CRYO_NO_SERVICE=1 to fall back to direct background process spawn.
  • Socket-based IPC: The agent communicates with the daemon via cryo-agent CLI subcommands (hibernate, note, send, alert), which send JSON messages over a Unix domain socket. receive and time are local (no daemon needed).
  • Fire-and-forget agent: The daemon spawns the agent and redirects its stdout/stderr to cryo-agent.log. All structured communication flows through the socket.
  • SIGUSR1 wake: cryo wake and cryo send --wake send SIGUSR1 to the daemon PID, which works regardless of watch_inbox setting. The daemon’s signal-forwarding thread converts this into an InboxChanged event.
  • Config/state split: cryo.toml is the project config (agent, retries, timeout, watch_inbox) created by cryo init. timer.json is runtime-only state (session number, PID, retry count, CLI overrides). CLI flags to cryo start are stored as optional overrides in timer.json.
  • Graceful degradation: If the agent exits without calling cryo-agent hibernate, the daemon treats it as a crash and retries with backoff. EventLogger is always finalized even on error.
  • Default agent: The CLI defaults to opencode run as the agent command (headless mode, not the TUI).

Files Created at Runtime

FilePurpose
timer.jsonRuntime state (session number, PID lock, retry count, CLI overrides)
cryo.logAppend-only structured event log
cryo-agent.logAgent stdout/stderr (raw tool-call output)
messages/inbox/Incoming messages for the agent
messages/outbox/Outgoing messages (fallback alerts)
messages/inbox/archive/Processed inbox messages
.cryo/cryo.sockUnix domain socket for agent-daemon IPC
gh-sync.jsonGitHub Discussion sync state (if configured)
cryo-gh-sync.logGitHub sync daemon log output (if configured)