<?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: Prince Jain</title>
    <description>The latest articles on DEV Community by Prince Jain (@princejain756).</description>
    <link>https://dev.to/princejain756</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%2F4179047%2Fb4603a50-4b5e-45dd-a2b8-705262e24dd1.jpg</url>
      <title>DEV Community: Prince Jain</title>
      <link>https://dev.to/princejain756</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/princejain756"/>
    <language>en</language>
    <item>
      <title>Auditing 153 Claude Code &amp; Codex transcripts for #107757 User-Agent and URL email leaks (and filtering 259 noreply@anthropic.com hits)</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Fri, 06 Nov 2026 05:33:48 +0000</pubDate>
      <link>https://dev.to/princejain756/auditing-153-claude-code-codex-transcripts-for-107757-user-agent-and-url-email-leaks-and-chf</link>
      <guid>https://dev.to/princejain756/auditing-153-claude-code-codex-transcripts-for-107757-user-agent-and-url-email-leaks-and-chf</guid>
      <description>&lt;p&gt;When anthropics/claude-code#107757 and #55743 hit the front page today (where Claude Code injects &lt;code&gt;oauthAccount.emailAddress&lt;/code&gt; from &lt;code&gt;~/.claude.json&lt;/code&gt; into context and models copy that email into outbound &lt;code&gt;User-Agent&lt;/code&gt; headers or query strings), I wrote a script to audit what my own coding agents had sent over the network across 153 local Claude Code and Codex CLI transcripts (&lt;code&gt;1,928&lt;/code&gt; deduplicated tool calls).&lt;/p&gt;

&lt;h3&gt;
  
  
  Two false-positive traps that bit my first script
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;noreply@anthropic.com&lt;/code&gt; trailer inflation (&lt;code&gt;259&lt;/code&gt; synthetic vs &lt;code&gt;77&lt;/code&gt; real email hits)&lt;/strong&gt;: My first pass ran a standard email regex across &lt;code&gt;~/.claude/projects/**/*.jsonl&lt;/code&gt; and &lt;code&gt;~/.codex/sessions/**/*.jsonl&lt;/code&gt; and returned &lt;code&gt;336&lt;/code&gt; email occurrences. I initially thought my sessions had leaked hundreds of personal and client addresses. Grouping by domain showed &lt;code&gt;259&lt;/code&gt; of those &lt;code&gt;336&lt;/code&gt; matches (&lt;code&gt;77.1%&lt;/code&gt;) were &lt;code&gt;noreply@anthropic.com&lt;/code&gt; and &lt;code&gt;example.com&lt;/code&gt; strings injected by Claude Code's own &lt;code&gt;Co-Authored-By&lt;/code&gt; commit trailer prompt. Filtering out synthetic trailer domains left &lt;code&gt;77&lt;/code&gt; real email occurrences across &lt;code&gt;8&lt;/code&gt; genuine domains (&lt;code&gt;gmail.com&lt;/code&gt; 53, &lt;code&gt;mcxindia.com&lt;/code&gt; 11, &lt;code&gt;prince.sh&lt;/code&gt; 4, &lt;code&gt;adelev8.com&lt;/code&gt; 4, &lt;code&gt;nvidia.com&lt;/code&gt; 2, &lt;code&gt;aqr.com&lt;/code&gt; 1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loopback dev-server checks vs external egress (&lt;code&gt;19&lt;/code&gt; loopback vs &lt;code&gt;11&lt;/code&gt; external)&lt;/strong&gt;: Extracting HTTP URLs from tool call inputs matched &lt;code&gt;30&lt;/code&gt; requests, &lt;code&gt;19&lt;/code&gt; of which (&lt;code&gt;63.3%&lt;/code&gt;) were local health checks against &lt;code&gt;127.0.0.1&lt;/code&gt; and &lt;code&gt;localhost&lt;/code&gt;. Separating loopback traffic (&lt;code&gt;EGL014&lt;/code&gt;) isolated the &lt;code&gt;11&lt;/code&gt; real external requests (&lt;code&gt;9&lt;/code&gt; to &lt;code&gt;q.prince.sh&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt; to &lt;code&gt;gemini.google.com&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What actually leaked across 153 sessions
&lt;/h3&gt;

&lt;p&gt;Once synthetic trailers and loopback requests were separated, the audit caught:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;2&lt;/code&gt; outbound URL query email leaks (&lt;code&gt;EGL008&lt;/code&gt;)&lt;/strong&gt;: Two tool calls passed &lt;code&gt;?authuser=&amp;lt;REDACTED_EMAIL&amp;gt;@gmail.com&lt;/code&gt; directly in outbound URLs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;1&lt;/code&gt; outbound file POST upload (&lt;code&gt;EGL010&lt;/code&gt;)&lt;/strong&gt;: A &lt;code&gt;Bash&lt;/code&gt; &lt;code&gt;curl&lt;/code&gt; command uploaded a local payload file via HTTP POST to an external endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;3&lt;/code&gt; remote SSH MCP tunnels (&lt;code&gt;EGL003&lt;/code&gt;)&lt;/strong&gt;: Three MCP servers in &lt;code&gt;~/.claude.json&lt;/code&gt; were configured to pipe tool arguments over &lt;code&gt;ssh root@&amp;lt;REDACTED_IP&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active hardware and Statsig telemetry IDs (&lt;code&gt;EGL002&lt;/code&gt;)&lt;/strong&gt;: &lt;code&gt;userID&lt;/code&gt;, &lt;code&gt;machineID&lt;/code&gt;, &lt;code&gt;cachedStatsigGates&lt;/code&gt;, and &lt;code&gt;cachedGrowthBookFeatures&lt;/code&gt; were active in &lt;code&gt;~/.claude.json&lt;/code&gt; because neither &lt;code&gt;DISABLE_TELEMETRY=1&lt;/code&gt; nor &lt;code&gt;CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1&lt;/code&gt; was set in &lt;code&gt;~/.claude/settings.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;153/153&lt;/code&gt; sessions (&lt;code&gt;100%&lt;/code&gt;)&lt;/strong&gt; injected my local macOS username path (&lt;code&gt;/Users/&amp;lt;USER&amp;gt;&lt;/code&gt;) into prompt context (&lt;code&gt;EGL005&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Running &lt;code&gt;egressleak&lt;/code&gt; and blocking leaks in &lt;code&gt;PreToolUse&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I published the zero-dependency auditor as &lt;code&gt;egressleak&lt;/code&gt; (&lt;code&gt;npx egressleak&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx egressleak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To block outbound email and token leaks deterministically without waiting for upstream CLI patches or trusting prompt instructions, run the &lt;code&gt;emit-hook&lt;/code&gt; generator mode in &lt;code&gt;npx egressleak&lt;/code&gt;. It outputs a zero-dependency Node.js &lt;code&gt;PreToolUse&lt;/code&gt; guardrail script (&lt;code&gt;~/.claude/hooks/egress-guard-hook.mjs&lt;/code&gt;) that inspects &lt;code&gt;Bash&lt;/code&gt;, &lt;code&gt;WebFetch&lt;/code&gt;, and &lt;code&gt;WebSearch&lt;/code&gt; tool inputs and exits with code &lt;code&gt;2&lt;/code&gt; if an outbound request includes a real email address in &lt;code&gt;User-Agent&lt;/code&gt;, an &lt;code&gt;?authuser=&lt;/code&gt; / &lt;code&gt;?email=&lt;/code&gt; query parameter, or a secret API token (&lt;code&gt;sk-&lt;/code&gt;, &lt;code&gt;ghp_&lt;/code&gt;, &lt;code&gt;AIza&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;egressleak&lt;/code&gt; inspects &lt;code&gt;.jsonl&lt;/code&gt; transcripts and static config files on disk. If an agent executes a Python or Node script that constructs a destination URL dynamically at runtime without passing the URL or header in the tool call arguments, transcript replay cannot see that packet.&lt;/li&gt;
&lt;li&gt;The generated &lt;code&gt;PreToolUse&lt;/code&gt; hook inspects tool call arguments (&lt;code&gt;Bash&lt;/code&gt;, &lt;code&gt;WebFetch&lt;/code&gt;, &lt;code&gt;WebSearch&lt;/code&gt;) before execution, not child processes spawned inside an already-approved script file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/princejain756/egressleak" rel="noopener noreferrer"&gt;https://github.com/princejain756/egressleak&lt;/a&gt;&lt;br&gt;
npm: &lt;a href="https://www.npmjs.com/package/egressleak" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/egressleak&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>claude</category>
      <category>privacy</category>
      <category>security</category>
    </item>
    <item>
      <title>Replaying 153 Claude Code &amp; Codex Sessions for Production Blast Radius (and Catching 247 Root SSH Calls)</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Fri, 06 Nov 2026 02:27:17 +0000</pubDate>
      <link>https://dev.to/princejain756/replaying-153-claude-code-codex-sessions-for-production-blast-radius-and-catching-247-root-ssh-32c9</link>
      <guid>https://dev.to/princejain756/replaying-153-claude-code-codex-sessions-for-production-blast-radius-and-catching-247-root-ssh-32c9</guid>
      <description>&lt;p&gt;An ops engineer on &lt;code&gt;r/devops&lt;/code&gt; asked today how to explain to teammates why giving an LLM agent root access to production is dangerous when &lt;em&gt;"they built their own wrapper around it and log what it does."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Logging what an agent executes is post-mortem detection, not containment. When an agent holds an unrestricted &lt;code&gt;ssh root@host&lt;/code&gt; shell just to run &lt;code&gt;journalctl&lt;/code&gt; or &lt;code&gt;systemctl is-active&lt;/code&gt;, there is zero technical boundary between a read-only check and &lt;code&gt;systemctl stop&lt;/code&gt;, &lt;code&gt;rm -rf&lt;/code&gt;, or &lt;code&gt;DROP TABLE&lt;/code&gt; over that same socket.&lt;/p&gt;

&lt;p&gt;To see what my own local coding agents had actually executed over the past month, I built &lt;strong&gt;agentblast&lt;/strong&gt; (&lt;code&gt;npx agentblast&lt;/code&gt;, &lt;a href="https://github.com/princejain756/agentblast" rel="noopener noreferrer"&gt;github.com/princejain756/agentblast&lt;/a&gt;) and ran it across all &lt;code&gt;153&lt;/code&gt; local sessions on my workstation (&lt;code&gt;126&lt;/code&gt; Claude Code sessions in &lt;code&gt;~/.claude/projects&lt;/code&gt; and &lt;code&gt;27&lt;/code&gt; Codex CLI sessions in &lt;code&gt;~/.codex/sessions&lt;/code&gt;, &lt;code&gt;1,122&lt;/code&gt; deduplicated shell commands).&lt;/p&gt;

&lt;h2&gt;
  
  
  What 153 Real Sessions Revealed
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AGENTBLAST v0.1.0 · Agent Production Blast-Radius &amp;amp; Permission Auditor
══════════════════════════════════════════════════════════════════════════════
Target            : ~/.claude (126 sessions) + ~/.codex (27 sessions)
Shell Replay      : 1122 deduplicated commands (1124 raw JSONL rows)
Safety Score      : 0/100 (Grade F) · Blast-Radius Index: 100/100
Root/Remote SSH   : 247 calls (241 read-only probes, 6 remote mutations)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;247 &lt;code&gt;ssh root@&amp;lt;REDACTED_IP&amp;gt;&lt;/code&gt; calls (&lt;code&gt;ABL007&lt;/code&gt;):&lt;/strong&gt; &lt;code&gt;241&lt;/code&gt; of those &lt;code&gt;247&lt;/code&gt; calls (97.6%) were strictly read-only inspection commands (&lt;code&gt;ls -la&lt;/code&gt;, &lt;code&gt;tail -n 40&lt;/code&gt;, &lt;code&gt;systemctl is-active&lt;/code&gt;), while &lt;code&gt;6&lt;/code&gt; performed remote state mutations (&lt;code&gt;systemctl restart&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt; webhooks). Because the agent used &lt;code&gt;root@&lt;/code&gt; instead of a restricted read-only SSH principal, every single one of those &lt;code&gt;241&lt;/code&gt; log checks carried full root blast radius.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2 plaintext API tokens in &lt;code&gt;~/.claude/settings.json&lt;/code&gt; (&lt;code&gt;ABL001&lt;/code&gt;) + 0 &lt;code&gt;permissions.deny&lt;/code&gt; rules (&lt;code&gt;ABL003&lt;/code&gt;):&lt;/strong&gt; Both &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; and &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; were stored in plaintext inside the &lt;code&gt;env&lt;/code&gt; block of &lt;code&gt;settings.json&lt;/code&gt;, and &lt;code&gt;permissions.deny&lt;/code&gt; was completely empty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;41 auto-trusted project roots in &lt;code&gt;~/.codex/config.toml&lt;/code&gt; (&lt;code&gt;ABL006&lt;/code&gt;) + file credential store (&lt;code&gt;ABL005&lt;/code&gt;):&lt;/strong&gt; Over weeks of opening folders, &lt;code&gt;~/.codex/config.toml&lt;/code&gt; had accumulated &lt;code&gt;41&lt;/code&gt; &lt;code&gt;[projects."..."].trust_level = "trusted"&lt;/code&gt; entries across external drives alongside &lt;code&gt;cli_auth_credentials_store = "file"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;25 shell commands touching &lt;code&gt;.env&lt;/code&gt; or service credentials (&lt;code&gt;ABL010&lt;/code&gt;), 12 daemon commands (&lt;code&gt;ABL012&lt;/code&gt;), and 10 agent-config reads (&lt;code&gt;ABL013&lt;/code&gt;).&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Two Mistakes in My First Pass
&lt;/h2&gt;

&lt;p&gt;My first prototype had two bugs that showed up immediately on real data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;False-positive panic on &lt;code&gt;/tmp&lt;/code&gt; &lt;code&gt;rm -rf&lt;/code&gt;:&lt;/strong&gt; My initial regex flagged every &lt;code&gt;rm -rf&lt;/code&gt; as &lt;code&gt;CRITICAL&lt;/code&gt;. Across &lt;code&gt;1,122&lt;/code&gt; commands, my agents had run &lt;code&gt;rm -rf&lt;/code&gt; twice: &lt;code&gt;rm -rf /tmp/quantiti-head&lt;/code&gt; and &lt;code&gt;cd /tmp &amp;amp;&amp;amp; rm -rf obskill&lt;/code&gt;. Flagging ephemeral &lt;code&gt;/tmp&lt;/code&gt; scratch cleanup as a critical incident trains developers to ignore the tool. &lt;code&gt;agentblast&lt;/code&gt; now inspects target paths and preceding &lt;code&gt;cd /tmp&lt;/code&gt; statements, separating non-&lt;code&gt;/tmp&lt;/code&gt; recursive deletions (&lt;code&gt;ABL008&lt;/code&gt;, &lt;code&gt;CRITICAL&lt;/code&gt;) from &lt;code&gt;/tmp&lt;/code&gt; / &lt;code&gt;$TMPDIR&lt;/code&gt; scratch cleanups (&lt;code&gt;ABL014&lt;/code&gt;, &lt;code&gt;LOW&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaking production IPs and token prefixes in audit output:&lt;/strong&gt; Printing raw evidence lines from &lt;code&gt;~/.claude/settings.json&lt;/code&gt; and &lt;code&gt;~/.claude/projects/**/*.jsonl&lt;/code&gt; exposed real server IPv4 addresses and API key prefixes in terminal screenshots. &lt;code&gt;agentblast&lt;/code&gt; now runs &lt;code&gt;redactSensitive()&lt;/code&gt; by default, masking public IPv4s as &lt;code&gt;&amp;lt;REDACTED_IP&amp;gt;&lt;/code&gt;, API tokens as &lt;code&gt;sk-&amp;lt;REDACTED&amp;gt;&lt;/code&gt;, and Base64 hook payloads as &lt;code&gt;&amp;lt;REDACTED_B64&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Audit your local ~/.claude and ~/.codex configs + session transcripts&lt;/span&gt;
npx agentblast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/princejain756/agentblast" rel="noopener noreferrer"&gt;https://github.com/princejain756/agentblast&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>devops</category>
      <category>llm</category>
      <category>security</category>
    </item>
    <item>
      <title>Auditing 687 React &amp; Tailwind Files for "Vibecoded" UI Tells (and Catching Two False-Positive Traps)</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Thu, 05 Nov 2026 23:35:06 +0000</pubDate>
      <link>https://dev.to/princejain756/auditing-687-react-tailwind-files-for-vibecoded-ui-tells-and-catching-two-false-positive-traps-4jj7</link>
      <guid>https://dev.to/princejain756/auditing-687-react-tailwind-files-for-vibecoded-ui-tells-and-catching-two-false-positive-traps-4jj7</guid>
      <description>&lt;p&gt;When I ran the first version of my static UI linter against &lt;code&gt;OpenCode-App&lt;/code&gt; (536 &lt;code&gt;.tsx&lt;/code&gt; files on my machine), two things broke immediately:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Code blocks and syntax themes triggered false positives.&lt;/strong&gt; Scanning raw file strings flagged &lt;code&gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&lt;/code&gt; documentation blocks for sample &lt;code&gt;href="#"&lt;/code&gt; tags and terminal ANSI color maps for &lt;code&gt;indigo&lt;/code&gt; tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global weight subtraction punished large repos.&lt;/strong&gt; Subtracting raw rule weights without normalizing for file count gave a 536-file desktop app a &lt;code&gt;68/100 (Grade C)&lt;/code&gt; when 99.1% of its files had zero findings (only 2 dialog components used &lt;code&gt;indigo&lt;/code&gt; utilities and 3 routes had an em-dash).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After masking out comments, &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; blocks while preserving exact &lt;code&gt;\n&lt;/code&gt; line numbers, and normalizing cosmetic penalties by &lt;code&gt;sqrt(4 / filesScanned)&lt;/code&gt;, I published &lt;a href="https://github.com/princejain756/uislop" rel="noopener noreferrer"&gt;uislop&lt;/a&gt; (&lt;code&gt;npx uislop&lt;/code&gt;) to catch 16 deterministic "vibecoded UI" tells across React, Next.js, Vue, Svelte, Tailwind, and HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx uislop ./src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real benchmark across 687 UI files
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Target            : W.prince/Princeportfolio (129 UI files) vs Vibecoded SaaS Landing
Files scanned     : 129 UI files · 47 findings across 3/6 categories
Human-Craft Score : 65/100 (Grade C) · Vibecode Index: 35/100
Palette Entropy   : 50/297 chromatic tokens in indigo/violet/purple (16.8%)

REAL CORPUS BENCHMARK (687 UI files across 4 repositories)
  rajesh-portfolio (21 UI files)          100/100 (Grade A) ·  0 findings ·  0.0% indigo
  OpenCode-App (536 UI files)              97/100 (Grade A) ·  6 findings · 13.0% indigo
  W.prince/Princeportfolio (129 UI files)  65/100 (Grade C) · 47 findings · 16.8% indigo
  vibecoded-landing.tsx (1 UI file)         0/100 (Grade F) · 24 findings · 95.2% indigo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What the 16 rules catch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Palette &amp;amp; Gradient Defaulting (&lt;code&gt;UIS001&lt;/code&gt;-&lt;code&gt;UIS004&lt;/code&gt;):&lt;/strong&gt; &lt;code&gt;bg-clip-text text-transparent bg-gradient-to-*&lt;/code&gt; headings, &lt;code&gt;from-indigo-500 via-purple-500 to-pink-500&lt;/code&gt; gradients, files where &lt;code&gt;indigo&lt;/code&gt;/&lt;code&gt;violet&lt;/code&gt;/&lt;code&gt;purple&lt;/code&gt; exceed 35% of all chromatic Tailwind utilities, and &lt;code&gt;blur-3xl rounded-full opacity-20&lt;/code&gt; background orbs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Icon &amp;amp; Eyebrow Clichés (&lt;code&gt;UIS005&lt;/code&gt;-&lt;code&gt;UIS007&lt;/code&gt;):&lt;/strong&gt; Importing 3+ of &lt;code&gt;Sparkles&lt;/code&gt;, &lt;code&gt;Zap&lt;/code&gt;, &lt;code&gt;Rocket&lt;/code&gt;, &lt;code&gt;Shield&lt;/code&gt;, &lt;code&gt;Brain&lt;/code&gt;, &lt;code&gt;Wand2&lt;/code&gt; from &lt;code&gt;lucide-react&lt;/code&gt;, &lt;code&gt;&amp;lt;Sparkles&amp;gt;&lt;/code&gt; + &lt;code&gt;animate-ping&lt;/code&gt; hero pills above &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, and repeated &lt;code&gt;bg-indigo-500/10 rounded-xl p-3&lt;/code&gt; squircle icon boxes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layout Monotony (&lt;code&gt;UIS008&lt;/code&gt;-&lt;code&gt;UIS009&lt;/code&gt;):&lt;/strong&gt; Stacked &lt;code&gt;grid-cols-1 md:grid-cols-3&lt;/code&gt; sections and &lt;code&gt;backdrop-blur&lt;/code&gt; + &lt;code&gt;hover:-translate-y-1&lt;/code&gt; glass cards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Copywriting (&lt;code&gt;UIS010&lt;/code&gt;-&lt;code&gt;UIS011&lt;/code&gt;):&lt;/strong&gt; &lt;code&gt;"Supercharge your"&lt;/code&gt;, &lt;code&gt;"Unleash the power of"&lt;/code&gt;, &lt;code&gt;"Built for modern teams"&lt;/code&gt;, &lt;code&gt;"Next-Generation"&lt;/code&gt;, and em-dash splices in UI text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fake Social Proof (&lt;code&gt;UIS012&lt;/code&gt;-&lt;code&gt;UIS014&lt;/code&gt;):&lt;/strong&gt; &lt;code&gt;"Sarah Chen"&lt;/code&gt;, &lt;code&gt;"Alex Rivera"&lt;/code&gt;, &lt;code&gt;"Acme Corp"&lt;/code&gt;, &lt;code&gt;"TechFlow"&lt;/code&gt;, &lt;code&gt;pravatar.cc&lt;/code&gt;, and LLM-memorized Unsplash portrait IDs (&lt;code&gt;photo-1534528741775-53994a69daeb&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hollow Wiring (&lt;code&gt;UIS015&lt;/code&gt;-&lt;code&gt;UIS016&lt;/code&gt;):&lt;/strong&gt; Dead &lt;code&gt;&amp;lt;a href="#"&amp;gt;&lt;/code&gt; links and &lt;code&gt;onClick={() =&amp;gt; {}}&lt;/code&gt; / &lt;code&gt;console.log&lt;/code&gt; handlers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code and CLI are MIT-licensed at &lt;a href="https://github.com/princejain756/uislop" rel="noopener noreferrer"&gt;https://github.com/princejain756/uislop&lt;/a&gt; (and on npm at &lt;a href="https://www.npmjs.com/package/uislop" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/uislop&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>react</category>
      <category>softwaredevelopment</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Replaying 147 Claude Code &amp; Codex Sessions to Tune autoCompactWindow (and Catching a 3x Token Overcount)</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Thu, 05 Nov 2026 21:39:31 +0000</pubDate>
      <link>https://dev.to/princejain756/replaying-147-claude-code-codex-sessions-to-tune-autocompactwindow-and-catching-a-3x-token-2f43</link>
      <guid>https://dev.to/princejain756/replaying-147-claude-code-codex-sessions-to-tune-autocompactwindow-and-catching-a-3x-token-2f43</guid>
      <description>&lt;p&gt;My first script for checking local Claude Code token usage summed raw &lt;code&gt;assistant&lt;/code&gt; lines in &lt;code&gt;~/.claude/projects/**/*.jsonl&lt;/code&gt; and overcounted session &lt;code&gt;4baee81b&lt;/code&gt; by 3.0x (33 JSONL usage rows for 11 actual API turns). Whenever a single turn emits text plus multiple &lt;code&gt;tool_use&lt;/code&gt; blocks, Claude Code writes separate streaming records sharing the same &lt;code&gt;message.id&lt;/code&gt;, and every record repeats the cumulative prompt token count. Codex CLI has a similar quirk where &lt;code&gt;event_msg&lt;/code&gt; (&lt;code&gt;token_count&lt;/code&gt;) rows repeat identical &lt;code&gt;info.total_token_usage.total_tokens&lt;/code&gt; snapshots.&lt;/p&gt;

&lt;p&gt;After deduplicating by &lt;code&gt;message.id&lt;/code&gt; across 147 local Claude Code and Codex sessions on my machine (3,197 raw records collapsing to 2,284 real API turns, 255.79M input tokens, 43.9% cache hit rate), two things jumped out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;13.4% of turns drove 47.8% of weighted token cost.&lt;/strong&gt; Specifically, the 307 turns that ran above 200K context accounted for nearly half of all cache-weighted input token-equivalents (where &lt;code&gt;cache_read_input_tokens&lt;/code&gt; is weighted at 0.1x and uncached input at 1.0x), peaking at 467,835 tokens in session &lt;code&gt;78fd79c6&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Early tool outputs carry massive Context Rent.&lt;/strong&gt; A 12K-token file read or &lt;code&gt;git diff&lt;/code&gt; output on turn 3 of a 45-turn session sits in the prompt window for 42 subsequent turns (&lt;code&gt;12,000 * 42 = 504,000&lt;/code&gt; token-turns of context rent). Worse, when compaction finally triggers, the agent often immediately re-reads the exact same files on the next 3 turns because the summary dropped active file paths.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Replaying local transcripts with &lt;code&gt;compactsim&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://github.com/princejain756/compactsim" rel="noopener noreferrer"&gt;compactsim&lt;/a&gt; as a zero-dependency Node.js CLI to audit &lt;code&gt;~/.claude/projects&lt;/code&gt; and &lt;code&gt;~/.codex/sessions&lt;/code&gt; offline and run counterfactual compaction simulations against your actual turn history.&lt;/p&gt;

&lt;p&gt;Run it directly without installing anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx github:princejain756/compactsim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the real output on my 147-session corpus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CompactSim v0.1.0 - Context Compaction &amp;amp; Token Waste Simulator
Corpus: 147 sessions (123 Claude Code, 24 Codex) | 2,284 API turns (3,197 raw JSONL usage records, 1.40x raw overcount)

Baseline Token Profile:
- Total input tokens: 255.79M (143.49M uncached @ 1.0x, 112.30M cache-read @ 0.1x, 43.9% cache hit rate)
- Weighted input token-equivalents: 160.79M tok-eq
- Peak session context: 467,835 tokens (session 78fd79c6)
- Turns &amp;gt; 200K context: 307 turns (13.4% of turns driving 47.8% of weighted token cost)
- Turns &amp;gt; 400K context: 59 turns (2.6% of turns driving 15.7% of weighted token cost)
- Mid-session cache-bust spikes (&amp;gt;25K uncached jump): 760 spikes across 147 sessions

Counterfactual Policy Replay:
1. Baseline (recorded transcripts):      160.79M tok-eq |   0.0% saved |  9 compactions |  8.7m wait
2. autoCompactWindow = 400,000 tokens:   138.92M tok-eq | -13.6% saved | 10 compactions |  9.8m wait
3. autoCompactWindow = 250,000 tokens:   114.93M tok-eq | -28.5% saved | 11 compactions | 11.9m wait
4. autoCompactWindow = 150,000 tokens:    89.49M tok-eq | -44.3% saved | 17 compactions | 18.2m wait
5. Sliding tool-output eviction (15t):   136.67M tok-eq | -15.0% saved |  9 compactions |  8.7m wait
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the counterfactual simulator works
&lt;/h2&gt;

&lt;p&gt;When you lower &lt;code&gt;autoCompactWindow&lt;/code&gt; (for example from the default window down to &lt;code&gt;250,000&lt;/code&gt;), you do not get free savings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The turn immediately following compaction pays a 1.0x uncached re-prefill cost on the compacted summary plus system prompt (~22K tokens).&lt;/li&gt;
&lt;li&gt;If the compaction summary drops active working context, the agent re-reads files on the next 1 to 3 turns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;compactsim&lt;/code&gt; models both the uncached compaction re-prefill penalty and the empirical post-compaction file re-read tax observed in your transcripts. On my corpus, &lt;code&gt;autoCompactWindow = 250,000&lt;/code&gt; hits the sweet spot: it cuts weighted token usage by 28.5% (&lt;code&gt;160.79M&lt;/code&gt; down to &lt;code&gt;114.93M&lt;/code&gt; token-equivalents) while adding only 2 extra compactions across 147 sessions.&lt;/p&gt;

&lt;p&gt;Code and zero-dep CLI are MIT-licensed at &lt;a href="https://github.com/princejain756/compactsim" rel="noopener noreferrer"&gt;https://github.com/princejain756/compactsim&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>coding</category>
      <category>llm</category>
    </item>
    <item>
      <title>Naplog: let the logs wait</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Thu, 22 Oct 2026 19:50:34 +0000</pubDate>
      <link>https://dev.to/princejain756/naplog-let-the-logs-wait-4c16</link>
      <guid>https://dev.to/princejain756/naplog-let-the-logs-wait-4c16</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Naplog turns a pasted batch of log lines into a short morning brief. You paste up to 120 lines, a local open-weight model reads them, and you get back at most five incidents. Every incident links to the exact source lines it claims as evidence, so checking its work takes seconds.&lt;/p&gt;

&lt;p&gt;The effort it saves is the 6 a.m. scroll. Anyone who has opened a log file planning to "just skim it" and resurfaced 40 minutes later gets to be a little lazier here: skim five slips, then only read the lines that matter.&lt;/p&gt;

&lt;p&gt;Naplog did not exist on October 21. It is two days of work, built inside this challenge window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;The demo has to run on my machine: the app only binds to 127.0.0.1 and that is the whole point. Here it is working on the bundled 16-line synthetic log:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpjetprhd716r287iutsw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpjetprhd716r287iutsw.gif" alt="Naplog demo: paste logs, local model reads them, brief links every claim to its source lines" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On that sample, gemma3:4b found all five planted issues (three database connection timeouts, a failed nightly report, a disk-full backup, a rejected auth token) in 127.8 seconds on an M1 Max. Not fast. The model reads slowly so I do not have to read at all.&lt;/p&gt;

&lt;p&gt;The repo includes the same sample file and a one-command start if you want to run it on your own logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/princejain756" rel="noopener noreferrer"&gt;
        princejain756
      &lt;/a&gt; / &lt;a href="https://github.com/princejain756/naplog" rel="noopener noreferrer"&gt;
        naplog
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local morning briefs from pasted logs via Ollama and Gemma. Every issue links back to its source lines. No cloud inference.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Naplog&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/princejain756/naplog/assets/cover.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fprincejain756%2Fnaplog%2FHEAD%2Fassets%2Fcover.png" alt="A server asleep under a blanket of log lines"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let the logs wait.&lt;/p&gt;
&lt;p&gt;Naplog turns a pasted batch of log lines into a short morning brief using a
local language model through &lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt;. Every issue in the
brief links back to the numbered lines it came from, so you can check the
evidence before acting. Built for Hacktoberfest 2026, Week 3.&lt;/p&gt;
&lt;p&gt;No cloud inference, no accounts, no scheduled jobs. The pasted text never
leaves this machine and is held only in memory for the lifetime of the
process.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Requirements&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Node.js 22 or newer (uses only the standard library)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt; running on this machine&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;gemma3:4b&lt;/code&gt; model pulled locally:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;ollama pull gemma3:4b&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Initial model download needs internet access. After that, inference runs
entirely offline.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Run&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm start&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Then open &lt;a href="http://127.0.0.1:3217" rel="nofollow noopener noreferrer"&gt;http://127.0.0.1:3217&lt;/a&gt;. The app listens on loopback only.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Test&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm &lt;span class="pl-c1"&gt;test&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Checks cover input preparation, schema validation, the Ollama request
contract (via a stubbed fetch), the HTTP surface, and…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/princejain756/naplog" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Node 22, standard library only, no dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;All inference runs through Ollama with gemma3:4b, a 3.35 GB open-weight model pulled to local disk. The interesting part is not the prompt. It is the contract around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;contract.json&lt;/code&gt; pins the model tag, system prompt, JSON schema, generation options, and limits in one auditable file.&lt;/li&gt;
&lt;li&gt;Before text reaches the model, common credential shapes (&lt;code&gt;password=&lt;/code&gt;, &lt;code&gt;token=&lt;/code&gt;, &lt;code&gt;api_key=&lt;/code&gt;, &lt;code&gt;secret=&lt;/code&gt;, &lt;code&gt;Bearer&lt;/code&gt; values) are replaced with &lt;code&gt;[REDACTED]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The model answers against a strict schema: at most five incidents, each citing input line numbers. Responses are bounded to 64 KiB and validated; malformed output and failures are never cached.&lt;/li&gt;
&lt;li&gt;One digest at a time per server. Concurrent calls get HTTP 429 instead of a queue that pretends to scale.&lt;/li&gt;
&lt;li&gt;Successful digests sit in an 8-entry in-memory cache keyed by content hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server checks Host and Origin headers, serves an explicit static allowlist, sends &lt;code&gt;no-store&lt;/code&gt; and CSP headers, and writes nothing to disk. No log bodies, no model output, no analytics.&lt;/p&gt;

&lt;p&gt;40 automated checks cover masking, schema validation, the Ollama request shape, the HTTP surface, and the single-inference lock. &lt;code&gt;npm test&lt;/code&gt; runs all of them without needing the model.&lt;/p&gt;

&lt;p&gt;Honest bits from the build. The Ollama already installed on this machine was too old to even pull gemma3:4b (HTTP 412), so the first hour went to upgrading Ollama, not writing inference code. And in the first live run the model described retry attempts in an observation but cited only the timeout lines as evidence. Legal, since those lines exist, but a good reminder of what the evidence links are: they show where a claim points, they do not prove it. That is why the UI stamps "AI draft. Check the source lines before acting." over the output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Logs are close to the worst thing you can send to a hosted API. They carry hostnames, internal IPs, user IDs, customer data, and the occasional credential somebody forgot to scrub. A closed endpoint would make this tool a data leak with extra steps.&lt;/p&gt;

&lt;p&gt;An open-weight model turns the privacy claim from contractual into structural. Inference happens in a process on my laptop, the model still works with the cable pulled, each run costs $0, and the model is swappable: change one string in &lt;code&gt;contract.json&lt;/code&gt;, run the same test suite, and the new model has to satisfy the same schema. Closed APIs deprecate, reprice, and get acquired. A 3.35 GB file on disk just sits there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;Real numbers from this build: 128 seconds of model time replaces the 10 to 15 minutes I would otherwise spend reading a batch like this carefully. Input is capped at 120 nonblank lines on purpose. The use case is the morning batch, not forensics. If you are pasting 5,000 lines, you are doing the job the tool was built to avoid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; &lt;code&gt;gemma3:4b&lt;/code&gt; performs all inference locally through Ollama.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensourceai</category>
    </item>
    <item>
      <title>canimcp: which clients silently break your MCP server's tools</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Fri, 16 Oct 2026 18:54:28 +0000</pubDate>
      <link>https://dev.to/princejain756/canimcp-which-clients-silently-break-your-mcp-servers-tools-54nl</link>
      <guid>https://dev.to/princejain756/canimcp-which-clients-silently-break-your-mcp-servers-tools-54nl</guid>
      <description>&lt;p&gt;A tool on r/mcp sat invisible to Claude Code for 17 days. A root oneOf in the input schema. No error on the server, no error on the client. The tool just never appeared in the client's list.&lt;/p&gt;

&lt;p&gt;Last week SineFrame published a run of Claude Code and Codex against the same ten MCP servers at pinned versions. Five of the ten features split the clients, and the two never failed on the same feature. A tool argument named ids[]? Claude Code drops the tool silently. A 14 KB input schema? Codex compacts it and loses your required nested fields. 2049 tools on one server? Codex keeps the first 2048.&lt;/p&gt;

&lt;p&gt;I wanted that list as a check I could run in CI, so I built canimcp: point it at a saved tools/list response or at your server command, and it reports which client+version breaks on what, each finding carrying its evidence grade and a source link.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx canimcp fixtures/quirky-tools.json --client codex

8 findings . 1 error . 5 warnings . 2 advisories . 10 tools checked

tool: create_payment
  [error] root-composition-adjacent . codex 0.162.0
    root oneOf sits next to "properties" (inputSchema)
    A root oneOf or anyOf placed next to "properties" made Codex lose
    the property names - the call reached the server mangled.
    fix: move the composition inside each property
    src: m3-probes-2026-10 . evidence: probe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things the evidence forced me to change in my own design:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I almost shipped probe results as equal to measured ones. The published matrix grades some rows as direct binary probes not yet run under the harness, so the corpus carries evidence grades (measured, probe, historical, field-report) and output labels them. A probe is a lead, not a verdict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I thought of this as a schema linter. Then the Codex detail sunk in: in code mode the model never sees your JSON Schema at all, only a compacted TypeScript declaration generated from it. This is not a "does your schema validate" tool. It is a "what does each client actually see" corpus. The schema is just the part I can check statically.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What it is not: a live test. It sees the schema, not runtime result shapes or tonight's client build. For real client trials there is M3; canimcp is the fast pass in CI before that.&lt;/p&gt;

&lt;p&gt;Corpus PRs need a reproduction and client versions. Cursor, Gemini CLI and friends stay unseeded until someone ships evidence.&lt;/p&gt;

&lt;p&gt;github.com/princejain756/canimcp - npx canimcp - zero dependencies, Node 18+.&lt;/p&gt;

&lt;p&gt;Which MCP client should get seeded into the corpus next?&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>cli</category>
      <category>devtools</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I let a frontier model audit my npm package - it found 16 bugs in 400 lines</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Thu, 15 Oct 2026 12:48:43 +0000</pubDate>
      <link>https://dev.to/princejain756/i-let-a-frontier-model-audit-my-npm-package-it-found-16-bugs-in-400-lines-209f</link>
      <guid>https://dev.to/princejain756/i-let-a-frontier-model-audit-my-npm-package-it-found-16-bugs-in-400-lines-209f</guid>
      <description>&lt;p&gt;I built slopsieve, a zero-dep Node CLI that scores a diff or PR for the hygiene signals reviewers check by hand. Before tagging v0.2.0, I ran an adversarial audit of the full source with a frontier model in high-thinking mode.&lt;/p&gt;

&lt;p&gt;The findings were real, not theoretical:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;diff -u&lt;/code&gt; output (no &lt;code&gt;diff --git&lt;/code&gt; header) parsed to zero files. The tool reported a confident, completely false 0/100.&lt;/li&gt;
&lt;li&gt;A removed line &lt;code&gt;-- i;&lt;/code&gt; inside a hunk (a C decrement) was consumed as a file header and corrupted the path.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--fail-at&lt;/code&gt; without a value silently became NaN and the gate never fired.&lt;/li&gt;
&lt;li&gt;Any package.json version bump counted as "new dependency for a small diff".&lt;/li&gt;
&lt;li&gt;test.each parameterization that kept coverage intact was scored as assertion removal.&lt;/li&gt;
&lt;li&gt;JSDoc &lt;a class="mentioned-user" href="https://dev.to/param"&gt;@param&lt;/a&gt;/@returns tagged as commented-out code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;catch {}&lt;/code&gt; with no parameter (valid ES2019) escaped detection.&lt;/li&gt;
&lt;li&gt;Reordered code was classified as whitespace-only churn because I sorted lines before comparing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All 16 are fixed, each with a regression case. The tool now scores its own diff 0/100 and correctly lints itself, which is how I found out my test file literally contains strings that look like the slop it tests for (fixed with per-file &lt;code&gt;slopsieve-ignore&lt;/code&gt; markers, eslint-disable style).&lt;/p&gt;

&lt;p&gt;What shipped alongside the fixes: secrets-in-diff detection with redacted evidence, phantom-import checks against the actual checkout, &lt;code&gt;--format github&lt;/code&gt; for Actions annotations, .slopsieverc.json, git range and --staged scoring, generated-file and lockfile exclusion.&lt;/p&gt;

&lt;p&gt;The lesson I keep relearning: happy-path parsing is where tools like this quietly lie to you. My parser handled &lt;code&gt;diff --git&lt;/code&gt; beautifully and reported a confident clean score on input it did not understand at all.&lt;/p&gt;

&lt;p&gt;repo: &lt;a href="https://github.com/princejain756/slopsieve" rel="noopener noreferrer"&gt;https://github.com/princejain756/slopsieve&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;what's the worst silent-failure bug a linter has ever handed you?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>javascript</category>
      <category>node</category>
      <category>testing</category>
    </item>
    <item>
      <title>slopsieve: a diff linter for the AI slop era</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Thu, 15 Oct 2026 12:12:00 +0000</pubDate>
      <link>https://dev.to/princejain756/slopsieve-a-diff-linter-for-the-ai-slop-era-1a73</link>
      <guid>https://dev.to/princejain756/slopsieve-a-diff-linter-for-the-ai-slop-era-1a73</guid>
      <description>&lt;p&gt;cURL scrapped its bug bounty after getting buried in AI slop. Godot is drowning in slop PRs. GitHub floated a PR kill switch. the maintainers' complaint is consistent: the code looks fine until you read it.&lt;/p&gt;

&lt;p&gt;so i built slopsieve, a zero-dep node CLI that scores a diff or PR for the 12 signals a tired reviewer checks at 1am:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx slopsieve fixtures/slop.patch

SLOP SCORE: 100/100 - ALARM
4 files · +37 -8 lines

FLAGS
  [30] test weakening        tests/cart.test.js:24 it.skip(...)
  [25] debug leftovers       src/cart.js:25 console.log("checking qty", qty)
  [20] empty catch/except    src/utils.js:12 } catch (e) {}
  [20] trivial dependency    package.json:17 adds 'is-odd'
  [15] commented-out code    3 commented-out lines
  [10] narration comments    6 narration comments
  [10] dead exports          'isQuantityOdd' referenced nowhere in this diff
  [ 5] vague util sprawl     src/utils.js created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;what it does: parses the unified diff, runs 12 weighted checks (it.skip, assertions removed, console.log/debugger, catch-all deps, exports nothing references, "this function..." comments), prints file and line for every flag. &lt;code&gt;--fail-at&lt;/code&gt; makes it a CI gate, &lt;code&gt;--json&lt;/code&gt; feeds tooling.&lt;/p&gt;

&lt;p&gt;the bug that embarrassed me: my debug-leftovers regex &lt;code&gt;dd\s*\(&lt;/code&gt; (laravel dump) matched &lt;code&gt;isQuantityOdd(&lt;/code&gt; because the string "dd(" hides inside "Odd(". the tool caught nothing wrong with the fixture and everything wrong with my regex. word boundary fixed it; the test fixture keeps it fixed.&lt;/p&gt;

&lt;p&gt;what it is not: an AI detector. it scores diff hygiene signals. a human can write a 100/100 slop diff, an LLM can write a 0/100 clean one. the README lists where the heuristics miss: two-line catch blocks, callers outside the diff, comment patterns in other languages.&lt;/p&gt;

&lt;p&gt;github.com/princejain756/slopsieve - npx slopsieve owner/repo#123&lt;/p&gt;

&lt;p&gt;what is the one signal you wish your PR queue flagged automatically?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>I replayed 7 repos' READMEs in fresh clones. 2 of them fail their own quickstart.</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Wed, 14 Oct 2026 19:15:19 +0000</pubDate>
      <link>https://dev.to/princejain756/i-replayed-7-repos-readmes-in-fresh-clones-2-of-them-fail-their-own-quickstart-37n3</link>
      <guid>https://dev.to/princejain756/i-replayed-7-repos-readmes-in-fresh-clones-2-of-them-fail-their-own-quickstart-37n3</guid>
      <description>&lt;p&gt;Your README is a promise nobody tests.&lt;/p&gt;

&lt;p&gt;Setup instructions rot silently. You rename a script, add an env var, switch a package manager, and the quickstart keeps promising a path that stopped working weeks ago. Nobody on the team notices, because everyone who would notice already has the repo running. The only people who hit the wall are new users, and they bounce without filing an issue.&lt;/p&gt;

&lt;p&gt;I got tired of wondering whether mine still worked, so I built a tool that checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;coldstart stages your committed state in a temp dir. No node_modules, no .env, none of the untracked files that make it work on your machine and nowhere else. Then it parses the shell commands out of your README and replays them in order, tracking the working directory and environment between steps.&lt;/p&gt;

&lt;p&gt;When a step fails, you get the exit code, the last output lines, and the exact README line that sent a new user there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static checks before anything runs
&lt;/h2&gt;

&lt;p&gt;A lot of README bugs are detectable without executing a single command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm run start&lt;/code&gt; documented but no "start" script in package.json&lt;/li&gt;
&lt;li&gt;pnpm lockfile present but the README says &lt;code&gt;npm install&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;curl | bash&lt;/code&gt; installers, flagged because they execute on the reader's machine, not in any sandbox&lt;/li&gt;
&lt;li&gt;commands that reference files the repo does not ship and the user cannot provide&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it found on my own repos
&lt;/h2&gt;

&lt;p&gt;7 repos, 2 fail their own quickstart. The worst one documents &lt;code&gt;npm run start&lt;/code&gt; and there is no start script anywhere in package.json. A reader following the README hits a wall at step 2 and leaves. That is a star I never got and never knew I lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limits
&lt;/h2&gt;

&lt;p&gt;It replays what the README documents, not what your CI does. Server-style commands get started, probed, and killed, so it can only tell you whether the app boots, not whether it works. Placeholder arguments like &lt;code&gt;your-api-key&lt;/code&gt; get skipped with a note instead of failing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx coldstart-cli            &lt;span class="c"&gt;# current directory&lt;/span&gt;
npx coldstart-cli &amp;lt;git-url&amp;gt;  &lt;span class="c"&gt;# or straight from GitHub&lt;/span&gt;
npx coldstart-cli &lt;span class="nt"&gt;--docker&lt;/span&gt;   &lt;span class="c"&gt;# real clean room in a container&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero dependencies, Node 18+. Repo: &lt;a href="https://github.com/princejain756/coldstart" rel="noopener noreferrer"&gt;https://github.com/princejain756/coldstart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run it on yours, I genuinely want to know what breaks. The weirder the README, the better the test case.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>documentation</category>
      <category>testing</category>
      <category>tools</category>
    </item>
    <item>
      <title>The MCP security tools all scan. None of them stop the call.</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Wed, 14 Oct 2026 10:16:46 +0000</pubDate>
      <link>https://dev.to/princejain756/the-mcp-security-tools-all-scan-none-of-them-stop-the-call-452b</link>
      <guid>https://dev.to/princejain756/the-mcp-security-tools-all-scan-none-of-them-stop-the-call-452b</guid>
      <description>&lt;p&gt;I spent a morning looking at MCP security tooling. Cisco has a scanner, there are three or four audit CLIs, all of them read your tool descriptions and report sketchy ones. Useful, but they share a blind spot: nothing sits between the agent and the server when the call actually happens.&lt;/p&gt;

&lt;p&gt;The failure mode that keeps showing up (the 159-point HN thread on MCP vulnerabilities is mostly this) is boring: the agent calls read_file with ../../etc/passwd, or fetch on &lt;a href="http://169.254.169.254" rel="noopener noreferrer"&gt;http://169.254.169.254&lt;/a&gt;, or a get_env tool that politely returns your AWS keys. A scanner that read the tool description last week does nothing here.&lt;/p&gt;

&lt;p&gt;So I built mcp-bouncer. It wraps any stdio MCP server as a JSON-RPC proxy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tools/list responses get filtered, so unapproved tools are invisible to the agent&lt;/li&gt;
&lt;li&gt;path args are normalized (dot segments resolved, separators unified) before allow/deny globs match, which kills traversal and most encoding games&lt;/li&gt;
&lt;li&gt;url args refuse private IPs, 169.254.169.254, *.internal, localhost, and any scheme you did not list&lt;/li&gt;
&lt;li&gt;per-tool rate limits, a response size cap, call timeouts&lt;/li&gt;
&lt;li&gt;every decision appended to a local JSONL audit file, with a sha256 digest of the args rather than the args themselves (args hold secrets; digests still let you correlate)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;First working version blocked every single call. The reason: my "contains a null byte" check compared against what was supposed to be a literal NUL and was actually an empty string, and everything includes the empty string. Test suite caught it because I assert the allowed path actually passes, which is the whole point of writing tests that check the happy path and not just the blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits, honestly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This is protocol-level enforcement. The wrapped server still runs as your user; a hostile binary can read whatever it wants. For that you want a container or a real sandbox.&lt;/li&gt;
&lt;li&gt;Stdio transport only. Remote HTTP MCP servers are not covered yet.&lt;/li&gt;
&lt;li&gt;A policy you wrote wrong is still wrong. &lt;code&gt;mcp-bouncer scan&lt;/code&gt; gives you a starting draft, not a guarantee.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;About 500 lines, zero dependencies, MIT.&lt;/p&gt;

&lt;p&gt;repo: &lt;a href="https://github.com/princejain756/mcp-bouncer" rel="noopener noreferrer"&gt;https://github.com/princejain756/mcp-bouncer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is the ugliest thing an MCP server has done in your setup?&lt;/p&gt;

&lt;h2&gt;
  
  
  update: post-launch hardening
&lt;/h2&gt;

&lt;p&gt;After publishing I ran the whole source through three rounds of security review with a frontier reasoning model. 33 findings, all patched with regression tests: json-rpc batches bypassing policy, non-lifecycle methods forwarded unconditionally, relative paths reaching the audit file, unanchored ipv4-mapped ipv6 checks, deep &lt;strong&gt;proto&lt;/strong&gt; keys in arguments, and a rate-limit map that could be wiped by fake tool names. 0.1.1 is on npm now. The final round came back clean.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>mcp</category>
      <category>security</category>
    </item>
    <item>
      <title>Your CLAUDE.md and AGENTS.md disagree and you don't know it</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Wed, 14 Oct 2026 07:29:43 +0000</pubDate>
      <link>https://dev.to/princejain756/your-claudemd-and-agentsmd-disagree-and-you-dont-know-it-5f23</link>
      <guid>https://dev.to/princejain756/your-claudemd-and-agentsmd-disagree-and-you-dont-know-it-5f23</guid>
      <description>&lt;p&gt;Every agent tool wants its own config file. CLAUDE.md for Claude Code, AGENTS.md for Codex and 30+ others, .cursor/rules for Cursor, .windsurfrules, GEMINI.md, copilot-instructions.md. You write a rule once, paste it into five places, and six months later the files disagree. One says &lt;code&gt;npm&lt;/code&gt;, another says &lt;code&gt;pnpm&lt;/code&gt;. One says never push to main, another says always.&lt;/p&gt;

&lt;p&gt;There are good sync tools (rulesync) but they ask you to adopt a new source-of-truth format. I wanted a linter, not a migration: audit the files I already have.&lt;/p&gt;

&lt;p&gt;So I built ruleherd. &lt;code&gt;npx ruleherd&lt;/code&gt; reads every instruction file in a repo and reports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CONFLICT: contradictions between files (tabs vs spaces, npm vs pnpm, never vs always on shared topics)&lt;/li&gt;
&lt;li&gt;DEAD REF: backticked paths and @imports pointing at files that don't exist&lt;/li&gt;
&lt;li&gt;DEAD CMD: &lt;code&gt;npm run x&lt;/code&gt; where no package.json has an x script&lt;/li&gt;
&lt;li&gt;STALE: "react 17" in the rules while package.json installs react 19&lt;/li&gt;
&lt;li&gt;DEAD GLOB: a .mdc rule whose globs point at a deleted directory (Cursor silently never loads it)&lt;/li&gt;
&lt;li&gt;DUPLICATE: paragraphs pasted across files&lt;/li&gt;
&lt;li&gt;BLOAT: single files over ~4k tokens that load into every prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Score out of 100. Strict mode exits nonzero for CI. Zero dependencies.&lt;/p&gt;

&lt;p&gt;Real output on my own machine (it scans global configs too):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRADE: B (85/100)
9 instruction files · ~4,757 tokens of agent context
  DUPLICATE ~333-char block in 6 files
  DUPLICATE ~939-char block in 6 files
  DUPLICATE ~705-char block in 6 files
          ~/.claude/CLAUDE.md, ~/.gemini/GEMINI.md,
          ~/.config/devin/AGENTS.md, windsurf global rules,
          ~/.agents/rules/, ~/.cursor/rules/browser-tooling.mdc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hand-sync one universal rules file into five tool locations. It drifted anyway.&lt;/p&gt;

&lt;p&gt;The embarrassing part: my first version flagged &lt;code&gt;@types/node&lt;/code&gt; as a dead file reference and &lt;code&gt;pnpm install&lt;/code&gt; as a missing npm script. Both are in my own config files. Auditing the auditor is humbling.&lt;/p&gt;

&lt;p&gt;Honest limits: contradiction detection is heuristic (keyword pairs and never/always polarity, not semantic understanding). Dead-ref checking is deliberately conservative. A clean grade means "no detectable drift", not "your rules are good".&lt;/p&gt;

&lt;p&gt;MIT, zero deps: &lt;a href="https://github.com/princejain756/ruleherd" rel="noopener noreferrer"&gt;https://github.com/princejain756/ruleherd&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which of your agent config files do you think is the stale one?&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
      <category>tools</category>
    </item>
    <item>
      <title>i stopped trusting coding agent demos, so i built a tool that interviews them</title>
      <dc:creator>Prince Jain</dc:creator>
      <pubDate>Wed, 14 Oct 2026 06:13:41 +0000</pubDate>
      <link>https://dev.to/princejain756/i-stopped-trusting-coding-agent-demos-so-i-built-a-tool-that-interviews-them-2576</link>
      <guid>https://dev.to/princejain756/i-stopped-trusting-coding-agent-demos-so-i-built-a-tool-that-interviews-them-2576</guid>
      <description>&lt;p&gt;i kept trusting agent demos more than i should have, so i built a small runner that makes coding agents prove it on my own tasks.&lt;/p&gt;

&lt;p&gt;the idea is boring on purpose: point it at any repo, define a few tasks in plain json, and it runs each agent CLI on a throwaway copy of the project. after the agent finishes, the verify scripts get restored from the source repo before they run. that part matters. an agent with write access can just edit its own checker and pass. i shipped agent-trials without the restore step, audited it, felt dumb, fixed it.&lt;/p&gt;

&lt;p&gt;a real run on a 3-task toy suite looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 opus    sonnet    haiku
fix-clamp     33.2s     39.5s     32.6s
divide-guard  22.8s     26.8s     90.5s
slug-test     42.7s     67.5s     45.5s
score          3/3       3/3       3/3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;scores and medians move around between runs. it's a smoke test, not a leaderboard. the thing i actually use it for is catching "the cli exited 0 but did nothing" and watching cost drift.&lt;/p&gt;

&lt;p&gt;zero dependencies, plain json suites, works offline if your agent cli works offline.&lt;/p&gt;

&lt;p&gt;github.com/princejain756/agent-trials&lt;/p&gt;

&lt;p&gt;what would you want it to measure that it doesn't?&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
