On May 2nd, I had three overlapping Claude Code sessions open and could not explain to any one of them what the other two were doing. One was manually relabeling orphaned notes. One was trying to link a daily capture to a JIRA ticket. One was drafting something about the calendar index. No single surface knew about all three. No path connected a daily note at L4 up to a north-star concept at L0 without me doing the stitching by hand.
That was the moment I stopped thinking of the notes app as a future codebase.
treating the notes app like another repo
For months I had been treating the notes app as a peer of vault, the ops repo, and dxdev-content-engine. A new repo that would eventually exist and eventually matter. Which meant every design conversation looped on the same question: where does the data live? Postgres for graph traversal? Markdown, because vault already works in markdown? Both, with a sync layer I hadn’t built yet?
Nobody could answer because the question was wrong.
I had confused “I need to decide the backing store” with “I don’t know what this system is for.” Those are different problems, and I was solving the second one as if it were the first. Every design session ended with a list of tradeoffs and no commit. Each new conversation started from scratch.
the notes app is the layer above, not the layer alongside
The reframe is simple. Vault stores human-readable documents. JIRA tracks work states. Claude Code sessions hold working memory. The auto-memory store under the home directory’s .claude/projects/ accumulates learned facts across every session. None of these are going anywhere. None of them need to migrate.
What they lack is edges.
A vault concept doc doesn’t know which JIRA tickets reference it. A Claude session can’t query what altitude a goal lives at without me telling it. The auto-memory store has no awareness of the vault hierarchy it’s supposed to support. the notes app’s job is the edges. It indexes the existing systems. It doesn’t replace them.
Once that landed, the storage argument dissolved. Each layer already owns its storage. the notes app just needs to read it and write edges back.
what that did to jira
Before this, JIRA was an awkward external appendage I periodically synced into vault markdown. The sync pipeline existed so I could read work state without leaving the vault context. That framing made JIRA feel secondary, something I tolerated rather than relied on.
After the reframe, JIRA is a first-class data source the graph indexes natively. Same for Claude transcripts. Same for the auto-memory store. I don’t have to decide whether a JIRA ticket should also live in vault. JIRA keeps its state. the notes app gets an edge to it. The sync pipeline is still useful, but its role shifts from “canonical record” to “convenient cache.”
That is a meaningful change in how I build toward it. I’m not migrating data. I’m drawing edges over what’s already there.
the gateway that already worked
The same day, I tested a small ingestion gateway. It could already read the vault, write back to it, commit, and push against the live repo. Not theoretical. Running.
That matters because the notes app doesn’t need a data migration to start being useful. The vault is already the document store. The gateway traverses it and records what it finds. The first version of the notes app that earns its name is a read pass plus a set of edges written somewhere queryable.
Earlier in that same session, I had asked Claude to sketch the architecture and it gave me two options: a Postgres node-store with a markdown sync bridge, or a flat-file edge store alongside the vault. Both answers assumed storage was the question. It took pushing on “what problem does this actually solve for an active session” before the frame shifted. The tool reinforced the wrong model before helping me find the right one. That’s worth noting because it’s the pattern. The wrong frame is coherent enough that Claude will defend it until you push directly on the job description.
the tunnels problem
Public exposure for the gateway got stuck on infrastructure. Cloudflare Access blocked the tunnel because of a named tunnel collision I hadn’t cleaned up. Tailscale Funnel required sudo in a context where I didn’t have it configured. Neither of those is an architectural problem. Both are DNS-and-tunnels problems, the kind that feel like they should take twenty minutes and take a week.
The design is solid. The thing keeping the gateway local right now is a Cloudflare Access rule and a Tailscale config, not a conceptual gap. I’m naming them because they’re what’s actually blocking, and vague blockers stay blocked longer than named ones.
what the storage argument was actually standing in for
I spent months treating the notes app as a storage decision because storage felt concrete and decidable. It was a proxy for a harder question: what is the job. Once I answered the job, the storage answer was obvious. Each existing system keeps what it already owns. The graph layer writes edges and reads across all of them.
The vault, JIRA, session transcripts I’ve been generating for over a year, the auto-memory store: that is already the data. What was missing was a layer that could traverse it without demanding it migrate to a new format.
Three sessions on May 2nd could not see each other, and the reason was never the backing store: it was that nothing drew an edge from a daily note at L4 to a north-star concept at L0. The vault, the JIRA tickets, the transcripts, and the auto-memory store already held every fact those sessions needed, and the ingestion gateway that read, wrote, committed, and pushed against the live repo proved the documents were reachable without moving a single one. So the first version worth calling the notes app is a read pass plus a table of edges, and it is finished when one of those three sessions can ask which ticket touches a given concept doc and get an answer without me stitching it by hand.