<?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: Navjyot N</title>
    <description>The latest articles on DEV Community by Navjyot N (@navjyotnishant).</description>
    <link>https://dev.to/navjyotnishant</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%2F3516402%2F2fe8f07b-36ae-4094-85ed-bcd19cc54155.png</url>
      <title>DEV Community: Navjyot N</title>
      <link>https://dev.to/navjyotnishant</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/navjyotnishant"/>
    <language>en</language>
    <item>
      <title>Before You Claim AI Made Your Team Faster, Measure It</title>
      <dc:creator>Navjyot N</dc:creator>
      <pubDate>Mon, 17 Aug 2026 03:04:12 +0000</pubDate>
      <link>https://dev.to/navjyotnishant/before-you-claim-ai-made-your-team-faster-measure-it-1o9b</link>
      <guid>https://dev.to/navjyotnishant/before-you-claim-ai-made-your-team-faster-measure-it-1o9b</guid>
      <description>&lt;p&gt;Every few months, I find myself in some version of the same conversation.&lt;/p&gt;

&lt;p&gt;A team has been using AI coding tools for a while. The excitement has cooled into a more practical question: what did we actually get from this?&lt;/p&gt;

&lt;p&gt;It is a fair question. Leaders have bought licenses, teams have changed habits, and somebody eventually has to explain whether any of it helped. The awkward part is that the usual answers do not feel very satisfying. Seat counts say who had access. Surveys say how people felt. Vendor dashboards say a tool was opened.&lt;/p&gt;

&lt;p&gt;None of that tells you what happened in the codebase.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;a href="https://github.com/navjyotnishant/whodunit" rel="noopener noreferrer"&gt;whodunit&lt;/a&gt;. It is a small open-source tool for answering AI adoption questions from evidence that already exists: git commits, local agent logs, and, if you want the shared view, delivery data from DevLake.&lt;/p&gt;

&lt;p&gt;The goal is not to make AI look good. It is to make the claims harder to misuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  The questions people actually ask
&lt;/h2&gt;

&lt;p&gt;These are the questions I keep hearing from clients and engineering leaders.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is my team actually adopting AI, and is adoption spread evenly?&lt;/li&gt;
&lt;li&gt;Can you show me the productivity improvement?&lt;/li&gt;
&lt;li&gt;Are people using AI well, or just chatting with it?&lt;/li&gt;
&lt;li&gt;Is AI helping around the edges, or writing most of the code?&lt;/li&gt;
&lt;li&gt;How much AI-written code is accepted?&lt;/li&gt;
&lt;li&gt;Where is AI being used: features, fixes, tests, docs?&lt;/li&gt;
&lt;li&gt;How much autonomy are developers giving the agent?&lt;/li&gt;
&lt;li&gt;Can we see churn for AI-written code?&lt;/li&gt;
&lt;li&gt;Which models are being used most?&lt;/li&gt;
&lt;li&gt;Did PR cycle time improve?&lt;/li&gt;
&lt;li&gt;How long did adoption take?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I like this list because it is honest. It is not a polished strategy deck. It is what people ask when they are trying to make sense of a real investment.&lt;/p&gt;

&lt;p&gt;Some of these questions are answerable. Some are partly answerable. &lt;strong&gt;One of them, the productivity percentage, is the one I am most careful with.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The small thing whodunit adds
&lt;/h2&gt;

&lt;p&gt;whodunit adds a plain git trailer to commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI-Attribution: v=1; status=assisted; method=intersected; agent=claude-code; agent_version=2.1.228; ratio=0.62; model=claude-opus-5; session=a3f9e21c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no magic in the format. That is the point. It is just git metadata, readable by any tool that can read a commit message.&lt;/p&gt;

&lt;p&gt;The trailer records whether a commit was AI-assisted, which agent was involved, which model was reported, and how strong the evidence is. The strongest method, &lt;code&gt;intersected&lt;/code&gt;, means text the agent produced survived into what was staged.&lt;/p&gt;

