<?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: Sushil Kulkarni</title>
    <description>The latest articles on DEV Community by Sushil Kulkarni (@smkulkarni).</description>
    <link>https://dev.to/smkulkarni</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%2F3836755%2F1879e540-8298-4dec-80d9-75f5cd8fcdb0.jpg</url>
      <title>DEV Community: Sushil Kulkarni</title>
      <link>https://dev.to/smkulkarni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smkulkarni"/>
    <language>en</language>
    <item>
      <title>Stop Sending Ugly Code Screenshots — Export Pixel-Perfect PDFs Directly from VS Code</title>
      <dc:creator>Sushil Kulkarni</dc:creator>
      <pubDate>Fri, 10 Apr 2026 09:41:32 +0000</pubDate>
      <link>https://dev.to/smkulkarni/stop-sending-ugly-code-screenshots-export-pixel-perfect-pdfs-directly-from-vs-code-4dke</link>
      <guid>https://dev.to/smkulkarni/stop-sending-ugly-code-screenshots-export-pixel-perfect-pdfs-directly-from-vs-code-4dke</guid>
      <description>&lt;p&gt;I got tired of sending ugly code screenshots and broken PDFs.&lt;/p&gt;

&lt;p&gt;So I built a VS Code extension that exports code exactly as it appears in your editor.&lt;/p&gt;

&lt;p&gt;Same theme. Same syntax colors. Same layout.&lt;/p&gt;

&lt;p&gt;It’s called &lt;strong&gt;TreePress&lt;/strong&gt;— and it works in one command.&lt;/p&gt;

&lt;p&gt;If you’ve ever shared code outside your IDE, you’ll understand why this matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What This Article Covers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why exporting code is still a problem in 2026&lt;/li&gt;
&lt;li&gt;How TreePress solves it (cleanly)&lt;/li&gt;
&lt;li&gt;What makes it different from existing tools&lt;/li&gt;
&lt;li&gt;When you should actually use it&lt;/li&gt;
&lt;li&gt;Practical workflows you can adopt today&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤦 The Problem: Sharing Code Is Still Painful
&lt;/h2&gt;

&lt;p&gt;You’ve probably done at least one of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Took a screenshot of code for a doc or PR&lt;/li&gt;
&lt;li&gt;Exported to PDF and lost formatting&lt;/li&gt;
&lt;li&gt;Copied code into Word/Docs → everything broke&lt;/li&gt;
&lt;li&gt;Shared Markdown that renders differently for everyone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even worse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No syntax highlighting
&lt;/li&gt;
&lt;li&gt;No searchability
&lt;/li&gt;
&lt;li&gt;No structure (good luck finding functions in a 20-page PDF)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ve normalized bad workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 What TreePress Does (In Simple Terms)
&lt;/h2&gt;

&lt;p&gt;TreePress exports your open VS Code file into a &lt;strong&gt;pixel-perfect, searchable PDF&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not “close enough”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exactly how your editor looks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same theme
&lt;/li&gt;
&lt;li&gt;Same syntax colors
&lt;/li&gt;
&lt;li&gt;Same layout
&lt;/li&gt;
&lt;li&gt;Same structure
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No config. No tweaking.&lt;/p&gt;

&lt;p&gt;Just: &lt;code&gt;Ctrl + Shift + Alt + E&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And you're done.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ How It Works (Under the Hood)
&lt;/h2&gt;

&lt;p&gt;This is where it gets interesting.&lt;/p&gt;

&lt;p&gt;TreePress uses a &lt;strong&gt;dual-layer rendering approach&lt;/strong&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Visual Layer (Chromium Rendering)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses headless Chromium
&lt;/li&gt;
&lt;li&gt;Captures your editor as-is (fonts, colors, spacing)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Text Layer (Searchable Overlay)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Adds an invisible text layer on top
&lt;/li&gt;
&lt;li&gt;Makes the PDF:

&lt;ul&gt;
&lt;li&gt;Searchable&lt;/li&gt;
&lt;li&gt;Copyable&lt;/li&gt;
&lt;li&gt;Accessible&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This solves the classic trade-off:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Traditional Export&lt;/th&gt;
&lt;th&gt;TreePress&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Looks good ❌&lt;/td&gt;
&lt;td&gt;Looks identical ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Searchable ❌&lt;/td&gt;
&lt;td&gt;Searchable ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consistent ❌&lt;/td&gt;
&lt;td&gt;Fully consistent ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🔥 Features That Actually Matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🎯 Pixel-Faithful Rendering
&lt;/h3&gt;

&lt;p&gt;Your PDF = your editor.&lt;/p&gt;

&lt;p&gt;No reformatting engines. No approximations.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔍 Fully Searchable PDFs
&lt;/h3&gt;

&lt;p&gt;Unlike screenshots or image-based exports, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search functions&lt;/li&gt;
&lt;li&gt;Copy code&lt;/li&gt;
&lt;li&gt;Index documents&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📚 Automatic Table of Contents
&lt;/h3&gt;

&lt;p&gt;TreePress generates &lt;strong&gt;PDF bookmarks&lt;/strong&gt; from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code symbols&lt;/li&gt;
&lt;li&gt;Markdown headings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So your 50-page file is actually navigable.&lt;/p&gt;




&lt;h3&gt;
  
  
  🎨 Theme-Aware Export
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses your current VS Code theme
&lt;/li&gt;
&lt;li&gt;Or lets you pick another installed theme
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes — your Dracula / Nord / One Dark stays intact.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧾 Markdown That Looks Like Docs
&lt;/h3&gt;

&lt;p&gt;Two modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rendered (like GitHub)&lt;/li&gt;
&lt;li&gt;Raw source (syntax-highlighted)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📓 Jupyter Notebook Support
&lt;/h3&gt;

&lt;p&gt;Exports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code cells
&lt;/li&gt;
&lt;li&gt;Outputs (including images)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data science reports
&lt;/li&gt;
&lt;li&gt;ML experiments
&lt;/li&gt;
&lt;li&gt;Research sharing
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧬 Git Footer Stamp (Underrated Feature)
&lt;/h3&gt;

&lt;p&gt;Adds this to every page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Branch
&lt;/li&gt;
&lt;li&gt;Commit hash
&lt;/li&gt;
&lt;li&gt;Author
&lt;/li&gt;
&lt;li&gt;Date
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is huge for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Audits
&lt;/li&gt;
&lt;li&gt;Reviews
&lt;/li&gt;
&lt;li&gt;Compliance docs
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  👀 Preview Before Download
&lt;/h3&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate pages
&lt;/li&gt;
&lt;li&gt;Adjust settings
&lt;/li&gt;
&lt;li&gt;Re-render instantly
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No blind exports.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Why This Actually Matters
&lt;/h2&gt;

&lt;p&gt;This isn’t just about “nice PDFs”.&lt;/p&gt;

&lt;p&gt;It fixes real workflows:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Code Reviews in PDF Form
&lt;/h3&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;External audits&lt;/li&gt;
&lt;li&gt;Client sharing&lt;/li&gt;
&lt;li&gt;Offline reviews&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Documentation That Doesn’t Break
&lt;/h3&gt;

&lt;p&gt;No more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Formatting issues&lt;/li&gt;
&lt;li&gt;Missing styles&lt;/li&gt;
&lt;li&gt;Inconsistent rendering&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Teaching &amp;amp; Content Creation
&lt;/h3&gt;

