Back to Directory/Documentation

Kybase

Self-hosted Markdown memory for AI agents: notes you can read and edit, with hybrid search.

DocumentationTypeScriptv0.2.2

Kybase gives Claude, Cursor, Windsurf and any other MCP-speaking agent a long-term memory you own: one Markdown knowledge base, running on your own machine, that every agent can search, read and update — and that you can open in a browser and edit by hand.

Self-hosted. Private by default. Plain Markdown. Yours.

The problem · Quick start · Connect your agent · What you get · Settings · Sharing · Backups · Upgrading

The problem

You tell your agent how the staging deploy works. It helps, and the session ends.

Tomorrow you open a new one:

You: what did we decide about the staging database?

Agent: I don't have that context — could you tell me again?

So you explain it again. Then you switch editors, and explain it there too.

With Kybase, the knowledge lives outside the agent:

You: what did we decide about the staging database?

Agent: (searches Kybase) You moved staging to its own Postgres instance so migrations could be tested against real data first — that's in "Staging environment", under "Database".

New session, same memory. Different tool, same memory.

Quick start

One local agent

Nothing to install, no Docker, no database to run:

{
  "mcpServers": {
    "kybase": {
      "command": "npx",
      "args": ["-y", "kybase-mcp"]
    }
  }
}

Put that in your client's MCP config and restart it. Your notes live under ~/.kybase, and kybase-mcp export vault.zip gets them back out as plain Markdown at any time.

The full app

For the web UI, the graph view, share links, and several agents against one knowledge base:

macOS and Linux

git clone https://github.com/Kyrzin/kybase.git
cd kybase
cp .env.example .env
sed -i.bak "s/^KYBASE_SECRET=$/KYBASE_SECRET=$(openssl rand -hex 32)/" .env
sed -i.bak "s/^POSTGRES_PASSWORD=$/POSTGRES_PASSWORD=$(openssl rand -hex 16)/" .env
rm -f .env.bak
docker compose pull && docker compose up -d

Windows (PowerShell) — no openssl or sed there, so the secrets are generated by .NET instead:

git clone https://github.com/Kyrzin/kybase.git
cd kybase
Copy-Item .env.example .env
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$b = New-Object byte[] 32; $rng.GetBytes($b)
$secret = ($b | ForEach-Object { $_.ToString('x2') }) -join ''
$b = New-Object byte[] 16; $rng.GetBytes($b)
$pass = ($b | ForEach-Object { $_.ToString('x2') }) -join ''
(Get-Content .env) -replace '^KYBASE_SECRET=$', "KYBASE_SECRET=$secret" -replace '^POSTGRES_PASSWORD=$', "POSTGRES_PASSWORD=$pass" | Set-Content .env
docker compose pull
docker compose up -d

Either block generates the only two secrets you need and starts the stack. Open http://localhost:3000, log in with your KYBASE_SECRET — grep KYBASE_SECRET .env shows it, or Select-String KYBASE_SECRET .env on Windows — then connect an agent.

That installs the app and its database — around 1 GB. Notes and text search work right away.

Semantic search needs an embedding provider. Open Settings and pick one:

  • Google or OpenAI — paste an API key and you are done.

  • Ollama, on your own machine — start it once, then pick a model in Settings:

    docker compose --profile ollama up -d
    

    It is not in the default install because its image carries NVIDIA and AMD GPU runtimes whatever your hardware is — about 4 GB that someone using a cloud provider would never run. Starting it later touches nothing else: the app keeps running and no note is affected.

Connect your agent

Kybase speaks MCP over Streamable HTTP at /api/mcp. A client that supports OAuth signs in once in your browser and gets its own token — listed under Settings → Access and revocable on its own — so your KYBASE_SECRET never goes into its config.

Claude Code — add it once for all your projects:

claude mcp add --transport http --scope user kybase https://your-domain/api/mcp

Then run /mcp in Claude Code, pick kybase → Authenticate, and enter your KYBASE_SECRET on the page that opens.

That's it — the agent can now search your notes, read them, write new ones, update existing ones and link them together.

Other clients — Claude Desktop, claude.ai, Cursor, Windsurf

Claude Desktop and claude.ai — Customize → Connectors → Add custom connector, same URL, then Connect and sign in. Claude connects from Anthropic's servers, so the instance has to be reachable over HTTPS from the internet. In Claude Desktop, remote servers go here, not in claude_desktop_config.json.

Cursor — ~/.cursor/mcp.json (global) or .cursor/mcp.json (project):

{
  "mcpServers": {
    "kybase": {
      "url": "https://your-domain/api/mcp"
    }
  }
}

Then connect kybase under Customize → MCPs and sign in.

