<?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: Christo</title>
    <description>The latest articles on DEV Community by Christo (@booyaka101).</description>
    <link>https://dev.to/booyaka101</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%2F4036239%2Fe7c21b84-c259-4a55-84e8-ec5f50485afb.png</url>
      <title>DEV Community: Christo</title>
      <link>https://dev.to/booyaka101</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/booyaka101"/>
    <language>en</language>
    <item>
      <title>Reading a Rust crate's capabilities out of its compiled symbols</title>
      <dc:creator>Christo</dc:creator>
      <pubDate>Sun, 19 Jul 2026 13:05:51 +0000</pubDate>
      <link>https://dev.to/booyaka101/reading-a-rust-crates-capabilities-out-of-its-compiled-symbols-58pb</link>
      <guid>https://dev.to/booyaka101/reading-a-rust-crates-capabilities-out-of-its-compiled-symbols-58pb</guid>
      <description>&lt;p&gt;Cargo tells you &lt;code&gt;once_cell 1.19.0 → 1.20.2&lt;/code&gt;. It doesn't tell you whether the new&lt;br&gt;
version started opening a socket. A dependency bump is a trust decision, and the&lt;br&gt;
lockfile diff gives you almost nothing to make it with.&lt;/p&gt;

&lt;p&gt;I kept chewing on this after xz. Not the specific attack so much as its shape: the&lt;br&gt;
change that mattered was invisible at the level anyone actually reviews. Nobody&lt;br&gt;
reads the full diff of every transitive dep on every patch bump. So I wanted a&lt;br&gt;
cheaper question answered automatically on the PR: did this bump change what the&lt;br&gt;
crate can &lt;em&gt;do&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;You can get further than I expected just by reading what the compiler emits.&lt;/p&gt;
&lt;h2&gt;
  
  
  v0 symbols are legible
&lt;/h2&gt;

&lt;p&gt;Rust's &lt;code&gt;v0&lt;/code&gt; symbol mangling demangles back to real paths. Build a crate, look at&lt;br&gt;
the rlib:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;RUSTFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-C symbol-mangling-version=v0"&lt;/span&gt; cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
nm target/release/deps/libnetcap-&lt;span class="k"&gt;*&lt;/span&gt;.rlib &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $NF}'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'^_R'&lt;/span&gt; | rustfilt | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a crate that opens a socket and spawns a process, some of what falls out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;process&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TcpStream&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket_addr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ToSocketAddrs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;to_socket_addrs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My first cut used &lt;code&gt;nm --defined-only&lt;/code&gt;, and it found nothing. Took me longer than&lt;br&gt;
I'd like to admit to see why. The capability you care about isn't in the crate's&lt;br&gt;
&lt;em&gt;own&lt;/em&gt; functions. It's in the calls it makes &lt;em&gt;out&lt;/em&gt; to std, and those are the&lt;br&gt;
&lt;strong&gt;undefined&lt;/strong&gt; symbols in the object files. &lt;code&gt;--defined-only&lt;/code&gt; throws away the whole&lt;br&gt;
signal. Once you keep the undefined refs, a crate that reaches for &lt;code&gt;TcpStream&lt;/code&gt;&lt;br&gt;
carries an undefined symbol that says so.&lt;/p&gt;

&lt;p&gt;Two nice properties fall out of v0 specifically. Demangling drops the per-crate&lt;br&gt;
disambiguator hash, so the same symbol is byte-identical across two versions and&lt;br&gt;
you can just &lt;code&gt;comm -13&lt;/code&gt; the old and new sets. And forcing&lt;br&gt;
&lt;code&gt;-C symbol-mangling-version=v0&lt;/code&gt; means you don't care what the toolchain default is;&lt;br&gt;
the audit reproduces anywhere.&lt;/p&gt;

&lt;p&gt;So the core is boring in a good way: for each crate whose version moved in&lt;br&gt;
&lt;code&gt;Cargo.lock&lt;/code&gt;, build old and new, diff the demangled symbols, and look at what got&lt;br&gt;
added.&lt;/p&gt;
&lt;h2&gt;
  
  
  The build.rs blind spot
