Epicrisis CompanionNot a medical device

The box of paper in the cupboard, turned into something you can read.

Thirty years of test results, discharge summaries, ultrasound reports — printed by clinics that no longer exist, in countries you no longer live in, in languages your current doctor does not read.

Epicrisis Companion turns that box into an archive on your own computer. Every value exactly as it was printed, in the language it was printed in, next to the reference range printed beside it, one click from the original page.

You run it for yourself, then for your father, then for your grandmother — one instance, one archive per person, and the archives never touch.

Self-hosted MIT No account Runs offline RU · UK · EN · ES · EL

Who it is for

The same program, three different reasons to open it.

For yourself

The appointment is in an hour and the doctor asks how long your haemoglobin has been at that level. Three years — and here are the eleven measurements, in the units each of the three laboratories used.

For your father with type 2 diabetes

Fifteen years of glycated haemoglobin in one line: before it was found, the two years it was bad, the year treatment started, and every year since. The picture no single form contains, and the one every endocrinologist asks for.

For your grandmother

Her archive is small, on paper, in the language of another decade, and nobody but the family will ever type it up. Twenty documents are still twenty documents you can hand over as a chart instead of a plastic bag.

Fifteen years of HbA1c
A father's diabetes, in one line. The shaded band is the reference range printed on each form, held until another form printed a different one. It steps because laboratories differ — not because anything was calculated. The rows below are Russian where his clinic was Russian, and English after he moved.

Every page, in pictures

All of it is the built-in demo: three archives of people who do not exist, drawn as scanned forms in five languages and then transcribed, checked and indexed for real — without a single model call and without anything leaving the machine. Drag the strip, or use the buttons. Click a picture to open it whole.

The charts are careful on purpose

Most of the work in this program is refusing to be helpful.

One test, two units, two charts
One test, two countries, two charts. Creatinine measured in µmol/L in one country and mg/dL in another. Nothing is converted: the moment a number is converted it is no longer the number printed on the page a doctor can ask you to show.
Blood, urine and stool kept apart
Blood, urine and stool are kept apart, by a tab. The same printed word — Protein, Glucose, Leukocytes — is a different measurement in blood and in urine, and a chart that puts them on one line lies quietly for years.

The machine checks itself

Models misread pages. So the archive does not trust its own reading.

The page of what needs checking
Checks that run with no model at all: a stored number that differs from the printed one, a date nobody could make out, a corner nobody could read, and the same blood draw filed three times. Copies come as a group with one already chosen — you change it only if the choice was wrong. Nothing on this page is changed for you.

Five languages, one test

Read and in daily use in Russian, Ukrainian, English, Spanish and Greek — including Greek capitals that lose their accents, headings spaced o u t like this, and tables printed sideways.

A Spanish laboratory form
The same program, a Spanish form: Hemoglobina, Hematíes, mg/dL, and the laboratory's own arrow in the margin.
A Russian laboratory form
And a Russian one: Гемоглобин, Эритроциты, мкмоль/л — the same test as the English form above, kept as one test and never rewritten.
One test, every spelling
Гемоглобін, Гемоглобин, Hemoglobina, Haemoglobin, Αιμοσφαιρίνη are one test. A model proposes the grouping, a second and deliberately different model reads it again, a reference is consulted where that is allowed — and then the person whose archive it is approves it. After that the vocabulary is stable, which is what makes a fifteen-year chart possible at all.

“Couldn't I just upload the files to a chatbot?”

For one page, yes — and it will read it better than any rule. For an archive it is a different job, and the difference is structural rather than a matter of prompting.

A model reading your filesEpicrisis
ScaleThousands of pages do not fit in a context windowRead once, stored, indexed; the whole archive answers in milliseconds
RepeatabilityAsk twice, get two answersThe reading is a file on your disk; tomorrow's answer is today's
ProvenanceA number in a chatEvery value carries its file, page and date, and links to the scan
Your correctionsDie with the conversationStored apart from the model's output, keyed to the printed line, reapplied after every re-read
Catching mistakesYou have to noticeDeterministic checks find them; a second, different model reads again and disagreements are shown
Units and specimensQuietly converted, quietly mergedNever converted; split by unit and by specimen
VocabularyRegrouped differently every timeOne vocabulary, approved once, in five languages
Several peopleOne pileOne archive per person, one index file each, by construction
With no model at allNothing worksSearch, charts, index, checks and the whole dashboard
The model is used for the one thing it is genuinely better at: reading a page. Everything built on top of that reading is ordinary code you can inspect — which is why this archive keeps working when the models change.

Tested on

Two real archives on one machine, kept by the people whose archives they are. Whose they are is nobody's business, and nothing from them appears here: every picture on this page comes from epicrisis demo, which invents its own people.

479
documents
5 355
values, as printed
1989–2026
years covered
5
languages
200+
institutions on the forms
492
approved test groups
292
tests, no network, no model

Your archive stays yours

The whole design assumes the machine is yours and the network is not.

On the machine

  • Self-hosted. Your computer or your own server. No account, no service, no telemetry.
  • The dashboard listens on 127.0.0.1 only. From anywhere else, through an SSH tunnel.
  • Your scans are read-only. Nothing is copied, moved or renamed. Everything derived lives under data/ and can be deleted and rebuilt from scratch.
  • Each person is a separate database. A folder is one owner's; two owners' folders may not contain one another; ids are random, because folder names carry surnames.

Before anything is sent to a model

  • A one-time written consent, on a page that shows you exactly what would be sent. Change the notice and it asks again.
  • Your own key or subscription, one isolated call per document, carrying that document's pages and nothing else.
  • The steps that need no model never ask — inventory, validation, index, search and every chart.

If you let an assistant read it over the network

  • Read-only tools only. Nothing writes, nothing runs, nothing reads a file outside the index.
  • An unguessable secret path. Without it the server answers as though nothing were there.
  • A private tunnel (Tailscale Funnel) that admits only the connector's own network.
  • A six-digit code from your authenticator (RFC 6238). unlock returns a pass good for four hours; every tool refuses without it; lock ends it early. The secret behind that code is generated on your server, read once into your phone, and never travels through a conversation.
  • An access log of time, address, tool name and whether the call was let through — never the secret, never the question, never the answer. A log of a medical archive that holds the questions is a second copy of the archive.
A secret path and a private tunnel say where a request came from and nothing at all about who sent it. The code from a phone is the only part a stranger cannot copy out of an address bar.
Three archives and the network lock
Three archives on one server, each at its own stage of the pipeline, and below them the read-only network tools with the state of the lock that guards them.

Try it without a page of your own

Python 3.14 and uv.

git clone https://github.com/bermana-net/epicrisis && cd epicrisis
uv sync
uv run epicrisis demo --into /tmp/demo        # three invented archives, no model called
uv run epicrisis serve --data-dir /tmp/demo/data

That demo is everything on this page: three lives that never happened — Vera, her father Anders, her grandmother Zoya — drawn as scanned forms in five languages, transcribed, checked and indexed for real, with not one call leaving your machine.

Then, when you are ready:

uv run epicrisis sources add ~/scans --owner "Your name"
uv run epicrisis update          # inventory → classify → extract → validate → index
uv run epicrisis serve

The honest part

Epicrisis is not a medical device. It is not for diagnosis, treatment or any clinical decision. It stores and shows what your documents say; it does not interpret them, does not decide what is normal, and does not advise.

A transcription from a scan can be wrong. That is why every value in this program is one click from the page it came from — and why the page, not the program, is the authority.