<?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: Isaac</title>
    <description>The latest articles on DEV Community by Isaac (@fathe__r).</description>
    <link>https://dev.to/fathe__r</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%2F4055977%2F1e4ed3ae-6a89-45cd-8c9b-8ad17fd2975e.jpg</url>
      <title>DEV Community: Isaac</title>
      <link>https://dev.to/fathe__r</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fathe__r"/>
    <language>en</language>
    <item>
      <title>My Env Var Scanner Gave My Own App a 0/100. So I Had to Figure Out Why</title>
      <dc:creator>Isaac</dc:creator>
      <pubDate>Fri, 14 Aug 2026 07:54:45 +0000</pubDate>
      <link>https://dev.to/fathe__r/my-env-var-scanner-gave-my-own-app-a-0100-so-i-had-to-figure-out-why-57p7</link>
      <guid>https://dev.to/fathe__r/my-env-var-scanner-gave-my-own-app-a-0100-so-i-had-to-figure-out-why-57p7</guid>
      <description>&lt;p&gt;I built Pookoo to catch a boring but real problem: environment variable drift.&lt;/p&gt;

&lt;p&gt;Dead variables nobody deleted. Secrets accidentally exposed in a public bundle. The same variable with different fallback values in different files. Required configuration that never made it into &lt;code&gt;.env.example&lt;/code&gt; or the documentation.&lt;/p&gt;

&lt;p&gt;The idea was deliberately simple: &lt;strong&gt;use static analysis, not an LLM.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Parse the code, build a picture of which environment variables are declared and how they're used, then surface places where those two disagree.&lt;/p&gt;

&lt;p&gt;The first real thing I did once Pookoo could run end-to-end was point it at a production app of mine.&lt;/p&gt;

&lt;p&gt;I wanted to know what it would say about actual, shipped code.&lt;/p&gt;

&lt;p&gt;It gave the app a &lt;strong&gt;0/100&lt;/strong&gt;. 😶&lt;/p&gt;

&lt;p&gt;And almost immediately, I could see why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first scan was wrong
&lt;/h2&gt;

&lt;p&gt;Pookoo flagged &lt;code&gt;NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY&lt;/code&gt; and &lt;code&gt;NEXT_PUBLIC_GOOGLE_MAPS_API_KEY&lt;/code&gt; as &lt;strong&gt;CRITICAL secret leaks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Except neither of those is supposed to be secret.&lt;/p&gt;

&lt;p&gt;That's the entire point of the &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; prefix, and "publishable" is right there in the Clerk variable's name.&lt;/p&gt;

&lt;p&gt;It also scanned &lt;code&gt;.next/dev/server/chunks/&lt;/code&gt;, which is compiled build output, and treated it as application source.&lt;/p&gt;

&lt;p&gt;Then it reported several SDK-consumed environment variables as dead.&lt;/p&gt;

&lt;p&gt;Those were variables that Clerk and Stripe read internally, somewhere inside their own packages. Pookoo doesn't inspect &lt;code&gt;node_modules&lt;/code&gt; intentionally so from the perspective of its dependency graph, those variables had no usages.&lt;/p&gt;

&lt;p&gt;The app wasn't catastrophic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pookoo was making claims that its analysis couldn't actually justify.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That turned out to be much more interesting than a clean first scan would have been.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with "unused"
&lt;/h2&gt;

&lt;p&gt;I didn't want Pookoo to statically parse an entire dependency tree just to prove that &lt;code&gt;CLERK_SECRET_KEY&lt;/code&gt; gets read somewhere inside &lt;code&gt;@clerk/nextjs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Walking through &lt;code&gt;node_modules&lt;/code&gt; would make scans slower, noisier, and much harder to reason about.&lt;/p&gt;

&lt;p&gt;But there was a consequence: any variable consumed internally by an SDK looked exactly like a dead variable, because nothing in the application's own source code referenced it.&lt;/p&gt;

&lt;p&gt;So I added a small piece of domain knowledge.&lt;/p&gt;

&lt;p&gt;Pookoo now knows about common SDK prefixes like Clerk, Stripe, Sentry, and others, as well as platform-level variables such as &lt;code&gt;NODE_ENV&lt;/code&gt; and &lt;code&gt;PORT&lt;/code&gt; that can be supplied by the runtime rather than explicitly referenced in application code.&lt;/p&gt;

&lt;p&gt;It's not a clever algorithm.&lt;/p&gt;

&lt;p&gt;It's an explicit acknowledgement that static analysis has boundaries.&lt;/p&gt;

