<?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: Diya</title>
    <description>The latest articles on DEV Community by Diya (@diya730).</description>
    <link>https://dev.to/diya730</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%2F3979482%2F5cc042c3-6d91-4387-8957-e14d130d550d.jpg</url>
      <title>DEV Community: Diya</title>
      <link>https://dev.to/diya730</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/diya730"/>
    <language>en</language>
    <item>
      <title>4 tools I built because I don't trust AI to check AI's work</title>
      <dc:creator>Diya</dc:creator>
      <pubDate>Sat, 18 Jul 2026 16:06:28 +0000</pubDate>
      <link>https://dev.to/diya730/four-deterministic-tools-for-the-agent-coding-era-40ga</link>
      <guid>https://dev.to/diya730/four-deterministic-tools-for-the-agent-coding-era-40ga</guid>
      <description>&lt;p&gt;If you've spent any real time working with coding agents, you've&lt;br&gt;
probably watched one of them touch a file that had nothing to do with&lt;br&gt;
the task. Or seen a schema quietly change underneath a tool you&lt;br&gt;
depend on. Or tried to figure out, after the fact, which one of 500&lt;br&gt;
subagents actually caused a run to go sideways.&lt;/p&gt;

&lt;p&gt;The obvious fix is "have another AI check it." I didn't want that fix.&lt;br&gt;
An LLM judging LLM output costs tokens on every single run, its&lt;br&gt;
reasoning is a black box you can't fully audit, and it can be wrong in&lt;br&gt;
ways that are hard to catch precisely &lt;em&gt;because&lt;/em&gt; it sounds confident.&lt;/p&gt;

&lt;p&gt;So I built four small tools that do the boring, deterministic version&lt;br&gt;
of the same job instead — AST parsing, graph algorithms, statistics.&lt;br&gt;
No model in the loop. Same answer every time, for free.&lt;/p&gt;
&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Catches&lt;/th&gt;
&lt;th&gt;Cost per run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/DIYA73/skillcheck" rel="noopener noreferrer"&gt;skillcheck&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;broken &lt;code&gt;SKILL.md&lt;/code&gt; files agents rely on&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/DIYA73/mcp-schema-watch" rel="noopener noreferrer"&gt;mcp-schema-watch&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;breaking changes in MCP servers you depend on&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/DIYA73/PR-Blast-Radius-" rel="noopener noreferrer"&gt;pr-blast-radius&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;PR scope creep, via import-graph analysis&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/DIYA73/swarm-trace-viewer" rel="noopener noreferrer"&gt;swarm-trace-viewer&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;where a large agent swarm actually diverged&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All four are MIT licensed. Here's what each one actually does.&lt;/p&gt;
&lt;h2&gt;
  
  
  skillcheck — a linter for the files your agents read
&lt;/h2&gt;

&lt;p&gt;Claude Code, Codex, and Cursor agents all read &lt;code&gt;SKILL.md&lt;/code&gt; files to&lt;br&gt;
learn how to do something. Nobody lints those files. skillcheck does:&lt;br&gt;
missing frontmatter, broken relative links, descriptions that are too&lt;br&gt;
short to be useful or too long to fit in context comfortably, and a&lt;br&gt;
hard token budget so one skill file can't quietly eat half an agent's&lt;br&gt;
context window before it's done anything.&lt;/p&gt;

&lt;p&gt;Ships as a CLI and a composite GitHub Action, so it runs in CI the&lt;br&gt;
same way ESLint does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DIYA73/skillcheck" rel="noopener noreferrer"&gt;github.com/DIYA73/skillcheck&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  mcp-schema-watch — breaking-change detection for MCP servers
&lt;/h2&gt;

