SPECKL: Testing a Human-First Approach to AI-Assisted Development

6 min read

I’m giving a talk at Umbraco in the City soon about Spec-Driven Development (SDD), which has had me deep in research on where AI tooling is taking software development. If you’ve been following the space, you’ve probably seen this idea cropping up more and more: write a detailed spec, hand it to an AI agent, let it generate entire systems while you review the output. It’s powerful, it’s fast, and the economics are compelling enough that I believe it’s where a lot of development is heading.

But while doing this research, I had an interesting series of conversations with Phil Whittaker that led to an experiment.

The Other Perspective

Phil and I were discussing SDD and the future of AI development tools. While I was exploring the automation angle, Phil kept pushing back toward something more collaborative.

“I don’t want to be replaced by AI,” he said. “I want to work with it.”

And the thing is, he was. Phil had already been developing this way—maintaining control, setting boundaries for AI assistance, getting good results. But his approach was intuitive, built from experience rather than codified into a repeatable process. Through our conversations, I realized there was something worth exploring here, but without formalizing it, I couldn’t properly test it, adopt it myself, or share it with others.

So I did what developers do: I built my interpretation of it.

Building SPECKL to Test the Hypothesis

Based on our conversations, I pulled out what I felt were the important corner stones combined with some of my own ideas into the SPECKL Manifesto. The core hypothesis: Humans build. AI assists. Specs define the boundaries.

SPECKL sits between “vibe coding” and full SDD:

  • Vibe coding: “Hey AI, build me a user auth system.” Fast, but you’re playing whack-a-mole with context drift and hallucinations.
  • SPECKL: You write a small, structured spec (a “speck”) that defines goals, inputs, outputs, and constraints. The developer stays in control—whether they’re coding themselves or asking AI to generate code—but everything happens within the boundaries of the spec.
  • SDD: You write a detailed spec and let AI generate the entire implementation while you review.

The question: Is there value in this approach, or are we just delaying the inevitable?

The SPECKL Approach

Specs are for alignment, not automation. They tell the AI what is true, not what to do. Here’s the minimal template:

## Goal
User/system outcome in one sentence

## Inputs
Data, params, triggers

## Outputs
UI state, API responses, files

## Constraints
Stack, performance, compliance limits

## Dependencies
Existing systems to understand first

## Requirements
What actually needs to be built

## Out of Scope
Explicit non-goals

## Done
Observable outcomes that prove success

An example of a generated spec would be something like this:

# Refund Reasons

# Goal
Enable merchants to capture and store a mandatory refund reason when processing order refunds for reporting and analysis purposes.

# Inputs
- Refund reason selection (enum, required):
  - Item defective or damaged
  - Wrong item sent
  - Item not as described
  - Item did not arrive
  - Customer changed mind
  - Ordered by mistake
  - Better price found
  - Shipping or delivery issues
  - Product quality not satisfactory
  - Other

# Outputs
- Refund reason stored in transaction activity metadata
- Refund reason displayed in order transaction history
- Refund reason available for reporting queries

# Constraints
- .NET 9.0 / C# backend with NPoco ORM
- TypeScript/Lit frontend components
- No free-text reason field - enum values only
- Backward compatibility: existing refund transaction activities without reasons must display gracefully
- Localization support for all enum values via Description attributes

# Requirements

## Backend (Core Domain)
- RefundReason enum already exists with all 10 values
- PaymentService.RefundOrderPaymentAsync must pass refund reason to RefundTransactionActivityMetaData
- RefundTransactionActivityMetaData already supports optional RefundReason property

## Backend (API Layer)
- Management API v2 refund endpoint must require refund reason in request body
- Update RefundOrderPaymentByIdManagementApiControllerV2 to use OrderRefundWithReasonRequest instead of OrderRefundRequest
- OpenAPI specification regeneration to include refund reason in API contract

## Frontend (Backoffice UI)
- Add refund reason dropdown to refund modal (order-refund-modal.element.ts)
- Dropdown must appear before "Restock Products" toggle
- Use uui-select component for reason selection
- Form validation: refund button disabled until reason selected
- Display refund reason in transaction activity table for completed refunds

## Localization
- Add English translations for all 10 enum values (matching Description attributes: ucRefundReason_*)
- Localization keys already defined in RefundReason enum Description attributes