&lt;p&gt;If I already know that an SDK can consume a particular family of environment variables, pretending otherwise doesn't make the analysis more rigorous. It just makes the result less useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Narrowing "secret"
&lt;/h2&gt;

&lt;p&gt;The secret detection rule had the opposite problem.&lt;/p&gt;

&lt;p&gt;It was too eager.&lt;/p&gt;

&lt;p&gt;The original keyword list included &lt;code&gt;KEY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At first glance, that seems reasonable. But "publishable key" is a real and intentional category.&lt;/p&gt;

&lt;p&gt;Clerk has publishable keys. Stripe has publishable keys. Some APIs are explicitly designed to expose certain identifiers to the client.&lt;/p&gt;

&lt;p&gt;So I narrowed the high-confidence secret indicators to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SECRET&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PASSWORD&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PRIVATE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I added a small allowlist for known-safe publishable-key patterns.&lt;/p&gt;

&lt;p&gt;The important change wasn't the exact list of keywords.&lt;/p&gt;

&lt;p&gt;It was changing the question from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Does this variable contain a word that sounds sensitive?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Does the evidence actually support calling this a secret?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a much better question for a static analyzer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not guessing about what can't be known
&lt;/h2&gt;

&lt;p&gt;The hardest change wasn't really a bug fix.&lt;/p&gt;

&lt;p&gt;It was deciding what Pookoo should do when the answer simply isn't knowable statically.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRIPE_SECRET_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's easy.&lt;/p&gt;

&lt;p&gt;The analyzer can resolve the exact variable being accessed.&lt;/p&gt;

&lt;p&gt;But what about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;someVar&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;someVar&lt;/code&gt; could contain anything at runtime.&lt;/p&gt;

&lt;p&gt;There is no static analysis trick that lets me magically know the value.&lt;/p&gt;

&lt;p&gt;I could assume every environment variable is potentially being used.&lt;/p&gt;

&lt;p&gt;That would reduce false positives, but it would also make dead-variable detection almost useless.&lt;/p&gt;

&lt;p&gt;Or I could assume dynamic access means nothing is being used.&lt;/p&gt;

&lt;p&gt;That gives me more findings, but some of them would obviously be wrong.&lt;/p&gt;

&lt;p&gt;So I chose a third option:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;don't guess.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A dynamic access still becomes part of Pookoo's internal graph. The access happened, so the analyzer records it.&lt;/p&gt;

&lt;p&gt;But because it can't determine which environment variable the access resolves to, it doesn't create an edge to a specific variable.&lt;/p&gt;

&lt;p&gt;In other words, Pookoo represents the uncertainty instead of pretending it doesn't exist.&lt;/p&gt;

&lt;p&gt;That decision also simplified another part of the codebase.&lt;/p&gt;

&lt;p&gt;The "is this variable unused?" check doesn't need another AST traversal or a pile of special cases.&lt;/p&gt;

&lt;p&gt;It's just a graph query:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find a declared environment variable with zero incoming usage edges.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;It does mean that a variable accessed only through an unresolved dynamic expression can still appear unreferenced.&lt;/p&gt;

&lt;p&gt;I haven't patched that with another guess.&lt;/p&gt;

&lt;p&gt;That's the tradeoff of refusing to claim more than the analysis can prove.&lt;/p&gt;

&lt;h2&gt;
  
  
  Renaming a rule until it stopped lying
&lt;/h2&gt;

&lt;p&gt;The same idea led to another change that I think is more important than it initially sounds.&lt;/p&gt;

&lt;p&gt;The rule used to be called:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NO_UNREFERENCED_ENV_VAR&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It also failed CI by default.&lt;/p&gt;

&lt;p&gt;But "unreferenced" is a much stronger claim than Pookoo can actually prove.&lt;/p&gt;

&lt;p&gt;It implies that the variable isn't used anywhere in the codebase or at runtime.&lt;/p&gt;

&lt;p&gt;Static analysis can't establish that.&lt;/p&gt;

&lt;p&gt;What Pookoo can establish is much narrower:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I didn't find a reference that I could statically resolve.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I renamed the rule to:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NO_STATIC_REFERENCE_FOUND&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And changed its severity from blocking to informational.&lt;/p&gt;

&lt;p&gt;It's a smaller claim.&lt;/p&gt;

&lt;p&gt;That's exactly why it's a better one.&lt;/p&gt;

&lt;p&gt;A static-analysis tool becomes more useful when its findings correspond closely to what it can actually prove.&lt;/p&gt;