&lt;p&gt;When the evidence is missing, whodunit records that too. It uses &lt;code&gt;undetermined&lt;/code&gt; instead of quietly deciding "no AI was used." &lt;strong&gt;That distinction between absence and zero is the rule the whole tool is built on.&lt;/strong&gt; That distinction matters more than it sounds. A missing signal is not a zero. It is just missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-screen answer
&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftrn627z6kod0ica0ey4t.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftrn627z6kod0ica0ey4t.png" alt="Whodunit executive summary showing adoption, coverage, acceptance, active sessions, and delivery comparison" width="800" height="849"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The executive dashboard is the page for the person who will not open the rest. It shows assisted commits, coverage, acceptance rate, active sessions, and delivery comparison in one place.&lt;/p&gt;

&lt;p&gt;The most important number on that page is not the flashiest one. It is coverage.&lt;/p&gt;

&lt;p&gt;Coverage tells you how much of the commit history has a valid attribution trailer. Adoption tells you how much of that covered history was assisted. Those are different claims, and mixing them up is where bad AI metrics start.&lt;/p&gt;

&lt;p&gt;A team can have high coverage and low adoption. That is a valid finding. It means the instrumentation is working and the evidence says AI is not showing up much in committed work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A team can also have low coverage and a beautiful adoption number. That one should make you pause.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adoption is a spread, not a slogan
&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foo18krcuoq2pa1k9k8py.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foo18krcuoq2pa1k9k8py.png" alt="Whodunit adoption dashboard showing contributor spread and committed work by contributor" width="800" height="1391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When someone asks "is the team adopting this?", the team average is not enough.&lt;/p&gt;

&lt;p&gt;I want to know whether adoption is spread across the group or carried by two people. I want to know who has no assisted commits at all. I want to know whether the data covers enough of the repo to trust the answer.&lt;/p&gt;

&lt;p&gt;That is why the adoption view shows contributor spread beside coverage. The contributor identity comes from the git committer email that is already present in commits. whodunit is not watching developers. It is making existing commit metadata easier to read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is one catch worth saying gently but clearly: the clock starts when instrumentation starts.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your team used AI for six months before installing hooks, those six months are not magically recoverable. whodunit can tell you what happened after the trailers started landing. For a real before-and-after story, capture a baseline before the rollout with &lt;code&gt;dun baseline capture&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Miss that window and you can still learn a lot. You just have to be honest about where the measurement begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Are they using it well?" is only partly measurable
&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi0lxoxpewti5v0m2unqg.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi0lxoxpewti5v0m2unqg.png" alt="Whodunit cost and efficiency dashboard showing model mix, tokens, cache behavior, and compaction" width="800" height="1102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the question that can get uncomfortable fast.&lt;/p&gt;

&lt;p&gt;People ask whether developers know compaction, whether they choose the right model, whether they use skills and sub-agents, whether they turn everyday work into good AI workflows. I understand why they ask. Training budgets depend on it.&lt;/p&gt;

&lt;p&gt;But I do not think a dashboard should pretend to read competence from a transcript.&lt;/p&gt;

&lt;p&gt;What whodunit can show is session shape. Did a session only involve conversation? Did it call tools? Did it edit files? Did it use many tools or MCP calls? Which models were used? Did the session compact?&lt;/p&gt;

&lt;p&gt;That gives you a useful proxy for "just chatting" versus "using the agent to do work." It does not tell you whether a developer is skilled with AI. That still needs human context: pairing, coaching, code review, and conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I would rather leave that boundary visible than build a confidence score no one should trust.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AI shows up in the work
&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fugn7de44n5h5et398luh.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fugn7de44n5h5et398luh.png" alt="Whodunit productivity funnel showing adoption, engagement, assisted work, and later stages that need stronger evidence" width="800" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For questions like "is AI being used for features, tests, docs, or fixes?", whodunit leans on commit prefixes and path heuristics.&lt;/p&gt;

&lt;p&gt;That is useful, but only if your repository gives the tool something decent to work with. If your team uses Conventional Commits, a &lt;code&gt;feat:&lt;/code&gt; commit is a pretty good signal. If your team does not, the feature panel will look empty even when people are shipping features all week.&lt;/p&gt;

&lt;p&gt;So I treat purpose as a label, not an observation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is a recurring theme in the project: the chart should say what it knows, and just as importantly, what it does not know.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Autonomy changes the shape of a session
&lt;/h2&gt;

