Skip to main content

ohkb

A simple, local knowledge base for agents.

ohkb gives an agent a stable set of tools for storing, finding, updating, and retiring knowledge across sessions. Entries are ordinary Markdown files. Search is provided by a local SQLite FTS5 index that can be rebuilt at any time.

ohkb does not call language models, create embeddings, or require a vector database. The agent decides what is worth keeping; ohkb keeps it organized and searchable.

한국어 · Architecture · MCP reference · Roadmap

At a glance

Storage Markdown files with YAML frontmatter
Search SQLite FTS5 with BM25 ranking
Interfaces CLI and local MCP server
Model usage None
Network access None in core commands
Data location ~/.ohkb, configurable with OHKB_DIR
Python 3.10+

Why ohkb

Agents often need a small amount of durable, curated knowledge: project conventions, decisions, facts discovered during research, or details that should survive beyond one conversation.

A general note-taking application does not provide a predictable tool contract for agents. A full RAG stack may add ingestion pipelines, chunking, embeddings, and external services when all that is needed is reliable local memory. ohkb stays between those two extremes:

  • the agent chooses what to learn and how to classify it;
  • each entry remains readable and editable without ohkb;
  • tags and aliases provide explicit search signals;
  • the search database is an index, not the source of truth;
  • the same operations are available through the CLI and MCP.

The result is intentionally small: tools an agent can use to remember, rather than a system that decides or writes knowledge on the agent's behalf.

Installation

Install the CLI with uv:

uv tool install ohkb

Or with pip:

pip install ohkb

The MCP server is an optional extra:

uv tool install "ohkb[serve]"
# or
pip install "ohkb[serve]"

Check the installation:

ohkb --version

Quick start

Initialize the data directory:

ohkb init

Store an entry:

ohkb learn "Python 3.13 can be built without the GIL using --disable-gil." \
  --title "Free-threaded Python" \
  --category python \
  --tags "GIL,CPython,free-threading,PEP-703" \
  --aliases "nogil,no-GIL Python,GIL removal"

Search and read it:

ohkb search "GIL"
ohkb get "python/free-threaded-python.md"

Browse the knowledge base and check its state:

ohkb tree
ohkb status
ohkb lint

Most commands support --json, which is the recommended output format when an agent or script is calling the CLI:

ohkb search "GIL" --json
ohkb get "python/free-threaded-python.md" --json
ohkb status --json

A reliable session usually follows the same sequence:

  1. Search before answering or creating anything.
  2. Read the exact paths returned by search, in full, before relying on them.
  3. Use ohkb index (or ohkb index -c <category>) only when you need to browse the structure.
  4. Add or update one focused fact at a time.
  5. Use ohkb status or ohkb lint to detect drift.
ohkb search "deployment rollback" --json
ohkb get "operations/deployment-rollback.md" --json
ohkb learn "..." -t "..." -c operations --tags "..." --aliases "..." --json

search before learn is important. It keeps the knowledge base compact and avoids creating several entries for the same fact.

Knowledge entries

Each entry is stored under wiki/<category>/<slug>.md. A title such as Free-threaded Python in category python becomes:

wiki/python/free-threaded-python.md

The file is standard Markdown with YAML frontmatter:

---
title: Free-threaded Python
category: python
tags:
- GIL
- CPython
- free-threading
- PEP-703
aliases:
- nogil
- no-GIL Python
entity_type: concept
source: manual
created: '2026-08-13T04:00:00+00:00'
updated: '2026-08-13T04:00:00+00:00'
---

Python 3.13 can be built without the GIL using --disable-gil.

One focused fact per file works best. Entries shorter than roughly 3,000 characters are recommended; ohkb lint reports oversized entries.

Categories

Categories may be nested:

ohkb learn "..." \
  --title "CPython garbage collection" \
  --category "python/internals" \
  --tags "CPython,GC,memory"

This creates python/internals/cpython-garbage-collection.md. Filtering by a parent category includes its descendants:

ohkb search "garbage collection" --category python

Tags and aliases

Tags and aliases are part of the retrieval model, not decorative metadata.

  • Tags connect entries that share concepts and power ohkb related.
  • Aliases capture alternate names, abbreviations, and terms users are likely to search for.

Three to seven useful tags and a few genuine aliases are usually enough. Avoid adding broad terms that do not help distinguish the entry.

Search uses SQLite FTS5 and BM25. Fields are weighted in this order:

title > tags > aliases > content

ohkb indexes its own search tokens. Korean, Japanese, and Chinese text is split into overlapping two-character pieces (중소기업 → 중소 소기 기업); other words are kept whole and lowercased. Any query token can match, and entries that match more of the query rank higher, so particles and spacing (요금제를, 중소 기업) do not prevent a match. Results include a relative score from 0 to 1; the score is meaningful within that result set rather than as a global relevance value.

ohkb search "python gil"
ohkb search "gil" --category python --limit 5
ohkb search "free threading" --json

No embeddings are generated. Search quality comes from concise entries, descriptive titles, and metadata selected when the entry is written.

Reading and editing

get returns the entry with line numbers so an agent can make a precise edit:

ohkb get "python/free-threaded-python.md"

Use one edit operation at a time:

# Replace one body line
ohkb edit "python/free-threaded-python.md" --line <line-number> "New text"

# Replace a range
ohkb edit "python/free-threaded-python.md" --lines 20-22 "Replacement text"

# Insert or delete
ohkb edit "python/free-threaded-python.md" --after 20 "Additional detail"
ohkb edit "python/free-threaded-python.md" --delete 21

Frontmatter cannot be changed with edit. Use meta instead:

ohkb meta "python/free-threaded-python.md" --add-tags "verified,python-3.13"
ohkb meta "python/free-threaded-python.md" --add-aliases "free-threaded CPython"
ohkb meta "python/free-threaded-python.md" --title "Free-threaded CPython"
ohkb meta "python/free-threaded-cpython.md" --category "python/runtime"

Changing the title or category relocates the file and removes the previous path. A conflicting destination is rejected rather than overwritten.

Archiving and restoring

forget is a reversible archive operation:

ohkb forget "python/free-threaded-python.md" --reason "Superseded by a newer entry"

Restore the most recent archive for that path:

ohkb restore "python/free-threaded-python.md"

List available archives or restore a specific version:

ohkb restore --list
ohkb restore "python/free-threaded-python.md" --list
ohkb restore --archive "python/free-threaded-python__20260813T120000000000Z.md"

If the same path is archived more than once, ohkb keeps timestamped versions instead of replacing the previous archive.

Working with local source files

The optional sources/ directory keeps copies of raw local material separately from curated knowledge:

ohkb source add ./research-notes.txt
ohkb source list

extract returns text from a local text or HTML file so an agent can review, classify, and store useful facts:

ohkb extract ./research-notes.txt --json

A typical intake flow is:

source add → extract → review and classify → search for duplicates → learn

Extraction is local and deterministic. It does not summarize content, call a model, or fetch URLs. Binary formats such as PDF, DOCX, images, and ZIP files must be converted to text first. Individual extraction targets are limited to 10 MiB; copied source files are limited to 100 MiB.

Files are the source of truth

ohkb writes the Markdown file first and then updates SQLite. The database can always be reconstructed from wiki/:

ohkb reindex

This matters when entries are edited with another tool or restored from version control. status reports whether the files and index agree:

ohkb status --json

If in_sync is false, run ohkb reindex. lint provides a more detailed health check and can report:

  • files missing from the index;
  • indexed paths with no file on disk;
  • invalid frontmatter;
  • missing tags or aliases;
  • category and filename mismatches;
  • oversized entries.

MCP server

Install the serve extra, then configure an MCP client to start ohkb over stdio:

{
  "mcpServers": {
    "ohkb": {
      "command": "ohkb",
      "args": ["serve", "--mode", "managed"]
    }
  }
}

The executable must be available in the MCP client's environment. The server is local stdio only; ohkb does not expose an HTTP transport.

Access modes

Mode Behavior
readonly Read, search, inspect, extract, and rebuild the local index
managed Adds write tools and asks the client for confirmation before changes
autonomous Makes write tools available without confirmation prompts
ohkb serve --mode readonly
ohkb serve --mode managed
ohkb serve --mode autonomous

Available MCP features include:

  • resource: ohkb://index;
  • prompts: research, learn_from_text, and organize;
  • read tools: index, search, get, tree, status, lint, reindex, log, related, extract, source_list;
  • write tools: learn, edit, meta, forget, restore, source_add.

See docs/MCP_TOOLS.md for parameters and return values.

Data directory

By default, all state is stored under ~/.ohkb:

~/.ohkb/
├── _meta.db           # SQLite metadata and FTS5 index
├── wiki/
│   ├── _index.md      # entry listing, written by `ohkb index`
│   └── <category>/
│       └── <slug>.md  # knowledge entries
├── sources/           # optional raw local files
├── archive/           # versioned forgotten entries
├── log.md             # append-only activity log
└── AGENTS.ohkb.md     # generated agent workflow guide

Use OHKB_DIR to keep separate knowledge bases or place the data elsewhere:

export OHKB_DIR="$PWD/.ohkb"
ohkb init

The directory is portable. It can be backed up, searched with standard tools, or placed under version control according to your own data policy. _meta.db does not need to be preserved if the Markdown files are available.

CLI reference

Command Purpose
ohkb index List every entry by category (-c for one category); also writes wiki/_index.md
ohkb search QUERY Search with optional category and result limit
ohkb get PATH Read an entry with line numbers
ohkb tree [PATH] Browse categories to a chosen depth
ohkb status Show counts, categories, and index sync state
ohkb lint Check metadata quality and file/index integrity
ohkb related PATH Find entries that share tags
ohkb log Show recent activity
ohkb learn [CONTENT] Create an entry; content may also come from --file
ohkb edit PATH Replace, insert, or delete body lines
ohkb meta PATH Update tags, aliases, title, category, or entity type
ohkb forget PATH Move an entry to the versioned archive
ohkb restore [PATH] List or restore archived entries
ohkb reindex Rebuild SQLite from Markdown files
ohkb source add/list Manage optional raw local sources
ohkb extract TARGET Extract text from a local text or HTML file
ohkb init Create the standard data layout and agent guide
ohkb serve Start the optional local MCP server

Run ohkb COMMAND --help for complete options. Successful commands exit with status 0; errors are written to stderr. Commands that offer --json keep stdout machine-readable.

Scope

ohkb is deliberately limited. The core project does not include:

  • model invocation or autonomous knowledge generation;
  • embeddings or vector search;
  • URL crawling and document ingestion pipelines;
  • automatic merging, splitting, or staleness decisions;
  • a web or HTTP runtime.

Those boundaries keep the storage format understandable and the tool contract predictable. Planned work is tracked in the roadmap.

Development

Clone the repository and install the development environment:

git clone https://github.com/otofu-git/ohkb.git
cd ohkb
uv sync --extra dev

Run the checks:

uv run pytest
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
uv build

The test suite uses real temporary filesystems and SQLite databases rather than mocks. See AGENTS.md for the architecture, invariants, and contribution guidelines used in this repository.

Version

Current release: 0.2.1

See docs/ROADMAP.md for planned work and compatibility milestones.

License

MIT

Metadata

Release files for ohkb 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ohkb 0.2.1
File Size Uploaded Provenance Actions
ohkb-0.2.1.tar.gz 145.3 kB Without provenance Details for ohkb-0.2.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ohkb 0.2.1
File Interpreter ABI Platform Actions
ohkb-0.2.1-py3-none-any.whl Python 3 none any Details for ohkb-0.2.1-py3-none-any.whl

Total release size: 192.6 kB

Release files / ohkb-0.2.1.tar.gz

Download URL ohkb-0.2.1.tar.gz
Size 145.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c492c36f6db2a89329c3056038c07c90f48db1a9cb00bbf14e194d95bb6b264b
BLAKE2b-256 checksum
How to use checksums
05ef20c8703cd6137d05dd6027b9ba42dfba5286f93d2860727b7751da3a8795
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.12

Release files / ohkb-0.2.1-py3-none-any.whl

Download URL ohkb-0.2.1-py3-none-any.whl
Size 47.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1f1c537bfbf172554e35073a679f0a50f001664d423ccf35ae118351c4d3c007
BLAKE2b-256 checksum
How to use checksums
e7cec9fcfb889884d1c31e4c7da79f07b6b289214e0a1a93c7b2c0731a90625d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.12

Security for ohkb 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page