Skip to main content
Glama

AI Daybook

An AI memory engine inspired by Google's Open Knowledge Format.

A personal knowledge base that an AI assistant reads and writes through one MCP server. The notes are plain markdown files with YAML frontmatter, in a git repo you own. Between the assistant and those files sits the Librarian: ordinary, deterministic Python with no LLM in it. It assigns ids, files notes, validates every write against a schema, enforces each note's lifecycle, and searches.

The assistant does the judgment: what to write, what a new note makes false, how to rerank what search returns. The Librarian does the bookkeeping and refuses bad writes. Search runs on your machine: word scoring plus a small local embedding model (bge-small), so your text never leaves the box.

Built by Sumit for his own notes, and run daily against several hundred of them. This repo has the code and a fictional example corpus; no real notes are included.

The file format is inspired by Google's Open Knowledge Format, also "OKF". This project was first named after it, which is why the code still says OKF and okf_. It is a separate project, not affiliated with Google. See Credits.

Status: shared as a reference implementation, as is. I can't offer support, so issues and pull requests are off. Ideas are welcome in Discussions, though I may not reply to all of them. MIT-licensed, so fork it and make it yours.

The note design: three layers

Every note (a node) has three layers, read in this order:

  1. Metadata. Title, type, project, tags, and asks: up to eight questions a stranger would type when this note is the answer. Search indexes asks like the summary, so a note can be found by someone who has forgotten its words.

  2. Summary: the current state. Up to eight - bullets. Bullet 1 says what the note is. Each other bullet states one point the note currently makes and ends with → § <heading>, the section of the body that holds the detail. When a point changes, its bullet says so: (changed 2026-09-02: was 2pm). The summary is rewritten whenever the note changes.

  3. Body: the long form. It is never overwritten. Corrections are appended as dated blocks, and a body replacement that would drop existing text is refused unless the caller passes an explicit flag. The body is the history; the summary is the answer of record.

---
id: okf_20260902_064500_d002
type: decision
title: Wholesale orders close at noon the day before
summary: |-
  - The current wholesale cut-off: cafés order by noon for the next morning's delivery.
  - Noon gives the evening shift the full mix before it starts → § Why
  - Replaces the 2pm cut-off (changed 2026-09-02: was 2pm) → § Why
status: active
maturity: established
canonical: true
project: bakery
asks:
- what time do cafés have to order by
- can a café order after lunch
supersedes: okf_20260714_070000_d001
---
# Wholesale orders close at noon the day before
## Why
…

Replacing a note does not delete it. The new note supersedes the old one; the Librarian marks the old note superseded and links both ways. Search then leaves superseded notes out and tells you history exists.

Related MCP server: Cortex

Quickstart (5 minutes, over stdio)

You need Python 3.11 or 3.12, and git.

git clone https://github.com/sumit-anfy/ai-daybook.git
cd ai-daybook
python3.11 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python -m librarian.validate examples/corpus     # OK — 0 error(s)

The server runs against the bundled example corpus by default: 37 notes from a fictional baker, Rowan, covering every note type. To keep the repo clean while you experiment, work on a copy:

cp -r examples/corpus ~/okf-demo

Claude Code:

claude mcp add --transport stdio --env OKF_ROOT=$HOME/okf-demo okf -- "$PWD/.venv/bin/python" "$PWD/server.py"

Claude Desktop: add this to claude_desktop_config.json (Settings → Developer → Edit Config), with absolute paths, then restart Claude Desktop:

{
  "mcpServers": {
    "okf": {
      "command": "/absolute/path/to/ai-daybook/.venv/bin/python",
      "args": ["/absolute/path/to/ai-daybook/server.py"],
      "env": { "OKF_ROOT": "/Users/you/okf-demo" }
    }
  }
}

Then ask Claude things like:

  • "Brief me: what time do the cafés have to order by, and why did it change?"

  • "Who owns the bakery?"

  • "Create a note in garden: the beans failed because they went in too early."

  • "Run the corpus audit."

The first search downloads the embedding model (about 64 MB) into a local cache. Until it is ready, and wherever fastembed is not installed, search falls back to words only and says so (semantic: false). OKF_SEMANTIC=0 chooses that mode on purpose.

Your own corpus

Start from the two schema notes, in a git repo of its own:

OKF_CODE=$PWD                   # run from the ai-daybook folder
mkdir ~/my-corpus && cp -r examples/corpus/schemas ~/my-corpus/
cd ~/my-corpus
git init -b main
git config user.name "Your Name"
git config user.email "you@example.com"
echo .okf.lock > .gitignore     # the Librarian's write lock

Edit PROJECT_REGISTRY in schemas/type-registry.md to list your own homes. The two schema notes are themselves filed under global-os, so either keep that home or change the project: line in both to one of yours. Then commit, and point OKF_ROOT at the folder:

"$OKF_CODE/.venv/bin/python" "$OKF_CODE/librarian/validate.py" .    # must be green
git add .gitignore schemas && git commit -m "OKF schema"

Commit before you turn on OKF_GIT_COMMIT=1: the Librarian refuses to write while any .md file in the corpus is uncommitted or untracked, so it never commits your half-finished edits along with its own. To push every write too, add a remote and push once (git remote add origin <url> && git push -u origin main) before setting OKF_GIT_PUSH=1. All settings are in .env.example.

If your homes do not include global-os, set OKF_FINDABILITY_PROJECT to the home the weekly findability log should be filed under. That run (HTTP mode only) measures a bank of held-out questions that name note ids, and the bundled bank names the example corpus's. On your own corpus it reports that nothing was measured until you write a bank and set OKF_FINDABILITY_BANK; the format is in tests/findability_seed.yaml.

Tests

