Sitemap
DevOps<>AI

Musings Around DevOps<>AI

What I Found When I Turned Four Years of ChatGPT Into a Knowledge Base

11 min readOct 14, 2026

--

Press enter or click to view image in full size

The export came in at 1,791 conversations. That number stopped me for a second, because it didn’t feel like 1,791 of anything. It felt like one long conversation I’d been having since December 2022, about whatever I was working on or worried about that week. Blog drafts, spec designs, arguments about agent architecture, meetup planning, homework help, a cod recipe. If you’d asked me what I’d been thinking about for four years, the honest answer was somewhere in that file.

The problem was that I couldn’t ask it anything. ChatGPT’s sidebar is fine when you remember a word from a title. It’s useless when the question is “where did this idea start?” or “which of these twenty chats were actually the same thought?” I had four years of thinking and no way to read it back.

So I decided to turn it into a knowledge base. I already keep my research in the Open Knowledge Format, which is a pleasantly boring idea: a directory of Markdown files, one per concept, each with a bit of YAML at the top saying what it is, who wrote it, and where it came from. No server, no SDK. cat works, git works, and any agent that can read Markdown can read the whole thing. I assumed the hard part would be the summaries, and that the export itself would be the easy bit.

The conversation I remembered wasn’t the one in the file

The first surprise was the shape of the data. I’d assumed a conversation was a list of messages. It isn’t. It’s a tree. Every time I edited a prompt or hit regenerate, ChatGPT kept the old branch and started a new one, and the export saves all of them. The conversation I actually remember is just one path through that tree, from a field called current_node back to the root.

That sounds like a parsing detail, but it changes what a summary means. If you read the whole tree, you end up summarizing answers I looked at and threw away, and prompts I rewrote because they were wrong. Of the roughly 23,500 messages in the export, about 19,100 survive once you keep only the branch I chose and drop the hidden messages and reasoning traces. The rest is real data about what ChatGPT said. It just isn’t what I decided.

The export records what happened. What I wanted was what I kept.

The second surprise was smaller but told me something similar. I had 48 ChatGPT Projects and custom GPTs, and the export names none of them. They’re IDs like g-p-6884c76e…. The names only ever lived in the app. So I had an agent read each project's conversation titles and propose a name, and I went through the list and approved or fixed them. A lot of the structure I thought was in my data was actually in the interface around it.

Splitting the work between code and an agent

Once I understood the data, the design mostly fell out of one question: which parts of this can be wrong in an interesting way?

Parsing the tree, building file names, linking conversations to projects, writing indexes: none of that should ever be a judgment call. So that’s plain Python, about 900 lines, with no network and no model calls. I run it with make import-chatgpt. It writes a clean, readable transcript for every conversation into a git-ignored cache, along with a queue of conversations that don't have a summary yet. Each transcript ends with a pre-filled template for the summary, so whoever writes it doesn't have to remember the format.

Deciding what a conversation was about is the part that can’t be deterministic. That’s where Claude Code comes in. It reads a transcript and writes one concept file: a title, a one-sentence description, tags, and a summary where every sentence is footnoted back to the original chat. Then I run the importer again, and it fills in the IDs and dates, links the new concepts into their project pages and indexes, adds a line to the log, and checks the whole bundle against OKF’s rules.

The rule that made this work is that neither side is allowed to touch the other’s fields. The importer owns the type, the link back to ChatGPT, the source entry, and a block of metadata like the model, message count and attachments. Everything else belongs to whoever wrote the summary, and the importer will never overwrite it or delete a file. That’s what lets me drop in a newer export next month without losing a single summary.

Here’s what one of those concepts looks like, trimmed a little:

---
type: Conversation
title: 'Code is clay, specs are the mold: stackable specs and LLM simulation'
description: The owner explained stackable specs (ADRs, BLTs and BDRs) as a mold
for AI-generated code, and ChatGPT produced a blog outline, a sample BDR and BLT
for password reset, a simulation and a verification.
tags: [spec-driven-development, writing-and-communication]
status: draft
generated:
by: claude-code/claude-opus-5-5
at: '2026-09-27T15:12:46Z'
chatgpt:
model: gpt-5-5-thinking
messages: 20
content_sha256: 5a0e2c4a…
summarized_sha256: 5a0e2c4a…
---

