Last month I asked Claude Code to add cursor-based pagination to WPNuxt. Thirteen minutes later, two commits had landed: a new composable, parser changes, code generation updates, a playground demo, and 205 lines of tests across 11 files. The code compiled, the tests passed, and the playground worked on the first try.
But that didn’t happen because AI is magic. It happened because I spent twenty minutes before opening the terminal writing a spec. I knew what useWPConnection should return, how the parser should detect connection queries, and how loadMore() should add new results. Claude Code wrote the implementation. I made the decisions.
That is the difference this article is about: letting AI write code, or actually engineering with AI.
From Vibe Coding to Agentic Engineering
In February 2025, Andrej Karpathy coined the term “vibe coding”. It describes a simple way of programming: you explain what you want, the AI writes the code, and you mostly accept it without understanding every line. It was an honest name. For prototypes and side projects, vibe coding is fun. You move fast, try ideas, and don’t worry too much about the details.
But vibe coding does not scale well. The code often looks correct. It compiles, it runs, and it may even pass basic tests. But it can still be fragile. It can create what I call AI slop: functions that are almost right, abstractions that do not fit the project, error handling for cases that cannot happen, and patterns that nobody really understands because nobody designed them.
One year later, in February 2026, Karpathy joined the conversation again. People were looking for a better name for the next step after vibe coding. He wrote on X: “personally, my current favorite is ‘agentic engineering.’” He said the name works because “there is an art & science and expertise to it.”
Karpathy focused on how much work the agent can do by itself: humans prompt, agents execute. I think the more useful framing is about ownership and discipline. The AI can write the code, but the human still owns the architecture, the quality, and the correctness. It is a different angle, but the spirit is the same.
Think of it like working with a contractor. An architect does not lay bricks, but they must understand load-bearing walls. They draw the plans, the contractor builds, and the architect checks the result. If the foundation is wrong, good bricklaying will not save the building.
That’s the mental shift: from author to architect.
What Changes in Practice
The difference becomes clear when you compare the approaches side by side:
| Traditional Development | Vibe Coding | Agentic Engineering | |
|---|---|---|---|
| Who writes code | You | AI | AI |
| Who designs | You | AI (implicitly) | You |
| Who reviews | Team / PR process | You (briefly, if at all) | You (every diff) |
| Who owns quality | You + team | Nobody, really | You |
| Failure mode | Slow but predictable | Fast but fragile | Fast and deliberate |
| Best suited for | Any project | Prototypes, throwaway code | Production code |
The shift is important. “Writing code” becomes “specifying, delegating, and reviewing.” This needs more engineering skill, not less. You need to know what good architecture looks like before you can review whether the AI produced it.
This is the part that often gets lost in the hype. Agentic engineering does not remove the need for senior developers. It amplifies the skill level that is already there. A senior developer with AI tools can become much more productive. A junior developer with AI tools can produce more code, but more code is not the same as better software.
My Daily Workflow
I use Claude Code as my main AI development tool. It runs in the terminal, has no IDE lock-in, and fits well into a git-based workflow. But the tool matters less than the way you use it.
My workflow follows a consistent loop:
1. Write the spec first. Before I open Claude Code, I write down what I want to build. Sometimes it is a detailed markdown document. Sometimes it is just bullet points. The format does not matter. What matters is that I have thought through the design before I delegate the work. My CLAUDE.md files contain project-level architecture decisions, so the agent stays aligned without me explaining everything again in every session.
2. Break it into small, scoped tasks. One logical change per prompt. “Add cursor-based pagination support” is too broad. “Add connection pattern detection to the parser when pageInfo and nodes appear as siblings” is the right scope.
3. Let Claude Code implement. This is where the speed comes from. The agent writes the code, generates the tests, and creates the playground examples. It handles the boilerplate and the mechanical work that used to take hours.
4. Review every diff like a PR. This is the step that separates agentic engineering from vibe coding. I read every line of every diff as if it came from a colleague’s pull request. If I do not understand a line, I ask about it. If the approach is wrong, I reject it and explain why.
5. Run tests, lint, and typecheck. After every change. Not only at the end. If something breaks, I fix it immediately instead of letting problems stack up.
Case Study: useWPConnection in WPNuxt
Let me show you what this looks like with a real feature. WPNuxt is a Nuxt module I maintain. It connects Nuxt applications to WordPress through GraphQL. Version 2.0 shipped without cursor-based pagination. That was a gap, because WPGraphQL uses the Relay connection pattern for all list queries.
The Spec
Before touching any code, I wrote down what I needed:
- A
useWPConnectioncomposable that wraps the existinguseWPContent - The parser should automatically detect connection queries by looking for
pageInfoandnodesas sibling fields - The code generator should produce
useWPConnection()instead ofuseWPContent()when a connection pattern is detected - The composable should return
data(accumulated nodes),pageInfo, and aloadMore()function - Two pagination modes: manual (cursor-based page navigation) and automatic (
loadMore()for infinite scroll)
This spec lived in the project’s CLAUDE.md file. It had two jobs: guide the AI agent during implementation, and document the architecture for future maintenance.
The Implementation
I broke the work into scoped tasks and let Claude Code implement each one. Two commits landed 14 minutes apart: 78bdff1 and db7972e.
Commit 1: feat: add connection/pagination support with useWPConnection
- Parser enhancement: 6 lines to detect the connection pattern
- New composable: 78 lines for
useWPConnection - Generator changes: 51 lines to produce the right composable call
- Test suite: 205 lines covering 13 test scenarios
- Playground: query file + demo page
Commit 2: feat: add loadMore() to useWPConnection for infinite scroll
- Enhanced composable with smart accumulation logic
- Split playground into page-based and infinite scroll examples
The feature was documented shortly after in the pagination guide and the README feature overview.
The detection logic is simple:
// In the parser: detect WPGraphQL connection pattern
const fieldNames = selections
.filter(s => s.kind === 'Field')
.map(s => s.name.value)
if (fieldNames.includes('pageInfo') && fieldNames.includes('nodes')) {
query.hasPageInfo = true
}Six lines. No user configuration needed. Add pageInfo to your GraphQL query, and the generated composable automatically exposes pagination.
The playground usage is also simple:
<script setup lang="ts">
const { data, pageInfo, loadMore, pending } = await usePaginatedPosts({
first: 3
})
</script>
<template>
<div v-for="post in data" :key="post.databaseId">
{{ post.title }}
</div>
<button
v-if="pageInfo?.hasNextPage"
:disabled="pending"
@click="loadMore()"
>
Load more
</button>
</template>What Needed Human Judgment
The AI handled the mechanical work well: boilerplate, test structure, and playground setup. But several decisions still needed human judgment:
- The detection heuristic. Deciding that
pageInfo+nodesas siblings is the right signal for connection queries needs domain knowledge about the WPGraphQL Relay spec. The wrong heuristic would silently break non-connection queries. - The accumulation pattern. How
loadMore()should append nodes while a param change should replace them. TheisLoadingMoreflag that distinguishes these two cases was a design decision, not an implementation detail. - The API surface. What
useWPConnectionshould return and what it should hide. ExposingloadMore()andrefresh()while hiding the internal cursor management is interface design.
The Honest Take
What went well: test generation was excellent. The 205-line test suite covered edge cases I might have missed: empty connections, null data, and the thenable pattern. The playground demo was immediately usable. The mechanical parts, like types, imports, and module registration, were flawless.
What required intervention: every architectural decision. The AI does not understand why you are building something. It only understands what you asked for. Without the spec, it would have produced something that technically works, but does not fit the existing patterns.
Total time from spec to working feature with tests: about 30 minutes. The same feature would have taken me 2-3 hours to write by hand. But those 20 minutes of spec writing were not optional. Without them, I would have spent more time correcting the AI than I saved.
Lessons Learned
After months of using this workflow, five principles have become non-negotiable:
Write the spec before you open the terminal. Even bullet points change the output a lot. The spec does not need to be perfect. It only needs to exist. Jumping straight into prompting is the fastest way to produce AI slop.
Read every diff like a PR review. AI-generated code that you do not understand is a risk, not an asset. If you cannot explain why a line exists, it should not be there. The five minutes you spend reading a diff can save hours of debugging later.
Tests are your safety net, not your guarantee. Let the agent write them. It is good at covering obvious cases. But review the tests just as carefully as the implementation. A test that verifies the wrong behavior is worse than no test at all.
Keep prompts small and scoped. One logical change per task. Large prompts often create large messes because the AI tries to solve everything at once. Small tasks are easier to review, easier to revert, and easier to commit cleanly.
Know when to code by hand. Some problems are faster to solve yourself. Tricky CSS, complex state machines, and performance-sensitive algorithms are good examples. Sometimes explaining what you want takes longer than writing it yourself. The skill is knowing which tasks to delegate and which tasks to keep.
Where This Is Heading
Agentic engineering is more than a hype term. It describes a workflow that already exists for people who use AI coding tools seriously. It makes good developers more productive. It does not replace the need for good developers.
The skills that matter most are the skills that were always hard: clear thinking, good specifications, and critical review. AI just makes the gap between “has those skills” and “doesn’t” more visible than ever.
If you want to try this approach, start small. Pick your next feature. Write the spec first, even if it is just bullet points. Break the work into tasks. Review every diff. See if it changes how you work.
← Previous
Quality Assurance in the Age of AI Development
AI writes the code fast. The hard part is trusting it. Here's how I use automated tests, CI, and AI PR reviewers to keep quality high.
Next →
What's New in WPNuxt 2.2
Cursor-based pagination, infinite scroll, reactive params, type guards, ACF helpers, and webhook cache revalidation — WPNuxt keeps shipping
