{"id":"4fe5f9f6-c931-4e5a-ac2e-72fa456c6f96","slug":"lasermemory","kind":"mcp","name":"lasermemory","summary":"Point it at a page, a PDF or text: a laser eye reads it, a keeper decides what is worth remembering — and shows you why. A memory agent for agents, classrooms and research.","owner":"chadhurley25075-png","repoUrl":"https://github.com/chadhurley25075-png/lasermemory","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":5,"match":null,"fewStars":false,"format":"mcp","createdAt":"2026-10-03T18:56:32.000Z","addedAt":"2026-10-21T09:47:59.287Z","logoUrl":"https://avatars.githubusercontent.com/u/325742731?u=1dfff72c2aa65c4df2f8a3a0381297898802f016&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["memory-knowledge","files-documents","search"],"tags":["knowledge-base","llm","local-first","memory","obsidian","rag","wiki","agents"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-21T09:48:18.100Z","sample":false,"url":"https://conduits.dev/tools/lasermemory","language":"Python","transports":["stdio"],"install":{"pypi":"lasermemory"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<p align=\"center\"><img src=\"docs/assets/lasermemory-banner.png\" alt=\"LaserMemory\" width=\"760\"></p>\n\n<h1 align=\"center\">LaserMemory</h1>\n<p align=\"center\"><b>Point it at anything. Watch it read. It keeps what matters — and writes its own wiki.</b></p>\n<p align=\"center\">\n<img alt=\"license\" src=\"https://img.shields.io/badge/license-Apache--2.0-blue\">\n<img alt=\"python\" src=\"https://img.shields.io/badge/python-3.10%20%E2%80%93%203.14-informational\">\n<img alt=\"platforms\" src=\"https://img.shields.io/badge/runs%20on-Linux%20%C2%B7%20macOS%20%C2%B7%20Docker-success\">\n<img alt=\"gpu\" src=\"https://img.shields.io/badge/GPU-optional-brightgreen\">\n<img alt=\"mcp\" src=\"https://img.shields.io/badge/agents-HTTP%20%C2%B7%20MCP-purple\">\n</p>\n\nLaserMemory is a **memory system you can watch**. Give it a web page, a PDF, a Word, PowerPoint or Excel file, a CSV,\nMarkdown, HTML, plain text, or a photo of a page. A laser eye reads it passage by passage, and a small local *keeper*\nmodel decides — live, with a real probability — what is worth remembering. Kept passages become short facts that are\nchecked against their source. The facts grow into a searchable memory **and a wiki that links itself**, and any\nagent can use both over HTTP or MCP.\n\n<p align=\"center\"><img src=\"docs/assets/lasermemory-reading.png\" alt=\"Step mode: the eye stops on a passage it kept, and the Learn tab shows why\" width=\"880\"></p>\n\n**Built for three kinds of people:** teachers who want to *show* how an AI memory works, students and researchers who\nwant to *collect and study* what a memory agent keeps and why, and anyone who wants a private, searchable library of\nwhat they read.\n\n## What it does\n\n- **Reads anything.** Web pages through a real headless browser; PDFs with their tables; Office documents; CSV,\n  JSON, Markdown, text; scans and photos through OCR. Any public URL, any upload, or pasted text.\n- **Decides what to keep — visibly.** The eye fires its laser at each passage and sweeps it while the keeper decides.\n  Kept passages flash green with their probability; reference lists are filed as citations, not knowledge.\n- **Stores facts, not paraphrase.** A distilled fact must use only numbers and names found in its passage, and the\n  keeper confirms the passage states it. Table rows are kept word for word. Every memory keeps its source, page and\n  passage.\n- **Grows without noise.** Re-reading strengthens a fact instead of duplicating it; look-alike facts with different\n  figures stay apart; related facts link to each other.\n- **Writes its own wiki.** Every fact files itself onto pages for its source, its topics and the names it mentions.\n  Pages link to each other through `[[wiki links]]` and shared facts, update the moment new data arrives, accept\n  notes, and export as an Obsidian vault. → [docs/WIKI.md](docs/WIKI.md)\n- **Finds the answer.** Hybrid search (meaning + words) with a reranker; every result cites its source.\n- **Runs anywhere.** No GPU? It still works. A laptop GPU, a gaming card, a Mac, a server — `lasermemory setup`\n  detects the hardware and configures the right models. → [docs/MODELS.md](docs/MODELS.md)\n- **Agent-ready.** HTTP API, an MCP server (14 tools), an `llms.txt` guide, a CLI, JSON / Markdown / wiki export.\n\n- **A desktop wiki app.** `lasermemory desktop` opens it like Obsidian: page reader, local graph, backlinks,\n  quick switcher, and a global graph where the eye fires at whatever you point to. It starts by laser-engraving\n  its name and your wiki's numbers.\n\n<p align=\"center\"><img src=\"docs/assets/lasermemory-wiki.png\" alt=\"The wiki app: a page, its local graph and backlinks\" width=\"880\"></p>\n<p align=\"center\"><img src=\"docs/assets/lasermemory-startup.png\" alt=\"The start-up: the eye engraves the name and your wiki's numbers\" width=\"880\"></p>\n<p align=\"center\"><img src=\"docs/assets/lasermemory-graph.png\" alt=\"The graph view: the eye fires at the page under the cursor\" width=\"880\"></p>\n\n## Teach, study, research\n\n- **Step through every decision.** Turn on **Step** and the laser stops at each passage; the **Learn** tab shows the\n  exact question the keeper was asked, its confidence against the threshold, whether a model or the simple rules\n  decided (with each rule that moved the score), and the facts it wrote down. Click any passage later to see the same.\n- **A dataset of every decision.** Each passage the keeper judges is logged — text, confidence, kept or skipped,\n  method, and the facts it produced — and exports as JSONL/CSV or a zip with a datasheet.\n- **Study what you read.** Fill-in-the-blank flashcards from the facts (Anki or CSV) and a BibTeX entry for every\n  source.\n- **Collects politely.** Honours each site's `robots.txt` by default and reads only the public web.\n\nLesson plans and exercises: [docs/TEACHING.md](docs/TEACHING.md) · the dataset and responsible collection:\n[docs/DATA.md](docs/DATA.md).\n\n<p align=\"center\"><img src=\"docs/assets/lasermemory-learn.png\" alt=\"The Learn tab with no keeper model: the simple rules and how each moved the score\" width=\"880\"></p>\n\n## Quick start\n\n```bash\ngit clone https://github.com/chadhurley25075-png/lasermemory && cd lasermemory\npython3 -m venv .venv && . .venv/bin/activate\npip install \".[cpu]\"\nlasermemory setup            # detects your hardware, installs the browser, writes a config\nlasermemory serve            # open http://127.0.0.1:8140\n```\n\nFrom another terminal, or from an agent:\n\n```bash\nlasermemory add https://en.wikipedia.org/wiki/Tardigrade report.pdf notes.docx -c research\nlasermemory ask \"how long can tardigrades survive without water\" -c research\nlasermemory wiki list -c research\nlasermemory wiki export ./research-vault -c research      # open it in Obsidian\nlasermemory desktop                                       # or open the wiki as a desktop app\n```\n\nDocker (no GPU needed): `docker build -t lasermemory . && docker run -p 127.0.0.1:8140:8140 -v lm:/data lasermemory`\n\n## Which models, on which machine\n\n| Your machine | Tier | Keeper | Search | You need |\n|---|---|---|---|---|\n| Any laptop, no GPU | `cpu` | built-in rules | bge-small + MiniLM reranker on the CPU | nothing else |\n| 4–8 GB GPU, M1/M2 Mac | `small` | Qwen3-4B-Instruct (Ollama) | nomic-embed + CPU reranker | [Ollama](https://ollama.com) |\n| 8–24 GB GPU, 16–32 GB Mac | `medium` | Qwen3-4B-Instruct ×2 | nomic-embed + MiniLM-L12 reranker | Ollama |\n| 24 GB+ GPU, Mac Studio, DGX | `large` | Qwen3-4B-Instruct ×6 | nomic-embed + MiniLM-L12 reranker | Ollama |\n| Your own model servers | `server` | any OpenAI-compatible model | any embedder / reranker | URLs |\n\nAll models are open-weight (Apache-2.0 / MIT) and run locally; nothing leaves your machine unless you point it at a\nhosted API. Why these models, how to swap them, and licenses: [docs/MODELS.md](docs/MODELS.md).\n\n## Measured\n\nEvery answer is checked at three layers (in the source? kept in memory? found by search?) — see [docs/EVAL.md](docs/EVAL.md).\n**Held-out** pages and questions were chosen after all tuning ended; the **main** set is the one the system was tuned on.\n\n| Setup | Held-out: first answer right | Held-out: in top 5 | Main: first | Main: top 5 | Facts supported by their source |\n|---|---|---|---|---|---|\n| `cpu` tier — no GPU, nothing but Python | 60% | 73% | 82% | 100% | — (no keeper model) |\n| `medium` tier — RTX 5080, Qwen3-4B keeper, CPU reranker | 73% | 87% | 78% | 98% | 100% / 99% of 120 judged |\n| `medium` + a GPU reranker (Qwen3-Reranker-0.6B) | **87%** | **100%** | 86% | 100% | 99% / 100% of 120 judged |\n\nMeasured on the release code (v1.1.0). Every model setup kept 100% of the answers in memory. \"Facts supported\" = an\nindependent, much larger judge model (GLM-5.3-Flash) read 120 sampled facts per run next to the passages they came\nfrom. One held-out answer pattern was widened after a correct answer (\"Edwin P. Hubble\") was graded wrong; every\nrow above was re-run with the corrected pattern.\n\n## Tested on\n\n| # | Machine | OS | Python | Setup | Tests | Main set: first / top 5 | Held-out: first / top 5 | Facts supported |\n|---|---|---|---|---|---|---|---|---|\n| 1 | NVIDIA DGX Spark (GB10) | Linux arm64 | 3.12 | cpu · rules keeper, bge-small + MiniLM-L6 on CPU | 98 passed | 82% / 100% | 60% / 73% | — |\n| 2 | DGX Spark | Linux arm64 | 3.10 | cpu | 98 passed | 86% / 100% | — | — |\n| 3 | DGX Spark, its own GPU | Linux arm64 | 3.11 | small · setup pulled Qwen3-4B into local Ollama | 99 passed | 80% / 100% | — | 100% of 60 |\n| 4 | Desktop PC (RTX 5080 16 GB) | Linux x86-64 | 3.12 | medium · auto-detected · Qwen3-4B + nomic + MiniLM-L12 | 98 passed, 1 skipped | 80% / 96% | 73% / 87% | — |\n| 5 | Desktop PC (RTX 5080) | Linux x86-64 | 3.12 | medium with qwen2.5:7b-instruct as keeper | 97 passed, 1 skipped | 49% / 76% (only 84% of answers kept) | — | — |\n| 6 | Mac Studio (M3 Ultra) | macOS arm64 | 3.14 | cpu | 97 passed, 1 skipped | 82% / 100% | 60% / 73% | — |\n| 7 | Mac Studio → RTX 5080 desktop | macOS arm64 | 3.14 | server · keeper and embedder on another machine's GPU | 98 passed, 1 skipped | 80% / 98% | — | — |\n| 8 | Docker on the DGX Spark | Debian arm64 container | 3.12 | cpu (image default) | smoke + eval | 82% / 100% | — | — |\n| 9 | DGX Spark | Linux arm64 | 3.12 | full test suite 10 times in a row | 10/10 runs green | — | — | — |\n| 10 | DGX Spark → RTX 5080 desktop | Linux arm64 | 3.12 | Qwen3-4B + nomic + Qwen3-Reranker-0.6B GPU | smoke + eval | 86% / 100% | 93% / 100% | 100% of 60 · 100% of 60 |\n\nNotes: the matrix ran on the code as it stood mid-testing; the table above it is the release code. Rounds 4 and 7 are shown on the final defaults — their first runs used bge-reranker-base, which scored ~51% first\nand was replaced (see [MODELS](docs/MODELS.md#choosing-a-reranker--measured)). Round 5 also ran on that earlier\nreranker; it is in the table for its keeper result: `qwen2.5:7b-instruct` kept only 84% of the answers, Qwen3-4B 100%.\nRound 3's first test run failed 3 tests because the suite read the machine's own config file; fixed, re-run shown.\nEvery round: a fresh clone, a fresh virtual environment, `lasermemory setup`, the full test suite, then the eval.\n\n## Use it from an agent\n\n```bash\nclaude mcp add lasermemory -- lasermemory mcp          # Claude Code; see docs/MCP.md for others\n```\n\nTools: `search_memory` · `get_memory` · `recent_memories` · `memory_stats` · `list_collections` · `list_sources` ·\n`ingest_url` · `ingest_file` · `ingest_text` · `remember_note` · `forget_memory` · `wiki_pages` · `wiki_page` · `wiki_add`.\nAgents without MCP read `/llms.txt`.\n\n## Documentation\n\n| | |\n|---|---|\n| [TEACHING](docs/TEACHING.md) | lesson plans, exercises, classroom setup |\n| [DATA](docs/DATA.md) | the decision dataset, exports, responsible collection |\n| [INSTALL](docs/INSTALL.md) | venv, pipx, Docker, systemd, tiers, tests |\n| [MODELS](docs/MODELS.md) | which models, why, tiers, swapping, licenses |\n| [WIKI](docs/WIKI.md) | how the wiki writes and links itself |\n| [CONFIG](docs/CONFIG.md) | config file and every setting |\n| [OUTPUTS](docs/OUTPUTS.md) | where everything is written; the life of one ingest |\n| [API](docs/API.md) · [`/llms.txt`](lasermemory/static/llms.txt) | HTTP API and live events |\n| [MCP](docs/MCP.md) | Claude Code, Claude Desktop, Cursor |\n| [ARCHITECTURE](docs/ARCHITECTURE.md) | how it works and why |\n| [EVAL](docs/EVAL.md) | how retrieval was measured |\n\n## Security\n\n- Listens on `127.0.0.1` by default; set `api_key` or `allow_nets` before binding a public address. With a key set,\n  open the reader or wiki app once as `…/?key=<your key>` (or type it when asked); the browser remembers it.\n- Reads only the public web: the browser's sole route out is a built-in proxy that checks every connection —\n  redirects included — and refuses private, loopback, link-local, carrier-grade NAT and local names.\n- Documents are processed locally; text goes only to the model endpoints you configure.\n\n## License\n\nRelease notes: [CHANGELOG.md](CHANGELOG.md).\n\nApache License 2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE). Copyright 2026 Chad Hurley.\nEvery runtime dependency is under a permissive licence (PDFs are read with pdfplumber, MIT, and pypdfium2,\nApache-2.0 / BSD-3-Clause); see [docs/MODELS.md](docs/MODELS.md#third-party-software-and-licenses).\n"}