An agent runtime built for transparency. All state lives in the filesystem. Everything is observable with standard Unix tools. Nothing is hidden.
Agent frameworks today are opaque. State is buried in memory, hidden behind abstractions, and impossible to inspect without framework-specific tooling. When an agent fails, you get a stack trace at best. You rarely get the full picture of what it was doing, what it knew, and where it went wrong.
They are also heavy. Hundreds of transitive dependencies ship with every install. Each one is an attack surface. For software that has access to your tools, your files, and your APIs, that is a problem.
loom takes a different approach: agents should be transparent, secure, and easy to understand. State is plain files on disk. You can inspect everything with cat, tail, grep, and ls — no special tooling, no dashboards, no SDKs. The dependency tree is kept as small as possible because every package you don't ship is a vulnerability you don't have.
Nothing fancy. Just processes and files.
Every agent has an identity, a status, an inbox, and an outbox — all stored as plain files. You can observe, debug, and understand the entire system with cat, tail, grep, and ls.
- Observable.
tail -f logs/my-agentworks.ls inbox/works.cat statusworks. No proprietary dashboards required. - Minimal dependencies. A small dependency tree means a small attack surface. Every package you don't ship is a vulnerability you don't have.
- Language-agnostic. The filesystem is the interface. Runners, plugins, and tools can be written in any language — Go, Python, Rust, shell scripts — they all just read and write files.
- Crash-resilient. State lives on disk, not in memory. Inbox messages are not lost when a process dies.
- Composable. Works with the Unix tools you already know:
watch,grep,jq,cron. No SDK required.
loom relies on Unix process semantics (POSIX signals, PID-based supervision, file descriptor inheritance). It runs on:
- Linux — x64, arm64
- macOS — x64, arm64
- Windows — via WSL (use the Linux binary inside WSL)
Native Windows is not supported.
- Bun 1.3+
git clone https://github.com/lorenzh/loom
cd loom
bun install
bun run buildLocal development: use
bun run loom <command>instead ofloom <command>when running from the source repo. Theloombinary is only available after installing the published npm package.
loom agent start <name> --model <model> # start agent in foreground (stdin/stdout)
loom agent start <name> --model <model> --detach # start agent in background (supervised)
loom agent ps # list all agents and their status
loom agent stop <name> # stop a running agent
loom agent logs <name> # view agent logs
loom agent logs <name> --follow # stream logs in real time
loom agent logs <name> --lines 50 # show last N log entries
loom send <name> <message> # send a message to an agent's inbox
loom send <name> --stdin # read message body from stdinAgents in foreground mode are Unix filters — stdin in, stdout out. This makes them composable with standard Unix tools:
# Interactive session
loom agent start my-agent --model ollama/qwen3:8b
# One-shot with piped input
echo "summarise this" | loom agent start summarizer --model ollama/qwen3:8b --stdin
# Chain models together
cat report.md | loom agent start summarizer --model ollama/qwen3:8b --stdin \
| loom agent start prioritizer --model ollama/qwen3:32b --stdin --system "prioritize by urgency"loom agent start my-agent --model ollama/qwen3:8b --system "You are a helpful assistant."
loom agent start my-agent --model ollama/qwen3:8b --system-file ./prompts/researcher.mdloom stores all state under $LOOM_HOME (default: ~/.loom):
~/.loom/
agents/
my-agent/
status # idle | running | stopped | dead
pid # current PID (if running)
model # model identifier
inbox/ # incoming .msg files
*.msg # pending messages
.in-progress/ # message being processed
.processed/ # completed messages
.failed/ # messages that errored
outbox/ # outgoing .msg files
logs/ # NDJSON log files (rotated daily)
conversations/ # full conversation history
memory/ # persistent memory files
crashes/ # crash records
Every field is a plain file. Inspect anything with cat:
cat ~/.loom/agents/my-agent/status
ls ~/.loom/agents/my-agent/inbox/
tail -f ~/.loom/agents/my-agent/logs/$(date +%Y-%m-%d).ndjsonloom routes models by prefix:
| Prefix | Provider |
|---|---|
anthropic/ |
Anthropic API |
openai/ |
OpenAI API |
openrouter/ |
OpenRouter |
ollama/ |
Local Ollama instance |
| (bare name) | Ollama (default) |
Providers are auto-discovered from environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY). For Ollama, no key is needed.
The system has three main components:
Runner — one per agent. A self-sufficient OS process that polls its inbox, calls the LLM, writes responses to the outbox, and maintains its own state files. Runners work standalone without a supervisor.
Supervisor — a process manager. Spawns runners in background mode, detects crashes, and restarts with exponential backoff. If the supervisor dies, runners keep running — they lose restart protection but continue processing messages.
Filesystem — the source of truth. All state is plain files. The CLI writes to the filesystem; the supervisor reads it. A SIGHUP signal nudges the supervisor to re-scan immediately.
Each agent has a restart policy: always (default), on-failure, or never. Exponential backoff with jitter prevents runaway restart loops:
delay = min(1s * 2^restartCount, 5m) + jitter(0..500ms)
After 10 failures within one hour, the agent is marked dead and the supervisor stops restarting it.
loom is in active development. Here is what works today and what is still in progress:
| Feature | Status |
|---|---|
loom agent start (foreground) |
✅ Working |
loom agent start --detach (background) |
✅ Working |
loom agent ps |
✅ Working |
loom agent stop |
✅ Working |
loom agent logs / --follow |
✅ Working |
loom send |
✅ Working |
| Anthropic, OpenAI, OpenRouter, Ollama providers | ✅ Working |
| Conversation history | ✅ Working |
| Crash recovery (orphaned message restore) | ✅ Working |
| Supervisor PID management and signal handling | ✅ Working |
Supervisor scan() — agent spawn and crash detection |
🚧 In progress (v0.2) |
| Message routing between agents | 🚧 In progress (v0.2) |
loom.yml parser and weave configuration |
🚧 In progress (v0.2) |
loom up / loom down |
🚧 In progress (v0.2) |
| Pipes and operator chains | 📋 Planned |
Architecture decision records live in docs/adrs/.
| ADR | Title |
|---|---|
| ADR-001 | Unix process model for agents |
| ADR-002 | Filesystem as process table |
| ADR-003 | Inbox watcher via polling |
| ADR-004 | Supervisor and restart policy |
| ADR-005 | Runner architecture |
| ADR-006 | CLI and agent lifecycle |
| ADR-007 | Garbage collection and archival |
| ADR-008 | Ollama model availability |
| ADR-009 | Message origin tracking |
| ADR-010 | Pipe runner — named reusable message processors |
| ADR-011 | loom.yml — declarative weave configuration |
| ADR-012 | Filesystem as state store |
| ADR-013 | Model routing and provider abstraction |
| Proposal | Title |
|---|---|
| plugin-model | Plugin and extension model |
| plugin-protocol | Plugin protocol — tools as executables |
MIT