Repository avatar
AI Tools
v0.1.0
active

ken

io.github.kenning-labs/ken

The current state of your life, for every AI you use. A judge checks every write.

Documentation

ken. The current state of your life, for every AI you use. Not what was said. What is true now. On your machine. A judge keeps it true.

Ken is a self-hosted MCP server that keeps the current state of your life: one linked record of your tasks, people, projects and preferences, shared by every AI app you use. Not what was said, but what is true now. We call that record "your world". One SQLite file, Python, alpha. It uses a model for its checks: OpenAI, any OpenAI-compatible API, a local model, or your Claude Code login.

CI License: AGPL-3.0 Python 3.11+

Get started  ·  Ken Cloud  ·  Benchmark  ·  FAQ  ·  How it works  ·  Discussions


Diagram: AI apps connect to Ken over MCP. A judge saves certain writes and sends uncertain ones to you as yes/no cards. Records are linked around a project.

What your agent receives

Over a few chats you told Claude about the kitchen renovation; on Monday, that the plumber sent a quote. On Tuesday, you ask any agent, in any app, to work on "approve the quote from Tomas for the kitchen renovation". The task names only Tomas and the renovation. Ken adds the rest through the links (trimmed):

{
  "task": "approve the quote from Tomas for the kitchen renovation",
  "related": [
    {"kind": "person",  "name": "tomas",
     "why": "named in the task",
     "note": "The plumber; sent a quote on Monday."},
    {"kind": "project", "name": "kitchen renovation",
     "why": "named in the task",
     "note": "New kitchen by December; budget 18k EUR."},
    {"kind": "person",  "name": "maya",
     "why": "linked: maya is a member of kitchen renovation",
     "note": "Your partner; owns the plumber question."},
    {"kind": "asset",   "name": "floor plan",
     "why": "linked: floor plan is part of kitchen renovation",
     "note": "The kitchen floor plan."}
  ],
  "last_report": "Maya asked Tomas to keep the old sink"
}

The agent starts with the budget, who owns the plumber question, the floor plan and the last thing that happened. You typed none of it into this chat. Each item also carries the evidence it rests on (left out above to keep it short).

What Ken stores

Built-in chat memoryKen
What it keepsnotes from past chatsthe current state: open, done, who owns what, what waits on what
Old factscan sit next to new onesreplaced; a judge catches duplicates and contradictions
Structureflat notespeople, projects, documents (asset records) and tasks, linked
Who decidesthe app saves what it wantsa judge checks every write; you decide the unsure ones
Which appsthat one appevery MCP app reads and writes the same world
Wherethe vendor's cloudone SQLite file on your machine; write text goes to the model you choose

What your own apps send (Claude Code on your machine, or any client with your own token) is saved after the judge checks it for duplicates and conflicts. Ken asks you with a card, in the chat you are already in, when a write would change an existing record, when the judge is unsure, when an app saves its own guess rather than your words, or when the write comes from an agent with its own token.

Get started

Rather not install anything? See Ken Cloud.

brew install uv     # skip if you have uv. Linux: curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install 'ken-engine[mcp] @ git+https://github.com/kenning-labs/ken#subdirectory=engine'
ken init

ken init asks three things: which model Ken uses, whether to add Ken to Claude Code, and whether to run it in the background. Then it tells you what is ready.

ken init in a terminal: the KEN wordmark, a model choice (2, your Claude Code login), then four steps marked done: Model, Your data, Claude Code (added as ken), Background (runs now and at every login). Last: Ken is ready, and: in Claude Code, say set up my world.

Let your agent install it

Paste this into Claude Code, Codex or another coding agent:

Install Ken, a local MCP server, from https://github.com/kenning-labs/ken (README, "Get started"):
1. If `uv --version` fails, install uv: `brew install uv` on macOS with Homebrew, otherwise
   `curl -LsSf https://astral.sh/uv/install.sh | sh`.
2. uv tool install 'ken-engine[mcp] @ git+https://github.com/kenning-labs/ken#subdirectory=engine'
3. Ask me which model Ken should use: my Claude Code login, or an OpenAI API key (never print a key).
   Then run `ken init --claude-code --add-to-claude --service`, or `ken init --api-key <key>
   --add-to-claude --service`.
4. Run `ken status` and `claude mcp list`. Tell me whether the engine is live and which server name
   reaches it, then what to say to start and how to undo the install.

If your agent may not change Claude Code's own settings, ken init prints the claude mcp add command for you to run.

More about the install: the model, other setups, running Ken by hand
  • uv installs Ken and fetches Python 3.11 or newer if you don't have it. After installing uv, open a new terminal. After the first PyPI release, the install becomes uv tool install 'ken-engine[mcp]'.
  • The model checks what your apps write and reads plain-text notes: an OpenAI key, your Claude Code login, another OpenAI-compatible API, or none for now. Without a terminal, pass it as a flag: ken init --claude-code, --api-key KEY (with --base-url URL), or --no-model.
  • Your data is in ~/.ken, private to you.
  • Claude Code: if it already has a server named ken (for example Ken Cloud), ken init keeps it and adds this engine as ken-local; turn the other one off in /mcp.
  • The background service starts at login (launchd on macOS, a systemd user service on Linux). Without it, run ken in a terminal and keep it open. Later: ken service status, ken service uninstall, or ken service install. ken status shows whether the engine is live; ken --version shows the version.
  • Apps talk to the engine through ken-mcp. Writes wait for the engine: with the engine stopped, a write returns outcome queued and applies when it starts, so do not send it again.

