Releases: deeplabua/deepdoc
Release list
0.3.0 — 2026-07-26
Release Notes
Added
-
--ocr, an opt-in build feature (#3).deepdoc --ocr scan.pdfrecognizes a scan and
prints Markdown in one command instead of two — for builds that ask for it. It is off by
default and absent from every released binary: the models alone are 12 MB against a 3.8 MB
binary, cargo-dist builds one artifact set for all channels (so "brew with models, crates.io
without" is not expressible), and recognition is probabilistic, which is not something to put
on the default path of a deterministic parser. Two features, so the cost is the one you choose:Feature What it adds ocrRecognition; models come from --ocr-model <dir>orDEEPOCR_MODEL_DIR. No weights, no network stack.ocr-fetch-models…plus downloading them to the user cache on first run — the only build of DeepDoc that touches the network. There is deliberately no
ocr-embed-models.deepocr-corecan compile its weights in, but it
reads them withinclude_bytes!from a directory DeepOCR's own CI populates before building;
the crate published to crates.io does not carry them, so the feature cannot compile for anyone
installing DeepDoc normally. A build flag that only works inside one repository's CI is a trap.Recognition runs entirely in memory: the page becomes a searchable PDF that never reaches the
filesystem, then goes through DeepDoc's ordinary PDF reader, so an OCR'd scan gets the same
reading-order, column and heading handling as any born-digital file. A standalone.png,
.jpgor.tiffalso becomes readable — not a document to DeepDoc, but a page to DeepOCR.--ocris an extra attempt, never a new failure mode: when recognition cannot help, the
original verdict stands, so a batch skips exactly what it skipped before, for the same reason.
It only triggers on a file that yields no text at all, so a mostly-text PDF with one scanned
page inside still extracts what it has and leaves that page alone. -
"ocr": truein the manifest on files whose text was recognized rather than read. Absent on
every other row, so a run without--ocremits exactly the 0.2.0 schema. Deterministically
parsed text and OCR output are not the same evidence — and a chunkhashthat changed because
a page was recognized differently is a different story from one that changed because the parser
improved.
Changed
--ocrnow explains itself in every build. It used to fail with clap's
unexpected argument '--ocr', which is true and useless. The flag is defined everywhere; a
build without the feature rejects it with the feature to install and the two-tool loop that
needs no special build. Same exit code (2).- The dependency-graph promise is now explicitly about the default build. With the
ocr
feature the graph gainsdeepocr-coreand its tree, includingdirs-sys(pure Rust despite the
name —libcandoption-ext, nothing compiled) andhayro, a page rasterizer. Rendering
pages is otherwise deliberately out of scope here; behind an off-by-default flag it is an
intentional exception. The default build is unchanged and still contains no C or-syscrates.
Notes
- Determinism is suspended for pages that go through recognition, and a run using
--ocrsays so
on stderr. Everything else remains byte-for-byte reproducible. - The
ocrfeature needs a newer toolchain than the default build (deepocr-corerequires Rust
1.92; DeepDoc itself still builds on 1.85).
Install deepdoc 0.3.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/deeplabua/deepdoc/releases/download/v0.3.0/deepdoc-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/deeplabua/deepdoc/releases/download/v0.3.0/deepdoc-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install deeplabua/tap/deepdocDownload deepdoc 0.3.0
| File | Platform | Checksum |
|---|---|---|
| deepdoc-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| deepdoc-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| deepdoc-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| deepdoc-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.2.0 — 2026-07-26
Release Notes
Auditable ingestion: a parser upgrade now says which chunks it actually changed, and a batch now
answers "what happened to every file?" in JSON instead of prose on stderr. Both came from
engineers reading the launch write-up (#1, #2).
Added
-
A content hash on every chunk (#1).
--chunk --format jsongives each chunk a
hash: "sha256:<hex>", so re-extracting a corpus after a parser upgrade tells you which chunks
moved and which can keep their embeddings. The hash covers the chunk's heading path and text
together (heading_path.join("\u{1F}") + "\u{1E}" + text, the ASCII unit and record
separators as the boundary): a chunk only contains its own heading when it starts with one, so
for everything else the context lives outsidetext, and re-filing the same sentences under a
new heading — the exact case worth catching — would otherwise hash identically. -
--manifest <path>(#2): one JSON array for the whole run naming, per input, its
status(extracted/skipped/error), thereasonthere is no output (no_text_layer,
unsupported_format,parse_error,io_error), the detectedformat, and theoutputfile
that was actually written. Exit code 4 is a process-level signal, so routing scans to OCR
meant either grepping stderr or hand-rolling a loop over the files — and a hand-rolled loop
re-derives the output names, wherereport.pdfandreport.docxcollapse into one
report.md.outputreports the name the batch really chose (out/report.pdf.md), so the
pipeline never computes it. Inputs that could not even be listed get an entry too. It works
without--recursive(an array of one), is deterministically ordered, and is a report, not a
policy: it changes no exit code and turns no skip into a failure.deepdoc ./corpus --recursive -o out/ --manifest run.json jq -r '.[] | select(.reason=="no_text_layer") | .source' run.json | xargs -n1 deepocr
Changed
- Breaking for
deepdoc-coreusers:Chunkhas a new public field,hash, so code that
builds one with a struct literal (Chunk { text, heading_path, source, byte_range }) no longer
compiles. Addhash: deepdoc_core::chunk::chunk_hash(&heading_path, &text). Reading chunks —
the common case — is unaffected. - The chunk header in
--format md/--format textnow carries a short form of the hash, so
"which chunk is this?" is answerable in every format, not only in JSON:
<!-- chunk 2/5 | Handbook > Payroll | bytes 296-390 | sha256:2b7c1d0f8a3e… -->.
Notes
sha2(RustCrypto) does the hashing: pure Rust, MIT OR Apache-2.0, and already in the graph
behind the PDF reader — the dependency tree gained no new crates, and still contains no C or
-syscrates.
Install deepdoc 0.2.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/deeplabua/deepdoc/releases/download/v0.2.0/deepdoc-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/deeplabua/deepdoc/releases/download/v0.2.0/deepdoc-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install deeplabua/tap/deepdocDownload deepdoc 0.2.0
| File | Platform | Checksum |
|---|---|---|
| deepdoc-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| deepdoc-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| deepdoc-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| deepdoc-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.1.1 — 2026-07-26
Release Notes
Changed
- A document with no extractable text now points at the tool that fixes it. The message used to
say a scan "needs--ocr" — a flag DeepDoc does not have, and rejects with exit 2. It now names
DeepOCR, which writes an invisible text layer over the
page image; the result is born-digital and extracts normally. Exit code 4 is unchanged, so an
ingestion pipeline keeps its routing signal. - The README documents that loop under Scanned documents. OCR stays deliberately outside this
parser: recognition is probabilistic, and mixing it in would cost the determinism DeepDoc is
built on. A--ocrfeature that links DeepOCR's engine in directly remains planned and off by
default, so the released binary stays small and model-free.
Install deepdoc 0.1.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/deeplabua/deepdoc/releases/download/v0.1.1/deepdoc-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/deeplabua/deepdoc/releases/download/v0.1.1/deepdoc-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install deeplabua/tap/deepdocDownload deepdoc 0.1.1
| File | Platform | Checksum |
|---|---|---|
| deepdoc-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| deepdoc-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| deepdoc-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| deepdoc-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
v0.1.0
Install deepdoc 0.1.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/deeplabua/deepdoc/releases/download/v0.1.0/deepdoc-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/deeplabua/deepdoc/releases/download/v0.1.0/deepdoc-installer.ps1 | iex"Install prebuilt binaries via Homebrew
brew install deeplabua/tap/deepdocDownload deepdoc 0.1.0
| File | Platform | Checksum |
|---|---|---|
| deepdoc-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| deepdoc-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| deepdoc-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| deepdoc-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |