A knowledgebase called kn
Plain text files, SQLite search, 118 lines of Ruby
Stating the Problem to be solved
I needed a place to dump operational knowledge. Config snippets, debugging notes, things I figured out once and will need again at some point. Every existing tool failed the same test: my notes were not plain text files I controlled, and I could not understand the entire system in a reasonable amount of time.
The "Architecture"
Notes are plain text files with a metadata header:
title: pf NAT on OpenBSD
tags: openbsd, networking, pf
date: 2026-04-24
---
To configure NAT with pf on OpenBSD, edit /etc/pf.conf:
match out on egress from (self) to any nat-to (egress)
pass out all
Apply the rules:
# pfctl -f /etc/pf.conf
# pfctl -e
Key-value header, three-dash separator, content. Parseable by awk. Readable by humans. Editable in any editor. If kn disappeared tomorrow, you still have a directory of text files that work with cat and grep.
The indexer is a shell script. It walks the notes directory, extracts metadata with awk, and inserts everything into SQLite with FTS5 for full-text search. The database is generated and disposable. Delete it, rerun the script, it comes back. The text files are the source of truth. The database is a convenience.
The web server is 118 lines of Ruby using WEBrick and ERB from the standard library. No gems. No framework. No JavaScript. It reads SQLite for search, reads the text files for rendering, and serves plain HTML. It works in lynx.
- 118 lines of Ruby
- ~40 lines of shell
- 21 notes and growing
- 0 gems, 0 JavaScript, 0 external dependencies
- Full-text search via SQLite FTS5
Without the web interface
cat notes/openbsd-pf-nat.md
grep -rl "pf" notes/
git log --oneline
awk -F': ' '/^tags:/{print $2}' notes/* | tr ',' '\n' | sort | uniq -c | sort -rn
The web interface makes search faster and reading prettier. It is not required.
The point
Your notes are text. The correct storage format for text is a text file. In a directory. On a filesystem that has been doing this job correctly since the 1970s. You search it with grep. You version it with git. You back it up with rsync. When grep gets slow at a few thousand files, you add a SQLite index. When you want to read in a browser, you add 118 lines of Ruby.
That is the entire system. It works. It will work in twenty years. It does not need a subscription, an account, an internet connection, a plugin ecosystem, or an Electron wrapper that uses more RAM than the Apollo guidance computer to display your grocery list.
What bothers me
The fact that an entire industry exists to sell you applications for storing text files is one of the most embarrassing failures of modern software engineering. We solved this problem fifty years ago. The solution is called a directory.