&lt;p&gt;MCP servers can change their tool schemas without any warning, and if&lt;br&gt;
your code depends on one, that shows up as a silent failure in&lt;br&gt;
production, hours after the actual change happened. This polls the&lt;br&gt;
servers you configure, snapshots each tool's schema, and diffs it&lt;br&gt;
against the last snapshot on every run — classifying every change as&lt;br&gt;
either &lt;strong&gt;breaking&lt;/strong&gt; (a required param appeared, a param was removed,&lt;br&gt;
a type changed) or &lt;strong&gt;informational&lt;/strong&gt; (a description changed, an&lt;br&gt;
optional param was relaxed). Slack only fires on the former.&lt;/p&gt;

&lt;p&gt;Postgres for history, BullMQ for scheduling, a small REST API to&lt;br&gt;
manage what's being watched.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DIYA73/mcp-schema-watch" rel="noopener noreferrer"&gt;github.com/DIYA73/mcp-schema-watch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  pr-blast-radius — scope creep, proven with a graph, not a vibe
&lt;/h2&gt;

&lt;p&gt;This is the one I'm most attached to. It parses the real AST of every&lt;br&gt;
file in your repo, builds the import graph, and checks whether the&lt;br&gt;
files changed in a PR are actually &lt;em&gt;connected&lt;/em&gt; to each other:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Blast radius (connected-components mode)

  ✓ src/userService.ts
  ✓ src/utils.ts
  ✗ src/paymentService.ts  Not import-connected to the main
                            group of changed files (group size: 1)

3 source file(s) changed, 1 flagged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two files that import each other are obviously part of the same&lt;br&gt;
change. A third file with no import relationship to either one, sitting&lt;br&gt;
in the same PR? That's worth a second look — and unlike a model's&lt;br&gt;
opinion, this verdict comes from the actual dependency graph, so it's&lt;br&gt;
the same answer every time you run it.&lt;/p&gt;

&lt;p&gt;It also excludes high fan-in "hub" files (a shared &lt;code&gt;types.ts&lt;/code&gt;, a&lt;br&gt;
barrel &lt;code&gt;index.ts&lt;/code&gt;) from the connectivity check first — otherwise every&lt;br&gt;
file in a codebase that imports the same central file looks&lt;br&gt;
"connected," and the whole check becomes noise. Runs as a GitHub&lt;br&gt;
Action that comments on the PR and &lt;em&gt;updates&lt;/em&gt; that comment on every&lt;br&gt;
push, instead of leaving a trail of duplicates behind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DIYA73/PR-Blast-Radius-" rel="noopener noreferrer"&gt;github.com/DIYA73/PR-Blast-Radius-&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  swarm-trace-viewer — finding the one agent that actually broke
&lt;/h2&gt;

&lt;p&gt;The newest of the four, and still just the foundation layer. When an&lt;br&gt;
orchestrator fans out into hundreds of subagents, a run failing&lt;br&gt;
doesn't tell you much on its own — was this agent the actual cause,&lt;br&gt;
or just downstream of something that failed three levels up?&lt;/p&gt;

&lt;p&gt;This builds the full agent tree from a flat event list, then walks it&lt;br&gt;
to separate &lt;strong&gt;root-cause failures&lt;/strong&gt; from &lt;strong&gt;cascades&lt;/strong&gt;, and flags&lt;br&gt;
statistical outliers among sibling agents — the one subtask that took&lt;br&gt;
10x longer than its five siblings for no obvious reason. It ships with&lt;br&gt;
a fully deterministic synthetic trace generator, seeded so the same&lt;br&gt;
input always produces the same trace, since there's no public&lt;br&gt;
1,000-agent orchestrator to record real traces from yet.&lt;/p&gt;

&lt;p&gt;Live streaming and the actual tree/timeline UI are next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DIYA73/swarm-trace-viewer" rel="noopener noreferrer"&gt;github.com/DIYA73/swarm-trace-viewer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern
&lt;/h2&gt;

&lt;p&gt;None of these are clever. That's kind of the point — a z-score, an&lt;br&gt;
import graph, and a tree walk will give you the same verdict at 2am as&lt;br&gt;
they will at 2pm, and they'll do it without a bill. As agents write&lt;br&gt;
and orchestrate more of our code, I think there's real room for tools&lt;br&gt;
that check that work the boring way.&lt;/p&gt;

