Semlith

Changelog

Every release of the open-source semlith binary, newest first: what it changes for you, and the headline of each change, with the full notes on GitHub.

Each release below opens with what it changes for you, then lists the headline of every item. Its full notes, with the reasons and the measurements, are on GitHub, linked under its version.

0.49.0

28 October 2026 · Full notes on GitHub

A machine with no network indexes and searches a folder that holds images, once its model cache is copied from a connected machine. No store format change and no re-index.

Added

  • semlith setup --all-models
  • The Privacy page lists every model weight
  • tests/airgap.sh

Fixed

  • A pictured query no longer fails when CLIP’s text encoder is missing
  • Indexing an image fetches both CLIP encoders
  • A cached rescoring model loads under airgap

0.48.0

27 October 2026 · Full notes on GitHub

docs.rs, crates.io, semlith --help and the README describe Semlith in the same words and link semlith.com. The binary does, sends and stores exactly what 0.47.1 did.

Changed

  • The crate docs open with the repo tagline
  • crates.io links the website
  • The README links the website

0.47.1

25 October 2026 · Full notes on GitHub

Fixed

  • A folder named in a path filter matched nothing

0.47.0

24 October 2026 · Full notes on GitHub

The README and the portal talk about Semlith. The binary does, sends and stores exactly what 0.46.4 did.

Changed

  • The README names Semlith Cloud only as a separate hosted service
  • Settings › Cloud, signed out, states the one sentence on both products
  • The MCP registry entry publishes itself

0.46.4

24 October 2026 · Full notes on GitHub

Docs and metadata only. The binary behaves as 0.46.3.

Changed

  • The README’s first screen is back in the usual order
  • README claims match the code
  • README prose
  • Crate and registry description

0.46.3

24 October 2026 · Full notes on GitHub

Test harness only. The binary behaves as 0.46.2.

Fixed

  • The browser drive no longer fails a release for a request the browser never sent

0.46.2

24 October 2026 · Full notes on GitHub

Metadata only. The binary behaves as 0.46.1.

Added

  • glama.json

0.46.1

24 October 2026 · Full notes on GitHub

Docs, metadata and one workflow. The binary behaves as 0.46.0.

Added

  • Listed in the official MCP registry

Changed

  • The README leads with what semlith changes for an agent
  • Dependencies

Fixed

  • The clean-install workflow’s Windows tamper check works again

0.46.0

24 October 2026 · Full notes on GitHub

The two security audits of 0.45.1 (2026-10-23) found nothing Critical or High. This release closes all eighteen of their findings, or records why one is accepted. Each fix comes with a test that fails on 0.45.1.

Security

  • Only a commit on main can become a signed release (SEC-001)
  • Each release job holds one permission (SEC-007)
  • The installers check who built a release, and refuse an old one (SEC-007, SEC-015)
  • semlith add never fetches through a proxy (SEC-003)
  • semlith upgrade unpacks the bytes it checked (SEC-004, SEC-014)
  • Packs and the embedding model are used as they were checked (SEC-004)
  • On macOS, a native parser cannot grow past its worker’s memory limit
  • Isolation headers (SEC-015)
  • Every lockfile is audited (SEC-010, SEC-011, SEC-013, SEC-016)
  • A secret scan gates every push (SEC-002)

Changed

  • CI decides more carefully what is prose (SEC-005, SEC-006)
  • The bug hunt in native-smoke.yml reads its own budget-capped ANTHROPIC_BUGHUNT_KEY and skips without it

Accepted

  • A process running as you that writes the model cache while the daemon runs could change an unpacked pack’s files, or the model graph ONNX Runtime opens by path, after the check
  • Two expired confidential-VM attestation tokens remain in the history behind the v0.37.0-rc.5 and rc.6 tags, which the tag ruleset keeps immutable

0.45.1

21 October 2026 · Full notes on GitHub

Changed

  • The README and the clients guide say what the binary does

0.45.0

21 October 2026 · Full notes on GitHub

Added

  • Settings › Cloud shows the org’s stores this machine has not connected
  • semlith cloud status says which stores are connected here
  • The Stores page’s Remote stores card

Security

  • rustls-webpki 0.103.16 and webpki-roots 1.0.10

0.44.1

19 October 2026 · Full notes on GitHub

Added

  • The documents benchmark is in the repository
  • The README’s first screen

Fixed

  • A call with no receiver resolves to the function it names, not a tie with a method
  • A method that calls the free function of its own name records the call
  • Two definitions of one name in one file keep their own calls
  • Members and top-level functions are told apart in every language
  • Go methods are qualified by their receiver type
  • A Rust integration test is not a library function
  • A call into the standard library no longer lands on a namesake in your code
  • JavaScript member calls are calls through a receiver
  • A grouped Rust use places what it imports
  • A Rust fn in a module body is a function
  • The extractor changes above take effect as files are re-indexed; the resolver changes answer at once
  • A live Slack token no longer reads as a typed placeholder by chance
  • Portal dialogs scroll instead of clipping

0.44.0

18 October 2026 · Full notes on GitHub

Added

  • Any number of remote workers

Fixed

  • Calls inside Rust macro arguments are calls
  • The CPU-backed worker lane is not refused as a software renderer

Upgrading

  • Library: accel::lane returns an owned Arc<Lane>; accel::Enabled.remote is now remotes (the remote lanes switched on); accel::Switches gains remotes and is no longer Copy

0.43.0

17 October 2026 · Full notes on GitHub

Fixed

  • A printed report keeps every column
  • semlith’s own PDF prints ids and paths whole
  • The change brief finishes
  • A team member’s local use counts in the cloud
  • semlith cloud push says what it leaves out
  • --out takes a folder
  • semlith_files says the total first

Security

  • SK30, DNS rebinding in semlith_add
  • zip 9.0.4

Changed

  • Dependencies: fastembed 7.1.1, serde_json 1.0.154, sha2 0.11.1, tree-sitter 0.27.1 and tree-sitter-erlang 0.21.0

0.42.0

17 October 2026 · Full notes on GitHub

Added

  • Many agents, one consistent store
  • A run is answered from before it until it commits
  • MCP 2026-07-28 clients are named
  • Chain v2
  • The watcher wakes the embedding lanes on the first change

Changed

  • Break, 2026-10-16: the whole-file side of a saving is what reading the file costs
  • One aggregation behind every figure
  • semlith_read, semlith_pattern, semlith_impact and semlith_trace are recorded with what they returned, from MCP, the CLI and the portal; a graph answer is one row, in the store that answered
  • The tool-list cost is one count, bytes over four: the gate in tests/retrieval.rs and the Agents page print the same number
  • Every report looks like Semlith, in every format
  • Break: CSV and JSON are data
  • Break: one default window, and it applies to every figure
  • Break: a schedule replaces one file in place
  • Numbers in reports print 736,397, as the portal does, through one formatter
  • The change brief counts every file it re-read (no per-store cap of 200), does not call a first index a re-read, and carries the blast radius of the changed definitions from the impact walk; paths print relative to the store’s root
  • The Reports page previews the rendered HTML in a sandboxed frame under a report-only policy; Copy stays Markdown
  • semlith_report takes window, scope, redact, excerpts and table
  • The settled share drops, and that is the honest number

