Trove parts
The parts of Trove, the door that reaches them, and who writes their state
Trove runs Claude Code sessions as an unattended work engine: each session works in its own git worktree, and you finalize the result to the default branch. This page explains how Trove is cut into parts, how a program outside the Hub reaches them, how a recurring spec uses them, and why one process writes all of their state.
One part, one job
Each part of Trove does one thing, keeps its own store, and has its own OPAL task family:
| Part | Its job | Task family |
|---|---|---|
| Specs | Stores structured specs and their work units, with history and leases | spec.* |
| Worktrees | Keeps many named worktrees on one checkout | worktree.* |
| Sessions | Runs LLM sessions and records their turns | session.* |
| Builds | Builds and tests, admitted by the machine's kiln broker | build.* |
| Placement | Decides where a job runs: here, later, or on another node | fleet.*, batch.* |
A part depends only on the libraries below it, never on a sibling. Where one
part needs the work of another, Trove passes it in. For example, the worktrees
part knows git and nothing about Claude Code: when Trove creates a worktree for
a session, the sessions part writes the session's CLAUDE.md and hook
configuration into it, and the worktrees part keeps those files out of git.
The door
The door is the one local endpoint of your user on your computer that answers OPAL calls from outside the app. A Claude Code session in a terminal, or a tool you run, calls a task through the door and gets the result. There is no network listener: a remote node reaches the parts over the node's own comms.
The door lives in a folder of your user only:
<runtime folder>/octomy-door/where the system gives each user a runtime folder, as/run/user/<uid>on Linux.<cache folder>/octomy-door/where it does not, as on Windows.
The folder holds door.lock, door.json and, where local sockets are files,
door.sock. door.json names the endpoint, a token that is new at each start,
the process and the identity that the door serves. Only your user can read it,
and the token is how a call proves that it came from someone who could.
Who serves the door
The door has two hosts, and one lock decides between them:
- The Hub. A Hub that runs on its default data folder, or with
--door, opens the door when it starts. An agent and a remote never do. - The standalone host. When no Hub runs, a tool can start the Hub without
its window,
hub --head-less --door, if you allowed it. Turn on Keep the Trove door open without the HUB window in the Hub's Trove settings. When that Hub starts later, it asks the standalone host to hand the door over, and the host ends after its running calls.
A Hub that finds another Hub holding the door serves none. It waits up to a minute, then works as a client of the Hub that has it.
What a call can do
A call names a task and its arguments. The door host runs it as one OPAL plan, with the same grants, preconditions and history as a call from the Hub's own chat. A call is refused quickly and by name when it cannot run:
- An unknown task answers
404. Aspec.*task on a door whose spec database is not open fails instead, and names the identity that the door serves: a head-less host with a locked hive, or a node with no identity, has no spec database. - A task whose scope you did not grant answers
403and names the scope. You grant and revoke scopes on the Hub's Door permissions page. Three ways lead there: the Settings tab of Trove, the Door category of the Trove settings, and Permissions in the OPAL group of the sentient lobby. - A task that asks before every call answers
409when nobody can answer: on the standalone host, run that call in the Hub instead.
Calls whose tasks use different resources run at the same time. Calls on one
resource run in order, and a call that waits more than 30 seconds for its
resource answers 503 and is tried again.
A lane is a composition
A lane is a name, a color and an active plan. Everything else belongs to a part: the lane's worktree to the worktrees part, its session to the sessions part, its builds to kiln, and its work units to the spec database. You can also compose the parts by hand, with no lane at all: a worktree, a session in it, and a build of it.
Recurring specs
Some work never ends. A lint debt or a count of raw owning pointers goes down with each fix, and goes up again with the work of other people. A recurring spec is an ordinary spec with one switch, Recurring. When the switch is on, a schedule of clockwork starts a run at its times. When the switch is off, the schedule pauses, and every setting and the history stay, dormant.
A run uses the parts in turn:
- The worktrees part makes a detached worktree at the head of
origin/main. Trove measures each probe there: the finding count of a lint check, or the matches of a regular expression. This is the before value. - The specs part copies the template unit of the spec into a new unit, and
the run gives it to a lane, as
trove.dispatchdoes. - The sessions part runs the session in the lane's worktree.
- Trove measures each probe again, on the head of the lane's branch. This is the after value.
- Trove, not the session, records the standard
STD-MEASUREand judges the run. A probe passes when it is better than before, or meets its target.
The spec database keeps every sample for good. So the history shows the trend of each probe, and the drift: the change that other work made between two runs. Example: a run lands at 945, and the next run starts at 952. The drift is +7.
Trust
A run leaves its work on its lane's branch, until you trust the spec. Then
a run that passed its judgement lands on main by itself. Trust is a choice
that you make in the Hub, one spec at a time. A change to the run plan clears
it.
The lander is mechanical C++ in the worktrees part. It works in a worktree of
its own, and no model takes part. Each step is a guard: the kill switch, the
window, a clean rebase, a diff that is not empty and under the delete limit,
the verify step, the probes on the exact commit, and a push that is never
forced. When main moves, the lander tries again, at most three times in a
run. Then it defers the landing to the next run. The door never gets the scope
spec.trust, so a session can never trust a spec or land a run.
Run a recurring spec and Trust a recurring spec give the steps.
One writer
All the state of the parts for one identity has exactly one writer: the process that holds the door's lock. Nothing else stops two Hubs from opening one data folder, so the door's lock decides. The spec database keeps its own rule on top of that: one database file for each sentient and device.
The door host also backs the spec database up: once a day, at the first call
after midnight, and before it opens a database of an older schema. The
door.status task reports when the last backup ran and why it failed, if it
did.