<?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: Jake Hoffman</title>
    <description>The latest articles on DEV Community by Jake Hoffman (@jake_hoffman).</description>
    <link>https://dev.to/jake_hoffman</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%2F3963720%2F10114758-dd7e-4adf-8b06-d56928f570fd.png</url>
      <title>DEV Community: Jake Hoffman</title>
      <link>https://dev.to/jake_hoffman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jake_hoffman"/>
    <language>en</language>
    <item>
      <title>I had Claude build a real fintech library in two weeks. Now I want it audited.</title>
      <dc:creator>Jake Hoffman</dc:creator>
      <pubDate>Tue, 02 Jun 2026 16:14:27 +0000</pubDate>
      <link>https://dev.to/jake_hoffman/i-had-claude-build-a-real-fintech-library-in-two-weeks-now-i-want-it-audited-1e3l</link>
      <guid>https://dev.to/jake_hoffman/i-had-claude-build-a-real-fintech-library-in-two-weeks-now-i-want-it-audited-1e3l</guid>
      <description>&lt;p&gt;I wanted to know whether an AI coding agent could build something real instead of a prototype, so I gave it the least forgiving problem I could find. Accounting. Turning Stripe's webhook events into proper double-entry bookkeeping you could hand to QuickBooks or Xero.&lt;/p&gt;

&lt;p&gt;Accounting is a good test because there's nowhere to hide. The debits equal the credits or the entry is wrong. An accountant either recognizes what you booked or they don't. There is a right answer and you can't argue your way to it.&lt;/p&gt;

&lt;p&gt;Two weeks later I have Ledgerly. It's on npm, it's Apache-2.0, and I'm not fully sure every entry is correct, which is the reason I'm writing this.&lt;/p&gt;

&lt;p&gt;Most days I gave Claude a single instruction and let it pick the most useful next thing to build. It read what already existed, chose something, and implemented it. I made the calls at the real forks, approved or rejected the accounting decisions, and pushed back when an entry looked off. I didn't write the code. My job was deciding what to build and checking whether it was right.&lt;/p&gt;

&lt;p&gt;Fifteen releases later it does more than I expected going in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;13 Stripe event types: charges, refunds, disputes, payouts, invoices.&lt;/li&gt;
&lt;li&gt;Revenue recognition. Pay a year up front and it books the cash to deferred revenue, then recognizes it across twelve months. The monthly pieces reconcile back to the original amount exactly.&lt;/li&gt;
&lt;li&gt;Sales tax kept as its own liability instead of mixed into revenue, and refunds draw it back down proportionally.&lt;/li&gt;
&lt;li&gt;Currency handling. Entries post in whatever currency your Stripe balance settled in, and it records a realized gain or loss when the rate moved between a charge and a later refund.&lt;/li&gt;
&lt;li&gt;Exporters for QuickBooks Online and Xero.&lt;/li&gt;
&lt;li&gt;A webhook server with signature verification, dedup, SQLite storage, a retry queue that dead-letters what keeps failing, and OAuth for both platforms.&lt;/li&gt;
&lt;li&gt;A Docker image and an npm package, both with signed build provenance.&lt;/li&gt;
&lt;li&gt;589 tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The moment that stuck with me was about payouts. When Stripe pays you into a bank account held in a different currency than your balance, it converts the money and takes a fee, and the bookkeeping for that fee is genuinely fiddly. I expected the agent to wing it, since making things up is the failure everyone warns about. It didn't. It told me it couldn't model that case correctly without real example payloads, wrote up what it would need to see, and left the code refusing those payouts with a clear error rather than posting a number it couldn't defend. I've worked with people who would have shipped the guess.&lt;/p&gt;

&lt;p&gt;Is the accounting right? I think it mostly is. The entries balance, the recognition schedule reconciles, there's a test behind every case, and there's a document in the repo that explains the reasoning for each entry so you can check the logic without reading the code. But me being fairly sure is not the same as an accountant confirming it, and I won't pretend it is.&lt;/p&gt;

&lt;p&gt;That's the ask. If you keep books for a SaaS, or you know the corners of the Stripe API, or you just like finding the thing that's broken, go break it. It's npm install ledgerly and the core is small enough to read in one sitting.&lt;/p&gt;

&lt;p&gt;What surprised me most had nothing to do with the code. Writing it was never the constraint. The constraint was knowing what to ask for, and knowing what correct looked like in a field where I'm not the expert. The agent produced every line, but I still had to decide what a refund does to a tax liability and whether revenue recognizes monthly, and some of the most useful moments were when the right answer was to admit I didn't know yet. I'd rather you check it than take my word for it.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/jakethehoffer/ledgerly" rel="noopener noreferrer"&gt;https://github.com/jakethehoffer/ledgerly&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>typescript</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
