What memkith is
memkith gives every coding agent on your team the same memory of a repository: the decisions, constraints, failed attempts and preferences that the code alone does not explain.
Agents start every session from zero. The one that spent an hour learning why the retry logic is shaped the way it is leaves nothing behind for the next one. memkith is where that hour goes. An agent records what it learned the moment it learns it, addressed to the files it concerns, and any agent your team points at the repository later recalls it before it touches those files.
Three rules shape everything below.
- Memory is written mid-session, as a reflex. There is no end-of-session summary step. An agent recalls before it plans or edits non-trivial code, and learns right after a meaningful investigation, correction or failed attempt.
- Memory belongs to a repository. It is scoped to paths inside one GitHub repository and shared with the people who have been given access to that repository in memkith.
- Your code never leaves your machine. memkith stores the text of each memory and the paths it points at, never file contents.
How it works
memkith runs in three places. On your machine, the CLI installs two programs your agent talks to: memkith-mcp, an MCP server with three tools, and memkith-hook, a hook that injects your team’s standing rules before every edit. memkith.com handles sign-in and decides which project a checkout belongs to. The memories API stores memories in Postgres, where row-level security checks every read and write against your access.
Your machine
Installed by the CLI
your agentClaude Code, Codex, Cursor, Zed
memkith-mcpRecall, learn, update over stdio
memkith-hookDirectives before every edit
.memkith/Directives, checked into the repo
memkith.com
Identity and access
/cli/loginBrowser sign-in, PKCE
/cli/exchangeCLI token to access token
/cli/repos/resolveorigin remote to project
dashboardProjects, people, grants
Memories API
api.memkith.com
/v1/memoriesRead, create, edit in place
Postgres + RLSEvery query runs as you; policies decide
- 01
Session start
Your agent launches memkith-mcp and reads its instructions: recall before non-trivial work, learn when something durable happens.
- 02
Before an edit
memkith-hook injects your standing directives into the agent's context. Local only, no network.
- 03
Recall
memkith-mcp exchanges your CLI token for a 15-minute access token, fetches the repository's memories, and ranks them on your machine.
- 04
Learn or update
The memory is written through the API. Postgres decides, row by row, whether you may read or write that repository.
The agent drives it. memkith has no background daemon, does not watch your files, and does not read your transcripts. Nothing is remembered unless an agent decides it passes the bar and calls memkith_learn.
Set up
The quickstart is the guided version. This is the same path in one place, including the two optional steps the quickstart leaves out.
1. In memkith: connect GitHub and turn on a project
From the dashboard, install the memkith GitHub App on the account or organization that owns the repository. memkith syncs the repositories the App can see, but none of them capture memory until you turn them on at Projects. The App reads repository names, never code.
2. Install the CLI
This installs memkith, memkith-hook and memkith-mcp as native binaries on macOS and Linux, so no Python is needed. On Windows, or if you prefer npm:
3. Sign in from the repository root
This opens a browser, signs this machine in, stores the credential in your OS keychain, and creates .memkith/ in the current directory with a directives.md template. Commit .memkith/; it holds no secrets. For another repository on the same machine, create a .memkith/ folder there yourself, or run memkith login again from it.
4. Connect your agent
memkith integrate <agent> prints the setup for each agent. For the two most common:
Claude Code. Run from the repository root. It writes the server into that project's .mcp.json.
Codex. Registers the server once for every Codex session on this machine.
Cursor takes {"mcpServers":{"memkith":{"command":"memkith-mcp","args":[]}}} in .cursor/mcp.json. Zed takes "memkith":{"command":"memkith-mcp","args":[],"env":{}} under context_servers in .zed/settings.json. Any other agent that speaks MCP over stdio can run memkith-mcp the same way.
5. Optional: add the directives hook
For Claude Code, add this to .claude/settings.json so directives reach the agent before every edit:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [{ "type": "command", "command": "memkith-hook" }]
}
]
}
}6. Optional: fill commit anchors automatically
See commit anchors for what this does.
7. Start a new session and make the first memory
Agents read MCP servers at startup, so a session that was already open will not see memkith. In a fresh one, give it something worth remembering:
Each memory appears on the project’s page in the dashboard as soon as it is written.
Anatomy of a memory
A memory is one self-contained claim about a repository. This is what an agent sees when it recalls one:
## Retries on the billing webhook must be idempotent
[mem-3f1c9a52-… · kind failure · scope src/billing/webhook.ts · commit a41e9d2 · by Ada Park <[email protected]> · from claude-code/7b2e… · 2026-09-14]
Re-check when: the webhook handler stops keying on event.id
Stripe redelivers on any non-2xx, and the first version charged twice
when the handler timed out after writing. The handler now records
event.id before side effects and returns 200 on a repeat. Do not
move the insert after the charge call.| Field | What it holds |
|---|---|
heading | One line that states the claim. It is what a reader scans. |
content | The claim in full, including why it is true. It must stand on its own for someone who was not in the session. |
kind | decision, constraint, failure, preference or claim (the default). Describes the shape of the knowledge. It does not affect ranking. |
scope | Repository-relative paths, files or directories, that the memory is about. Empty means it applies to the whole repository. Absolute paths, backslashes and .. are rejected. |
reuse rule | When the memory is safe to rely on, and what should make an agent re-check it. Shown as Re-check when. |
id | mem- followed by a UUID. Never changes, even when the memory is edited. |
author | Your git user.name and user.email at the time it was learned. |
source | The agent and conversation it came from, for example claude-code plus the session id. Filled in automatically. |
commit | The commit the claim was true at, or pending until the scoped files are committed. See commit anchors. |
branch | The branch it was learned on. Recorded for provenance only; see the last section. |
The five kinds
- decision: a choice the team made, with the alternative it rejected. “Invoices are immutable once sent; corrections are a new credit note, not an edit.”
- constraint: something the code must respect that nobody chose. “The payments provider retries webhooks for 72 hours, so handlers must be idempotent.”
- claim: any other durable fact, such as a coupling between distant files. The default.
- failure: something that was tried and did not work. Written as symptom, cause, fix, so the next agent skips the hour.
- preference: how the team wants something done when more than one way is correct. “Prefer server actions over route handlers for dashboard forms.”
Duplicates are reinforced, not stored twice
Before a memory is saved, its content is compared, ignoring case and punctuation, with every memory already in the repository. An exact match returns the existing id as reinforced and writes nothing. The server repeats the check under a lock, so two agents learning the same thing at the same moment still produce one memory.
Memories are edited in place
When code or a decision contradicts a memory, the agent calls memkith_update with its id. Heading, content, kind, scope and reuse rule can change. Author, source, creation date and repository cannot. There is no version history and no supersession chain: the memory is simply corrected.
What makes a good memory
memkith is only as useful as what goes into it. The MCP server hands every agent the same bar at the start of each session. A candidate is stored only if it passes all four gates:
| Gate | The question |
|---|---|
Durable | Is it likely to be true beyond this task or session? |
Non-obvious | Would the code, the diff and the existing docs fail to tell the next agent this? |
Actionable | Would knowing it change a future agent's plan, edit or diagnosis? |
Grounded | Is it backed by code, a test, an observed failure or an explicit team decision? |
Before learning, the agent recalls in the affected scope. If the same claim exists and is still true, it adds nothing. If an existing claim is now wrong, it updates that one instead of adding a second.
Worth remembering
- “The CSV importer streams rows because the largest customer files are 2 GB; loading them whole OOMs the worker.” A constraint the code implies but never states.
- “Upgrading pg to 8.12 broke connection pooling under Workers. Symptom: intermittent ECONNRESET. Cause: the new keepalive default. Fix: pin 8.11 until the pool is replaced.” A failure, in the shape that saves time.
- “We chose row-level security over checks in handlers so a forgotten check fails closed.” A decision, with its reason.
Not worth remembering
- What the code already says: function signatures, file layout, what a diff changed.
- Transient status: “the build is red”, “I am halfway through the refactor”.
- Speculation nobody has confirmed.
- One-off instructions for the current task.
- Secrets of any kind. memkith does not scan for them, so this one is on you and your agent.
Directives
Some knowledge is not about a file. It is a rule that applies to every action: which test runner to use, which folder never to touch. Those go in .memkith/directives.md, checked into the repository.
# Directives
Always-on agent-behavior rules, one per `- ` line.
- run tests with `pnpm test`, never `npx jest`
- never edit files under drizzle/ that are already applied
> - quoted lines are inactive examples and are ignoredEvery line that starts with - is one directive. Everything else is ignored, including quoted lines, which makes > - a convenient way to keep an example or park a rule.
memkith-hook reads the file before each edit and returns the directives as extra context for the agent:
{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Standing directives (apply to every action):\n- run tests with `pnpm test`, never `npx jest`\n- never edit files under drizzle/ that are already applied"}}- It is local. No network, no sign-in, no MCP server needed. Directives keep working offline.
- It never blocks. With no
.memkith/folder or no directives it prints nothing and exits 0, and it never denies a tool call. - Directives are not memories. They are not recalled, ranked or scoped; they are sent before every matched edit. Keep the list short.
Run memkith hook in the repository to see exactly what your agent will receive.
Commit anchors
Every memory records the commit it was true at, so a reader can tell how old the code behind it is. Which commit depends on the scope:
- Scoped, files committed: the latest commit that touched those files.
- Scoped, files uncommitted: the literal
pending. Agents usually learn while the change is still in the working tree, so this is the common case. - Repository-wide: the current HEAD.
A pending anchor is filled in once the files are committed, in one of three ways: by running memkith resolve, by the post-commit hook that memkith install-git-hook writes, or on the next memkith_learn in that repository.
#!/bin/sh
# memkith-managed-hook
# Backfill commit anchors for memories whose scoped code just landed.
# Best-effort; a post-commit hook never blocks the commit.
'/opt/homebrew/bin/memkith' resolve --quiet >/dev/null 2>&1 || trueThe hook is best-effort and silent. A commit never waits on it and never fails because of it. If you already have a post-commit hook, memkith leaves it alone and tells you to add memkith resolve --quiet to it yourself.
Workspaces and access
Memory access is granted in memkith and nowhere else. Being able to push to a repository on GitHub gives you nothing here; being granted access here does not touch GitHub.
Workspaces
Every account gets a workspace on its first visit to the dashboard, with you as its owner. Installing the GitHub App attaches the GitHub account or organization to it. People join from the Team page, as members.
| Role | Can |
|---|---|
owner | Write every project's memory, always. Add and remove people, grant access, turn projects on and off. Cannot be removed. |
admin | Add ordinary members, grant and revoke access, turn projects on and off. Memory access comes from grants like anyone else. |
member | Read or write the memory of the projects they have been granted, nothing more. |
Projects
A project is one GitHub repository that the workspace has turned on. The App syncs every repository it can see; turning one on is the deliberate step that lets memory be read and written. Turning a project off keeps its memories and grants, and turning it back on restores them. If a repository is removed from the App’s selection on GitHub, its memory is unreachable until it is selected again.
A checkout finds its project through its origin remote, normalized to github.com/owner/name in lower case. The lookup fails closed: an unknown, disconnected or forbidden repository is an error, never a silent fallback to somewhere else.
Grants
On a project’s Access tab, an owner or admin gives a member read or write. Read lets their agent recall. Write also lets it learn and update. Two details matter:
- Removing someone from the workspace deletes their grants. If they are added back they start with none.
- Writing a memory does not give you lasting rights to it. Lose access to the project and you lose access to what you wrote there; the memory stays with the project.
MCP tool reference
memkith-mcp exposes exactly three tools over stdio. Each returns plain text. Errors come back as text beginning error:, so the agent can read and act on them.
memkith_recall
Retrieve memories relevant to a question and/or the files being worked on. Call before planning or editing non-trivial code.
| Name | Type | What it does |
|---|---|---|
query | string = "" | A natural-language question or topic keywords. |
scope | string[] | Repository-relative files or folders you are working on. |
k | int = 10 | The most memories to return. |
kind | string | Only return memories of this kind, for example failure before retrying something. Omit for every kind. |
Returns No relevant memories., or the matches formatted as in the example above, separated by blank lines.
memkith_learn
Record new knowledge, only after the four gates pass and recall confirms it is not a duplicate.
| Name | Type | What it does |
|---|---|---|
heading | string | Required. One-line summary of the claim. |
content | string | Required. The self-contained claim, including the why. |
scope | string[] | Repository-relative paths it applies to. Empty or omitted means repository-wide. |
kind | string = "claim" | decision, constraint, failure, preference or claim. |
reuse_rule | string | When it is safe to reuse, and what should trigger a re-check. Must not be blank if passed. |
source | string | Overrides the automatic agent-and-conversation provenance. Normally omitted. |
Returns created mem-… or, for an exact duplicate, reinforced mem-…. Author, branch and commit are filled in from git.
memkith_update
Edit a memory in place when the current code or an explicit decision contradicts it. Pass only the fields to change.
| Name | Type | What it does |
|---|---|---|
memory_id | string | Required. The id from a recall result. |
heading | string | New one-line summary. |
content | string | New self-contained claim, including the why. |
scope | string[] | The full new list of paths. An empty or omitted list keeps the current scope; it never clears it. |
kind | string | New kind. |
reuse_rule | string | New reuse rule. |
repo_wide | bool = false | Detach the memory from every path. The only way to clear scope. Cannot be combined with a scope. |
Returns updated mem-…. Fails with no memory with id '…' when the id does not exist or you cannot see it, and with nothing to update when no field was passed.
CLI reference
The CLI is plumbing: it signs you in and sets things up. Memory itself is read and written only by agents, through MCP, so there is no recall or learn command. memkith --help is the authority for your installed version.
Sign in through the browser. On success it prints
Signed in as [email protected].and creates.memkith/in the current directory if it is missing. Without--force, an existing session prints a warning and is replaced anyway; press Ctrl-C to keep it.--no-browserPrint the sign-in URL instead of opening a browser.--forceReplace an existing session without the warning.
Show the signed-in account, which website and API this machine talks to, where the token is stored, and whether the access token is valid, expiring or expired. Exits 1 when signed out.
--refreshForce a token exchange before reporting.
Print the MCP setup for one or more agents:
claude,codex,cursor,zed. It prints and never writes; you run or paste what it prints.--allPrint the setup for all four agents.
Write a
post-commithook that runsmemkith resolveafter every commit. Respectscore.hooksPathand worktrees. It refuses to overwrite a hook it did not write.Stamp the commit on memories whose scoped files have since been committed. Idempotent, so it is safe to run at any time.
--quietPrint nothing, for use from the git hook.
Print the directive payload the hook would inject. Same as running
memkith-hook; useful to check your directives parse.Revoke this machine's session on memkith.com and delete the local credential. Local state is cleared even when the website cannot be reached.
Print the installed version.
What leaves your machine
memkith never reads, uploads or stores your source code. This is the complete list of what does leave your machine:
- The heading, content, kind, scope and reuse rule of each memory your agent writes.
- Its provenance: your git name and email, the branch, the commit, and the agent and conversation id.
- Your
originremote URL, with any credentials stripped, to find the project. - At sign-in, your machine’s name, so you can tell sessions apart in settings.
Credentials
Signing in gives the machine a CLI token (it starts mks_) that lasts 30 days, kept in your OS keychain. memkith.com stores only its hash. The token is never sent to the memories API; it is exchanged for a 15-minute access token that is. Revoke a machine from settings or by running memkith logout on it. An access token already issued stays valid until it expires, at most 15 minutes later.
Keeping and deleting
Memories do not expire. Turning a project off keeps them. Removing a person keeps what they wrote. There is no way to delete a single memory yet; correct it with memkith_update instead.
Troubleshooting
Start with memkith status. It says whether you are signed in, as whom, and against which environment. Most other problems are one of these, listed by the message or symptom you will see.
- not signed in for https://memkith.com; run `memkith login`
- No session on this machine, or it was cleared. Run
memkith login. Check withmemkith status. - this repository is not connected to Memkith, or you do not have memory access to it yet
- The most common one. Either the project is not turned on at Projects, or you have no grant on it. A workspace owner or admin grants access from the project’s Access tab. memkith answers these cases identically on purpose.
- this checkout has no origin remote
- memkith identifies the project by
git remote get-url origin. Add the GitHub remote asorigin. A fork has a different origin, so it does not match the upstream project. - this checkout's origin is not a GitHub repository URL
- Only GitHub repositories can be connected today. GitLab and self-hosted remotes are not resolvable yet.
- this GitHub repository is not connected to Memkith
- The GitHub App is not installed on the account that owns the repository, or the repository is not in its selection. Fix it from Projects.
- the Memkith memories API rejected this session; run `memkith login`
- The access token was refused even after one automatic refresh. Sign in again. If it persists, check that MEMKITH_ENV is unset or set to production.
- the Memkith memories API denied access to this memory (HTTP 403)
- You can read this project but not write to it. Ask an owner or admin for write access.
- could not reach the Memkith memories API
- You are offline, or a proxy blocks api.memkith.com. Recall and learn need the network; directives do not, and keep working.
- The agent never calls memkith_recall
- An agent reads its MCP servers at startup. Start a new session after connecting it, and confirm the server is listed (for Claude Code, /mcp). Then ask it to recall something by name once.
- Memories land on the wrong project, or none
- The MCP server picks the nearest folder with a
.memkith/directory above where the agent launched it, falling back to that directory. If your agent starts servers elsewhere, setMEMKITH_REPO_ROOTin the server’s environment. - timed out after 300s waiting for the browser callback
- The browser never returned to the CLI. On a remote machine use
memkith login --no-browser. Raise the wait withMEMKITH_LOGIN_TIMEOUT. - brew refuses to load the formula
- Homebrew requires third-party taps to be trusted first. Run
brew trust memkith/memkith, then install again.
What memkith does not do yet
Knowing the edges saves you from building on something that is not there. As of today:
- Branches do not isolate memory. The branch is recorded, but recall returns a project’s memories regardless of it. A memory learned on a feature branch is visible on main immediately.
- Scope is paths, not symbols. There are no function or line anchors. When a file moves, its memories keep the old path until an agent updates their scope.
- Recall matches words, not meaning. There are no embeddings. Use the repository’s own terms, and pass paths.
- GitHub only. Projects come from the GitHub App; other hosts cannot be connected.
- No deletion. Memories can be corrected, not removed.
- Local MCP only.
memkith-mcpruns on your machine over stdio. A hosted MCP endpoint is not available. - The hook is for Claude Code. Other agents get memory through MCP but not directives, unless they support an equivalent pre-edit hook you can point at
memkith-hook.
What is being worked on next is on the roadmap.