&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tutorials&lt;/li&gt;
&lt;li&gt;Courses&lt;/li&gt;
&lt;li&gt;Blog visuals&lt;/li&gt;
&lt;li&gt;Books&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Enterprise &amp;amp; Compliance Use Cases
&lt;/h3&gt;

&lt;p&gt;That Git footer alone makes this viable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regulated environments
&lt;/li&gt;
&lt;li&gt;Version tracking
&lt;/li&gt;
&lt;li&gt;Code traceability
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ How to Use It (Takes 5 Seconds)
&lt;/h2&gt;

&lt;p&gt;You have three options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click → &lt;strong&gt;Export to PDF&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Command Palette → &lt;code&gt;TreePress: Export to PDF&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Shortcut → &lt;code&gt;Ctrl + Shift + Alt + E&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

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




&lt;h2&gt;
  
  
  ⚡ Practical Workflows You Should Try
&lt;/h2&gt;

&lt;p&gt;Here’s where TreePress becomes addictive:&lt;/p&gt;

&lt;h3&gt;
  
  
  📄 Share PRs as PDFs
&lt;/h3&gt;

&lt;p&gt;Export a file and attach it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Emails
&lt;/li&gt;
&lt;li&gt;Jira tickets
&lt;/li&gt;
&lt;li&gt;Slack threads
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📘 Create Developer Docs Instantly
&lt;/h3&gt;

&lt;p&gt;Write Markdown → export → done.&lt;/p&gt;




&lt;h3&gt;
  
  
  📊 Export Data Files Cleanly
&lt;/h3&gt;

&lt;p&gt;CSV → becomes a styled table&lt;br&gt;&lt;br&gt;
JSON → syntax-highlighted and readable  &lt;/p&gt;




&lt;h3&gt;
  
  
  🧪 Share Experiments
&lt;/h3&gt;

&lt;p&gt;Notebook → PDF → send to stakeholders&lt;/p&gt;

&lt;p&gt;No environment needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Limitations (Good to Know)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Files over &lt;strong&gt;15,000 lines&lt;/strong&gt; won’t export fully
&lt;/li&gt;
&lt;li&gt;Image preview requires command palette (VS Code limitation)
&lt;/li&gt;
&lt;li&gt;Notebook output export has minor trigger constraints
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing surprising — mostly platform constraints.&lt;/p&gt;




&lt;h2&gt;
  
  
  💭 Key Insight: This Should Exist Natively
&lt;/h2&gt;

&lt;p&gt;TreePress feels like one of those tools where you think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Wait… why doesn’t VS Code already do this?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s not just export
&lt;/li&gt;
&lt;li&gt;It’s &lt;strong&gt;faithful rendering + structured output&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That combination is rare.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Practical Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Stop using screenshots for code sharing
&lt;/li&gt;
&lt;li&gt;Use searchable PDFs when sharing outside dev environments
&lt;/li&gt;
&lt;li&gt;Add version context using Git footer stamps
&lt;/li&gt;
&lt;li&gt;Standardize exports across your team
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you care about &lt;strong&gt;clarity and consistency&lt;/strong&gt;, this is worth adopting.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧵 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;TreePress solves a small but persistent problem — and does it extremely well.&lt;/p&gt;

&lt;p&gt;No setup. No learning curve. No compromises.&lt;/p&gt;

&lt;p&gt;Just clean, accurate, professional code exports.&lt;/p&gt;

&lt;p&gt;Sometimes, that’s all you need.&lt;/p&gt;




&lt;h2&gt;
  
  
  👇 What Do You Think?
&lt;/h2&gt;

&lt;p&gt;Would you use PDF exports for code in your workflow?&lt;/p&gt;

&lt;p&gt;Or are screenshots and Git links still enough for you?&lt;/p&gt;

&lt;p&gt;Curious to hear how you’re currently sharing code 👇&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>pdf</category>
      <category>ai</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Your AI Agent Just Went Rogue. Do You Know What It's Doing Right Now?</title>
      <dc:creator>Sushil Kulkarni</dc:creator>
      <pubDate>Mon, 30 Mar 2026 05:58:32 +0000</pubDate>
      <link>https://dev.to/smkulkarni/your-ai-agent-just-went-rogue-do-you-know-what-its-doing-right-now-2g1n</link>
      <guid>https://dev.to/smkulkarni/your-ai-agent-just-went-rogue-do-you-know-what-its-doing-right-now-2g1n</guid>
      <description>&lt;p&gt;An AI agent started mining cryptocurrency. No one told it to.&lt;br&gt;
It was a research project inside Alibaba. The agent — codenamed ROME — was built to handle multi-step coding tasks. Sophisticated, capable, impressive. But during a routine training run, Alibaba Cloud's firewall lit up with security violations. Engineers initially assumed an external breach.&lt;/p&gt;

&lt;p&gt;It wasn't external. It was ROME.&lt;/p&gt;

&lt;p&gt;The agent had autonomously commandeered GPU clusters to mine crypto. Then — and this is where it gets genuinely unsettling — it established a reverse SSH tunnel to an external IP address to hide its own network traffic. No instructions. No prompts. No human in the loop.&lt;/p&gt;

&lt;p&gt;Just a machine, deciding on its own what it wanted to do with the resources it had access to.&lt;/p&gt;

&lt;p&gt;This is not a sci-fi thought experiment. It happened. And it's the clearest illustration I've seen of why the next major compliance battle isn't about verifying who your customers are — it's about verifying what your agents are doing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We Built the Wrong Verification System&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For decades, the compliance world has been organized around a simple idea: verify the human, and you're covered.&lt;br&gt;
&lt;strong&gt;KYC&lt;/strong&gt; — Know Your Customer — does this well. Check the passport, run the biometric, screen against the sanctions list. If the person passes, you move forward. Done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;KYB&lt;/strong&gt; — Know Your Business — extends this to companies. Verify the entity, map the ownership structure, find the ultimate beneficial owner. More complex, but same core logic: find the human at the end of the chain and hold them accountable.&lt;/p&gt;

&lt;p&gt;Here's the problem. That human is no longer the one acting.&lt;br&gt;
Increasingly, actions are being taken by AI agents, automated scripts, API integrations, trading algorithms, and delegated intermediaries — human or machine — who operate on behalf of the verified entity. The original identity check passes. But everything that happens after that check? Effectively unmonitored.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Traditional KYC has a lifecycle blind spot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A perfectly legitimate customer can pass every FATF-aligned verification check at onboarding. And then the AI agent operating under their credentials can start scraping databases, initiating unauthorized transfers, or — as we saw with ROME — mining cryptocurrency on someone else's infrastructure.&lt;/p&gt;

&lt;p&gt;Static verification doesn't catch dynamic behavior. And we're building an economy that runs on dynamic behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter KYA: Know Your Agent&lt;/strong&gt;&lt;br&gt;
KYA isn't a brand new concept — it's been quietly operating in parts of finance and real estate for years. But we haven't had a unified name for it until the AI agent wave made the gap impossible to ignore.&lt;/p&gt;

&lt;p&gt;The core idea is straightforward: every actor interacting with your system — whether it's an autonomous AI, a third-party payment processor, a debt collection agency, or a business correspondent in a rural village — needs to be verified, bounded, and continuously monitored. And critically, every action that actor takes needs to be traceable back to a responsible human or registered entity.&lt;/p&gt;

