Menu
AI-assisted engineering

I build with Claude.
I still own the result.

Claude is in my daily work — writing code, driving end-to-end tests, reviewing diffs before anyone else sees them. It makes me faster. It does not make me less accountable, and nothing reaches your repository that I have not read.

Development

Scaffolding, refactors, and the tedious middle of a feature. I decide the architecture and read every line that lands — the leverage is in typing speed, not in judgement.

End-to-end testing

Claude drives the real application in a browser and reports what actually happened. A test that exercises the running system catches what a green unit suite cheerfully misses.

Code review

Every diff gets an adversarial pass before it reaches a human — N+1s, missing tenant scopes, unhandled failure paths. It is a second reader that never gets tired at 6pm on a Friday.

Documented rules

The rules below are loaded as a skill, so the same standards apply on project thirty as on project one. Consistency is the part that does not survive on memory alone.

The working loop

How the work actually gets done

The value is not in asking a model to write a function. It is in a repeatable loop where every step is verifiable, and where the expensive mistakes get caught before they reach your repository.

01

Establish context before asking for code

A model with no context invents plausible APIs that do not exist in your codebase. Before any work starts, it reads the surrounding files, the conventions, the existing patterns. Most bad AI output traces back to a question asked without context, not to a weak model.

02

Load the rules as a skill

Project standards live in .claude/skills/ as versioned files, not in a prompt someone retypes from memory. The same rules apply on a Friday afternoon as on a Monday morning, and they are reviewable in a pull request like any other code.

03

Plan before implementing

For anything non-trivial, the plan comes first and gets read before a line is written. Rejecting a wrong approach in a paragraph costs seconds. Rejecting it after it is built costs the afternoon.

04

Implement in reviewable slices

Small diffs that each do one thing. A 900-line change nobody can meaningfully review is not productivity, whoever wrote it — it is deferred risk with a commit message attached.

05

Verify against the running system

Not "the tests pass" — drive the actual application and observe what happens. A green suite proves the code does what the tests assert, which is not the same as doing what you wanted.

06

Adversarial review before a human sees it

A separate pass whose only job is to find what is wrong: N+1s, missing authorization, unhandled failure paths, silent truncation. Cheap to run, and it catches the class of bug that survives to production.

Prompting

Ask for the constraint, not the code

Most disappointing output is a specification problem, not a model problem. The request left the important decision unstated, so the model made it — and made it plausibly, which is worse than making it badly, because a plausible wrong answer survives review.

Vague

Write a function to import users from CSV.

Specified

Import users from CSV into the users table. The file can be 200k rows, so it must stream rather than load into memory. Duplicate emails should update the existing row, not insert. Wrap in a transaction per 1,000-row chunk. Follow the existing importer in app/Imports/.

The weak version leaves memory strategy, duplicate handling, transaction boundaries and house style unstated — so four decisions get guessed.

Vague

This page is slow, make it faster.

Specified

This page issues 340 queries. Count them, find the N+1s, and fix the ones in the render path first. Do not add caching. Report the before and after query count.

The weak version invites a plausible theory. The strong one names the measurement, forbids the tempting shortcut, and demands a number back.

Vague

Add authentication.

Specified

Add token authentication using the existing Sanctum setup. Every route under /api/v1/projects must authorize against the project policy, not just check that a user is logged in. Add a failing test first for a user fetching another user's project.

Authentication and authorization are different problems. The weak version reliably produces the first and silently omits the second.

Name the constraint

Memory limits, row counts, latency budgets, what must not change. Unstated constraints get invented.

Point at the pattern

Reference an existing file to follow. This is the single highest-leverage sentence in most prompts.

Forbid the shortcut

If caching or a rewrite would hide the problem rather than fix it, say so explicitly up front.

Demand evidence

Ask for the number, the test, the output. "Done" is a claim; a before-and-after count is a result.

Honest trade-offs

