{"id":"dea390d8-173b-4b13-921d-0db408088f4c","slug":"fransdressler-loom","kind":"mcp","name":"loom","summary":"Self-hosted second-brain agent network over an Obsidian vault — cited RAG, a self-healing builder-inbox loop, and life-domain modules. Claude Code plugin (/loom:* commands) + bundled MCP server.","owner":"FransDressler","repoUrl":"https://github.com/FransDressler/loom","license":"MIT","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-05-28T22:39:58.000Z","addedAt":"2026-10-21T04:37:04.769Z","logoUrl":"https://avatars.githubusercontent.com/u/111640197?u=ba67cf5a7a23e468e7300508977319d371f7fd99&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["search","developer-tools","files-documents"],"tags":["ai-agents","claude-code","knowledge-management","obsidian","rag","second-brain"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-23T02:18:11.833Z","sample":false,"url":"https://conduits.dev/tools/fransdressler-loom","language":"Python","transports":["stdio"],"install":{"pypi":"loom"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Loom\n\n**A self-hosted second-brain agent network over an [Obsidian](https://obsidian.md) vault.**\n\nLoom turns a plain-Markdown vault into a living logbook *and* a message bus for a\nsmall network of agents. It answers questions from your own notes **with\ncitations**, notices when it's *missing* knowledge, and dispatches a second agent\nto close the gap — then keeps the vault tidy, researches topics into linked note\nclusters, and is reachable from iMessage, WhatsApp, Telegram or Discord.\n\n> The vault is the source of truth — no database lock-in, no hidden state. Everything\n> is Markdown you can read, grep, and version yourself. *(You name your own vault — the\n> author's happens to be called ANVIL. Loom configures via `LOOM_*` env vars /\n> `~/.config/loom/settings.json`; legacy `ANVIL_*` vars and `~/.config/loom/` are still\n> read as a fallback, so a pre-rename install keeps working until you run\n> [`migrate-to-loom.sh`](deploy/migrate-to-loom.sh).)*\n\n---\n\n## What makes it different\n\nMost \"AI second brain\" tools do RAG over your notes. Loom does too — but three\nthings set it apart (and, as far as a survey of ~25 comparable projects found, the\n**combination** of all three doesn't exist elsewhere):\n\n1. **Self-healing knowledge — the builder-inbox loop.** When the retrieval agent\n   can't answer from the vault, it doesn't hallucinate. It files a *complaint*\n   (`gap` / `dislike` / `research`) into a queue, and a **second** agent works that\n   queue down — revising or extending the affected notes, escalating to web research\n   on a true source-miss. A recall miss today becomes better notes tomorrow.\n2. **The vault is the bus, not just the store.** Separate processes (chat listeners\n   and background workers) coordinate through an append-only `events.jsonl` feed\n   and claim-by-move queues *inside the vault*. You can read the agent network like a\n   log, replay it, and audit it — there is no opaque message broker.\n3. **One brain, every life-domain, every channel.** Fitness (Oura + Strava → a daily\n   training plan), calendar, kanban, an interactive tutor + a Feynman learning mode,\n   and Anki card generation — all driven from chat (with voice notes), all guarded by a\n   *propose-and-confirm + .trash recovery* safety model.\n\n**Honest positioning:** the individual building blocks — cited RAG, Karpathy-style\n`raw → wiki` notes, deep research with gap-checks, nightly consolidation — are by\nnow table stakes, and several projects do parts of this very well\n(see [How it compares](#how-it-compares)). Loom's novelty is the *builder-inbox loop*\nand the *union* of all of the above in one self-hosted monolith.\n\n---\n\n## Architecture\n\n```\n   iMessage · WhatsApp                ┌──────────────────────────────────┐\n   Telegram · Discord  ──capture──▶   │        Obsidian vault            │\n   (text · voice · PDF · zip)         │   plain Markdown + [[wikilinks]] │ ◀── you, in Obsidian\n                                      │                                  │\n   ┌───────────────┐                  │  knowledge notes  (concept wiki) │\n   │  listener     │ ───────────────▶ │  events.jsonl     ← BUS + logbook│\n   │  (capture)    │                  │  builder-inbox/   ← complaint Q  │\n   └───────────────┘                  │  ops/tasks/       ← kanban       │\n                                      │  .trash/          ← recoverable  │\n   ┌───────────────┐   scope-miss     └──────────────────────────────────┘\n   │ retrieve agent│ ──┐ files a            ▲              ▲\n   │ (cited recall)│   │ complaint          │ revises      │ gardens\n   └───────────────┘   └────────────▶ ┌─────┴───────┐ ┌────┴──────────────┐\n                                      │ builder     │ │ cleaner /         │\n                                      │ agent       │ │ consolidate        │\n                                      │ (fix notes) │ │ (nightly, confirm) │\n                                      └─────────────┘ └────────────────────┘\n```\n\nPowered by the [Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk-python),\ndriven through your Claude Code login — no separate `ANTHROPIC_API_KEY` needed.\n\n---\n\n## Runtime & providers — use Loom without Claude Code\n\nLoom is **Claude-Code-native by default**: the `/loom:*` commands and the agentic\nskills run on your Claude Code login, no API key required. But Loom does **not** ship\nits own multi-provider engine (a Gemini engine was tried and deliberately removed —\nmaintaining a provider matrix in-tree isn't worth it). Instead, the **MCP server is the\nprovider-agnostic contract**: any MCP host can drive Loom — including\n[Hermes Agent](https://github.com/NousResearch/hermes-agent) running Gemini (or any\nother model) with your own API key. Hermes owns the LLM/session control; Loom owns the\nvault.\n\nWhat that means in practice — two tiers of tools:\n\n| Tier | Tools | Needs Claude? | Works from Hermes/Gemini today |\n|------|-------|---------------|--------------------------------|\n| **Provider-free** (pure disk/network) | `complain`, `inbox_status`, `loom_status`, `schema`, `glossary`, `lint` (checks-only), `fitness_overview/week/status/sync/query` | No | ✅ yes, out of the box |\n| **Claude-backed services** (run an internal Claude agent) | `retrieve`, `research`, `digest`, `wiki`, `lint` (agent pass), `normalize`, `clean`, `fitness_plan`, `anki` | Yes (today) | ⚠️ via the portable skill recipe — see below |\n\n**Portable skills.** Each agentic skill is just a *prompt that orchestrates atomic\ntools*, so every one ships as a host-agnostic recipe under [`skills/`](plugin/skills/) that any\nLLM host (Hermes + Gemini, …) can run against Loom's MCP server — no Claude involved:\n\n| Skill | Portable recipe | Atomic deps beyond Read/Write/Glob/Grep |\n|-------|-----------------|------------------------------------------|\n| [`retrieve`](plugin/skills/retrieve/SKILL.md) | cited recall + complaint | `complain` (MCP) |\n| [`builder`](plugin/skills/builder/SKILL.md) | work one complaint, revise notes | queue file-moves (Bash) |\n| [`digest`](plugin/skills/digest/SKILL.md) | rebuild the overview note | — |\n| [`fitness`](plugin/skills/fitness/SKILL.md) | Oura/Strava → daily plan | `fitness_*` read tools (MCP) |\n| [`anki`](plugin/skills/anki/SKILL.md) | notes → cards → Anki | AnkiConnect (plain HTTP/curl) |\n| [`cleaner`](plugin/skills/cleaner/SKILL.md) | declutter → `.trash` (confirm) | `lint` checks (MCP) |\n| [`wiki`](plugin/skills/wiki/SKILL.md) | source notes → concept wiki | — (sequential, not parallel) |\n| [`deep-research`](plugin/skills/deep-research/SKILL.md) | topic → linked cluster | host WebSearch/WebFetch; Mathpix OCR |\n| [`ingest`](plugin/skills/ingest/SKILL.md) | drop folder → vault | Mathpix OCR (HTTP/curl or `loom-ingest`) |\n| [`checkpoint`](plugin/skills/checkpoint/SKILL.md) | discussion → checkpoint + wiki | the `wiki` skill/tool (MCP/CLI) |\n\nThe Claude-Code build accelerates the heavy ones (`wiki`, `deep-research`, `ingest`)\nwith Python-parallel multi-agent fan-out; the portable recipes do the same work\nsequentially in one host LLM. See\n[docs/hermes-integration.md](docs/hermes-integration.md) for the wiring.\n\n---\n\n## Quickstart\n\n```bash\ngit clone https://github.com/FransDressler/loom\ncd loom\n./install.sh            # interactive: deps + extraction backend + provider + keys\n```\n\n`install.sh` runs `uv sync`, then asks the choices that branch the system — document\nextraction (**Mathpix** OCR vs. local **markitdown**), LLM provider (**Claude Code** vs.\n**Hermes**), your vault path, and any API keys — and writes them all into a single\n`~/.config/loom/settings.json` (chmod 600). Re-run it any time; your current choices\nbecome the defaults. Then:\n\n```bash\nloom# interactive REPL\nloom \"deepfakes are…\"      # one-shot capture\nloom \"what did I note on adiabatic QC?\"   # one-shot recall\n```\n\nIn the REPL: type a thought to capture, a question to recall, `/research <topic>`\nto build a cluster, `/exit` to quit.\n\n**Configuration** lives in `~/.config/loom/settings.json` (see\n[`deploy/settings.example.json`](deploy/settings.example.json)) — friendly fields\n(`vault`, `extraction`, `provider`, `mathpix`) plus an `env`/`secrets` escape hatch for\nany raw `LOOM_*` override. The legacy `~/.config/loom/env` file\n([`deploy/loom.env.example`](deploy/loom.env.example)) is still read as a fallback; a\nreal environment variable always wins. Every feature below is off until you enable it.\n\n### In Claude Code (plugin + MCP server)\n\nThe repo doubles as a Claude Code plugin named `loom`. Install it straight from\nGitHub — no clone needed:\n\n```bash\nclaude plugin marketplace add FransDressler/loom\nclaude plugin install loom@loom\n```\n\n(Working in a local checkout instead? `claude plugin marketplace add .` registers the\nclone you're in.) …then call `/loom:retrieve`, `/loom:deep-research`, `/loom:fitness`,\n`/loom:anki`, etc. The most reliable way to get the tools regardless of install path is\nto register the bundled MCP server explicitly against your local checkout:\n\n```bash\nclaude mcp add -s user loom -- uv run --directory /path/to/loom loom-mcp\n```\n\nDetails in [docs/claude-code-plugin.md](docs/claude-code-plugin.md).\n\n### In the Claude desktop app (claude.ai)\n\nThe native desktop app has no plugins or `/loom:*` commands, but it can load Loom's\nbundled **MCP server** (giving you the `mcp__loom__*` tools) and its **skills**. See\n[docs/claude-desktop.md](docs/claude-desktop.md) for the `claude_desktop_config.json`\nsnippet and requirements — the server runs locally over stdio, so the app must be on\nthe same machine as the repo and vault. (The desktop app is macOS/Windows only; on\nLinux, use Claude Code above.)\n\n---\n\n## How it compares\n\nLoom is not the first AI second brain. The closest relatives — and where Loom\ndiffers — honestly:\n\n| Project | Strongest at | Doesn't have (vs Loom) |\n|---|---|---|\n| [**Khoj**](https://github.com/khoj-ai/khoj) (~35k★) | the most mature integrated self-hosted product: cited RAG, scheduler, WhatsApp + Obsidian + Telegram | own DB instead of a vault-bus; no builder-inbox loop; no life-domain modules |\n| [**claude-obsidian**](https://github.com/AgriciDaniel/claude-obsidian) (~7k★) | same `raw → wiki` architecture, hybrid adaptive retrieval, `/autoresearch` | explicitly *not* an agent bus; no scheduler; no complaint-queue loop; no chat front-end |\n| [**obsidian-second-brain**](https://github.com/eugeniughelbur/obsidian-second-brain) (~2.5k★) | Karpathy LLM-wiki, gap-check-before-research, nightly agents, 4-CLI | a cross-CLI skill, not a resident agent network; no message bus; no chat/voice; no life-domains |\n| [**Hermes**](https://github.com/NousResearch/hermes-agent) | the richest messaging/autonomy layer (20+ channels, built-in cron) — Loom ports `doctor`/`jobs`/`redact` from it | no Obsidian-vault-as-bus; no cited retrieval agent; no builder loop; no `raw → wiki` |\n\nIf you want a polished turnkey product, Khoj is further along. Loom is for people\nwho want the vault to be the substrate, the agents to be inspectable Markdown\nprocesses, and the knowledge base to repair itself.\n\n---\n\n## Feature reference\n\n### Research / build mode\n\nResearches a topic across the web (and PDFs), then writes a **Hub note (Map of\nContent)** plus linked **sub-notes** — with embedded figures, `## Sources` sections,\nand `[[wikilinks]]` into your existing notes.\n\n```bash\nloom research \"Adiabatic quantum computing for portfolio optimization\"\nloom research \"Mamba state-space models\" --source ~/papers/mamba.pdf \\\n                                           --source https://arxiv.org/pdf/2312.00752.pdf\n```\n\nThe agent discovers relevant PDFs itself and can also take `--source` files/URLs.\nEach is run through **Mathpix OCR**; figures inside PDFs are downloaded into the\nvault and captioned. Without Mathpix credentials, research still runs text-only.\n\n| Variable | Purpose |\n|---|---|\n| `LOOM_MATHPIX_APP_ID` / `_APP_KEY` | Mathpix Convert API credentials (enables PDF/image OCR) |\n| `LOOM_RESEARCH_MODEL` | Model for the research agent (default: account default) |\n| `LOOM_RESEARCH_MAX_TURNS` | Turn budget per research run (default: 80) |\n| `LOOM_RESEARCH_MAX_PDFS` | Cap on documents OCR'd per run (default: 10) |\n\n### Graft a missing concept (targeted gap-fill)\n\n`/loom:graft` is the **surgical counterpart to deep-research**: instead of building a\nwhole new cluster, you name ONE thing that's missing — an equation, a diagram, a concept —\nand it pulls that single source from the web **with its real figures**, OCRs the diagrams'\nmath via Mathpix, files it into the **existing cluster it belongs to** (asking you when the\ntarget is ambiguous), and runs the wiki builder to weave in the links and embed the\ndiagram. Use it when a cluster is *almost* complete and you just want to fill a hole.\n\n```bash\n# usually driven by the /loom:graft skill, which picks sources + cluster and then calls:\nloom graft --url \"https://de.wikipedia.org/wiki/Arrhenius-Gleichung\" \\\n           --into \"wissen/werkstoffkunde\" --title \"Arrhenius-Gleichung\"\nloom graft --url \".../skript.pdf\" --into \"wissen/werkstoffkunde\" --kind pdf\n```\n\n`loom graft` is the deterministic half — it reuses the deep-research fetch/OCR/figure\npipeline to write `<cluster>/raw/<slug>.quelle.md` (real figures localized into\n`attachments/`, math-bearing diagrams Mathpix-OCR'd inline). The `/loom:graft` skill then\nwrites the source note in its own words and delegates the concept notes + Hub to\n`/loom:wiki`. Narrow by design (1–3 sources); a broad topic is deep-research's job.\n\n### Adaptive retrieval + builder-inbox\n\nA dedicated **retrieval agent** answers a question by deciding how many notes\n(breadth) and how many linked notes (depth) to pull in *itself*, builds the\ncontext, and cites what it used. When the vault falls short it doesn't guess — it\nfiles a **complaint** into the builder-inbox. A **builder** later works that queue\ndown, revising/extending the affected notes; on a true source-miss it can escalate\nto research. See [docs/retrieval-rework.md](docs/retrieval-rework.md).\n\n```bash\nloom retrieve \"How do I encode TSP as a Hamiltonian?\"   # adaptive recall + cite\nloom complain \"QAOA note doesn't explain the mixer\" --kind gap --target AQC/QAOA.md\nloom builder            # work the complaint queue down once\nloom builder --watch    # keep polling builder-inbox/todo/ every ~10s\n```\n\nComplaints are `.md` files in `builder-inbox/todo/` → `done/` (claim-by-move, so a\npoll never double-processes one). Both the retrieval agent and you file them.\n\n| Variable | Purpose |\n|---|---|\n| `LOOM_RETRIEVE_MODEL` | Model for the retrieval + builder agents |\n| `LOOM_BUILDER_INBOX_DIR` | Vault folder for the complaint queue (default: `builder-inbox`) |\n| `LOOM_BUILDER_ALLOW_RESEARCH` | Let the builder escalate a source-miss to research (default: off) |\n\nThe bundled MCP server exposes `retrieve`, `complain`/`inbox_status`, `research`,\n`wiki`, the maintenance passes (`sync`/`digest`/`lint`/`normalize`/`glossary`/`schema`),\n`clean_preview`, the `fitness_*` data tools, and the `anki_*` tools — so the whole\nvault is drivable from a Claude Code conversation.\n\n### Anki flashcards from your vault\n\n`/loom:anki` (or `loom-anki`) generates atomic spaced-repetition cards **from your\nown knowledge notes** on a topic and pushes them into the running Anki desktop app\nvia [AnkiConnect](https://foosoft.net/projects/anki-connect/) (add-on code\n`2055492159`), then triggers the AnkiWeb sync. Pushing is *additive* — duplicates\nare skipped, so re-running a topic never spams.\n\n```bash\nloom-anki --status                     # is AnkiConnect reachable? decks?\nloom-anki --generate \"Scoliosis training\" --deck \"Med::Scoliosis\"\nloom-anki --generate \"Topic\" --no-push  # dry run: print the cards as a table\n```\n\n### Tutor mode (interactive)\n\n`/loom:tutor` (or the `tutor` MCP tool) is an interactive one-on-one tutor over **one\nsubject cluster** of your vault. Where retrieval *answers* and Feynman mode *examines*,\nthe tutor **leads** the lesson with real pedagogy — Socratic guidance, scaffolding in\nthe zone of proximal development, worked→faded examples, active recall, a hint ladder,\nand immediate feedback grounded in the cluster's notes and cited as `[[note]]`. It is\nread-only on the vault except for one per-subject **learner-model** note\n(`lernsessions/Lernstand — <subject>.md`) it maintains itself, so every fresh session\nopens at your current edge and revisits old weak spots.\n\nYou talk to it turn by turn from Claude Code: each call is one turn of a persistent,\nresumable session (memory survives across turns and even a server restart, within\n`LOOM_TUTOR_SESSION_GAP_H`, default 8 h). Every session is written up as a chat protocol\n`lernsessions/tutor-<subject>-<date>.md`. At session end it points you to its sibling\nmodes — a **Feynman** explain-back to consolidate a gap, **Anki** cards for retention —\nwithout doing their work. It never edits your knowledge notes.\n\n```\n/loom:tutor AQC | Ich will Adiabatensatz und Verschränkung verstehen\n```\n\n### Checkpoint & resume (discussion → wiki)\n\n`/loom:checkpoint` closes the loop between a *throwaway chat* and the *durable vault*.\nAfter a long session on a topic — a `/loom:deep-research` run plus the follow-up\nback-and-forth where the real understanding actually forms — it does two things at once:\nit **checkpoints** the discussion (a re-entry note under `diskussionen/` with the current\nstate, the open threads, the decisions, and a cold-start prompt to pick up later), and it\n**lifts the knowledge into the wiki** (it distils the discussion into source note(s) in a\n`wissen/<slug>/` cluster, then hands off to the existing `wiki` pipeline to build the\nconcept notes + Hub — no wiki logic duplicated).\n\nUnlike `retrieve`/`tutor`/`wiki`, which run as isolated agents over vault *files*, this one\nruns **in the main session** — its input is the live conversation only the host can see, so\nit has no `mcp__loom__*` tool and *is* the slash command. Come back any time with\n`--resume`, which reloads the checkpoint note plus its linked Hub/concepts and continues the\ndiscussion where you left it.\n\n```\n/loom:checkpoint deepfakes            # capture: checkpoint + build the wiki\n/loom:checkpoint --resume deepfakes   # later: reload and pick the discussion back up\n```\n\n### Dynamic context management\n\nThe vault is long-term memory; every session is a disposable working window. Three\nindependently-flagged pieces (all **off by default** — see `deploy/loom.env.example`):\n\n1. **Memory surfaces** (`LOOM_MEMORY_NOTES`): two budgeted vault notes (profile +\n   current projects) are injected into every agent prompt, so a fresh session starts warm.\n2. **Per-turn context hint** (`LOOM_CONTEXT_HINT`): a deterministic UserPromptSubmit\n   hook (no LLM, <1 s, fail-open) injects the last `retrieve` topic + matching note\n   titles, so the agent notices a topic shift and re-retrieves instead of reasoning on\n   stale context.\n3. **Sleep-time consolidation** (`LOOM_CLEANER_CONSOLIDATE`): a daily pass that\n   distills active chats into episode notes *before* they fall out of the rolling\n   window, folds durable facts into the memory surfaces, and updates checkpoints.\n   Dry-run by default; optional retention moves idle chat windows to a recoverable trash.\n\n### loom doctor / status\n\n`loom doctor` is the self-diagnosis for the whole flag-and-service zoo (structure\nadapted from [hermes-agent](https://github.com/NousResearch/hermes-agent), MIT): a\ndeclarative FEATURES table binds every feature group to its prerequisites, plus\nparallel channel-connectivity probes, systemd unit/timer checks, queue-backlog\nchecks, and memory-surface budgets. `--fix` repairs only a non-destructive list\n(mkdir, `chmod 600` the env file, install unit files) — it never deletes or touches\nuser data. **Secrets never appear**: config details only say \"set/empty\", and the\nwhole report passes through `redact_text` as a final choke point. `loom status`\nis the quick read-only snapshot, also exposed as the `loom_status` MCP tool.\n\n### Scheduled prompts (loom-jobs)\n\n`LOOM_JOBS=1` (off by default) lets the chat agent schedule one-shot or recurring\nprompts — \"remind me every morning at 7:30 about X\" — from WhatsApp/Telegram/iMessage.\nA tiny, strict schedule DSL (`once 2026-06-12 09:00` · `every 30m` · `daily 07:30`),\none JSON file per job under `~/.local/state/loom/jobs/` with at-most-once semantics,\ndelivery back to the originating chat. (Port of the slimmed core of hermes-agent's cron.)\n\n### Calendar, Kanban, Day plan\n\n- **Calendar** (`LOOM_CALENDAR=1`): reads Google Calendar (REST v3, OAuth) and iCloud\n  via public ICS feeds into a local `calendar.db`, turned into a shared workload picture\n  (busy hours, free blocks, exam countdowns). With `LOOM_CALENDAR_WRITE=1` Loom can\n  *propose* study blocks — every write goes through the confirm queue, only into a\n  dedicated calendar, only on events carrying Loom's own signature.\n- **Kanban** (`LOOM_KANBAN=1`): tasks are plain vault notes in\n  `ops/tasks/{todo,working,done}/`, visible in Obsidian and driven from chat via\n  `task_add`/`task_list`/`task_move`.\n- **Day plan** (`LOOM_DAYPLAN=1`): a morning timer builds one executable daily schedule\n  from calendar + training plan + top tasks + weekly budgets, as a check-off note plus a\n  short push. Every source is optional — the plan degrades instead of failing.\n\n### Messaging inboxes\n\nOne shared listener engine runs the whole capture pipeline; each service is a thin\ntransport adapter, so iMessage, WhatsApp, Telegram and Discord behave identically.\nEach has `--check`, `--list-chats` and `--poll` (run on a systemd timer, see `deploy/`):\n\n- `loom-imessage` — via a [BlueBubbles](https://bluebubbles.app) relay on a Mac.\n- `loom-whatsapp` — via a [WAHA](https://waha.devlike.pro) relay (WhatsApp HTTP API in\n  Docker, linked by QR — **no Meta Business account needed**).\n- `loom-telegram` — the lightest: a Bot HTTP API bot (no relay/container).\n- `loom-discord` — a bot polled over the REST API (no gateway).\n\nAll four capture **anything you send**:\n\n- **Photos & PDFs** → Mathpix OCR (stored + embedded; stored as-is if Mathpix is off).\n- **Voice notes** → transcoded (ffmpeg) and transcribed; audio + transcript both kept.\n- **Files** (docx, pptx, xlsx, csv, EPub, …) → Markdown via MarkItDown; unreadable types\n  are still stored, never dropped.\n- **`.zip` archives** → unpacked; each file filed individually (path-traversal and\n  zip-bomb hardened).\n- A rolling **chat history** is fed as context, so you can carry a topic across messages.\n- The agent can **send a vault file back** into the chat on request (sandboxed to the vault).\n- Heavy flows (deep research, ingest) are **queued** for the task worker so the chat never\n  blocks; long jobs post progress one-liners back into the chat.\n\n> ⚠️ **Remote-code-execution flags** (both off by default, enable only for a chat **you**\n> control): `LOOM_CODE_SESSIONS` hands classified coding tasks to a headless\n> `claude -p --dangerously-skip-permissions` run; `LOOM_FULL_AGENT` gives the chat agent\n> itself the full tool set including Bash on every message. Treat both as unrestricted RCE.\n\n### More entry points\n\n- `loom-ingest` — a document drop folder; `--watch` runs each settled file through the\n  deep-research pipeline with the files *as* the sources (no web).\n- `loom-feynman` — Feynman learning mode: record yourself explaining a subject; an\n  examiner agent loads the subject's whole vault cluster, corrects you with `[[note]]`\n  citations, and asks exactly one follow-up. Local transcription via faster-whisper\n  (`uv sync --extra feynman`).\n- `loom-fitness` — a daily training coach from your Oura ring + Strava: syncs into a\n  local SQLite store, computes TSS/CTL/ATL/TSB, and a coach agent writes today's plan as\n  a dated vault note. Coaching knowledge ported from the MIT\n  [claude-coach](https://github.com/felixrieseberg/claude-coach).\n- `loom-cleaner` — daily non-destructive gardening; proposes clutter for deletion via\n  chat, confirmed deletions go to `.trash` (recoverable).\n- `loom-tasks` — the skill task-queue worker for the heavy flows the chat agent queues.\n- `loom-mcp` — the stdio MCP server for the Claude Code CLI.\n\n---\n\n## Security & privacy\n\n- **Local-first.** Your notes are plain Markdown on your disk; the vault is the only\n  source of truth. No third-party note service.\n- **Secrets stay out of the repo and out of chat.** Credentials live in\n  `~/.config/loom/env` (outside the repo); `redact.py` masks secrets before any text\n  leaves over a chat channel; `loom doctor` only ever reports \"set/empty\".\n- **Propose-and-confirm.** Outward or irreversible actions (deleting a note, sending mail,\n  creating a calendar event) are queued and confirmed via chat before they run; deletions\n  go to `.trash`, never a hard delete.\n- The RCE flags above are **opt-in** and clearly marked.\n\n## Tests\n\n```bash\nuv run pytest\n```\n\n## License\n\n[MIT](LICENSE) © Frans Dressler. Loom ports patterns from\n[hermes-agent](https://github.com/NousResearch/hermes-agent) and\n[claude-coach](https://github.com/felixrieseberg/claude-coach) (both MIT).\n"}