Your agent's long-term memory for every tool in your stack.
A Claude Code skill that builds a living reference brief for any tool you work with, then keeps it current with cheap delta-checks instead of rebuilds.
Doc tools like Context7 tell your agent how an API works right now. That is one slice. They do not carry pricing, plans, status, changelog-as-news, the service's own list of integrations and actors, the version pins that bite you, or the gotchas people only learn in production. And they forget everything the moment the session ends.
living-docs owns that layer. One curated markdown file per tool, on disk, in git, kept
fresh on demand. Build it once; after that it is check-deltas-and-patch, never rebuild.
you: /docs supabase
first run ── fetch docs, pricing, changelog,
limits, gotchas, community → brief.md
→ sources.yaml
you (three weeks later): /docs refresh supabase
later runs ── poll cheap change-detectors,
re-fetch only what actually moved
Two ideas do the work.
Curate, do not dump. The brief is a condensed, opinionated guide, the mental model plus
recipes, gotchas, pricing, and real limits, not a raw docs dump. Raw material lives in
full/ and is never loaded wholesale. A curated guide beats raw-docs-in-a-tool and costs a
fraction of the context.
Build once, then patch. Every stale-able fact maps to a sources.yaml entry with a
cheap change_detector: an OpenAPI version string, an RSS date, a GitHub release tag. A
refresh polls the detectors first and re-fetches only the sections that actually changed.
The first run is the only expensive one.
<library>/<tool>/
brief.md the curated, agent-facing guide you actually read
sources.yaml every stale-able claim → source URL + last_fetched + ttl + change_detector
history.md append-only build/refresh log
full/ raw dumps (llms-full.txt, openapi.json, KB mirror) for drill-down only
A fully worked, public example ships at
examples/apify/brief.md, a brief for the Apify scraping
platform built by this skill. It is the depth bar.
Maintenance has to stay cheap or the library rots. Every layer below costs nothing or runs on a free model, and your main agent is never in the loop.
| Step | Script | Cost |
|---|---|---|
What is stale? last_fetched + ttl_days per section |
stale.py (--lint, --summary) |
free, local |
| What actually moved? GitHub release tag, npm/PyPI version, RSS date, page hash | detect.py |
free, ~10 s for 90 tools |
| Did the facts change? Compare the old section with the re-fetched page | groq_refresh.py |
free: local Ollama first (--provider auto), Groq free tier as fallback |
| Do it unattended every night | refresh_batch.py |
free on your own GPU |
| Tell me what drifted | docs_freshness.py |
free, one ntfy push |
The nightly refresh (refresh_batch.py --max 60 --commit from a systemd or launchd
timer, plus a weekly --all-tools sweep) picks the moved and stale sections of the tools
you actually used recently and re-fetches each. It only auto-applies what it can check
mechanically: a version read straight from a registry (npm, PyPI, GitHub latest release,
WordPress), or a local-model (gpt-oss:20b) edit that changes only numbers on existing
lines, with each new number found on the page next to that line's own words. Everything
else, new bullets or rewritten prose, goes to a _review/ queue for /docs review.
That line was drawn from evidence. The first unattended run let the model apply any patch that passed basic guards; a strict review of its 23 patches found 11 with at least one wrong fact (an old version number picked off PyPI's release list, a canary tag reported as the latest release, shifted changelog dates, invented features). Replayed under the current policy, 21 of those 23 would have been handled deterministically or queued. A small model is a good checker and a poor writer, so it is only allowed to check.
It is also built for pages it does not trust:
- a section is only marked verified if the fetched page contains that section's own distinctive facts (numbers, versions, names), so a bot wall or the wrong page cannot silently "confirm" stale facts;
- patches that add instruction-like text, add a URL found in neither the old section nor the page, drop dates, or change the section length wildly are rejected;
- it only fetches http(s), never shells out with a string, and can yield the GPU to
another resident model (
DOCS_GPU_YIELD_TO); - when a version moves, it lists every other line of the brief that still names the old version, instead of guessing a find-and-replace.
The finding that shaped this: in a blind test, a fresh agent asked an n8n question went
straight to web search, although a curated n8n brief sat on disk. An agent decides from
the skill listing alone, and "use it when the task is about a tool" does not tell it
which tools have briefs. scripts/describe.py writes your tool names into the skill's
when_to_use (most active first, within Claude Code's 1,536-character listing cap). After
that, the same test opened the brief first and answered from it. Run it whenever you add
a tool; the nightly job does too.
Inside a big brief or a 12 MB help-center mirror, agents search instead of loading:
docs-search "webhook retry" --tool n8n (SQLite FTS5 over every brief and raw dump,
incremental, curated briefs ranked above raw dumps) returns the few passages that matter.
scripts/eval.py scores the library against your own ground-truth questions
(<library>/_eval/questions.yaml: question, tool, a live-verified answer, and 1-3
distinctive strings a correct passage must contain). Per question it checks two things,
with no model and in seconds: does search surface a passage with the right answer, and
does the brief hold the true current fact at all. Ground truth goes stale too, so
questions past --max-age days are flagged for re-verification. The nightly refresh
appends the score to its summary. On the author's library the first run scored 12 of 15;
all three misses were "latest version / current price" facts that had drifted, which is
exactly what the refresh exists for.
/docs <tool> build a brief, or open it if it is still fresh
/docs <tool> --deep also mirror the full catalog, OpenAPI, help center, wider community
/docs refresh <tool> re-fetch only the stale or moved sections
/docs search <query> full-text search across all briefs and raw dumps
/docs absorb file facts you flagged in your notes into the right brief
/docs review verify and apply (or discard) changes the nightly job queued
/docs --stale | --lint staleness per section | manifest health
/docs list list all briefs
/docs import <tool> <path> adopt an existing hand-written guide as a managed brief
living-docs ships with reach, a thin router over direct HTTP APIs and tools you
already have. No MCP server processes, no background daemons, nothing resident in RAM. It
is the fetch layer /docs runs on, and it stands alone as a CLI.
reach web <url> clean markdown of any page (JS-rendered), Jina Reader -> local headless Chromium
reach search <query> web search (Exa, then self-hosted SearXNG, then Jina)
reach psearch <query> Perplexity Search API with citations
reach repo-wiki <org/repo> DeepWiki explainer of how a codebase actually works
reach yt <url> YouTube metadata + transcript
reach rss <feed> latest items from a feed
reach repo <org/repo> GitHub metadata + README
reach instagram <user> public Instagram posts (ScrapeCreators, Apify fallback)
reach tiktok <user> public TikTok videos (ScrapeCreators)
reach facebook-page <page> public Facebook page posts (ScrapeCreators)
reach reviews <maps-url> Google Maps reviews (Bright Data, async)
reach reddit <query> public Reddit search through Apify
reach x-public <query> public X search (Apify Actor, no cookies)
reach x-followers <handle> public X audience relations (Apify Actor)
reach x <query> deeper X access through agent-reach and a burner profile
reach linkedin <url> LinkedIn profile, company or posts (HarvestAPI, Apify fallback)
reach doc <file> local Word/PPT/Excel/PDF/EPUB -> markdown, keyless
reach transcribe <audio> audio/video -> text (self-hosted whisper.cpp, Groq fallback)
reach crawl map|site managed JS crawl (Firecrawl) for the hard cases
reach doctor what works right now, with live vendor balances
repo-wiki is worth calling out: it pulls a DeepWiki explainer of a
repository (architecture, data flow, key modules), which beats a bare README when you are
writing accurate gotchas and recipes for a tool. It reads DeepWiki through Jina keylessly,
and falls back to the DeepWiki MCP (which also answers free-form ask_question queries).
The keyless commands (web, repo-wiki, yt, rss, repo) work out of the box. Search
and the crawl paths use optional API keys, kept in ~/.reach/keys.env (gitignored, chmod
600). Every path degrades instead of failing: web goes Jina, then a free local headless
Chromium, then Firecrawl, then curl, and reach prints which backend served it on stderr.
The public X routes run through Apify Actors: keyed API, no cookies, no account
risk. They leave the cookie-backed reach x route intact. Both default to 20
results, accept a bounded REACH_APIFY_LIMIT from 1 to 200, send APIFY_TOKEN
only in an authorization header, and take REACH_X_TWEET_ACTOR /
REACH_X_FOLLOWER_ACTOR so the route is not tied to one Actor vendor.
"Twitter" and "X" are trademarks of X Corp; these routes are not affiliated with or endorsed by X Corp.
Requires Claude Code. From a clone of this repo:
./install.shThat symlinks skills/docs and skills/reach into ~/.claude/skills/ (an existing real
copy is moved to ~/.claude/skills-backup/ first), puts reach and docs-search on your
PATH, and creates ~/.reach/keys.env from the example. The reference library
defaults to ~/docs-reference (override with DOCS_REFERENCE_DIR). Then, in Claude Code:
/docs supabase
Requirements: Python 3.10+ with SQLite FTS5 (standard in most builds). PyYAML is
recommended (pip install pyyaml); without it a small fallback parser is used.
Optional: Ollama with gpt-oss:20b for free local refreshes
(fits a 16 GB GPU). yt-dlp, gh and Playwright for a stronger reach. Any of
EXA_API_KEY, JINA_API_KEY, FIRECRAWL_API_KEY, GROQ_API_KEY (free tier) or
DEEPSEEK_API_KEY in ~/.reach/keys.env. A self-hosted or access-controlled
ntfy for pings: on public ntfy.sh anyone who knows a topic can read it.
- It is a durable, curated, self-refreshing knowledge layer for the tools you use, the parts a docs MCP skips and never remembers.
- It is not a docs MCP replacement. Point-in-time API lookups are what Context7 and
friends are for.
living-docssits next to them and covers the rest. - Secrets are always placeholders. Briefs never contain a real key, and
reachreads keys from a gitignored file, never from a brief or the repo.
skills/docs/references/design-rationale.md
covers why it is built this way: the prior art that got deleted for auto-running every
session, the curate-not-dump evidence, and the freshness model.
MIT. Built with Claude Code.