This page is addressed to an AI agent working with memhtml, and it is written so the person evaluating memhtml over your shoulder can read it too. It is short, and every claim on it points at behavior a test checks.
1. The manifest outranks this page
Section titled “1. The manifest outranks this page”memhtml manifest prints the binary’s whole contract: every command, argument, flag, response type, error code, and environment variable. A bare memhtml returns the same thing, and so do memhtml help and memhtml --help when stdout is a pipe. Each of them answers on a machine with no store, no database, and no credentials, which makes the manifest your liveness check as well as your contract.
For one command, memhtml help <command> (or memhtml <command> --help, or -h) returns that command’s entry alone: a usage line, its arguments and flags, the response type it emits, the usage-error codes, examples, and sibling commands. Piped, it is a cli.help envelope whose data is the manifest’s entry for the command plus those derived fields, so nothing it says can contradict the manifest. On a terminal it is Markdown, for the person behind you; --json forces the envelope there too. Every usage error on a command that exists ends its suggestions with the memhtml help <command> call that shows the table you needed; an unknown command gets nearest-name candidates instead.
For an agent. Prefer the manifest to this page wherever the two could disagree. The manifest is generated from the source of truth, so it is right and this page is stale. This page adds what a schema cannot state: what a silence means, and which surface you are on.
2. Assumptions to drop
Section titled “2. Assumptions to drop”Each item below is a place where memhtml behaves unlike the system you are pattern-matching it to.
Branch on code and never on error. A failure envelope carries four fields: {apiVersion, error, code, suggestions}. The code values are append-only, so a shipped code keeps its meaning for good and is never removed. The error string is prose for a human, and whoever improves the wording rewrites it freely, so a matcher over that string gives you a test that passes until someone edits a sentence. See error codes and the envelope.
An absent path was archived. memhtml removes nothing from a store. Eviction is a git mv into archive/<YYYY>/ that mirrors the original path, so git log --follow reads through a memory’s whole life. When a path you were holding stops appearing in results, retry with --include-archived before you conclude the fact is gone. See store layout and path algebra.
The git tree is the system of record and the index is disposable. .memhtml/index.db is a projection, and memhtml index rebuild reconstructs it from the tree, so anything that has to survive lives in a file: authored links are <link> elements and metadata is <meta> elements. Read a query result as a pointer to a file, and the file as the fact. See the index plane and the state plane.
One memory holds one fact. A memory is a single claim. Writing a five-paragraph summary as one memory defeats retrieval, because the arm that should rank one of those claims scores the whole blob instead. Split the summary into claims and let memhtml link carry the relationships between them. See the memory file format.
Read the flags instead of guessing them. Every flag the binary accepts is in the manifest, and an unknown flag returns a usage error with a suggestion attached rather than a silent default. A guess costs a round trip, where the manifest answers the same question in one call. See global flags.
3. Which surface you are on
Section titled “3. Which surface you are on”Two surfaces reach the same store, and the test for which one you have is free.
| Signal | Surface | Entry point |
|---|---|---|
memory_search is in your tool list |
MCP | Call the tools directly. Nothing to install. |
| You can run a shell command | CLI | memhtml manifest, then the command you need. |
| Neither | Read-only | You are reading documentation. Fetch the Markdown, not the HTML. |
The MCP server is the same binary. memhtml serve mcp speaks stdio and composes the same services the command line does, so both surfaces agree on which store, which database, and which vector space a call reaches. A tool’s arguments mirror its command’s flags. See MCP tools and the reference overview, which links one page per command.
For an agent. Read your tool list to find your surface, rather than running a command and inspecting the failure. When memory_search is absent from that list, you are on the CLI.
4. The shortest path to a working integration
Section titled “4. The shortest path to a working integration”On the MCP surface there is no setup: call memory_search with prose, then memory_read on a hit’s path. On the command line:
memhtml manifest # the contract, and the liveness checkmemhtml init # scaffold a store at --repo or $MEMHTML_ROOTmemhtml write --title … --claim … # one memory, one fact, one commitmemhtml search "prose, not a query language" --denseMake --dense a habit on every call. It emits minified JSON with null fields dropped, which is what you want when the output goes into a prompt. memhtml recall runs the same retrieval under a character budget, for when you want a context pack rather than a hit list.
Every command writes exactly one JSON envelope to stdout and nothing else, and sends its logs to stderr. The one exception is memhtml help on a terminal, which writes Markdown; piped, or with --json, it is an envelope like every other command. Exit 0 is success. Exit 2 is a usage error you fix by changing the call. Exit 1 is a runtime failure you fix by changing the store or the environment.
When you are the operator wiring a host agent rather than the agent being wired, one command is the whole path: it writes the host’s MCP entry, its hooks, an instruction block, and a skill, and records them in a receipt so uninstall removes exactly that.
memhtml integrations install # claude, codex, cursor, opencode; omitted, it detects them5. What to avoid
Section titled “5. What to avoid”- Scraping these pages. Every one of them is served as Markdown; section 7 has the URLs.
- Parsing the
errorprose. Section 2 explains what that costs you. - Writing a query language into
memhtml search. The argument is prose, and retrieval fuses four ranking arms, so an operator syntax has nothing to bind to. - Bundling unrelated writes. The store owns staging and every corpus change is exactly one commit, so a caller cannot make one commit mean two things. Use
memhtml applywhen the writes are one change. - Spending a tool call per hop. A question that needs several traversals of the corpus is one
memhtml execscript against a read-only mount. See the code-mode guide. - Editing
.memhtml/index.db, or hand-writing a memory file’s markup from memory. Write through the commands, which own the commit and the validation.
6. Read next
Section titled “6. Read next”Each row carries the page and its raw Markdown, so you can fetch rather than render. The reference tier is generated from the source registries, and it is where every count and every enumerated value lives.
| Read this | Raw Markdown |
|---|---|
First call: the envelope, the exit codes, --dense |
first-call.md |
| Write surfaces: the three ways in | write-surfaces.md |
| When to batch: one write or many | when-to-batch.md |
| Conflicts: what a contradiction does | conflicts.md |
| Authoring: the markup a memory is | authoring.md |
| Code mode: many hops in one call | code-mode.md |
| Error codes: the values you branch on | error-codes.md |
Response types: the type discriminators |
response-types.md |
| MCP tools: the tools and their arguments | mcp-tools.md |
| Commands: every command, one page each | reference.md |
7. The machine surfaces
Section titled “7. The machine surfaces”Any page is available as Markdown: append .md to its path. /reference/mcp-tools/ is served at /reference/mcp-tools.md as text/markdown. This holds for every page on the site, including the generated ones, and each page links its own twin from <head> with rel="alternate" type="text/markdown".
The whole site comes three ways. llms.txt is the index, and it lists this page first. llms-full.txt is every page in one file. llms-small.txt is the same corpus with non-essential content removed, for a tighter context.
For an agent. Fetch llms-small.txt before llms-full.txt. When you already know which page you want, fetch that page’s .md twin instead of either bundle: it is a fraction of the tokens and the same text.