&lt;p&gt;I'd rather have Pookoo say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I couldn't find a static reference to this variable."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;than:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This variable is dead."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;when the second statement isn't something the analyzer can actually know.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Pookoo looks like now
&lt;/h2&gt;

&lt;p&gt;Pookoo is still less than three weeks old.&lt;/p&gt;

&lt;p&gt;So far, it's crossed roughly 1,000 npm downloads, with a much smaller GitHub footprint.&lt;/p&gt;

&lt;p&gt;What I do have is a tool that encountered a real failure against a real application almost immediately.&lt;/p&gt;

&lt;p&gt;And that failure gave me a much better understanding of what I actually want Pookoo to be.&lt;/p&gt;

&lt;p&gt;Not a tool that produces the most warnings.&lt;/p&gt;

&lt;p&gt;Not a tool that sounds confident.&lt;/p&gt;

&lt;p&gt;A tool that can tell the difference between:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"I know this is wrong."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"I found something suspicious."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"I don't have enough information to say."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That distinction is becoming the interesting part of building it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The next thing I'm working on is intra-file constant resolution.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now, Pookoo treats that similarly to a genuinely dynamic access because it doesn't yet trace the assignment back far enough to resolve &lt;code&gt;KEY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But this is a common pattern, and in this case the answer is actually knowable.&lt;/p&gt;

&lt;p&gt;It's the natural next step for the same reason as everything above:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;there's information Pookoo currently has access to, but isn't using yet.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the part of static analysis I'm enjoying most.&lt;/p&gt;

&lt;p&gt;Every limitation forces a choice:&lt;/p&gt;

&lt;p&gt;Do we make an assumption?&lt;/p&gt;

&lt;p&gt;Do we add domain knowledge?&lt;/p&gt;

&lt;p&gt;Do we improve the analysis?&lt;/p&gt;

&lt;p&gt;Or do we explicitly model the uncertainty?&lt;/p&gt;

&lt;p&gt;I'm starting to think the quality of a static-analysis tool isn't just about how much it can detect.&lt;/p&gt;

&lt;p&gt;It's about how carefully it knows the difference between what it &lt;strong&gt;knows&lt;/strong&gt;, what it &lt;strong&gt;suspects&lt;/strong&gt;, and what it &lt;strong&gt;can't know&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you want to see what Pookoo finds in your own project:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And if you want to generate an &lt;code&gt;.env.example&lt;/code&gt; automatically:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you try it and find a case Pookoo doesn't understand, I'd genuinely like to hear about it.&lt;/p&gt;

&lt;p&gt;Those edge cases are currently some of the best inputs for deciding what it should learn next.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Isaac</dc:creator>
      <pubDate>Sat, 01 Aug 2026 03:21:31 +0000</pubDate>
      <link>https://dev.to/fathe__r/-cgc</link>
      <guid>https://dev.to/fathe__r/-cgc</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/fathe__r/your-env-file-is-a-mess-and-how-to-fix-it-in-2-seconds-309m" class="crayons-story__hidden-navigation-link"&gt;Your .env file is a mess (and how to fix it in 2 seconds)&lt;/a&gt;


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

          &lt;a href="/fathe__r" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4055977%2F1e4ed3ae-6a89-45cd-8c9b-8ad17fd2975e.jpg" alt="fathe__r profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/fathe__r" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Isaac
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Isaac
                
              
              &lt;div id="story-author-preview-content-4277469" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/fathe__r" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4055977%2F1e4ed3ae-6a89-45cd-8c9b-8ad17fd2975e.jpg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Isaac&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/fathe__r/your-env-file-is-a-mess-and-how-to-fix-it-in-2-seconds-309m" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 31&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/fathe__r/your-env-file-is-a-mess-and-how-to-fix-it-in-2-seconds-309m" id="article-link-4277469"&gt;
          Your .env file is a mess (and how to fix it in 2 seconds)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/typescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;typescript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/fathe__r/your-env-file-is-a-mess-and-how-to-fix-it-in-2-seconds-309m" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/fathe__r/your-env-file-is-a-mess-and-how-to-fix-it-in-2-seconds-309m#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

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

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Your .env file is a mess (and how to fix it in 2 seconds)</title>
      <dc:creator>Isaac</dc:creator>
      <pubDate>Fri, 31 Jul 2026 05:55:45 +0000</pubDate>
      <link>https://dev.to/fathe__r/your-env-file-is-a-mess-and-how-to-fix-it-in-2-seconds-309m</link>
      <guid>https://dev.to/fathe__r/your-env-file-is-a-mess-and-how-to-fix-it-in-2-seconds-309m</guid>
      <description>&lt;p&gt;If you've been working on a project for a while, your environment variables are probably a mess.&lt;/p&gt;

