Loom¶
Loom (lithos-loom) is the orchestration daemon of the Lithos ecosystem. It subscribes to Lithos's event stream, claims Lithos tasks by tag, and hands them to subprocess plugins — the shipped one, story-develop, runs an implement → review → PR loop with containerised coding agents. It also projects Lithos tasks into an Obsidian vault and mirrors GitHub issues into Lithos tasks.
Status: pre-release, under active development, documents main
Loom has no tagged release yet (package version 0.1.0) and its CLI, config and plugin surfaces still change week to week. These pages describe the current main branch of agent-lore/lithos-loom; the per-command CLI pages are pulled from that repo at build time so they cannot lag it.
Source repo: github.com/agent-lore/lithos-loom (MIT).
Three surfaces¶
One lithos-loom run process is a supervisor that forks up to three children, each gated by a block in the TOML config:
| Surface | Child | Spawn gate | What it does |
|---|---|---|---|
| Route-runner | route-runner |
any [[routes]] stanza |
Consumes lithos.task.created / updated / released events, matches task tags against routes, asks Lithos whether the task is ready, claims it collision-safely, runs the route's plugin as a subprocess and applies result.json. Adding a route's trigger tag to an already-open task dispatches it without a restart. |
| Obsidian bridge | obsidian-sync |
[obsidian_sync] present |
Projects open tasks into a Tasks-plugin-compatible _lithos/tasks.md, pushes tick / priority / due-date edits back to Lithos, mirrors project-context docs both ways, and ships Templater macros for capture. |
| GitHub issue watcher | github-watcher |
[github_watcher] enabled = true |
Polls each watched repo, materialises new issues as Lithos tasks carrying metadata.github_issue_url, mirrors title / body / labels / close in both directions, and resolves the pr gates that delivered PRs leave behind. |
Each child runs its own in-process event bus and its own connection to Lithos; there is no inter-child IPC. Restart safety comes from sources re-bootstrapping on connect and subscribers being idempotent — Loom keeps no persistent event log.
How it fits the ecosystem¶
flowchart LR
GH["GitHub\nissues + PRs"] <--> LOOM
OBS["Obsidian vault"] <--> LOOM
LOOM["Loom daemon\n(host process)"] <--> LITHOS["Lithos\n/sse + /events"]
LOOM --> PLUG["Plugin subprocess\n(story-develop →\nclaude / codex in docker)"]
PLUG --> GH
LENS["Lens (web UI)"] --> LITHOS
INFLUX["Influx (ingestion)"] --> LITHOS
- Lithos owns the corpus and the task lifecycle. Loom never replaces it as the source of truth — the vault is a projection plus a narrow write surface, and every orchestration state Loom needs to survive a restart lives on the Lithos task (metadata keys, findings, gate tasks and
waits_on_gateedges). - Loom is the only piece that runs coding agents. A
story-developrun ends with a reviewed branch and an open PR; the task stays open behind a first-classprgate until the PR merges, when the watcher completes the story. - Lens reads the same gates, findings and
reconciliation_statekeys Loom writes; Influx feeds the knowledge base Loom's agents search.
Loom deliberately runs as a host process, not a container: it creates git worktrees you can cd into, invokes claude / codex / gh CLIs that authenticate against per-user dotfiles, and must be on Obsidian Desktop's PATH for the Templater macros.
What Loom needs from Lithos¶
Loom talks MCP to Lithos over the /sse endpoint and consumes GET /events for task.* and note.* events. Beyond the ordinary task and knowledge tools it depends on:
| Lithos feature | Used for |
|---|---|
task.metadata + single-shot lithos_task_create(metadata=...) |
Every metadata.* key Loom reads or writes (project, priority, develop_*, github_issue_url, markers) |
Task graph: task_type, blocks / parent_child / waits_on_gate edges, lithos_task_ready / lithos_task_blocked / lithos_task_spawn |
Server-side readiness (the runner never derives it itself), project import task graphs, pr and human gates. The daemon refuses to boot if the probe fails. |
lithos_write(id=..., expected_version=...) with the version_conflict envelope |
Vault → Lithos note push with optimistic locking |
lithos_task_complete returning the tasks it unblocked |
Dispatching the next task in a chain off the completion itself |
lithos_finding_post |
Prefixed findings ([Friction], [NeedsHuman], …) — the operator-facing audit trail |
Run lithos-loom doctor to probe all of this end to end against a live server.
Pages¶
| Page | What it covers |
|---|---|
| Installation | Requirements, uv install, config discovery, running and draining the daemon, doctor |
| Concepts | Routes and tag matching, readiness and claiming, the plugin contract and result.json, gates, the event bus, finding prefixes |
| story-develop | The implement → review → PR loop, review profiles and personas, model resolution, converge, merge gate, review-only mode, admission |
| Obsidian bridge | Projects, the task inbox projection, bidirectional sync, Templater macros |
| GitHub watcher | Issue mirroring in both directions, per-project repos, the per-host gate, reopen handling, PR-gate resolution |
| CLI | Every command group at a glance, with links to the per-command reference pages |
| Changelog | Current state of main (no tagged releases yet) |