engineering6 min read
Builder · Applied AI

The second CourtCollect is four percent the size of the first

In January I spent six days building CourtCollect, a court-to-collections platform that reached 174,238 lines. When a Texas court needed the work in May, what shipped was a 6,851-line review console built in about 27 hours. Reading tinyclaw, someone else's small multi-agent assistant, showed me why the second one is small: it writes only the part no existing tool covers, and borrows the rest.

CourtCollect started in January as a platform for moving case files from courts to collections agencies: upload, validate, transform, deliver over SFTP. I built it with Claude Code in six days, 117 commits, and it came out at 174,238 lines of source and tests. In May a municipal court in Texas actually needed that work done, and what I shipped was a 6,851-line review console inside this site, built in about 27 hours. It has the same name, and none of the first repo's code is in it. This post is about the gap between those two numbers, and about tinyclaw, someone else's 6,182-line multi-agent assistant, which I forked and read and which is small for the same reason the second CourtCollect is.

Six days in January

The first CourtCollect has three portals (court, agency, operations), 96 page components, 29 database models and 28 API router modules. Job state is event-sourced: every change is appended to a log, and the job row caches the latest state. n8n runs the async stages. (On this site I have since replaced n8n with a graph layer of my own.) There are 20,365 lines of backend tests and 8,847 lines of Playwright specs.

Around that pipeline sits everything a platform might want someday. A video tutorial system. An A/B testing framework. A monitoring dashboard whose components render placeholder data. A complete GraphQL API, 5,694 lines, that the React app never calls, because it does everything over REST. A review I ran on the repo in April listed all of that, along with a short list of things that would need fixing before any real court's data touched it.

None of it was hard to produce, and that is the uncomfortable part. With an agent writing most of the code, 174,000 lines cost me six days. At that price the line count stopped telling me anything about whether the thing was useful.

CourtCollect, the first one174,238 lines
117 commits across six days in January 2026
The console the court uses6,851 lines
16 pull requests over about 27 hours in May 2026
tinyclaw (Jian’s, forked, unrun)6,182 lines
a multi-agent assistant over Discord, Telegram and WhatsApp
One square is a thousand lines of source and tests. Docs and migrations are not counted.
Three codebases at one scale, one square per thousand lines of source and tests. Press "Show what the court uses" and the first repo empties: none of its squares are in the version the court runs. The hollow red squares are the GraphQL layer nothing calls. The chips isolate one kind of code across all three.

What the court actually needed

The real job, when it came, was narrower than the platform and shaped differently. A batch of about 490 cases was headed to a collections agency. Around 30 of them were flagged, meaning something about the case was worth a person's look before it went out. The court needed one person, a reviewer rather than a developer, to go through the flagged cases and decide each one: keep it, hold it, send it back to the court, or remove it. Then the agency needed a file containing only the cases that were cleared.

The first CourtCollect had 29 models, and none of them could hold that decision. It modeled a file moving through a pipeline. The job turned out to be a person making a call about a case. The pipeline part (read a workbook, map its columns, write a workbook) fit in about 330 lines of Python across two scripts.

Twenty-seven hours in May

The console is 16 pull requests merged between one morning and the next afternoon. It is a large-type guided wizard that walks the reviewer through the flagged cases one at a time and then pages through the rest for a quick check, a magic-link sign-in so nobody has to manage a password, an email to me when the review is finished, and an admin page where I approve the batch and export the decisions.

The part that carries the weight is where personal data is allowed to go. The review screens show what the reviewer needs to recognize a case. Social Security numbers, birth dates, license numbers and street addresses never enter the database or the web app; ages are computed from birth dates before the dates are thrown away. The case memos are redacted in memory as they are uploaded, and only the redacted copy is stored. What the app exports is a decisions file with none of those fields in it. The one place the decisions meet the full records again is a script that runs on my own machine, against a workbook that never leaves it.

That boundary explains most of the size. An app that never holds the sensitive fields has nothing to encrypt, audit or purge. The rest of the smallness is borrowed: sign-in, email, file storage and permissions already existed on this site for other things, so the console used them instead of bringing its own. Even the idea I liked best from the first repo survived only in miniature. The event-sourced job state became one status column with four values: in review, ready for admin, approved, sent.

tinyclaw is small for the same reason

tinyclaw is Jian's project (jlia0 on GitHub), MIT-licensed. My fork has 50 commits and none of them are mine, and I have not run it. I read it this week because it does something I would have built big: several AI agents, each in its own workspace, answering on Discord, Telegram and WhatsApp, handing work to each other in teams, running all day. It does that in 6,182 lines.

It gets there by owning almost none of the hard parts. The agent is not tinyclaw's code. It spawns the Claude Code or Codex command-line tool you already have, in that agent's folder, and reads the reply from stdout. The processes live in tmux: one pane per channel, plus panes for the queue, a heartbeat and the logs. The queue is three directories on disk.

A channel client (Discord, Telegram, WhatsApp) writes the message into incoming/ as msg.json.

Step a message through tinyclaw's queue, then kill the processor while the message is in flight. The file waits, whole, in processing/, and a restart moves it back to incoming/. That rename and the startup sweep are the entire recovery design.

Three directories and a rename

A channel client writes each incoming message as a JSON file into incoming/. The processor moves it into processing/ with a rename, which the filesystem does in one step, so the file is always wholly in one place and never half in each. When the reply is ready it goes to outgoing/, the channel client sends it, and the processing/ copy is deleted. If the processor dies mid-message, the file just sits in processing/. On startup the processor renames anything it finds there back into incoming/.

That is the whole crash-recovery story, and for this job it is enough, because it only has to be right on one machine for one person. The processor that does all of this is 613 lines. The console and tinyclaw made the same trade: each picked the one thing no existing tool did for it, wrote that, and borrowed everything else.

When I would still build the big one

If CourtCollect had ten courts and five agencies, it would need what the first repo has: real separation between tenants, unattended SFTP delivery with retries, and an audit trail that someone other than me could trust. Multi-tenancy is not something to borrow from a personal site.

The console is also less small than its line count says. It leans on this site's sign-in, email and storage, which are a large codebase in their own right, and the 6,851 lines are only what one more surface costs once all of that exists. Moved anywhere else, it would have to pay for those parts again.

tinyclaw has edges too. A directory queue on one disk does not spread across machines. It drives other companies' command-line tools, so it depends on their terms and their output formats holding still. And everything I have said about it comes from reading the code, not from running it. I would not route a client's data through it.

What I would tell myself in January

When an agent writes the code, lines are cheap, and a big repo stops being evidence of anything except hours spent. The first CourtCollect answered questions nobody had asked yet. The second one started from the single decision a real person had to make, and built only what that decision needed. tinyclaw starts the same way in a different domain: a message comes in, an agent answers it, and nothing is built that the round trip does not use.

The January repo is public now as an archived snapshot, with the agency's name swapped for a generic one and a warning not to deploy it. It is a decent reference for how a multi-tenant version might look, if the day comes when there are ten courts. Until then, the version that is four percent of its size is the one doing the work.

Experience it yourselfBrowse every pull request this site has merged
ShareXLinkedInHacker NewsEmail

Get the next one

An occasional note when something genuinely new ships here — essays, free tools, projects. No schedule, no filler, easy out.

Need something like this built?

I design and ship AI tools, full-stack apps, and data pipelines — end to end, to production. Tell me the problem in a sentence; I'll give you an honest read on fit within a day.

Work with me →