Windsurf — ~/.codeium/windsurf/mcp_config.json, with serverUrl instead of url:

{
  "mcpServers": {
    "kybase": {
      "serverUrl": "https://your-domain/api/mcp",
      "headers": {
        "Authorization": "Bearer <KYBASE_SECRET>"
      }
    }
  }
}

That header carries your KYBASE_SECRET, which is full access to the whole instance: use it only for a client without OAuth, and keep it in your own config — never in a file you commit.

Clients that only speak stdio use the npx -y kybase-mcp block from Quick start, in the same file.

What you get

  • Markdown, not an opaque memory blob — every note is plain text; read it, edit it, grep it, back it up with cp
  • One knowledge base, every agent — Claude, Cursor, Windsurf and the web UI all look at the same notes
  • Hybrid search — full-text and meaning-based search fused into one ranked result, so an agent finds the note whether it knows the exact wording or not
  • Section-level reads and writes — an agent reads or edits the part of a note it needs, not the whole file
  • Backlinks and a knowledge graph — [[wikilinks]] connect related notes automatically
  • Yours to take — Settings → Export .zip gives plain Markdown with folders as directories, readable by any editor, Obsidian included. Import .zip merges one back.

Obsidian and Notion are built for a person reading and writing. Kybase is built for the loop between you ↔ your knowledge ↔ your agent: you edit in the browser, an agent searches and updates over MCP, and both are looking at the same Markdown. If the agent remembered something wrong, you open the note and fix the sentence.

Private by default

Kybase runs on your infrastructure. No SaaS account, no external memory service, no cloud database — your own Postgres, local embeddings through Ollama, and a secret you generate.

Cloud embedding providers are optional. Choosing one sends your notes' full text to that provider to compute embeddings; Ollama keeps everything on your machine.

How agents use it

search_notes("deployment steps for staging")
  → hit includes section: "Rollback"
  → get_note(section: "Rollback")
  → agent reads just that section, not the whole note
  → append_to_note(section: "Rollback", text: "...")

Search says which section of a note matched, not just which note. On a long note that can mean reading a fraction of the content — cheaper for every step after the first search, and it is how the agent writes back too.

The server ships with instructions that teach the agent to search before writing and to add [[wikilinks]] to related notes, so the graph grows as the agent works instead of filling up with orphans.

Settings

Everything else goes in .env, copied from .env.example, which documents each option. Only KYBASE_SECRET and POSTGRES_PASSWORD are required; KYBASE_PORT changes the host port, and KYBASE_TAG pins a version (e.g. 1.4) instead of tracking latest.

Embedding provider. Open Settings in the web UI, pick a provider (Ollama, Google or OpenAI), choose a model, add an API key if it needs one, and click Save & Apply. Switching re-embeds every note, and the database adapts to the new model's vector size on its own.

[!IMPORTANT] Ollama keeps everything on your machine. Google and OpenAI are convenience options: picking either sends your notes' full text to that provider.

Sharing notes

The Share button on a note creates a public read-only link — rendered Markdown, no login, wikilinks shown as plain text so nothing else in your vault is reachable. The link is the access: revoke links you no longer need under Settings → Active share links.

Backups

Everything lives in one Postgres volume, so a nightly pg_dump is one line. Full recipe including cron and restore: docs/backup.md.

Upgrading

# prebuilt image
docker compose pull && docker compose up -d

# or rebuild from source
git pull && docker compose up -d --build

Migrations apply automatically on startup. Details: docs/upgrading.md.

More documentation

SECURITY.md (threat model) · CONTRIBUTING.md (running it locally, opening a PR) · docs/backup.md · docs/upgrading.md · packages/kybase-mcp (the standalone stdio package)

License

AGPL-3.0 — free to use, modify, and self-host. If you run a modified version as a network service, you must make its source available to your users under the same license.

For a commercial license (e.g. embedding Kybase in a closed-source product or service), contact the author.

Copyright © Denis Kurzin (https://github.com/Kyrzin)

Installation

Source-derived launch command. Check the maintainer’s required arguments and credentials before running:

bash
npx -y kybase-mcp

Set up in your AI client

Merge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.

json
{
  "mcpServers": {
    "io-github-kyrzin-kybase": {
      "command": "npx",
      "args": [
        "-y",
        "kybase-mcp"
      ]
    }
  }
}

Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.

Claude Desktop setup reference

Package

kybase-mcpnpm

Compatible MCP Clients

Kybase works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.

  • Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.
  • Cursor~/.cursor/mcp.jsonRestart Cursor for changes to take effect.
  • VS Code.vscode/mcp.jsonReload VS Code window for changes to take effect.
  • Windsurf~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect.
  • Claude Code.mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.

Learn More