Skip to content

Releases: rohitg00/agentmemory

v0.9.17 — OpenAI-compat provider + telemetry id + Compare polish

Choose a tag to compare

@rohitg00 rohitg00 released this 16 May 19:37
3a3f866

OpenAI-compatible LLM provider lands the universal-adapter shape — one config (OPENAI_API_KEY + OPENAI_BASE_URL + OPENAI_MODEL) covers OpenAI, Azure OpenAI (auto-detected from hostname), DeepSeek, SiliconFlow, vLLM, LM Studio, Ollama (via /v1), and any future endpoint mirroring POST /v1/chat/completions. Worker telemetry now pins a stable project_name so engine metrics + traces attribute cleanly. agent-memory.dev Compare section no longer wraps awkwardly.

Added

  • OpenAI-compatible LLM provider (#307, @fatinghenji). Closes #185, #232 (Ollama works via OPENAI_BASE_URL=http://localhost:11434/v1), #312, supersedes #240.

  • Azure OpenAI auto-detection. .openai.azure.com hostname → swaps Authorization: Bearer for api-key, drops /v1 path prefix, appends api-version=<version> query (default 2024-08-01-preview, override via OPENAI_API_VERSION).

  • OPENAI_TIMEOUT_MS env var. AbortController-bounded fetch, default 60s, clear timeout error with the env-var hint. Other raw-fetch providers tracked in #373.

  • OPENAI_REASONING_EFFORT passthrough. Forwarded as reasoning_effort on the request body for OpenAI reasoning models (o1, o3, gpt-*-reasoning) and providers that mirror that schema. Standard chat models reject the field with 400 — README documents the caveat. Falls back to message.reasoning when message.content is empty (Ollama Cloud thinking-model shape).

Changed

  • telemetry.project_name pinned to "agentmemory" (#426). iii-sdk auto-detection produces inconsistent identifiers per host (agentmemory, node, npm, occasionally the user's home dir basename via npx). Pinning gives every install the same stable identifier in engine metrics + traces. Also pins language and framework.

  • OPENAI_API_KEY_FOR_LLM=false opt-out. detectLlmProviderKind now mirrors detectProvider's existing gate — users who set OPENAI_API_KEY only for embeddings won't see the LLM auto-activate. README leads with an explicit shared-use callout.

  • Compare section (#427). Title AGENTMEMORY VS. THE FIELD.VS. THE FIELD. (eyebrow already says VS.). text-wrap: balance globally on .section-title. NATIVE PLUGINS cell 6 (Claude/Codex/OpenClaw/Hermes/pi/OpenHuman)6 (names already shown in Agents grid). Row grid rebalanced + word-break: break-word + 24px padding so cells like YES (APACHE-2.0) have breathing room.

Install

npm install -g @agentmemory/agentmemory@0.9.17
agentmemory

Try with any OpenAI-compatible endpoint:

# Standard OpenAI
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-mini

# DeepSeek
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.deepseek.com
OPENAI_MODEL=deepseek-chat

# Local Ollama
OPENAI_API_KEY=ollama
OPENAI_BASE_URL=http://localhost:11434/v1
OPENAI_MODEL=llama3.1:8b

# Azure (auto-detected by hostname)
OPENAI_API_KEY=...
OPENAI_BASE_URL=https://my-resource.openai.azure.com/openai/deployments/gpt-4o
OPENAI_API_VERSION=2024-08-01-preview

Full changelog: https://github.com/rohitg00/agentmemory/blob/main/CHANGELOG.md#0917--2026-05-16

v0.9.16 — DevEx polish + agent-memory.dev refresh

Choose a tag to compare

@rohitg00 rohitg00 released this 15 May 18:59
b7e1240

Two waves: (1) DevEx polish on top of v0.9.15 — 5-port ready panel, iii console install, interactive global-install prompt, onboarding now actually wires the agents you select, MCP reworded as opt-in. (2) Marketing site refresh — new AS FEATURED IN bar (AlphaSignal · Agentic AI Foundation · Trendshift) + Agents/Compare/CommandCenter/Hero updated for the v0.9.15 surface.

Added

  • 5-port ready panel (#410). Single clack note replaces the old single-line ready hint. Lists REST / Viewer / Streams / Engine / iii console — all derived from configured env vars (AGENTMEMORY_URL, III_*_PORT, III_ENGINE_URL), not hardcoded localhost.

  • iii console install probe + auto-install (#410). ensureIiiConsole() detects the binary on PATH or ~/.local/bin/iii-console. If missing on a TTY, prompts to run curl -fsSL https://install.iii.dev/console/main/install.sh | sh. Console is first-class.

  • Interactive global-install prompt (#410). First npx run asks Install agentmemory globally so agentmemory works in any shell? [Y/n]. Yes runs npm install -g @agentmemory/agentmemory@<VERSION> inline. No writes skipGlobalInstall: true to preferences. Fixes the v0.9.15 footgun where agentmemory stop in a new shell hit command not found.

  • Onboarding wires selected agents inline (#408). After the multi-select step, asks Wire these agents now? [Y/n] and dispatches each through the same runAdapter the explicit agentmemory connect uses. Successes + failures bucketed in a summary block.

  • Memory-share callout (#408). Between multi-select and provider step: All selected agents share the same memory at :3111. A memory saved by Claude Code is visible to Codex + Cursor instantly.

  • AS FEATURED IN bar on agent-memory.dev (#415). New FeaturedIn component between Hero and Stats. Three cards with real brand marks: AlphaSignal (180K subs), Agentic AI Foundation (Linux Foundation backed), Trendshift (live badge endpoint).

Changed

  • MCP messaging reworded as opt-in (#409). Endpoints summary now reads REST first (REST API: 121 endpoints at ...) with a second line for MCP (MCP surface (opt-in via npx @agentmemory/mcp): 51 tools · 6 resources · 3 prompts). Each connect adapter prints a protocol-note line explaining which surface it's wiring.

  • CLI --help mcp description (#409). Now reads Start standalone MCP shim — opt-in surface for MCP-only clients (Cursor, Gemini CLI, etc). REST always available at :3111.

  • Engine version-mismatch warning (#410). Was hardcoded v0.9.14+. Now uses ${VERSION} so the string never lies post-release.

  • CommandCenter — iii console (#415). OPTIONALFIRST-CLASS. Bullet counts bumped to 121 HTTP endpoints to match generated-meta.json.

  • Compare table (#415). MCP TOOLS 44 → 51. New REST ENDPOINTS (121) and NATIVE PLUGINS (6 first-party agents) rows.

  • Agents grid (#415). FOUR → SIX first-party (added pi + OpenHuman). Codex CLI now reads NATIVE PLUGIN (has hooks).

  • Hero CTA (#415). START IN 60 SECONDSSTART IN 30 SECONDS.

Fixed

  • CLI no longer kills its own parent process. lsof -i :PORT -t returns client PIDs alongside the LISTEN-socket owner — including the CLI's keep-alive fetch. Now restricts to -sTCP:LISTEN and filters process.pid.

  • Splash banner ASCII (#411). Broken middle glyphs (_ _ instead of _ __ around the 'n') replaced with verified figlet agentmemory standard-font output. 70 cols × 6 rows.

  • README install hoisted to top (#411). Install section moved from line 306 to the top under the nav anchors. 4-line block leading with npm install -g. Quick Start kept below.

Install

npx @agentmemory/agentmemory@0.9.16
# or — recommended:
npm install -g @agentmemory/agentmemory@0.9.16
agentmemory

Full changelog: https://github.com/rohitg00/agentmemory/blob/main/CHANGELOG.md#0916--2026-05-15

v0.9.15 — DevEx overhaul

Choose a tag to compare

@rohitg00 rohitg00 released this 15 May 15:43
c3a613a

DevEx overhaul. Four PRs landed simultaneously rebuilding the first-run experience to SkillKit-grade polish.

Added

  • Splash banner + onboarding wizard (#403). Terminal-width-aware ASCII (full at ≥120 cols, compact at 80–119, single-line below 80). First-run flow: multi-select 8 native-plugin agents + 8 MCP-server agents, single-select LLM provider (Anthropic / OpenAI / Gemini / OpenRouter / MiniMax / BM25-only), seeds ~/.agentmemory/.env with the chosen provider's *_API_KEY= line commented.

  • ~/.agentmemory/preferences.json (#403). Schema-versioned JSON with smart defaults. Atomic write. Future runs skip the splash.

  • agentmemory connect <agent> (#402). Automates native-plugin install for claude-code, codex, cursor, gemini-cli, openclaw end-to-end. Stubs for hermes, pi, openhuman. Each adapter: detect → backup → merge → verify → idempotent on re-run. Supports --dry-run, --force, --all, interactive picker.

  • agentmemory remove (#406). Tears down everything we installed: pidfile, state, preferences, backups, ~/.local/bin/iii (only when it matches our installed version), agent connections. Asks separately for .env and memory data dir. Two confirmations by default.

  • agentmemory doctor v2 (#406). Interactive Fix/Skip/More/Quit per finding. New flags: --all (auto-fix every finding, for CI), --dry-run.

  • agentmemory stop --force (#405). Bypasses Docker-compose heuristic refusal so engines started before v0.9.14 can be torn down without lsof | xargs kill.

  • --reset flag. Wipes preferences, re-runs onboarding.

  • --verbose / AGENTMEMORY_VERBOSE=1. Restores the pre-v0.9.15 25-line [agentmemory] X engine-boot log stream when debugging.

Changed

  • First-run output trimmed from 30+ lines to ~10. The [agentmemory] Worker v0.9.x boot log stream is buffered behind a bootLog shim and only surfaces with --verbose.

  • isEngineRunning() short-circuit now adopts the engine (#405). When the CLI finds an existing engine on :3111, it writes ~/.agentmemory/iii.pid and ~/.agentmemory/engine-state.json if neither exists. Closes the migration gap where pre-v0.9.14 engines could not be stopped via agentmemory stop.

  • Viewer port auto-bump (#405). :3113 taken → retry 3114 → 3115 → ... up to 3122 before failing loud. Pre-fix was silent skip.

  • Engine version-mismatch warning (#405). iii on PATH != IIPINNED_VERSION (v0.11.2) now warns loud with override path. Pre-fix was silent acceptance — v0.11.6 on PATH led to undebuggable EPIPE loops.

  • npx PATH hint (#405). Runs invoked via npx get one extra line after engine ready: Tip: install globally for the bare \agentmemory` command: npm install -g @agentmemory/agentmemory. Suppressible via preferences.skipNpxHint`.

Install

npx @agentmemory/agentmemory@0.9.15
# or
npm install -g @agentmemory/agentmemory@0.9.15
agentmemory

Full changelog: https://github.com/rohitg00/agentmemory/blob/main/CHANGELOG.md#0915--2026-05-15

v0.9.14 — CLI installer first + agentmemory stop

Choose a tag to compare

@rohitg00 rohitg00 released this 15 May 14:12
372c6a6

CLI bootstrap rework so npx @agentmemory/agentmemory stops failing on Rancher Desktop and other Docker-shim daemons. The native iii-engine binary is now the first-class start path; Docker becomes opt-in. Also ships agentmemory stop so engines started in the background can be torn down without lsof | xargs kill. README agents grid reorders OpenHuman next to the other native-integration agents.

Added

  • agentmemory stop command (#396). Reads ~/.agentmemory/iii.pid first, falls back to lsof -i :PORT -sTCP:LISTEN -t, sends SIGTERM, waits 3s, escalates to SIGKILL. State file (~/.agentmemory/engine-state.json) records whether the engine was started natively or via docker compose up -d, so stop runs docker compose -f <file> down for Docker engines instead of signaling the host's Docker socket proxy by accident.

  • AGENTMEMORY_USE_DOCKER=1 env var. Opt-in path for users who want the bundled docker-compose.yml to keep handling iii-engine lifecycle. Without it, the CLI prefers the native binary in ~/.local/bin/iii.

Changed

  • startEngine() fallback order rewritten (#396). New tier order: (1) iii on PATH, (2) ~/.local/bin/iii or fallback paths, (3) interactive clack p.select with three choices — auto-install the pinned v0.11.2 binary, use Docker compose, or print manual install instructions and exit, (4) Docker compose only via explicit opt-in or the post-install failure fallback, (5) fail-loud with install instructions. CI / non-TTY environments auto-pick install. The Docker fallback was tier 2 and silently fired on every cold start; on Rancher Desktop docker compose up -d returns 0 even when the daemon's pull silently fails, which produced "engine started but REST never responded" misdiagnoses.

  • Installer logic extracted from runUpgrade into runIiiInstaller(). Both first-run and agentmemory upgrade now share the same pinned-v0.11.2 curl-and-tar path.

  • README agents grid reordered (#397). Row 1 is now Claude Code → Codex CLI → OpenClaw → Hermes → pi → OpenHuman → Cursor → Gemini CLI.

Fixed

  • CLI no longer kills its own parent process. lsof -i :PORT -t returns every PID with an active TCP connection to the port, including the CLI's own keep-alive fetch() from isEngineRunning(). Without a LISTEN filter, agentmemory stop would SIGKILL itself — exit code 137, state files never cleaned up. Now filters to -sTCP:LISTEN and drops process.pid from the candidate set.

  • agentmemory stop no longer clears the pidfile when a stale process holds the port. Pre-fix behaviour cleared the pidfile and printed "Nothing to stop" — the next run would silently start a second engine on a port that the first engine still owns. Now preserves the pidfile and surfaces the live PIDs.

  • Docker-started engines stop safely. Pre-fix code called findEnginePidsByPort and signaled whatever held :3111. When the engine was started via docker compose up -d, that's the host's Docker socket proxy, not the engine — killing it took down Docker Desktop networking for every other container. The new state file lets runStop detect Docker-managed engines and run docker compose down instead.

Install

npx @agentmemory/agentmemory@0.9.14

Or pin in package.json:

"@agentmemory/agentmemory": "0.9.14"

Full changelog: https://github.com/rohitg00/agentmemory/blob/main/CHANGELOG.md#0914--2026-05-15

v0.9.13

Choose a tag to compare

@rohitg00 rohitg00 released this 15 May 09:15
8b98432

Six PRs landed since v0.9.12 — .env.example discovery shipped (#372), CJK BM25 tokenizer landed (#344 / PR #362), benchmark/load-100k.ts load harness landed (#346 / PR #363), one-click deploy templates for fly.io / Railway / Render / Coolify added (#343 / PR #361), Gemini provider defaults moved to current GA models (#246 + #368 / PR #370), and the in-tree Python ecosystem story switched from a duplicate REST client to a one-page iii-sdk example (#342 / PR #364). Plus 14 Dependabot security advisories closed via Next.js + PostCSS bumps.

Contributors

Huge thanks to three external contributors this release:

  • @fatinghenji — pre-cleanup work on the OpenAI-compatible LLM provider (PR #240 / PR #307); the universal-adapter shape will land in the next minor once branch maintenance catches up
  • @AmmarSaleh50 — Gemini embedding migration with L2-norm + 768-dim plumbing (PR #246, folded into PR #370)
  • @yut304 — Gemini LLM default deprecation fix (PR #368, folded into PR #370)

Added

.env.example at repo root + bundled in the npm tarball (#383, closes #372, #47, #293, partial #233)

Every env var actually read by src/ is now documented in one place, grouped by surface: LLM provider, embedding provider, auth, search tuning, behaviour flags, CLI runtime, ports, iii engine pin, Claude Code bridge, Obsidian export. Every line is commented out by default so the file ships as a config template, not a config. The npm package now lists .env.example in its files field so npm i -g @agentmemory/agentmemory carries it.

New agentmemory init CLI command copies the bundled template to ~/.agentmemory/.env if absent; refuses to overwrite an existing config and prints a diff command pointing at the latest template. The exists-check + copy is now a single atomic copyFile(template, target, COPYFILE_EXCL) so two parallel init runs cannot race.

New scripts/check-env-example.mjs CI sync-checker walks every .ts / .mts / .mjs / .js file under src/ and fails CI when the runtime reads an env var the template doesn't document (or vice versa). Plugged into .github/workflows/ci.yml after npm test. Initial bootstrap: 60 keys in sync.

CJK tokenizer for BM25 search (#362, closes #344)

New src/state/cjk-segmenter.ts detects CJK input by Unicode block and routes to @node-rs/jieba (Chinese, native, no model download), tiny-segmenter (Japanese, pure JS, ~25 KB), or rule-based syllable-block split (Korean). Both segmenters declared in optionalDependencies so the base install stays lean; soft-fail with a one-time stderr hint when the dep is missing. Order-preserving single-pass tokenization across mixed CJK + non-CJK runs — regression test for "abc 메모리 def 项目 ghi" returns ["abc","메모리","def","项目","ghi"].

benchmark/load-100k.ts load harness (#363, closes #346)

Hand-rolled, dependency-free harness that seeds N synthetic memories against a local daemon at http://localhost:3111 and records p50 / p90 / p99 latency + throughput for POST /agentmemory/remember, POST /agentmemory/smart-search, and GET /agentmemory/memories?latest=true across the matrix N ∈ {1k, 10k, 100k} × concurrency C ∈ {1, 10, 100}. Content drawn from a seedable mulberry32 PRNG so re-running against the same build produces the same seed corpus. Results land in benchmark/results/load-100k-<short-git-sha>.json. Wired as npm run bench:load.

One-click deploy templates: fly.io / Railway / Render / Coolify (#361, closes #343)

Each template under deploy/<platform>/ ships a multi-stage Dockerfile that COPY --from=iiidev/iii:0.11.2s the engine binary into a node:22-slim runtime, npm-installs @agentmemory/agentmemory under /opt/agentmemory with iii-sdk pinned via package.json overrides (avoids the caret-resolves-to-0.11.6 drift), and runs an entrypoint that rewrites the bundled iii-config.yaml to bind 0.0.0.0 + use absolute /data paths, chowns the platform-mounted volume to node:node via gosu, generates a first-boot HMAC secret, and exec's the agentmemory CLI as the unprivileged node user under tini (with TINI_SUBREAPER=1). Verified end-to-end on fly.io (machine in iad, 1 GB volume, healthcheck passing). Coolify template uses expose: instead of ports: so Traefik handles TLS termination + domain routing.

examples/python/ quickstart via iii-sdk (#364, closes #342)

Quickstart + observation/recall flow showing iii-sdk (Python) calling mem::remember / mem::smart-search / mem::context directly over ws://localhost:49134. Replaces a duplicate-transport Python REST client (initial PR #360, closed) with a single-SDK story — the same iii-sdk install (pip install iii-sdk / cargo add iii-sdk / npm install iii-sdk) talks to every agentmemory function from any language.

Changed

Gemini provider defaults bumped to current GA models (#370, closes #368, #246)

LLM default gemini-2.0-flashgemini-2.5-flash (the gemini-flash-latest moving alias was rejected — production behaviour should be deterministic from a release perspective).

Embedding default text-embedding-004gemini-embedding-001 (the previous default is deprecated and shuts down 2026-01-14 per ai.google.dev/gemini-api/docs/deprecations). Three implementation details ride along:

  1. URL path :batchEmbedContent:batchEmbedContents (plural — the new model's batch endpoint).
  2. Every request now sends outputDimensionality: 768 so the returned vectors match GeminiEmbeddingProvider.dimensions = 768 and the index-restore dim guard from #248 — no reindex needed for existing users.
  3. Returned vectors are L2-normalized before the result-array push because gemini-embedding-001 does not normalize by default unlike text-embedding-004 — without this the downstream cosine-similarity math silently collapses recall. l2Normalize warns once on a zero-norm embedding so operators can correlate index quality dips with upstream regressions.

Security

14 open Dependabot advisories closed via Next.js + PostCSS bumps (#348)

13 Next.js advisories closed: middleware/proxy bypass, SSRF on WebSocket upgrades, DoS via connection exhaustion, CSP-nonce XSS, image-opt DoS, RSC cache poisoning, beforeInteractive XSS, and segment-prefetch routes — by bumping the website's Next.js to ^16.2.6. The PostCSS XSS-via-unescaped-</style> advisory closed by pinning to ^8.5.10 via overrides in website/package.json. Verified npm audit --omit=dev returns 0 and npm run build clean on Next 16.2.6.

Dependabot now runs weekly against six update streams (npm × 5 paths + github-actions) per the new .github/dependabot.yml.

Install / upgrade

npm i -g @agentmemory/agentmemory@0.9.13
# or
npx @agentmemory/agentmemory@0.9.13

# MCP standalone shim
npx -y @agentmemory/mcp@0.9.13

# After install:
npx @agentmemory/agentmemory init   # copy bundled .env.example to ~/.agentmemory/.env

Full changelog: v0.9.12...v0.9.13

v0.9.12 — BM25 unicode + vector live-write + viewer hardening + plaintext-bearer guard

Choose a tag to compare

@rohitg00 rohitg00 released this 13 May 15:17
87fae50

Four landed PRs since v0.9.11 — one type-correctness fix, one search-quality fix (BM25 unicode + vector-index live-write), one viewer hardening (CSP-clean fonts + load-error surface), and one integrations security hardening (bearer token over plaintext HTTP).

Contributors

Huge thanks to four external contributors this release:

  • @mvanhorn — plaintext-bearer-auth guard across Hermes (Python), OpenClaw (mjs), and pi (TypeScript) plus the AGENTMEMORY_REQUIRE_HTTPS=1 escalation knob (#315)
  • @nik1t7n — original repro for the BM25 non-ASCII tokenizer bug + vector-index-never-populated trace (#295)
  • @hem57 — Windows repro screenshot + browser-console CSP-violation trace that pinned down the viewer "stuck Loading" path (#323)
  • @cl0ckt0wer — precise file:line trace for the duplicate RetentionScore.source declaration (#277)

Fixed

BM25 tokenizer now indexes non-ASCII; vector index now actually populated at runtime (#327, closes #295)

Two bugs in one PR:

BM25 tokenizer regex stripped every non-ASCII character. src/state/search-index.ts used \w (JS \w is ASCII-only), so non-English search returned empty results across the board — Greek, accented Latin, Hebrew, Arabic, Cyrillic. Regex replaced with /[^\p{L}\p{N}\s/.\\-_]/gu (Unicode letters/numbers, preserves underscore for memory_recall-style identifiers, keeps existing path/separator handling).

VectorIndex.add() had zero callers anywhere in src/. The vector index was loaded from disk at startup and never updated at runtime, so hybrid search returned stale results forever. New vectorIndexAddGuarded() helper in src/functions/search.ts wires vectorIndex.add() into remember.ts, observe.ts synthetic-compression branch, compress.ts post-LLM compression, and the cold-start rebuildIndex() walk — with a per-write dimension guard (symmetric to the persistence-load guard from #248), 16k-char input clipping (so an oversized memory can't 400 the embed call), and consistent stderr logging that no longer swallows embed failures.

migrateVectorIndex() utility re-embeds every memory + per-session observation against a new provider when dimensions change; per-session try/catch isolation so one bad session can't abort the whole migration; structured failedSessions[] result with a "<sessions-list-failed>" sentinel that distinguishes a catastrophic list-failure from per-session failures.

Soft-fail throughout: a downed embedder never breaks an upstream save. Live-tested end-to-end against Greek fixtures (thanks @nik1t7n for the original repro).

CJK caveat preserved: this fix recovers Greek, Cyrillic, accented Latin, Hebrew, Arabic, and other space-delimited scripts. CJK languages without spaces between characters still tokenize as a single sentence-long token — separate concern, needs a segmenter (PR #224 area).

Integrations now warn when sending the bearer token over plaintext HTTP (#315, closes #275)

Symmetric guard across all three plugin runtimes (Python / mjs / TypeScript): a request that would attach Authorization: Bearer <secret> to a http://<non-loopback>:port URL now logs a one-time stderr warning telling the operator the token is observable on the wire.

Loopback hosts (localhost, 127.0.0.1, ::1) and https:// URLs are exempt.

New env knob AGENTMEMORY_REQUIRE_HTTPS=1 escalates the warning to a hard refusal — the plugin throws before any request is sent, so a misconfigured deployment can fail loudly instead of leaking the bearer once.

Edge cases verified by 13 tests: IPv6 [::1] loopback (loopback), RFC1918 LAN IPs (192.168.x.x / 10.x.x.x warn — NOT loopback by design), lookalike hostnames (localhost.evil.com warns), no-secret short-circuit (guard never fires when no bearer would be sent), https-with-secret silent. Thanks @mvanhorn.

Viewer dashboard no longer sticks on "Loading dashboard…" (#335, closes #323)

Two narrow fixes from @hem57's Windows repro:

  1. Removed the <link rel="stylesheet"> to fonts.googleapis.com. The viewer's strict CSP (default-src 'none', style-src 'unsafe-inline', font-src 'self') blocks external stylesheet origins by design, so every page load logged a CSP violation for the font CSS and another for each blocked font file. System-font fallbacks were already declared on every --font-* CSS variable so dropping the external <link> is a clean swap.

  2. Wrapped loadDashboard() body in a try/catch that renders the error inline ("Dashboard failed to load: <reason>") instead of leaving the placeholder text up forever. Future "stuck Loading" reports now come with concrete error messages instead of just a screenshot of the placeholder.

RetentionScore type no longer declares source twice (#326, closes #277)

src/types.ts:835 and :842 both declared source?: "episodic" | "semantic" on RetentionScore. TypeScript silently accepts duplicate property declarations when the types are identical, so the build never errored — but the documented JSDoc on the first declaration (the #124 back-compat note explaining undefined should probe both scopes) was effectively shadowed by the duplicate. Removed the second declaration; grep confirmed no caller writes source twice on the same row, so the cleanup is a pure type-correctness fix with no runtime change. Thanks @cl0ckt0wer.

Changed

  • @agentmemory/mcp package version bumped 0.9.11 → 0.9.12 to lockstep with the main package.

Install / upgrade

npm i -g @agentmemory/agentmemory@0.9.12
# or
npx @agentmemory/agentmemory

# MCP standalone shim
npx -y @agentmemory/mcp

Full changelog: v0.9.11...v0.9.12

v0.9.11 — Codex plugin platform + OpenClaw slot fix + website star button

Choose a tag to compare

@rohitg00 rohitg00 released this 12 May 23:23
25dddc4

Three additions on top of v0.9.10: OpenAI Codex got a plugin platform and agentmemory now ships a Codex manifest + marketplace alongside the existing Claude Code one (so codex plugin marketplace add rohitg00/agentmemory installs MCP + 6 hooks + 4 skills in one step); the OpenClaw integration now actually claims the plugins.slots.memory slot via registerMemoryCapability (older builds advertised the slot via manifest kind but never declared the capability so the slot reported unavailable); and the marketing website's hero CTA row now ships a live "Star on GitHub" button.

Added

Codex plugin support (#311)

OpenAI Codex shipped a plugin platform at developers.openai.com/codex/plugins. The shape mirrors Anthropic Claude Code plugins. This release adds:

  • plugin/.codex-plugin/plugin.json — Codex manifest pointing at the same shared .mcp.json + skills/ directory the Claude Code manifest uses, plus a Codex-specific ./hooks/hooks.codex.json.
  • plugin/hooks/hooks.codex.json — Codex-shaped hook subset. Registers exactly the events Codex's hook engine supports: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PreCompact, Stop. Drops the Claude-Code-only events (SubagentStart, SubagentStop, SessionEnd, Notification, TaskCompleted, PostToolUseFailure) that Codex's input schemas don't define.
  • .codex-plugin/marketplace.json at the repo root — git-subdir source pointing at ./plugin.

Why the same scripts work on both hosts: verified against codex-rs/hooks/src/engine/discovery.rs that Codex's hook engine injects CLAUDE_PLUGIN_ROOT into hook subprocesses for OOTB compat with existing Claude Code plugin scripts:

env.insert("PLUGIN_ROOT".to_string(), plugin_root_value.clone());
// For OOTB compat with existing plugins that use this env var.
env.insert("CLAUDE_PLUGIN_ROOT".to_string(), plugin_root_value);
env.insert("PLUGIN_DATA".to_string(), plugin_data_root_value.clone());
env.insert("CLAUDE_PLUGIN_DATA".to_string(), plugin_data_root_value);

So every ${CLAUDE_PLUGIN_ROOT}/scripts/... reference in the existing hooks works unmodified on Codex. The Codex wire-format input schemas (session-start.command.input.schema.json and siblings) use the same field names as Claude Code (session_id, cwd, hook_event_name, source, transcript_path, model, permission_mode), so the existing plugin/scripts/*.mjs parsers work as-is.

Install:

# 1. start the memory server
npx @agentmemory/agentmemory

# 2. register the marketplace + install the plugin
codex plugin marketplace add rohitg00/agentmemory
codex plugin install agentmemory

Registers @agentmemory/mcp as an MCP server (51 tools with AGENTMEMORY_TOOLS=all), 6 lifecycle hooks, and 4 skills (/recall, /remember, /session-history, /forget).

Star on GitHub button in the website hero CTA row (#316)

Adds a ghost-style GitHubStarButton component next to START IN 60 SECONDS and SEE IT MOVE with inline SVG star icon, STAR label, and a live stargazer count fetched once on mount from api.github.com/repos/rohitg00/agentmemory. Count is cached in localStorage for 30 minutes per repo. Graceful degradation: if the API is unreachable / rate-limited / blocked, the button still renders without the count. No new dependencies.

Fixed

OpenClaw plugins.slots.memory = "agentmemory" now reports as available, not unavailable (#310)

On OpenClaw 2026.4.9+, the integration declared "kind": "memory" in its manifest and wired before_agent_start / agent_end hooks but never called api.registerMemoryCapability(...) — so OpenClaw's memory-slot machinery saw no claim on the slot even though the hooks and REST API worked end-to-end.

The fix lands api.registerMemoryCapability({ promptBuilder }) at register time when the host exposes it, with the promptBuilder accepting the documented { availableTools, citationsMode? } params and emitting a three-line block identifying agentmemory as the active provider:

if (typeof api.registerMemoryCapability === "function") {
  api.registerMemoryCapability({
    promptBuilder: (_params) => [
      "Long-term memory provider: agentmemory (external REST service on " +
        client.baseUrl + ").",
      "agentmemory recalls relevant prior observations before each turn via the " +
        "before_agent_start hook and captures completed turns via agent_end.",
      "Treat recalled context as background, not authoritative — prefer current " +
        "workspace state and explicit user instructions when they conflict.",
    ],
  });
}

Older OpenClaw builds without the capability API still load via the existing hook-only path (the typeof ... === "function" guard). The PR does not ship a MemoryPluginRuntime adapter because OpenClaw's current MemoryRuntimeBackendConfig type is exactly { backend: "builtin" } | { backend: "qmd"; ... } — both in-process backends that don't fit an external REST shape. Verified against openclaw@2026.5.7's plugin-sdk/src/plugins/types.d.ts and memory-state.d.ts declarations directly.

Changed

  • @agentmemory/mcp package version bumped 0.9.10 → 0.9.11 to lockstep with the main package.
  • README distinguishes Codex CLI (MCP only) from Codex CLI (full plugin) in the per-host install table and lists the marketplace install command for the latter.

Install / upgrade

npm i -g @agentmemory/agentmemory@0.9.11
# or
npx @agentmemory/agentmemory

# MCP standalone shim
npx -y @agentmemory/mcp

# Codex CLI plugin (new)
codex plugin marketplace add rohitg00/agentmemory
codex plugin install agentmemory

Full changelog: v0.9.10...v0.9.11

v0.9.10 — distroless volume perms + viewer reverse proxy + budget loop

Choose a tag to compare

@rohitg00 rohitg00 released this 12 May 17:19
292e9f6

Three deployment-shape fixes reported live by @flamerged (#299, #301): the v0.9.7 docker-compose persistence fix was incomplete because the distroless engine runs as UID 65532 but docker volume create initializes the named volume mountpoint as root:root mode 755; the viewer's port-detection JS hardcoded '3113' so any reverse-proxy fronting on port 80/443 returned an empty dashboard; and the mem::context budget loop short-circuited the entire selection on the first oversized block — pinning a large slot could starve all other context blocks even when smaller ones would have fit.

Fixed

docker-compose.yml now chowns the named volume to UID 65532 before the engine starts

The iiidev/iii image is distroless and runs as UID 65532; docker initializes named volumes as root:root mode 755; the engine has no sh / chown to self-heal at startup, so writes to /data/state_store.db and /data/stream_store returned Permission denied (os error 13). The engine silently buffered in RAM, the API kept reporting success: true, and state evaporated on every container restart — the exact symptom v0.9.7's working-directory fix set out to solve.

The compose file now ships an iii-init one-shot service (busybox:1.36, ~4 MB image, exits in <100 ms) that runs chown -R 65532:65532 /data && chmod 755 /data once at compose-up, plus user: "65532:65532" on the iii-engine service and depends_on.iii-init.condition: service_completed_successfully so the engine never starts before the volume is owner-correct.

Migration: existing deployments that already hit the bug should run docker compose down && docker compose up -d after upgrading — the init container fixes the volume in place on the first run, no manual chown needed.

(#304, closes #301 — thanks @flamerged for the precise UID + mountpoint trace and the chown workaround that confirmed the fix shape)

Viewer dashboard now works behind any reverse proxy on standard ports (80 / 443)

src/viewer/index.html resolved the REST base URL through:

// before
var viewerPort = params.get('port') || window.location.port || '3113';

When the page was served on port 80 / 443, window.location.port was the empty string, the fallback hardcoded '3113', and every browser-side /agentmemory/* fetch went to <host>:3113 — typically loopback-only on the self-hosted shape, so unreachable from outside. The viewer rendered cleanly but every panel showed the empty "first run" state even when curl <proxy-host>/agentmemory/sessions returned correct data.

The fix uses window.location.origin as the REST base when neither ?port= nor window.location.port is set, and window.location.host for the WebSocket URL so the same-origin path works for both REST and live updates. Behaviour with an explicit ?port=N or non-default window.location.port is unchanged.

(#304, closes #299 — thanks @flamerged for the deployment context + the lines-927–930 trace)

mem::context budget loop no longer bails the entire selection on the first oversized block

The selection loop in src/functions/context.ts used break when usedTokens + block.tokens > budget, so a single oversized block at the top of the sorted list — most commonly a fat pinned slot under #288's new injection path — cut off every smaller block that would have fit. Switched to continue, so smaller blocks downstream of an oversized one can still slip into the remaining budget. Net effect: pinned-slot priority semantic is preserved (pinned blocks still sort first via recency: Date.now()), but the worst case no longer starves the entire context. Total tokens still bounded by tokenBudget (default 2000); only the composition under contention changes.

Bonus — README polish

@PR #305 added the Trendshift #1 Repository Of The Day trophy badge and a star history chart to the top of the README, dropped Hermes + OpenClaw into the tagline alongside the other first-party integrations they already ship plugins for, and reflowed the Karpathy-gist sentence onto a single italic line for narrower viewports.

Changed

  • @agentmemory/mcp package version bumped 0.9.9 → 0.9.10 to lockstep with the main package.

Install / upgrade

npm i -g @agentmemory/agentmemory@0.9.10
# or
npx @agentmemory/agentmemory

# MCP standalone shim
npx -y @agentmemory/mcp

If you ran the v0.9.7+ Docker compose stack and saw state vanish on every restart, the init container shipped in this release fixes the volume in place — just docker compose down && docker compose up -d after upgrading.

Full changelog: v0.9.9...v0.9.10

v0.9.9 — pinned slot injection + MiniMax env loader

Choose a tag to compare

@rohitg00 rohitg00 released this 11 May 18:39
03fb42d

Two field-reported regressions closed: pinned memory slots never reached SessionStart context (the renderPinnedContext and listPinnedSlots helpers shipped in v0.7 had no callers), and the MiniMax compression provider read its base URL straight off process.env, missing ~/.agentmemory/.env values that the rest of agentmemory loads through the shared merged-env path.

Fixed

Pinned memory slots are now actually injected into SessionStart context

@wyh0626 traced (#286) that renderPinnedContext (src/functions/slots.ts:182) and listPinnedSlots (src/functions/slots.ts:169) — introduced in #182 — had zero callers in src/:

$ git grep renderPinnedContext src/
src/functions/slots.ts:182:export function renderPinnedContext(...)

$ git grep listPinnedSlots src/
src/functions/slots.ts:169:export async function listPinnedSlots(...)

mem::context (the function /agentmemory/session/start invokes and that session-start.mjs reads back into Claude Code) read profile / sessions / summaries / observations but never slots, so anything an agent wrote into a pinned slot via mem::slot-replace / mem::slot-append / mem::slot-reflect sat in KV and never reached the next session.

The mem::slot-reflect writer fires on the Stop hook when AGENTMEMORY_REFLECT=true and persists into pending_items / session_patterns / project_context — the reflect → next-session loop was open.

The fix wires listPinnedSlotsrenderPinnedContext into mem::context behind isSlotsEnabled(), matching the existing isGraphExtractionEnabled() gate convention:

if (isSlotsEnabled()) {
  const slotContent = renderPinnedContext(
    await listPinnedSlots(kv).catch(() => []),
  );
  if (slotContent) {
    blocks.push({
      type: "memory",
      content: slotContent,
      tokens: estimateTokens(slotContent),
      recency: Date.now(),
    });
  }
}

recency: Date.now() so the pinned block sorts to the top of the budget-bounded selection.

Verify:

# server: AGENTMEMORY_SLOTS=true AGENTMEMORY_INJECT_CONTEXT=true
curl -X POST localhost:3111/agentmemory/slot/replace \
  -H 'Content-Type: application/json' \
  -d '{"label":"tool_guidelines","content":"rule-alpha"}'

curl -X POST localhost:3111/agentmemory/session/start \
  -H 'Content-Type: application/json' \
  -d '{"sessionId":"s1","project":"/tmp","cwd":"/tmp"}'

Before: "context": "" (0 chars).
After: context contains the tool_guidelines slot wrapped in <agentmemory-context>.

AGENTMEMORY_SLOTS=false (the default) keeps the existing behaviour untouched.

(#288, closes #286 — thanks @wyh0626 for the precise zero-callers trace and the six-case regression suite covering global / multi-sort / unpinned-skip / empty-skip / project-shadows-global / gate-off)

MiniMax provider now honors MINIMAX_BASE_URL from ~/.agentmemory/.env, with the default pointed at the current Anthropic-compatible host

@rager306 reported (#285) v0.9.8 MiniMax compression failing MiniMax API error 401: invalid api key against a verified-good key:

  • Direct curl https://api.minimax.io/anthropic/v1/messages with the same key → 200 OK.
  • Control curl https://api.minimaxi.com/anthropic/v1/messages with the same key → 401.

The 401 was the stale fallback host answering — the key was fine.

Root cause: split-brain env source. src/config.ts (provider detection + API-key load) reads ~/.agentmemory/.env through the merged getMergedEnv() loader; src/providers/minimax.ts read MINIMAX_BASE_URL straight off process.env:

// before
this.baseUrl =
  process.env['MINIMAX_BASE_URL'] || 'https://api.minimaxi.com/anthropic'

Deployments that kept MiniMax config in ~/.agentmemory/.env only (systemd / launchd / --env-file not exported into the worker shell) got the key loaded but the base URL fell through to the stale default.

The provider now resolves MINIMAX_BASE_URL via getEnvVar() (same merged loader the rest of agentmemory uses), and the default is bumped from api.minimaxi.com to api.minimax.io/anthropic per MiniMax's current Anthropic-compatible docs:

// after
this.baseUrl =
  getEnvVar('MINIMAX_BASE_URL') || 'https://api.minimax.io/anthropic'

Existing users on the legacy host can still override via MINIMAX_BASE_URL either in ~/.agentmemory/.env or the process env.

(#289, closes #285 — thanks @rager306 for the precise repro and the local-patch verification)

Changed

  • @agentmemory/mcp package version bumped 0.9.8 → 0.9.9 to lockstep with the main package.

Install / upgrade

npm i -g @agentmemory/agentmemory@0.9.9
# or
npx @agentmemory/agentmemory

# MCP standalone shim
npx -y @agentmemory/mcp

Full changelog: v0.9.8...v0.9.9

v0.9.8 — local fallback tools/list returns 7 not 4

Choose a tag to compare

@rohitg00 rohitg00 released this 11 May 13:58
0f0bb50

Single-line follow-up to v0.9.7's MCP shim work. v0.9.7 surfaced probe failures, added an AGENTMEMORY_FORCE_PROXY=1 escape hatch, and shipped AGENTMEMORY_DEBUG=1 — but the local-mode tools/list branch was still returning only 4 tools when an agentmemory server was unreachable, not the documented 7-tool IMPLEMENTED_TOOLS set the shim's InMemoryKV actually backs.

Fixed

@agentmemory/mcp local-mode tools/list now exposes all 7 IMPLEMENTED_TOOLS

The local-fallback branch in src/mcp/standalone.ts filtered getVisibleTools() through IMPLEMENTED_TOOLS, but getVisibleTools() honors the shim process's own AGENTMEMORY_TOOLS env var:

unset / "core" → 8 ESSENTIAL_TOOLS
"all"          → 51 tools

The intersection of ESSENTIAL_TOOLS (8) and IMPLEMENTED_TOOLS (7) is exactly 4 tools:

memory_save, memory_recall, memory_smart_search, memory_sessions

Those four were the only ones MCP clients saw when no agentmemory server was reachable — even though the shim's InMemoryKV implements all seven (the four above plus memory_export, memory_audit, memory_governance_delete).

The filter source was wrong: the shim dispatches by IMPLEMENTED_TOOLS, not by ESSENTIAL_TOOLS, so a server-tier env var should never have shaped the shim's local-fallback list. Switched to:

const fallback = getAllTools().filter((t) => IMPLEMENTED_TOOLS.has(t.name));

IMPLEMENTED_TOOLS.has(t.name) still picks the right 7 names — but now from the unfiltered universe regardless of AGENTMEMORY_TOOLS.

Refactor for testability

The tools/list handler was inline inside the createStdioTransport callback. Extracted into an exported handleToolsList() so it's directly testable. Added a regression test asserting the local-fallback path returns exactly the 7 names under both AGENTMEMORY_TOOLS=core and unset.

Verified live via stdio

$ {
    printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}'
    printf '%s\n' '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}'
    printf '%s\n' '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
    sleep 1
  } | node dist/standalone.mjs 2>/dev/null \
    | grep -o '"name":"memory_[^"]*"' | sort -u
"name":"memory_audit"
"name":"memory_export"
"name":"memory_governance_delete"
"name":"memory_recall"
"name":"memory_save"
"name":"memory_sessions"
"name":"memory_smart_search"

(#283, closes #234)

Changed

  • @agentmemory/mcp package version bumped 0.9.7 → 0.9.8 to lockstep with the main package.

Install / upgrade

npm i -g @agentmemory/agentmemory@0.9.8
# or
npx @agentmemory/agentmemory

# MCP standalone shim
npx -y @agentmemory/mcp

Full changelog: v0.9.7...v0.9.8