# Dependencies
- `src/Umbraco.Commerce.Core/Models/RefundReason.cs` - Enum definition
- `src/Umbraco.Commerce.Core/Models/OrderRefundRequest.cs` - Request DTOs (both optional and required variants)
- `src/Umbraco.Commerce.Core/Models/TransactionActivities/RefundTransactionActivity.cs` - Stores refund metadata
- `src/Umbraco.Commerce.Core/Services/IPaymentService.cs` - Refund service interface
- `src/Umbraco.Commerce.Core/Services/Implement/PaymentService.cs` - Refund service implementation (line 234 creates RefundTransactionActivityMetaData)
- `src/Umbraco.Commerce.Cms.Web.Api.Management/Order/Controllers/RefundOrderPaymentByIdManagementApiControllerV2.cs` - API v2 endpoint
- `src/Umbraco.Commerce.Cms.Web.StaticAssets/Client/src/order/modals/order-refund/order-refund-modal.element.ts` - Refund UI modal
- `src/Umbraco.Commerce.Cms.Web.StaticAssets/Client/src/order/components/transaction-activities/uc-transaction-activity-table.element.ts` - Transaction history display
- `src/Umbraco.Commerce.Cms.Web.StaticAssets/Client/src/lang/en.ts` - English localization

# Out of Scope
- Free-text reason field or "Other" explanation field
- Refund reason required for API v1 endpoint (deprecated, will be removed in v17)
- Payment provider integration changes (reason is metadata only, not sent to payment gateways)
- Analytics or reporting dashboards using refund reasons
- Database schema changes (reason stored in existing transaction activity metadata JSON)
- Migration of historical refund data to add reasons retroactively
- Refund reason filtering in order list advanced filters
- Customer-facing refund reason display (backoffice only)

# Done
- Merchants see a required "Refund Reason" dropdown in the refund payment modal
- Merchants cannot complete a refund without selecting a reason
- Refund reasons appear in order transaction history after refund completes
- API v2 refund endpoint validates that reason is provided
- TypeScript API client types include refund reason field

Small. Clear. Composable. Usually just a few hundred words.

Unlike vibe coding where the AI guesses at context, here it has real boundaries to work within. You make the architectural decisions—whether coding yourself, directing the AI, or mixing both.

Making It Practical

To test this, I built a set of slash commands for Claude Code:

  • /spkl:init <description> – Initializes a new specification directory with a feature description
  • /spkl:spec <description|refinement> – Generates or refines a spec following the SPEKL methodology
  • /spkl:tasks – Breaks the spec into human-actionable implementation tasks
  • /spkl:collab – Starts a spec bound pair-programming collaboration session

The workflow: initialize a spec, describe what you want to build (Claude researches patterns and security), refine the spec, generate a task breakdown, then assists on the implemention—always bounded by the spec.

The Experiment Continues

Here’s where I’m at: I’m not sure if SPECKL is the future, but I needed to build it to find out.

The SDD research for my talk keeps pointing toward automation. The economics are compelling, the technology is improving rapidly, and the trajectory seems clear.

But there might be value in a transitional approach—something more structured than vibe coding, more hands-on than full SDD. SPECKL might just be a stepping stone that teaches us to write better specs and think in boundaries before full automation arrives.

I’ll be testing this on real projects to see what works and what doesn’t, continuing to expand SPECKL through Phil’s ongoing insights.

I’m already working on some ideas for additional commands—like /spkl:explore to investigate ideas or codebases and distill findings as contextual memories, or /spkl:critique to review the implementation against the spec. The goal is building a toolkit that keeps developers in control while making AI collaboration genuinely useful.

Try It (If You’re Curious)

SPECKL is open source and available on GitHub: mattbrailsford/SPECKL

If you’re using Claude Code, you can install it as a plugin directly from the marketplace:

# Add the marketplace
claude add-marketplace https://github.com/mattbrailsford/speckl

# Install the plugin
claude install speckl

If you’re using a different AI tool, the Manifesto and spec template are tool-agnostic—you can adapt them to your workflow.

I’d genuinely love feedback. Does this middle path work for you? Have you found different approaches that work better? Are we all heading toward full SDD anyway and this is just an interesting detour? And if you have ideas for commands that would make SPECKL more useful—I’m all ears.

And if you’re at Umbraco in the City, come chat after my SDD talk. I’ll be exploring both sides of this coin—where we’re heading with automation, and whether approaches like SPECKL have a place in that future.

Until next time 👋