&lt;p&gt;We've all been there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your &lt;code&gt;.env&lt;/code&gt; file has 30 variables, but half of them are left over from features you deleted last year.&lt;/li&gt;
&lt;li&gt;A new developer joins the team, clones the repo, and spends half a day trying to figure out why the app won't boot because the &lt;code&gt;.env.example&lt;/code&gt; file hasn't been updated since 2023.&lt;/li&gt;
&lt;li&gt;Worse: someone accidentally put a sensitive API key behind a &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; or &lt;code&gt;VITE_&lt;/code&gt; prefix, and you just shipped it to the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Environment variables are the backbone of modern web apps, but we manage them like it's 2014—by manually copying and pasting keys between files and hoping we didn't forget anything.&lt;/p&gt;

&lt;p&gt;I got tired of this, so I built a tool to fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet Pookoo 🦉
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pookoo&lt;/strong&gt; is a zero-config, static analysis CLI that audits, documents, and manages your environment variables automatically.&lt;/p&gt;

&lt;p&gt;You don't need to install it to try it. Just run this in the root of any JS/TS project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx pookoo scan &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In less than a second, Pookoo reads your source code (using AST parsing, so it &lt;strong&gt;never executes your code&lt;/strong&gt; and &lt;strong&gt;never sends data anywhere&lt;/strong&gt;) and gives you a report of everything that is broken.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6nolcciuhfwghvaipe6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6nolcciuhfwghvaipe6x.png" alt="Pookoo Scan CLI Output" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What it detects:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dead variables&lt;/strong&gt;: Keys in your &lt;code&gt;.env&lt;/code&gt; that are never actually referenced in your source code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Undocumented variables&lt;/strong&gt;: Keys used in your source code (&lt;code&gt;process.env.SOMETHING&lt;/code&gt;) that are missing from your &lt;code&gt;.env.example&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret leaks&lt;/strong&gt;: Sensitive keys (like &lt;code&gt;STRIPE_SECRET_KEY&lt;/code&gt;) that are accidentally exposed via client-side prefixes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inconsistent defaults&lt;/strong&gt;: The same variable using different hardcoded fallbacks across different files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Generating &lt;code&gt;.env.example&lt;/code&gt; automatically
&lt;/h2&gt;

&lt;p&gt;The best part about Pookoo knowing exactly what variables your code uses? It can write your &lt;code&gt;.env.example&lt;/code&gt; for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx pookoo init &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command scans your codebase, finds every single environment variable you are actually using, and generates a perfectly categorized &lt;code&gt;.env.example&lt;/code&gt; file. It even adds comments telling you exactly which files are using which variables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncnqnkx426p36vi6nok3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncnqnkx426p36vi6nok3.png" alt="Pookoo generated env.example" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating Documentation
&lt;/h2&gt;

&lt;p&gt;If you work on a larger team, you can generate a beautiful markdown reference of your entire configuration surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx pookoo docs &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;CONFIG_DOCS.md&lt;/code&gt; file with a table of every variable, its scope (Client vs Server), and where it's used. &lt;/p&gt;

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

&lt;p&gt;Pookoo supports &lt;strong&gt;Next.js&lt;/strong&gt;, &lt;strong&gt;Vite&lt;/strong&gt;, &lt;strong&gt;Create React App&lt;/strong&gt;, &lt;strong&gt;Node.js&lt;/strong&gt;, and generic TypeScript projects out of the box.&lt;/p&gt;

&lt;p&gt;If you want to keep your project clean permanently, you can even add it to your CI/CD pipeline to fail the build if someone forgets to document a new variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pookoo scan &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--fail-on&lt;/span&gt; HIGH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd love for you to try it on one of your messy projects and let me know how many dead variables it finds! &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;npm&lt;/strong&gt;: &lt;a href="https://www.npmjs.com/package/pookoo" rel="noopener noreferrer"&gt;npmjs.com/package/pookoo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⭐️ &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/CreatorLZ/pookoo" rel="noopener noreferrer"&gt;github.com/CreatorLZ/pookoo&lt;/a&gt; (Drop a star if you find it useful!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know what you think in the comments! 👇&lt;/p&gt;

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