Those two hashes at the bottom are my favorite part. I go back to old chats all the time, and that has a consequence. The importer hashes the messages I kept. The summary records the hash it was written from. If I reopen a conversation from last spring and add three more messages, the next export produces a different hash, and the importer tells me that summary is stale.

A summary isn’t a description of a conversation. It’s a description of a specific version of one. I hadn’t thought of it that way until the data forced me to.

Deciding the words before the summaries

Before any summaries got written, I did something that felt like a detour: a tag vocabulary. Forty-eight tags in eight groups, each with a definition, what it includes and what it doesn’t. context-engineering, for example, covers what goes into a model's context, but explicitly not the wording of individual prompts, which is prompt-engineering.

It turned out to matter more than anything else I did. Seventeen hundred summaries written by agents, with free-form tags, would have produced something like 400 tags that mostly meant “AI.” With a fixed list, the OKF check simply fails if a tag isn’t in the vocabulary. No agent gets to invent a new category at conversation 900 because it’s been a long day.

The same instinct showed up in what I left out. Some conversations aren’t worth a page: a greeting, a bare link with no question, an image request that never got an answer. Those go in a skip list, and the importer refuses to run if a skip doesn’t have a reason written next to it. Forty-three conversations are skipped, and I can read why for every one. An exclusion with a reason is a decision. An exclusion without one is just a place where things quietly disappear.

The two days of summaries

The code was the small part. The summaries were the big part. I split the queue into batches and ran Claude Code subagents in parallel, each working through its own slice, while one lead session was the only thing allowed to run the importer. Two importers running at once would have fought over the indexes and the log.

The log tells the story better than I can. On the first day it went from 0 concepts to 20, which was a trial batch I read before trusting the process, then to 624. The next morning it was 1,149, then 1,715, then 1,744 with nothing left in the queue. The agents ran into my plan’s usage limit roughly every 550 conversations. Because the queue was just a file and the importer is safe to re-run, a limit reset was mostly an inconvenience: re-run, re-slice, keep going.

What was actually in there

Once it was done, the first thing I did was look at which tags came up most, expecting agent architecture or specs. It was writing-and-communication, with 414 conversations. The next closest, agent architecture, had 154.

I’d have told you I use ChatGPT to think about software. The data says I mostly use it to figure out how to say what I think about software. That’s a different job, and honestly a more useful thing to know about myself than any single summary in the bundle.

Get Owen Zanzal’s stories in your inbox

Join Medium for free to get updates from this writer.

The other surprise was the timeline. Of the 1,744 summaries, 1,599 come from 2025 and 2026. The first two years were a trickle. Somewhere in there it stopped being a tool I tried and became where I did the thinking.

Search became something I actually use. Instead of scrolling, I ask the bundle:

make query BUNDLE=chatgpt TAG=spec-driven-development Q="stackable"

That returns 12 conversations spread across more than a year: blog outlines, spec simulations, workflow designs. I’d never have connected them by title. One of them is called “GitHub README access issue.”

Looking at the whole thing at once

Press enter or click to view image in full size

Search answers questions you already have. I wanted to see the thing I didn’t know to ask about, so I rendered the bundle as a graph:

make graph BUNDLE=chatgpt OUT=out/chatgpt-graph.html

It’s a single HTML file with the data baked in. No server, nothing loaded from the network, so it opens straight from disk. Each of the 48 tags is a large dot, colored by its group in the taxonomy. Each conversation is a small dot, pulled toward the tags it carries and colored by the group most of its tags belong to. Click any dot and a side panel shows its summary, its tags, who wrote it, and a small badge that says draft and unverified, because nobody has checked it yet.

The first thing you see is the shape. The middle is a dense blue and orange knot of AI-assisted development and building with AI: coding agents, specs, agent architecture, all tangled together because those conversations tend to carry two or three of those tags at once. Around the right edge, family, food, health, home and money sit apart from it, each surrounded by a tight little fan of dots. Those fans are conversations with exactly one tag. There are 516 of them, and most of them are the parts of my life that don’t overlap with anything else.

