A personal operating system running on Claude Code. Storage is plain markdown under git — no database, no service, no account. A link, a slide deck, or a stray to-do dropped into a Discord channel from a phone gets extracted, classified, templated, and filed, arriving in the repository as a pull request waiting for review.
| Pain point | What this does about it |
|---|---|
| Tasks scattered across chat apps, email, and memory | Every action item converges on one ledger, tasks/TASKS.md, whose format a script validates and whose IDs must be unique |
| Incoming material arrives in every format — web pages, Word, slides, PDFs, recordings | scripts/intake/extract.py reduces them all to plain text, which wb-intake then digests |
| Saving something is not finding it — three months later it is gone | Mandatory templates and YAML frontmatter, machine-validated, filed under PARA, with a generated index |
| You see something useful on your phone and have forgotten it by the time you're at a desk | Drop it in the Discord #inbox channel; the bridge polls it back, and Claude digests it and opens a PR |
Three intake channels converge on one pipeline. There is a single step in the middle — the wb-intake
skill extracts, classifies, and applies a template — and the output fans out to four destinations. Every digest
ends in a pull request rather than a write straight to the trunk: the human gate is the one part
of this system that cannot be skipped.
The daily writer in this system is Claude, not me. A rule written into CONTRIBUTING.md as a paragraph
of natural-language advice will certainly be diluted after a few dozen sessions. So there is a meta-rule:
every rule must carry a check that runs automatically (Rule 2), and one check verifies that property
itself — all_rules_have_checks.py scans the rule list, and any rule without a matching check turns CI red.
One command, python3 scripts/run_checks.py, runs all of them. Green means the skeleton is intact.
A decision earns a place in design/ on one test only: will a future me ask "why was it settled
this way?", and is the answer absent from the code?
One user, no ops budget, and when it breaks I am the one fixing it. Discord over Telegram or iMessage because
the design needs several channels to sort into (#inbox / #tasks / #daily /
#refs) and room to add more bots later, each with its own job. Domestic Chinese platforms would
genuinely suit the network conditions and Office previews better, but they would mean maintaining a bridge from
day one — against the principle of getting it working before adding complexity.
The real constraint is not features, it is that the writer is an agent. Markdown + git makes every write a diff
— the precondition for the human merge gate, and the reason full-text search is just grep. No
dependencies, no service, no account; cat will still read it in ten years. The cost is that complex
queries need a script, and that a few thousand files will eventually call for an index.
With the official plugin fully configured, the bot still never answered. The cause was that it receives over the
Discord gateway — a WebSocket — and WebSocket does not get through on this machine: DNS resolved to an address in
a Facebook range, and once DNS was fixed the IP and SNI layers were blocked too. After testing seven variations one
by one, the conclusion was clean: only WebSocket was stuck; REST was entirely fine. So the bridge
became a zero-dependency Python job polling the Discord REST API, with urllib reading
https_proxy natively.
The criterion in that investigation was not "it connected" but the HELLO (op:10) frame the Discord
gateway must send after a handshake. Watching only for "it connected" yields false positives — three processes sat
in SYN_SENT while looking like they were running. Picking a criterion that cannot lie to you is the only
thing that saves time on this class of network problem.
ProgramArguments must name the interpreter's real path, not the /usr/bin/python3 shim, or the permission check attaches to the wrong binary.
The governance mechanisms — every rule carries a check, the agent-loop / agent-verify contracts, keeping
CLAUDE.md short — are distilled from an earlier project and from a toolkit built alongside it; the
"inbox → PR" pipeline shape is borrowed from that project's reference scout. In other words this is not a workflow
designed from nothing, but two sets of practices already proven in real work, converged into the smallest skeleton
one person can maintain.