OpenLoom
Don't trust the agent's word — trust the file system.
OpenLoom is a webhook-driven task harness for OpenCode. It gives OpenCode a JSON task API, a session monitor, webhook fan-out, a web dashboard, and a file-inbox storage runner — so you can dispatch work from anywhere, even a phone.
OpenLoom does not replace OpenCode. It fills the gaps in its HTTP API.
Install
Requires Python 3.11+ and a running OpenCode server.
uv tool install openloom
That's it. Server deps, python-docx, requests — all bundled. No --with, no [extras].
Quick start
1. Start OpenCode
opencode serve
2. Configure (optional)
Defaults work out of the box with a local OpenCode on port 4096. For custom setups:
openloom init
This writes ~/.openloom/config.yaml. Edit it, or use env vars:
export OPENLOOM_OPENCODE_URL=http://127.0.0.1:4096
export OPENLOOM_OPENCODE_USERNAME=opencode
export OPENLOOM_OPENCODE_PASSWORD=your-password
3. Start OpenLoom
openloom serve
Web dashboard at http://127.0.0.1:8967. Verbose logging: openloom serve -v.
Webhook API
Dispatch a task from any HTTP client, CI pipeline, or messaging bot:
curl -X POST http://127.0.0.1:8967/api/tasks \
-H "Content-Type: application/json" \
-d '{"name": "fix-typo", "workspace": "/path/to/project", "goal": "Fix the typo in README.md"}'
Endpoints:
| Method | Path | Description |
|---|---|---|
POST |
/api/tasks |
Create and dispatch a task |
GET |
/api/tasks |
List all tasks |
GET |
/api/tasks/{id} |
Get task status |
POST |
/api/tasks/{id}/abort |
Abort a stuck session |
DELETE |
/api/tasks/{id} |
Delete a task |
GET |
/api/tasks/{id}/events |
SSE stream of task events |
Task payload
{
"name": "unique-task-name",
"workspace": "/absolute/path/to/project",
"goal": "Natural-language instruction for OpenCode"
}
Webhook notifications
OpenLoom fires webhooks on task lifecycle changes. Configure in config.yaml:
bus:
webhook_url: https://your-service.com/hooks/openloom
webhook_secret: "shared-secret"
Event payload:
{
"event": "TASK_UPDATED",
"task_name": "fix-typo",
"task_id": "abc123",
"status": "completed",
"timestamp": 1719676800,
"timestamp_iso": "2024-06-29T12:00:00+00:00",
"recent_activity": [...]
}
Storage Runner
Drop files into an inbox directory and OpenLoom dispatches them as tasks automatically.
Setup
Add a storage level to config.yaml:
levels:
storage:
path: ./inbox # directory to watch
poll_interval_s: 5 # check every 5 seconds
class: myapp.MyConnector # optional connector class
Supported formats
| Extension | Format |
|---|---|
.yaml / .yml |
Task spec (name, workspace, goal) |
.md |
Markdown — first heading as name, body as goal |
.txt |
Plain text |
.docx |
Word documents (auto-detected) |
Connectors
Storage connectors fetch task files from external sources. A connector is a Python class with a download(path) -> bytes | None method. Put it in ./connectors/:
# connectors/mysource.py
import requests
from openloom.levels.storage.base import Connector
class MyConnector(Connector):
def __init__(self):
self._session = requests.Session()
self._session.proxies = {"http": None, "https": None} # bypass system proxy
def download(self, path: str) -> bytes | None:
url = f"https://my-server/files/{path}"
r = self._session.get(url, timeout=30)
r.raise_for_status()
return r.content
Configure in config.yaml:
levels:
storage:
class: mysource.MyConnector
Dashboard
openloom serve serves a Svelte dashboard at http://127.0.0.1:8967:
- Dashboard — live task overview
- Tasks — create, browse, abort, delete tasks
- Activity — event stream with session messages
- Session drawer — inspect OpenCode sessions in real time
Configuration
Run openloom init for a starter ~/.openloom/config.yaml. Key sections:
opencode_url: "http://127.0.0.1:4096"
server:
port: 8967
bus:
webhook_url: ""
webhook_secret: ""
levels:
storage:
path: ./inbox
poll_interval_s: 5
Full reference: docs/configuration.md.
Requirements
- Python 3.11+
- OpenCode running with HTTP API enabled
Metadata
Release files for openloom 0.17.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| openloom-0.17.0.tar.gz | 678.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openloom-0.17.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.3 MB
Release files / openloom-0.17.0.tar.gz
| Download URL | openloom-0.17.0.tar.gz |
|---|---|
| Size | 678.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
465d26b08efb4c98b7b31a6f80ac88a0702085c0174b20370504af04f42a0521
|
|
BLAKE2b-256 checksum How to use checksums |
dbedf882d9e6c94dc5cac91903ccc20950642fb50929b3fe8adcdb037592a00b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 9, 2026.
Transparency logRelease files / openloom-0.17.0-py3-none-any.whl
| Download URL | openloom-0.17.0-py3-none-any.whl |
|---|---|
| Size | 667.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cfe0a155d1fb5e3f43a339cc5244e3e860ef397d0cf49fc3f449cc47b7627a1f
|
|
BLAKE2b-256 checksum How to use checksums |
0462273cc8088736256b793efd2942cae99465b2eb1609fa51532b7bb5ff5d1c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 9, 2026.
Transparency log