What it is good at, and where it will hurt you

Anyone selling you AI-assisted development without a list on the right-hand side of this page is selling something. Both columns are real, and knowing the second one is what makes the first one safe.

Where it wins

The tedious middle

Boilerplate, migrations, form requests, test scaffolding, mechanical refactors across many files. Work that is well understood and slow to type.

Breadth on unfamiliar ground

Reading an unfamiliar codebase or a legacy framework and summarising how it actually fits together, far faster than doing it by hand.

A tireless second reader

Review does not degrade at the end of a long day. It flags the missing authorization check on the fortieth file as reliably as the first.

Exploring options cheaply

Three approaches sketched and compared before committing to one. The cost of considering an alternative drops close to zero.

Tests that would not get written

Edge cases and failure-path coverage that gets skipped under deadline because it is unglamorous.

Where it hurts

Confidently wrong

The failure mode is not gibberish — it is a fluent, well-formatted answer that is incorrect. Wrong output arrives looking exactly like right output, which is precisely why unreviewed AI code is dangerous.

Invented APIs

Methods and packages that do not exist, named exactly as they should have been. Caught instantly by running the code, and not at all by reading it approvingly.

Volume outruns review

It can produce more code than anyone will honestly read. Unreviewed volume is the real risk, and it is a process failure rather than a model failure.

Eager over-engineering

Left unconstrained it will abstract, add a layer, and refactor adjacent code nobody asked it to touch. Scope discipline has to be imposed from outside.

Weakest where stakes are highest

Novel architecture, security-critical decisions, and anything depending on business context it cannot see. These stay human decisions.

Confidentiality is a real question

Your source is going to a third party. That needs a deliberate answer about what may be sent, under which agreement — not an assumption. Ask any engineer using AI on your codebase what theirs is.

The one rule

Measure before you change anything.

Every performance disaster I have been called into had the same shape: someone had a theory, acted on the theory, and made it worse. A theory costs nothing to hold and everything to act on.

The page issuing 3,982 database queries per request was not found by reading code. It was found by counting queries. Once counted, the fix was obvious — it came down to 52.

That is also the discipline I apply to AI-assisted work. The model produces a confident answer whether or not it is correct, so the number comes first and the explanation comes second.

Quality

Gates that do not care who wrote the code

AI-assisted work raises quality only when the checks are mechanical and run every time. A gate that depends on someone remembering to be careful is not a gate. None of the following know or care whether a human or a model produced the diff — which is exactly why they work.

Static analysis at a real level

PHPStan or Psalm high enough to hurt, failing the build. Invented methods and impossible types die here, automatically, before review.

Formatting is not a discussion

Pint or an equivalent, enforced in CI. Style should never consume review attention that belongs on correctness.

Query budgets in tests

Assert a maximum query count on hot endpoints. An N+1 reintroduced six months from now fails a test instead of a customer.

Tests written against the requirement

Not against the implementation that was just produced. A test derived from the code it tests only proves the code is self-consistent.

Security review as a distinct pass

Authorization, injection, secrets, unsafe deserialization — reviewed as its own concern, because it is never what you are looking at when reviewing behaviour.

Verify against the running system

Drive the real application and observe. Passing tests and a working feature are correlated, not identical.

The ruleset

Nine rule files. Take the ones you need.

MIT licensed

Deliberately not a general style guide — Laravel's own conventions cover that, and cover it well. Every rule here states the failure mode it prevents, because a rule without a consequence attached is a preference. Delete the files that do not apply to your project: a smaller, relevant skill beats a comprehensive one the model has to wade through.

Core rules

3 files

Distilled from thirty production Laravel projects — the three areas where I have watched real projects fail.

rules/performance-forensics.md

Performance forensics

Applies when — An application got slow and nobody knows why

Count queries before theorising. The N+1 you find is rarely the one that matters — it hides in a Blade accessor, not the controller, and eager loading can make it worse. Payoff order: query count, then indexes, then cache, then architecture.

