This is a guest post from Kenny Eliason - CEO and co-founder of Quilia, the client platform built for personal injury law firms.
I'm currently the only full-time developer at Quilia. We build an app for the clients of personal injury law firms. A firm subscribes, hands the app to its clients, and the clients use it to stay on top of their case. About 50,000 people use it across almost 60 firms in the US.
It's an exciting time to be building. AI has changed almost everything I've known about this work over the last 20 years, and I'm excited about it. I'm putting out more code than ever, and bugs get fixed faster than a second person could find them. On a busy day I'll push five OTA updates.
The stack is pretty standard on purpose: Expo for builds, updates, and store delivery, Supabase for the database, TypeScript, PostHog for analytics, Linear for work tracking, and Sentry for errors. My terminal is always logged into Claude, with Codex and a couple of Grok bots in the mix too. The agents sit on top of that stack and use it the same way I do.
That works because the tools underneath hold up. I rely on Expo, and I have no interest in rebuilding it with custom code. I love having strong partners that take work off my plate and fill gaps I'd otherwise have to build myself, so the agents and I can spend our time on the product.
The agent loop that ships bug fixes
Most of our bug fixes are automated now. Here's the loop:
- Sentry gathers whatever it can about the error.
- A triage agent grabs the Sentry context, looks at the current code, hits the database when it needs to, and finds the issue.
- For obvious regressions (a form that stopped submitting because someone introduced a stray comma), it patches the bug, opens a PR, merges it, ships an OTA update through Expo Update, and back-merges to development.
- If confidence drops below a high bar (we're around 95%), it stops. Nothing goes live. The item lands in Linear for a human.
Linear is the spine. Sentry triages into Linear. Another agent picks work up from Linear, does the background debugging, and pushes through the same path. The slow part is the "needs human" pile. Often the agent almost had it. It just couldn't see the last click. To get it a screenshot, I have to pull the branch, spin up the environment, run the app, and feed the evidence back by hand. That's the biggest bottleneck I have left.
It's why I'm on the waitlist for Expo Simulators, Expo's cloud simulator service. It's in preview right now. If the agent can watch the app run, fewer tickets stall on me. My whole approach is that the more data I can give my agents, the better they perform. Sight is data.
The agents also talk to Expo directly through the Expo MCP server and Expo's APIs. They pick whichever fits the job. I don't copy-paste dashboard output anymore.
OTA updates set the pace
Bug-fix updates go out constantly. On top of those I usually push about two releases a day while I'm developing: ship when it's good enough, keep building, ship again before the end of the day.
An OTA update here means a JavaScript update through Expo Update. Native changes go through a full build and store review. When we add a deploy label to a PR, a GitHub Actions workflow checks whether the change needs a full native build or an update. Today that's package-change detection. If a package changed, it's a full build. If not, it's an OTA update. Expo Fingerprint does the same check with more rigor, and it's on my list to look at next.
Every update still runs through our release cycle so tags, versioning, and GitHub stay honest. When we cut an official store release, a skill gathers the updates since the last one and writes the notes. Expo is in the critical path for all of it: Expo Build for the builds, prebuild and our development build locally, and Expo Submit for the stores.
OTA updates are the piece that makes the whole loop pay off. The agent fixes the bug, ships the update, and the next person through the app never sees the problem.
Supabase is the other half
We tried a few things before Supabase. In the early days we ran on a Notion database, then moved to plain Postgres. I've been doing this long enough to have run phpMyAdmin for years, so when we landed on Supabase it felt like a breath of fresh air. It keeps getting better, too. Every time I log in they've launched an easier way to do something, and they've been great to work with. We did a story with Supabase back in our early days, so writing this one feels like coming full circle.
Two things matter most for iteration speed. The first is branching. We branch the database, run tests against the current structure, and don't maintain a second instance that's always out of sync. I create migration files, add columns and tables, and CI checks that the migrations build cleanly off the current schema. I review, merge, and go to prod knowing it'll work.
The second is MCP. I run two Supabase MCP setups. Production is read-only, so agents can triage against real data without breaking anything. Development is read and write for building. During triage the agent takes a quick hit at prod, sees what happened, then fixes it on the right side of the fence.
Supabase has always felt agent-friendly to me because it's so easy to get to. Mostly I just need to talk to my data, and Supabase makes that simple. As easy as Expo has made it to get builds out, Supabase has made it that easy to run a database.
Skills that remove the copy-paste
I maintain a lot of skills. The one I'd point to is our Release Coordinator. It looks at every commit since the last release and summarizes them into a changelog. It triggers the PR that triggers the builds. When the builds land, it writes the store copy, translates it (we ship in about 20 languages), and uses the Apple and Google APIs to fill in the listings. Google wants different fields than Apple, so it builds both. By the time it finishes, both stores are ready for me to review and submit.
Every submission goes in complete, with the tags, promotional text, release notes, and translations all filled in, and I haven't had a kickback since. Building it took a lot of work, even with agent help, so I wouldn't expect every team to build the whole store API path themselves. The idea travels, though: teach an agent your release routine once and let it run that routine every time.
I also keep skills that encode the company mission. Every time an agent goes to check something, it knows the goal: improve the experience for every client going through a personal injury case. That keeps agents steered toward the experience, not just toward closing tickets. And every time I catch myself giving the same feedback twice, it goes into a skill. I don't want to ask for the same thing ten times.
I know it sounds like I'm working myself out of a job. I'm not. My job is orchestration now. I think of myself as the conductor, and the more I can conduct instead of playing every instrument, the faster and better we can build. About 15 years ago I helped a guy switch his mouse from double-click to single-click. When I finished, he joked, "Man, you just saved seconds of my life." He was kidding, but that mentality stuck with me. Any time an agent could have done something a little faster than me, I build it in.
What users feel
What we couldn't do before is analyze, at a fine grain, what's working and what isn't. The agents look at which factors go into a client completing a flow and why some people don't, then we iterate. We can see where someone got lost, ship a fix the same day, and make sure the next person through has a better experience than the last one.
It's not that users say more now. They say less. A problem that would have annoyed someone before gets fixed before they have time to complain about it. We aren't chasing every individual request. We take what people run into and turn it into a better experience for everyone. Our internal tracking has about 82% of clients saying they'd recommend the experience, and adoption and usage keep going up. We're hearing less, and hopefully that's a good sign. It usually is.
If you're a small team thinking about this
You don't need a big team to run a loop like this. You need a stack the agents can see into and act on: an error tracker that hands over context, a database with a safe read-only path into prod, and a way to ship a JavaScript fix in minutes instead of days. For us that's Sentry, Supabase, and Expo Update. Whatever you pick, lean on good partners for the infrastructure and spend your time on the product.
If you're already on Expo and Supabase, the cheapest win is a database branch for CI and a read-only Supabase MCP against prod. Expo's Supabase guide covers the setup. If you're not shipping OTA updates yet, start with the Expo Update docs. This whole loop depends on it. And if your agents are stuck on "needs human" the way mine are, get on the Expo Simulators waitlist. I'll see you there.












