Skip to content
gauravsoni.dev
Back to home CASE STUDY · AGENTIC AI · ~8 MIN READ

From Figma to merge request in an afternoon

A mid-size frontend feature used to take me about a week. Now it takes 3–4 hours of my own time. Here's the setup, the numbers, and where it still breaks.

  • ~4–5 days → ~3–4 hper mid-size feature
  • 8–12×typical range
  • ~5×when the agent goes the wrong way
  • 3–4 monthsusing this setup

The result, and what was slow before

For the last three to four months I've built most of my features at work with a chain of AI agents. The homepage says 10×. Here's what that means.

It doesn't apply to everything I do. It's for one type of work: a mid-size frontend feature, usually three or four tickets, from Figma design to merged code. These are my own estimates, not tracked data.

Stage Before Now
Design → decisions + PRD ~1 day 30–40 min
Writing tickets ~half a day a few minutes
Code + tests (incl. my review) 2–3 days 2–3 hours
Commits + MR description 2–3 hours ~20 min
Total ~4–5 days ~3–4 hours

That's the normal case. When the agent goes the wrong way, it's closer to 5×. More on that later.

When I looked at where the old week went, most of it wasn't hard engineering. It was turning a design into decisions, then writing those same decisions down again and again. In a PRD. In tickets. In code. In commit messages. In the MR description.

And the part I rushed most, walking through every edge case, was the part that caused bugs later.

The pipeline

Every step is a Claude Code skill. I don't write the code by hand anymore. I run one skill, check what it made, and run the next.

Not all of the skills are mine. Grill-me, the PRD skill and the TDD skill come from Matt Pocock. The React best-practices skill comes from Vercel. I wrote the skills for Jira tickets, commit messages and merge requests. The part I built is how it all fits together: which model runs which step, where I check the work, and what I do when it goes wrong.

The main session runs on Opus 5. It hands the smaller jobs to other models.

The agentic pipeline Seven steps from left to right: Grill-me (Opus 5), PRD and tickets (Haiku), Code and tests (Sonnet), Code review (Opus 5), My review (human), Commit and MR (Haiku), AI review in CI. Code and tests, code review and my review repeat per ticket, with a lint and format hook always on. I decide at three points: I answer the grill-me questions, I approve the diff, and I pick which CI review comments to fix. per ticket always on: lint + format hook · mine 01 PUBLIC Grill-me Opus 5 you answer 02 PUBLIC+MINE PRD + tickets Haiku 03 PUBLIC Code + tests Sonnet 04 Code review Opus 5 05 My review human you approve 06 MINE Commit + MR Haiku 07 AI review in CI CI you pick fixes where I decide PUBLIC open skill (Matt Pocock, Vercel) MINE skill or setup I wrote The agentic pipeline Seven steps from top to bottom: Grill-me (Opus 5), PRD and tickets (Haiku), Code and tests (Sonnet), Code review (Opus 5), My review (human), Commit and MR (Haiku), AI review in CI. Steps 3 to 5 repeat per ticket with a lint and format hook always on. I decide at three points: grill-me answers, the diff, and which CI comments to fix. per ticket 01 PUBLIC Grill-me Opus 5 you answer 02 PUBLIC + MINE PRD + tickets Haiku 03 PUBLIC Code + tests Sonnet 04 Code review Opus 5 05 My review human you approve 06 MINE Commit + MR Haiku 07 AI review in CI CI you pick fixes always on (steps 3–5): lint + format hook where I decide · PUBLIC open skill · MINE my own
One feature, start to finish. The loop runs once per ticket. One feature, start to finish. Steps 3–5 run once per ticket.
  1. Grill-me (Opus 5). Claude reads the Figma design through the Figma MCP, plus the product owner's requirements. Then it questions me one branch of the decision tree at a time, until we agree on every case. Usually 13–14 questions.
  2. PRD and tickets (Haiku). It turns the grill-me conversation into a PRD, splits that into tickets, and creates them in Jira. One ticket is always for QA: how to test the feature by hand.
  3. Code and tests per ticket (Sonnet). Code and unit tests are written together, following the React best-practices skill. A hook runs the formatter and linter every time a file changes.
  4. Code review (Opus 5). A review skill checks the code against the PRD and our standards.
  5. My review. I read the full diff. If I don't understand a change, I ask the agent to explain it before I accept it.
  6. Commit and merge request (Haiku). Conventional commit messages, push, open the MR.
  7. AI review in CI. Another Claude step comments on the MR based on the ticket. I go through the comments and send the fixes back to Sonnet.

Why different models

I use the strongest model where a mistake costs the most: deciding what to build and reviewing the code. Writing a PRD from a finished conversation, or a commit message from a diff, is mostly summarising. Haiku does that fine and costs much less.

Sonnet sits in the middle. It writes good code when the plan is clear, and by step 3 the plan is clear.

Having Opus review Sonnet's code also helps. A stronger model does a second pass, instead of the same model checking its own work.

Where I stay in control

There are three places where I decide:

  • Grill-me. The agent asks, but I answer. Every decision in the PRD is mine.
  • The diff. I don't approve code I can't explain.
  • Review comments. I decide which ones matter.

Everything in between, I hand off.

One story, start to finish

Here's a typical one, kept generic. Before the user can finish an action, the app sends their input to a backend check. Depending on the answer, it either lets them go ahead or shows a warning.