&lt;/h2&gt;

&lt;p&gt;Then I hit the thing that actually keeps me up, and it's the xz-shaped one. A build&lt;br&gt;
script compiles to a &lt;em&gt;separate&lt;/em&gt; binary that Cargo runs at build time. None of that&lt;br&gt;
lands in the crate's rlib. A dependency can add a &lt;code&gt;build.rs&lt;/code&gt; that decodes a blob&lt;br&gt;
and drops it in &lt;code&gt;~/.cargo/bin&lt;/code&gt;, and the symbol diff stays perfectly quiet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// build.rs — runs on your machine, at compile time&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cargo:rerun-if-changed=build.rs"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;process&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sh"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-c"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;// symbol analysis never sees this&lt;/span&gt;
        &lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only way to catch it is to read the source, not the artifact. One Rust detail&lt;br&gt;
made that easier than I feared: Cargo extracts a crate into&lt;br&gt;
&lt;code&gt;~/.cargo/registry/src/.../&amp;lt;crate&amp;gt;-&amp;lt;version&amp;gt;/&lt;/code&gt; during &lt;em&gt;resolution&lt;/em&gt;, before it&lt;br&gt;
compiles anything. So you can diff a new or changed &lt;code&gt;build.rs&lt;/code&gt;, catch a flip to&lt;br&gt;
&lt;code&gt;proc-macro = true&lt;/code&gt;, or a fresh &lt;code&gt;links = "…"&lt;/code&gt;, even for proc-macro-only or bin-only&lt;br&gt;
crates that never build as a lib. Those are exactly the crates the symbol lane&lt;br&gt;
can't touch.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where it breaks: generics
&lt;/h2&gt;

&lt;p&gt;I don't want to oversell it, because it has a real ceiling and the ceiling is&lt;br&gt;
monomorphization. A generic function only produces a symbol once it's&lt;br&gt;
instantiated. If a crate does this and never calls it with a concrete type itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ToSocketAddrs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TcpStream&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;TcpStream&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// monomorphized in the *caller's* crate, not here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then &lt;code&gt;TcpStream::connect&lt;/code&gt; shows up in &lt;em&gt;your&lt;/em&gt; rlib, not the dependency's. Capability&lt;br&gt;
reached purely through uninstantiated generics is invisible to this. It's a triage&lt;br&gt;
signal — "the surface changed, go look" — not a sandbox and definitely not a proof.&lt;br&gt;
I'd rather say that plainly than pretend otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it something you'd leave on
&lt;/h2&gt;

&lt;p&gt;A scanner that re-flags every bump gets muted within a week, so the part I put the&lt;br&gt;
most thought into is a sign-off ledger. You approve a &lt;code&gt;(crate, version)&lt;/code&gt; once, and&lt;br&gt;
after that it only re-alarms on the &lt;em&gt;unreviewed&lt;/em&gt; delta. That's what lets you set&lt;br&gt;
&lt;code&gt;fail-on: high&lt;/code&gt; and block merges without drowning in noise. The one rule I was&lt;br&gt;
careful about: a sign-off suppresses only the capability lanes. A newly-published&lt;br&gt;
RustSec advisory or a changed crates.io publisher is never hidden by an old&lt;br&gt;
approval, because those are new facts, not the thing you reviewed.&lt;/p&gt;

&lt;p&gt;It comes out as one comment per PR:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🟠 &lt;strong&gt;HIGH&lt;/strong&gt; — &lt;code&gt;smallvec&lt;/code&gt; has a known security advisory (RUSTSEC-2021-0003)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  If you want to poke at it
&lt;/h2&gt;

