Releases: timgordontg/engrim
Release list
engrim 1.3.2 — multi-store merge, negation checks, and review safety
What's New in v1.3.2:
• Multi-Store Merge (engrim merge):
- Fold another SQLite store's records and logs into the current store (
engrim merge OTHER.db). - Idempotent with monotonic status resolution (
superseded/donecarry over and are never reactivated) and content-hash deduplication. - Supports parallel CI jobs and multi-machine agent reconciliation (contributed by @mwpastore).
• Explicit Negation Handling in Capture Checks: - Prevents reversed decisions (e.g. "decided not to use X") from falsely matching existing positive decisions (contributed by @emsilva).
• 0-Session Review State: - Correctly reports review status as unknown when no session logs exist, avoiding false-positive "safe to clear" verdicts on fresh unlogged environments (contributed by @emsilva).
• Full Test Coverage: - 197 passing tests across all components.
engrim 1.3.1 — safe prune, tag filtering, and strict gate mode
What's New in v1.3.1:
• Safe, Opt-In Prune (engrim prune):
- Purge stale transcript logs and reclaim SQLite disk space (
VACUUM). - Off by default: refuses to delete anything without an explicit retention window (
--keep-days <N>) or$ENGRIM_PRUNE_KEEP_DAYS. - Reclaim fragmented space without deleting any logs:
engrim prune --vacuum.
• Tag Filtering on Recall (--tag/--tags): - Filter memories directly by tag:
engrim recall -q "jwt" --tag authorengrim list --tag db. - Full support across CLI and the stdio MCP server tools for Claude Code and Cursor.
• Exit 2 Review Gating (--strict/--gate): - Gate mode:
engrim review --strictexits with code 2 if uncommitted architectural decisions are detected. - Stop hook integration (
ENGRIM_STRICT=1): blocks agents or orchestrators from silently abandoning unpersisted context or clearing before recording.
• Native CLI Version Flag: - Added
-v/--versionto theengrimCLI parser.
• Comprehensive Test Suite: - 136 tests passing (100% green across all platforms).
engrim 1.3.0 — The Universal Cross-Model Memory Standard
Transforming engrim into the universal, local-first episodic memory store across Google Antigravity, Claude Code, Cursor, and Windsurf on the same codebase.
What's New in v1.3.0:
- Universal Multi-Agent Memory: Share project decisions, architecture rationale, and operational state across Antigravity, Claude Code, Cursor MCP, and Windsurf without context drift or memory amnesia.
- Deep Google Antigravity CLI Integration: Built-in adapter (
engrim.adapters.agy) supportinghandle_bootandhandle_stoplifecycle hooks viaengrim hook --agent agy --event boot|stop. - Universal Setup Command: One-command configuration (
engrim setup [--agy|--claude|--cursor|--all|--dry-run]) with auto-detection for installed environments. - Cross-Agent Provenance Tracking: Tracks which agent recorded each memory (
origin_agent:antigravity,claude-code,cursor,cli,user) with automatic backward-compatible schema migration, CLI flags, and clear display annotations. - Hardened MCP Server: Standardized MCP server over JSON-RPC 2.0 (
engrim serve --mcp) exposingengrim_recall,engrim_add,engrim_context, andengrim_review. Zero stdout contamination. - 120 Passing Tests: 100% test pass rate across all legacy and new multi-agent test suites.
engrim 1.2.2 — setup proves the hooks run instead of assuming it
Every hook engrim wires ends in || true, so a bad hook can never break a Claude Code session. The cost of that safety was silence: a completely non-functional install still printed a full column of green checkmarks. That is how the Windows breakage went unnoticed until someone installed fresh and watched nothing happen.
setup now earns its checkmarks. It runs the binary it just wired, through bash, the way Claude Code will — it was the shell quoting that broke, not the binary, so checking it any other way proves nothing. On failure it prints the reason up front, still writes the hooks (a fixed PATH shouldn't also mean re-wiring by hand), and exits non-zero with the failure as its last word.
That last word needed an explicit stdout flush to actually be last. sys.exit writes to unbuffered stderr while the checkmarks go to a stdout that is block-buffered whenever it isn't a terminal — so under a pipe the verdict printed above the checkmarks it was contradicting. Found by piping the failure path, not by reading it.
_git_root now stops at $HOME instead of climbing past it. Climbing made the project tag depend on whatever happened to sit in /home or C:\Users on that particular machine. A repo above $HOME no longer resolves and falls back to the raw cwd tag: coarser, but deterministic everywhere. The home comparison is normcase'd too, or the guard fails open on Windows, where C:\Users\Tim and c:/users/tim are one directory.
settings.json read errors are honest. A permission error or a decode failure under a legacy locale no longer gets reported as invalid JSON, sending you off to fix a file that was never broken.
Verified on Windows, macOS and Linux (Python 3.10–3.13), and by an external tester on a fresh Windows 11 install.
engrim 1.2.1 — runs cleanly on Windows, macOS and Linux
A fresh install on Windows surfaced three failures. All of them were silent: engrim setup
printed five green checkmarks while nothing it wired could actually run.
Fixed
- Hook commands the shell couldn't run.
setupinterpolated the Windows binary path unquoted
into a POSIX command. bash readC:\Users\...\engrim.EXEbackslashes as escapes and the command
collapsed toC:UserstimgoAppData...— not found — and the trailing2>/dev/null || true
swallowed the error. Every hook was a silent no-op. Paths are now forward-slashed and quoted,
which also fixes install paths containing spaces on macOS and Linux. setupduplicated its hooks on every run. The idempotency markerengrim hooknever matched
engrim.EXE hook, so each run appended another hook group. Matching now normalises separators,
quotes and.exe, and still recognises hooks written by earlier versions.- UnicodeEncodeError on every piped command. Windows gives a non-console stdout cp1252, and the
status bar leads with an emoji — sostatusline,contextandstatscrashed on every refresh
while looking perfect in a terminal. stdin had the mirror bug: the minder silently injected
nothing for prompts it couldn't decode. All three streams are UTF-8 now. - Setup crashed on a CLAUDE.md or settings.json containing an emoji (text-mode
open()used the
locale codec) — and reported it as "settings.json is not valid JSON". - Project tags could split one project into two memory buckets on Windows (
C:\pfrom getcwd vs
c:/pfrom a hook payload). Normalised there; POSIX tags are untouched. - The plugin install route was broken end to end on Windows. A venv puts entry points in
Scripts/*.exe; onlybin/was ever checked, so the bootstrap failed its own-xtest and all
four hooks no-opped forever. Both layouts are resolved now. - The plugin and marketplace manifests still pinned 1.1.0 against a shipped 1.2.0, so the plugin
installed a version behind the one being announced.
Root cause
CI was Linux-only. It now runs on Windows and macOS as well, and smoke-tests the commands
through pipes the way Claude Code actually invokes them.
17 new tests (103 total). The 10 that reproduce these bugs fail against the unpatched source.
Nothing changed for existing Linux and macOS installs beyond the quoting fix, which is backward
compatible — re-running engrim setup will not duplicate hooks written by any earlier version.
engrim 1.2.0 — the log records the work, not just the talk
The transcript log kept prose only, which left it too chat-focused. Measured on one real session: 14 KB of visible text against 315 KB of tool traffic — so the record of what was actually done, files changed and releases cut, existed nowhere searchable.
Action lines
Each state-changing tool call now folds into the log as one line:
[changed] src/engrim/cli.py
[ran] Cut the release — gh release create v1.2.0 …
A snippet of value, not the payload: 93 KB of tool calls became ~10 KB of readable spine. Deliberately state-changing only — greps and reads are how you find things, not what you did, and including them buried the signal 4:1.
recall --log
Extraction without reachability is nearly pointless, so recall can now search the transcript alongside curated memory:
engrim recall -q "release.yml" --log
Opt-in, so the two-tier split holds: the log still never auto-loads into context, it's just no longer unreachable when you ask. Plain scan, no FTS table — 21 ms over 44k rows doesn't justify an index or a migration.
Existing history isn't left behind
engrim log --reindex re-derives searchable text from the raw turns already on disk. On the author's store that recovered 2,619 turns across eight projects, in under a second each.
Action lines never trip the ✎ to capture nudge — they're a record of work, not a decision to curate. 86 tests.
engrim 1.1.2 — the status bar stays fast for the whole session
Performance fix for a regression introduced in 1.1.1.
1.1.1's uncaptured-count memo was fingerprinted against the newest log row — and a new row lands every turn. So on a project showing ✎ N to capture, the first status-bar refresh after every single turn paid a full embedding-model load: 1.19s, against 0.07s before 1.1.1. Precisely the wrong trade for the long sessions the nudge exists to serve.
A verdict about "is this snippet already curated?" depends only on the curated side; new log turns are irrelevant to it. Verdicts are now cached against curated state alone, and consulted before an embedder is resolved (resolving is the ~1s, so a lookup after it would save nothing).
Measured after the fix:
| before | after | |
|---|---|---|
| first refresh, new decision | 1.19s | 1.11s |
| every refresh thereafter | 1.19s | 0.07s |
Correctness is unchanged: the nudge persists while a decision is uncaptured and still flips to ✓ clear-safe the moment it's curated, since a curation change drops the cache.
81 tests. Verified under concurrency — 8 simultaneous status refreshes racing 8 log writes on one store, no errors.
engrim 1.1.1 — the clear-safe counter and `review` now agree
Bugfix. The status bar / auto-curate hook and engrim review could report different backlogs for the same store — the hook nudging "N decisions logged but not yet in curated memory" while review said everything was captured.
Two independent causes
- Different captured-checks.
reviewused the semantic check when an embedder is present (cosine ≥ 0.45); the ambient counter was hard-wired to the lexical one (0.6 word overlap). A decision curated in different words read as captured toreviewand uncaptured to the bar — permanently. The nudge could never self-clear, so it accumulated and cried wolf. - Different scan windows.
reviewscanned a flat last-k; the bar used a hybrid lean-window-plus-capture-floor scan. The bar could count turnsreviewnever looked at.
Fix
_is_captured() is now the single definition of "already in curated memory" (lexical or semantic), and _CAPTURE_SCAN the single window. The status bar, the minder's auto-curate nudge, the boot tail and review all route through both — they agree by construction. Capturing a decision in your own words now clears the nudge.
Cost held flat. The lexical tier runs first, so a clear-safe project never loads a model; only a snippet that would nag escalates to the embedder. The count is memoized against a fingerprint of the rows it reads, so the status bar recomputes only when the log or store actually changed.
Also
- Mid-session auto-curate nudge fires at 2 uncaptured decisions instead of 4 — capture belongs at the moment of the decision, since a wrap-time-only habit loses exactly the long sessions worth keeping. Affordable now that the counter can't false-positive.
- Both curate directives now ask for what was measured, not what was concluded — "momentum score is the constant 92.0" ages well; "momentum looks broken" doesn't.
79 tests pass.
engrim 1.1.0 — auto-curate uncaptured decisions
Survives a hard session close. A window closing or a session-limit expiry can't curate itself — no hook fires reliably on a kill. The raw transcript log already survived it (every turn is logged + the next boot sweeps up any orphaned tail); this release closes the loop so the decisions you discussed but never add-ed don't get stranded there.
What's new
- Auto-curation on the next boot. When a prior session left uncaptured decisions, the fresh session's agent is handed a
[⟳ AUTO-CURATE]directive — it runsengrim review+engrim addon the durable survivors before it answers you. Zero user interaction; judgment applied (it skips chatter, reversed calls, and false-positives, keeping the store high-signal). Decision-gated, dedup-safe, and self-limiting — it stops the moment a decision is captured. - Mid-session backstop. A long session that builds a backlog of uncaptured decisions gets the same nudge mid-stream, so you don't have to wait for the next boot. Conservative floor so ordinary work-in-progress never trips it.
- Why not auto-write? A regex writing your memory would pollute the high-signal store. An intelligence writes the record instead — same automation, with judgment.
Housekeeping
- Fixed a stale plugin bootstrap pin (
0.8.1→1.1.0). - README documents auto-curation and softens the "honest list" edge accordingly.
- +5 tests; full suite green.
engrim 1.0.0
First stable release.
Hardened project-scope resolution
-p auto now anchors on a .claude project dir, not just VCS roots — so non-repo workspaces (a data/ops dir with no .git) no longer fall back to the raw cwd. Previously, launching from a subdirectory silently filed records under a sibling scope that the status line and boot pack never read: writes landed, but the counter never moved, so logging looked dead. $HOME is now guarded so a stray ~/.claude can't collapse every loose project under home into one bucket.
- Battle-tests added: non-git
.claudeanchor, nearest-marker-wins (git over an ancestor.claude), and~/.claudenever becoming a catch-all. Full suite 67 passed. - Version unified to 1.0.0 across the package, plugin manifest, and marketplace.
🤖 Generated with Claude Code