The designer shares the Figma file. The product owner has written the requirements. That's where I start.

Grill-me, about 35 minutes. Opus reads the design and the requirements and starts asking. What does the user see while the check runs? What if they change the input after the check? What if the check fails?

That last one led somewhere I wouldn't have gone on my own. It asked what happens if the backend returns a 429, too many requests. That's not in the design and it's not in the happy flow.

We agreed on this. If the server sends a Retry-After header, we wait that long. If not, we back off: retry after 100 ms, then 200 ms, then 400 ms. If it still fails after that, we show a toast saying the service isn't available right now.

Before this setup, that case would most likely have come back as a production bug.

PRD and tickets, a few minutes. Haiku turns the conversation into a PRD and creates four tickets in Jira: three for the feature, one for QA.

Code, per ticket, 20–30 minutes plus my review. Sonnet writes the code and tests. Opus reviews it. Then I read the diff.

On this story, the agent hardcoded the retry delays right inside the function. The code worked, but I didn't like it. I asked it to move them into constants so we can reuse them elsewhere. One small round, and done.

Commit and MR, a few minutes. Haiku writes the commits and opens the MR. The CI review adds a few comments. Some are useful, some aren't. I decide which ones to fix.

Total time from design to MR: one afternoon.

How I got to ~10×

First, the honest part. I don't have tracked data. These numbers are my estimates from using this setup for three to four months, on stories like the one above. All times are my own hands-on time. The agent itself only runs for two or three minutes per step.

Here's the maths for a typical mid-size story:

  • Before: about 30–39 hours. A day for decisions and the PRD, half a day for tickets, two to three days for code and tests, and a few hours for review, commits and the MR description.
  • Now: about 2.5–4 hours. Around 40 minutes for grill-me, the PRD and tickets. Then 20–30 minutes per ticket for code and tests, plus 20–40 minutes of my own review per ticket, usually one or two rounds. Then about 20–30 minutes for commits, the MR and CI comments.

That's roughly 8–12×. So "10×" is the middle, not the best case.

The worst case is different. Sometimes the agent goes the wrong way and I have to dig in myself. That can cost me 4–5 hours on a single ticket. When that happens, the story takes 6–8 hours, which is closer to . It doesn't happen often, but it happens.

Some things I left out on purpose:

  • Understanding the design with the designer and PO. That takes the same time as before, so it's not in either column.
  • Review rounds from other developers. I don't have a good "before" number for these, so I didn't count them in the old version either.

And the 10× only applies to this type of work. Debugging a weird production issue, or a discussion about architecture, isn't 10× faster. Those still take the time they take.

What didn't work

The setup isn't perfect. Here's what went wrong so far, and what I did about it.

The agent added a library we didn't need. On one ticket it installed an npm package for something we could already do with our own code. When I pushed back, it didn't just agree. It gave me reasons, and some of them were made up. I had to dig in, check it myself and explain why it was wrong. That one ticket cost me 4–5 hours, and it's where the 5× worst case comes from.

In the end the agent said I was right. But that proves nothing. These models often agree once you push hard enough. What counted was that I checked it myself.

I haven't changed the skills after this. It happened once, and one incident isn't a pattern. If it happens again, I'll add a rule to the TDD skill: don't add a dependency without asking, check what we already have first.

It forgot to lint. Sometimes the agent just didn't run the formatter or linter. Telling it again in the prompt didn't fully fix it. So I added a Claude Code hook that runs both every time a file changes. Now it can't forget, because it isn't up to the agent anymore.

That's the biggest lesson for me. If the model keeps forgetting something, don't ask it more nicely. Take the job away from it. A prompt makes something likely. A hook makes it certain.

Grill-me decides when it's done. The skill keeps asking until the agent thinks we've covered everything, usually 13–14 questions. So the stopping point depends on the model's judgement, not mine.

I also don't read the PRD afterwards. I was there for every question, so I trust what's in it. But that's a trade-off. Haiku writes the PRD, and if it drops a decision while summarising, the code review won't catch it, because it checks against that same PRD. I'd only see it later in the diff, if at all.

A template you can copy

You don't need my exact setup. Here's the shape of it.

1. Start with public skills.

2. Write small skills for your own tools. Mine are short. Each one does one job:

  • To Jira: "Take each ticket from the PRD. Create it in Jira with a title, a description, acceptance criteria and a link to the PRD. Add one ticket for QA with steps to test it by hand."
  • Commit: "Read the staged diff. Write a conventional commit message. Keep the subject under 72 characters. Explain why, not what."
  • Merge request: "Push the branch. Open an MR with a summary, the linked tickets, how to test it, and anything the reviewer should look at closely."

3. Pick a model per step. A strong model where mistakes cost the most (decisions, review). A mid model for code. A small model for summaries and git.

4. Put the rules the model forgets into hooks. Here's a minimal version of my lint hook, in .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs -I{} sh -c 'npx prettier --write \"{}\" && npx eslint --fix \"{}\"'"
          }
        ]
      }
    ]
  }
}

5. Keep three checks for yourself. Answer the grill-me questions yourself. Don't approve a diff you can't explain. Decide which review comments matter.

Start with one feature. Time it before and after. Then decide.

Questions about this setup?

Happy to talk about it.