{
  "markdown": "# AnchorDB\n\n**Code memory for AI coding agents.** AnchorDB is an MCP server that stores notes\nattached to specific code — a file, a line range, a symbol — and keeps them\nattached as that code moves. The context an agent builds up in one session is\nstill there in the next one.\n\nPoint Claude Code, Cursor, or any Model Context Protocol host at it, and an agent\ncan read *why* a workaround exists before editing it, and leave notes for whoever\ncomes next. Everything stays local: one SQLite file, your git repositories, no\nnetwork calls, no account.\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/jolovicdev/anchor-db/master/install.sh | sh\nclaude mcp add anchordb -- anchordb-mcp --db ~/.anchordb/anchor.db\n```\n\nNo account, no API key, and nothing to run in the background. `git` is the only\nrequirement; prebuilt binaries cover Linux, macOS, and Windows, and there is a\n[container image](#with-docker) and a [Go install](#with-go) path too.\n\nThree ways in, over the same data:\n\n| | |\n|---|---|\n| `anchordb-mcp` | MCP server for coding agents. Talks to SQLite directly; no daemon needed. |\n| `anchorctl` | Command-line client for shells, scripts, and CI. |\n| `anchord` | HTTP API and web viewer for reading code and notes in a browser. |\n\n## Why\n\nChat history is a bad place to keep what you learn about a codebase. It scrolls\naway, it is not attached to anything, and the next session starts blank.\n\nA comment in the source is better, but you cannot leave one everywhere, and much\nof what matters does not belong in the file: a reproduction for a bug you did not\nfix, why the obvious refactor is wrong, what broke the last time someone touched\nthis retry loop, where you stopped.\n\nAnchorDB keeps those notes beside the code instead of inside it, and follows the\ncode when it moves. A note pinned to a function is still on that function after\nyou rename it, reorder the file, or move it to another package.\n\n## Use cases\n\n- Coding agents that should read context before editing a file or symbol\n- Agent handoffs, where one run leaves precise notes for the next\n- Long debugging sessions, keeping repros and findings attached to the code\n- Review notes on risky paths — billing, auth, migrations, retry logic\n- Any codebase where the reason for a decision outlives the person who made it\n\n## How It Works\n\nAnchorDB stores `anchors`.\n\nEach anchor contains:\n\n- repo metadata\n- a note body and kind\n- a file path\n- a line and column range\n- selected text plus surrounding context\n- an optional symbol path\n\nWhen files change, AnchorDB re-resolves anchors using the saved span, text context, and symbol information. Tree-sitter improves symbol extraction and relocation, but the system still works without it.\n\nResolution tries strategies from most to least certain and stops at the first\nthat holds up:\n\n1. **Exact span** — the recorded lines still hold the recorded text.\n2. **Git line mapping** — each anchor records the commit its line numbers were\n   taken against, so `git diff` says exactly where those lines went. This is\n   deterministic where text matching can only guess, and it is the difference\n   between finding the right copy of a duplicated block and finding the first\n   one. The mapping is always verified against the stored text before it is\n   applied, so it degrades safely rather than mis-anchoring.\n3. **Symbol match** — the same symbol path, scored on how much of its body\n   survived.\n4. **Text and context match** — the recorded text found elsewhere in the file,\n   ranked by surrounding context.\n\nAn anchor that none of these can place is marked `stale` and keeps its last\nknown position. Because the diff is available, a stale anchor can say whether\nits code was *rewritten in place* or *deleted outright*. Resolution is per-path\nand failures are isolated, so one unresolvable file never stops the rest of a\nrepo from syncing.\n\nAnchors written before this existed have no recorded base commit; they simply\nskip the git step and fall back to text matching.\n\n## Triage\n\nStale anchors are a queue, not a dead end. AnchorDB ranks the places each one\nmight now belong -- with a confidence score and a code preview -- and lets you\naccept one:\n\n```bash\nanchorctl anchor stale --repo-id repo_123\nanchorctl anchor candidates --id anchor_123\nanchorctl anchor relocate --id anchor_123 --candidate 0\n```\n\nRelocating re-reads the span from the file, re-derives the symbol at the new\nposition, and re-bases the anchor onto the current commit, so the next automatic\npass can follow it through git again. To re-pin somewhere the suggestions\nmissed, give an explicit range instead:\n\n```bash\nanchorctl anchor relocate --id anchor_123 --start-line 42 --end-line 58\n```\n\nThe same loop is available to agents over MCP (`anchor_stale`,\n`anchor_candidates`, `anchor_relocate`), so a run that refactors code can re-pin\nthe notes it left behind. In the web viewer it appears as a review panel on each\nstale anchor.\n\n## History\n\nEvery move, stale, and update is recorded with its reason and confidence, and\nthat history is readable everywhere:\n\n```bash\nanchorctl anchor events --id anchor_123\n```\n\nIt answers \"why is this note here?\" — for example `created`, then\n`moved · git line mapping`, then `stale · the anchored lines were deleted or\nrestructured`. Resolution passes that change nothing record nothing, so the\nhistory stays signal.\n\nPaths are always interpreted as repo-relative and confined to the repository:\nrequests that try to escape the root, follow a symlink out of it, or read `.git`\nare rejected. Git refs that would be parsed as command-line options are refused\nfor the same reason.\n\nBuilt-in symbol extractors:\n\n- Go\n- Python\n- JavaScript\n- TypeScript\n\n## Install\n\n`git` is the only runtime requirement. Every release ships prebuilt binaries for\nLinux, macOS, and Windows, so a Go toolchain is only needed if you build from\nsource.\n\nOnly `anchordb-mcp` is needed to use AnchorDB from a coding agent. `anchorctl`\nand `anchord` add the command-line client and the web viewer.\n\n### Download a binary\n\nLinux and macOS:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/jolovicdev/anchor-db/master/install.sh | sh\n```\n\nThat fetches the archive for your platform, verifies it against the release\nchecksums, and installs into `~/.local/bin`. Set `ANCHORDB_INSTALL_DIR` to put it\nsomewhere else, or `ANCHORDB_VERSION` to pin a version.\n\nTo do it by hand instead, take the archive for your platform from the\n[releases page](https://github.com/jolovicdev/anchor-db/releases), unpack it, and\nmove the binaries onto your `PATH`. `checksums.txt` in each release covers every\narchive.\n\n### With Go\n\nRequires Go 1.25 or newer.\n\n```bash\ngo install github.com/jolovicdev/anchor-db/cmd/anchordb-mcp@latest\ngo install github.com/jolovicdev/anchor-db/cmd/anchorctl@latest\ngo install github.com/jolovicdev/anchor-db/cmd/anchord@latest\n```\n\nFrom a local checkout:\n\n```bash\ngo install ./cmd/anchordb-mcp ./cmd/anchorctl ./cmd/anchord\n```\n\nIf the installed command is not found afterwards, the Go bin directory is not on\nyour `PATH`:\n\n```bash\ngo env GOBIN          # if empty, binaries are in $(go env GOPATH)/bin\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n```\n\n### With Docker\n\n```bash\ndocker run --rm -i \\\n  -v ~/.anchordb:/data \\\n  -v /path/to/repo:/path/to/repo \\\n  ghcr.io/jolovicdev/anchor-db:latest\n```\n\nAnchors record absolute repository paths, so mount each repository at the same\npath it has on the host — otherwise the paths stored in the database will not\nmatch anything the container can see. The container is only worth the trouble in\nCI or a sandbox; a binary on the host is simpler everywhere else.\n\n### Verify\n\n```bash\nanchordb-mcp --version\n```\n\n### Where to keep the database\n\nOne database holds many repositories. A stable per-user location works well:\n\n```bash\nmkdir -p ~/.anchordb\n```\n\nUse `~/.anchordb/anchor.db` in the commands below. Keep it out of your\nrepositories — it is local state, not source, and does not belong in git.\n\n## Install with a coding agent\n\nIf you would rather have an agent do this, point it at this repository and say\n\"install this\". The steps below are written to be followed directly.\n\n**1. Check prerequisites.** `go version` (needs 1.25+) and `git --version`. If Go\nis missing, stop and ask before installing a toolchain.\n\n**2. Install the MCP server.**\n\n```bash\ngo install github.com/jolovicdev/anchor-db/cmd/anchordb-mcp@latest\n```\n\n**3. Find the binary.** `go env GOBIN`, or `$(go env GOPATH)/bin` if that is\nempty. Use the absolute path in step 5 rather than editing shell profiles.\n\n**4. Choose a database path.** `mkdir -p ~/.anchordb` and use\n`~/.anchordb/anchor.db`. Do not put it inside the user's repository.\n\n**5. Register the server.** For Claude Code:\n\n```bash\nclaude mcp add anchordb -- /absolute/path/to/anchordb-mcp --db /absolute/path/to/anchor.db\n```\n\nFor any host using `mcpServers` JSON, merge — do not overwrite — the entry shown\nunder [Claude Code Setup](#claude-code-setup). Absolute paths only; most hosts do\nnot expand `~`.\n\n**6. Verify.** `anchordb-mcp --version` should print a version. Restart the host\nand confirm `anchor_context` appears in the tool list. If it does not, the config\nwas not picked up: check you edited the config for the host that is running, and\nthat it fully restarted.\n\n**7. Register the repository** with the `repo_add` tool, or:\n\n```bash\nanchorctl repo add --name <name> --path /path/to/repo\n```\n\nReport the returned repo ID to the user; most commands take it.\n\n### Using it well\n\nRead before editing. Call `anchor_context` with the repo ID and file path before\nmodifying a file. Anchors record what the code does not say — why a workaround\nexists, which invariant a function holds, what broke last time. Skipping that is\nhow the same bug gets reintroduced.\n\nWrite what is durable and non-obvious. Good anchors: a constraint the types do\nnot enforce, why an appealing simplification is wrong, a reproduction for a bug\nyou did not fix, handoff state when stopping mid-task. Set `author` to identify\nyourself, for example `agent://claude`.\n\nSkip what the code already says. A note restating a function signature is noise,\nand noise buries the anchors that matter.\n\nRe-pin what you break. After a refactor, call `anchor_stale` for the repo. Use\n`anchor_candidates` to see suggested new locations and `anchor_relocate` to\naccept one, or give an explicit line range if you know better. Leaving stale\nanchors behind makes the next run worse than the last.\n\nDo not commit the database, and do not delete anchors you did not create without\nasking.\n\n## Quick Start\n\nStart the server:\n\n```bash\nanchord --db ~/.anchordb/anchor.db\n```\n\nRegister a repo:\n\n```bash\nanchorctl repo add --name demo --path /path/to/repo\n```\n\nCreate an anchor:\n\n```bash\nanchorctl anchor create \\\n  --repo-id repo_123 \\\n  --ref WORKTREE \\\n  --path internal/service/run.go \\\n  --start-line 42 \\\n  --start-col 1 \\\n  --end-line 49 \\\n  --end-col 2 \\\n  --kind warning \\\n  --title \"Retry must stay idempotent\" \\\n  --body \"This path duplicated writes during incident 2026-02-14.\" \\\n  --author human://alice\n```\n\nOpen the viewer:\n\n```text\nhttp://127.0.0.1:7740/\n```\n\nStart the MCP server:\n\n```bash\nanchordb-mcp --db ~/.anchordb/anchor.db\n```\n\n## CLI\n\n`anchorctl` talks to the running HTTP server.\n\nIt reads the base URL from `ANCHOR_DB_URL`. Default:\n\n```text\nhttp://127.0.0.1:7740\n```\n\n### Repo Commands\n\nAdd a repo:\n\n```bash\nanchorctl repo add --name demo --path /path/to/repo\n```\n\nList repos:\n\n```bash\nanchorctl repo list\n```\n\nGet one repo:\n\n```bash\nanchorctl repo get --id repo_123\n```\n\nSync one repo:\n\n```bash\nanchorctl repo sync --id repo_123\n```\n\nRemove one repo:\n\n```bash\nanchorctl repo remove --id repo_123\n```\n\n### Anchor Commands\n\nList anchors:\n\n```bash\nanchorctl anchor list --repo-id repo_123 --path internal/api/server.go --limit 20 --offset 0\n```\n\nGet one anchor:\n\n```bash\nanchorctl anchor get --id anchor_123\n```\n\nCreate an anchor:\n\n```bash\nanchorctl anchor create \\\n  --repo-id repo_123 \\\n  --ref WORKTREE \\\n  --path internal/api/server.go \\\n  --start-line 40 \\\n  --start-col 1 \\\n  --end-line 52 \\\n  --end-col 2 \\\n  --kind warning \\\n  --title \"Keep request validation strict\" \\\n  --body \"This handler should reject empty repo_id values.\" \\\n  --author human://alice\n```\n\nUpdate anchor metadata:\n\n```bash\nanchorctl anchor update \\\n  --id anchor_123 \\\n  --kind handoff \\\n  --title \"Next step\" \\\n  --body \"Trace the retry path before changing the timeout logic.\" \\\n  --author agent://planner \\\n  --tags billing,handoff\n```\n\nArchive an anchor:\n\n```bash\nanchorctl anchor close --id anchor_123\n```\n\nReopen an anchor:\n\n```bash\nanchorctl anchor reopen --id anchor_123\n```\n\nRe-run anchor resolution:\n\n```bash\nanchorctl anchor resolve --id anchor_123\n```\n\n### Context, Comments, Search\n\nGet file or symbol context:\n\n```bash\nanchorctl context --repo-id repo_123 --ref WORKTREE --path internal/api/server.go --symbol \"*Server.handleRepos\"\n```\n\nList comments:\n\n```bash\nanchorctl comment list --anchor-id anchor_123\n```\n\nAdd a comment:\n\n```bash\nanchorctl comment add --anchor-id anchor_123 --author human://alice --body \"Confirmed in production replay.\"\n```\n\nFull-text search:\n\n```bash\nanchorctl search --query retry --repo-id repo_123 --path internal/api/server.go\n```\n\nQueries are treated as literal text, so punctuation-heavy terms such as `C++`,\n`don't`, or `retry (v2)` are safe to search for. Multiple terms are ANDed, and a\ntrailing `*` performs a prefix search:\n\n```bash\nanchorctl search --query \"retry idempot*\" --repo-id repo_123\n```\n\nAll CLI commands return JSON.\n\n## HTTP API\n\nDefault listen address:\n\n```text\nhttp://127.0.0.1:7740\n```\n\n### Endpoints\n\n- `GET /health`\n- `GET /v1/repos`\n- `POST /v1/repos`\n- `GET /v1/repos/{repo_id}`\n- `POST /v1/repos/{repo_id}/sync`\n- `DELETE /v1/repos/{repo_id}`\n- `GET /v1/anchors`\n- `POST /v1/anchors`\n- `GET /v1/anchors/{anchor_id}`\n- `PATCH /v1/anchors/{anchor_id}`\n- `POST /v1/anchors/{anchor_id}/close`\n- `POST /v1/anchors/{anchor_id}/reopen`\n- `POST /v1/anchors/{anchor_id}/resolve`\n- `GET /v1/anchors/{anchor_id}/comments`\n- `POST /v1/anchors/{anchor_id}/comments`\n- `GET /v1/anchors/{anchor_id}/events`\n- `GET /v1/anchors/{anchor_id}/candidates`\n- `POST /v1/anchors/{anchor_id}/relocate`\n- `GET /v1/stale`\n- `GET /v1/context`\n- `GET /v1/search`\n- `GET /view`\n\n### Common Requests\n\nCreate a repo:\n\n```http\nPOST /v1/repos\nContent-Type: application/json\n\n{\n  \"name\": \"demo\",\n  \"path\": \"/path/to/repo\"\n}\n```\n\nResponse:\n\n```json\n{\n  \"id\": \"repo_123\",\n  \"name\": \"demo\",\n  \"root_path\": \"/path/to/repo\",\n  \"default_ref\": \"abc123...\",\n  \"created_at\": \"2026-03-11T10:00:00Z\",\n  \"updated_at\": \"2026-03-11T10:00:00Z\"\n}\n```\n\nCreate an anchor:\n\n```http\nPOST /v1/anchors\nContent-Type: application/json\n\n{\n  \"repo_id\": \"repo_123\",\n  \"ref\": \"WORKTREE\",\n  \"path\": \"internal/service/run.go\",\n  \"start_line\": 42,\n  \"start_col\": 1,\n  \"end_line\": 49,\n  \"end_col\": 2,\n  \"kind\": \"warning\",\n  \"title\": \"Retry must stay idempotent\",\n  \"body\": \"This path duplicated writes during incident 2026-02-14.\",\n  \"author\": \"human://alice\",\n  \"tags\": [\"billing\", \"warning\"]\n}\n```\n\nUpdate an anchor:\n\n```http\nPATCH /v1/anchors/anchor_123\nContent-Type: application/json\n\n{\n  \"kind\": \"handoff\",\n  \"title\": \"Next step\",\n  \"body\": \"Check the retry path before changing timeout handling.\",\n  \"author\": \"agent://planner\",\n  \"tags\": [\"billing\", \"handoff\"]\n}\n```\n\nClose, reopen, or resolve an anchor:\n\n```http\nPOST /v1/anchors/anchor_123/close\nPOST /v1/anchors/anchor_123/reopen\nPOST /v1/anchors/anchor_123/resolve\n```\n\nRead file context:\n\n```http\nGET /v1/context?repo_id=repo_123&ref=WORKTREE&path=internal/service/run.go&symbol=*Runner.Run\n```\n\nFull-text search:\n\n```http\nGET /v1/search?query=retry&repo_id=repo_123&path=internal/service/run.go&limit=20&offset=0\n```\n\nAdd a comment:\n\n```http\nPOST /v1/anchors/anchor_123/comments\nContent-Type: application/json\n\n{\n  \"author\": \"human://alice\",\n  \"body\": \"Confirmed in staging replay.\"\n}\n```\n\nAll API responses are JSON. Validation failures return:\n\n```json\n{\n  \"error\": \"message\"\n}\n```\n\n## MCP\n\n`anchordb-mcp` serves the same data over MCP stdio and reads the SQLite database directly. It does not require `anchord` to be running.\n\nRun it:\n\n```bash\nanchordb-mcp --db ~/.anchordb/anchor.db\n```\n\n### Claude Code Setup\n\nOn Linux or WSL, Anthropic currently documents two install paths for Claude Code:\n\n- native installer: `curl -fsSL https://claude.ai/install.sh | bash`\n- npm installer: `npm install -g @anthropic-ai/claude-code`\n\nAfter Claude Code is installed, add AnchorDB as a stdio MCP server:\n\n```bash\nclaude mcp add anchordb --scope project -- /absolute/path/to/anchordb-mcp --db /absolute/path/to/anchor.db\n```\n\nUseful follow-up commands:\n\n```bash\nclaude mcp list\nclaude mcp get anchordb\n```\n\nInside Claude Code, use `/mcp` to inspect configured MCP servers and their status.\n\nNotes:\n\n- `--scope project` stores the configuration in `.mcp.json` for the current project\n- `--scope local` keeps it private to your local project setup\n- `--scope user` makes it available across projects on your machine\n- everything after `--` is the actual server command and its arguments\n\nEquivalent `.mcp.json` entry:\n\n```json\n{\n  \"mcpServers\": {\n    \"anchordb\": {\n      \"command\": \"/absolute/path/to/anchordb-mcp\",\n      \"args\": [\"--db\", \"/absolute/path/to/anchor.db\"]\n    }\n  }\n}\n```\n\nOnce connected, a coding agent can:\n\n- read anchor context before editing a file\n- search previous notes and comments\n- create or update anchors during debugging\n- leave handoff notes for the next run\n\n### MCP Tools\n\n- `repo_add`\n- `anchor_repos`\n- `repo_get`\n- `repo_sync`\n- `repo_remove`\n- `anchor_context`\n- `anchor_create`\n- `anchor_update`\n- `anchor_close`\n- `anchor_reopen`\n- `anchor_resolve`\n- `anchor_comment`\n- `anchor_search`\n- `anchor_text_search`\n- `anchor_events`\n- `anchor_stale`\n- `anchor_candidates`\n- `anchor_relocate`\n- `anchor_get`\n- `anchor_comments`\n- `anchor_file_view`\n\n### MCP Resources\n\n- `anchordb://repos`\n- `anchordb://repo/{repo_id}`\n- `anchordb://context/{repo_id}{?ref,path,symbol}`\n- `anchordb://search{?query,repo_id,path,symbol,kind,limit,offset}`\n- `anchordb://anchors/{repo_id}{?path,symbol,status,limit,offset}`\n- `anchordb://file/{repo_id}{?ref,path}`\n- `anchordb://events/{anchor_id}`\n- `anchordb://anchor/{anchor_id}`\n- `anchordb://comments/{anchor_id}`\n\n## Viewer\n\nThe web viewer shows:\n\n- a repo file list\n- the selected file with highlighted anchor ranges\n- anchor cards and threaded comments\n- the Git working-tree diff for that file\n\nHighlighted lines mark anchor coverage. The diff panel shows the actual Git diff for the selected file.\n\n## Storage\n\nEverything lives in one SQLite database — anchors, comments, history, and the\nfull-text search index. No server, no external dependency, nothing leaves the\nmachine.\n\nAll three binaries read the same file:\n\n```bash\nanchord --db ~/.anchordb/anchor.db\nanchorctl repo list                 # via anchord\nanchordb-mcp --db ~/.anchordb/anchor.db\n```\n\nKeep it outside your repositories. It is local state, not source.\n\nBack it up by copying the file while nothing is writing, or with\n`sqlite3 anchor.db \".backup anchor-backup.db\"`.\n\n## Troubleshooting\n\n| Symptom | Cause | Fix |\n|---|---|---|\n| `command not found: anchordb-mcp` | Go bin directory not on `PATH` | `export PATH=\"$PATH:$(go env GOPATH)/bin\"`, or use absolute paths |\n| MCP host does not list the server | Config not reloaded | Restart the host fully; check `claude mcp list` |\n| `not a git repository` | Path is not a git checkout | `git init`, or point at the actual repository root |\n| `path escapes repository root` | Path outside the repo, or a symlink leaving it | Use a repository-relative path |\n| `invalid git ref` | Ref begins with `-` | Use a commit SHA, a branch name, or `WORKTREE` |\n| Anchors show as `stale` after a refactor | The code moved beyond automatic matching | Run the triage loop: `anchorctl anchor stale` |\n| `connection refused` from `anchorctl` | `anchord` is not running | Start it, or use the MCP tools, which need no daemon |\n| Search returns nothing for an exact phrase | Terms are ANDed | Try fewer terms, or a prefix: `retry idempot*` |\n\n## Versioning\n\nAnchorDB follows semantic versioning. All three binaries report the same\nversion:\n\n```bash\nanchord --version\nanchorctl version\nanchordb-mcp --version\n```\n\nThe database schema migrates forward automatically on open. Anchors created by\nearlier versions keep working; those written before git-aware resolution simply\nfall back to text matching until they next resolve cleanly.\n\nEach tagged release builds its binaries on the platform they target, publishes a\n`checksums.txt` covering every archive, and pushes a matching multi-architecture\nimage to `ghcr.io/jolovicdev/anchor-db`.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n",
  "bytes": 20758,
  "sha": "9c5b862e5e599c3dd20145b5f6791b734c26f2ea833609815e4dbe71ac3474d0",
  "repo_slug": "jolovicdev/anchor-db",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_jolovicdev_anchordb_ccd696a9/readme"
}