<?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: Hrutav Modha</title>
    <description>The latest articles on DEV Community by Hrutav Modha (@hrutav_modha_c0c028285f7e).</description>
    <link>https://dev.to/hrutav_modha_c0c028285f7e</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3840520%2Fcd7dc7fd-35c4-48e2-8945-c37082ccaf60.jpg</url>
      <title>DEV Community: Hrutav Modha</title>
      <link>https://dev.to/hrutav_modha_c0c028285f7e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hrutav_modha_c0c028285f7e"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Hrutav Modha</dc:creator>
      <pubDate>Sun, 30 Aug 2026 04:13:46 +0000</pubDate>
      <link>https://dev.to/hrutav_modha_c0c028285f7e/-4eie</link>
      <guid>https://dev.to/hrutav_modha_c0c028285f7e/-4eie</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/hrutav_modha_c0c028285f7e/how-driftjs-updates-dom-without-diffing-or-signals-39cc" class="crayons-story__hidden-navigation-link"&gt;How DriftJS Updates DOM Without Diffing or Signals?&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/hrutav_modha_c0c028285f7e" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3840520%2Fcd7dc7fd-35c4-48e2-8945-c37082ccaf60.jpg" alt="hrutav_modha_c0c028285f7e profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/hrutav_modha_c0c028285f7e" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Hrutav Modha
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Hrutav Modha
                
                
              
              &lt;div id="story-author-preview-content-4523370" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/hrutav_modha_c0c028285f7e" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3840520%2Fcd7dc7fd-35c4-48e2-8945-c37082ccaf60.jpg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Hrutav Modha&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/hrutav_modha_c0c028285f7e/how-driftjs-updates-dom-without-diffing-or-signals-39cc" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 29&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/hrutav_modha_c0c028285f7e/how-driftjs-updates-dom-without-diffing-or-signals-39cc" id="article-link-4523370"&gt;
          How DriftJS Updates DOM Without Diffing or Signals?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/architecture"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;architecture&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frontend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/hrutav_modha_c0c028285f7e/how-driftjs-updates-dom-without-diffing-or-signals-39cc" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/hrutav_modha_c0c028285f7e/how-driftjs-updates-dom-without-diffing-or-signals-39cc#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>How DriftJS Updates DOM Without Diffing or Signals?</title>
      <dc:creator>Hrutav Modha</dc:creator>
      <pubDate>Sat, 29 Aug 2026 16:36:37 +0000</pubDate>
      <link>https://dev.to/hrutav_modha_c0c028285f7e/how-driftjs-updates-dom-without-diffing-or-signals-39cc</link>
      <guid>https://dev.to/hrutav_modha_c0c028285f7e/how-driftjs-updates-dom-without-diffing-or-signals-39cc</guid>
      <description>&lt;p&gt;In my last post, I introduced DriftJS — a frontend framework built around a register-based bytecode VM instead of Virtual DOM diffing or a compile-only reactive model. This post is the natural follow-up: how does the reactivity actually work under the hood?&lt;/p&gt;