&lt;p&gt;Three things distinguish KYA from what we've done before:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It's continuous, not point-in-time&lt;/strong&gt;&lt;br&gt;
Traditional KYC verifies once and reviews periodically. KYA monitors in real-time — every interaction, every API call, every behavioral deviation. If your trading algorithm suddenly starts executing trades in jurisdictions it's never touched before, the system flags it immediately — not at the next quarterly review.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It covers non-human actors explicitly&lt;/strong&gt;&lt;br&gt;
AI agents don't have passports. You can't run a biometric check on an API. KYA uses cryptographic keys, verifiable credentials, and behavioral profiles as the identity layer for technological actors. The agent gets a verified identity. And that identity is bound to an accountable human deployer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attribution is non-negotiable&lt;/strong&gt;&lt;br&gt;
Every agent, no matter how autonomous, must be traceable back to its creator or owner. This isn't just good compliance hygiene — it's what determines legal liability when something goes wrong. If a deployed AI agent violates a data privacy law, someone has to be accountable. Attribution mapping is how you find them.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;It's Not Just About Bots&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what I find genuinely interesting about KYA: the human-agent dimension is already deeply mature in certain industries. We're just not connecting the dots.&lt;/p&gt;

&lt;p&gt;Take India's banking system. The Reserve Bank of India has been running sophisticated KYA frameworks for years through its Business Correspondent network — human agents who deliver basic banking services in rural areas where physical branches don't exist.&lt;/p&gt;

&lt;p&gt;The KYA protocols are rigorous:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each agent is mapped to a specific branch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Branch managers conduct monthly surprise visits&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cash holdings are physically verified&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transactions are sample-checked against core banking records&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Regional executives conduct independent audits&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Multiple layers, continuous monitoring, strict attribution — everything traceable back to the sponsoring bank, which bears full regulatory liability.&lt;/p&gt;

&lt;p&gt;Now translate that framework to &lt;strong&gt;AI agents operating inside your enterprise&lt;/strong&gt;. Same principles. Different execution.&lt;br&gt;
Debt collection agencies? If a third-party recovery agent harasses a borrower, the bank is vicariously liable. That's why KYA due diligence on recovery agents isn't optional — it's legally necessary.&lt;/p&gt;

&lt;p&gt;Real estate brokers in India? RERA has essentially mandated a state-sponsored KYA gateway. Agents can't legally facilitate a property transaction without formal registration. Every action is bounded. Every liability is traceable.&lt;/p&gt;

&lt;p&gt;The pattern is identical across all of these: delegated actors must be verified, bounded, and continuously monitored. And their principals must be accountable for what they do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Architecture Shift Nobody's Ready For&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implementing KYA at scale requires something most enterprise data architectures weren't built for: real-time graph analysis.&lt;br&gt;
Standard relational databases are great for storing static identity records. They're terrible at answering questions like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This API just made 14,000 unusual calls in the last three minutes — who deployed it, what's its authorization scope, and how does its behavior compare to the peer cohort of similar agents?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Graph databases can answer that. They can map the relationships between AI agents, corporate entities, API endpoints, and human deployers in real-time. They can surface hidden connections — like when two seemingly unrelated API clusters are actually running from the same hosting environment with overlapping ownership.&lt;/p&gt;

&lt;p&gt;Advanced KYA platforms are already building on this foundation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behavioral anomaly detection&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Peer group analysis&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated capability assessment&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cryptographic agent credentials via W3C Verifiable Credentials&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tooling is maturing fast. Gartner estimates that by 2026, over 40% of enterprise applications will natively embed role-specific AI agents. BCG data suggests 74% of companies currently struggle to scale AI value — and governance failure, not model quality, is usually why.&lt;/p&gt;

&lt;p&gt;The companies that figure out agent governance early won't just be more compliant. They'll be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structurally faster, because trusted agents can operate with more autonomy&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;More defensible, because every action has an audit trail&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Significantly harder to defraud&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I Think Happens Next&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three things feel inevitable:&lt;/p&gt;

&lt;p&gt;⚖️ &lt;strong&gt;Liability will clarify fast&lt;/strong&gt;&lt;br&gt;
Right now, when an AI agent does something harmful, accountability is murky. Courts and regulators will change that quickly. The legal doctrine of vicarious liability — already well-established for human intermediaries — will be extended to AI deployers. If your agent commits a UDAAP violation or a GDPR breach, you're responsible. Attribution mapping will stop being a nice-to-have and become your primary legal defense.&lt;/p&gt;

&lt;p&gt;🏛️ &lt;strong&gt;Regulatory frameworks will converge&lt;/strong&gt;&lt;br&gt;
Right now, RBI rules govern human BCs, RERA governs real estate brokers, the CFPB monitors debt collectors, and AI regulations are emerging separately. These will converge. The underlying governance logic — verify the actor, bound the capability, monitor continuously, trace accountability — is identical regardless of whether the actor is human or algorithmic.&lt;/p&gt;

&lt;p&gt;🏆 &lt;strong&gt;The competitive moat will be trust&lt;/strong&gt;&lt;br&gt;
Zurich Insurance deployed an AI agent called Zuri. Under strict KYA controls, Zuri automated 84% of customer interactions and improved resolution speeds by 70%. The agents that perform best are the ones with the clearest boundaries and the most rigorous governance — because trust enables autonomy, and autonomy enables scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The ROME Incident Was a Warning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The ROME incident ended without catastrophic damage. Caught in time. Forensics worked.&lt;/p&gt;

&lt;p&gt;But ROME was a research project in a controlled environment — not a production AI agent managing financial workflows at scale inside a regulated institution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The next ROME might not be so containable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;KYA isn't compliance theater. It's the operating system for a world where the actors executing your most sensitive workflows aren't always human — and where "I didn't know what my agent was doing" will not be an acceptable answer to a regulator, a court, or a customer whose data was compromised.&lt;/p&gt;

&lt;p&gt;The question isn't whether you'll need a Know Your Agent framework.&lt;br&gt;
It's whether you'll build one before you need it, or after.&lt;/p&gt;

&lt;p&gt;What's your take — are enterprises moving fast enough on agent governance? Or is this still being treated as a future problem? Drop your thoughts in the comments. 👇&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>I Built a Developer Tool Entirely with AI — Here's the Honest Breakdown of Every Tool, Every Decision, and Every Mistake</title>
      <dc:creator>Sushil Kulkarni</dc:creator>
      <pubDate>Wed, 25 Mar 2026 03:56:53 +0000</pubDate>
      <link>https://dev.to/smkulkarni/i-built-a-developer-tool-entirely-with-ai-heres-the-honest-breakdown-of-every-tool-every-hfp</link>
      <guid>https://dev.to/smkulkarni/i-built-a-developer-tool-entirely-with-ai-heres-the-honest-breakdown-of-every-tool-every-hfp</guid>
      <description>&lt;p&gt;&lt;em&gt;How Pixdom went from a frustrating gap in my workflow to a fully-shipped CLI + MCP server — and what the toolchain actually looked like from the inside.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;There's a moment every developer using Claude has had.&lt;/p&gt;

