Skip to main content
Forks are not free-floating: the daemon organizes them in a snapshot tree, where each child is a delta against its parent. This is the shape RL exploration wants — branch the environment at decision points, explore each branch independently, keep the winners, prune the losers:
A tree’s payload is either a single VM or a whole cluster (N member VMs forked, suspended, and resumed as one unit — see Cluster mode).

Node lifecycle

Full request/response shapes: Daemon API.

Budgets

The agent decides what to keep; k7d enforces budgets so the tree doesn’t eat the machine. Every tree carries a TreeBudget: When a tree_create* request omits the budget, the daemon applies a documented default sized for a node running a handful of 256 MiB guests: 8 live VMs, 8 GiB RAM, 32 GiB disk, chain depth 1.

LRU eviction

Under budget pressure, the daemon suspends the least-recently-active unprotected nodes: their delta goes to disk and their RAM is freed. Suspended nodes can be resumed later. Proactive suspension kicks in at 85% of the RAM budget — kept well below OOM territory and kernel reclaim stalls. tree_protect pins a node (a winner you cannot afford to lose) so budget pressure can’t touch it. Eviction never deletes state — only tree_prune does. The budget/eviction bookkeeping is one of the two formally verified pieces of k7d: the model is translated to Lean via Aeneas and its invariants are machine-checked. See Formal verification.

Node metadata

tree_nodes returns every node’s metadata (NodeInfo): id, parent, children, state, label, dirty_page_count (pages this node’s delta captures; Σ over members for a cluster), has_base_snapshot (whether the node has its own full memory image — a checkpoint / fork-point), created_at_unix, last_active_at_unix (what LRU ranks on), protected, payload kind (Vm or Cluster), and vm_count.