Repository navigation
Releases: dburriss/eru
Release list
v0.14.0
Added
- Ranked search powered by Ferret.
eru searchwith terms and the MCPsearch_knowledgetool now rank files by content (BM25: rarer terms count more, matches in the path, headings and front matter count extra, word forms match, somockfindsmocked) and return the best first. One engine now serveseru search, the MCP tool and theeru serve/api/searchendpoint, so their rules no longer differ search_knowledgetakes an optionallimit(default 15) andmode, caps each file at three excerpt lines, and returnstruncated, per-hitscoreandwarningsin its structured result.eru searchgains--limitand--mode lex|sem|hybridand prints scores- Optional semantic and hybrid search (
sem,hybrid) with a local embedding model (bge-small-en-v1.5, about 33 MB, no service). Choose withsearch.mode,ERU_SEARCH_MODE,--modeor the MCPmodeparameter. The model is never downloaded during an MCP search: the server fetches it in the background, and until thensemandhybridrunlexand say so inwarnings.eru search --mode hybridrunslexfirst and then downloads the model for next time.FERRET_OFFLINE=1,FERRET_MODEL_DIRandFERRET_MODEL_URLcontrol the download search.ignorePatternsconfig (default["index.md", "log.md"]): matching files are never searched, so a generatedindex.mdno longer duplicates its README. READMEs stay searchable, unlikesite.ignorePatterns.search.mode(defaultlex) andsearch.ignorePatternsare managed witheru configeru browseFiles pane: pressing Enter on a search filter now runs the same ranked content search in the background and lists the best matches first (#tagfilters and the instant as-you-type narrowing are unchanged)eru source add --scan --exclude <glob>(repeatable) skips OKF bundles whose directory matches the glob; excluding the root bundle registers its nested bundles insteadokf.fixTypes(an ordered list of{pattern, type}globs) andokf.defaultTypeconfig settings:eru okf fixtypes untyped files by glob, including READMEs, and--default-typenow overrides a matching rule- Root
apm.ymlso eru can be installed as an APM package (apm install dburriss/eru): theeru,semantic-searchandorganizing-documentationskills plus theingestoragent and theeruMCP server
Changed
- The built-in search backends (simple scan, per-file word index and the
ckprocess) are removed in favour of Ferret.ERU_SEARCH_BACKENDis deprecated and only mapped:cknow meanshybrid, any other valuelex, with a warning on stderr.eru syncno longer builds a per-file word index; search indexes are built on first use and by the MCP server in the background, under~/.cache/eru/ferret(eru cache clearremoves them and the old~/.cache/eru/index) eru search <terms>now matches file content, not only path and description, and its--output jsonentries gainpath,hash,scoreandexcerpts(sourceNameandremotePatharenullfor local files). The MCPsearch_knowledgestructured result is now{ hits, truncated, warnings }in camelCase, as its output schema already advertised, instead of PascalCaseHits- Release binaries carry ONNX Runtime for semantic search (about 45 MB more per platform; it is unpacked on first run)
- A
README.mdwith a frontmattertypeis now a concept:eru okf validate,fixandverifyhandle it like any other concept, it is listed in generated catalogs and discovered with its metadata. A README without atypeis still skipped.eru sitestill hides READMEs by default throughsite.ignorePatterns
Fixed
- Files in a local
knowledge/directory were listed twice by search on case-insensitive file systems (macOS, Windows) - Table output no longer crashes (
Could not find color or style 'Go') when a path, message or description contains square brackets, e.g. everyeru okf validatebroken-link warning; table cells are now rendered literally in all commands
v0.13.1
Fixed
eru siterewrites relative Markdown links in document bodies (explanation.md,./x.md#anchor,../other/x.md) to the generated page; links to unindexed files, external links and code are left as written
v0.13.0
Added
eru configinspects and manages configuration:listshows the global and local config files with their paths and versions,viewshows the effective config with the origin (local,globalordefault) of each value,get <key>shows one setting,set <key> <json-value> [--global] [--unset]edits a setting (validated before writing, files left untouched on error) andmigrate [--local|--global] [--dryrun]rewrites an older config as version 3, keeping a.bakof the original- Configurable generated site. Every page is built from four slots (
top,left,right,main) of widgets, set undersite.layout(site-wide) and per page; a slot is an ordered list orfalse. Widgets:breadcrumbs,title,meta,verified,generated,description,tags,stale,cli,content,list,toc,related,graph,facets,links site.pagesdefines custom pages atpages/<id>/index.html: afilter(bysource,bundle,type,tag,status,ext,pathglobs,stale, withnot) withsort,group,limitandopen(page,resourceorsource), acontentpage rendering a repo Markdown file (content.file) or an indexed document (content.doc), or both. The built-in pages (browse,sources,tags,types,bundles) can be dropped withfalseor overridden by a page of the same id, andsite.homepicks the page atindex.html- Three list views,
cards,listandtable, chosen withsite.defaultViewor a page'sview;site.cards.columns(1-6) sets the card grid's maximum columns. Table headers sort when JavaScript is available site.documentconfigures document pages:layoutfor every document andrulesthat match ontype,tag,bundle,sourceand the other filter fields, so different documents get different layouts. Theverifiedwidget shows the trust tier with each verifier and date;generatedshows who or what generated a document and wheneru site serverebuilds when a local Markdown file used by a content page changes- Site config errors (unknown page or widget, a widget in a slot it is not valid in, a bad view or column, a missing or out-of-repo content file) fail with a message naming the key; a failed rebuild writes nothing, so
eru site servekeeps serving the last good build
Changed
-
Breaking: the generated site has refreshed defaults. Every page gets a facet column on the left and, when it has headings or links, a table of contents on the right; lists are a card grid of up to three columns; the top nav is built from the pages that exist. Document pages are rebuilt from widgets, and the default document layout shows the link graph at the top of the page and the linked-document lists at the bottom. To get close to the old look, set
site.layout.leftandsite.layout.righttofalseandsite.cards.columnsto1 -
Browse filtering is driven by markup instead of per-list ids: any element marked
data-docis filterable,data-<facet>attributes hold its values as JSON arrays anddata-facet="<name>"on a sidebar list makes it a filter. Types and bundles are now checkbox facets on Browse. Custom CSS or scripts that relied on#file-list,#file-countor thesource-filters,ext-filtersandtag-filtersids need updating -
The page-level
SiteFeaturesflagsTagPagesandSourcePagesare removed fromGenerateOptions; drop pages withsite.pages.<id>: falseinstead (typesandbundleswere previously tied toTagPages) -
Breaking: config files are now version 3. Settings are grouped into top-level sections, shared by
~/.config/eru/config.jsonand.eru/config.json, and thesettings/defaultsblocks are removed. Section names are singular and the entities a section holds always live underitems. Version 1 and 2 files are migrated automatically when read and rewritten as version 3 only on the next save (read-only commands leave the file untouched); newly created configs are written as version 3Version 2 Version 3 siteIgnorePatternssite.ignorePatternssiteHideEmptyBundlessite.hideEmptyBundlesokfIgnorePatternsokf.ignorePatternsmcpRefreshIntervalMinutesmcp.refreshIntervalMinutesbranch,commitOnPull,stateFilesync.branch,sync.commitOnPull,sync.stateFileblockPatterns,allowPatterns,allowBinariesfiles.blockPatterns,files.allowPatterns,files.allowBinariesdefaultInbox,inboxWatchIntervalSecondsinbox.default,inbox.watchIntervalSecondsinboxes/defaultInboxesinbox.itemssources/defaultSourcessource.itemscollectionscollection.items -
Every settings section is now valid in both the global and the local file, merging local-over-global per key.
sync.stateFilewas previously local-only, andsync.branchandmcp.refreshIntervalMinutesglobal-only -
eru inbox defaultwritesinbox.default
Fixed
- Reading a version 1 config (sources with
basePath) migratesbasePathto amanifestbundle instead of dropping it
v0.12.0
Added
eru print <source:path|hash>prints a document's contents to stdout (-o jsonfor{source, path, hash, content}). It resolves from the source indexes, so documents need not be added first, and reads the local file, then the cache, then a live fetch. A 3-8 character path hash that matches several documents errors and lists the candidates
v0.11.1
Fixed
eru syncre-runs OKF bundle discovery when a source's index has no entries, even if the remote HEAD SHA is unchanged; previously an empty index with a current SHA stayed empty (0 entries indexed) until the remote moved. This recovers indexes left empty by builds from before "Do not empty index on failed sync"
v0.11.0
Added
-
eru site generateadds a Bundles tab after Types:bundles/index.htmllists every registered bundle with its kind and file count, andbundles/<source>/<path>/index.htmllists one bundle's files. A file appears under its most specific bundle only. Bundles are named<source>(root) or<source>/<path>, so nested bundles are namespaced by their parents. The Browse sidebar gains a Bundles section anddata/documents.jsoncarries abundlefield -
siteHideEmptyBundlessetting (defaultfalse): whentrue,eru site generateleaves bundles with no listed files out of the Bundles tab and Browse sidebar -
eru source add --scan --nestedkeeps nested OKF bundles instead of letting a root bundle cover them -
eru syncreports the index size per source (norms: 69 entries indexed (okf:/)) and warns on stderr when a source indexed nothing, saying whether bundles are missing or OKF concept files lack atype;--output jsongains anindexesarray
Changed
eru syncno longer walks an OKF bundle that is nested under another OKF bundle it already walked
Fixed
eru syncno longer empties the index of OKF-bundle sources: the first sync after adding one populated it, but every later sync wiped it while the unchanged remote HEAD skipped rediscovery, so search found nothing. Discovered entries now persist between syncs, are pruned only when the remote changes and the re-walk succeeds, and a failed re-walk keeps the previous entries
v0.10.0
Added
eru inbox default <name>setssettings.defaultInbox(-gfor global).eru okf validatewarns on broken links in concept andindex.mdfiles:broken-link,broken-image,broken-wikilinkandbroken-anchor(heading missing from the target note; GitHub-style and generated-site anchors both accepted), each with its line number and the link as written. They never change the exit code unless--strict-linksis given, which reports them as violations. The ingestor template now writes self-contained notes and rewrites links that point outside the bundle
Changed
eru inbox channel addno longer copies the agent onto adefaultchannel; it sets the inbox'sdefaultChannelto the new channel when none is seteru inbox processarchives tracked items withgit mv(FsForge 0.0.1GitOps.moveFile), so the archive shows as staged renames; untracked items and non-git directories still get a plain move
v0.9.1
Fixed
- Path handling on Windows: domain code built and split
/-separated bundle and remote paths withSystem.IO.Path, which emits\on Windows and broke 69 tests in the release build; it now uses/-only helpers, and a test guards against reintroducingPath.Combine/GetDirectoryName/GetFileNameinEru.Domain
v0.9.0
Added
eru source add --scandetects OKF bundles (anyindex.mdwithokf_version; a root marker covers nested ones) and falls back to theknowledge/convention. Breaking: without--scan,eru source addno longer auto-detects theknowledge/bundle; register bundles witheru source bundle add- OKF bundle discovery (and so
eru site generate) now indexes only concept files that have a non-emptytypefrontmatter; untyped markdown is skipped eru okf verify <file>records a{ by, at }confirmation in a concept file'sverifiedlist (--bydefaults tohuman:<git user.email>,--atto now);eru okf fixnow strips a malformedverified(placeholders likeunknown/false, entries missingby/at), keeping valid entries;eru okf validatewarns on placeholderverifiedvalues andby: unknown, pointing atfixandverify- OKF v0.2 alignment:
eru okf init/fixwriteokf_version: "0.2";eru okf validatereports non-fatal v0.2 shape warnings (generated,verified,stale_after,status,sources, legacytimestamp,log.mdorder); eru readssourcesand falls back to a legacytimestampwhengeneratedis absent; the ingestor agent template now writes spec-shapedgenerated/sourcesand omitsverifieduntil a human reviews;eru inbox sendquotesresourcein its frontmatter eru okf init <path>creates missingindex.mdfiles (root withokf_version, plus a catalog table per folder), never overwriting;eru okf fix <path>repairs a tree soeru okf validatepasses (index frontmatter, missing concept frontmatter/type, non-ISOlog.mddate headings, missing indexes). Both write by default;--dry-runpreviews,--default-typesets the type for untyped conceptseru source bundle addwarns when a bundle is auto-detected asmanifestbut has no.eru/manifest.json, listing the ways to fix it (addokf_versiontoindex.md, pass--kind okf, or create a manifest);eru source adddoes the same for a detectedKNOWLEDGE/bundleeru okf validate: the bundle-rootindex.mdfrontmatter message now explains that it should contain onlyokf_version, which is what makes eru detect an OKF bundleREADME.mdand dot-directories (.github,.claude,.agents, …) are no longer treated as OKF concepts: they are skipped byeru okf validateand OKF bundle discoverysiteIgnorePatternsnow defaults toindex.md,log.mdandREADME.md(configs with an explicit value are unchanged)okfIgnorePatternssetting (defaultapm_modules/**,inbox/**,node_modules/**) to skip paths during OKF bundle discovery anderu okf validateeru versioncommand prints the version and the git commit it was built from- Added description field to the manifest
- Remote git inboxes:
eru inbox add <name> <git-url> [--branch]registers a repo as an inbox anderu inbox sendclones it shallowly, commits the item and pushes (via FsForge); remote inboxes are send-only - Added
eru site servecommand to serve the generated static site locally with live reload on changes to the cache eru okf validate <path>command to check a directory tree for OKF §11 conformance (parseable frontmatter with a non-emptytype, validindex.md/log.mdstructure); never flags unknown types, unknown extra keys, broken cross-links, or missing optional fields- Generated site now surfaces OKF frontmatter: a trust-tier badge per file (
unverified/machine-confirmed/human-reviewed, derived fromverified[].by) and a new "Types" filter/browse page alongside the existing Sources and Tags - Added
SiteIgnorePatternwith default values of "index.md" and "log.md" to ignore OKF structure files when generating site pages - OKF bundle discovery on sources
eru inboxcommands for handling inboxes/channels and sending to inboxeseru inbox processcommand to run pending inbox items through their channel's configured ACP agent, archiving processed items; supports--inbox,--channel,--item,--all,--dryrun, and--output;--debugalso reports per-item agent handshake timings (initialize/session-new/prompt)eru inbox watchcommand to watch an inbox's raw directory and automatically runinbox processon new items, debounced and also polled on a configurable interval (--interval, default from config); supports--dryrunand--debug--agent-timeoutoption oneru inbox channel addto bound how long an ACP agent call may run; the timeout is a liveness check (reset on any agent activity) rather than a fixed deadline- ACP agent output is streamed as it arrives instead of only being shown once the call completes
eru inbox processnow falls back further when a channel has no--agent-instructionsconfigured and<inbox>/.agents/agents/ingestor.mddoesn't exist: it checks a tool-specific convention path derived from--agent-command(e.g..claude/agents/ingestor.mdforclaude), and finally falls back to eru's own built-in curation instructions — so a channel's agent always receives some curation instructions--append <text|@file>(repeatable) oneru inbox processanderu inbox watchadds text to the agent prompt after the resolved instructions and before the item; a leading@reads a file,@@is a literal@
Changed
- Built-in ingestor instructions (
agents/ingestor.agent.md) now produce a valid OKF bundle: folderindex.mdfiles get no frontmatter, the rootindex.mdcarries onlyokf_version,README.mdis treated as outside the bundle, and the agent useseru okf initfor new folders anderu okf validate/fixas a final self-check - Built-in ingestor instructions (
agents/ingestor.agent.md) no longer loop untilinbox/raw/is empty; the agent processes only the items it is told to (byeru, a harness prompt, or a workflow) and asks if none are specified - Built-in ingestor instructions (
agents/ingestor.agent.md) no longer include a commit step, so they stay neutral across environments; use--appendto add commit/PR behaviour eru manifest verifyrenamed toeru manifest validate;verifyis kept as a backward-compatible aliaseru addgives a clearer error when passed a bare repo URL, suggestingeru source add <url>followed byeru add <source>:<path>- Unhandled exceptions now print a concise
eru: unexpected error: <message>instead of a raw stack trace; pass--debugto see the full stack trace
Fixed
- OKF bundle discovery no longer fails when a source has no branch configured
- Pinned the test runner via
global.json(Microsoft.Testing.Platform) to fixdotnet testdiscovery
v0.7.1
Fixed
- MCP resources now declare
text/plainMIME type — previously the SDK defaulted toapplication/octet-stream, causing many MCP clients and inspectors to not display theeru://sources,eru://sources/{name}, anderu://installedresources