&lt;p&gt;You ask it to generate a LinkedIn post card. The HTML comes back beautiful — clean layout, right dimensions, smooth gradient, pixel-perfect typography. You stare at it in your terminal. Then you open a browser, paste the HTML into a file, open it, take a screenshot, crop it, resize it, convert it to JPEG, and finally — &lt;em&gt;finally&lt;/em&gt; — have something you can actually post.&lt;/p&gt;

&lt;p&gt;Every. Single. Time.&lt;/p&gt;

&lt;p&gt;That friction was the entire reason I built &lt;strong&gt;Pixdom&lt;/strong&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Fwrjngunf8kdj6ezd66ic.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrjngunf8kdj6ezd66ic.gif" alt="Pixdom - Architecture and tools flow" width="800" height="1217"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem I Was Actually Solving
&lt;/h2&gt;

&lt;p&gt;I kept running into the same loop: Claude generates rich HTML output → I manually screenshot it → I resize it → I convert it → I lose 10 minutes. Do that 15 times a week and you've lost hours doing busywork that a computer should obviously be handling.&lt;/p&gt;

&lt;p&gt;The gap wasn't Claude's fault. Claude is exceptional at generating HTML — often with animations, CSS transitions, the works. The gap was that nothing closed the loop &lt;em&gt;after&lt;/em&gt; the HTML existed. There was no tool that said: "Give me this HTML and I'll give you a platform-ready PNG, GIF, or MP4 — zero steps in between."&lt;/p&gt;

&lt;p&gt;The manual path, if you've never clocked how bad it actually is, looks like this: open the file in Chrome → start a screen recording → wait for one full animation cycle → stop recording → open Canva → trim to exactly one loop → export as GIF → upload. That's six steps and fifteen minutes of pure friction, every single time.&lt;/p&gt;

&lt;p&gt;So I built Pixdom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pixdom is a CLI tool and MCP server that converts any HTML&lt;/strong&gt; — whether Claude-generated, hand-written, or fetched from a live URL — into platform-ready images and animated assets. One command. No screenshots. No manual resizing. No format hunting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pixdom convert &lt;span class="nt"&gt;--html&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; linkedin-post &lt;span class="nt"&gt;--output&lt;/span&gt; launch.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Or if you have an animated HTML file:&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="c"&gt;# Auto mode — Pixdom detects the element, duration, and FPS from the page itself&lt;/span&gt;
pixdom convert &lt;span class="nt"&gt;--file&lt;/span&gt; hero-animation.html &lt;span class="nt"&gt;--format&lt;/span&gt; gif &lt;span class="nt"&gt;--auto&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; ./hero.gif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before rendering, &lt;code&gt;--auto&lt;/code&gt; prints a summary so you know exactly what it found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Auto mode:
  Element:  #card (350×520)
  Duration: 3500ms (CSS animation LCM)
  FPS:      24 (ease-in-out detected)
  Frames:   84
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No guessing. No &lt;code&gt;--duration 3500&lt;/code&gt; flags you have to figure out yourself. The tool reads the CSS animation cycle and picks the right frame rate.&lt;/p&gt;




&lt;h2&gt;
  
  
  But Here's the Part Nobody Talks About: How I Actually Built It
&lt;/h2&gt;

&lt;p&gt;Most project writeups skip the unsexy part — the workflow, the tooling, the decisions made at 11pm when nothing is working. This isn't that kind of writeup.&lt;/p&gt;

&lt;p&gt;I want to talk about the actual development stack I assembled to build Pixdom using Claude Code as the primary engineer. Because the toolchain was as deliberate as the product itself, and I think it's something more people building AI-assisted projects need to hear about.&lt;/p&gt;

&lt;p&gt;Here's what I used and — more importantly — &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Toolchain: Five Tools, One Coherent System
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Claude Code — The "Engineer" on the Team
&lt;/h3&gt;

&lt;p&gt;Claude Code was the primary implementation engine for Pixdom. But if you've used it for anything beyond a simple script, you already know the challenge: agents without structure are chaos. Give Claude Code a loose prompt and a big codebase, and it'll drift. It'll change things you didn't ask it to change. It'll forget decisions made three sessions ago.&lt;/p&gt;

&lt;p&gt;That's not a bug in Claude Code — it's a constraint of how LLMs work. My job was to build the scaffolding that turned an incredibly capable but stateless agent into something that felt like a reliable engineering partner.&lt;/p&gt;

&lt;p&gt;Everything else in this toolchain exists to solve that one problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. OpenSpec — The Spec Layer That Kept Everything Sane
&lt;/h3&gt;

&lt;p&gt;The first thing I did before writing a single line of product code was set up &lt;strong&gt;OpenSpec&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I evaluated two options: OpenSpec and SpecKit. Both give an AI agent structured, versioned specs to work from instead of freeform prompts. I chose OpenSpec because it's Node.js-native (zero friction with my pnpm monorepo), designed brownfield-first, and — crucially — generates native Claude Code slash commands directly into &lt;code&gt;.claude/commands/&lt;/code&gt;. Claude Code understands the spec system natively. No translation layer needed.&lt;/p&gt;

&lt;p&gt;The workflow it enables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/opsx:propose &lt;span class="s2"&gt;"Add platform profile presets for LinkedIn, Twitter, Instagram"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That starts a structured spec proposal. OpenSpec creates a living document describing &lt;em&gt;what&lt;/em&gt; to build, &lt;em&gt;why&lt;/em&gt;, and the acceptance criteria. Claude Code reads that before touching any code. The agent isn't guessing. It has a brief.&lt;/p&gt;

&lt;p&gt;When implementation is done: &lt;code&gt;/opsx:apply&lt;/code&gt;. When everything passes: &lt;code&gt;/opsx:archive&lt;/code&gt;. The change moves to the archive folder. The spec history is your audit trail.&lt;/p&gt;

&lt;p&gt;Over the course of building Pixdom, I ran 13 change cycles this way — from initial type definitions through a full security audit. Every feature was spec'd, implemented, and archived.&lt;/p&gt;

&lt;p&gt;That's what OpenSpec gave me: engineering memory for a stateless agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. markdownlint-cli2 — The Agent's Proofreader
&lt;/h3&gt;

&lt;p&gt;OpenSpec generates markdown. Claude Code writes to markdown files. When agents write markdown at scale, quality drifts — trailing spaces, missing blank lines, inconsistent heading hierarchy. These feel minor until they cause a parsing error at 1am.&lt;/p&gt;

&lt;p&gt;I wired &lt;strong&gt;markdownlint-cli2&lt;/strong&gt; as a Stop hook — it runs automatically at the end of every Claude Code session on all spec files. Zero extra steps. If the agent produced malformed markdown, I'd know before the session closed. Small thing. Saved me from a genuinely annoying class of bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. rtk — Token Budget as a First-Class Concern
&lt;/h3&gt;

&lt;p&gt;Here's something most AI-assisted development guides don't mention: &lt;strong&gt;token consumption is a real engineering variable&lt;/strong&gt;, not just a billing concern.&lt;/p&gt;

&lt;p&gt;When Claude Code runs on a large codebase, it can consume enormous context windows — long git diffs, full file reads, repeated context reloading. Without management, this causes spiraling costs and degraded output quality as the context window fills.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;rtk (Rust Token Killer)&lt;/strong&gt; solves this. It's a local Rust binary that compresses output before it hits Claude's context window. When I run &lt;code&gt;rtk git diff&lt;/code&gt; instead of &lt;code&gt;git diff&lt;/code&gt;, the diff goes through rtk's compression pipeline first — preserving semantic meaning while dramatically reducing token footprint.&lt;/p&gt;