Fixed

  • Clocks: a row is printed with the UTC offset in force when it was written, semlith ledger prints the date on rows older than today, and the portal pairs the local date with the local time (an IST row at 03:00 on 10-10 read “10-09 03:00”)
  • A run’s card, history and log events give the work’s own time, not the time the wizard sat on its Review page (41 s of work read “done in 1m 31s”); a time left that had counted down to a second rises again when the rate falls; the CLI prints the last twenty seconds’ chunks/s; a catch-up that found nothing to embed no longer leaves the store’s last run reading “0 / 233 chunks”
  • cloud status and the portal say when the cloud last checked a source (“checked 14 h ago”), floored the same way, never “behind” for an index at the branch head
  • semlith refused --store X lists X only with a daemon running; semlith prices lists its table
  • The portal prints the daemon’s real store home, the Privacy page lists files semlith add fetched, a registration that cannot reach this daemon is not counted as registered, Review lists every dotfile the hidden rule skipped, and an encrypted document or an archive past the 32 MiB budget says so rather than “no text layer”
  • A Neural Engine worker waiting on the Core ML compile lock leaves when the process that started it has gone
  • A Core ML worker removes only earlier protocols’ worker copies, never a later one’s
  • A file whose first 8 KiB is mostly invalid UTF-8 or control characters is refused as binary with the share in its reason (ripgrep’s sherlock.br, a Brotli file with no NUL, became one chunk of U+FFFD)
  • No call edge claims a call that does not exist (G1)
  • Missed callers and mislabelled edges (G2, G3, G8)
  • Python owners and alias spans (G4, G5)
  • Setext Markdown headings (G6)
  • symbol counts and orders (G7, G9, G10, G11)
  • “Called and not found” is code the corpus does not hold
  • Asking for fewer results only cuts the answer (G12)
  • A question about code is answered with code (G13)
  • read prints every line of its range (G14)
  • brief spends its budget in the order its help states and names every drop (G15, G16)
  • Markup is read and searched as written (F13)
  • A local store and its remote mirror answer once (F21)

Security

  • A redacted report’s query digest is keyed with a per-machine salt (~/.semlith/report.salt); the unkeyed digest could be reversed by hashing a corpus’s own symbol names
  • What a code store holds of an HTML file

0.41.0

15 October 2026 · Full notes on GitHub

Security

  • .git and credential folders stay out, wherever they are (S12)
  • Every read of a file’s bytes refuses a link (S13)
  • The session token is never in a log file (S14)
  • Model files are checked before they are loaded (S15)
  • Exports cannot run anything (S16)
  • Paths are quoted for where they are written (S17)
  • One file costs seconds, not CPU-minutes (S18)
  • Developer overrides are not in the release binary (S20)
  • A search can stay on this machine, and the Privacy page says when it does not (S21)
  • add connects to the address it checked (S22)
  • Small surface issues (S23)
  • Store hygiene (S24)
  • SECURITY.md says what is true (S25)
  • The gate that stays (S19)

Fixed

  • Three parser inputs found by the new fuzzers
  • The review list no longer fills with build churn
  • The Linux login service serves
  • Renaming or deleting a store on Windows

0.40.0

15 October 2026 · Full notes on GitHub

Security

  • A file can no longer crash semlith (S01, High)
  • Agent keys are read-only by default (S03)
  • One slow call no longer stalls every agent (S02)
  • read never serves what a link points at (S05, S13)
  • cloud login opens only the host’s own page (S04)
  • A repository’s config runs nothing (S07)
  • llama-server’s key is off the command line (S08)
  • Config rewrites keep modes and links (S09)
  • A refused secret leaves nothing behind (S10)
  • Releases are signed (S06)
  • Idle sockets no longer lock anyone out (S11)
  • cargo audit on every push

Fixed

  • Three index-time races
  • Decisions shows a retried file’s outcome without a reload

0.39.0

13 October 2026 · Full notes on GitHub