&lt;p&gt;I've been calling the mechanism &lt;strong&gt;Jump-Based Reactivity&lt;/strong&gt; in my own notes — that's just the name I've given it for now, not an established or official term, so take it as a working label rather than a claim of industry terminology. Here's the actual model behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two established approaches, and where they spend their time
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Virtual DOM diffing&lt;/strong&gt; (React, and Vue's core diffing engine) answers "what changed?" at runtime, by comparing two trees. Even a single-character update walks a comparison algorithm over the affected subtree before a single DOM node gets touched. The cost is proportional to how much UI you're describing, not how much of it actually changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signals&lt;/strong&gt; (Solid, Svelte 5, Angular signals) answer "what changed?" by building a live subscription graph at runtime — a reactive value tracks every computation that reads it, and writing to it directly notifies exactly those subscribers. No tree, no diff, but there's a graph of subscription objects that has to be built, maintained, and torn down as your app runs.&lt;/p&gt;

&lt;p&gt;This model takes a third position: answer "what changed, and where" &lt;strong&gt;entirely at compile time&lt;/strong&gt;, so that at runtime there's no tree to walk and no graph to traverse — just a direct address to jump to.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it actually works
&lt;/h2&gt;

&lt;p&gt;When your template is compiled, every place a piece of state gets rendered — an interpolated value, a dynamic attribute — has a precise, fixed location in the compiled instruction stream. The compiler doesn't just generate that instruction stream; it builds an index while doing so: for every variable your component declares, it records exactly which instruction addresses depend on it.&lt;/p&gt;

&lt;p&gt;Think of it as a table of contents built at compile time: &lt;em&gt;"if &lt;code&gt;count&lt;/code&gt; changes, the instructions that care about it live at these exact addresses."&lt;/em&gt; This table is static — built once, when the component is compiled, and reused for every instance of that component afterward. Nothing about it changes at runtime.&lt;/p&gt;

&lt;p&gt;At runtime, when a state variable is mutated, the framework doesn't recompute anything or walk anything. It looks up the variable's entry in that compile-time table, and for each address recorded there, it &lt;strong&gt;jumps directly to that exact point in the instruction stream and executes precisely one instruction&lt;/strong&gt; — read the new value, write it to the DOM. Then it stops. No re-execution of the surrounding component, no walk through unrelated instructions, no revisiting parts of the UI that didn't change.&lt;/p&gt;

&lt;p&gt;Multiple state changes in the same tick get coalesced into a single batched pass, so five synchronous mutations don't trigger five separate rounds of this — they're collected and flushed together, with a safety limit against updates that could otherwise trigger each other in an unbounded loop.&lt;/p&gt;

&lt;p&gt;Conditional and loop blocks work on the same principle at a slightly coarser level — tracked as named regions rather than individual instructions, so a state change that affects which branch is active, or which items exist in a list, resolves to "which regions does this variable affect" via a direct lookup, not a scan across every conditional or loop in the component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this isn't Virtual DOM with extra steps
&lt;/h2&gt;

&lt;p&gt;There's no tree, at any point, that gets rebuilt and compared. The entire "what needs to update" question is answered once, at compile time, and stored as a flat address table — never re-derived at runtime against a tree structure. A component with hundreds of static DOM nodes and one dynamic binding pays a cost proportional to &lt;em&gt;one&lt;/em&gt; — the address recorded for that binding — never the size of the surrounding tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this isn't Signals with a different name
&lt;/h2&gt;

&lt;p&gt;This is the comparison people reach for fastest, and it's worth being precise about. A signal's dependency relationships are discovered &lt;strong&gt;dynamically, at read time&lt;/strong&gt; — a computation reads a signal, and that read &lt;em&gt;creates&lt;/em&gt; a subscription object that has to live in memory for as long as the relationship holds. This compile-time address table is the opposite: built once, entirely at compile time, and it's pure data — a lookup table, not a graph of live subscription objects being created and torn down as the app runs.&lt;/p&gt;

&lt;p&gt;The other real difference is granularity, and it's worth being upfront about: signals are fine-grained by construction — one reactive value, one precise set of subscribers. This model currently groups by declared variable name rather than individual binding. That's a real tradeoff against what signals give for free, and it's the thing I'm actively tightening next — recent benchmarking made it clear exactly where that coarseness costs the most: targeted updates to individual list items, not bulk rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lineage, and what's actually new
&lt;/h2&gt;

&lt;p&gt;Compiling a template into an instruction stream that gets executed rather than diffed isn't new — Ember's Glimmer engine has done that since around 2017, and it's the closest existing relative to this design. What's different is &lt;em&gt;how&lt;/em&gt; the "what changed" question resolves at runtime. Prior bytecode-VM approaches build their update-tracking structures at runtime and walk them sequentially when state changes. This model's address table is built at compile time and resolved through direct lookups — no runtime structure to walk, just a jump to a known address.&lt;/p&gt;

&lt;p&gt;That's the actual claim: not reactivity reinvented from nothing, but a genuinely different way of assembling ideas that mostly already existed — compile-time indexing, direct addressing — into something with a different performance profile in practice.&lt;/p&gt;




&lt;p&gt;Feedback, are genuinely welcom&lt;/p&gt;

&lt;p&gt;GitHub Repo: &lt;a href="https://github.com/hrutavmodha/driftjs" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introducing DriftJS: An Ultra-Fast, Register-Based Bytecode VM Framework</title>
      <dc:creator>Hrutav Modha</dc:creator>
      <pubDate>Wed, 05 Aug 2026 15:25:03 +0000</pubDate>
      <link>https://dev.to/hrutav_modha_c0c028285f7e/introducing-driftjs-an-ultra-fast-register-based-bytecode-vm-framework-4j9g</link>
      <guid>https://dev.to/hrutav_modha_c0c028285f7e/introducing-driftjs-an-ultra-fast-register-based-bytecode-vm-framework-4j9g</guid>
      <description>&lt;p&gt;The frontend ecosystem is always evolving, moving from Virtual DOM diffing to fine-grained reactivity and compiler-heavy approaches. Today, I'm excited to share an experimental project exploring a different path: &lt;strong&gt;DriftJS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DriftJS&lt;/strong&gt; is a next-generation frontend framework powered by an in-browser &lt;strong&gt;register-based Bytecode Virtual Machine (VM)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hrutavmodha/driftjs" rel="noopener noreferrer"&gt;&lt;strong&gt;Check out the GitHub Repository&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture &amp;amp; Compiler Pipeline
&lt;/h2&gt;

&lt;p&gt;Unlike traditional Virtual DOM frameworks that re-evaluate large tree structures, or compiler-only frameworks, DriftJS compiles &lt;code&gt;.drift&lt;/code&gt; single-file templates into compact binary-serializable bytecode streams (&lt;code&gt;CompiledModule&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;At runtime, a lightweight &lt;strong&gt;256-register VM&lt;/strong&gt; executes these instructions directly against the DOM.&lt;/p&gt;

&lt;p&gt;The compilation and execution workflow consists of 5 tightly decoupled stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DriftLexer&lt;/strong&gt;: On-demand parser-driven tokenization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DriftParser&lt;/strong&gt;: AST construction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DriftTransformer&lt;/strong&gt;: Whitespace stripping &amp;amp; Acorn JS expression enrichment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DriftGenerator&lt;/strong&gt;: Emits a precise 15-Opcode Bytecode Array, Constant Pool, &amp;amp; Reactive Bindings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DriftClientVM&lt;/strong&gt;: Executes Bytecode via 256 Registers &amp;amp; Keyed LIS Reconciler&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔥 Key Technical Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🛡️ &lt;strong&gt;100% CSP Compliant&lt;/strong&gt;: Built-in Acorn AST interpreter evaluates JS expressions in scope &lt;em&gt;without&lt;/em&gt; &lt;code&gt;eval()&lt;/code&gt; or &lt;code&gt;new Function()&lt;/code&gt;, making DriftJS safe for strict Content Security Policy environments.&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Register-Based Virtual Machine&lt;/strong&gt;: Uses exactly 256 fast virtual registers (&lt;code&gt;r0&lt;/code&gt;, &lt;code&gt;r1&lt;/code&gt;, ...) for DOM elements, text nodes, and values. Memory allocation is kept incredibly low.&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Keyed LIS Reconciliation&lt;/strong&gt;: Features a custom Longest Increasing Subsequence (LIS) list reconciler that minimizes DOM node movements, insertions, and deletions during loop updates (triggered by the &lt;code&gt;0x0E REACTIVE_FOR&lt;/code&gt; opcode).&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Fast-Path Attribute Patching&lt;/strong&gt;: Re-evaluates element attributes in-place without rebuilding DOM subtrees when data object references remain stable using the &lt;code&gt;0x05 SET_ATTR&lt;/code&gt; opcode.&lt;/li&gt;
&lt;li&gt;📍 &lt;strong&gt;Fine-Grained Reactive Regions&lt;/strong&gt;: HTML comment anchors visually bound &lt;code&gt;@if&lt;/code&gt; and &lt;code&gt;@for&lt;/code&gt; blocks, allowing surgical &lt;code&gt;clearBetweenAnchors&lt;/code&gt; re-rendering of targeted regions without disturbing surrounding DOM elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏆 Benchmark Results vs React 19
&lt;/h2&gt;

&lt;p&gt;In the official &lt;code&gt;js-framework-benchmark&lt;/code&gt; suite, DriftJS shows massive performance gains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10.8x FASTER&lt;/strong&gt; than React 19 on "Swap rows (1k)" (119.0ms vs 1285.7ms)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3.05x FASTER&lt;/strong&gt; on "Clear 1,000 rows" (92.4ms vs 282.0ms)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2.06x FASTER&lt;/strong&gt; on "Create 10,000 rows" (1842.9ms vs 3804.5ms)&lt;/li&gt;
&lt;li&gt;Uses &lt;strong&gt;~1.8x less memory&lt;/strong&gt; during the "Run-Clear" cycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5.75x smaller&lt;/strong&gt; uncompressed bundle size than React 19.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  We Need Your Help! 🤝
&lt;/h2&gt;

&lt;p&gt;DriftJS is currently an &lt;strong&gt;experimental prototype&lt;/strong&gt;. While the single-template bytecode compilation, Acorn expression evaluation, and basic keyed LIS list reconciliation are implemented and passing test suites, there is more to do!&lt;/p&gt;

&lt;p&gt;Current limitations include a lack of component composition/nesting, routing, state management stores, and SSR/hydration.&lt;/p&gt;

&lt;p&gt;We warmly invite framework researchers, compiler engineers, and open-source contributors to collaborate with us! Whether you want to fix bugs, optimize VM opcode execution, improve compiler error reporting, or add developer tools, we'd love to have you.&lt;/p&gt;

&lt;p&gt;Drop by the &lt;a href="https://github.com/hrutavmodha/driftjs" rel="noopener noreferrer"&gt;repo&lt;/a&gt;, check out the architecture, and let us know what you think!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>frontend</category>
    </item>
    <item>
      <title>I'm a Diploma Student. I Built an AI Agent Sandbox in 2–3 Days Using setfacl</title>
      <dc:creator>Hrutav Modha</dc:creator>
      <pubDate>Mon, 23 Mar 2026 17:31:54 +0000</pubDate>
      <link>https://dev.to/hrutav_modha_c0c028285f7e/the-problem-nobody-is-solving-properly-in-multi-agent-ai-43d0</link>
      <guid>https://dev.to/hrutav_modha_c0c028285f7e/the-problem-nobody-is-solving-properly-in-multi-agent-ai-43d0</guid>
      <description>&lt;p&gt;I'm in 4th semester Diploma in Computer Engineering.&lt;/p&gt;

&lt;p&gt;I don't know AutoGen, CrewAI, or Docker.&lt;/p&gt;

&lt;p&gt;I had a problem, sat at my PC, and solved it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I was running agentic workflows via Gemini CLI using a markdown task file.&lt;/p&gt;

&lt;p&gt;Wanted a loop: Developer → Tester → Reviewer.&lt;/p&gt;

&lt;p&gt;Issue: &lt;strong&gt;Tester could read implementation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So instead of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Does this satisfy the spec?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It asked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Does this match the code?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's not testing — it's validation bias. I saw it happen: wrong code passed &lt;br&gt;
because tests were influenced by source.&lt;/p&gt;

&lt;p&gt;"Tell AI not to read files" is not a security model. It's trust.&lt;/p&gt;

&lt;p&gt;I needed enforcement.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;Linux already solves this: &lt;strong&gt;filesystem-level access control.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;useradd &lt;span class="nt"&gt;--system&lt;/span&gt; &lt;span class="nt"&gt;--no-create-home&lt;/span&gt; &lt;span class="nt"&gt;--shell&lt;/span&gt; /usr/sbin/nologin kernelcage-agent
setfacl &lt;span class="nt"&gt;-m&lt;/span&gt; u:kernelcage-agent:--- tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Tester physically cannot read &lt;code&gt;src/&lt;/code&gt;, the problem is eliminated at the &lt;br&gt;
OS level. No prompts. No containers. Just the kernel refusing the syscall.&lt;/p&gt;

&lt;p&gt;The key insight: &lt;code&gt;setfacl&lt;/code&gt; lets you set permissions per user without &lt;br&gt;
touching anyone else's access. My own permissions stay untouched. Only &lt;br&gt;
&lt;code&gt;kernelcage-agent&lt;/code&gt; gets restricted.&lt;/p&gt;


&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;3 agents, enforced by kernel.&lt;/p&gt;

&lt;p&gt;No need for 3 users. Agents run sequentially — use one unprivileged &lt;br&gt;
daemon user (&lt;code&gt;kernelcage-agent&lt;/code&gt;), flip ACL permissions per turn using &lt;br&gt;
&lt;code&gt;setfacl&lt;/code&gt; before handing control to each agent.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;TASKS.md&lt;/th&gt;
&lt;th&gt;REVIEW.md&lt;/th&gt;
&lt;th&gt;src/&lt;/th&gt;
&lt;th&gt;tests/&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Developer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;R+W&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tester&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;R+W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reviewer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R+W&lt;/td&gt;
&lt;td&gt;R+W&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Developer cannot read &lt;code&gt;tests/&lt;/code&gt; — kernel refuses the call&lt;/li&gt;
&lt;li&gt;Tester cannot read &lt;code&gt;src/&lt;/code&gt; — derives tests only from spec, not implementation&lt;/li&gt;
&lt;li&gt;Reviewer sees all, modifies only coordination files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; kernelcage-agent bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;generated_command&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No sudo, no password — privilege escalation fails instantly at OS level.&lt;/p&gt;

&lt;p&gt;The permission flip in Python looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mark_no_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;setfacl -R -m u:kernelcage-agent:--- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;setfacl -R -d -m u:kernelcage-agent:--- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mark_write_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;setfacl -R -m u:kernelcage-agent:rwx &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;setfacl -R -d -m u:kernelcage-agent:rwx &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mark_read_only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;setfacl -R -m u:kernelcage-agent:rx &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;setfacl -R -d -m u:kernelcage-agent:rx &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-d&lt;/code&gt; flag sets default ACLs so newly created files inside a directory &lt;br&gt;
automatically inherit the same restrictions. Without it, a file created by &lt;br&gt;
the Developer agent would have no ACL and be readable by everyone.&lt;/p&gt;


&lt;h2&gt;
  
  
  Protocol
&lt;/h2&gt;

&lt;p&gt;Two markdown files. That's the entire inter-agent communication layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;TASKS.md&lt;/code&gt;&lt;/strong&gt; — forward progress&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; [ ] Task 1
&lt;span class="p"&gt;-&lt;/span&gt; [x] Task 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;REVIEW.md&lt;/code&gt;&lt;/strong&gt; — bug channel&lt;/p&gt;

&lt;p&gt;When this file exists, it overrides normal flow across all three agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Present → fix described bug first&lt;/li&gt;
&lt;li&gt;Absent → continue with next task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No APIs. No message queues. Files are the protocol.&lt;/p&gt;




&lt;h2&gt;
  
  
  Feedback Loop
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TASKS.md → Developer → src/
           (no test access)
                ↓
           Tester → tests/
           (no src access)
                ↓
           Reviewer → runs suite
                ↓
          FAIL        PASS
           ↓            ↓
      append          mark done
      REVIEW.md       commit + push
           ↓
      Developer
      reads bug,
      fixes src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No human intervention in the normal path.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prior Art Search
&lt;/h2&gt;

&lt;p&gt;Searched GitHub, ArXiv, Google Scholar, HackerNews, Reddit, and &lt;br&gt;
documentation of every major agentic framework.&lt;/p&gt;

&lt;p&gt;Findings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All frameworks use either prompt isolation or containers&lt;/li&gt;
&lt;li&gt;None applied native Linux filesystem permissions to isolate agents 
from each other in a coding loop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Closest match: A March 2026 academic paper on a hospital agent OS using &lt;br&gt;
the exact same mechanism — Linux user isolation, ACL-based file permissions, &lt;br&gt;
inter-agent coordination via document writes — for medical agents under &lt;br&gt;
HIPAA compliance requirements.&lt;/p&gt;

&lt;p&gt;Same architecture. Different domain. Published after this.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Status
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Single Python script&lt;/li&gt;
&lt;li&gt;Uses a predefined &lt;code&gt;TASKS.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;One unprivileged daemon user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setfacl&lt;/code&gt; permission flipping per agent turn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No config system, no multi-provider support, no packaging yet.&lt;/p&gt;

&lt;p&gt;Works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/hrutavmodha/ai-sandboxer" rel="noopener noreferrer"&gt;https://github.com/hrutavmodha/ai-sandboxer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: &lt;code&gt;setfacl&lt;/code&gt; requires ACL support enabled on your filesystem.&lt;br&gt;
Check with &lt;code&gt;mount | grep acl&lt;/code&gt;. If not enabled:&lt;br&gt;
&lt;code&gt;sudo mount -o remount,acl /&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Honest Note
&lt;/h2&gt;

&lt;p&gt;Built in 2-3 days.&lt;/p&gt;

&lt;p&gt;No prior framework knowledge. No Docker. No awareness of what the &lt;br&gt;
"standard" solution was supposed to be.&lt;/p&gt;

&lt;p&gt;Just looked at the problem and reached for what the OS already provides.&lt;/p&gt;

&lt;p&gt;Sometimes not knowing the established approach means you find a &lt;br&gt;
different one.&lt;/p&gt;

&lt;p&gt;If there's a flaw, I genuinely want to know.&lt;/p&gt;

&lt;p&gt;Stars, issues, and brutal feedback all welcome.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>linux</category>
      <category>security</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