writing-and-communication is the biggest dot on the screen, and it doesn't sit in either half. It hangs right between the professional knot and the personal edge, which is the tag count from earlier made visible. Its most common partner is the AI software lifecycle, with 61 conversations carrying both. That's the whole pattern in one pair of tags: building something, then working out how to say it.

Down at the bottom, all alone, floats agentic-commerce. It came along when I copied the professional tags from my research bundle, where I've saved several sources on it. In four years of conversations I never talked about it once. My research bundle knows what I read. This one knows what I actually thought about, and they're not the same list.

Then I looked at the numbers in the header: 1,796 concepts and 366 links. Every one of those links goes from a project page to a conversation. Not one goes from a conversation to another conversation.

That makes sense once you think about how ChatGPT works. A chat can’t cite another chat. Every conversation starts from nothing, so the summaries, which describe what was in each one, have nothing to link to. Whatever held those conversations together was never in the conversations. It was in my head, and in the tags and projects I added afterwards.

The graph didn’t show me how my ideas were connected. It showed me that until this week, nothing recorded those connections except me.

That’s also what made the next step feel necessary rather than tidy.

The moment it really clicked was later, in a different project. I was writing up a set of positions on software factories, my own ideas next to talks and articles by other people. For the first time, my ideas had sources too. The page on one idea, which I’d been calling change grammar, cites the two ChatGPT conversations where it took shape, and you can follow the footnote straight to them. As far as I know, it’s the first page anywhere that connects those two conversations to each other.

Before, my own thinking was the one thing in my research with no provenance. It came from “somewhere in ChatGPT.” Now it has footnotes like everything else.

The part that isn’t technical

A ChatGPT export is probably the most personal dataset I own. Mine mixes work with health, family and relationships, sometimes in the same week. I had to decide how to treat that before the first summary was written, not after.

The raw export and the transcripts never go near git. They live in an ignored cache folder, and the account files with my email and phone number are never read. Photos and binary attachments stay out of the bundle entirely; the concepts just list them by name and size. And I made a choice that surprised me a little: I told the agents to summarize personal conversations as specifically as the technical ones, names and actual issues included. A vague summary of something that mattered to me is worse than no summary. That choice also settles something else. This bundle is for me and my agents, and it doesn’t get published.

Every summary also says plainly who wrote it. Each one carries generated.by: claude-code/… and starts life as a draft, and the agents aren't allowed to mark anything as verified by a human. Only I can do that. Seventeen hundred pages were written about my life, and every one of them tells you that I haven't checked it yet.

“The AI summarized my chats” is a claim. “This summary was written by this model, from this version of the conversation, and no human has reviewed it” is something you can actually build on.

There’s another part of this that bothers me. OpenAI lets me export my conversations, but only as the whole history at once. There’s no incremental export, no practical way to keep a local copy in sync without downloading and processing everything again. I built around that limitation, but it still seems like an odd way to give someone access to their own data.

And the more I looked at that data, the less comfortable I became with what it represents. One conversation about a recipe or a work problem doesn’t say much about me. Seventeen hundred conversations, across four years, say an enormous amount. What I care about, what worries me, how I make decisions, what I’ve changed my mind about. It’s a remarkably detailed picture of a person, sitting with one provider.

I’ve been uneasy for a while about the combination of model lab, inference provider and user interface in a single company. Add the prospect of public-market pressures, and I’m even less convinced that the incentives of that company will always line up with mine, or with the public’s. That isn’t an accusation about what OpenAI is doing with my data today. It’s a question about who should control something this personal, and what happens when the incentives change.

As AI companies grow from startups into the next generation of public corporations, I think it’s a good time to separate the value of these tools from the ownership of what we put into them. I still use ChatGPT. I just don’t want ChatGPT to be the only place my thinking exists.

Back to the sidebar

I started with a feeling that four years of ChatGPT was one long conversation I couldn’t read back. That was only half right. It wasn’t one conversation. It was a record of what got said, including a lot of things I rejected, rewrote or abandoned, with the structure I’d put around it stripped away.

What I have now is different. It isn’t what ChatGPT said. It’s what those conversations were about, what I kept from them, and who says so. It’s still thousands of drafts, and most of them I’ll never read. But the next time I wonder where an idea came from, I won’t be scrolling a sidebar. I’ll be following a footnote.

--

--