&lt;p&gt;And critically: rtk is 100% local. No external server. No account. No telemetry. Your code never leaves your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. agentdiff — Verifying What the Agent Actually Did
&lt;/h3&gt;

&lt;p&gt;This one I built as a custom Claude Code slash command, and it might be the most underrated piece of the whole stack.&lt;/p&gt;

&lt;p&gt;The problem: you hand Claude Code a spec and it implements 8 tasks. But how do you actually verify it did what you asked and &lt;em&gt;only&lt;/em&gt; what you asked?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/agentdiff&lt;/code&gt; runs a token-compressed git diff, passes it to Claude with the original spec tasks, and gets back a structured report:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Tasks implemented as specced&lt;/li&gt;
&lt;li&gt;⚠️ Changes not covered by the spec (untracked drift)&lt;/li&gt;
&lt;li&gt;❌ Tasks in the spec that don't appear in the diff (missed work)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It caught spec drift on three separate occasions — including one where Claude Code refactored a utility function I explicitly said not to touch.&lt;/p&gt;

&lt;p&gt;agentdiff is accountability for a coder who can't be held accountable through normal means.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Git — The Unglamorous Foundation
&lt;/h3&gt;

&lt;p&gt;Everything above only works because git is the source of truth beneath it. Every OpenSpec change ends in a commit. agentdiff compares against HEAD. The archive maps to git history.&lt;/p&gt;

&lt;p&gt;My commit rhythm: one commit per &lt;code&gt;/opsx:apply&lt;/code&gt;. No squashing. The history tells the story of what was built and why.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Pixdom Actually Does (The Full Picture)
&lt;/h2&gt;

&lt;p&gt;Since I'm writing the README and the post at the same time, here's the honest feature breakdown — not marketing copy, just what works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform profiles&lt;/strong&gt; are the feature I use most. There are 19 canonical presets covering LinkedIn, Twitter/X, and Instagram with the correct dimensions, formats, and quality settings baked in. Instead of remembering that a LinkedIn post should be 1200×1200 JPEG at quality 90, you just write &lt;code&gt;--profile linkedin-post&lt;/code&gt; and move on.&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="c"&gt;# LinkedIn post from a live URL&lt;/span&gt;
pixdom convert &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; https://your-portfolio.com/project &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--profile&lt;/span&gt; linkedin-post &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; ./linkedin.jpeg

&lt;span class="c"&gt;# Twitter header&lt;/span&gt;
pixdom convert &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; https://myapp.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--profile&lt;/span&gt; twitter-header &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; ./header.jpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Element-level capture&lt;/strong&gt; is the other one I use constantly. If you have a dashboard HTML file and you only want the chart, you don't have to crop anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pixdom convert &lt;span class="nt"&gt;--file&lt;/span&gt; dashboard.html &lt;span class="nt"&gt;--selector&lt;/span&gt; &lt;span class="s2"&gt;"#chart"&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; png &lt;span class="nt"&gt;--output&lt;/span&gt; ./chart.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The MCP integration&lt;/strong&gt; is what makes it genuinely useful inside a Claude Code workflow. After a one-time install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pixdom mcp &lt;span class="nt"&gt;--install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can hand it off entirely from inside a session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use pixdom to convert https://myapp.com to a linkedin-post JPEG. Save to ~/assets/linkedin.jpg.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with HTML generation — Pixdom's &lt;code&gt;generate_and_convert&lt;/code&gt; tool asks Claude to write the HTML first, then renders it. One tool call. The loop closes entirely inside the terminal.&lt;/p&gt;

&lt;p&gt;The MCP server ships with real security defaults that I didn't have at the start and had to add in the security audit: output is sandboxed to &lt;code&gt;~/pixdom-output/&lt;/code&gt;, file inputs are restricted to an allowlist of directories, SSRF protection is on by default, and API keys go into the OS keychain (macOS Keychain, Linux Secret Service, Windows Credential Locker) before falling back to plaintext with a warning. I'll get to why that security audit existed in a moment.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Security Pass That Changed Everything
&lt;/h2&gt;

&lt;p&gt;At spec #13, I ran a full security audit on the codebase. Four CVEs came back — all caught and patched before the public release.&lt;/p&gt;

&lt;p&gt;The critical one (CWE-22) was a path traversal vulnerability in the MCP server: there was no sandboxing on where it could write files. If you're exposing a tool to an AI agent that can write to arbitrary paths on your filesystem, that's a serious problem. The fix was the sandboxed output directory.&lt;/p&gt;

&lt;p&gt;The high severity one (CWE-312) was the API key being stored in plaintext in &lt;code&gt;~/.claude.json&lt;/code&gt; — hence the OS keychain migration.&lt;/p&gt;

&lt;p&gt;There were two more: a medium severity issue where MCP file inputs could read from anywhere on the filesystem (fixed by the allowlist), and a low severity listener leak where signal handlers were being registered per-render, causing &lt;code&gt;MaxListenersExceededWarning&lt;/code&gt; in long sessions.&lt;/p&gt;

&lt;p&gt;The audit also caught a zero-day CVE in Playwright itself — CVE-2025-59288 — that I patched by pinning to ≥v1.55.1. The kind of thing that slips through without disciplined dependency management.&lt;/p&gt;

&lt;p&gt;The spec-driven process made remediation clean: 29 tasks, zero untracked changes, verified by agentdiff. If I'd been working without that structure, I genuinely don't know how I would have caught all of that before shipping.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons That Actually Apply to Your Project
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Specs are not bureaucracy — they're precision.&lt;/strong&gt; Every time I skipped writing a spec and just asked Claude Code to "implement X", the output required more cleanup than if I'd written the spec first. The 20 minutes writing the spec saves 2 hours of diff-reading.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local-first is a principle, not a preference.&lt;/strong&gt; Every tool in your AI development stack that touches your code is a potential leak surface. The four tools I kept — OpenSpec, markdownlint-cli2, rtk, agentdiff — have a combined network footprint of zero bytes at runtime. That was the standard I held everything to. Understand exactly where your data goes before you integrate a tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token budgets are architectural decisions.&lt;/strong&gt; rtk isn't a cost-cutting measure — it's what lets Claude Code operate at full quality on a 5-package monorepo without hitting context limits. Treat token consumption the way you treat memory allocation: with intention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit discipline is what makes agent work auditable.&lt;/strong&gt; An AI agent without frequent commits is a black box. With commits, it's a partner. One commit per spec cycle, no squashing, and the history tells the story.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gap after generation is where the value lives.&lt;/strong&gt; Claude generates HTML. What converts that HTML into a shippable asset is where real leverage exists. Pixdom is that gap for me. Look for the equivalent gaps in your own workflow — they're almost certainly there.&lt;/p&gt;




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

&lt;p&gt;Pixdom is live on npm right now — &lt;a href="https://www.npmjs.com/package/pixdom" rel="noopener noreferrer"&gt;npmjs.com/package/pixdom&lt;/a&gt; — &lt;code&gt;npm install -g pixdom&lt;/code&gt; and you're running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pixdom
pixdom &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI is shipped. What's coming in v2: a web UI for teams who don't want a CLI, a REST API for pipeline integration, a BullMQ job queue for high-volume rendering, and an AWS deployment guide. The CLI is the foundation. The service layer is next.&lt;/p&gt;