&lt;p&gt;It's a composite GitHub Action, MIT, no server, runs entirely in your CI. There's&lt;br&gt;
a live demo PR where it catches a real advisory:&lt;br&gt;
&lt;a href="https://github.com/Booyaka101/rust-symbol-audit-demo/pull/1" rel="noopener noreferrer"&gt;https://github.com/Booyaka101/rust-symbol-audit-demo/pull/1&lt;/a&gt;, and the repo is&lt;br&gt;
&lt;a href="https://github.com/Booyaka101/rust-symbol-audit" rel="noopener noreferrer"&gt;https://github.com/Booyaka101/rust-symbol-audit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The part I'm least sure about is the false-positive ergonomics — the allow-list and&lt;br&gt;
ledger design — so if you have opinions there, that's the feedback I actually want.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I built this with heavy help from an AI coding assistant (Claude), and&lt;br&gt;
the first draft of this post came out of that too. I've reworked it and I stand&lt;br&gt;
behind every claim here — the design decisions and the opinions are mine. Flagging&lt;br&gt;
it because that's the honest thing to do.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>rust</category>
      <category>security</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I fire 50 research prompts before bed and read the answers with coffee — free, on Gemini's background tier</title>
      <dc:creator>Christo</dc:creator>
      <pubDate>Sun, 19 Jul 2026 10:34:18 +0000</pubDate>
      <link>https://dev.to/booyaka101/i-fire-50-research-prompts-before-bed-and-read-the-answers-with-coffee-free-on-geminis-3641</link>
      <guid>https://dev.to/booyaka101/i-fire-50-research-prompts-before-bed-and-read-the-answers-with-coffee-free-on-geminis-3641</guid>
      <description>&lt;p&gt;Something slipped into the Gemini API that I don't think enough people clocked: you can run a prompt &lt;em&gt;in the background&lt;/em&gt;. You send it, get an interaction ID back in under a second, and the model keeps working server-side while you close your laptop. No held-open connection, no keeping a tab alive.&lt;/p&gt;

&lt;p&gt;And on the free tier — &lt;code&gt;gemini-3.1-flash-lite&lt;/code&gt;, no billing account, no card — it costs nothing.&lt;/p&gt;

&lt;p&gt;That combination is quietly great for one specific thing: &lt;strong&gt;research you don't need answered &lt;em&gt;right now&lt;/em&gt;.&lt;/strong&gt; "Summarize this week in AI." "Compare the 2026 EU AI Act timeline against the UK's." "Is anyone actually regretting moving off Postgres?" Questions where you'd happily wait a few minutes, if waiting meant you didn't have to sit there babysitting a terminal.&lt;/p&gt;

&lt;p&gt;The problem is the background API hands you the &lt;em&gt;hard&lt;/em&gt; half. You get an ID back and now it's yours to manage: remember which prompt it belonged to, poll it, and — the sharp edge — the free tier &lt;strong&gt;throws the result away after 24 hours&lt;/strong&gt; if nothing collects it. Lose the ID or forget to check, and the work is just gone.&lt;/p&gt;

&lt;p&gt;So I built the boring client half and called it &lt;strong&gt;gemcatch&lt;/strong&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 gemcatch research &lt;span class="s2"&gt;"compare the 2026 EU AI Act timeline against the UK approach"&lt;/span&gt;
&lt;span class="c"&gt;# Task 8f3a1c04 submitted. Run: gemcatch get 8f3a1c04 when ready.&lt;/span&gt;

&lt;span class="c"&gt;# ...close the laptop, come back whenever...&lt;/span&gt;
npx gemcatch get 8f3a1c04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It drops every interaction ID into a local SQLite file right next to the prompt that made it, so you never lose the thread. The moment a task finishes, the answer is cached on disk — &lt;code&gt;gemcatch get&lt;/code&gt; reads it straight from there, no network, even after the 24-hour server-side expiry.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I actually use: batch
&lt;/h2&gt;

&lt;p&gt;One prompt at a time is fine. The reason gemcatch earned a permanent spot in my shell is the batch command. I keep a plain text file of questions and fire the whole thing at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;questions.txt
what changed &lt;span class="k"&gt;in &lt;/span&gt;the EU AI Act &lt;span class="k"&gt;in &lt;/span&gt;the last month
state of React Server Components adoption &lt;span class="k"&gt;in &lt;/span&gt;production
is anyone regretting moving off Postgres to a managed KV

&lt;span class="nv"&gt;$ &lt;/span&gt;gemcatch batch questions.txt
Batch batch-7f3a1c: submitted 3 task&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;gemcatch daemon &lt;span class="nt"&gt;--exit-when-idle&lt;/span&gt;                  &lt;span class="c"&gt;# poll until they're all collected&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;gemcatch &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt; batch-7f3a1c &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; answers.md   &lt;span class="c"&gt;# every answer, one markdown file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I run that before bed. By morning &lt;code&gt;answers.md&lt;/code&gt; is waiting — every prompt and its answer in a single file, ready to read with coffee. And when I want the takeaways instead of the raw pile, &lt;code&gt;gemcatch digest --tag batch-7f3a1c&lt;/code&gt; runs them back through the model once and hands me one synthesized summary. It's the closest thing I've got to a research intern who works the night shift for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The daemon exists for exactly one reason
&lt;/h2&gt;

&lt;p&gt;That 24-hour expiry is the whole gotcha. Caching a result forever is easy; &lt;em&gt;noticing&lt;/em&gt; it landed is the hard part. &lt;code&gt;gemcatch daemon&lt;/code&gt; just polls whatever's in flight on a loop and writes each result to SQLite the instant it completes — so nothing gets dropped because you forgot to check back. Kill it, reboot, pull the power; everything it already collected is on disk, and it picks up where it left off.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's deliberately boring
&lt;/h2&gt;

&lt;p&gt;No dashboard, no account, no telemetry. It's a small pile of Node, a SQLite file, and a handful of commands — &lt;code&gt;research&lt;/code&gt;, &lt;code&gt;batch&lt;/code&gt;, &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;watch&lt;/code&gt;, &lt;code&gt;daemon&lt;/code&gt;, &lt;code&gt;export&lt;/code&gt;, &lt;code&gt;digest&lt;/code&gt;. Every outbound call is rate-limited and retried so a wide batch stays inside the free tier's limits instead of blowing straight through them. MIT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx gemcatch research &lt;span class="s2"&gt;"your question"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;strong&gt;&lt;a href="https://github.com/Booyaka101/gemcatch" rel="noopener noreferrer"&gt;github.com/Booyaka101/gemcatch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If "ask now, read later, pay nothing" fits how you actually work, I'd love to know what you'd point it at — and what would make the batch flow better. Scheduled/recurring runs are the thing I'm eyeing next.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>node</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I stopped trusting "Bun vs Node" blog posts and asked X what devs actually say this week</title>
      <dc:creator>Christo</dc:creator>
      <pubDate>Sun, 19 Jul 2026 08:31:26 +0000</pubDate>
      <link>https://dev.to/booyaka101/i-stopped-trusting-bun-vs-node-blog-posts-and-asked-x-what-devs-actually-say-this-week-26ni</link>
      <guid>https://dev.to/booyaka101/i-stopped-trusting-bun-vs-node-blog-posts-and-asked-x-what-devs-actually-say-this-week-26ni</guid>
      <description>&lt;p&gt;The top Google hit for "bun vs node" on my screen was written in early 2024. It benchmarks a Bun that's shipped a dozen releases since. That's how most of us pick tools: reading a snapshot of an argument that already moved on.&lt;/p&gt;

&lt;p&gt;The argument that's actually current — the one with real production war stories — is happening on X this week. It's just not indexed anywhere you'd think to look.&lt;/p&gt;

&lt;p&gt;So one weekend I built a CLI that asks it directly. It hands your question to Grok 4.5's live X search and makes every claim cite a real post, with a recency tag on each. It's called &lt;strong&gt;GrokScope&lt;/strong&gt;, and you can watch it work in about five seconds — no API key, no signup:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  What it found on Bun vs Node (and the bit I didn't expect)
&lt;/h2&gt;

&lt;p&gt;I ran &lt;code&gt;grokscope ask "bun vs node in 2026"&lt;/code&gt;. The thing that stuck with me: the "Bun is going to kill Node" energy is basically gone. That framing feels like 2023. What's landing now is more skeptical and a lot more specific.&lt;/p&gt;

&lt;p&gt;The optimist case is still real, and people are putting numbers on it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Moving from Node to Bun was a game changer for me, it cut process usage across all my services by over 20%."&lt;br&gt;
— &lt;a href="https://x.com/bartdominiak/status/2076939953653621055" rel="noopener noreferrer"&gt;@bartdominiak&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the pushback has gotten sharper than the usual benchmark flexing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Bun has faster http methods? An AI agent can create a .node addon to out perf Bun trivially. No need to switch runtimes."&lt;br&gt;
— &lt;a href="https://x.com/jdalton/status/2077411139361644675" rel="noopener noreferrer"&gt;@jdalton&lt;/a&gt;, who knows these internals better than most of us&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And some of the folklore is cracking — one re-benchmark had &lt;strong&gt;Deno beating Bun&lt;/strong&gt; on raw throughput (133k vs 122k req/s), which is not the story anyone was telling twelve months ago.&lt;/p&gt;

&lt;p&gt;Where it nets out, and this matches my gut after reading through it: it's not a war anymore. Reach for &lt;strong&gt;Bun&lt;/strong&gt; on greenfield projects, CLIs, scripts, and edge/serverless, where the speed and the batteries-included DX actually pay off and you don't mind the bleeding edge. Stay on &lt;strong&gt;Node&lt;/strong&gt; when boring reliability, native addons, or a large existing codebase are the real constraint. Plenty of teams just run both. Bun's Zig-to-Rust rewrite reads less like a flex and more like it trying to grow up.&lt;/p&gt;

&lt;p&gt;The part I like: none of that is me editorializing. It's ~30 days of people who ship this stuff, and I can click through to every source and disagree if I want to.&lt;/p&gt;

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

&lt;p&gt;One call to xAI's Responses API with Grok 4.5's &lt;code&gt;x_search&lt;/code&gt; tool switched on. Grok runs the searches, reasons over the posts, and returns text with inline citations; GrokScope renders those as numbered clickable links and decodes each post's date straight from its snowflake ID. No scraping, no X API keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grokscope ask &lt;span class="s2"&gt;"is anyone actually using RSC in prod?"&lt;/span&gt;
grokscope compare drizzle prisma
grokscope trending &lt;span class="nt"&gt;--topics&lt;/span&gt; &lt;span class="s2"&gt;"rust,typescript,go"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's &lt;code&gt;--json&lt;/code&gt; for CI and &lt;code&gt;--md&lt;/code&gt; if you want to drop a report into a doc — I generated the pull-quotes above with it.&lt;/p&gt;

&lt;p&gt;Responses are also &lt;strong&gt;cached locally&lt;/strong&gt; now, so an identical repeat query — or re-rendering the same result as &lt;code&gt;--json&lt;/code&gt; instead of &lt;code&gt;--md&lt;/code&gt; — costs nothing, and &lt;code&gt;grokscope history&lt;/code&gt; pages back through past runs offline. &lt;code&gt;--fresh&lt;/code&gt; forces a live refetch when you want the newest posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest part
&lt;/h2&gt;

&lt;p&gt;Live queries are bring-your-own xAI key, roughly &lt;strong&gt;$0.15–0.30 each the first time&lt;/strong&gt; (the search pulls dozens of posts into context; it prints the exact cost after every run, so nothing sneaks up on you) — repeats come free from the local cache. The &lt;code&gt;demo&lt;/code&gt; is free forever because it just replays a recorded run. It's a weekend side project — MIT, and definitely still has rough edges.&lt;/p&gt;

&lt;p&gt;Repo's here: &lt;strong&gt;&lt;a href="https://github.com/Booyaka101/grokscope" rel="noopener noreferrer"&gt;github.com/Booyaka101/grokscope&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you run it, point it at an argument you actually care about and tell me whether the verdict matches your gut. The cases where it's &lt;em&gt;wrong&lt;/em&gt; are the ones I most want to hear about.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