&lt;p&gt;All four repos are open for issues and PRs. If one of these solves a&lt;br&gt;
problem you actually have, I'd genuinely like to know.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
    </item>
    <item>
      <title>I built an MCP server that tracks your Claude Code context budget in real time📎</title>
      <dc:creator>Diya</dc:creator>
      <pubDate>Sun, 05 Jul 2026 23:51:25 +0000</pubDate>
      <link>https://dev.to/diya730/i-built-an-mcp-server-that-tracks-your-claude-code-context-budget-in-real-time-28ai</link>
      <guid>https://dev.to/diya730/i-built-an-mcp-server-that-tracks-your-claude-code-context-budget-in-real-time-28ai</guid>
      <description>&lt;p&gt;Every developer using Claude Code or Cursor has hit this wall: the agent starts looping, responses get worse, and then — context overflow. You had no warning. You had no visibility. You just lost the whole session.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;ContextPulse&lt;/strong&gt; to fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ContextPulse?
&lt;/h2&gt;

&lt;p&gt;ContextPulse is a framework-agnostic MCP server that sits between your AI coding agent and your tools. It intercepts every tool call, counts tokens in real time, tracks your context budget, and fires alerts before you hit the wall.&lt;/p&gt;

&lt;p&gt;It ships in two repos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/DIYA73/contextpulse-mcp" rel="noopener noreferrer"&gt;contextpulse-mcp&lt;/a&gt;&lt;/strong&gt; — the MCP server + NestJS REST API + WebSocket gateway + BullMQ alert queue&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/DIYA73/contextpulse" rel="noopener noreferrer"&gt;contextpulse&lt;/a&gt;&lt;/strong&gt; — the Next.js real-time dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The problem it solves
&lt;/h2&gt;

&lt;p&gt;Current observability tools (Langfuse, LangSmith, Phoenix) are framework-first and show you cost &lt;em&gt;after&lt;/em&gt; the run. They don't tell you &lt;em&gt;during&lt;/em&gt; the run that you're at 87% context and one tool call away from overflow.&lt;/p&gt;

&lt;p&gt;And nobody in open source lets you compare two agent runs side by side to see what changed after a prompt edit.&lt;/p&gt;