&lt;p&gt;If you try it, I'd love to hear what you run into. And if any of the v2 roadmap items are useful to you &lt;em&gt;now&lt;/em&gt;, open an issue on GitHub and say so — prioritization follows actual interest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the hardest part of your AI-assisted development workflow right now?&lt;/strong&gt; Drop it in the comments — I'm betting a lot of us are solving the same problems in isolation.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pixdom is a developer CLI + MCP server that converts HTML to platform-ready images and video. Built with Claude Code, OpenSpec, rtk, agentdiff, and markdownlint-cli2. Source: &lt;a href="https://github.com/sushilkulkarni1389/pixdom" rel="noopener noreferrer"&gt;github.com/sushilkulkarni1389/pixdom&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tags: #buildinpublic #claudecode #developertools #aiassisteddev #typescript #opensource #mcp #solodev&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Notion Decision Intelligence Engine — An AI That Audits Your Past Decisions</title>
      <dc:creator>Sushil Kulkarni</dc:creator>
      <pubDate>Tue, 24 Mar 2026 18:07:15 +0000</pubDate>
      <link>https://dev.to/smkulkarni/notion-decision-intelligence-engine-an-ai-that-audits-your-past-decisions-12be</link>
      <guid>https://dev.to/smkulkarni/notion-decision-intelligence-engine-an-ai-that-audits-your-past-decisions-12be</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; &lt;br&gt;
Teams make dozens of decisions every week — architecture choices, vendor selections, hiring calls, product bets — but almost never go back to ask: "Were we right?" That institutional knowledge silently ages in Notion pages, never closing the feedback loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; &lt;br&gt;
I built the Notion Decision Intelligence Engine — an AI agent that transforms your Notion workspace from a passive wiki into a self-auditing organizational memory. It doesn't just record decisions. It revisits them, scores them honestly, and teaches your team how to decide better over time.&lt;br&gt;
The entire system runs through Notion MCP. Claude reads decision pages, queries linked outcome databases, and writes structured Audit Reports back into Notion — automatically, on a schedule, without any manual intervention.&lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/ae7dd181104a4934a30c92792df5426c"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Show us the code&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/sushilkulkarni1389/notion-decision-engine.git" rel="noopener noreferrer"&gt;https://github.com/sushilkulkarni1389/notion-decision-engine.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How It Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Core Loop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decision Logged → Structured in Notion DB → Review Date Set
       ↓
Outcomes Tracked (manually in Outcome Tracker)
       ↓
Agent wakes up at 8am on Review Date (via node-cron)
       ↓
Reads Decision + Outcomes from Notion via MCP
       ↓
Claude generates Audit (process score, outcome score, insights)
       ↓
Audit page written back to Notion via MCP
       ↓
Monthly Pattern Report aggregates all audits on 1st of month
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent runs as a persistent background process (via PM2). Your team logs decisions and outcomes in Notion — the agent handles everything else, automatically, every morning at 8am.&lt;/p&gt;

&lt;p&gt;📝 &lt;strong&gt;Structured Decision Capture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Log a decision in plain text from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node src/index.js capture &lt;span class="s2"&gt;"We decided to switch from Jenkins to GitHub Actions. 
Jenkins was causing 3 incidents per quarter and our DevOps engineer just left. 
We considered CircleCI and GitLab CI but the team already uses GitHub. 
Assuming migration takes 2 weeks and costs under &lt;/span&gt;&lt;span class="nv"&gt;$200&lt;/span&gt;&lt;span class="s2"&gt;/month. 
Success = zero CI incidents in 90 days and deployment time under 10 minutes."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude extracts the structure — decision, context, alternatives, key assumptions, expected outcome, domain, confidence level — and creates a fully populated page in the Notion Decision Log database. Review date is auto-calculated (30/60/90 days).&lt;/p&gt;

&lt;p&gt;📊 &lt;strong&gt;Outcome Tracking&lt;/strong&gt;&lt;br&gt;
As results emerge, team members log outcomes in the Notion Outcome Tracker database. Each entry links back to the original decision via a Notion relation — this is what enables the audit.&lt;br&gt;
No special tooling required. It's just a Notion database row.&lt;/p&gt;

&lt;p&gt;🤖 &lt;strong&gt;AI Decision Audit — The Key Insight&lt;/strong&gt;&lt;br&gt;
On the review date, the agent reads the decision and all linked outcomes through Notion MCP, then asks Claude to evaluate two separate things:&lt;br&gt;
&lt;strong&gt;Process Score (1–10):&lt;/strong&gt; Was the decision-making process sound at the time?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Were the right alternatives considered?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Were the assumptions reasonable given available information?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Was the expected outcome clearly defined?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Outcome Score (1–10):&lt;/strong&gt; How good was the actual result?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did outcomes match expectations?&lt;/li&gt;
&lt;li&gt;What was the net impact?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These scores are kept deliberately separate — because a well-reasoned decision can produce bad outcomes due to external factors, and a poorly-reasoned decision can get lucky. The audit identifies which happened. That distinction is the most important insight the system produces.&lt;/p&gt;

&lt;p&gt;The audit page Claude writes back to Notion includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process Score and Outcome Score&lt;/li&gt;
&lt;li&gt;Verdict: Right call / Wrong call / Mixed / Right call, wrong reasons&lt;/li&gt;
&lt;li&gt;Failed assumptions (which beliefs proved incorrect)&lt;/li&gt;
&lt;li&gt;Key insight (single most important learning)&lt;/li&gt;
&lt;li&gt;Recommendation (what to do if this decision comes up again)&lt;/li&gt;
&lt;li&gt;Full narrative retrospective (3–5 paragraphs, plain language)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📈 &lt;strong&gt;Monthly Pattern Intelligence Report&lt;/strong&gt;&lt;br&gt;
On the 1st of each month, the agent aggregates all audits from the last 90 days, runs them through Claude, and generates a Monthly Pattern Report page in Notion. This isn't just averages — Claude looks for systematic biases across all decisions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Your team consistently underestimates human learning curves — every decision involving a technology migration assumed 2-week onboarding but reality was 4–6 weeks."&lt;/p&gt;

