<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sohardh Chobera</title>
    <description>The latest articles on DEV Community by Sohardh Chobera (@sohardh).</description>
    <link>https://dev.to/sohardh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3863586%2Ff92c804a-1f4a-44b7-b9d0-b5ea48debb25.jpeg</url>
      <title>DEV Community: Sohardh Chobera</title>
      <link>https://dev.to/sohardh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sohardh"/>
    <language>en</language>
    <item>
      <title>Ustaad: Building a Wiki That Thinks</title>
      <dc:creator>Sohardh Chobera</dc:creator>
      <pubDate>Mon, 06 Apr 2026 09:42:34 +0000</pubDate>
      <link>https://dev.to/sohardh/ustaad-building-a-wiki-that-thinks-5h9k</link>
      <guid>https://dev.to/sohardh/ustaad-building-a-wiki-that-thinks-5h9k</guid>
      <description>&lt;p&gt;I have a problem. I hoard information. Browser tabs, Notion pages, PDFs, chat transcripts with AI assistants. They pile up and slowly rot. Two months later I go looking for that one brilliant insight from a conversation with Grok about distributed systems, and I can’t find it. The knowledge existed. I just couldn’t access it.&lt;/p&gt;

&lt;p&gt;Traditional note-taking apps solve the &lt;strong&gt;storage&lt;/strong&gt; problem. They don’t solve the &lt;strong&gt;synthesis&lt;/strong&gt; problem.&lt;/p&gt;

&lt;p&gt;Then I came across &lt;a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f" rel="noopener noreferrer"&gt;Andrej Karpathy’s gist&lt;/a&gt; about using an LLM to maintain a living wiki. The idea stopped me mid-scroll. Instead of using an LLM to &lt;strong&gt;answer&lt;/strong&gt; questions from a pile of documents, you use it to &lt;strong&gt;build and maintain&lt;/strong&gt; a structured, interlinked knowledge base. The LLM handles all the tedious bookkeeping, cross-referencing, deduplication, consistency. You get a wiki that compounds over time. Every new source makes it smarter.&lt;/p&gt;

&lt;p&gt;I built that. I call it &lt;strong&gt;Ustaad (ਉਸਤਾਦ)&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not RAG?
&lt;/h2&gt;

&lt;p&gt;The default answer when people say “I want to query my documents with an LLM” is RAG(Retrieval-Augmented Generation). Chunk your documents, embed them, stuff the relevant chunks into the context window at query time.&lt;/p&gt;

&lt;p&gt;RAG works. But it’s fundamentally stateless. Every single query rediscovers the same knowledge from scratch. There’s no memory, no synthesis across sources, no understanding that “entity X from document A is the same as entity X in document B.”&lt;/p&gt;

&lt;p&gt;The wiki approach is different. You pay the synthesis cost once, at ingestion time. The LLM reads the new document, looks at the existing wiki, and decides: what pages need to be created? What existing pages need updating? What cross-references are missing? The result gets persisted. The next ingestion starts from a richer base.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.sohardh.com%2Fimages%2Fustaad-architecure.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.sohardh.com%2Fimages%2Fustaad-architecure.png" alt="ustaad-architecure.png" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The system has four core modes: &lt;strong&gt;Ingest&lt;/strong&gt;, &lt;strong&gt;Query&lt;/strong&gt;, &lt;strong&gt;Lint&lt;/strong&gt;, and &lt;strong&gt;Watch&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ingest
&lt;/h3&gt;

&lt;p&gt;You drop in a source like a Markdown, PDF, a raw dump of a Google Chat thread, anything. The backend (Spring Boot + Spring AI) reads the entire current wiki and passes it to the LLM along with the new source.&lt;/p&gt;

&lt;p&gt;The prompt turns the LLM into a strict wiki editor. It returns structured JSON: a list of file operations (create this page, update that page, add these backlinks). The backend safely applies the changes.&lt;/p&gt;

&lt;p&gt;The wiki follows Obsidian-flavored Markdown with mandatory YAML frontmatter. Everything lives in typed folders: &lt;code&gt;topics/&lt;/code&gt;, &lt;code&gt;entities/&lt;/code&gt;, &lt;code&gt;adrs/&lt;/code&gt;, &lt;code&gt;code-snippets/&lt;/code&gt;, etc. There’s a master &lt;code&gt;index.md&lt;/code&gt; catalog and an append-only &lt;code&gt;log.md&lt;/code&gt; that records every ingestion.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;[[backlinks]]&lt;/code&gt; are what make it feel alive. After a few ingestions, pages start referencing each other in ways I never would have manually connected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query
&lt;/h3&gt;

&lt;p&gt;Ask a question in plain English. The backend loads the full wiki as context and streams the answer back via Server-Sent Events.&lt;/p&gt;

&lt;p&gt;This is where the upfront synthesis cost pays off. The LLM isn’t hunting through raw chunks, it’s reasoning over a pre-organized knowledge graph. The answers feel coherent because the underlying structure is coherent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lint
&lt;/h3&gt;

&lt;p&gt;Wikis drift. An entity page goes stale. Two topic pages contradict each other. A code snippet is missing a language tag.&lt;/p&gt;

&lt;p&gt;Lint runs nightly (and on demand). It finds orphan pages, flags contradictions with &lt;code&gt;⚠️ [NEEDS_REVIEW]&lt;/code&gt;, and ensures every code block is properly tagged. It’s like a CI pipeline for knowledge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch
&lt;/h3&gt;

&lt;p&gt;Register any local folder and Ustaad polls it every 60 seconds. New or modified files get auto-ingested. Drop a PDF into a watched folder and it quietly becomes part of the wiki.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;Backend is Spring Boot 3 with Spring AI for clean LLM abstraction. I defaulted to Google Gemini because of its large context window (ingesting a source + the entire wiki can get heavy). Ollama works great for fully local runs. OpenAI and Claude support are planned next.&lt;/p&gt;

&lt;p&gt;Streaming responses use Server-Sent Events, the same pattern I &lt;a href="https://sohardh.com/blog-post/server-sent-events" rel="noopener noreferrer"&gt;wrote about earlier&lt;/a&gt; when building the hospital queue dashboard.&lt;/p&gt;

&lt;p&gt;The wiki itself is just plain Markdown files on disk. No database, no vector store. Just a directory that Git can version-control.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Surprised Me
&lt;/h2&gt;

&lt;p&gt;The cross-referencing quality blew me away. After ingesting a handful of architecture docs and chat logs, the LLM started creating backlinks I wouldn’t have thought to add myself. It noticed the same database entity mentioned in an ADR and a performance log and quietly linked them.&lt;/p&gt;

&lt;p&gt;The lint step catches more than just style issues. It surfaces real inconsistencies between early and later ingestions.&lt;/p&gt;

&lt;p&gt;What I underestimated: context length. As the wiki grows, passing the entire thing to the LLM on every ingestion becomes expensive and slow. I’m now thinking about smarter relevance-based chunking. The hard part is deciding what’s “related” without first reading everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;The repo is live at &lt;a href="https://github.com/Sohardh/ustaad" rel="noopener noreferrer"&gt;github.com/Sohardh/ustaad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Point it at a Gemini API key or a local Ollama instance.&lt;/p&gt;

&lt;p&gt;Drop in a few documents you’ve been meaning to organize and watch the wiki build itself.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you’ve found a smarter solution to the context-length problem, or you’ve built something similar, I’d genuinely love to hear about it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>wiki</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