&lt;p&gt;Autonomy was more interesting than I expected.&lt;/p&gt;

&lt;p&gt;Different tools have different permission vocabularies. Codex may report modes like &lt;code&gt;never&lt;/code&gt; and &lt;code&gt;on-request&lt;/code&gt;. Claude Code may report &lt;code&gt;acceptEdits&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;, or &lt;code&gt;auto&lt;/code&gt;. whodunit keeps those names instead of pretending they all map neatly onto the same ladder.&lt;/p&gt;

&lt;p&gt;The useful question is not only "how often did people grant autonomy?" &lt;strong&gt;It is "what happened once they did?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On my data, high-autonomy sessions were fewer, but much denser. Tool calls per session captured that better than raw session count. Still, I would be careful with the interpretation. A mode that allows more actions will naturally produce more actions. Tool calls are activity, not delivered value.&lt;/p&gt;

&lt;h2&gt;
  
  
  The productivity number everyone wants
&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjs3qzhobfzeb8yktfx82.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjs3qzhobfzeb8yktfx82.png" alt="Whodunit delivery impact dashboard showing assisted versus other delivery metrics and the productivity caveat" width="800" height="1174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the question that started the whole thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Show me the productivity improvement after AI adoption.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wish that number were easier to produce honestly. It would make the meeting shorter.&lt;/p&gt;

&lt;p&gt;The problem is that assisted and unassisted work are not random groups. Developers choose when to use an agent. They may use it for larger changes, repetitive migrations, unfamiliar code, tests, or work they already know how to delegate.&lt;/p&gt;

&lt;p&gt;So if assisted commits are larger, what does that prove?&lt;/p&gt;

&lt;p&gt;Maybe AI helped people take on bigger work. Maybe it encouraged bigger diffs. Maybe people simply used it on a different kind of task. The same chart supports all three stories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That is why whodunit shows comparisons, not productivity gains.&lt;/strong&gt; It can show change size, churn, acceptance, purpose, adoption, and cycle-time differences when delivery data is wired up. It should not turn those into a percentage and call it ROI.&lt;/p&gt;

&lt;p&gt;A baseline helps. If you capture a pre-adoption window before installing hooks, &lt;code&gt;dun delta&lt;/code&gt; can compare that period with a later one. That is much stronger than comparing assisted and unassisted commits inside the same period.&lt;/p&gt;

&lt;p&gt;It is still observational. Teams change, codebases change, projects change. &lt;strong&gt;The baseline gives you a better conversation, not a laboratory experiment.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That may sound unsatisfying. In practice, I think it is a relief. It lets you say, "Here is what moved, here is what did not, and here is what we cannot honestly claim."&lt;/p&gt;

&lt;h2&gt;
  
  
  The mistakes I am trying to avoid
&lt;/h2&gt;

&lt;p&gt;The biggest metric mistakes are usually flattering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Empty is not zero.&lt;/strong&gt; If an agent does not report token usage, showing zero makes it look free. If a commit has no attribution evidence, treating it as "not AI" makes adoption look cleaner than the evidence allows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tokens are not dollars.&lt;/strong&gt; A transcript does not know whether someone is using a subscription, an enterprise contract, or API billing. whodunit reports tokens and cache behavior. It does not invent a price.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache writes count.&lt;/strong&gt; Cache read ratio should include uncached input, cache writes, and cache reads. Leaving writes out made one of my early analyses look much better than it was.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A fix rate is not a defect rate.&lt;/strong&gt; Fix-labelled commits are a rework proxy. They are useful, but they do not prove AI caused or prevented defects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A difference is not a gain.&lt;/strong&gt; This is the one I keep coming back to. If the groups are self-selected, the comparison can be useful without being causal.&lt;/p&gt;

&lt;p&gt;None of this makes the tool less useful. It makes it safer to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it is built
&lt;/h2&gt;