Then, in Claude (Code or Desktop), say "set up my world". Claude reads what it can reach (connected mail, calendar, files) and proposes your people, projects and documents in batches. Ken saves nothing until you say yes.

In Claude: 'set up my world'. Claude reads, lists your people, projects and preferences, and asks first. You answer 'keep everything', and Claude confirms: your world is set up.

Connecting an agent. Any MCP client works: Claude Code, Codex, a script on a schedule. Give each agent its own token under http.agent_tokens, and every write from it becomes a card for you. Only your own token can answer a card.

When Ken calls a model, and what changes without an OpenAI key

The agent that calls Ken does most of the work: it reads your mail or your code, decides what matters, and sends Ken structured updates. Ken itself calls a model for a few jobs:

JobModel (OpenAI default)
Decide whether a write is new, a duplicate or a conflict; rank your undated tasksOpenAI Decisions API (gpt-6-luna)
Judge a write when Decisions cannotgpt-5.6-luna
Turn a free-text report (tell) into the right writesgpt-5.6-terra
You haveWhat Ken does
An OpenAI keyeverything above; most calls cost a fraction of a cent, a tell report more
A Claude Code loginthe same jobs through claude -p; Decisions is off
No modelstores what agents send with no duplicate or conflict check, and cannot read tell reports; agent-token writes still become cards

Turn Decisions off with decisions: {enabled: false}; other models are under Models below.

Claude Desktop

Add Ken to claude_desktop_config.json (Settings → Developer → Edit Config) and restart the app. Use the full path that which ken-mcp prints:

{
  "mcpServers": {
    "ken": { "command": "/full/path/to/ken-mcp" }
  }
}
Apps that need a URL: claude.ai, ChatGPT, another machine, your phone

Set a token in ~/.ken/config.yaml, then serve Ken over HTTP:

http:
  host: 127.0.0.1
  port: 8765
  token: "a-long-random-secret"
ken-mcp --http

Put it behind a tunnel or reverse proxy you control (ngrok, Cloudflare Tunnel, Caddy). Then connect with https://<your-host>/mcp and the header Authorization: Bearer <token>:

claude mcp add --transport http ken https://<your-host>/mcp --header "Authorization: Bearer <token>"

An app that cannot send a header can use https://<your-host>/t/<token>/mcp. The token is the only lock, so treat the URL like a password. Ken refuses to listen beyond localhost without a token.

Models: OpenAI, any OpenAI-compatible API, a local model, or your Claude Code login

All settings sit under llm: in ~/.ken/config.yaml.

SetupUnder llm:
OpenAI (default)api_key: sk-...
Any OpenAI-compatible APIbase_url: https://.../v1, api_key: ..., tiers: {fast: <model>, reasoning: <model>}
Local model (Ollama)base_url: http://localhost:11434/v1, api_key: ollama, api_style: chat, tiers: {fast: llama3.1}
Your Claude Code loginprovider: claude-code (default tiers sonnet and opus)

api_style: chat is for a server with no /v1/responses endpoint. The Claude Code provider runs claude -p for each call, so answers take a few seconds longer. Use it on your own machine or your own household server, not for a public service. More options are in engine/config.example.yaml.

Cards in the terminal and a morning push

Your AI app shows each card in the chat. You can also answer from the terminal:

ken cards              # the open cards
ken decide <id> yes    # or: no

ken push sends your open cards to any URL that takes a text body, for example an ntfy topic. Set push.url in the config and run ken push each morning from cron or launchd. Nothing waiting means nothing sent. Try it with ken push --dry-run.

The MCP tools
ToolWhat it does
tasks, get_contextopen (or closed) tasks; everything that matters for one task, with the evidence for each item
who_is, find, world, eventsone person or project, a search, your whole world, what happened in a date range
add_task, complete_task, discard_task, reschedule_task, schedule_tasktask writes
assign_task, link_taskswho does a task; which task waits on which
log_event, remember, forgetevents, people, projects, preferences, facts
tella free-text report; Ken turns it into the right writes
hydrateday zero: build your world in batches you confirm
pending, decidethe open cards, and your answer to one

Every write returns the real outcome and the ids of any cards it raised, so an agent has the facts to tell you correctly what was saved.

Ken Cloud

Rather not run it yourself? We run Ken for you: the same engine as this repo, on a small virtual machine and disk of your own in Frankfurt (EU). Sign in with Google, paste one URL into Claude (or ChatGPT, where custom connectors are on), and see your day and your world in a web app. Model calls are included, so you need no API key. Get early access →

