Build Recall
KINDAreplaces $10/mosaves $120/yrback to the verdict
A personal knowledge tool that summarises sources and connects them automatically, where the whole difficulty is that automatic linking produces mostly noise, and a graph where everything connects to everything is the same as a graph with no links at all.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the local application and the extraction pipeline.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - installfree, needs memory
Why Reading history and summaries are personal, and entity extraction runs over everything you save.
Get it Any local runner with a model that returns structured output reliably for extraction. open ↗
Verify
Ten extractions return valid structured output with positions - have readyfree
Why Graph density, entity resolution and link quality are all uninteresting below a hundred sources and become the entire problem above two hundred.
Get it Import from wherever you save things now, including the duplicates and the articles about the same topic from different angles.
Verify
Two hundred sources exist with overlapping subject matter - decidefree
Why An unthresholded graph connects everything, and choosing the threshold after seeing the graph means choosing whichever makes it look best.
Get it Decide the minimum link strength and the density above which you consider the graph degraded, before generating any links.
Verify
Both numbers are written down and configured - have readyfree
Why Entity resolution quality is only assessable where you know the right answer, including the cases where two similar names are genuinely different people.
Get it From your sources, list ten entities including two pairs that look similar and are distinct.
Verify
The list exists with the correct merges and non-merges noted
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- sources(id, kind, url, title, text, author, published_at, captured_at) - entities(id, kind, canonical_name, aliases_json, first_seen_source_id) · kind is person, organisation, concept or work - mentions(source_id, entity_id, char_start, char_end, surface_form, confidence) - links(id, from_entity_id, to_entity_id, kind, strength, evidence_source_ids_json, created_at) · kind names the relationship - summaries(source_id, body, cited_spans_json, model, generated_at, validated) - reviews(entity_id, merged_into_id, decided_by, at) · entity merges are decisions and are reversible - A link stores the sources that evidence it, so a connection can be inspected rather than trusted, and a weak link can be found and removed.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DB_PATH | required | ~/.local/share/recall/graph.db | Sources, entities and links. A record of what you have been reading. |
EXTRACTION_MODEL | required | local | Runs over everything you save, so local is the sensible default. |
LINK_STRENGTH_THRESHOLD | required | 0.6 | Below this no link is created. Unthresholded graphs connect everything. |
MAX_ENTITY_DEGREE | required | 200 | An entity connecting to more than this is flagged as a hub rather than accepted. |
AUTO_MERGE_ENTITIES | required | never | Present as a constant. Combining two people is not recoverable. |
PRUNE_AFTER_DAYS | required | 365 | Weak links and orphaned entities are pruned on a policy to keep the graph legible. |
The build, in order
Sources saved whole
What you read is stored as text, not as a link.
Fetching later means a page that changed or vanished.
Files
src/capture.tsA claim's provenance depends on both.
Files
src/extract.tsAny field at capture time is a decision, and decisions end habits.
Files
src/capture.ts
done when · tick each as it passeswatch out- Storing a link and fetching the content when needed means a source that changed or disappeared takes your notes and summaries with it, and the failure appears months later when the reference is most valuable. Extract and store the text at capture.
The same thing named three ways
Entity mentions across sources resolve to one node.
So a link can point at the sentence rather than the document.
Files
src/entities.tsCombining two people is not recoverable from the mentions.
Files
src/merge.tsWith the decision recorded. You will get some wrong.
Files
src/merge.tstests/merge-reversal.test.ts
done when · tick each as it passeswatch out- Merging entities automatically on name similarity combines two different people who share a surname, and afterwards there is no way to separate their mentions because the information about which was which is gone. Propose, require confirmation, and keep merges reversible.
Links that mean something
The graph is sparse enough to be useful.
Co-occurrence alone connects everything to everything.
Files
src/links.tsAn untyped association is barely more useful than none.
Files
src/links.tsRising density is a defect, not coverage.
Files
src/graph-health.ts
done when · tick each as it passeswatch out- Linking every pair of entities that co-occur in any source produces a graph where a common concept connects to everything, and a graph where everything is connected carries exactly as much information as one with no links. Threshold on strength, type the relationship, and treat rising density as a defect rather than as coverage.
Summaries you can check
Every summary line cites the text it came from.
Validated against the stored text, not against the source URL.
Files
src/summarise.tssrc/validate.test.tsA summary with one invented line silently removed is still untrustworthy.
Files
src/summarise.tsYour reading history is a record of what you were thinking about.
Files
src/policy.ts
done when · tick each as it passeswatch out- A summary of a source you have not read is exactly the artefact people quote later without checking, and a model summarising a long article will confidently smooth over a qualification. Require a citation per line, validate that it resolves, and reject the whole summary rather than dropping the offending line.
Finding your way backproduct builder
The graph helps you answer a question rather than looking impressive.
A whole-graph view of thousands of nodes answers nothing.
Files
src/navigate.tsYou remember a phrase, not a heading.
Files
src/search.tsDensity grows and legibility falls without it.
Files
src/prune.ts
done when · tick each as it passeswatch out- A graph visualisation of several thousand nodes looks impressive and answers no question, because at that size nothing is legible and nothing can be traced. Start from an entity and show its immediate neighbourhood, and treat a whole-graph view as a diagnostic rather than as the product.
That is the whole plan for Recall. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Question answering across the library.
- Collaborative or shared graphs.
- Topic modelling as a replacement for entities.
- Importing another knowledge base's link semantics.
- hosted extraction, model routing, browser capture, sync, and knowledge-graph polish
- publisher bypasses
- cross-device mobile capture
- high-quality recommendation graph
- licensed full-text feeds
- Surfacing an old source when a new one connects to it, which is where a graph earns its keep
- Contradiction detection between sources on one entity, which is genuinely useful and hard
- Reading queue ordering by how connected a source is to what you already have
Need the files? The project pack on the verdict page hands your agent the whole brief · more reading.