&lt;p&gt;There are two pieces.&lt;/p&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnlhwl654yb963vghcddq.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnlhwl654yb963vghcddq.png" alt="whodunit solution architecture showing local git and agent evidence flowing through dun into trailers, a local journal, optional local reports, and optional DevLake/Grafana dashboards" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At a high level, whodunit keeps the sensitive work local. The developer machine reads git and local agent logs, stamps attribution into commits, and keeps a local journal. A team only gets the shared dashboards if someone chooses to sync the &lt;code&gt;whodunit_*&lt;/code&gt; tables into the optional DevLake layer.&lt;/p&gt;

&lt;p&gt;The first is &lt;code&gt;dun&lt;/code&gt;, a Go CLI that runs locally:&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;cd &lt;/span&gt;your-repo
dun init          &lt;span class="c"&gt;# installs the git hooks&lt;/span&gt;
git commit ...    &lt;span class="c"&gt;# the trailer is stamped automatically&lt;/span&gt;
dun status        &lt;span class="c"&gt;# coverage and method mix&lt;/span&gt;
dun report        &lt;span class="c"&gt;# local HTML report&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Collection is local. The hooks, daemon, and ingest command read git plus local agent transcripts and write a local SQLite journal. &lt;code&gt;dun report&lt;/code&gt; renders a self-contained HTML file without a server or network call.&lt;/p&gt;

&lt;p&gt;The second piece is optional: a DevLake and Grafana layer for teams that want a shared view. whodunit writes to its own &lt;code&gt;whodunit_*&lt;/code&gt; tables and leaves DevLake's domain tables alone. If DevLake is already where your delivery metrics live, this lets attribution sit beside them instead of creating another stack.&lt;/p&gt;

&lt;p&gt;The supported adapters today are Claude Code, Codex CLI, and &lt;code&gt;agy&lt;/code&gt; from Antigravity. Each agent records different things, and whodunit keeps those differences visible instead of smoothing them away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy, plainly
&lt;/h2&gt;

&lt;p&gt;The collection path makes no network calls.&lt;/p&gt;

&lt;p&gt;There are two pieces of identifying information worth naming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File paths, because they reveal what someone worked on.&lt;/li&gt;
&lt;li&gt;Committer email, because a shared dashboard needs to attribute work to contributors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both already exist in or around the development workflow. Both stay local unless you configure sync.&lt;/p&gt;

&lt;p&gt;The journal has no field for prompt text, message content, file contents, hostnames, or remote URLs. &lt;strong&gt;That is not a filtering promise. It is a schema choice.&lt;/strong&gt; There is nowhere for those values to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I landed
&lt;/h2&gt;

&lt;p&gt;I built whodunit because I wanted a better answer in the room.&lt;/p&gt;

&lt;p&gt;Not a louder answer. Not a prettier one. A more honest one.&lt;/p&gt;

&lt;p&gt;Most of the eleven questions can be answered from commits and local transcripts. Adoption spread, model mix, acceptance, autonomy, churn, purpose, and coverage are all measurable with real denominators. Cycle time can be measured when delivery data is connected.&lt;/p&gt;

&lt;p&gt;But whether a developer truly understands compaction or model choice is not in the data. And the clean productivity percentage people want is not there unless you are willing to make assumptions quietly.&lt;/p&gt;

&lt;p&gt;I am not willing to make them quietly.&lt;/p&gt;

&lt;p&gt;So the tool shows the difference, prints the denominator, and leaves room for argument. That is the part I care about most. If the metric logic is wrong, I want to know. If the 1.25x cache write break-even is off, tell me. If there is a better way to handle selection bias, I would genuinely like to hear it.&lt;/p&gt;

&lt;p&gt;The point is not to win the AI adoption story.&lt;/p&gt;