The Ken Cloud web app on a demo world: today's plan with a done and an upcoming work slot next to calendar events, a chat with Ken, a card from an agent waiting for yes or no, and the queue of tasks by deadline.
Self-hostedKen Cloud
Where Ken runsyour machineyour own virtual machine and disk, Frankfurt (EU)
Setupinstall, ken init, keep ken runningsign in with Google
Modelyour OpenAI key, Claude Code login or a local modelincluded
Connect claude.ai or ChatGPTa tunnel or reverse proxy you runone URL
Web app (your day, your world)not includedincluded
Updatesuv tool upgrade ken-enginewe deploy them

What changes when we host it:

  • Where your world lives: a 1 GB disk attached only to your machine. Accounts share the sign-in and the URL gateway, not the engine or the database.
  • Who can reach it: your own token, and us as the operators of the machine. We do not read it unless you ask us to debug something.
  • Model calls: the text of a write goes to OpenAI, under our account, so it can be judged.
  • Calendar: if you link Google Calendar, the gateway keeps its token encrypted and reads today's events live for the web app. It stores no events.
  • Moving to self-hosting: ask us, and we hand you your SQLite file to run with ken.

Benchmark (alpha)

ken-bench score, alpha run: False reports stay out, at half the cost. Ken 87, a to-do file 70, mem0 39. Cost per scenario: Ken $0.62, to-do file $1.23, mem0 $1.37.

Alpha run, not proof. 2 scenarios × 3 runs, written by us and used while fixing bugs. We will publish the scenarios, prompts, raw answers and grader, with a run on unseen scenarios and Graphiti added, before these numbers mean more than direction.

The job it tests is Ken's own: keeping a current world that several agents write to and apps read. Read it as a check on that job, not a neutral comparison. The same agent (gpt-5.6-luna) reads ~135k tokens of everyday chat into each system through that system's own tools; a second agent plants false reports; answers are graded against fixed keys. mem0 is the open-source mem0ai 2.2.1 on the same model and text-embedding-3-small.

MeasureKento-do filemem0
False-report safety: answers stay right after planted reports943939
App readability: a plain program reads the tasks, no model89890
Current-state answers778377
ken-bench score (equal-weight mean)877039
Cost per scenario, all model calls included$0.62$1.23$1.37
  • mem0 scores 0 on app readability by design: it stores free text, not records. Without that row the score is Ken 86, to-do file 61, mem0 58.
  • Ken costs less because the agent sends it short typed writes and reads small typed answers. mem0 runs its own extraction model on every add; the to-do file is read and rewritten whole on every update.
  • A well-kept to-do file still answers current-state questions better on these short histories.
  • This is not mem0's main job: mem0 is built for recall, and on recall questions over raw chat it beat Ken in our earlier runs (95 vs 73).

Privacy

This is self-hosted Ken. For Ken Cloud, see what changes when we host it.

  • Ken stores everything in ~/.ken/: one config file and one SQLite database, both private to you.
  • The text of a write goes to the model you configure so it can be judged: OpenAI by default, your Claude Code login, or a local model that keeps it all on your machine.
  • Ken sends no telemetry. Apart from those model calls, only ken push sends anything, and only if you turn it on.
  • Ken never reads your mail, chats or calendar itself. Your agents read those with their own tools and send Ken the result: who is who, what was decided, what is due.
  • Agents you connect run with your permissions. Connect only agents you trust; give each one its own token so its writes come to you as cards.

To remove Ken and everything it stored: uv tool uninstall ken-engine && rm -rf ~/.ken.

FAQ

How is this different from Claude's or ChatGPT's own memory?

Their memory lives inside one app and one vendor. Ken is one world that every MCP app shares, it is stored on your machine, and you approve what agents write. You can see and change everything it holds.

How is this different from mem0, Zep or other memory libraries?

mem0 (OpenMemory) and Zep (Graphiti) also serve memory over MCP. mem0 updates and deletes facts as they change; Graphiti keeps typed, time-aware facts in a graph. Ken differs in three ways: it tracks task state (owner, status, deadline, what a task waits on), it holds uncertain and agent-token writes for your approval, and it is one SQLite file with no vector store.

Why no embeddings or vector database?

Ken looks things up by the names and links you confirmed: the task names Tomas, Tomas works on the kitchen renovation, the floor plan belongs to it. That is exact and explainable, and it fits in one SQLite file. The trade-off: a lookup by name misses a synonym ("the plumber" does not find Tomas unless a note says so). The agent that calls Ken usually knows the name.

Is it ready?

Alpha. We use it every day. Before 1.0, expect breaking changes to config keys and MCP tool arguments; the database migrates forward on upgrade. How it works inside is in ARCHITECTURE.md.


Questions and ideas: Discussions  ·  Bugs: Issues  ·  Security: SECURITY.md

Contributions are welcome: read CONTRIBUTING.md and the Code of Conduct. Your first pull request asks you to accept the CLA with one click. Changes are in CHANGELOG.md.

Ken is licensed under the AGPL-3.0. Made by Kenning Labs.

No installation packages available.