&lt;p&gt;ContextPulse does both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Phase 1 — MCP server core&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intercepts tool calls via the MCP protocol&lt;/li&gt;
&lt;li&gt;Counts tokens using &lt;code&gt;tiktoken&lt;/code&gt; (cl100k_base)&lt;/li&gt;
&lt;li&gt;Stores everything in PostgreSQL — sessions, runs, tool calls, budget snapshots, alerts&lt;/li&gt;
&lt;li&gt;Fires warnings at 70% and critical alerts at 90% context usage&lt;/li&gt;
&lt;li&gt;Detects loops: when the same tool is called 3× in a row&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 2 — Real-time dashboard&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NestJS REST API: &lt;code&gt;GET /api/runs&lt;/code&gt;, &lt;code&gt;/api/runs/:id&lt;/code&gt;, &lt;code&gt;/api/runs/:id/tool-calls&lt;/code&gt;, &lt;code&gt;/api/runs/:id/alerts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;WebSocket gateway (Socket.io) pushes live events to the dashboard&lt;/li&gt;
&lt;li&gt;Next.js 15 dashboard with live budget bar, tool call waterfall, alert feed, event log&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 3 — BullMQ alert queue + loop graph&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BullMQ async alert worker: processes budget and loop alerts without blocking the MCP server&lt;/li&gt;
&lt;li&gt;Optional webhook delivery via &lt;code&gt;ALERT_WEBHOOK_URL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Loop detection frequency chart — highlights tools called above the loop threshold in red&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Phase 4 — Run diff engine&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /api/diff?runA=&amp;lt;id&amp;gt;&amp;amp;runB=&amp;lt;id&amp;gt;&lt;/code&gt; compares two runs&lt;/li&gt;
&lt;li&gt;Returns token delta, tool call delta, budget winner, new loops introduced, loops resolved&lt;/li&gt;
&lt;li&gt;Full diff UI in the dashboard: side-by-side stat cards, delta table, tool-by-tool breakdown&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeScript · NestJS · Next.js 15 · PostgreSQL · Redis
BullMQ · WebSocket (Socket.io) · MCP SDK · tiktoken · Zod · Tailwind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Start PostgreSQL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;createdb contextpulse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Clone and run the MCP server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/DIYA73/contextpulse-mcp
&lt;span class="nb"&gt;cd &lt;/span&gt;contextpulse-mcp
npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env
npm run dev:api   &lt;span class="c"&gt;# NestJS API on port 3000&lt;/span&gt;
npm run dev:mcp   &lt;span class="c"&gt;# MCP server on stdio&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Add to Claude Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;~/.claude/settings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"contextpulse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"tsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/contextpulse-mcp/src/proxy/server.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgresql://localhost:5432/contextpulse"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Run the dashboard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/DIYA73/contextpulse
&lt;span class="nb"&gt;cd &lt;/span&gt;contextpulse
npm &lt;span class="nb"&gt;install
echo&lt;/span&gt; &lt;span class="s2"&gt;"NEXT_PUBLIC_API_URL=http://localhost:3000"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .env.local
npm run dev   &lt;span class="c"&gt;# Dashboard on port 3001&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:3001&lt;/code&gt; — you'll see the live dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it in your agent
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp_start_session   → get sessionId
cp_start_run       → get runId
cp_track_tool_call → call after every tool call
cp_get_budget      → check live budget anytime
cp_get_run_summary → full run summary with timeline
cp_end_run         → clean up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response from &lt;code&gt;cp_track_tool_call&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"toolCallId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a1b2c3..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inputTokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;142&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputTokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalTokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;229&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14820&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"percentUsed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.41&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"budgetStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alert"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When budget hits 90%:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"budgetStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"critical"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alert"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"critical"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The run diff engine
&lt;/h2&gt;

&lt;p&gt;This is the feature I haven't seen anywhere else in open source.&lt;/p&gt;

&lt;p&gt;After changing your prompt or agent config, you can compare two runs side by side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/diff?runA=&amp;lt;uuid&amp;gt;&amp;amp;runB=&amp;lt;uuid&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response tells you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which run used fewer tokens (and by how much %)&lt;/li&gt;
&lt;li&gt;Which tools appeared only in one run&lt;/li&gt;
&lt;li&gt;New loops introduced in Run B&lt;/li&gt;
&lt;li&gt;Loops that were resolved from Run A&lt;/li&gt;
&lt;li&gt;Per-tool token delta&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dashboard shows it as a full diff UI with a summary sentence like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Run B used 12,400 fewer tokens (23% more efficient). Run B resolved 1 loop: read_file."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I learned building this
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Context engineering is the real bottleneck.&lt;/strong&gt; Not model capability. The GitHub MCP server alone costs 42,000–55,000 tokens in tool definitions before you type a single prompt. Tracking this in real time changed how I think about agent design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BullMQ graceful fallback matters.&lt;/strong&gt; The alert queue degrades to console logging when Redis isn't available. This made the MCP server safe to use without Redis — alerts still fire, they just aren't queued.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TypeScript strict mode with exactOptionalPropertyTypes catches real bugs.&lt;/strong&gt; The BullMQ + ioredis version conflict (two different Redis class definitions) only showed up clearly because of strict typing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MCP server + API: &lt;a href="https://github.com/DIYA73/contextpulse-mcp" rel="noopener noreferrer"&gt;github.com/DIYA73/contextpulse-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Dashboard: &lt;a href="https://github.com/DIYA73/contextpulse" rel="noopener noreferrer"&gt;github.com/DIYA73/contextpulse&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this is useful to you, a ⭐ on GitHub goes a long way. And if you build something on top of it, I'd love to see it.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>I opened my first PR to LiveKit's agents repo — here's the bug I found</title>
      <dc:creator>Diya</dc:creator>
      <pubDate>Sun, 21 Jun 2026 18:22:07 +0000</pubDate>
      <link>https://dev.to/diya730/i-opened-my-first-pr-to-livekits-agents-repo-heres-the-bug-i-found-5abm</link>
      <guid>https://dev.to/diya730/i-opened-my-first-pr-to-livekits-agents-repo-heres-the-bug-i-found-5abm</guid>
      <description>&lt;p&gt;I've been growing my open source portfolio one contribution at a time, and this week I landed on something genuinely interesting in &lt;a href="https://github.com/livekit/agents" rel="noopener noreferrer"&gt;&lt;code&gt;livekit/agents&lt;/code&gt;&lt;/a&gt; (11k+ stars, the framework behind a ton of real-time voice AI agents).&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug
&lt;/h2&gt;

&lt;p&gt;If you're building a voice agent on a realtime model (OpenAI Realtime, xAI, Gemini Live), the model streams your transcription back in chunks. A single utterance can fire &lt;strong&gt;many&lt;/strong&gt; &lt;code&gt;user_input_transcribed&lt;/code&gt; events before it's final — token by token for OpenAI/xAI, or as one big interim blob for Gemini.&lt;/p&gt;

&lt;p&gt;If you want to react exactly once per utterance (say, show a "user is typing" indicator on your frontend via RPC), you need a stable key to correlate all those interim events together.&lt;/p&gt;

&lt;p&gt;That key already existed internally — &lt;code&gt;InputTranscriptionCompleted&lt;/code&gt; carries an &lt;code&gt;item_id&lt;/code&gt;. But when the framework re-emitted it upward as the public &lt;code&gt;UserInputTranscribedEvent&lt;/code&gt;, the &lt;code&gt;item_id&lt;/code&gt; was silently dropped — leaving consumers with no reliable way to dedupe across providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Small once you see it: add the field, forward it.&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;class&lt;/span&gt; &lt;span class="nc"&gt;UserInputTranscribedEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;is_final&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;    &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_on_input_audio_transcription_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InputTranscriptionCompleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_user_input_transcribed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;UserInputTranscribedEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_final&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_final&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two files, about 10 lines of real change. The actual work was tracing the event from the realtime model layer, through &lt;code&gt;AgentActivity&lt;/code&gt;, up to &lt;code&gt;AgentSession&lt;/code&gt;, to find exactly where the field got swallowed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;I didn't need to understand all of &lt;code&gt;livekit-agents&lt;/code&gt; to land this — just one event's lifecycle, end to end. Small, well-scoped issues are the most achievable way into a big codebase, especially when someone's already mapped the territory in the issue itself.&lt;/p&gt;

&lt;p&gt;PR is up, CI green, waiting on review: &lt;a href="https://github.com/livekit/agents/pull/6172" rel="noopener noreferrer"&gt;github.com/livekit/agents/pull/6172&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>8 Claude Code skills for NestJS — drop in and use immediately</title>
      <dc:creator>Diya</dc:creator>
      <pubDate>Sat, 13 Jun 2026 21:06:26 +0000</pubDate>
      <link>https://dev.to/diya730/8-claude-code-skills-for-nestjs-drop-in-and-use-immediately-1o4n</link>
      <guid>https://dev.to/diya730/8-claude-code-skills-for-nestjs-drop-in-and-use-immediately-1o4n</guid>
      <description>&lt;p&gt;Working with NestJS daily, I kept writing the same patterns.&lt;/p&gt;

