Verified transcript cache protocol and reference CLI for AI agents.
Project description
Verified Transcript Cache Protocol
Reference implementation: donotreadagain (dnr)
Read once, never again. A small protocol for faithful, signed transcripts of expensive-to-parse source files, so AI agents stop re-OCR/re-parsing the same PDF, image, scan, spreadsheet, or audio every time.
Tell your agent:
Use dnr for this folder.
That one line is the adoption path. The agent fetches SKILL.md, checks cached transcripts before parsing files, and records any expensive read it had to do anyway.
This repo contains the Verified Transcript Cache Protocol, its record
schema and conformance vectors under spec/, and dnr, the reference
CLI implementation. Harnesses can call the CLI today or implement compatible records
natively later.
The problem
AI agents re-parse the same file every time they touch it — re-OCR a scan, re-run vision on a screenshot, re-transcribe an audio clip, re-extract a PDF. It's slow, it burns tokens and model calls, and it's non-deterministic. In repeat-access corpora (legal, research, compliance) the same documents get read dozens of times; with multi-agent setups every agent re-parses independently. The waste compounds exactly where it hurts.
The idea
The protocol defines a cache/trust/index layer for expensive source-file reads. A local
extractor, local ASR model, or the calling AI agent
reads a file once; dnr stores the resulting transcript + structured metadata as a signed JSON
record in a folder .dnr.db by default, so original files stay byte-identical. Any agent that
opens it later reads the cached transcript instead of re-parsing. A per-folder SQLite + FTS5
index makes a whole folder searchable without opening anything. Portable in-file records remain
available with explicit --embed, but file modification is never the default.
The second view is the win:
| first view (re-parse) | second view (cached) | |
|---|---|---|
| born-digital PDF | local text extraction (PyMuPDF→pypdf) | ~60 ms — no PDF parse |
| image / scan / audio | a vision / Whisper model call | a few ms of text — no model at all |
…and the cache is trustworthy: a record is used only if it's signed by a trusted key and its content_hash still matches the file, so "fast" never means "stale or forged."
Protocol contract
For agents and harnesses, the protocol is a small pre-read loop:
- Known file: run
dnr read <file>before parsing it. If stdout has text, use it and do not re-read. - Miss: if the task still needs the file, parse/look/listen once, then cache that result with
dnr ingestordnr record. - Folder question: run
dnr index <folder>, thendnr query <folder> ...before opening files. - Folder preparation: use
dnr status <folder> --pending; rundnr backfill <folder>only when the user wants a folder pass. - Boundary: never bulk-transcribe just because files are pending; only cache work the task actually needs.
Harness maintainers can copy the integration contract and reference adapters from HARNESS.md, or implement the protocol directly from PROTOCOL.md.
Demo
$ dnr ingest contract.pdf # transcribe once → sign → cache in .dnr.db
ingested contract.pdf [db-only (index)]
method=text-extract transcriber=pymupdf
signed key_id=ce6d170a497238f7
$ dnr read contract.pdf # later (or from any agent): verified cache hit — no re-parsing
LOAN AGREEMENT
Lender: Acme Capital LLC
Borrower: Jordan Smith
Principal: USD 1,200,000
...
$ dnr index ./contracts
$ dnr query ./contracts --match damages --context 40 # search a whole folder, no files opened
contract.pdf
… Principal: USD 1,200,000 Maturity: 2026-12-31 Damages clause: section 7.
The transcript lives in the folder's .dnr.db by default, so contract.pdf itself stays untouched.
If you explicitly need the cache to travel inside the file, add --embed.
Quickstart
Recommended install:
pipx install donotreadagain
dnr --version
# one-off/fallback when installing is not available:
uvx --from donotreadagain dnr <cmd>
# audio ASR:
pipx inject donotreadagain faster-whisper # ffmpeg may also be needed for decoding
dnr ingest report.pdf # extract once (local) → sign → store in .dnr.db
dnr backfill ./case-folder # folder pass: local-provider files now, agent/vision worklist after
dnr read report.pdf # print the cached transcript (verified), or fall back
dnr index ./case-folder # build .dnr.db
dnr status ./case-folder --pending # honest usable/pending/repair coverage
dnr query ./case-folder --match "손해배상" --tag 가압류 --since 2025-01-01
For a scan / image / anything you must look at, the agent transcribes it and records the result:
dnr record scan.png --transcript-file t.md --method vision --transcriber <your-model>
How it fits together
File = canonical truth Index .dnr.db = default cache
┌────────────────────────────┐ harvest ┌────────────────────────────┐
│ original file bytes │ ───────▶ │ signed record + FTS5 search │
│ content_hash · transcript │ │ path · tags · transcript … │
│ provenance · fields · sig │ └────────────────────────────┘
└────────────────────────────┘ ▲ query via sqlite3 — dnr CLI optional for reads
▲ transcribe once · sign · store db-only (expensive)
Where the record lives (no sidecar files):
- db-only by default in the folder's
.dnr.db, so original files stay byte-identical. If the source file changes, the stale record is removed and the file must be re-ingested/re-recorded. - Optional in-file with explicit
--embedfor formats with a metadata slot — PDF→XMP, MP3→ID3, M4A/MP4/MOV→MP4 freeform atom, FLAC/OGG/OPUS→Vorbis/Opus comments, PNG→iTXt, JPEG→APP segment. This makes the transcript travel with the file, but it rewrites file bytes and is never the default. - Nothing for already-readable text (
.txt/.md/.csv) — an agent just reads it.
Current format support:
| Format | Transcription | Record storage | Status |
|---|---|---|---|
local text layer (PyMuPDF first, pypdf fallback) or agent vision for scans |
db-only default; optional XMP with --embed |
partial | |
| PNG / JPEG | agent-supplied vision transcript | db-only default; optional PNG iTXt / JPEG APP with --embed |
implemented |
| HEIC / HEIF | agent-supplied vision transcript; optional pillow-heif hash |
db-only | partial |
| MP3 / WAV / M4A / FLAC / OGG / OPUS | local Whisper provider via donotreadagain[audio], if installed |
db-only default; optional in-file for non-WAV carriers with --embed |
partial |
| DOCX | local python-docx text extraction |
db-only | implemented |
| XLSX | local openpyxl sheet extraction |
db-only | implemented |
| MP4 / MOV video | agent-supplied transcript/ASR+vision | db-only default; optional MP4 freeform with --embed |
partial |
| PPTX / other office/media | planned providers or agent-supplied transcript | db-only until carriers land | planned |
Using it
- Read (consumer):
dnr read <file>returns the cached transcript only if it's present, trusted, and still matches (self-validating — a changed file silently misses). No dnr tool? An agent can read.dnr.dbdirectly with ambientsqlite3(the db's_dnr_readmetable self-describes). - Transcribe (producer):
dnr ingest(local: PyMuPDF→pypdf / python-docx / openpyxl / optional faster-whisper) ordnr record(agent supplies a vision/OCR transcript). dnr is an opportunistic cache: do this when the current task already requires reading/parsing that file, not just because a folder has pending files. If a needed file's cached transcript is empty/garbled/unusable, repair that file immediately; ask only before expanding into whole-folder OCR/searchability work. - Backfill a folder:
dnr backfill <folder>(alsodnr ingest <folder>) ingests locally-processable files in one pass, skips already-readable text, and prints a worklist for images/scans/videos or low-quality results that need agent/vision repair. - Query a folder:
dnr query <folder>combines--match(FTS, Korean/CJK ok) ∩--tag a,b∩--since/--until∩ restricted--whereover fixed columns; plus--any(OR sweep),--dedup,--context(KWIC),--format json. Save composed queries with--save/--use; accumulate labels withdnr tag. - Agents onboard locally: point an agent at a dnr folder and it fetches SKILL.md once for that task/folder. Recommended install is
pipx install donotreadagain; one-off fallback isuvx --from donotreadagain dnr ....dnr initjust ensures a signing key by default; to persist the bootstrap in a project instruction file, rundnr init --agent-file AGENTS.md(or--agent-file CLAUDE.md). Harness authors can integrate the same read-through cache hook with HARNESS.md.
Design principles
- Protocol first, CLI as proof. The Verified Transcript Cache Protocol is the portable contract;
dnris the reference implementation that proves it works and gives harnesses an optional hook today. - Original files stay untouched by default. The default write path is
.dnr.db; in-file records require explicit--embed. - Not a general knowledge format. dnr stores faithful transcripts tied to original files. Curated concepts, runbooks, summaries, and knowledge-base pages belong in higher-level docs; dnr can feed those systems, but it is not trying to replace them.
- dnr is the deterministic substrate; the agent is the intelligence. dnr does verifiable primitives (hash, sign, full-text/structured query); it never infers metadata (dates, parties, topics) or does fuzzy semantic search — that's the agent's job. Set metadata explicitly with
dnr tag/dnr date. - File = truth, index = regenerable cache. Delete
.dnr.dband rebuild it from the files anytime. - Transcriber-agnostic. dnr ships a contract (the verbatim guide) + a trust layer, not a model. Fidelity is the transcriber's; provenance is recorded so a consumer can apply its own quality policy (
trusted ≠ faithful).
Status & honest limits
v0.2 early release. Published on PyPI as donotreadagain; the recommended path is pipx install donotreadagain. uvx remains a one-off/fallback path, but it still requires uv and can be slower than a normal install for repeated use. Standalone binaries remain a future packaging option for Python-less environments. Works today for repeat-access corpora; validated by real-corpus dogfooding. Known limits we're explicit about:
- Adoption is the real lever. The value compounds when agents know dnr (a skill, eventually native support) — not from the tool alone.
trusted ≠ faithful. A signature proves who made it + that it matches the file, not that the transcription is accurate. Low-quality/garbled transcripts are flagged (dnr status), not silently trusted.- Coverage is still growing. PDF/PNG/JPEG/HEIC/DOCX/XLSX and common audio containers are useful today; OOXML carriers, more video containers, pre-query auto-scan, and larger-corpus concurrency are still roadmap work.
- Benchmarks are early. The README numbers are illustrative dogfood timings; see BENCHMARKS.md and experiments/content-hash-invariance for the current proof/measurement status. A broader latency/token benchmark remains a release-readiness item.
- Python packaging is the product path. Use
pipxfor the cleanest install;uvxremains the one-off/fallback route.
See PROTOCOL.md (protocol contract) · spec/ (schema and vectors) · HARNESS.md (harness integration) · vision.md (design) · SECURITY.md (threat model) · qna.md (settled design decisions) · MILESTONES.md (roadmap).
Development
git clone https://github.com/melodysdreamj/donotreadagain
cd donotreadagain
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest # the suite is green and fast
Contributions welcome — see CONTRIBUTING.md. Release automation is documented in RELEASING.md.
License
MIT © 2026 june lee
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file donotreadagain-0.2.3.tar.gz.
File metadata
- Download URL: donotreadagain-0.2.3.tar.gz
- Upload date:
- Size: 99.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c90b0ff5db25a987edb84bb21e4cf5f6000779f6829a965da998b174ef5c243
|
|
| MD5 |
214a659e41111ff28a07a7418d358d81
|
|
| BLAKE2b-256 |
fd5d2ed0c9bb2862eaa9ecfa1a2fa47e7c044414c112e410255dbdb353b069d1
|
Provenance
The following attestation bundles were made for donotreadagain-0.2.3.tar.gz:
Publisher:
publish.yml on melodysdreamj/donotreadagain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
donotreadagain-0.2.3.tar.gz -
Subject digest:
7c90b0ff5db25a987edb84bb21e4cf5f6000779f6829a965da998b174ef5c243 - Sigstore transparency entry: 1897603296
- Sigstore integration time:
-
Permalink:
melodysdreamj/donotreadagain@83e041dd40621c588e9b41e9fd3e96d74bb1e9ea -
Branch / Tag:
- Owner: https://github.com/melodysdreamj
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@83e041dd40621c588e9b41e9fd3e96d74bb1e9ea -
Trigger Event:
release
-
Statement type:
File details
Details for the file donotreadagain-0.2.3-py3-none-any.whl.
File metadata
- Download URL: donotreadagain-0.2.3-py3-none-any.whl
- Upload date:
- Size: 50.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
114fc24424ccee5354cbc39721f4080bead343ad802a61d4a661438c113c04d3
|
|
| MD5 |
ca6910b4222b09d6b5121bbafb9784a1
|
|
| BLAKE2b-256 |
c895bf7d45dd21fc0e713185e33c5d76f9ea2a412c7fa4d73b2b03efd6c1bb5a
|
Provenance
The following attestation bundles were made for donotreadagain-0.2.3-py3-none-any.whl:
Publisher:
publish.yml on melodysdreamj/donotreadagain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
donotreadagain-0.2.3-py3-none-any.whl -
Subject digest:
114fc24424ccee5354cbc39721f4080bead343ad802a61d4a661438c113c04d3 - Sigstore transparency entry: 1897603687
- Sigstore integration time:
-
Permalink:
melodysdreamj/donotreadagain@83e041dd40621c588e9b41e9fd3e96d74bb1e9ea -
Branch / Tag:
- Owner: https://github.com/melodysdreamj
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@83e041dd40621c588e9b41e9fd3e96d74bb1e9ea -
Trigger Event:
release
-
Statement type: