<?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: Eduard Barrera</title>
    <description>The latest articles on DEV Community by Eduard Barrera (@eduardbar).</description>
    <link>https://dev.to/eduardbar</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3785480%2Fb9d5b2ee-06a0-469a-ad08-a2f212ff22c6.jpeg</url>
      <title>DEV Community: Eduard Barrera</title>
      <link>https://dev.to/eduardbar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eduardbar"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Eduard Barrera</dc:creator>
      <pubDate>Sun, 22 Feb 2026 20:37:35 +0000</pubDate>
      <link>https://dev.to/eduardbar/-5f1i</link>
      <guid>https://dev.to/eduardbar/-5f1i</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/eduardbar" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F3785480%2Fb9d5b2ee-06a0-469a-ad08-a2f212ff22c6.jpeg" alt="eduardbar"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/eduardbar/drift-an-open-source-cli-that-detects-silent-technical-debt-in-ai-generated-typescript-code-4ll7" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;drift: an open source CLI that detects silent technical debt in AI-generated TypeScript code&lt;/h2&gt;
      &lt;h3&gt;Eduard Barrera ・ Feb 22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tooling&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>typescript</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>drift: an open source CLI that detects silent technical debt in AI-generated TypeScript code</title>
      <dc:creator>Eduard Barrera</dc:creator>
      <pubDate>Sun, 22 Feb 2026 20:34:27 +0000</pubDate>
      <link>https://dev.to/eduardbar/drift-an-open-source-cli-that-detects-silent-technical-debt-in-ai-generated-typescript-code-4ll7</link>
      <guid>https://dev.to/eduardbar/drift-an-open-source-cli-that-detects-silent-technical-debt-in-ai-generated-typescript-code-4ll7</guid>
      <description>&lt;p&gt;I've been vibe coding for months. Fast shipping, AI pair programming, features done in hours.&lt;/p&gt;

&lt;p&gt;At some point I sat down and actually &lt;em&gt;read&lt;/em&gt; the code the AI had written.&lt;/p&gt;

&lt;p&gt;It worked. But it had left a consistent pattern of silent debt — the kind CI doesn't catch, linters don't flag, but makes the codebase progressively harder to work with.&lt;/p&gt;

&lt;p&gt;Things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;catch(e) {}&lt;/code&gt; — errors swallowed silently with no logging, no rethrow&lt;/li&gt;
&lt;li&gt;Unused imports from refactors the AI did and never cleaned up&lt;/li&gt;
&lt;li&gt;Functions with no explicit return types breaking IDE inference&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;console.log&lt;/code&gt; buried 3 layers deep in business logic&lt;/li&gt;
&lt;li&gt;50-line functions doing 5 unrelated things&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TODO&lt;/code&gt;/&lt;code&gt;FIXME&lt;/code&gt; comments the AI added as placeholders and never resolved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of it broke anything. All of it made the codebase worse.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;drift&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;drift is a CLI that scans your TypeScript project using AST analysis (&lt;a href="https://ts-morph.com" rel="noopener noreferrer"&gt;ts-morph&lt;/a&gt;) and scores each file from 0–100 based on AI-generated debt patterns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @eduardbar/drift scan ./src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;drift — vibe coding debt detector

Score    67/100  HIGH
4 file(s) with issues · 5 errors · 12 warnings · 3 info

src/api/users.ts (score 85/100)
  ✖ L1    large-file     File has 412 lines (threshold: 300)
  ▲ L34   debug-leftover console.log left in production code
  ▲ L89   catch-swallow  Empty catch block silently swallows errors
  ▲ L201  any-abuse      Explicit 'any' type detected

src/utils/helpers.ts (score 70/100)
  ✖ L12   duplicate-function-name 'formatDate' looks like a duplicate
  ▲ L55   dead-code       Unused import 'debounce'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The 8 detection rules
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;What it catches&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;large-file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;error&lt;/td&gt;
&lt;td&gt;Files over 300 lines — AI dumps everything into one place&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;large-function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;error&lt;/td&gt;
&lt;td&gt;Functions over 50 lines — AI avoids splitting logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;debug-leftover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;warning&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;console.log&lt;/code&gt;, &lt;code&gt;TODO&lt;/code&gt;, &lt;code&gt;FIXME&lt;/code&gt;, &lt;code&gt;HACK&lt;/code&gt; comments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dead-code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;warning&lt;/td&gt;
&lt;td&gt;Unused imports — AI imports more than it uses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;duplicate-function-name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;error&lt;/td&gt;
&lt;td&gt;Near-identical function names — AI regenerates instead of reusing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;any-abuse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;warning&lt;/td&gt;
&lt;td&gt;Explicit &lt;code&gt;any&lt;/code&gt; — AI defaults to &lt;code&gt;any&lt;/code&gt; when it can't infer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;catch-swallow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;warning&lt;/td&gt;
&lt;td&gt;Empty catch blocks — AI makes code "not throw"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;no-return-type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;info&lt;/td&gt;
&lt;td&gt;Missing explicit return types on functions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Score breakdown
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Grade&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;CLEAN&lt;/td&gt;
&lt;td&gt;No issues found&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1–19&lt;/td&gt;
&lt;td&gt;LOW&lt;/td&gt;
&lt;td&gt;Minor issues, safe to ship&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20–44&lt;/td&gt;
&lt;td&gt;MODERATE&lt;/td&gt;
&lt;td&gt;Worth a review before merging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;45–69&lt;/td&gt;
&lt;td&gt;HIGH&lt;/td&gt;
&lt;td&gt;Significant structural debt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;70–100&lt;/td&gt;
&lt;td&gt;CRITICAL&lt;/td&gt;
&lt;td&gt;Review before this goes anywhere near prod&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Validation
&lt;/h2&gt;

&lt;p&gt;I ran it on the &lt;a href="https://github.com/shadcn-ui/ui" rel="noopener noreferrer"&gt;shadcn/ui CLI source&lt;/a&gt; — professional human-written code. Score: &lt;strong&gt;0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I ran it on my own vibe-coded modules. Score: &lt;strong&gt;40–60&lt;/strong&gt; consistently.&lt;/p&gt;

&lt;p&gt;The difference is real. The tool makes it measurable.&lt;/p&gt;

&lt;h2&gt;
  
  
  CI integration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check for vibe coding drift&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx @eduardbar/drift scan ./src --min-score &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit code &lt;code&gt;1&lt;/code&gt; if score exceeds &lt;code&gt;--min-score&lt;/code&gt;. Blocks the merge. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Known limitation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;console.log&lt;/code&gt; in intentional CLI output files gets flagged as &lt;code&gt;debug-leftover&lt;/code&gt;. A &lt;code&gt;.drift.config.ts&lt;/code&gt; to mark exceptions is on the roadmap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;TypeScript · ts-morph · Commander.js · kleur · zero runtime dependencies&lt;/p&gt;




&lt;p&gt;Zero config. MIT. Works on any TypeScript or JavaScript project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/eduardbar/drift" rel="noopener noreferrer"&gt;github.com/eduardbar/drift&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;npm:&lt;/strong&gt; &lt;code&gt;npx @eduardbar/drift scan .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you're shipping AI-generated code — run this before your next deploy. You'll be surprised.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