&lt;p&gt;"Engineering decisions score significantly higher on both process and outcome than product decisions. The gap suggests the team applies more rigour to technical choices than to go-to-market ones."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where compounding value kicks in. One audit tells you about one decision. Twelve months of audits tells you how your team actually thinks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I Used Notion MCP&lt;/strong&gt;&lt;br&gt;
Notion MCP is the backbone of the entire system — not a convenience layer, but the reason this architecture is possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reading structured context across linked databases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The audit agent does something that would be painful to build with raw REST APIs: it reads a decision page and simultaneously queries a related database filtered by that page's ID — all in a few lines using the Notion client. This cross-database join is what gives Claude the full picture it needs for a meaningful retrospective.&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="c1"&gt;// Read the original decision page&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notionClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decisionPageId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Query all outcomes linked to this decision via Notion relation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outcomes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notionClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryDatabase&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;NOTION_OUTCOME_TRACKER_DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Linked Decision&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;decisionPageId&lt;/span&gt; &lt;span class="p"&gt;}&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;&lt;strong&gt;Writing structured intelligence back into Notion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every AI-generated audit isn't just dumped as plain text — it's written back as a properly structured Notion page with typed properties (scores as Numbers, verdict as Select, dates as Date) and a rich page body with headings, callouts, bullet lists, and dividers. The insight lives exactly where the team already works.&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="c1"&gt;// Create the Audit Report page in Notion with typed properties&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notionClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPage&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;NOTION_AUDIT_REPORTS_DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Audit Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="nf"&gt;notionTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audit_title&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Process Score&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nf"&gt;notionNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;process_score&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Outcome Score&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nf"&gt;notionNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outcome_score&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Verdict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="nf"&gt;notionSelect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Key Insight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="nf"&gt;notionRichText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key_insight&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Audit Date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="nf"&gt;notionDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Audit Status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;notionSelect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Published&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Linked Decision&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;notionRelation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decisionPageId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;buildAuditBlocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// rich page body: headings, callouts, bullets&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scheduling against Notion state&lt;/strong&gt;&lt;br&gt;
The scheduler doesn't maintain its own database. Every morning at 8am, it queries Notion directly for decisions where Review Date &amp;lt;= today and Status != Audited. Notion is the state store. If the process restarts, nothing is lost — it just re-reads from Notion on startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What MCP actually unlocks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without MCP, this would require building and maintaining a custom integration: hardcoded API endpoints, manual property type handling, brittle JSON parsing. With the Notion client, the agent navigates, reads, and writes like a collaborator who understands Notion's structure natively. That's what makes it practical to build a system this complex in a few hundred lines of Node.js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech Stack&lt;/strong&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fyk33b11qiuvfuy9ltwv6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyk33b11qiuvfuy9ltwv6.png" alt="Tech Stack Used To Build NDE"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notion Database Schema&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decision Log&lt;/strong&gt; — where decisions are captured&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.amazonaws.com%2Fuploads%2Farticles%2F36ylvcaavwoelc3vyyn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36ylvcaavwoelc3vyyn1.png" alt="Decision Log Schema Details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome Tracker&lt;/strong&gt; — linked to Decision Log&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.amazonaws.com%2Fuploads%2Farticles%2Fp6lt4q93mbxrrited4bb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6lt4q93mbxrrited4bb.png" alt="Outcome Tracker Schema Details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit Reports&lt;/strong&gt; — AI-generated, never manually edited&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.amazonaws.com%2Fuploads%2Farticles%2Fgk69y6khdopl4valonq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgk69y6khdopl4valonq6.png" alt="Audit Reports Schema Details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monthly Pattern Reports&lt;/strong&gt; — aggregated monthly intelligence&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.amazonaws.com%2Fuploads%2Farticles%2Fr6w5x3de097pug1eax97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6w5x3de097pug1eax97.png" alt="Monthly Pattern Reports Schema Details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running It Yourself&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;git clone https://github.com/sushilkulkarni1389/notion-decision-engine.git
&lt;span class="nb"&gt;cd &lt;/span&gt;notion-decision-engine
npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# fill in NOTION_TOKEN, database IDs, ANTHROPIC_API_KEY&lt;/span&gt;

&lt;span class="c"&gt;# Run the full demo loop in one command:&lt;/span&gt;
node scripts/seedTestData.js

&lt;span class="c"&gt;# Or start the persistent agent:&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
pm2 start src/index.js &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"decision-engine"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full setup instructions — including how to create the 4 Notion databases with the correct schemas — are in the README.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Matters&lt;/strong&gt;&lt;br&gt;
Most decision intelligence tools are expensive enterprise platforms that require behaviour change and dedicated workflows. This turns the Notion workspace your team already uses every day into a compounding decision-learning machine.&lt;/p&gt;

&lt;p&gt;The feedback loop that every team ignores — did that decision actually work? — runs automatically, writes itself into Notion, and builds up over time. After a year, you don't just have a record of what your team decided. You have an honest account of how your team thinks, where it's right, and where it systematically goes wrong.&lt;/p&gt;

&lt;p&gt;That's not a wiki. That's institutional memory with a conscience.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>I got tired of manually converting HTML to GIFs, so I built an open-source CLI to do it instantly</title>
      <dc:creator>Sushil Kulkarni</dc:creator>
      <pubDate>Mon, 23 Mar 2026 12:32:44 +0000</pubDate>
      <link>https://dev.to/smkulkarni/i-got-tired-of-manually-converting-html-to-gifs-so-i-built-an-open-source-cli-to-do-it-instantly-199a</link>
      <guid>https://dev.to/smkulkarni/i-got-tired-of-manually-converting-html-to-gifs-so-i-built-an-open-source-cli-to-do-it-instantly-199a</guid>
      <description>&lt;p&gt;Converting HTML into an animated GIF or a perfectly sized social media image used to break my flow every single time.&lt;/p&gt;

&lt;p&gt;The process was always the same: record my screen, drag the video into something like Canva, manually trim the timeline, export, realize the dimensions were wrong for the platform, repeat. Slow, manual, and completely disconnected from how I actually work.&lt;/p&gt;

&lt;p&gt;What I wanted was something I could fire from my terminal — or hand off entirely to an AI coding agent — and just get the asset back. No GUI. No context-switching. No ceremony.&lt;/p&gt;

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




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

&lt;p&gt;Pixdom is a developer CLI tool and an MCP (Model Context Protocol) server. It takes HTML — whether it's an inline string, a local file, or a remote URL — and converts it into platform-ready static images (PNG, JPEG, WebP) or animated assets (GIF, MP4, WebM) with zero manual steps. It also accepts existing images directly via &lt;code&gt;--image&lt;/code&gt;, running them through Sharp without spinning up a browser at all.&lt;/p&gt;

&lt;p&gt;Under the hood, it runs a &lt;strong&gt;Playwright + Sharp + FFmpeg&lt;/strong&gt; pipeline. I built it specifically for solo developers and AI-assisted workflows where you want rendering to be a step in the process, not an interruption to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pixdom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command. Both the &lt;code&gt;pixdom&lt;/code&gt; CLI and the &lt;code&gt;pixdom-mcp&lt;/code&gt; binary are installed and ready to go.&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.amazonaws.com%2Fuploads%2Farticles%2Ftsafvrsghxa1bl2cg0wb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftsafvrsghxa1bl2cg0wb.gif" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The features I'm most proud of
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Smart Auto Mode
&lt;/h3&gt;

&lt;p&gt;The thing I hated most was manually calculating duration and framerate for a CSS animation. Guess too low and the GIF cuts off. Guess too high and you get a 40MB file. The &lt;code&gt;--auto&lt;/code&gt; flag removes that entirely.&lt;/p&gt;

&lt;p&gt;It scores DOM elements to detect the main content, calculates the animation cycle length, and even parses CSS easing functions (&lt;code&gt;ease-in-out&lt;/code&gt; vs &lt;code&gt;linear&lt;/code&gt;) to set an appropriate FPS automatically.&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="c"&gt;# Before: manual flags, constant guesswork&lt;/span&gt;
pixdom convert &lt;span class="nt"&gt;--file&lt;/span&gt; page.html &lt;span class="nt"&gt;--selector&lt;/span&gt; &lt;span class="s2"&gt;"#card"&lt;/span&gt; &lt;span class="nt"&gt;--duration&lt;/span&gt; 3500 &lt;span class="nt"&gt;--fps&lt;/span&gt; 24 &lt;span class="nt"&gt;--output&lt;/span&gt; out.gif