Changed

  • A first import commits less (#210)
  • Store format 5: turbovec 1.1 (#219)

Fixed

  • The credential-scan test no longer fails on an unlucky draw (#222)

0.38.1

12 October 2026 · Full notes on GitHub

Fixed

  • A cached vector made on another lane is used

0.38.0

10 October 2026 · Full notes on GitHub

The public scorecard

  • bench/scorecard/ reproduces every published number

Documentation

  • The README and the documentation are rewritten to the point

Fixed

  • A long query no longer puts a screenshot first
  • A file emptied on disk is evicted from the store
  • A scope’s first search no longer pays the whole filter resolution each time the scope changes (#183)
  • A failed accelerator lane is tried again (#188)
  • A live secret that opens on FAKE by chance is no longer a dummy
  • A search hit is named for the definition it is mostly about
  • The run card’s drain line counts down
  • Home tells agents apart from the portal
  • A report saved after midnight is named for the right day
  • semlith accel --help
  • A test no longer deletes the login service

0.37.0

9 October 2026 · Full notes on GitHub

The Semlith Cloud client leaves release candidate. Everything rc.1 to rc.7 carried ships here; the sections below them say what each added. Nothing changes for anybody who never signs in: with no ~/.semlith/cloud.json the binary makes no connection to Semlith Cloud at all.

In this release, from rc.1 to rc.7

  • Semlith Cloud, from this machine
  • Images indexed by their bytes, not their extension (rc.2)
  • A vector cache a library caller can give a store of its own (rc.3)
  • An index run that tells the truth about itself everywhere it is shown; the image lane on a thread of its own; checkpoints that no longer drain the lanes; WebGPU on NVIDIA checked against its Vulkan driver (rc.4)
  • A CPU cap, 0-100 % of semlith’s own process (SEMLITH_CPU_CAP, the Limits card, in steps of 5); the CPU lane always on; lanes this machine’s hardware cannot run refused at the switch (rc.6, rc.7)

Removed

  • The remote lane and semlith worker
  • ledger::measure, which had no caller in the binary
  • The direct rustls, rcgen, ring and base64 dependencies, which only the remote lane used

Changed

  • The published crate carries the source, the tree-sitter queries, the files the binary compiles in and the notices; tests, harnesses, docs and CI stay in the repository

0.37.0-rc.7

9 October 2026 · Full notes on GitHub

Changed

  • The CPU cap steps by 5

0.37.0-rc.6

8 October 2026 · Full notes on GitHub

Added

  • A CPU cap

Changed

  • The CPU lane is always on
  • The switches tell the truth

Fixed

  • A first index through a remote GPU is 1.39x faster (#207)
  • images in index -v’s write parts now counts only the writer’s work, not the image model’s own thread

0.37.0-rc.5

7 October 2026 · Full notes on GitHub

Added

  • A remote embedding lane, attested before anything is sent
  • The portal’s lane row and doctor --gpu say where the remote lane points and what its attestation proved
  • People with their own NVIDIA GPU: the CUDA and TensorRT lanes documented and measured (both cosine 1.0000)

0.37.0-rc.4

6 October 2026 · Full notes on GitHub

Fixed

  • An index run tells the truth about itself, everywhere it is shown
  • A run no longer stops to drain at each checkpoint (#203)
  • Images are embedded on a thread of their own, so the text lanes keep embedding while the image model works; it had run on the writer and left the Neural Engine idle through a stretch of screenshots (#203)
  • A run admitted behind another job on its store’s writer can be taken out of the queue; the button said “nothing waiting in the queue”
  • Time left counts the embedding alone
  • The images total counts images with the image model and, on a reviewed run, the plan’s from the first second (it read 1 / 34, then 2 / 18, then 55 / 55); the drain’s “still embedding” no longer counts the window being filled twice
  • A long run gives the writer to file changes in its folders every five minutes rather than every 45 seconds, since each hand-over drains the lanes; a queued job still waits at most 45 seconds
  • Creating or deleting a store no longer waits for a search or graph in progress to finish
  • A phase said again with nothing new is logged once; under a stage filter the log folds a phase line that repeats the last one shown
  • The run log has one reader per run, shared by every card that shows it: the wizard’s rebuilt card added every line twice
  • A progress bar redrawn in place moves: the page patched its width as a style attribute, which the portal’s content-security policy drops, so the bar kept its first width while its percentage climbed
  • The WebGPU lane on Linux refuses to start when Vulkan has only a software device, and names the hardware device it uses
  • A failed accelerator lane is tried again on the first run ten minutes after it failed, and the failure is written to the daemon’s log
  • A scoped search is no slower than an unscoped one on a large store: a <repo>/** scope is a range of a path index rather than a GLOB over every path, and the eight most recent resolved scopes are kept, so an agent moving between repositories does not resolve each one again (#183)
  • A file that became empty, too large or unreadable is evicted, so its old chunks stop answering searches; an unusable image’s vectors go with its rows
  • A query longer than CLIP’s 77 tokens is never a confident image match
  • A key-like secret whose random part happens to open on FAKE or DUMMY is no longer taken for a declared test dummy
  • Long log lines, attention rows and feed entries in the portal wrap instead of cutting off the reason
  • measure_the_store_at_scale takes each size’s idle RSS as the median of five fresh opens, so a bimodal first figure on a hosted runner no longer fails the release suite (#199)

Added

  • The portal matches Semlith Cloud on what the two share: full text on hover for anything cut off and a tip on every progress bar; sortable columns marked; filters and tabs kept across a reload, and the setup wizard too; a busy wizard button that says what it is doing; search store chips, the budget tip and the store before each result path; the ledger’s read bars on one scale (a session that sent more than the whole file overflowed), its savings tables and chain footer; a “chain verified” chip on reports; a store error card and nav badge, an empty Stores state and a Sources table in Inside the index; the Review tab’s loading state and the wizard’s “nothing in the grey zone” note

Changed

  • semlith index -v splits the writer’s time by part: rows and their keyword index, eviction, graph, vectors, commits, saves, hashes and the vector cache (#198)
  • A failed known-answer check names every chunk under the floor, not only the worst (#197)
  • semlith setup says what --hook-mode gate buys where the choice is made, and docs/clients.md records the measurement behind it (#189)

Security

  • rustls 0.23.45, past RUSTSEC-2026-0285 (TLS 1.3 handshake messages accepted across encryption levels)

0.37.0-rc.3

5 October 2026 · Full notes on GitHub

Added

  • A store opened through the library can be given a vector cache of its own: Semlith::vector_cache takes a cache::Location (a file and a cap), and that store’s index runs read and write that cache and never the machine’s

Changed

  • semlith cloud status reports how many chunks the organisation indexed this month against its cap (12,400 of 100,000 chunks indexed) when the host counts chunks; semlith cloud push states the host’s estimate (about 1,400 chunks to index) and its --json report carries estimate_chunks

0.37.0-rc.2

4 October 2026 · Full notes on GitHub

Fixed

  • An image whose extension misnames its format - a PNG saved as .jpg, as image generators and chat apps often save them - is indexed by its bytes

0.37.0-rc.1

4 October 2026 · Full notes on GitHub

Semlith Cloud, from this machine

  • semlith cloud login [<org>] signs in by a code approved in the browser (the device authorization grant), or with --token checked against the host first
  • semlith cloud connect <org> adds the org’s stores as remote stores named <org>/<store>, listed by stats, files, semlith_stats, the Stores page and Search’s picker with a remote · <org> badge, and refused by every write path with a sentence saying why
  • A search naming a remote store, or none, is one list: remote hits merged with local ones by score under the same k and budget, each with its badge, revision and lag
  • semlith cloud push <org>/<store> <dir> [--wait] [--prune] sends only the files whose hashes changed, after semlith’s own refusals
  • semlith cloud sync <store> on|off: per store, off by default, the ledger’s rows (when, client, session, tool, tokens; never the query text) go to the org’s ledger once a minute, at most 1,000 at a time
  • semlith cloud report and semlith cloud replay
  • Settings › Cloud draws both states; the Ledger page says what is syncing, the Privacy page what leaves the machine and when, the daemon card · cloud: <org>, and semlith doctor has a cloud line

Added

  • Semlith::index_paths_under, Semlith::index_rest_under and Semlith::undo_run: a run under a control an embedder drives (pause, yield and continue from IndexReport::pending, stop and undo every slice’s written), each taking the store’s lock as index_paths does

Fixed

  • An MCP client reached over HTTP is labelled by the Semlith-Host header its stdio proxy sends, never by the ancestry of the daemon serving it
  • A stopped run’s undo no longer archives the run’s own definitions as symbol history
  • semlith search answers from connected remote stores too, not only the MCP tool and the portal
  • semlith cloud replay says once, not twice, that session replay is off for the org
  • The model cache is created private (0700) when it does not exist yet
  • Markdown heading names drop their inline emphasis, code spans and links: a Confluence heading ## **Making purposeful content** was named with its asterisks in search and the graph
  • A finished run’s history row is written before anything can read the run as finished; a daemon stopped right after “done” could lose it
  • With the cloud unreachable, the search summary counts its stores as skipped, not as 0 hits; a remote store the cloud no longer offers says so in Settings › Cloud; cloud status sizes caps in GB

0.36.0

2 October 2026 · Full notes on GitHub

Search on a store of many repositories

  • Search has no graph list
  • Every lookup tool can be scoped
  • The right repository first, unscoped
  • Faster on a large store
  • A faster keyword list

What semlith costs an agent

  • Eight tools listed, not sixteen
  • Caller questions go to the graph tools
  • The hook sends document reads to semlith
  • The portal says which tools agents are offered

Fixes

  • A folder added to a running store is watched from that moment; it used to be indexed once and then not watched until the daemon restarted (#180)
  • The portal on Windows no longer reports ERR_CONNECTION_RESET (#181)
  • A store deleted while the page was polling is no longer opened again in the moment between leaving the served set and leaving the registry, which recreated and re-indexed it
  • The Graph route reads under a 15 s limit and answers 503 naming how to scope it past that, so no request holds a worker for minutes on a very large store (#173)
  • Inside the index keeps each store’s measure until the store changes and measures a store over 20 000 chunks on a thread of its own, so a cold measure no longer competes with every other route (#175)
  • The accel countdown test measures the gap between its clock and the lane’s and allows for it, so a preempted runner cannot push it out of bounds either way (#177)

Installing

  • Releases are attested and the installers check them

0.35.0

2 October 2026 · Full notes on GitHub

The portal, redrawn

  • Nine pages in three groups, and a page per store
  • A first-run screen and a five-step wizard
  • What the older portal had, folded in
  • Live without rebuilding
  • A large store’s Graph page no longer holds the daemon
  • Add sources adds a folder
  • Loaders are the loading

Dropped folders resolve to their real path

  • A drop on the portal finds the real path, and uploads nothing
  • “Index with semlith” in the file manager, when asked
  • Safari drops take the real path

From a manual walk

  • Read and decided the way people use it
  • Index health reads each store once
  • semlith start and semlith upgrade say it once and say it right

The portal’s v6 backend

  • Stores are made, named and set from the page
  • Review decides several files at once
  • Index runs are kept
  • The ledger can be paused, and a broken chain repaired without a rewrite
  • Session replay is on by default
  • Airgap can be switched on at runtime, and every outbound connection is counted
  • Start at login, one client at a time, and what each tool costs
  • Search and brief answers carry what the agent sees

0.34.0

30 September 2026 · Full notes on GitHub

What the documents hold, counted

  • Inside the index counts pages, slides and cells
  • Older stores are counted on their next index pass without re-embedding
  • Inside the index no longer stalls other reads

Model, tokens and cost in the ledger

  • Each ledger row can show the model, tokens and cost of the call that made it
  • Cost comes from a models.dev price table built into the binary
  • Savings figures are priced from the same table

Fixed

  • Doctor reads IO CLI’s user-scope registration
  • A correct steering hook no longer reads as stale
  • The Doctor page colours each Skill & hook part by its state

0.33.1

30 September 2026 · Full notes on GitHub

Search answers on a large multi-repository store

  • The graph list’s walk is bounded
  • Seeding the walk uses an index
  • A failed graph list no longer fails the search

Exact search finds every line ripgrep finds

  • A < in HTML text no longer hides the lines after it
  • Every file is searched, and every line keeps its number

0.33.0

30 September 2026 · Full notes on GitHub

Twelve clients, each tested every release

  • semlith setup supports twelve clients
  • Upgrading cleans up after them, once
  • Zed and Cline are registered by setup
  • ChatGPT desktop (the Codex app) is registered by setup
  • Every client on macOS, Linux and Windows
  • Every retrieval is filed under the app that made it
  • A daemon restart no longer breaks connected clients
  • Nothing is created for a client that is not installed

Fixed

  • Copilot in VS Code refused every chat with semlith enabled
  • An upgrade left every client on the old daemon
  • semlith doctor reported the wrong start time for the daemon
  • Setup printed the agent key
  • The access report filed every proxied session under one store with zero hits
  • The ledger chain could fork
  • The stdio proxy’s start line
  • semlith doctor explains Gemini CLI’s folder trust
  • Stopping the daemon mid-index printed an ONNX Runtime error
  • A test of the Neural Engine compile countdown no longer fails on a slow runner (#166)

0.32.0

29 September 2026 · Full notes on GitHub

Indexing, several times faster on the machine you already have

  • An index pass is three stages running at once
  • The Neural Engine, on Apple silicon
  • A machine-wide vector cache
  • A store that answers while it fills
  • Everywhere else
  • Experimental lanes, built without their hardware

Fixed

  • A store built with one of fastembed’s own models no longer has its batches sent to a GPU lane, which runs granite and would have given it vectors from the wrong model
  • semlith doctor --gpu printed n/a for a lane that failed its check; it prints FAIL
  • A pack that fails its digest is deleted whole, not left half-unpacked
  • The GPU lane through Core ML was sent batches of one to three chunks on a model that computes eight at a time, so three quarters of its work was padding, and the lane’s pace, read from those batches and charged for the wait of a second batch queued behind the first, cut the next batch further
  • The vector cache takes 1.7 KB on disk a vector, where it took 4.7 KB: its table kept about a kilobyte of each row on the row’s page and moved the rest of the vector to an overflow page of its own, so a full cache was three times its cap
  • semlith stats names every lane that is on, the Neural Engine and the experimental lanes included; it named only the CPU, the GPU and CUDA
  • semlith accel status shows the running daemon’s lanes, so a Neural Engine compiling in the daemon no longer reads as idle in the terminal
  • A run’s rate counts vectors that have landed, not rows written ahead of them
  • The portal’s pages no longer wait seconds on a large store: the Stores figures read how many lines each file spans from a new index on the chunks table instead of every chunk’s text (14 s to 0.2 s on a 600 MB store)
  • A daemon stopped while an accelerator lane was restarting no longer waits for the lane: batches queued on a lane that is not ready go to the CPU
  • A killed lane worker no longer takes the daemon down with it
  • The Neural Engine no longer compiles for minutes on every start or fails its start

0.31.0

28 September 2026 · Full notes on GitHub

A store takes the disk its live content needs

  • semlith compact
  • The daemon compacts on its own
  • What a store takes is shown
  • A reader sees a writer’s new shards

Fixed

  • A file refused for a secret it gained left its old text readable in freed database pages, the keyword index and the write-ahead log until a vacuum
  • A key pasted as a search query was recorded in full in the ledger
  • A model download that stopped receiving bytes left semlith setup waiting for ever with no message
  • A file that a .semlithignore or .gitignore line excluded after it was indexed stayed in the store, searchable, for ever: only a file gone from disk was swept
  • Machine limits notes ran a reason into the next sentence (“would allow 7 Room up to 8”), and the Stores page’s Saved column broke inside a word
  • Three checks that failed intermittently now compare like with like: the native smoke’s pause window follows the run’s measured batch rate (#152), the drive’s threads each check skips on a home whose value is saved (#153), and the extra-store memory check measures one server answering from one store and then from three, rather than two processes whose footprints settle up to 120 MB apart for the same store (#149)

0.30.1

27 September 2026 · Full notes on GitHub

A long run stops re-checking what it has left, and its estimate moves

  • Slices check the files they reach
  • The estimate follows the run

Fixed

  • The document reader no longer panics on text with a multi-byte character twelve bytes after an & (“end byte index 12 is not a char boundary”), which it did five times on the rust-lang/book documents
  • Machine limits states one figure for the vectors per store
  • A slice cut short counted the files it had refused as not yet reached, so a run with refused files settled on a total its counter never reached

0.30.0

26 September 2026 · Full notes on GitHub

Agents use semlith, and it answers them well

  • What breaks if this changes
  • Answers an agent can act on
  • Bringing the agent to them

Fixed

  • The remaining-time estimate no longer jumps to minutes while a run writes its index, and never more than doubles between polls
  • a_port_something_already_holds_is_seen_as_held no longer races the rest of the suite
  • The daemon’s watcher said 0 indexed at startup for a catch-up it had only queued; it now says the catch-up was deferred, then what it found
  • semlith start no longer fails while a terminal semlith index is writing one of its stores
  • Across several stores, brief names the store on every span and symbol, and a symbol’s edges come from its own store rather than every store defining the name
  • The server instructions stayed over their 600-byte limit by the length of “folders” when the roots did not all fit
  • The research agent reads a located span through semlith_read; Read is kept for files semlith does not index
  • A run card’s plan line is updated in place, so a poll no longer rebuilds it
  • A run started from the portal shows its time estimate from the first batch: daemon runs now record the store’s embed rate, and a store with none uses the last run the daemon watched
  • A semlith_index forwarded to the daemon names every refusal of the run, its skips by reason, and how many files await review, as the in-process reply does

0.29.0

25 September 2026 · Full notes on GitHub

Eleven portal fixes found using 0.28.0

  • Index run cards count down
  • Stores can be deleted together
  • Impact says what it shows and where to start
  • Graph’s rail keeps its buttons in view
  • Smaller fixes

0.28.0

24 September 2026 · Full notes on GitHub

The service indexes 4.6× faster, the GPU works beside the CPU, and the run controls act at once

  • Priority now follows the work
  • Machine limits apply as soon as they are saved
  • Values saved under 0.27.0 take effect now
  • Everything the daemon embeds goes through one queue
  • Pause and Stop act at the next batch
  • Stop can delete the store
  • The chunks/s figure is a rolling rate
  • Idle sessions are released, and all readers share one query session
  • Chunks are batched by length
  • The GPU works beside the CPU, on by default
  • WebGPU
  • CUDA
  • Switches
  • Where each vector came from
  • Lanes are checked before they are trusted
  • Only the daemon uses GPU lanes
  • A reader panic fails one file, not the store
  • The hybrid-core thread count covers Linux and Windows
  • Fixed
  • Fixed, found while building this release
  • The Privacy route lists every download

0.27.0

23 September 2026 · Full notes on GitHub

The portal drawn the way the design draws it, and reports that write themselves

  • semlith start against a store a daemon already holds is no longer an error
  • Reports schedules itself
  • Reports is the page the design specifies
  • Two of the builder’s three toggles do what they say
  • A fifth report format: PDF
  • /api/report takes a window and a scope
  • Impact draws the canvas its caption promised
  • Index and Inside the index are two pages
  • Session replay looks like the design in all three places it appears
  • One hover card, everywhere
  • One unreadable store no longer takes the readable ones down with it
  • Pages scroll to their end
  • Controls read as controls
  • Two columns become one on a phone
  • Every page’s panels are in the design’s order
  • Scroll position survives a live repaint
  • Code blocks lose the fade
  • The type scale is the design’s
  • Three layouts that fought the page
  • The Stores page notices a root folder that has gone
  • A saved limit is called saved on every branch
  • About loses two blocks
  • The retrieval harness gains an image class

0.26.1

21 September 2026 · Full notes on GitHub

The portal, opened beside the design it was built from

  • The first-run screen is complete
  • The menu is four groups again
  • The routes the design draws between pages are there
  • The Graph page’s right column was painting over itself
  • Reports is the page the design draws
  • --model opus_5 priced at Sonnet 5 and said so
  • The browser’s own paragraph margin was a second spacing system

0.26.0

20 September 2026 · Full notes on GitHub

The whole portal, free, in the binary

  • Impact
  • Trace
  • The path finder, drawn
  • Map
  • Inside the index
  • The ledger, session by session
  • Session replay
  • Reports
  • Cloud

Four defects, all of them older than this release

  • #122
  • #120
  • #121
  • #124

0.25.0

20 September 2026 · Full notes on GitHub

What was tried, and what was kept

  • Code chunks carry their definition
  • A cross-encoder writing the order outright
  • The same cross-encoder fused with the fused order
  • A deeper candidate pool for questions
  • Normalising spellings before comparing a hint against a path

0.24.0

19 September 2026 · Full notes on GitHub

0.23.0

19 September 2026 · Full notes on GitHub

An agent asking semlith a question used to spend four round trips on it: search, read the span, ask what calls it, read those. Three of them re-established what the first already found. semlith brief answers it in one.

Retrieval

Fixed

  • Warm query p50 and peak indexing memory are measured again
  • #104 closes
  • The native smoke harness runs only on release pull requests
  • sha2 0.11 finalises to a value that no longer implements LowerHex

Changed

  • tools/list is thirteen tools at 4 441 bytes, about 1 111 tokens, against twelve at 3 995 and 999
  • semlith stats says whether a store carries the rescoring sidecar and how many definitions it has retired

0.22.0

19 September 2026 · Full notes on GitHub

Retrieval was measured by an instrument that could not measure it. This release rebuilt the instrument first and only then moved the number, which is why the figures below are lower than the ones they replace and mean more.

The measuring stick, before the ranking work

  • The retrieval harness indexes a pinned corpus, not the working tree
  • The question set is 107 questions, split 77 development / 30 sealed
  • Every figure is the median of three runs, with the spread beside it,
  • A path question can be a hit

Retrieval

  • An identifier-shaped query puts the definition first

Fixed

  • The native smoke harness no longer writes under your own home
  • The smoke harness says what supervision it found
  • #104 is not fixed

0.21.0

18 September 2026 · Full notes on GitHub

On 2026-09-17 a session opened with no semlith server. The registration was correct, at user scope, and the installed binary answered initialize in well under a second over six stores. It happened again on 2026-09-18. Nothing anywhere said why.

semlith is there before a client asks

  • semlith start --service installs the daemon as a login service: a launchd user agent on macOS, a systemd user unit on Linux, a logon task on Windows
  • semlith setup and the installers install it, including where nothing can answer a prompt — a piped installer, CI, --yes
  • Installing onto a port something already holds registers the service for the next login and leaves the running daemon alone
  • On macOS, a binary inside ~/Documents, ~/Desktop, ~/Downloads or iCloud Drive is refused rather than installed

The handshake no longer waits for the embedding model

  • semlith mcp answers initialize and tools/list before any model is loaded
  • A machine with nothing indexed gets a server instead of an exit code
  • semlith mcp no longer claims a privacy rejection for a file that is not there

semlith doctor names the step that failed

  • A server registered at user scope and switched off for one directory is reported as a fault in that directory, naming the file, the key and the directory, with the command that turns it back on
  • Every registration semlith writes names the resolved absolute path of the binary rather than the bare command semlith

Housekeeping

  • The native smoke harness on all three platforms installs the login service, kills the daemon and confirms it comes back, and checks that the handshake answers with the embedding model made impossible to load

0.20.2

18 September 2026 · Full notes on GitHub

A full manual drive of every portal page on 2026-09-17 — every button, filter, picker, toggle, sort, index run, search, graph interaction, agent action, privacy scan and about row, at desktop, tablet and phone widths — found 62 defects. This release fixes all of them, and adds the scripted browser drive that replays every one of their reproductions as a standing gate.

The product no longer contradicts itself

  • A store holds only what its roots cover
  • One search is one retrieval
  • LAST WRITE is the store’s last write, read from the store rather than from this daemon’s memory of its own session
  • semlith ledger and the portal both print local time with the zone offset, from the operating system rather than from UTC arithmetic

Index runs tell the truth about what they did

  • Runs are keyed by run id rather than by store
  • A finished run offers Remove and not Stop
  • Live runs sort above finished ones, a finished card folds to one line, all the finished cards can be cleared at once, and the “N runs queued.” line clears when nothing is queued
  • The live chunk counter is the run’s, not the slice’s
  • A store the portal creates holds its watcher off until the run that is about to index it arrives, so a run no longer finds its own files unchanged and reports 1 indexed … 1 chunks for a store that has just gained three files
  • A run that is rewriting its shards says so

Features that did not work

  • Adopt existing .semlith
  • Add from a URL
  • Open in Files
  • Projects under a folder…
  • The graph’s edge-kind filters filter
  • Changing lang:, path: or the token budget re-runs the search, like every other control on the page
  • The Retrieval ledger page shows the ledger: the rows semlith ledger prints, paged and sortable

The HTTP surface

  • An unknown path answers 404, with 401 kept for a request that failed the token
  • site.webmanifest’s icon paths resolve, so a page load logs no console error
  • /api/files?limit= above the maximum answers 400 naming it, the same contract offset already had, rather than clamping silently

Copy, states and polish

  • A registry entry whose directory is missing is shown as missing, naming the path that is absent, and is offered nowhere a real store is offered
  • The Machine limits panel’s derivations are computed from the numbers it prints: a negative headroom says the floor applies, MB and MiB are one unit, “threads each” recomputes when “runs at once” changes, and a saved value is called saved rather than derived
  • Doctor gives a fix command only for a client that is on this machine, and where two commands are genuinely right for one state the cell says why
  • The Claude Code HTTP stanza carries the --scope user the paragraph above it insists on; inline code on the Agents page renders as code; closing the MCP endpoint asks first; and the dry run is the primary button while the one that writes ten configuration files is the secondary
  • Four model notes described a different model than the row they sat on, the model semlith actually runs showed no size, and sorting by size buried the only rows that had one
  • The Privacy page’s Rules badge says it is about new writes, and the scan below it says it is about what is already stored
  • The theme control offers system, light and dark, so following the operating system is reachable again
  • Truncated paths carry a title, four tables carry captions, unselectable rows in a picker are dimmed, pickers sort case-insensitively, the code preview fades where a line continues, the tablet stat tiles break three and two, a phone’s store chips are one scrolling row, and a sub-second run reads in tenths
  • The first search after the daemon starts says it is loading the embedding model rather than showing five seconds of “searching”

The gate

  • tests/drive/ drives Chrome over the DevTools Protocol and replays the reproduction for every one of the 62 findings, asserting the corrected behaviour and writing a transcript and a screenshot per check

Unchanged

  • The MCP tool list, the tool schemas and the store format

0.20.1

17 September 2026 · Full notes on GitHub

Fixed

  • install.ps1 can replace a semlith that is already installed

0.20.0

17 September 2026 · Full notes on GitHub

A sliced run carries on instead of starting over

  • A run yields the writer back to the watcher every 45 seconds and returns as a fresh job
  • The progress a page shows belongs to the run rather than to the slice, so the counter no longer returns to 1 partway through

The run clock

  • Starts when the run is submitted, not when the writer reaches it: the wait for a writer is time you are waiting
  • Spans every slice
  • Stops while a run is held, and freezes at its total when the run ends

The Doctor page

  • Has a navigation icon
  • Its Clients and Rules sections use the same layout as every other section in the portal

A run lives in the daemon, not in the page that started it

  • An index run is the daemon’s: its id, paths, status, counters, clock, the last 500 lines of its log and its closing summary
  • The snapshot is written by the same say closure that emits every event, so the card and the log cannot disagree about what happened
  • The Index page draws one card per store, each with its own Pause, its own Stop and its own log, read by a cursor so two tabs open on the same run each see every line exactly once
  • POST /api/index no longer streams
  • The elapsed clock was measured around one slice

One folder becomes one store

  • POST /api/index takes "store": "each" — one store per path, each resolved through the same function semlith index <path> resolves through, suffix and all, so indexing a folder from the page and again from a terminal produces one store rather than two
  • semlith index --each is the same choice in the terminal, sequential — one process, one embedder, one store at a time
  • semlith index --projects <FOLDER> takes the paths from the git repositories directly under that folder and implies --each
  • The Index page has the same list as a checklist, from GET /api/projects and the same discovery function, so the page and the terminal cannot disagree about what is under a folder

Runs wait for each other, and the daemon decides how many

  • Each store’s writer used to take the next job on its own queue with nothing above it, so eleven open stores meant eleven runs at once whatever the machine had
  • POST /api/index/control gains dequeue, and a queued card’s button reads Remove
  • A new src/system.rs reads logical cores, physical cores where the platform says, total memory and memory free now — /proc/meminfo, sysctl and host_statistics64, GlobalMemoryStatusEx — with no new dependency
  • The three are settings rather than constants: SEMLITH_INDEX_PARALLEL (new), SEMLITH_EMBED_THREADS and SEMLITH_INDEX_MEMORY win, then ~/.semlith/settings.json, then the derivation
  • Changing runs-at-once takes effect on the next admission: raising it admits the head immediately, lowering it stops nothing already going, because a run holds a writer and undoing it would cost the work it has done
  • A daemon that ends with runs queued drops them, and its next start names each on that store’s event feed as never started — along with any run that was going and what it had committed

The portal reads live

  • GET /api/changes returns six monotonic integers, one per data domain, each bumped in the one function that writes that domain
  • It is a poll and not a server-sent stream because a stream holds one of the daemon’s eight HTTP workers for as long as the tab is open, which is the same constraint the run-state work above exists to respect
  • Search, Read and Graph are not refetched on a timer

Also

  • The Doctor page has a navigation icon and the card padding every other page uses

0.19.0

17 September 2026 · Full notes on GitHub

One unreadable file no longer ends the run

  • A file that fails on its own content — a truncated PNG, a source file tree-sitter cannot parse — is reported failed with the decoder’s or the parser’s own message, and the run indexes the next file
  • Every skipped file says why, from a closed set: empty, over 8 MiB, not a regular file, unreadable with the operating system’s own words, binary, no text in this document, not a decodable image
  • The done event, the CLI’s last lines and semlith_index’s return count the skipped by reason and name every failed path
  • A file whose reader produced nothing used to be counted and never reported, so the portal’s progress bar stopped short of its own total on any tree with binaries in it
  • Entries the walk itself cannot read are failed files on the same channel rather than a line on stderr the daemon never sees
  • The watcher survives a per-file failure

Credentials

  • A content scan runs on every file’s text before it is chunked, stored or embedded, including the text a reader produced from a .docx or a notebook
  • The deny-list widened to every environment-variable file rather than .env and .env.* alone, and to the per-user credential files the hidden-file rule used to catch on its own: .npmrc, .netrc, .pypirc, .pgpass, .htpasswd, .boto, .s3cfg and *.ppk
  • A refused file that an earlier run indexed is evicted in the same pass, and the refusal says so
  • semlith scan [STORE] runs both rules over everything a store already holds, prints each file semlith would refuse today, and exits non-zero while any remain

A whitelisted dotfile is indexed rather than refused

  • The hidden-file rule now applies only to a path the caller named
  • This changes what a store holds on a re-index

Fixed

  • semlith index from a second process while semlith start is running produced a store the portal and every agent could not see until the daemon was restarted
  • semlith_symbol and semlith_path returned Windows verbatim paths — \\?\C:\work\api\src\lock.rs — which no editor opens and no shell completes
  • The home directory was canonicalised twice per file to answer a question that cannot change during a run, which on Windows is two opened handles per file

Also

  • semlith_pattern, semlith pattern and /api/pattern take path — the same glob filter every other surface takes, which this one ignored — and offset, so a listing the 200-match cap cut short can be continued
  • The portal’s Index page shows the elapsed time, corrected to the daemon’s own clock on every file so a backgrounded tab cannot drift, counting through a pause and frozen on the total when the run ends

0.18.0

16 September 2026 · Full notes on GitHub

Every agent client on the machine, from every project

  • semlith setup registers semlith in every client that documents a registration command, at the scope that client spells “every project”, rather than registering Claude Code alone and printing the other twenty-six as stanzas to paste
  • Every registration is the stdio form: the client launches semlith mcp, which reads the agent key from ~/.semlith/agent.key itself
  • An existing semlith entry is removed before the new one is added, at every scope the client has — including the project-scope entry in ~/.claude.json that made semlith invisible from every directory but one
  • semlith setup --register-all, and a control on the portal’s Agents page, write the configuration file of the ten clients that have no registration command
  • docs/clients.md carries the registration facts in its fence info strings, so the document a human reads and the one src/clients.rs parses are one file
  • The shell startup block semlith setup writes carries PATH and nothing else

semlith doctor

  • New command, with --json and --fix
  • A portal view of the same report, from the same route

The Privacy page can fix what it reports

  • Every failing rule carries the command that repairs it, copyable
  • directory modes, agent key, and model cache when the cache is your own carry a button as well
  • private addresses gets the manual step and no button
  • Fixed: the agent key check rendered the same sentence whether the mode was compliant or not, so a key at 0644 read exactly like one at 0600

Fixed

  • One corpus indexed twice now produces one index, and the retrieval harness reproduces its own numbers (#88)
  • SEMLITH_CHECKPOINT_SECS is now SEMLITH_CHECKPOINT_FILES

0.17.3

16 September 2026 · Full notes on GitHub

Added

  • A ## Prior art section in the README, citing the paper by title, its four authors and its arXiv id, and turbovec by author, licence and repository, with two sentences on what data-oblivious buys a local index
  • tests/readme.rs asserts the README carries both the turbovec repository URL and 2504.19874, so an edit that drops either fails the build
  • tests/portal.rs asserts no semver literal appears in a user-visible string in src/portal/app.js

Fixed

  • NOTICE named BAAI/bge-small-en-v1.5 as the default model, which the product stopped using
  • docs/architecture.md, which the README calls the full account, described the single-file index that store format 2 replaced in 0.7.0 — including a crash-safety argument and an atomic-write argument stated over the wrong object
  • The portal’s About page said forty grammars arrived in a named release and that the binary had grown by a measured number of MiB against another one — three versions and four figures, hardcoded, where no reader could tell which build they described

A Ctrl-C guarantee that CI can see fail

  • The test now waits for the watcher’s own watching … banner, which is printed after the handler is installed, instead of for a clock
  • .github/smoke.sh gains cli/watch/sigint-whole, which interrupts a real watcher and then checks the exit status, that no half-written index was left behind, and that every chunk still has a vector

Removed

  • The About page’s MCP revisions row

0.17.2

16 September 2026 · Full notes on GitHub

Added

  • docs/portal.md, the first documentation of the portal: one section per page, how the daemon starts, and the concepts behind the graph, the search list and the two credentials
  • docs/clients.md, holding the client configuration stanzas moved out of the README
  • docs/performance.md, holding the benchmark tables with their reproduction commands and the release each was measured for
  • tests/readme.rs, which parses the counts out of the README and asserts each against its source — languages, edge kinds, tools, commands, formats, image types and clients

Fixed

  • The portal’s Graph page drew four of the six edge kinds the store holds: contains and aliases were fetched from /api/graph and dropped before painting, while the hover card counted them anyway
  • src/graph.rs’s module comment still said six languages carry edges, which 0.17.0 made false
  • Four places said a rotated agent key stays valid until the daemon exits, including the message the portal prints after a rotation
  • docs/compatibility.md’s covered-surface table named none of symbol, neighbors, path, ledger or drop, which are stable commands
  • CONTRIBUTING.md said CI runs on Linux and macOS, and did not mention the msrv or scripts jobs

0.17.1

15 September 2026 · Full notes on GitHub

Ten bugs. Four of them are one bug: Windows sets no HOME, and semlith read it in nine places that each had a different answer when it was missing. The rest are what a person meets on the first day — a path printed in a form nothing opens, a pipe closed early, a root that cannot be read, a forget that removes nothing, a page parameter checked and ignored. No new command, no new tool, no new argument and no schema change.

One home-directory helper

  • #70 — the store home resolves on Windows
  • #71 — the portal’s directory browser refuses instead of rooting at the drive
  • #72 — the directory deny-list fails closed
  • #73 — a run with no home is an error, not a store in the working directory

Fixed

  • #74 — paths print in the form the platform opens
  • #75 — semlith files | head exits quietly
  • #76 — an unreadable index root creates nothing and registers nothing
  • #77 — semlith forget forgets the file the listing printed, and semlith drop runs at all
  • #78 — GET /api/search applies the offset it validates

Notes

  • Five answers change where the old one reported success
  • A Windows user may have a stray .semlith
  • #82 — the harness ledger is empty of real rows
  • No store format change

0.17.0

15 September 2026 · Full notes on GitHub

The code graph covered six of the forty-six languages --lang accepts. That gap was a promise the product did not keep: --lang kotlin narrowed a search perfectly well, and then semlith symbol answered nothing about the same corpus with nothing saying why. It is closed.

One language table

  • The extractor reads filter::LANGUAGES, the table the search filter reads
  • Every language has a fixture that says what it must extract

Forty grammars

  • Twelve of the new grammars ship a tags query; twenty-eight do not
  • Nothing is vendored and nothing is a git dependency
  • THIRD-PARTY-NOTICES ships with the crate and with every release archive,

What a symbol is in a language that has no functions

  • Fourteen of the forty-six are markup, data or configuration, and their structure is their symbol set
  • What they reference is files
  • Svelte and Vue contribute their template and say so

Fixed

  • C and C++ attributed every call to the file rather than to the function making it
  • C++ captured no calls at all, C# captured no invocations, JavaScript captured no imports, PHP captured neither a require nor a function call, and Swift captured no calls
  • Elm recorded nothing about a declaration depending on another

Surface

  • semlith languages prints a graph column,
  • No new command, tool, argument or schema

What it costs

  • The binary more than doubles: 47.0 MiB to 111.3 MiB, +64.3 MiB (+137%)
  • Retrieval moved, and the move was measured rather than assumed

0.16.0

14 September 2026 · Full notes on GitHub

0.15.0 made the free product honest and cheap. It did not make it better at finding things. This release spends the harness that release built on the ranking itself, and reports what the harness said — including where it said no.

The graph list stops being a set and becomes a ranking

  • Graph neighbours are ranked by personalised PageRank
  • A symbol question is answered with one evidence block
  • An edge records the line the call was written on
  • A walk crosses a re-export

Search reads the query before it ranks the answer

  • An identifier and a question are weighted differently
  • prefer: code | docs | any
  • The fused set is reranked by graph distance and freshness

Two new tools, and a tool list that did not grow

  • semlith read
  • semlith pattern
  • Twelve tools now fit the budget ten used to

A store has one name

  • The portal drew store chips the search route then refused

The portal

  • Neither new tool gets a page, and that is the decision rather than an omission
  • The Search page rebuilt to that design: the query-shape hint, file cards with span summaries, word-pill fusion badges, the provenance sentence, a signature strip, a line-number gutter, a read-whole-symbol control, and an ego-graph panel
  • Three bugs found by rendering the pages rather than reading the diff: image previews were handed a blob: URL the page’s own CSP had always refused and so had never worked; the Read and Pattern views could let a slow earlier answer overwrite a newer one; and the graph canvas leaked an animation loop per visit
  • The Languages page is gone

0.15.0

14 September 2026 · Full notes on GitHub

The graph stops answering questions it cannot support, the search stops sending the thing itself when it was asked where the thing is, and the ledger starts recording the agents it exists to measure.

A graph that says how much it knows

  • An edge’s target is resolved, not matched by name
  • edges.hint records what the source said about where a call goes
  • A path walks definitions, not names
  • --all-edges walks the old way and says what it found
  • semlith neighbors collapses and hides
  • Search expansion follows only the kinds that mean “depends on”

A search that answers where

  • semlith_search answers with locations by default
  • Every hit says whether its file has moved under it
  • tools/list is 3 940 bytes with one store open, from 8 634

A ledger that records the user it exists for

  • Every retrieval is recorded, from every surface
  • Recording is on by default, and semlith start --ledger is removed
  • Both sides of a ratio are counted with the store’s own tokenizer
  • semlith ledger --verify re-walks the chain
  • Four nullable columns on retrievals

A number behind every retrieval claim

  • tests/retrieval.rs

Removed

  • semlith start --ledger
  • This is a break in the covered surface

Notes

  • Existing stores open unchanged, and format_version stays 2

0.14.0

14 September 2026 · Full notes on GitHub

Every finding of the security audit of 0.13.0, closed in one release, each with the test that would have caught it. The restrictions are the release: docs/compatibility.md records the four that break something 0.13.0 did, with the way back for each, and docs/security.md is the user-facing version of what semlith now refuses.

Nothing else on this machine can act as you

  • H2, L6 — the portal session moved from a cookie to a request header
  • M1 — the token comes from the OS random source
  • M9 — a panicking route costs one request
  • L1 — what one client can hold is bounded
  • L2 — an Mcp-Session-Id from a client is accepted only as the sixteen hex characters the server produces

Nothing you did not write decides what semlith answers with

  • M2 — a store semlith did not create is opened only after semlith trust
  • M7 — the model weights are pinned to a commit and a digest
  • L3 — the parsers are bounded
  • L4 — /api/image canonicalises before it looks up

What a leaked agent key gets

  • M6 — the agent-facing index tools work inside a boundary
  • M6 — semlith add refuses an address that is not on the public internet
  • M4 — the agent key stops travelling

On disk

  • M5 — what semlith writes is readable by its owner and nobody else
  • M3 — the PATH line semlith setup writes is a shell word
  • L5 — the registry’s temp file carries this process’s id

The release itself

  • #57 — the prebuilt Linux binary starts on Debian 12, Ubuntu 22.04 LTS, RHEL 9 and Amazon Linux 2023 again
  • H1b — semlith upgrade has one origin and no way to be told another
  • H1c, H1d — the download is bounded and the archive is unpacked in this process
  • M8 — release.yml grants contents: write to the one job that uploads
  • L7 — install.ps1 sets TLS 1.2 before its first request
  • I1, I2, I3 — SECURITY.md describes the release that exists

Added

  • semlith trust <dir> records a store outside the store home as one you have agreed to open, and semlith trust --list prints what is trusted
  • semlith index --include-secrets indexes what the deny-list otherwise refuses
  • The portal’s Privacy page carries a Rules section: one row per rule this release adds, each with the daemon’s own check of it
  • docs/security.md, the user-facing version of what semlith refuses, and docs/models.md, the pinned commits and digests with the commands to check them yourself

0.13.0

13 September 2026 · Full notes on GitHub

The portal becomes the product’s own design, agents get an endpoint they can keep in a config file, and a query can find a picture.

Added

  • MCP over HTTP, at http://127.0.0.1:7365/mcp
  • A persisted agent key, in ~/.semlith/agent.key
  • semlith key show and semlith key rotate
  • A rotation carries the key into the files that hold it
  • Bulk forget, and deleting a store
  • An index run says what it is doing
  • A request no longer waits for the watcher
  • Pause and stop an index run
  • An endpoint switch
  • Image search
  • Sorting and pagination on every table the portal renders
  • An indexed column on the Files page

Changed

  • The portal is rebuilt against its design
  • The product is written “Semlith” in prose
  • The Linux prebuilt binaries print their glibc floor
  • initialize, tools/list and ping answer with no store open

Removed

  • semlith impact, the semlith_impact MCP tool and GET /api/impact
  • This is a break in the agent-facing surface

Fixed

  • A tooltip inside a table was unreadable
  • The Index page painted an empty bordered box
  • --airgap could have fetched a model
  • A route that no longer exists answers 404
  • The install script’s progress bar, properly this time

0.12.0

13 September 2026 · Full notes on GitHub

The store learns the shape of the code in it, and search uses it.

Added

  • A code graph, extracted on the same pass that re-embeds a file
  • Extracted or inferred, on every edge
  • semlith symbol, semlith neighbors, semlith path, semlith impact
  • Graph-aware search
  • A Graph page and an Impact page in the portal
  • An opt-in retrieval ledger

Fixed

  • The install script’s progress bar

Notes

  • Existing stores open unchanged
  • Measured
  • Six languages carry edges
  • Everything in this release is free on every tier, permanently

0.11.0

12 September 2026 · Full notes on GitHub

The rest of a real archive, and a way to put something into a store that was never a file on the disk.

Added

  • EPUB, RTF, .eml and .mbox readers
  • semlith add <URL>
  • Twenty-one more languages for --lang
  • A Languages view in the portal

Changed

  • The portal’s Files view shows a language for a file that has no extension, where it previously showed nothing

Security

  • semlith add is the first outbound connection semlith makes that is not the model download or semlith upgrade, and it holds to the same rules

0.10.0

12 September 2026 · Full notes on GitHub

One command on a fresh machine. No Rust toolchain, no package manager, nothing installed first — and on Linux, no OpenBLAS and no OpenSSL either, because the binary no longer needs them.

Added

  • install.sh and install.ps1
  • semlith setup [--yes]
  • semlith upgrade [--check] [--version <tag>] [--airgap]
  • Portal parity

Changed

  • The Linux binary needs nothing but glibc and libstdc++
  • The OpenBLAS instruction is gone
  • The README’s Install section leads with the two one-liners
  • One new runtime crate

Documentation

  • docs/compatibility.md now covers the install script URLs and the environment variables they honour, the release archive layout both they and semlith upgrade read, semlith setup --yes, and semlith upgrade --check’s exit codes

0.9.0

12 September 2026 · Full notes on GitHub

A store no longer has to live inside the repository it indexes, and a portal in your browser shows you what is in it. semlith start is one process that owns every store, keeps them current as you save, and serves that page on 127.0.0.1 — which also ends the choice between a watcher keeping a store current and an agent being able to write to it.

Added

  • A store home
  • semlith adopt <dir>
  • semlith start
  • The portal
  • semlith mcp forwards to a running daemon
  • --airgap
  • A token rotate route

Changed

  • Client stanzas lost their paths
  • semlith mcp with no flags opens every registered store rather than ./.semlith alone
  • The out-of-scope note in AGENTS.md and docs/architecture.md now states the loopback rule instead of forbidding a server, per #41
  • turbovec 0.9.0 → 1.0.0: search_with_allowlist returns a Result instead of panicking on an id the index does not hold, which is the better contract for a shard that legitimately lacks an id its range covers
  • fastembed 6.0.1 → 6.0.3
  • Three further Dependabot updates that landed on develop while this release was in flight and are merged into it rather than shipped separately: a patch-updates group of two crates, Swatinem/rust-cache in both workflows, and softprops/action-gh-release 3.0.2 → 3.0.3
  • chacha20 in the lockfile, which had been yanked upstream

Security

  • The portal binds 127.0.0.1 only, with no flag to change it

Dependencies

  • No new crate

0.8.0

30 July 2026 · Full notes on GitHub

The documents a corpus is actually made of. A notebook, a Word file, a slide deck, a spreadsheet or an HTML page is now read as the text a person opening it would see, rather than as its markup, its JSON, or not at all.

Added

  • Nine more formats, behind the same extraction the PDF reader already sat behind
  • A cap on what an archive may decompress to: 32 MiB of text
  • zip 8.6.0

Changed

  • HTML files and notebooks are indexed differently than before, not just additionally
  • A document that cannot be read is a skipped file
  • No store format change and no migration

0.7.0

30 July 2026 · Full notes on GitHub

A corpus larger than a repository. The first index of one says where it has got to, survives being interrupted, and searching it costs a bounded amount of memory rather than an amount that grows with the corpus.

Changed

  • Breaking: a store created by 0.7.0 has a new layout, and an older semlith will not read it

Added

  • A resident-memory budget for the vector index
  • Checkpointed indexing
  • Progress that predicts
  • Opening a store loads no vectors

Performance

  • Changing one file in a sharded store rewrites one shard rather than the whole index — the difference between watching a monorepo and not being able to
  • Search latency is unchanged for a store that fits inside its budget

0.6.0

30 July 2026 · Full notes on GitHub

semlith works from whichever agent you already use, the MCP tools cover the store rather than a fifth of it, and what counts as stable is written down.

Fixed

  • The server no longer claims protocol revisions it cannot speak

Added

  • MCP 2026-07-28, the stateless revision, alongside the handshake
  • Three more tools, so the MCP surface covers what the CLI does
  • A setup stanza for every MCP client in common use
  • docs/compatibility.md
  • format_version in the store’s meta table
  • SEMLITH_MCP_INDEX_BUDGET
  • The MCP server says what it is on stderr

Changed

  • semlith forget takes the store’s write lock

Performance

  • The tool list grew from 2220 bytes for two tools to 4790 for five — roughly 555 estimated tokens to 1197, measured through both release binaries
  • An MCP server at rest holds no store lock: semlith index in another terminal against the store an open server is serving succeeds

0.5.0

30 July 2026 · Full notes on GitHub

One query across several stores, so an agent working across repositories asks one question instead of one per repository.

Added

  • --store is repeatable on the read commands
  • Every hit says which store it came from
  • SEMLITH_STORE accepts a list
  • One MCP server, several stores

Changed

  • A read command refuses a store path that is not already a store
  • index, watch and forget take exactly one --store

0.4.0

29 July 2026 · Full notes on GitHub

Keeps a store current while you work: files are re-embedded as they are saved, and an agent already connected over MCP sees the change without restarting.

Added

  • semlith watch [PATHS...]
  • A long-running reader now sees another process’s writes
  • Ctrl-C stops a watcher cleanly

Changed

  • semlith watch holds the store’s write lock for as long as it runs
  • An indexing pass that changes nothing no longer rewrites index.tv

0.3.0

29 July 2026 · Full notes on GitHub

Narrows a search to part of a corpus, so one store per repository can answer a question about one subsystem.

Added

  • --path, --ext and --lang on semlith search
  • The semlith_search MCP tool takes the same filters
  • semlith languages

0.2.0

29 July 2026 · Full notes on GitHub

Removes three of the four limitations 0.1.0 shipped with, cuts peak indexing memory to a third, and changes the default embedding model.

Changed

  • New default embedding model: granite-embedding-small-english-r2, int8
  • Existing stores are not affected and are not migrated
  • Search is now hybrid
  • ONNX Runtime thread count is chosen rather than defaulted
  • Minimum supported Rust version is now 1.89

Added

  • One writer per store
  • semlith models lists the new default alongside fastembed’s built-in models

Fixed

  • A release whose git tag disagrees with Cargo.toml now fails the release build instead of publishing binaries labelled with a version they were not built from

Performance

  • Peak indexing memory is now roughly 600 MB and no longer grows with the corpus
  • Indexing throughput is up from ~13 to ~23 chunks/sec
  • Retrieval quality

Library API

  • DEFAULT_MODEL: EmbeddingModel is replaced by default_model() -> Model
  • Semlith::open takes Option<Model> rather than Option<EmbeddingModel>, and Semlith::model returns &Model
  • New modules: embed (model identity and loading) and lock (store locking)

0.1.0

26 July 2026 · Full notes on GitHub

First release.

Added

  • Local semantic search over files
  • turbovec-backed vector index
  • SQLite for everything else
  • Incremental indexing
  • MCP server
  • PDF support
  • Sensible skipping
  • Commands
  • Model selection

Performance

  • Warm query: ~6 ms
  • Cold CLI start: ~250 ms, almost all of it loading the ONNX model
  • Indexing: ~13 chunks/sec, ~1.7 GB peak RSS
  • Re-index with nothing changed: 17 ms