&lt;p&gt;The point is to make the story sturdy enough to trust.&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/navjyotnishant/whodunit" rel="noopener noreferrer"&gt;github.com/navjyotnishant/whodunit&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Docs: &lt;a href="https://navjyotnishant.github.io/whodunit/" rel="noopener noreferrer"&gt;navjyotnishant.github.io/whodunit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Relayent: use your AI subscription in your app — during dev cycle</title>
      <dc:creator>Navjyot N</dc:creator>
      <pubDate>Mon, 20 Jul 2026 02:17:06 +0000</pubDate>
      <link>https://dev.to/navjyotnishant/relayent-use-your-ai-subscription-in-your-app-during-dev-not-prod-53jo</link>
      <guid>https://dev.to/navjyotnishant/relayent-use-your-ai-subscription-in-your-app-during-dev-not-prod-53jo</guid>
      <description>&lt;p&gt;&lt;em&gt;Relayent — a blend of &lt;strong&gt;relay&lt;/strong&gt; and &lt;strong&gt;agent&lt;/strong&gt;. It relays your app's calls to an AI coding agent (Claude Code, Codex, Gemini, Cursor) that's already installed and signed in on a machine you control.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; there's a live playground at &lt;strong&gt;&lt;a href="https://relayent-demo.ignorelist.com" rel="noopener noreferrer"&gt;relayent-demo.ignorelist.com&lt;/a&gt;&lt;/strong&gt; — pick a model, send a message, and the reply comes back from a real CLI subscription with no API key behind it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I built Relayent to scratch a very specific itch, and I want to be upfront about its scope before anything else: &lt;strong&gt;this is a tool for the development cycle, not for production.&lt;/strong&gt; When you ship to real users, provisioned API tokens are the right answer — that's what they're for. What follows is about the awkward middle: the weeks of building and QA &lt;em&gt;before&lt;/em&gt; you ship, where you're burning metered tokens just to see if the thing works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap: you pay for the model twice
&lt;/h2&gt;

&lt;p&gt;You (or your engineers) already pay for an AI subscription. Claude, Codex, Gemini, Cursor — flat monthly price, and generous. You can lean on it all day in your editor and the bill doesn't move.&lt;/p&gt;

&lt;p&gt;Then a feature lands on your plate: a chat box in the product, an in-app assistant, a summarizer that fires on every uploaded doc. And none of it can touch that subscription. The subscription is scoped to the IDE-and-CLI experience — it was never meant to sit behind arbitrary application traffic. So the app talks to the metered API instead, billed per token.&lt;/p&gt;

&lt;p&gt;Here's the part that stings. You're not even in production yet. You're &lt;em&gt;developing&lt;/em&gt;. Every test run, every "does this prompt actually work," every QA pass over the new feature — all of it draws down metered API tokens, for a feature that isn't earning anything yet. &lt;strong&gt;You end up paying twice for the same models:&lt;/strong&gt; once for a subscription only a human can use, and again, at API rates, to build and test the feature before a single customer sees it.&lt;/p&gt;

&lt;p&gt;Relayent's whole premise is that during that phase, the gap doesn't need to exist. There's an authenticated CLI session already sitting on your dev machine. Why can't your app-under-development borrow it? Relayent routes the app's AI calls to that already-running subscription. &lt;strong&gt;It doesn't proxy an API key or store a credential — it never touches the CLI's auth at all.&lt;/strong&gt; It just uses the session that's already there.&lt;/p&gt;

&lt;p&gt;To be clear about where the line is: use this to &lt;em&gt;develop and QA&lt;/em&gt; against real models without watching a token meter spin. When the feature goes live, wire up proper API tokens. Relayent is a dev-cycle convenience, not a production dependency, and I'd push back on anyone trying to make it one.&lt;/p&gt;

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

&lt;p&gt;There are just two moving pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The relay&lt;/strong&gt; — a small job broker that both sides can reach over the network. Your app POSTs jobs to it and long-polls for results. Where it lives is up to you: a public host, an internal box on your intranet, or even localhost on the same machine as the bridge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The bridge&lt;/strong&gt; — runs on your own machine, right next to the signed-in CLI. It dials &lt;em&gt;out&lt;/em&gt; to the relay, pulls jobs meant for you, runs the AI coding agent headlessly, and posts the result back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bridge is where the security story really lives. &lt;strong&gt;It only ever makes outbound connections&lt;/strong&gt; — it opens nothing for the relay (or anyone else) to connect back into, so there's no port to scan, no service to attack on your machine. And crucially, &lt;strong&gt;your AI subscription and API keys never leave that machine.&lt;/strong&gt; The bridge uses the CLI's own already-signed-in session locally; it doesn't read your credentials, doesn't copy them, and doesn't send them to the relay. The relay only ever sees a job going in and a result coming out — never a token, a password, or a subscription. So even a compromised relay never gets your credentials; the worst it can do is queue jobs, not walk away with the keys to your subscription.&lt;/p&gt;