3,982 queries → 52 Composite indexes Cache is not a fix
Read this rule ↗
rules/multi-tenancy.md

Multi-tenancy

Applies when — More than one customer's data lives in one system

Shared schema or database per tenant is the decision that determines everything after it. The honest framing is not which is correct — it is what a leak costs you. Global scopes help enormously and guarantee nothing.

Isolation models Scope bypass paths Blast radius
Read this rule ↗
rules/external-writes.md

External writes

Applies when — You call a system you do not control, and it can fail halfway

Never let local state answer a question the authority can answer. Cache for display, never for decisions. If your table says March and the registry says January, the registry is right and the site goes dark in January.

Idempotency Reconciliation Timeout semantics
Read this rule ↗

Language & platform rules

6 files

Standards applied across the stack, organised by where the work happens. These codify established practice — OWASP guidance, framework security documentation, well-understood patterns — rather than recounting specific engagements.

rules/laravel-application-rules.md

Laravel

Applies when — Day-to-day controllers, models, policies, requests

When a service class earns its existence and when it is a controller method with extra steps. Where logic actually belongs. Transaction boundaries that never wrap a third-party call. The authorization check everyone forgets.

Service layer Policies Mass assignment PHPDoc shapes
Read this rule ↗
rules/rest-api-rules.md

REST APIs

Applies when — Designing or changing an API other people depend on

Response shape stability beats elegance. Object-level authorization — user A fetching user B by guessing an ID — is the most common serious API flaw. Idempotency, error envelopes, and pagination that survives concurrent writes.

Versioning OWASP API #1 Idempotency Cursor pagination
Read this rule ↗
rules/database-rules.md

MySQL & PostgreSQL

Applies when — Schema, indexes, and migrations on tables with real data

A constraint in the database beats a check in application code, because application checks race and constraints do not. Composite index column order. Which migrations lock a table offline, and how that differs sharply between engines.

Money is never a float EXPLAIN Expand/contract Lock behaviour
Read this rule ↗
rules/react-rules.md

React & React Native

Applies when — Frontend state, security, and render cost

Conflating server state with client state causes most React bugs. Derived values that should never have been state. The useEffect-as-data-fetcher antipattern. Measuring re-renders with the Profiler instead of guessing at memo.

Server vs client state XSS Token storage Profiler
Read this rule ↗
rules/python-rules.md

Python

Applies when — Services, data work, and anything that started as a script

Separating I/O from computation so logic is testable. Pickle deserialization is remote code execution. Type hints as executable documentation. Where Python is genuinely slow and where that is a myth.

Module boundaries Unsafe deserialization The GIL, accurately
Read this rule ↗
rules/ai-integration-rules.md

AI / LLM integration

Applies when — Shipping a feature that calls a model in production

A model call is an external write to a system you do not control. Prompt injection — especially indirect, via retrieved documents — is the central threat. Model output must never reach a privileged action unvalidated. "The system prompt says not to" is not a security control.

Prompt injection Schema-constrained output Cost ceilings Eval sets
Read this rule ↗

Take the ruleset. It is free.

Drop the folder into .claude/skills/ in your project and Claude Code loads it when the work matches. MIT licensed — use it, fork it, ship it. A link back is appreciated and not required.

SKILL.md 9 rule files ~2,000 lines No attribution required
Download the skill ↓
Applied to

The rules are written from Laravel work, but the discipline behind them travels. Here is the stack they get applied to.

Laravel · 28 REST APIs · 20 React · 5 MySQL · 29 AI / LLM · 1 React Native · 3 CodeIgniter · 3 cPanel / WHM · 2 Vue.js · 1 CakePHP · 1 SilverStripe · 1

Got something slow, leaky, or half-migrated?

Tell me the symptom and I will tell you what I would measure first. That part is free.

Get in touch ↗