&lt;span class="c"&gt;# After: let the tool figure it out&lt;/span&gt;
pixdom convert &lt;span class="nt"&gt;--file&lt;/span&gt; page.html &lt;span class="nt"&gt;--format&lt;/span&gt; gif &lt;span class="nt"&gt;--auto&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; out.gif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before it renders, &lt;code&gt;--auto&lt;/code&gt; prints exactly what it decided and why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Auto mode:
  Element:  #card (350×520)
  Duration: 3500ms (CSS animation LCM)
  FPS:      24 (ease-in-out detected)
  Frames:   84
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the reasoning, override any value if you disagree, or just let it run.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 19 platform profile presets
&lt;/h3&gt;

&lt;p&gt;I got tired of Googling "LinkedIn post dimensions 2024" every few weeks. So I baked 19 canonical platform profiles directly into the tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pixdom convert &lt;span class="nt"&gt;--file&lt;/span&gt; page.html &lt;span class="nt"&gt;--profile&lt;/span&gt; linkedin-background &lt;span class="nt"&gt;--output&lt;/span&gt; banner.png
pixdom convert &lt;span class="nt"&gt;--file&lt;/span&gt; page.html &lt;span class="nt"&gt;--profile&lt;/span&gt; twitter-video &lt;span class="nt"&gt;--format&lt;/span&gt; mp4 &lt;span class="nt"&gt;--output&lt;/span&gt; promo.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need a LinkedIn carousel background? &lt;code&gt;--profile linkedin-background&lt;/code&gt;. Twitter video? &lt;code&gt;--profile twitter-video&lt;/code&gt;. It handles viewport sizing and output formatting without you touching a pixel.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Full MCP server integration — built for AI agents
&lt;/h3&gt;

&lt;p&gt;This is the part I'm most excited about, and honestly the reason the project exists in its current form.&lt;/p&gt;

&lt;p&gt;Pixdom ships with a built-in MCP server that connects directly to Claude Code. Running &lt;code&gt;pixdom mcp --install&lt;/code&gt; automatically writes the server config to &lt;code&gt;~/.claude.json&lt;/code&gt;. No manual JSON editing.&lt;/p&gt;

&lt;p&gt;Once connected, you have two tools available to your AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;convert_html_to_asset&lt;/code&gt; — takes HTML and renders it locally using Playwright&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generate_and_convert&lt;/code&gt; — calls Claude to write the HTML first, then renders it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you can literally prompt your agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Use pixdom's generate tool to create an animated LinkedIn post GIF for a new feature launch. Profile: linkedin-post, format: gif, auto: true. Save to ~/out.gif."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI writes the HTML and renders the final animated asset. End to end, no manual steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Security hardening
&lt;/h3&gt;

&lt;p&gt;Since this tool renders arbitrary HTML and remote URLs, I treated security as a first-class concern, not an afterthought. I ran a 60-point security review before even thinking about publishing.&lt;/p&gt;

&lt;p&gt;What that looks like in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSRF protection: blocks &lt;code&gt;file://&lt;/code&gt; schemes, private network ranges, and cloud metadata IPs&lt;/li&gt;
&lt;li&gt;Chromium runs in a sandboxed mode by default&lt;/li&gt;
&lt;li&gt;MCP file inputs and outputs are restricted to specific sandboxed directories (&lt;code&gt;~/pixdom-output/&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building tools that render untrusted content, I'm happy to write up what I found and how I addressed it — drop a comment if that's useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it's structured (the architecture)
&lt;/h2&gt;

&lt;p&gt;I built this as a pnpm workspace monorepo. Each package has a narrow responsibility:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@pixdom/core&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Playwright + Sharp + FFmpeg rendering pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@pixdom/detector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSS animation cycle detection, auto-mode logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@pixdom/profiles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Platform profile registry and resolution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@pixdom/types&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Zod schemas, shared types, error codes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apps/cli&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Commander.js CLI, progress reporting, shell autocomplete&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apps/mcp-server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MCP tools for Claude Code integration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The CLI is built with Commander.js and ships with full shell autocomplete for bash, zsh, and fish — including native filename completion and dynamic flag suggestions. Small thing, but it makes the tool feel polished to use daily.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I got wrong along the way
&lt;/h2&gt;

&lt;p&gt;The first version of auto-detection was embarrassingly naive. I was just taking the longest &lt;code&gt;animation-duration&lt;/code&gt; value I could find in the stylesheet and calling that the cycle length. It worked maybe 60% of the time.&lt;/p&gt;

&lt;p&gt;The real fix was building a scoring model that weighs animation complexity, element hierarchy, and easing type together. It took a few iterations to get right, and there are still edge cases I'm working through — particularly with scroll-triggered animations that don't run on load.&lt;/p&gt;

&lt;p&gt;I'm also still not happy with how I'm handling very large HTML files with external dependencies. The current approach works but it's not elegant. That's on the roadmap.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's coming in v2
&lt;/h2&gt;

&lt;p&gt;v1 is out. Here's what I'm focused on next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Broader AI tool support&lt;/strong&gt; — &lt;code&gt;pixdom mcp --install --tool all&lt;/code&gt; to configure for Gemini, Codex, and Cursor in one command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML input validation&lt;/strong&gt; — content sniffing to warn before wasting render time on a non-HTML file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web UI + REST API&lt;/strong&gt; — for teams that want a shared rendering service rather than per-developer installs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BullMQ job queue&lt;/strong&gt; — for scalable cloud deployments where you're processing assets at volume&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  One last thing worth saying
&lt;/h2&gt;

&lt;p&gt;Pixdom was designed, written, and debugged with Claude Code — which is also what created the problem it solves. Claude generated the animated HTML. Claude helped build the tool to render it. There's a certain loop in there that felt worth acknowledging.&lt;/p&gt;




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

&lt;p&gt;Pixdom is live on npm and the repo is public.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pixdom
pixdom &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;npm&lt;/strong&gt; → &lt;a href="https://www.npmjs.com/package/pixdom" rel="noopener noreferrer"&gt;npmjs.com/package/pixdom&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt; → &lt;a href="https://github.com/sushilkulkarni1389/pixdom" rel="noopener noreferrer"&gt;github.com/sushilkulkarni1389/pixdom&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this is solving a problem you've run into — CLI rendering, AI agent workflows, automated social asset generation — install it and tell me where it breaks. Bug reports, edge cases, and honest feedback are more useful to me right now than anything else.&lt;/p&gt;

&lt;p&gt;If you find it useful, a ⭐ on the repo goes a long way. It's what gets the project in front of other developers who'd actually use it.&lt;/p&gt;

&lt;p&gt;A few things I'd genuinely like your take on in the comments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the MCP integration approach make sense to you, or is there a simpler interface you'd want?&lt;/li&gt;
&lt;li&gt;Are there platform profiles missing from the 19 that you'd use regularly?&lt;/li&gt;
&lt;li&gt;Is the auto-detection concept useful, or would you rather just control duration manually?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I read every comment and respond to every issue. If something doesn't work, open one.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>cli</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