&lt;p&gt;So I packaged them as Claude Code skills — drop into ~/.claude/skills/ &lt;br&gt;
and Claude Code picks them up automatically.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's included
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;nestjs-module&lt;/strong&gt; — scaffold any module, service, controller, DTOs correctly in one shot&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;typeorm-patterns&lt;/strong&gt; — entities, relations, migrations, QueryBuilder patterns&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;bullmq-queue&lt;/strong&gt; — job queues, processors, retry logic, cron jobs&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;websocket-gateway&lt;/strong&gt; — Socket.io gateways, rooms, Redis pub/sub streaming&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nestjs-auth&lt;/strong&gt; — JWT auth, guards, role-based access, CurrentUser decorator&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;redis-caching&lt;/strong&gt; — cache-aside pattern, TTL strategy, invalidation on write&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docker-nestjs&lt;/strong&gt; — production Dockerfile, docker-compose with health checks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nestjs-testing&lt;/strong&gt; — unit tests, e2e tests, mocking repos and queues&lt;/p&gt;
&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/DIYA73/nestjs-skills ~/.claude/skills/nestjs-skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then just describe what you need in Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scaffold a users module with TypeORM
add a BullMQ email queue with retry logic  
protect this route with JWT auth
write unit tests for UsersService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/DIYA73/nestjs-skills" rel="noopener noreferrer"&gt;https://github.com/DIYA73/nestjs-skills&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built these while working on mcp-hub — a self-hosted MCP server &lt;br&gt;
registry also in NestJS. The skills came out of that work.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>claudecode</category>
      <category>ai</category>
    </item>
    <item>
      <title>I built a self-hosted MCP server registry and proxy in TypeScript</title>
      <dc:creator>Diya</dc:creator>
      <pubDate>Sat, 13 Jun 2026 16:01:36 +0000</pubDate>
      <link>https://dev.to/diya730/i-built-a-self-hosted-mcp-server-registry-and-proxy-in-typescript-12b</link>
      <guid>https://dev.to/diya730/i-built-a-self-hosted-mcp-server-registry-and-proxy-in-typescript-12b</guid>
      <description>&lt;p&gt;The official MCP registry is written in Go and cloud-hosted.&lt;br&gt;
I wanted something I could self-host, written in TypeScript, &lt;br&gt;
that my team could run inside our own infra.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;mcp-hub&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Register&lt;/strong&gt; any MCP server (SSE, HTTP, stdio transports)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy&lt;/strong&gt; all tool calls through one endpoint with auth forwarding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stream&lt;/strong&gt; every tool call live via WebSocket (Socket.io)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor&lt;/strong&gt; server health async via BullMQ jobs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;NestJS — API framework&lt;/li&gt;
&lt;li&gt;PostgreSQL — server registry + tool call logs
&lt;/li&gt;
&lt;li&gt;Redis — WebSocket pub/sub + BullMQ transport&lt;/li&gt;
&lt;li&gt;BullMQ — async health check queue&lt;/li&gt;
&lt;li&gt;Socket.io — real-time log streaming&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Register a server once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3000/api/v1/servers &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "github-mcp",
    "url": "http://my-mcp-server:8080",
    "transport": "http"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then proxy any tool call through mcp-hub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3000/api/v1/proxy/&lt;span class="o"&gt;{&lt;/span&gt;serverId&lt;span class="o"&gt;}&lt;/span&gt;/call &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{ "tool": "create_issue", "input": { "title": "Bug" } }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every call is logged to PostgreSQL and streamed live over WebSocket.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run it in one command
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/DIYA73/mcp-hub
&lt;span class="nb"&gt;cd &lt;/span&gt;mcp-hub
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;API at &lt;code&gt;http://localhost:3000/api/v1&lt;/code&gt;&lt;br&gt;
WebSocket at &lt;code&gt;ws://localhost:3000/logs&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;I'm running multiple MCP servers locally and needed a central &lt;br&gt;
place to register them, forward calls, and see what's happening &lt;br&gt;
in real time. Nothing TypeScript-native existed.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/DIYA73/mcp-hub" rel="noopener noreferrer"&gt;https://github.com/DIYA73/mcp-hub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback welcome — especially if you're running MCP servers in prod.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>nestjs</category>
      <category>ai</category>
      <category>mcp</category>
    </item>
    <item>
      <title>I built a self-hosted "Git for AI prompts" — version control, test runner &amp; A/B testing (open source)</title>
      <dc:creator>Diya</dc:creator>
      <pubDate>Thu, 11 Jun 2026 23:49:31 +0000</pubDate>
      <link>https://dev.to/diya730/i-built-a-self-hosted-git-for-ai-prompts-version-control-test-runner-ab-testing-open-1i2b</link>
      <guid>https://dev.to/diya730/i-built-a-self-hosted-git-for-ai-prompts-version-control-test-runner-ab-testing-open-1i2b</guid>
      <description>&lt;p&gt;If you're building anything with LLMs, you've probably hit this problem: your prompts are scattered across code files, Notion docs, and Slack threads. There's no version history. You can't easily test a change. And you have no idea what's actually running in production.&lt;br&gt;