About 30 seconds. The write tests run on throwaway copies of the example corpus. Run them both ways: with the embedding model, and words only.

.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest
OKF_SEMANTIC=0 .venv/bin/python -m pytest

CI runs both on every push.

The tools

Tool

What it does

brief

Search. Returns the best-matching notes with bodies, their neighbours, and what was left out as stale

read_node / list_nodes

Read one note by id; list by type and status

create_node / update_node

The write path: validated, filed, state machine enforced

validate_corpus

Check every note against the schema

audit_corpus

Weekly triage: orphans, stale links, near-duplicates, suggested links

resolve_suggestion

Accept or dismiss a suggested link

propose_deletion / delete_node

Delete only retired, unlinked notes; hand anything else to a human

A session note must end with a close-out (Keep / Conflicts / Your call / Tasks), and every ruling it lists must cite the note it is filed in. The server refuses a session note that skips either.

Architecture

Claude (Desktop, Code, claude.ai)
   │  MCP: stdio, or HTTP behind TLS with a bearer token or GitHub OAuth
server.py           thin FastMCP wrapper: ten tools, auth, no logic
   │
librarian/          the deterministic core (no LLM, no network)
   validate.py      schema + registry, read live from the corpus's own schema notes
   store.py         the write path: lock, validate as a set, atomic replace,
                    state machine, supersession, body guard, git commit/push
   context.py       brief(): hybrid ranking, intent-aware type priors, aliases
   embed.py         local bge-small embeddings (fastembed, ONNX), cached in ~/.okf
   sections.py      long notes searched section by section
   summary.py       the bullet-summary format and its checks
   cluster.py       after a write: "which neighbours does this make false?"
   redundancy.py    after a rule is written: "does a canonical note already say this?"
   completeness.py  session rulings must cite the note they are filed in
   audit.py         weekly triage, link suggestions, purge candidates
   findability.py   weekly run of held-out stranger questions, logged as a note
   │
your corpus         markdown + YAML frontmatter, its own git repo
   schemas/         node.schema.md and type-registry.md are themselves notes
okf_web/            Starlette graph explorer and markdown editor, password login
deploy/             systemd units, Caddy, a pull-and-test auto-deploy timer

Some design choices:

  • The vocabulary lives in the corpus. Note types, folders and project homes are YAML blocks inside schemas/type-registry.md. The validator reads them live; changing your homes is an edit to a note, not to the code.

  • Fail closed. No registry means no writes. HTTP without auth refuses to start. A check that cannot run reports a failure, not a pass.

  • Search only adds. The embedding layer and the aliases can reorder results or add matches, but never remove a word match. Every score is broken down in the output (score_lexical, score_semantic, prior), so you can see why a note ranked where it did.

  • Live data stays in its own app. Tasks, spreadsheets and calendars are resource notes that point at them, never copies that go stale.

Retrieval numbers (example corpus only)

python tests/retrieval_report.py prints these. They are measured on the 37-note example corpus with the benchmark in tests/retrieval_benchmark.yaml (48 questions) and the held-out bank in tests/findability_seed.yaml (20 notes, two questions each, written without reusing the note's own words).

Words + embeddings

Words only

Benchmark top-1

46/48

43/48

Benchmark top-5

47/48

48/48

Held-out questions, top-1

15/20

5/20

Held-out questions, in the default pack of 8

20/20

14/20

Held-out short phrases, in the default pack of 8

20/20

16/20

Read these as a smoke test, not a quality claim: the same person wrote the corpus and the questions, and 37 notes is an easy haystack. The useful signal is the gap between the two columns on held-out wording. That gap is what the embedding layer is for.

What is not built

  • No LLM inside. The server never calls a model. Summaries, asks, and the "what does this make false?" review are written by the assistant that calls the tools.

  • No importers. Nothing reads Notion, Obsidian or Apple Notes.

  • Single owner. One corpus, one owner. Auth decides who gets in, with no per-note permissions, no sharing, and no multi-user editing.

  • No packaging. Run from a checkout; there is no pip install okf and no Docker image.

  • No encryption at rest. Notes are plain files. Protect the disk and the repo.

  • Edges are only links. relates_to links are plain lists. The typed-edge vocabulary in the schema (supports, contradicts, …) is not used yet.

  • Tested on macOS and Linux only. It has not been run on Windows.

  • Scheduled work is external. The weekly audit is meant to be run by a scheduled assistant task calling audit_corpus; this repo ships no scheduler beyond the findability run inside the HTTP service.

Credits

  • Google's Open Knowledge Format, this project's inspiration, and where the code's OKF name comes from. Knowledge as cross-linked markdown files with YAML frontmatter, versioned in git, comes from there. Google's OKF is a format, and it deliberately leaves storage, serving and search open; this project is one answer to those for a single owner. It has also drifted from the spec: notes use their own status values and link by id rather than by markdown link, and they have not been tested against an OKF v0.2 consumer.

  • Andrej Karpathy's LLM Wiki: an LLM maintaining a persistent wiki under a schema, rather than retrieving and forgetting. This design was reached separately and later found to match it closely. The difference is that here the schema is enforced by code that refuses bad writes.

  • Tiago Forte's Building a Second Brain, where the idea of a second brain started, and the capture-everything inbox this project chose not to build.

  • Built on FastMCP and fastembed, with BAAI's bge-small-en-v1.5 embedding model.

Licence

MIT.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A dynamic, governed memory layer for Markdown notes that serves knowledge to AI clients and humans through a secure MCP server, with scoped access, git-audited changes, and optional LLM-powered semantic search.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables interaction with a local knowledge repository via MCP, providing tools for capturing, indexing, and searching Markdown notes with Git version control and optional semantic search.
    4 npm
    MIT