Install
$ agentstack add mcp-teaarte-loom ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Agent runs you can prove — not just trust
loom drives multi-step LLM agent work — code review, implementation, any review-gated task — as a replay-deterministic state machine: safety invariants enforced at commit time, human gates where they matter, and a complete, replayable audit trail in a local SQLite file you own.
[](https://www.npmjs.com/package/@loomfsm/pipeline) [](LICENSE) [](.nvmrc) [](#) [](https://loomfsm.dev)
loomfsm.dev · Quickstart · Why loom · Blog · [Architecture](ARCHITECTURE.md) · [Whitepaper](WHITEPAPER.md)
A task parked on its final gate: the security reviewer found a blocker — the run waits for you.
What is loom
You hand loom a task. It drives a sequence of LLM agents through phases — classify → plan → implement → review → validate → finalize — committing every step atomically to a local SQLite database. You approve at the gates that matter; everything else runs on its own. The whole run is recorded and replayable, and invariants make certain failures structurally impossible: an agent can't sign off while a blocking issue is open, or rewrite the tests it's judged by and self-approve.
flowchart LR
C([classify]) --> P([plan]) --> I([implement]) --> R([review]) --> V([validate]) --> F([finalize])
Durable execution — checkpointing, retries, resume — became table stakes for agent infrastructure. loom is built for the layer above: structural safety and a provable process. It's for high-stakes, multi-step, review-gated work where being wrong is expensive — not throwaway prompts.
It runs five ways, all driving the identical state machine, gates, and invariants:
| | mode | when to use | |---|---|---| | 🖥️ | Web dashboard — loom up | a browser console for the whole fleet — submit, watch, approve, configure | | 📱 | Telegram bot — loom bot telegram | drive the fleet from your phone — submit, approve gates, ship — over a chat | | 💬 | Inside your agent host — /task … | zero setup; runs through Claude Code, no API key | | ⚡ | Headless one-shot — loom run "…" | drive one task to the end from a terminal | | 🤖 | Autonomous daemon — loom daemon | set-and-forget; parks on your gates, wakes when you answer |
Quickstart
npm i -g @loomfsm/pipeline # installs the `loom` CLI and everything it needs
Web dashboard — the fastest path:
loom up # start the local control plane and open the dashboard
It opens at http://127.0.0.1:4317 with a first-run wizard: choose a backend, add a project, submit your first task.
Inside your agent host (Claude Code):
loom setup # register the MCP server + the /task, /done, /proceed commands
loom allowlist add # authorize the current project (once per project; default-deny)
then, in that project: /task add rate limiting to the login endpoint.
State lives at /.loom/state.db — a plain SQLite file you own. loom setup is idempotent and never overwrites a command you've edited.
Running loom
Every mode drives the same engine; they differ only in who executes each step and how long it waits for you.
Web dashboard — loom up
One local server supervises a fleet of projects and serves a web UI. loom up starts it and opens the page (a bare loom does the same).
loom up # start + open the browser
loom up --no-open # start without a browser (SSH / headless)
loom up --port 8080
loom up --token "$(openssl rand -hex 16)" # require a bearer token on the API
From the dashboard you can:
- browse projects and their live status — running, parked at a gate, or stalled — with total elapsed time;
- add a project by browsing to its folder in an in-app picker (works for a brand-new empty directory), or by path; it's named by its folder, not its full path;
- submit a task, choose its policy, flag it ⚡ fast for a single-pass run (or pick a complexity), optionally run it in Docker (see [Container isolation](#container-isolation)), and pre-arm push / squash-merge on accept;
- pause / resume / cancel — pause stops spending but keeps progress; resume re-drives from where it left off; cancel frees the slot — then push or squash-merge a finished task on demand;
- answer a gate (accept / reject / auto-apply) — reading the exact spawn output you're approving — and tail a collapsible live log over SSE, with tokens / turns / cache as the cost signal;
- inspect the agent chain — a horizontal timeline of runs, each with its model, tokens, and duration; click one to read its prompt + output and the findings / verdicts it produced — for the live task and for any finished task in history;
- configure once — tabbed settings for global config, secrets (write-only, masked), the per-agent model map, and provider keys managed per backend, through forms generated from the config schema.
The server binds loopback by default and refuses to bind to a non-loopback host without a token. Pass --token (or set LOOM_SERVER_TOKEN) to require Authorization: Bearer … on every API call. This is a localhost operator console, not a multi-tenant service.
loom serve is the same control plane without a browser — for a remote box or an always-on supervisor (loom serve --project ./svc --token "$TOKEN"; loom serve status | stop).
Telegram bot — loom bot telegram
Drive the fleet from your phone. The bot is a thin client of the control plane (loom up / loom serve): pick a project, submit a task, approve or answer gates with inline buttons, read the plan and live status on a tap, and push / squash-merge a finished task — all from a chat.
export LOOM_TG_BOT_TOKEN=""
export LOOM_TG_ALLOWED_USERS="" # comma-separated; default-deny
loom bot telegram # needs a control plane running (loom up / loom serve)
It is outbound-only (long-poll, no webhook), so the control plane stays loopback-bound — there is no inbound port to open. The one auth surface is the user-id allowlist: the bot can launch agents on your repos, so an un-listed sender is refused (message the bot once and it replies with your id). Point it at a remote plane with LOOM_SERVER_URL / LOOM_SERVER_TOKEN.
Inside your agent host — /task
Zero setup: your host (Claude Code) executes each agent step, and loom surfaces each gate inline. No API key, no network.
/task add rate limiting to the login endpoint # start
/proceed # re-attach to an interrupted task
/done # show the result + clear the slot
Headless one-shot — loom run
loom run "add rate limiting to the login endpoint"
Each step runs through the Claude Code CLI (claude -p) in an isolated git worktree, on your existing login — your subscription, no API key. A genuine human gate pauses and is printed for you to answer; otherwise it runs straight to a verdict. Your main working tree is never touched.
Autonomous daemon — loom daemon
A long-lived supervisor over the headless loop — "set it and check back".
loom daemon start "migrate the auth module to the new SDK"
loom daemon status # driving / parked at a gate / backing off?
loom daemon stop
It runs the work server-side and surfaces you only at decision points: it parks on a human gate and wakes when you answer, retries transient failures with backoff, recovers an interrupted task on restart (idempotent re-delivery, no double work), and commits finished work to a loom/ branch — reviewable, never auto-merged. --watch keeps the slot for the next task; --detach runs it in the background.
Container isolation
The git-worktree default isolates the file tree but not the process. For unattended autonomy, run each spawn inside a container that mounts only a dedicated clone of the project (never your live checkout) plus the one credential needed to sign in — a real blast-radius bound.
# 1. Build the reference image (Claude Code CLI + git). Needs loom's docker/ dir — clone the
# repo, or bring your own image that has `claude` + `git` on PATH.
docker build -t loom-claude:latest docker/
# 2. Point loom at the image + mint a SUBSCRIPTION token (not an API key).
export LOOM_DOCKER_IMAGE=loom-claude:latest
export CLAUDE_CODE_OAUTH_TOKEN="$(claude setup-token)"
# 3. Use it — in the SAME shell (the capability is read once at startup):
loom run --docker "refactor the payment module" # CLI: require the fence (no fence, no run)
loom daemon start --docker --watch # autonomous, fenced
loom up # dashboard: the per-task "run in Docker" box is now enabled
The toggle is auto by default (use Docker if available, else fall back to the worktree with a notice); --docker requires it; --no-docker forces the worktree. loom claims only the isolation it actually provides. Full setup, environment variables, and how the work comes back: [docker/](docker/).
CLI reference
# run
loom up [--no-open] [--port p] [--token t] [--project dir]... start the control plane + open the dashboard
loom serve [--project dir]... [--host h] [--port p] [--token t] [--detach] [--docker|--no-docker]
loom serve stop | status
loom run "" [--docker|--no-docker] drive one task to the end (headless)
loom daemon start [--watch] [--detach] [--docker] [""] supervise a project: park/wake, retry, recover
loom daemon stop | status [path]
loom bot telegram drive the fleet from a Telegram chat (needs a running plane)
# configure once (global; every project inherits it)
loom config get [key] | set backend mode + notify / resilience defaults
loom secrets set | list machine-local secret store (chmod 600); masked on list
loom models set | list bind a bundle's agents to models
loom projects add [path] [--label ] | list | remove the catalog of projects you've worked on
# host setup & project lifecycle
loom setup [--user|--project] [--dry-run] [--force] register the MCP server + /task,/done,/proceed
loom allowlist add [path] [--dry-run] | list authorize a project directory (default-deny)
loom init [--dry-run] ensure .loom/ + authorize this project
loom status [path] read-only snapshot of the task (flags a stall)
loom reset [path] [--force] [--dry-run] archive a finished task, free the slot
loom history [path] list this project's archived tasks
loom --help | --version
Configure once
loom resolves a backend per spawn. Set your keys and a per-agent model map once — from the CLI or the dashboard — and every project inherits it.
loom config set backend auto # Claude Code CLI if present, else a provider
loom secrets set OPENROUTER_API_KEY sk-... # chmod 600, referenced as secret:, never printed
loom models set implementer openrouter:deepseek/deepseek-chat # bind an agent to a model
loom models list # each agent's effective model
autoprefers the Claude Code CLI (your subscription, no key) and falls back to a
configured provider — OpenRouter, Ollama (local), or Anthropic.
- Each agent can declare a fallback chain — try your subscription first, fall back to a
provider on a rate limit or a hard failure — so a long run doesn't stall on one backend.
- Decision agents (classify, review) run as a single model call; a file-editing agent runs
through an agentic-CLI harness — Aider or opencode — behind the same isolated-worktree seam as claude -p, so an implementer can run on DeepSeek or a local Ollama model and actually edit files. The harness is chosen by a generic, bundle-declared capability, never by name.
- The dashboard edits this same layer through schema-generated forms — nothing is UI-only.
> Multi-backend dispatch is validated against real non-Claude models, with hardening > continuing. The zero-config default runs through your Claude Code login.
Why loom
🛡️ Safety enforced at commit time, not promised by a prompt. Invariants run inside the database transaction and roll it back on violation — the unsafe state never exists. The code bundle ships rules like "acceptance can't pass while a blocking finding is open" and "if an agent touched the tests, the final gate must be human-approved" — so an agent can't quietly rewrite the tests it's judged by and approve itself. Guardrails are prompts; invariants are guarantees.
🔁 Replay-deterministic and fully auditable. State lives in atomic SQLite transactions with one timestamp token threaded through every step. Every spawn, finding, verdict, and gate is recorded — open the database and see exactly what happened, or replay a recorded run against a changed invariant to ask "would the new rule have caught last week's incident?"
🎚️ Human-in-the-loop, on a dial. A policy decides each gate: human (approve every step), on-blockers (ask only on a real blocker — the default), or auto (full autonomy with a deterministic safety floor).
🔌 Pluggable by design. Three orthogonal axes — bundles (the domain), providers (the LLM backend), transports (the wire). Any combination is valid at the kernel boundary; a new domain is a new bundle and the kernel never changes. The kernel contains no vendor, model, or transport names (enforced by CI).
💥 Crash-safe. Same (state, timestamp, ledger) → same trajectory. Recovery is "restart and let the idempotency ledger dedup" — no half-applied steps. A drop just pauses the daemon, and it resumes on its own.
> What it guarantees — honestly. loom guarantees the process: the declared review ran, > nothing was bypassed, irreversible steps got a human. It does not guarantee the model's > output is correct — that's the agents' job. What you get is the ability to prove which > process ran and see every decision behind a result.
Architecture
The kernel is generic — it knows nothing about code review or any domain. Three orthogonal axes plug into it (bundles = the domain, providers = the LLM backend, transports = the wire), and any combination is valid. A shared @loomfsm/driver runtime holds the transport-neutral drive() loop every transport wraps, so the directive contract is implemented once and the kernel never changes for a new domain.
📐 Full architecture, with diagrams — [ARCHITECTURE.md](ARCHITECTURE.md). Design rationale — [WHITEPAPER.md](WHITEPAPER.md). The short version — loomfsm.dev/why.
Packages
Install @loomfsm/pipeline — the meta-package that pulls the runtime (kernel, loader, driver, daemon, server, dashboard, mcp-server, cli, the code bundle, and the zero-config provider). The anthropic-sdk / openrouter / ollama providers install on demand, so the base stays lean.
packages/
kernel/ generic FSM, invariants, ledger, gate-policy, types — no vendor names
config/ configure-once control layer — keys, per-agent model map, project catalog
loader/ build-time assembly of the bundle / provider / extension registry
driver/ orchestration runtime — drive() l
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [teaarte](https://github.com/teaarte)
- **Source:** [teaarte/loom](https://github.com/teaarte/loom)
- **License:** Apache-2.0
- **Homepage:** https://loomfsm.dev
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.