&lt;p&gt;So the flow is small on purpose. Your app POSTs a job to the relay; the bridge — on the machine with the logged-in CLI — dials out, polls for work, runs the CLI headlessly, and returns the answer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Your app  ──POST──▶  Relay  ◀──poll out──  Bridge
              job    (network-reachable)      (your machine, dials OUT)
                                                     │
                                                     └─▶ claude / codex / gemini / cursor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shape does two useful things. &lt;strong&gt;Nothing listens on the dev machine&lt;/strong&gt; — no inbound port, no tunnel, no NAT to punch through. The bridge is purely a client; it reaches out, never the reverse. And the relay is the only component anything connects &lt;em&gt;to&lt;/em&gt;, so it's the only attack surface to harden — and if you expose it to the public internet, the only thing that has to be internet-hardened. No credentials pass through Relayent itself; the CLI on the bridge uses its own session, and the relay never sees a password or an API key.&lt;/p&gt;

&lt;p&gt;The relay is a small Go job broker behind a versioned &lt;code&gt;/v1&lt;/code&gt; API — POST a job, long-poll the result. Four backends work today: &lt;code&gt;claude&lt;/code&gt;, &lt;code&gt;codex&lt;/code&gt;, &lt;code&gt;gemini&lt;/code&gt;, and &lt;code&gt;cursor&lt;/code&gt;. (Cursor runs in &lt;code&gt;--mode ask&lt;/code&gt;, read-only, so a job can't edit files or run shell commands on the bridge.) Install and sign into whichever CLI you want to lend out, and it shows up — no restart.&lt;/p&gt;

&lt;h2&gt;
  
  
  The demo playground
&lt;/h2&gt;

&lt;p&gt;The fastest way to get the idea is to go use it: &lt;strong&gt;&lt;a href="https://relayent-demo.ignorelist.com" rel="noopener noreferrer"&gt;relayent-demo.ignorelist.com&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; on the public demo, only &lt;strong&gt;Cursor&lt;/strong&gt; works out of the box — the other backends (Claude, Codex, Gemini) are switched off to keep strangers from spending paid quota. Pick Cursor to see a live reply.&lt;/p&gt;
&lt;/blockquote&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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fdemo-playground.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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fdemo-playground.png" alt="The Relayent Playground: a chat UI with a " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's a plain chat page — pick a model, type, get a reply. Nothing fancy, and that's the point: every reply on that page is running on a real CLI subscription behind a bridge, not on any API key. The model dropdown isn't hardcoded either; it's populated live from the relay's capabilities, so it only ever lists what a connected bridge can actually run.&lt;/p&gt;

&lt;p&gt;Under the hood the demo is a thin proxy. The browser only ever talks to the demo server's own &lt;code&gt;/api/*&lt;/code&gt; endpoints, which forward to the relay with a server-side credential — the app credential never reaches the page. And which models the demo is &lt;em&gt;allowed&lt;/em&gt; to offer is a policy decision made in the admin console (more on that next). For a public demo like this one, you keep the paid backends switched off and expose something you don't mind strangers exercising — otherwise a public URL is just a way to let the internet spend your quota.&lt;/p&gt;

&lt;h2&gt;
  
  
  The admin panel
&lt;/h2&gt;

&lt;p&gt;Once more than one person is using a relay, you need somewhere to run it from. That's the admin console.&lt;/p&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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fadmin-users.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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fadmin-users.png" alt="The Relayent admin console's Users view: each user's role, bridge status, pending-job count, and bound-bridge count, with per-user lifecycle actions (enrol, promote/demote, disable, delete) — operational visibility, no prompt or result content anywhere" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You sign in with your identity provider — Google, or any OIDC issuer — and land here. It's organized into a few groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Users&lt;/strong&gt; — everyone with a bridge on the relay: their role, whether their bridge is online, how many jobs are pending, how many bridges they've bound. Promote, demote, disable, or remove someone from the same row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enrol a bridge&lt;/strong&gt; — mint a one-time token so a specific user can pair their machine. That's how a bridge gets bound to exactly one person.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backends&lt;/strong&gt; — the on/off switches for &lt;code&gt;claude&lt;/code&gt; / &lt;code&gt;codex&lt;/code&gt; / &lt;code&gt;cursor&lt;/code&gt; / &lt;code&gt;gemini&lt;/code&gt;. This is the control that keeps a public demo from touching your paid subscriptions: flip the expensive ones off and they simply aren't reachable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App credentials&lt;/strong&gt; — issue and revoke the credentials your apps (and the demo) use to enqueue work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit&lt;/strong&gt; — a per-user activity trail: job counts, backends, timing. Notably, &lt;em&gt;not&lt;/em&gt; the prompts or results — the console shows what happened, never what was said.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One deliberate choice worth calling out: &lt;strong&gt;the admin is an operator, not an observer.&lt;/strong&gt; You can see that Alice ran forty jobs on Cursor yesterday and that her bridge is online right now. You cannot see what she asked. That boundary is structural, not a UI toggle — there's simply nowhere in the audit record for prompt content to live.&lt;/p&gt;

&lt;p&gt;The console is the admin's view. Everyone else gets their own: sign in as a regular user and you land on a status page scoped to &lt;em&gt;you&lt;/em&gt; — is my bridge online, which backends can it run, how many jobs are queued — and nothing about anyone else. Same sign-in door (&lt;code&gt;/login&lt;/code&gt;), routed by role: admins to the console, users to their own page. It's the same operator-not-observer line drawn one level down — you can see your own machine, not the relay's other tenants.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interesting part: keeping tenants apart
&lt;/h2&gt;

&lt;p&gt;Everything above is easy with one user. It gets interesting the moment several people share a relay, each bringing their own subscription — which is exactly the setup where this is useful for a team. Now the relay is holding several authenticated sessions at once, and &lt;strong&gt;it has to guarantee that Alice's prompt can never be picked up by Bob's bridge.&lt;/strong&gt; If it could, Alice would be quietly spending Bob's quota, on Bob's machine, and Bob would never know.&lt;/p&gt;

&lt;p&gt;The tempting shortcut is a single shared pairing key — but that quietly makes one secret do three different jobs at once: authenticating the caller, identifying the tenant, and naming the routing namespace. Possession becomes authorization, and anyone holding the key &lt;em&gt;is&lt;/em&gt; you: no way to tell tenants apart, no way to revoke just one. That's exactly the property you can't have when several people's subscriptions sit behind one relay.&lt;/p&gt;

&lt;p&gt;So Relayent pulls those three jobs apart. Every request carries a &lt;code&gt;Principal&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Principal&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;UserID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Kind&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Scopes&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;KeyFP&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auth decides &lt;em&gt;who you are&lt;/em&gt;; the queue routes purely on &lt;code&gt;UserID&lt;/code&gt;. And the queue is keyed by that id all the way down, so one person's jobs and another's are never even in the same list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jobUser&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;userID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt; &lt;span class="c"&gt;// unknown job, or another tenant's — same answer either way&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That check sits at every method that touches a job by id. Knowing a job id isn't enough to do anything with it — you also have to &lt;em&gt;be&lt;/em&gt; the user it belongs to, resolved from your Principal, not from something you put in a request body. And it fails identically whether the job doesn't exist or just isn't yours, so probing can't even confirm a job exists in a namespace you can't see.&lt;/p&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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fsystem-arch.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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fsystem-arch.png" alt="Relayent multi-tenant relay architecture: N apps enqueue jobs for specific users; the relay splits auth from routing via a Principal and keys its in-memory queue by userID; each user's own outbound-only bridge claims only its user's jobs" width="799" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  On security, briefly
&lt;/h2&gt;

&lt;p&gt;I'll keep this short, because it's a blog post and not a threat model. Relayent was built security-first: the bridge only ever dials out (nothing to attack on the user's machine), no credentials pass through the relay, the pairing key is a bearer secret checked in constant time and never logged, humans sign in via OIDC so there's no password anywhere at rest, and machine credentials are stored hashed. Per-user isolation is enforced and tested, anti-spoofing guard included.&lt;/p&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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fsecurity-arch.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%2Fgithub.com%2FToolTropolis%2FRelayent%2Freleases%2Fdownload%2FBLOG-IMAGES%2Fsecurity-arch.png" alt="Relayent data-protection diagram in two rows. TODAY: app, relay, and bridge icons; both hops are TLS-encrypted in transit, and the amber relay sees prompts and results in the clear. PLANNED end-to-end (rolling out): the app seals the prompt to the bridge's key, the green relay routes only sealed ciphertext it cannot read (just routing metadata — who, which job, backend), and the bridge is the only place that can decrypt it. A strip lists the controls the relay protects today — dial-out-only bridge, no credentials through the relay, constant-time pairing key, OIDC sign-in, hashed machine credentials, tested per-user isolation" width="799" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The one honest caveat I'd want any reader to take away: &lt;strong&gt;isolation here is authorization, not encryption.&lt;/strong&gt; Tenants can't reach each other's jobs, but the relay operator's process still holds prompts and results in memory in the clear while a job runs. &lt;strong&gt;Don't push secrets through a relay you don't trust.&lt;/strong&gt; If you want the full picture — including what it deliberately &lt;em&gt;doesn't&lt;/em&gt; protect against — &lt;a href="https://github.com/ToolTropolis/Relayent/blob/main/SECURITY.md" rel="noopener noreferrer"&gt;SECURITY.md&lt;/a&gt; lays it out without spin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this lands
&lt;/h2&gt;

&lt;p&gt;Relayent solves one problem well: during development and QA, let your app lean on the AI subscription you're already paying for, instead of quietly metering API tokens on a feature that isn't live yet. Point your team at it, give everyone their own bridge, and the dev-cycle token bill largely goes away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And it all runs in your own environment.&lt;/strong&gt; You can stand the whole thing up locally — relay and bridge on machines you control — so nothing leaves your network and no data goes to a third party. &lt;strong&gt;You never hand Relayent a key or a subscription;&lt;/strong&gt; you just install and sign into the AI coding agents you already use (Claude Code, Codex, Gemini, Cursor), and the bridge picks them up automatically. Your credentials stay where they are, your prompts and results stay in your environment, and &lt;strong&gt;full data privacy is the default, not a configuration step.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just don't mistake it for a production answer. In prod, provisioned API tokens are the right tool — properly scoped, properly billed, properly supported. Relayent is the thing that saves you money on the way there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it in your own environment
&lt;/h2&gt;

&lt;p&gt;The demo is the two-minute version. If you want to actually run it — stand up a relay, pair a bridge on your own machine, and point a dev build at it — everything you need is in the repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ToolTropolis/Relayent/blob/main/INSTALL.md" rel="noopener noreferrer"&gt;INSTALL.md&lt;/a&gt;&lt;/strong&gt; — start to finish: build the bridge, run a relay (localhost, private, or public with automatic TLS), verify it, and troubleshoot. Exact commands, expected output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ToolTropolis/Relayent/blob/main/README.md" rel="noopener noreferrer"&gt;README.md&lt;/a&gt;&lt;/strong&gt; — the overview, quick start, and the multi-tenant setup if you're running it for a team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ToolTropolis/Relayent/blob/main/API.md" rel="noopener noreferrer"&gt;API.md&lt;/a&gt;&lt;/strong&gt; — the &lt;code&gt;/v1&lt;/code&gt; contract for wiring your app in: every call, what the numbers mean, and a runnable client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ToolTropolis/Relayent/blob/main/SECURITY.md" rel="noopener noreferrer"&gt;SECURITY.md&lt;/a&gt;&lt;/strong&gt; — the full threat model and, importantly, what it deliberately &lt;em&gt;doesn't&lt;/em&gt; protect against. Read this before you put a relay on the internet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A local relay + one bridge takes a few minutes and needs nothing but the CLIs you already have signed in. Kick the tires at &lt;strong&gt;&lt;a href="https://relayent-demo.ignorelist.com" rel="noopener noreferrer"&gt;relayent-demo.ignorelist.com&lt;/a&gt;&lt;/strong&gt;, and the code's on &lt;a href="https://github.com/ToolTropolis/Relayent" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>showdev</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
