| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| semlith-v0.30.0-aarch64-apple-darwin.tar.gz | 2026-09-26 | 24.0 MB | |
| semlith-v0.30.0-aarch64-unknown-linux-gnu.tar.gz | 2026-09-26 | 23.6 MB | |
| semlith-v0.30.0-x86_64-pc-windows-msvc.zip | 2026-09-26 | 21.7 MB | |
| semlith-v0.30.0-x86_64-unknown-linux-gnu.tar.gz | 2026-09-26 | 24.8 MB | |
| SHA256SUMS | 2026-09-26 | 448 Bytes | |
| README.md | 2026-09-26 | 8.0 kB | |
| Semlith 0.30.0 source code.tar.gz | 2026-09-26 | 3.0 MB | |
| Semlith 0.30.0 source code.zip | 2026-09-26 | 3.2 MB | |
| Totals: 8 Items | 100.3 MB | 0 | |
Agents use semlith, and it answers them well
A benchmark of 216 headless Claude Code sessions on 2026-09-25 found that the
setup semlith setup wrote got 7 % of an agent's lookups, and that forcing the
agent onto semlith cost answer quality, because the tools failed on exactly the
questions agents ask. This release fixes the tools first, then the levers that
bring the agent to them.
What breaks if this changes. semlith_impact walks from a definition, not a
name: Fleet::search_preferring, module::function and Type.method resolve to
the definition that owner holds, each reaching row carries the call-site line,
and the answer stays under 16 000 characters at any depth — past the cap, rows
collapse into per-file counts with a more: line. The same question at the
default depth was 75 012 characters on 0.29.0, over Claude Code's MCP limit.
The Rust extractor now records a method's owner and a receiver's declared type
(self in impl T, x: T, T::new(), a field store: T), so the two
search_preferring methods are told apart; callers of a name with several
definitions say which one they mean (→ Fleet::search_preferring).
semlith_neighbors and semlith_symbol take the same cap.
Answers an agent can act on. Paths in answers are relative to the store
root, named once at the top, and semlith_read resolves them — src/lib.rs
no longer matches the fixture copy. A locate row is one line and names the
definition a chunk is about with its start line (search_preferring method
@3295). semlith_read with a symbol name returns each definition whole, and
serves an edited file's current lines from disk, marked, through the same
secret scan. semlith_symbol takes up to 20 names and answers with one row per
definition. semlith_files {tree: true} gives a directory view with counts,
languages, per-file lines, symbols and first definitions, and what is on disk
but not indexed, and why. brief gives its one text span to code for a code
question, labels the others honestly, and leaves Markdown headings out of its
graph lines. Tests rank below product code unless the question names tests,
identical copies collapse into one hit, and semlith_stats collapses its long
tail. semlith_search {exact: true} is grep over the index: every indexed line
matching a regular expression, each file once, each line naming the definition it
sits in, within the same max_tokens budget as a locate answer, the rest as per-file
counts with the offset that continues — also semlith search --exact and the
Search page's exact view. semlith_read of a bare path reads the file, or past
8 000 characters lists its definitions; it used to answer "nothing indexed". A git checkout no longer marks unchanged files stale. A .semlithignore
leaves paths out of a store; this repository's leaves the retrieval corpus copy
out.
Bringing the agent to them. semlith setup sets alwaysLoad on Claude
Code's entry, writes a hook that reads Bash as well as Read, Grep and
Glob and names one concrete semlith call (soft by default; --hook-mode gate
or hard opt-in), a rewritten skill, and a read-only semlith-explorer
research agent. The server instructions name the indexed folders and route by
question. semlith doctor reports all of it, and doctor --fix clears a
per-project disable for the current directory.
The secret scan tells test dummies from keys, and says what it did not index
A match that a declared rule says is a test dummy — a published documentation
example, a body saying EXAMPLE or FAKE or one character repeated, a
private-key header with no key — no longer refuses its file; one live-looking
match anywhere still does. A secret-sounding name assigned a random literal,
quoted or not, now refuses its file too, which catches an AWS secret access key
beside its id. Every file that was not indexed is listed, per store, in five
classes, and a secret carries a 0–100 % estimate that it is real with the
signals behind it. A person — never an agent, never in bulk — can accept one
file at a time, redacted or as-is, from semlith refused accept or the portal's
Index page after a scan; the acceptance remembers salted fingerprints, never
values, and a new secret refuses the file again. A credential file is never
acceptable. Every run opens with a model-free scan phase. semlith index on a
terminal stops for review only when something is the person's to decide; the
portal holds every scan for a look at its plan.
The portal shows the plan before it embeds
The Index page's one button reads Scan: every run stops after its scan
phase and the page shows what it found — files to embed and their size,
unchanged, needing a decision, not indexed, and an estimate — even when nothing
needs a decision. Each held-back file is a row with Accept redacted,
Accept as-is (or Accept) and Keep refused, each accept behind a
confirm with an "I have reviewed this file" tick, and one line counts the files
not indexed that need nothing, with Show files to list them. The button then
reads Start indexing; an undecided file stays refused, and Discard scan
drops the held runs along with a store the scan made for a new folder. The Files page
gains a Decisions tab, which lists only what a person decided — accepted,
refused, or let through as test dummies — each with Revoke or Refuse
instead, and a Tree tab, an editor-style explorer that opens one folder
level at a time, with file icons, lines and symbols, and what is on disk but not
indexed greyed with why; the Indexed tab shows paths relative to the store root.
POST /api/index takes review: "always", a
discarded scan's stop takes delete: true, and /api/files?tree=1&format=json
answers one tree level.
Fixed
- The remaining-time estimate no longer jumps to minutes while a run writes its index, and never more than doubles between polls. Closes [#143].
a_port_something_already_holds_is_seen_as_heldno longer races the rest of the suite. Closes [#141].- The daemon's watcher said
0 indexed at startupfor a catch-up it had only queued; it now says the catch-up was deferred, then what it found. semlith startno longer fails while a terminalsemlith indexis writing one of its stores. That store is named as waiting and opened, watcher and catch-up included, when the run lets go.- Across several stores,
briefnames the store on every span and symbol, and a symbol's edges come from its own store rather than every store defining the name. A root-relativesemlith_readthat two stores both hold is refused naming each, as two roots inside one store already were. - 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;Readis 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_indexforwarded 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. Files left out by.semlithignorecount in the skip total.
Install
macOS and Linux
:::sh
curl -fsSL https://raw.githubusercontent.com/semlith/semlith/main/install.sh | sh
Windows
:::powershell
irm https://raw.githubusercontent.com/semlith/semlith/main/install.ps1 | iex
Or download the archive for your platform below, unpack it, and put
semlith on your PATH. Intel macOS has no prebuilt binary: ONNX
Runtime no longer publishes x86_64 macOS builds.
Verify a download against SHA256SUMS before running it.