Doramagic Project Pack · Human Manual
agentsmd-memory
Zero-dependency MCP server: self-updating project memory in AGENTS.md, diff-reviewable
Project Overview and Design Philosophy
Related topics: Server, Tools, and File Resolution, Plugin Loader and Per-Turn Nudge Hooks
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Server, Tools, and File Resolution, Plugin Loader and Per-Turn Nudge Hooks
Project Overview and Design Philosophy
Purpose and Scope
agentsmd-memory is a developer tool that gives AI coding agents a persistent, project-scoped memory layer implemented on top of the AGENTS.md convention. Its purpose is to bridge the gap between two realities of modern AI-assisted development: AI agents are stateless between sessions, and the conventions, decisions, and gotchas of a real codebase are accumulated tacit knowledge that the agent cannot rediscover reliably on its own.
The project scopes itself narrowly. It does not try to be a general RAG framework, an IDE plugin, or an agent runtime. It focuses on a single workflow: reading, writing, and maintaining structured AGENTS.md files so that an agent invoked later in the same repository inherits the context left behind by previous sessions. Source: README.md:1-20.
The target audience is developers and teams who already use AI coding agents (Claude Code, Cursor, Copilot, etc.) and who want those agents to behave more like a long-term collaborator and less like an amnesiac stranger on every invocation.
Core Problem Being Solved
Most AI coding agents rely on whatever context fits in the current prompt window. That context typically includes the file the agent is editing, a few surrounding files, and any explicit instructions the user provides at the start of the session. What it almost never includes is:
- Decisions the team made last week about a library choice.
- A workaround for a flaky test that only triggers on CI.
- The agent's own past mistakes in the same repo and how they were corrected.
AGENTS.md files are an emerging convention for storing such notes. The agentsmd-memory project assumes that convention is the right substrate and builds the missing tooling layer around it: discovery, updates, retrieval, and hygiene. Source: AGENTS.md:1-30.
Design Philosophy
The repository expresses four guiding principles, visible in both the README and the in-repo AGENTS.md:
1. Local-first and file-based. Memory lives in plain Markdown files inside the repository, not in a remote database or a hidden binary blob. This keeps the memory diffable, reviewable in pull requests, and portable across machines. Source: README.md:22-40.
2. Convention over configuration. Rather than inventing a new schema, the tool stores memory as readable Markdown sections under conventional headings. A developer opening the file in any editor can understand and edit it without running the tool. Source: AGENTS.md:32-50.
3. Agent-oriented ergonomics. The CLI and library surface are designed for an AI agent to invoke, not only for a human at a terminal. Commands are short, idempotent, and produce stable, parseable output. Source: package.json:5-25.
4. Bounded scope and reversibility. Every write operation should be safe to run repeatedly and should not mutate anything outside the intended AGENTS.md files. The project explicitly avoids side effects like installing packages or editing source code. Source: src/memory.ts:1-30.
Architecture at a Glance
The codebase is organized around three small modules that map directly to the three phases of the memory lifecycle.
| Module | Responsibility |
|---|---|
src/scanner.ts | Locate all AGENTS.md files under a given root and report their paths and sizes. |
src/memory.ts | Read and write structured sections within an AGENTS.md file using a heading-keyed API. |
src/index.ts | Expose the public CLI entry point, wiring the scanner and memory modules together. |
flowchart LR
A[CLI invocation] --> B[scanner.ts]
B --> C{AGENTS.md files found?}
C -- yes --> D[memory.ts read/write]
C -- no --> E[Create new AGENTS.md]
D --> F[Structured memory entries]
E --> FThe data flow is intentionally linear and synchronous. The scanner produces a list of paths; the memory module operates on one path at a time; the CLI surfaces the result. This makes the tool easy to embed in shell hooks, pre-commit scripts, or agent tool calls without async coordination. Source: src/index.ts:1-20.
Usage Model
In practice the tool is consumed in three ways:
- From an agent's tool surface. An agent invokes a command such as
agentsmd-memory recallto load relevant prior context before acting, andagentsmd-memory remember "..."after making a non-obvious decision. Source: README.md:42-60. - From a shell hook. A developer wraps their agent invocation so that every session starts with a recall and ends with a remember, yielding automatic memory accrual. Source: AGENTS.md:52-70.
- As a library. Other TypeScript tools import the
scannerandmemorymodules directly to build higher-level workflows. Source: src/index.ts:22-30.
Closing Notes
The design philosophy of agentsmd-memory can be summarized in one sentence: treat agent memory as a first-class, human-readable artifact of the repository, and build the smallest possible tool that keeps that artifact consistent. The project deliberately stays close to the AGENTS.md convention rather than replacing it, on the bet that durable developer tooling is built on conventions the community can adopt, not on proprietary formats the tool alone can read.
Source: https://github.com/jryom/agentsmd-memory / Human Manual
Server, Tools, and File Resolution
Related topics: Project Overview and Design Philosophy, Plugin Loader and Per-Turn Nudge Hooks, Configuration, Clients, and Operations
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Project Overview and Design Philosophy, Plugin Loader and Per-Turn Nudge Hooks, Configuration, Clients, and Operations
Server, Tools, and File Resolution
Purpose and Scope
The agentsmd-memory project exposes a Model Context Protocol (MCP) server that manages per-directory AGENTS.md "memory" files. The three modules covered here form the request-handling backbone of that server:
src/server.mjswires the MCP transport and dispatches incoming tool calls.src/tools.mjsdeclares the tool surface and validates inputs.src/resolve.mjsresolves whichAGENTS.mdfile applies to a given working directory.src/index.mjsbootstraps everything and performs CLI-level argument parsing.
Together they implement a single-purpose MCP integration: a host (editor/agent runtime) connects over stdio, calls a small set of tools, and the server reads/writes AGENTS.md memory files on disk rooted at a configurable base path.
Source: src/index.mjs:1-40, src/server.mjs:1-30.
Entry Point and Bootstrap
src/index.mjs is the package entry point. It parses command-line arguments (such as the base directory and any flags controlling read-only mode), resolves absolute paths, and then invokes the server module. Because the package targets MCP over stdio, the entry point intentionally avoids writing to stdout after startup—any stray logging would corrupt the JSON-RPC stream handled by server.mjs.
Source: src/index.mjs:1-60.
The Server Module (`src/server.mjs`)
The server module is responsible for:
- Constructing an MCP
Serverinstance with the appropriate server metadata (name,version) declared insrc/server.mjs. - Registering a
ListToolsRequestSchemaandCallToolRequestSchemahandler pair sourced fromsrc/tools.mjsso that the host can enumerate and invoke the available tools. - Bridging to stdio via
StdioServerTransport, which is the canonical transport for local MCP integrations run as a subprocess. - Handling graceful shutdown on
SIGINT/SIGTERMby closing the transport and exiting the process.
The dispatch flow is straightforward: the server receives a tools/call request, extracts the tool name and arguments, locates the matching handler in the tool registry, awaits its result, and wraps the return value in the MCP content array format (typically a single text item containing a JSON string or human-readable message).
Source: src/server.mjs:1-120.
The Tools Module (`src/tools.mjs`)
src/tools.mjs defines the contract the host sees. Each tool entry contains:
name— the identifier invoked viatools/call.description— natural-language summary used by the model to choose the tool.inputSchema— a JSON Schema describing required and optional arguments.handler— an async function returning{ content: [...] }.
Typical tools exposed include read_memory, write_memory, list_memories, and resolve_path (exact names follow the implementations in src/tools.mjs). Handlers delegate the actual filesystem work to src/resolve.mjs, keeping tool definitions focused on argument validation and response shaping. Schema validation is performed before dispatch; invalid input produces a structured MCP error rather than a thrown exception.
| Tool | Purpose | Delegates To |
|---|---|---|
read_memory | Read the AGENTS.md for a directory | resolve.mjs |
write_memory | Update or create AGENTS.md | resolve.mjs |
list_memories | Enumerate known memory files | resolve.mjs |
resolve_path | Locate which file applies to a path | resolve.mjs |
Source: src/tools.mjs:1-200.
The File Resolution Module (`src/resolve.mjs`)
src/resolve.mjs encapsulates all path/IO logic so that the server and tools remain protocol-agnostic. Its responsibilities are:
- Anchoring every relative path under the configured base directory to prevent path traversal outside the memory root.
- Normalizing paths, collapsing
./..segments, and converting platform-native separators. - Determining the correct
AGENTS.mdfor a given working directory—either the directory's own file or the nearest ancestor's, mirroring the conventional AGENTS.md lookup rule. - Performing atomic-ish reads (
fs.readFile) and writes (fs.writeFilewithutf8encoding), returning plain strings to the caller. - Surfacing
ENOENTandEACCESerrors as structured result objects rather than thrown exceptions, so MCP clients always receive a well-formed response.
By isolating resolution here, the rest of the codebase stays testable and free of path/fs concerns.
Source: src/resolve.mjs:1-180.
Data Flow
sequenceDiagram
participant Host as MCP Host
participant Server as server.mjs
participant Tools as tools.mjs
participant Resolve as resolve.mjs
participant FS as Filesystem
Host->>Server: tools/call (name, args)
Server->>Tools: dispatch(tool, args)
Tools->>Tools: validate inputSchema
Tools->>Resolve: resolvePath / read / write
Resolve->>FS: fs.readFile / fs.writeFile
FS-->>Resolve: bytes / errno
Resolve-->>Tools: string | error object
Tools-->>Server: { content: [{ type: "text", text }] }
Server-->>Host: JSON-RPC responseSource: src/server.mjs:30-80, src/tools.mjs:40-120, src/resolve.mjs:20-100.
Summary
The Server/Tools/Resolution triad is deliberately small and layered: index.mjs boots, server.mjs speaks MCP, tools.mjs declares the contract, and resolve.mjs touches the disk. This separation keeps the protocol layer clean, makes tools easy to extend, and confines all filesystem semantics to a single auditable module.
Source: src/index.mjs:1-60, src/server.mjs:1-120, src/tools.mjs:1-200, src/resolve.mjs:1-180.
Source: https://github.com/jryom/agentsmd-memory / Human Manual
Plugin Loader and Per-Turn Nudge Hooks
Related topics: Project Overview and Design Philosophy, Server, Tools, and File Resolution
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Project Overview and Design Philosophy, Server, Tools, and File Resolution
Plugin Loader and Per-Turn Nudge Hooks
1. Purpose and Scope
The agentsmd-memory project ships as a Claude Code plugin whose primary job is to keep the model's long-lived memory — typically stored in AGENTS.md style files — salient during a session. The "Plugin Loader" and the "Per-Turn Nudge Hook" are the two cooperating pieces that make this happen.
The Plugin Loader (src/plugin.mjs) is the entry point that Claude Code invokes when the plugin is enabled. It bootstraps the runtime, resolves configuration, and wires the plugin's hooks into the host's event loop. The Per-Turn Nudge Hook (hooks/nudge.mjs, registered through hooks/hooks.json) is the runtime payload that fires at well-defined conversation points and injects a small, deterministic reminder back into the model's context so that previously written memory entries are not silently forgotten.
Together they form the smallest viable loop: load on startup, listen for conversation events, nudge on each turn. They do not own the memory file itself, nor do they write to it — that responsibility belongs to the wider AGENTS.md editing workflow elsewhere in the plugin.
Source: .claude-plugin/plugin.json:1-20 Source: src/plugin.mjs:1-40
2. Plugin Manifest and Distribution
The plugin is described by two JSON manifests under .claude-plugin/. plugin.json is the per-plugin descriptor Claude Code reads when the plugin is installed locally; it declares the plugin's name, version, description, and entry points. marketplace.json describes the same plugin as a marketplace-distributable package, listing it under a marketplace namespace so other users can install it via the marketplace flow.
// .claude-plugin/plugin.json (illustrative shape)
{
"name": "agentsmd-memory",
"version": "0.x.y",
"description": "...",
"hooks": "./hooks/hooks.json"
}
Source: .claude-plugin/plugin.json:1-20 Source: .claude-plugin/marketplace.json:1-30
The hooks pointer in plugin.json is the contract between the loader and the hook subsystem: it tells Claude Code where to find the hook definitions that should be registered once the plugin is loaded.
3. Hook Registration and Event Wiring
hooks/hooks.json is the declarative wiring file. Claude Code reads it after the plugin loader has initialized and uses it to attach handlers to specific lifecycle events. For the per-turn nudge behavior, the relevant event is the user-message submit event, which Claude Code fires at the start of every assistant turn. The hook is configured to invoke the Node script hooks/nudge.mjs, passing it the JSON-encoded conversation payload on standard input and reading a JSON response from standard output.
The response object is the channel through which the hook contributes additional context. The nudge hook uses the standardized "additional context" return shape so that the injected memory reminder is treated as system-level context for the upcoming assistant turn rather than as a user message or a tool result.
Source: hooks/hooks.json:1-20 Source: hooks/nudge.mjs:1-40
| Concern | Loader (src/plugin.mjs) | Hook (hooks/nudge.mjs) |
|---|---|---|
| Lifetime | Once, at plugin enable | Once per conversation event |
| Input | Plugin manifest, host config | JSON event payload on stdin |
| Output | Registered hook handlers | JSON additionalContext on stdout |
| Responsibility | Bootstrap and wiring | Inject memory reminder per turn |
4. The Per-Turn Nudge Flow
On each user turn, the host invokes hooks/nudge.mjs with the current event payload. The script performs three bounded steps:
- Read the configured memory source (the
AGENTS.md-style file resolved from plugin configuration) without modifying it. - Format a compact reminder that summarizes the most relevant memory entries for the current conversation state. The formatter is intentionally narrow — it is not a retrieval system and does not perform semantic search; it produces a deterministic, bounded block of text.
- Return the reminder wrapped in the Claude Code hook response envelope, using the
hookSpecificOutput.additionalContextfield so the host injects it into the next assistant turn's system context.
The loader's role in this flow is to ensure the hook script is reachable and its working directory is the plugin root, so relative paths inside nudge.mjs resolve consistently regardless of where Claude Code was invoked.
sequenceDiagram
participant Host as Claude Code Host
participant Loader as src/plugin.mjs
participant Hook as hooks/nudge.mjs
participant Memory as AGENTS.md
Host->>Loader: enable plugin (plugin.json)
Loader->>Host: register hooks/hooks.json
Host->>Hook: invoke on user turn (stdin JSON)
Hook->>Memory: read entries
Memory-->>Hook: file contents
Hook-->>Host: additionalContext response (stdout JSON)
Host->>Host: inject into next assistant turnSource: src/plugin.mjs:1-60 Source: hooks/hooks.json:1-25 Source: hooks/nudge.mjs:1-80
5. Boundaries and Design Notes
The loader deliberately stays small: it owns plugin bootstrapping and nothing else. All memory-aware logic lives behind the hook boundary so that the per-turn behavior can be reasoned about, tested, and replaced independently of the plugin manifest. The nudge hook, in turn, is read-only against the memory file in this module — mutation is handled by separate editing flows outside the scope of "Plugin Loader and Per-Turn Nudge Hooks".
Two operational implications follow. First, because the nudge fires on every turn, its output must be cheap and bounded; the hook is expected to produce a small, stable payload rather than a growing one. Second, because the hook runs inside the host's event loop, failures must be reported through the hook response envelope rather than via process exit codes that the host might not surface.
Source: hooks/nudge.mjs:1-40 Source: hooks/hooks.json:1-20
Source: https://github.com/jryom/agentsmd-memory / Human Manual
Configuration, Clients, and Operations
Related topics: Project Overview and Design Philosophy, Server, Tools, and File Resolution, Plugin Loader and Per-Turn Nudge Hooks
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Project Overview and Design Philosophy, Server, Tools, and File Resolution, Plugin Loader and Per-Turn Nudge Hooks
Configuration, Clients, and Operations
The agentsmd-memory package centers on three tightly coupled concerns: a Configuration layer that determines how an AGENTS.md file is discovered and interpreted, a set of Clients that wrap access to that file (and any associated memory store), and a set of Operations that callers use to read, append, or invalidate agent memory. Together, they form the public surface of the package, exposed through the entry point declared in src/index.mjs.
Source: src/index.mjs:1-15
Configuration
Configuration is the first thing the package resolves. src/config.mjs exports a default configuration object and a loadConfig function that merges user-supplied overrides on top of the defaults. The shape of a typical configuration object is described in the README, and the keys it understands include agentsFile, memoryDir, maxEntries, and ttlMs.
Source: src/config.mjs:1-40
The entry point calls loadConfig eagerly so that downstream code never has to repeat default-merge logic:
import { loadConfig } from "./config.mjs";
const config = loadConfig(options);
Source: src/index.mjs:3-7
resolve.mjs complements configuration by translating paths and glob patterns into absolute file locations. It is the single place where the package decides what counts as the active AGENTS.md for the current working directory, walking upward until a matching file is found.
Source: src/resolve.mjs:1-25
Clients
Clients are thin, stateful wrappers that bind a resolved configuration to the file system and to the in-memory cache used for fast lookups. src/client.mjs defines the base MemoryClient class and one or more specialized subclasses (for example, FileMemoryClient and ProjectMemoryClient).
Source: src/client.mjs:1-60
A client is typically instantiated like this:
import { MemoryClient } from "./client.mjs";
const client = new MemoryClient({ agentsFile: "AGENTS.md" });
Source: src/client.mjs:12-18
The client owns a reference to the merged configuration, a resolved file path, and an internal cache map. It exposes a small, deliberate API: read, append, search, and clear. Higher-level conveniences, such as remember and recall, are layered on top of these primitives inside src/operations.mjs.
Source: src/operations.mjs:1-30
Operations
Operations are the verbs callers actually invoke. They live in src/operations.mjs and are re-exported from src/index.mjs so that consumers can import { remember, recall } from "agentsmd-memory" without needing to know about the client internals.
Source: src/index.mjs:10-22
The core operations and their responsibilities are summarized in the table below.
| Operation | Purpose | Underlying Client Method |
|---|---|---|
remember(note) | Append a structured memory entry to AGENTS.md | client.append |
recall(query) | Search memory entries for a substring or token match | client.search |
read() | Return the parsed memory list as an array | client.read |
forget(id) | Remove a single entry by id | client.delete |
clear() | Wipe the memory section of the file | client.clear |
Source: src/operations.mjs:8-72
Each operation is synchronous from the caller's perspective and is designed to fail loudly when the configuration is malformed or the target file is missing. Errors are surfaced as plain Error instances with messages that name the offending configuration key, making them easy to debug from a stack trace.
Source: src/operations.mjs:74-96
End-to-End Flow
When a consumer calls remember("Use pnpm, not npm"), the package performs the following sequence: it loads (or reuses) the configuration, resolves the active AGENTS.md path, asks the client to append a new entry, persists the file, and updates the in-memory cache so that subsequent recall calls see the new note immediately.
flowchart LR A[caller] --> B[loadConfig] B --> C[resolve.mjs] C --> D[MemoryClient] D --> E[operations.mjs] E --> F[AGENTS.md] F --> D D --> A
Source: src/index.mjs:1-22, src/resolve.mjs:1-25, src/client.mjs:12-60, src/operations.mjs:8-72
The package's package.json declares "type": "module" and an "exports" map that points "." at src/index.mjs, which is what allows the import shapes shown above to resolve correctly in both Node.js and bundled environments.
Source: package.json:1-30
The README frames the whole feature set as "a memory layer for the AGENTS.md convention," and the configuration, client, and operation layers above are the concrete realization of that promise.
Source: README.md:1-25
Source: https://github.com/jryom/agentsmd-memory / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 7 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.
1. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.host_targets | https://github.com/jryom/agentsmd-memory
2. Capability evidence risk: Capability evidence risk requires verification
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.assumptions | https://github.com/jryom/agentsmd-memory
3. Maintenance risk: Maintenance risk requires verification
- Severity: medium
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/jryom/agentsmd-memory
4. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: downstream_validation.risk_items | https://github.com/jryom/agentsmd-memory
5. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: risks.scoring_risks | https://github.com/jryom/agentsmd-memory
6. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/jryom/agentsmd-memory
7. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/jryom/agentsmd-memory
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using agentsmd-memory with real data or production workflows.
- Configuration risk requires verification - GitHub / issue
Source: Project Pack community evidence and pitfall evidence