<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[The Builder's Journal]]></title><description><![CDATA[The Builder's Journal]]></description><link>https://rahuldk.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 10:30:45 GMT</lastBuildDate><atom:link href="https://rahuldk.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How I built a DSC PDF signer in Rust and Tauri]]></title><description><![CDATA[I'm a company director, and in India that means signing board resolutions and financial statements with a Digital Signature Certificate (DSC). The DSC is a…]]></description><link>https://rahuldk.hashnode.dev/how-i-built-a-dsc-pdf-signer-in-rust-and-tauri</link><guid isPermaLink="true">https://rahuldk.hashnode.dev/how-i-built-a-dsc-pdf-signer-in-rust-and-tauri</guid><category><![CDATA[Rust]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Security]]></category><category><![CDATA[Tauri]]></category><dc:creator><![CDATA[Rahul Dhileep Kumar]]></dc:creator><pubDate>Sat, 24 Oct 2026 16:58:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a74b4f5c807076eec3fd62b/650416bf-55b1-47d6-bc81-b901d9d053e9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I'm a company director, and in India that means signing board resolutions and financial statements with a Digital Signature Certificate (DSC). The DSC is a Class 3 certificate on a USB token, the same one used for MCA and GST filings.</p>
<p>For a while, signing a PDF with that token meant paying for and installing a large commercial PDF suite. A lot of software for one click and a PIN. I wanted something small, free and offline that would never break a signature already on the PDF.</p>
<p>So I built <a href="https://sign.rahuldk.in/?utm_source=hashnode&amp;utm_medium=social&amp;utm_campaign=launch-v0.6">TrackMy Sign</a>, a free, open-source (MIT) desktop app for Windows, macOS and Linux. This post is about how it works underneath. The code is at <a href="https://github.com/rahuldk1105/trackmysign">github.com/rahuldk1105/trackmysign</a>.</p>
<h2>The stack</h2>
<ul>
<li><strong>Rust</strong> for everything that matters: talking to the token, parsing PDFs, building signatures.</li>
<li><strong>Tauri 2</strong> for the desktop shell, so the app ships as a native binary with a webview rather than a bundled browser.</li>
<li><strong>React</strong> for the interface.</li>
</ul>
<p>The interesting parts are all on the Rust side, so that's where the rest of this goes.</p>
<h2>Part 1: talking to the token with PKCS#11</h2>
<p>An Indian DSC token is a smart card in a USB stick. The private key is generated on it and can't be exported. You never get the key; you ask the token to sign something with it.</p>
<p>The standard way to ask is PKCS#11, a C API that token vendors implement in a driver library: a <code>.dll</code> on Windows, a <code>.dylib</code> on macOS, a <code>.so</code> on Linux. Every vendor ships its own. The flow is the same for all of them:</p>
<ol>
<li>Load the vendor's library and call <code>C_Initialize</code>.</li>
<li>Find a slot with a token in it and open a session.</li>
<li><code>C_Login</code> with the user's PIN.</li>
<li>Find the certificate object and the private key that matches it.</li>
<li>Call <code>C_Sign</code> with that key over the data to be signed.</li>
</ol>
<p>Steps 3 and 5 are the ones that matter for security. The PIN goes to the token's driver, and the signing happens on the token. The private key never leaves it. TrackMy Sign doesn't store the PIN.</p>
<p>The awkward part is step 1. There's no standard place for the driver. Each vendor installs its library somewhere different, under a different name, on each platform. So the app keeps a list of known driver locations for common Indian tokens (HyperPKI, ePass2003, ProxKey, mToken, SafeNet and others), loads every one it finds, and lists the certificates from all of them together. A driver that fails to load is skipped rather than taking the app down with it. You can also point it at a driver in an odd location.</p>
<h2>Part 2: what a PDF signature actually is</h2>
<p>A PDF signature is a CMS (PKCS#7) <code>SignedData</code> structure stored inside the PDF. TrackMy Sign uses the standard <code>adbe.pkcs7.detached</code> sub-filter with SHA-256. "Detached" means the CMS blob doesn't contain the content it signs; it contains a hash of it, the signer's certificate chain, and the signature over those signed attributes.</p>
<p>The question is: which content? The answer is the ByteRange.</p>
<p>When you add a signature, you add a signature dictionary to the PDF. It has a <code>/Contents</code> entry, which is a hex string reserved for the CMS blob, and a <code>/ByteRange</code> entry, which is four numbers:</p>
<pre><code>/ByteRange [0 840 960 240]
/Contents &lt;000000...000000&gt;
</code></pre>
<p>That reads as: "this signature covers bytes 0 to 840, and bytes 960 to 1200". The gap in the middle is exactly the <code>/Contents</code> hex string. The signature covers the whole file except the hole where the signature itself goes.</p>
<p>So signing is roughly:</p>
<ol>
<li>Write the new PDF content with a <code>/Contents</code> placeholder big enough for the signature, filled with zeros.</li>
<li>Work out the byte offsets and write the real <code>/ByteRange</code> numbers.</li>
<li>Hash the bytes in the two ranges with SHA-256.</li>
<li>Build the signed attributes, and send them to the token via <code>C_Sign</code>.</li>
<li>Assemble the CMS <code>SignedData</code> with the certificate chain, hex-encode it, and write it into the placeholder.</li>
</ol>
<p>Nothing outside the placeholder changes after step 3. If it did, the hash would no longer match.</p>
<h2>Part 3: incremental updates, and why the auditor's signature survives</h2>
<p>This was the requirement I cared most about. Financial statements can arrive already signed by an auditor. If they signed before you, your signature has to go on without breaking theirs.</p>
<p>Look at what the auditor's ByteRange covers: specific bytes of the file as it was when they signed. If any of those bytes move or change, their signature is invalid. A tool that loads a PDF into an object model, adds a signature and serialises the whole thing again will shift offsets, renumber or recompress objects, and break the auditor's signature.</p>
<p>PDF has a mechanism for this, called an incremental update. You don't rewrite anything. You append to the end of the file:</p>
<ul>
<li>the new and changed objects (the signature dictionary, the signature field, its visible appearance, the updated page and form objects);</li>
<li>a new cross-reference section listing where those objects are;</li>
<li>a new trailer whose <code>/Prev</code> points back to the previous cross-reference section.</li>
</ul>
<p>A reader follows the chain from the newest trailer backwards and sees the latest version of each object. The original bytes are still there, byte for byte. The auditor's ByteRange still covers exactly what it covered before, and those bytes are untouched. Their signature stays valid. Yours covers the whole file including their signature, which is what you want.</p>
<p>TrackMy Sign has its own PDF parser and incremental writer, written in Rust. The writer only ever appends. It never rewrites the original bytes.</p>
<p>The same mechanism handles the other features that touch a signed file: signing into an existing empty signature field in a bank or government form, putting one signature's visible box on every page, and certifying (locking) a document.</p>
<h2>Part 4: testing without a physical token</h2>
<p>You can't run CI against my USB token, so the tests use SoftHSM, a software implementation of a PKCS#11 token. To the app it looks like any other token driver: load the library, log in, find the key, sign.</p>
<p>The end-to-end tests generate PDFs, sign them through SoftHSM, and then check the output with two independent validators:</p>
<ul>
<li><strong>pyHanko</strong>, a Python PDF signing library, validates the signatures.</li>
<li><strong>qpdf</strong> checks that the file structure is sound.</li>
</ul>
<p>Using validators I didn't write matters. My parser agreeing with my writer proves very little. Two unrelated tools agreeing with both proves rather more.</p>
<p>Then the real-world checks, done by hand with my own Hypersecu HyperPKI HYP2003 token: Adobe Acrobat Reader shows "Signature is VALID" on the output.</p>
<h2>Part 5: the GST portal's local signer</h2>
<p>The GST portal doesn't sign in the browser. Its JavaScript connects to a signer service running locally on your computer, over a secure WebSocket to <code>127.0.0.1</code>, and asks it to sign. Normally that service is a separate utility you install.</p>
<p>TrackMy Sign can act as that local signer. At a high level:</p>
<ul>
<li>It listens only on <code>127.0.0.1</code>, only while the app is running, and only answers requests from the GST portal's domain.</li>
<li>Because the browser needs a trusted TLS certificate even for localhost, the app sets up a certificate for <code>127.0.0.1</code> on that computer.</li>
<li>Every request is shown to you. You approve it and enter your PIN; the token signs.</li>
</ul>
<p>It's an independent implementation of the local protocol the portal's JavaScript uses. A GST portal DSC registration signed this way was accepted by the portal.</p>
<p>What it can't do: MCA21 V3 and the Income Tax portal use eMudhra's emBridge with licensed encryption, so TrackMy Sign can't sign on those. Keep using emBridge there.</p>
<h2>Part 6: releases on three platforms</h2>
<p>Every release is built by GitHub Actions from the public source, for Windows, macOS and Linux. Nobody builds a release on my laptop, and you can see what each release was built from.</p>
<p><strong>macOS.</strong> The Mac app is signed and notarised by Apple. Notarisation means Apple scans the signed app and issues a ticket, so Gatekeeper opens it without the "unidentified developer" dance.</p>
<p><strong>Windows.</strong> The installer isn't code-signed yet, so Windows SmartScreen shows a warning the first time you run it. I'd rather tell you that here than have you find out. A Microsoft Store version is in review, and a winget package is waiting for approval.</p>
<p><strong>Linux.</strong> AppImage and .deb.</p>
<h2>What's in v0.6.0</h2>
<p>Beyond signing: a signature designer (company seal or logo, "For Company — Director" lines), batch signing with one PIN, a watch folder, optional trusted timestamps and LTV, signature verification with PDF reports and whole-folder checks, password-protected PDFs, page tools (merge, rotate, reorder), signing any file as <code>.p7s</code> or <code>.p7m</code>, a private signing history, a DSC expiry reminder, in-app updates, and English, Hindi and Tamil. It works offline, with no account and no telemetry. The <a href="https://sign.rahuldk.in/features/?utm_source=hashnode&amp;utm_medium=social&amp;utm_campaign=launch-v0.6">features page</a> has the full list.</p>
<p>It isn't affiliated with Adobe, eMudhra, GSTN, MCA or the CCA.</p>
<h2>Try it, break it</h2>
<ul>
<li>Website: <a href="https://sign.rahuldk.in/?utm_source=hashnode&amp;utm_medium=social&amp;utm_campaign=launch-v0.6">https://sign.rahuldk.in/?utm_source=hashnode&amp;utm_medium=social&amp;utm_campaign=launch-v0.6</a></li>
<li>Source: <a href="https://github.com/rahuldk1105/trackmysign">https://github.com/rahuldk1105/trackmysign</a></li>
<li>Downloads: <a href="https://github.com/rahuldk1105/trackmysign/releases/latest">https://github.com/rahuldk1105/trackmysign/releases/latest</a></li>
</ul>
<p>I've only tested with my own token. If you have a different one, I'd like to hear whether it works, and especially if it doesn't. Issues and pull requests welcome.</p>
]]></content:encoded></item><item><title><![CDATA[The 3 a.m. call: why every founder needs an Arun]]></title><description><![CDATA[When I'm stuck badly enough, I call Arun. He's our CTO. He's the one person I trust to pick up at any hour. In the night I broke production, he got a short…]]></description><link>https://rahuldk.hashnode.dev/the-3-a-m-call-why-every-founder-needs-an-arun</link><guid isPermaLink="true">https://rahuldk.hashnode.dev/the-3-a-m-call-why-every-founder-needs-an-arun</guid><category><![CDATA[Founder]]></category><category><![CDATA[Startups]]></category><dc:creator><![CDATA[Rahul Dhileep Kumar]]></dc:creator><pubDate>Fri, 23 Oct 2026 04:04:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a74b4f5c807076eec3fd62b/6f4c2ce7-b452-4bbb-b6b0-5b405992dcd2.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I'm stuck badly enough, I call Arun.
He's our CTO.
He's the one person I trust to pick up at any hour.</p>
<p>In <a href="https://www.rahuldk.in/blog/the-night-i-broke-production">the night I broke production</a>, he got a short section.
Four lines and a photo.
This is the longer version, because I think the idea deserves more than four lines.</p>
<p>The idea is simple.
Every founder needs one person who picks up.
Not a mentor you email on Mondays.
Not a group chat.
One person, at any hour, who will actually answer.</p>
<h2>The one person who picks up</h2>
<p>Arun picks up at any hour.
Which, if you think about it, is frankly suspicious.
Does he sleep? Is he three people?
I've decided not to ask, in case the answer ruins it.</p>
<p>If you want to know who he is, <a href="https://www.arunvignesh.my/">his portfolio</a> does a better job than I would.</p>
<p>What I think a person like that gives a founder is a floor.
"Stuck" stops meaning "stuck forever".
The bad nights still happen.
They just have a bottom.</p>
<p>TrackMy Tech is bootstrapped.
There's no board of investors waiting by the phone.
There's Arichandran, our co-founder and director, there's Arun, and there's the rest of us.
When something breaks, the people in the room are the plan.</p>
<h2>Why going it alone is harder than it looks</h2>
<p>I'm not the first person to notice this.
Paul Graham put "single founder" near the top of his essay <a href="https://paulgraham.com/startupmistakes.html">The 18 Mistakes That Kill Startups</a>.
His reasoning is blunt.
"Starting a startup is too hard for one person."
Even if you could do all the work yourself, he says, you need colleagues "to brainstorm with, to talk you out of stupid decisions, and to cheer you up when things go wrong."</p>
<p>That last part is the 3 a.m. call in one sentence.</p>
<p>He also writes that "the low points in a startup are so low that few could bear them alone."
I've had a few low points.
I can confirm they are, in fact, low.</p>
<h2>The catch: the people can also sink you</h2>
<p>Here's the uncomfortable flip side.
The people around you aren't only your safety net.
They can also be the thing that breaks.</p>
<p>Noam Wasserman, who wrote <em>The Founder's Dilemmas</em>, has studied this for years.
<a href="https://thecrimson.com/article/2012/4/9/hbs-start-noam-founder/">The Harvard Crimson reported</a> that his research drew on data from "nearly 10,000 founders of technology and life sciences startups in the U.S."
His main finding, as the Crimson summed it up: "Startup companies are most likely to fail due to personal disagreements within their management teams."</p>
<p>Not the market. Not the tech.
The people.</p>
<p>The same article notes that 73 percent of founders in his survey decided how to split equity in the first month.
An equal split avoids tension early on, but can cause problems if a co-founder backs out later.
In other words: the hard conversations don't go away if you skip them.
They just wait for a worse moment.</p>
<p>So I don't think the lesson is "have a co-founder, done".
I think it's "have someone you trust, and do the work to keep that trust".</p>
<h2>Trust is what makes the call possible</h2>
<p>There's a reason the 3 a.m. call works with one person and not with others.
You have to be willing to say "I've messed this up and I don't know why" out loud.</p>
<p>Amy Edmondson has a name for the condition that makes that possible.
In <a href="https://www.jstor.org/stable/2666999">her 1999 paper</a> she describes team psychological safety as "a shared belief held by members of a team that the team is safe for interpersonal risk taking."
She studied 51 work teams in a manufacturing company.
Teams with more psychological safety showed more learning behaviour, and that learning behaviour was linked to better team performance.</p>
<p>Her examples of learning behaviour are worth reading slowly: seeking feedback, sharing information, asking for help, talking about errors and experimenting.</p>
<p>"Asking for help" and "talking about errors" are basically the job description of a 3 a.m. call.
If you're scared of looking stupid, you don't call.
You sit there alone for hours, checking the same code again.</p>
<p><img src="https://www.rahuldk.in/posts/every-founder-needs-an-arun/phone-screen-in-the-dark.jpg" alt="A smartphone screen glowing in a dark room, showing app icons including the phone app" /></p>
<p><em>Photo: <a href="https://unsplash.com/@pathum_danthanarayana">Pathum Danthanarayana</a> on <a href="https://unsplash.com/photos/t8TOMKe6xZU">Unsplash</a></em></p>
<h2>What I'd tell another founder</h2>
<p>None of this is a grand theory.
It's my opinion, from someone who makes that call when he's stuck badly enough.</p>
<ol>
<li><strong>Decide who you'll call before the crisis.</strong> Not during it. In the middle of an outage you won't think clearly enough to pick. Know the name now.</li>
<li><strong>Make it mutual.</strong> If you only ever call, it's not trust, it's a helpline. Pick up for them too. Be the person who answers.</li>
<li><strong>Say the embarrassing thing early.</strong> The call only helps if you're honest about how badly it's gone. Edmondson's research is basically a long argument for this.</li>
<li><strong>Have the awkward talks on a calm day.</strong> Equity, roles, who decides what. Wasserman's findings suggest the skipped conversations are the ones that come back.</li>
<li><strong>Write things down so the call is rarer.</strong> Passwords in the right place, deployment steps, when certificates expire, how to roll back. If the answer lives in one person's head, that person gets woken up a lot.</li>
</ol>
<p>That last one matters more than it sounds.
The goal isn't to call Arun more.
The goal is to call him only when it really can't wait.
He picks up at any hour. That doesn't mean he should have to.</p>
<h2>One last thing</h2>
<p>Find your Arun.
Then try very hard to need him less.</p>
<p>And if you already have one, maybe send them a thank-you message.
During the day, for once.</p>
<h2>FAQ</h2>
<h3>Do you need a co-founder to start a startup?</h3>
<p>Not strictly. But Paul Graham lists "single founder" as one of the mistakes that kill startups, mainly because the low points are hard to carry alone. At the very least, have one person you can call.</p>
<h3>What is psychological safety in a team?</h3>
<p>Amy Edmondson defines it as a shared belief that the team is safe for interpersonal risk taking. In practice: you can admit a mistake or ask for help without being punished for it.</p>
<h3>How do you make late-night emergencies rarer?</h3>
<p>Write things down. Deployment steps, credentials, renewal dates and rollback commands should live somewhere the whole team can find them, not in one person's head.</p>
<h2>Sources</h2>
<ul>
<li><a href="https://paulgraham.com/startupmistakes.html">Paul Graham: The 18 Mistakes That Kill Startups</a></li>
<li><a href="https://thecrimson.com/article/2012/4/9/hbs-start-noam-founder/">The Harvard Crimson: Noam Wasserman on founders (2012)</a></li>
<li><a href="https://www.jstor.org/stable/2666999">Amy Edmondson: Psychological Safety and Learning Behavior in Work Teams, Administrative Science Quarterly (1999)</a></li>
</ul>
<h2>What next</h2>
<p>The outage night, in full: <a href="https://www.rahuldk.in/blog/the-night-i-broke-production">we blamed our code, it was SSL</a>.
Another late-night call, from the other side: <a href="https://www.rahuldk.in/blog/i-said-i-would-help-a-friend">I said I would help a friend</a>.</p>
<p>Running an academy? <a href="https://www.trackmyacademy.com">Track My Academy</a> handles attendance, fees, player reports and parent messages.
It's built by <a href="https://www.trackmytech.in">TrackMy Tech</a>.</p>
]]></content:encoded></item><item><title><![CDATA[I tried to build my own offline Claude Code]]></title><description><![CDATA[Claude Code and Bolt made coding agents look easy. You type a sentence, and a model reads your files, edits them and runs things. So naturally I wanted my…]]></description><link>https://rahuldk.hashnode.dev/i-tried-to-build-my-own-offline-claude-code</link><guid isPermaLink="true">https://rahuldk.hashnode.dev/i-tried-to-build-my-own-offline-claude-code</guid><category><![CDATA[AI]]></category><category><![CDATA[dev tools]]></category><dc:creator><![CDATA[Rahul Dhileep Kumar]]></dc:creator><pubDate>Wed, 21 Oct 2026 03:31:35 GMT</pubDate><content:encoded><![CDATA[<p>Claude Code and Bolt made coding agents look easy.
You type a sentence, and a model reads your files, edits them and runs things.</p>
<p>So naturally I wanted my own.
Offline. On my machine. No account, no trial, no meter running.</p>
<p>I built a personal coding-agent experiment to explore one specific thing: contextual memory limits.
How much can a local model actually keep in its head while it works on your code?</p>
<p>This isn't a results post.
It's about the stack, and about the wall the experiment was built to poke at.
Because anyone who tries this will hit the same wall.</p>
<h2>The stack</h2>
<p>Four pieces, all of them free.</p>
<ul>
<li><strong><a href="https://www.electronjs.org/docs/latest/">Electron</a></strong> for the desktop app. In its own words: "By embedding Chromium and Node.js into its binary, Electron allows you to maintain one JavaScript codebase."</li>
<li><strong>React</strong> for the interface.</li>
<li><strong><a href="https://github.com/microsoft/monaco-editor">Monaco</a></strong> for the editor. Its README calls it "the fully featured code editor from VS Code". You get a real editor without building one.</li>
<li><strong><a href="https://docs.ollama.com/faq">Ollama</a></strong> to run the model locally. Its FAQ is plain about it: "Ollama runs locally. We don't see your prompts or data when you run locally."</li>
</ul>
<p>Why offline?
Partly the obvious reasons: your code stays on your machine, and it works without internet.</p>
<p>Partly me.
Early on, we chased every free AI trial going, with <a href="https://www.rahuldk.in/blog/dozens-of-email-accounts-and-zero-shame">dozens of email accounts</a>, because we didn't yet know how to use Claude or Codex.
A model that runs on your own laptop never asks for a new email address.
If you can get it for free, why spend money on it?</p>
<h2>The real constraint: the context window</h2>
<p>A model doesn't remember your project.
It only sees what's in its context window: the prompt, the files you paste in, the chat so far.
Everything outside that window doesn't exist for it.</p>
<p>A coding agent eats context fast.
File contents, tool output, error logs, its own previous answers.
It all piles up.</p>
<p>Local models start with a small window.
The <a href="https://docs.ollama.com/faq">Ollama FAQ</a> says "By default, Ollama uses a context window size of 4096 tokens."
Its <a href="https://docs.ollama.com/context-length">context length page</a> says the default now depends on your VRAM: 4k under 24 GiB, 32k between 24 and 48 GiB, and 256k at 48 GiB or more.
The <a href="https://docs.ollama.com/modelfile">Modelfile reference</a> still lists <code>num_ctx</code> with "Default: 2048".</p>
<p>So even the docs don't agree with each other.
Which is a lesson in itself: check what you're actually running.
The context length page suggests running <code>ollama ps</code> and looking at the CONTEXT column.</p>
<p>The same page recommends at least 64,000 tokens for "web search, agents, and coding tools".
You raise it with the <code>OLLAMA_CONTEXT_LENGTH</code> environment variable, or per request with <code>num_ctx</code> inside <code>options</code>, <a href="https://docs.ollama.com/faq">per the FAQ</a>.</p>
<h2>Why you can't just turn the number up</h2>
<p>Because memory isn't free.
Ollama's <a href="https://docs.ollama.com/context-length">context length page</a> says it directly: a larger context uses more memory.</p>
<p>The reason is the KV cache.
While a model generates, it stores keys and values for every token it has seen, so it doesn't recompute them.
NVIDIA's <a href="https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/">guide to LLM inference optimisation</a> gives the formula:
batch size × sequence length × 2 × layers × hidden size × bytes per value.</p>
<p>Their worked example is Llama 2 7B in 16-bit precision.
At 4,096 tokens, the KV cache alone comes to about 2 GB.
That's on top of the model weights.</p>
<p>And it grows linearly.
Double the context, roughly double the cache.
On a laptop, that's the whole game.
Every extra token of memory competes with the model itself for the same RAM.</p>
<h2>Bigger isn't the same as better</h2>
<p>Say you find the memory.
You still have a problem.</p>
<p>The 2023 paper <a href="https://arxiv.org/abs/2307.03172">Lost in the Middle</a>, by Nelson F. Liu and colleagues, tested models on finding information in long inputs.
Performance was usually best when the relevant bit was at the start or the end.
It dropped when the information sat in the middle, even for models built for long contexts.</p>
<p>Their conclusion: "current language models do not robustly make use of information in long input contexts."</p>
<p>For a coding agent, that's uncomfortable.
The file you read twenty minutes ago is now somewhere in the middle.
It's technically in context. It may as well not be.</p>
<h2>How Claude Code deals with it</h2>
<p>The tool that inspired the experiment doesn't pretend the problem away.
It manages it.</p>
<p>Anthropic's <a href="https://code.claude.com/docs/en/memory">memory docs</a> start with: "Each Claude Code session begins with a fresh context window."
Knowledge carries across sessions in two ways: CLAUDE.md files you write, and auto memory that Claude writes itself.
Both are loaded at the start of every conversation.</p>
<p>The docs also say to keep each CLAUDE.md under 200 lines.
"Longer files consume more context and reduce adherence."
Even the memory has a memory budget.</p>
<p>Then there's compaction.
The <a href="https://code.claude.com/docs/en/context-window">context window docs</a> say Claude Code "compacts automatically as you approach the limit".
Running <code>/compact</code> "replaces the conversation with a structured summary".
Afterwards it re-reads up to five of the files it read or edited most recently.
The project-root CLAUDE.md is re-read from disk and survives.</p>
<p>So the trick isn't a bigger window.
It's deciding what deserves to be in the window at all.</p>
<h2>What anyone trying this will hit</h2>
<p>My opinion, from the research above, for anyone building their own local agent:</p>
<ol>
<li><strong>The default window is smaller than you think.</strong> If the agent seems to forget your file instantly, check the context length before blaming the model.</li>
<li><strong>Memory is the budget.</strong> Context costs RAM through the KV cache. On a laptop, you're trading model size against how much it can see.</li>
<li><strong>Order matters.</strong> Put instructions and the most important code at the start or the end, not buried in the middle.</li>
<li><strong>Write memory to disk.</strong> A short notes file that loads every session beats hoping the model remembers turn three.</li>
<li><strong>Summarise on purpose.</strong> Long chats need compacting. Doing it deliberately beats letting the window quietly overflow.</li>
</ol>
<p>None of this makes a local agent as good as the hosted ones.
It does make it clear why they're built the way they are.</p>
<h2>FAQ</h2>
<h3>What is the default context length in Ollama?</h3>
<p>It depends on which page you read and how much VRAM you have.
The FAQ says 4096 tokens. The context length page says 4k, 32k or 256k depending on VRAM.
Run <code>ollama ps</code> to see what you actually got.</p>
<h3>Why does a bigger context window need more memory?</h3>
<p>The model keeps a KV cache entry for every token in context.
That cache grows linearly with context length, so doubling the window roughly doubles its memory.</p>
<h3>How does Claude Code remember things between sessions?</h3>
<p>Through CLAUDE.md files you write and auto memory notes it writes itself.
Both load at the start of each session. Long sessions get compacted into a summary.</p>
<h2>Sources</h2>
<ul>
<li><a href="https://docs.ollama.com/context-length">Ollama: Context length</a></li>
<li><a href="https://docs.ollama.com/faq">Ollama: FAQ</a></li>
<li><a href="https://docs.ollama.com/modelfile">Ollama: Modelfile reference</a></li>
<li><a href="https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/">NVIDIA: Mastering LLM techniques, inference optimisation</a></li>
<li><a href="https://arxiv.org/abs/2307.03172">Liu et al., Lost in the Middle: How Language Models Use Long Contexts (arXiv 2307.03172)</a></li>
<li><a href="https://code.claude.com/docs/en/memory">Claude Code docs: How Claude remembers your project</a></li>
<li><a href="https://code.claude.com/docs/en/context-window">Claude Code docs: Explore the context window</a></li>
<li><a href="https://www.electronjs.org/docs/latest/">Electron documentation</a></li>
<li><a href="https://github.com/microsoft/monaco-editor">Monaco Editor on GitHub</a></li>
</ul>
<h2>What next</h2>
<p>How I learned these tools in the first place: <a href="https://www.rahuldk.in/blog/dozens-of-email-accounts-and-zero-shame">dozens of email accounts and zero shame</a>.
And what happens when an AI coding agent does its job and the humans don't: <a href="https://www.rahuldk.in/blog/the-night-i-broke-production">the night I broke production</a>.</p>
]]></content:encoded></item></channel></rss>