I built Prompt Vault to fix this — a self-hosted web app that treats your prompts like code.&lt;br&gt;
What it does&lt;br&gt;
Version control — every edit creates a new version. You can activate any version at any time, just like git checkout.&lt;br&gt;
Auto-detected variables — use {{variable}} syntax in your prompts. The UI automatically detects them and lets you fill values before testing.&lt;br&gt;
Test runner — run any prompt version directly against OpenAI from the UI. See the response, latency, and token usage instantly.&lt;br&gt;
A/B testing — create a test between two prompt versions, run both in parallel, and compare outputs side by side.&lt;br&gt;
Multi-user — JWT auth, each user's data is fully isolated.&lt;br&gt;
Self-hosted — Docker Compose for one-command setup. Your prompts stay on your infrastructure.&lt;br&gt;
Tech stack&lt;/p&gt;

&lt;p&gt;Backend: NestJS + TypeScript&lt;br&gt;
Database: PostgreSQL + Prisma&lt;br&gt;
Frontend: Next.js 15 + Tailwind CSS&lt;br&gt;
Auth: JWT + bcrypt&lt;br&gt;
AI: OpenAI API&lt;/p&gt;

&lt;p&gt;Quick start&lt;br&gt;
bashgit clone &lt;a href="https://github.com/DIYA73/prompt-vault" rel="noopener noreferrer"&gt;https://github.com/DIYA73/prompt-vault&lt;/a&gt;&lt;br&gt;
cd prompt-vault/backend&lt;br&gt;
cp .env.example .env&lt;/p&gt;

&lt;h1&gt;
  
  
  Add your DATABASE_URL and OPENAI_API_KEY
&lt;/h1&gt;

&lt;p&gt;npm install&lt;br&gt;
npx prisma generate&lt;br&gt;
npx prisma migrate dev --name init&lt;br&gt;
npm run start:dev&lt;/p&gt;

&lt;h1&gt;
  
  
  New terminal
&lt;/h1&gt;

&lt;p&gt;cd ../frontend&lt;br&gt;
npm install&lt;br&gt;
npm run dev&lt;br&gt;
Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; — register, create a project, add your first prompt.&lt;br&gt;
Why I built it&lt;br&gt;
Every team I've seen building LLM features manages prompts the same broken way — hardcoded strings in source code, no history, no way to safely iterate. Prompt Vault is the tool I wished existed.&lt;br&gt;
GitHub&lt;br&gt;
⭐ &lt;a href="https://github.com/DIYA73/prompt-vault" rel="noopener noreferrer"&gt;https://github.com/DIYA73/prompt-vault&lt;/a&gt;&lt;br&gt;
Would love feedback — especially from anyone managing prompts at scale.&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fkg451qfi3dqxa4s8imc2.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.amazonaws.com%2Fuploads%2Farticles%2Fkg451qfi3dqxa4s8imc2.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>nextjs</category>
      <category>nestjs</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
