Spec-Driven Design with Claude Code
One of the most common mistakes developers make when using Claude Code is jumping straight into implementation. You open the terminal, write a quick prompt like "build me a web app that does X," and let Claude start generating code. This approach is sometimes called vibe coding — you have a rough idea in your head, and you just start coding with the AI, improvising and fixing things as you go.
Vibe coding can work for small throwaway scripts or experiments. But for anything bigger — a real product, a multi-file application, or a feature with business requirements — it tends to produce inconsistent results, misaligned architecture, and a growing heap of technical debt.
This article introduces a more disciplined approach: spec-driven design. Instead of asking Claude to code immediately, you first ask it to help you write a specification. That specification then lives in your project as a CLAUDE.md file, and Claude references it every time it generates code. By the end of this article, you will know how to use Claude Code's Plan Mode, the /models command, and the CLAUDE.md memory system together to build a well-specified project from scratch.
Vibe Coding vs. Spec-Driven Design
The Problem with Vibe Coding
When you vibe code with an AI, you are relying on the model's best guess about what you want. The model does not know your naming conventions, your preferred architecture patterns, your non-functional requirements, or which libraries you want to avoid. Every session starts fresh with minimal context, and the model fills in the gaps with assumptions.
The result is often functional but fragile code. Different parts of the project may use inconsistent patterns. The model might choose a technology stack that conflicts with your deployment environment. Business logic may be scattered across the wrong layers. These problems compound as the project grows.
What Spec-Driven Design Does Differently
Spec-driven design adds one step before implementation: write down what you are building and why. You create a structured document — the spec — that captures your project's purpose, data models, UI requirements, architecture decisions, and feature scope. Claude then uses this spec as its primary reference throughout the entire development process.
This approach has two key benefits. First, it forces you to think clearly about the problem before writing a single line of code. Second, it gives Claude consistent, high-quality context that reduces guesswork and produces more coherent results. The spec becomes a shared contract between you and the AI.
The spec file is stored as a CLAUDE.md file, which Claude Code automatically loads into context at the start of every session. You do not need to repeat your requirements every time you open a new conversation — the spec is always there.
Plan Mode: Read-Only Research Before Writing Code
What Is Plan Mode?
Claude Code has two operating modes: a default write mode where Claude can read files, run commands, and modify code, and a plan mode where Claude is restricted to read-only operations. In plan mode, Claude can browse documentation, read existing files, and reason about architecture — but it cannot write or modify anything.
Plan mode is ideal for the spec-writing phase. You want Claude to research your problem, understand the domain, and produce a thoughtful plan — not to rush into writing files prematurely.
Activating Plan Mode
Switching between modes in Claude Code is done with a single keyboard shortcut. Press Shift + Tab to toggle between write mode and plan mode. The current mode is displayed at the bottom of the Claude Code interface.
Before submitting a spec-writing prompt, always switch to plan mode first. This guarantees that Claude will research and reason before touching any files.
Choosing the Right Model with /models
Not all tasks require the same model. For coding tasks, a faster model like Claude Sonnet works well. But for deep planning and reasoning — like writing a specification — you want the most capable model available.
Use the /models command to see all available models and switch to the one best suited for the task. At the time of writing, Claude Opus is the most capable model for deep reasoning. When writing a spec, select Opus before submitting your prompt.
Once you select a model, it remains active for the current session. You can switch back to a lighter model for implementation tasks to reduce costs and increase speed.
Building HookHub: A Worked Example
What Are Claude Code Hooks?
Before diving into the spec-writing process, it helps to understand the domain that HookHub covers. Claude Code hooks are user-defined shell scripts or commands that are automatically executed at specific points in the Claude Code agent loop. They allow developers to extend Claude Code's behavior without modifying its core.
Hooks are configured in Claude Code's settings.json file and are triggered by lifecycle events:
- PreToolUse — runs before Claude calls any tool (e.g., block dangerous commands, validate inputs)
- PostToolUse — runs after a tool call completes (e.g., auto-format files after an edit)
- UserPromptSubmit — runs when the user submits a prompt (e.g., inject context, load memory files)
- Notification — runs when Claude sends a notification (e.g., log alerts or trigger external systems)
- Stop — runs when Claude's agent loop ends (e.g., clean up temporary files, send a completion message)
Hooks are powerful, and the open-source community has begun sharing useful hooks in GitHub repositories. HookHub is a site designed to discover and browse these community hooks.
The Spec-Writing Prompt
With plan mode active and Claude Opus selected, the following prompt was submitted to Claude. Notice that it is conversational and direct — no advanced prompt engineering was applied:
I want you to help me write a spec file for a project I am building. It's called "hookhub". It's a place where cool open source Claude hooks are displayed and browsed. Search on Claude hooks and write an initial spec for this. Remember it's an MVP ATM and we need only the functionality of displaying the hooks. Hooks are found in GitHub repositories, they have name, category, description and link to repo. The main page should display the hooks in a grid-like view.
The prompt accomplishes several things at once:
- Describes the project name and purpose (HookHub — browse open-source Claude hooks)
- Asks Claude to research the domain before writing (search for Claude hooks)
- Constrains the scope explicitly — this is an MVP, display-only
- Defines the data model: hooks have a name, category, description, and repository link
- Defines the UI layout: a grid view on the main page
Claude's Research Phase in Plan Mode
Because plan mode restricts Claude to read-only operations, Claude begins by calling web search tools to research Claude Code hooks. It fetches documentation from Anthropic's official docs and browses community repositories for real-world hook examples. At each step, Claude may ask for permission to fetch a URL — approve these requests to allow the research to complete.
After gathering enough information, Claude presents a plan for what the spec file will contain. This is your opportunity to review and adjust before any file is written. A typical plan for HookHub would include:
- Project overview and vision
- MVP scope definition — what is in and what is out
- Hook data model (fields and types)
- UI and UX requirements
- Technical architecture and stack recommendation
- User stories
- Future considerations beyond the MVP
Once you approve the plan, Claude exits plan mode and moves into write mode to generate the spec file.
Redirecting the Output Location
By default, Claude may suggest writing the spec to a file like hookhub/SPEC.md. However, since we want the spec to be auto-loaded by Claude Code as project memory, we should store it as a CLAUDE.md file inside a spec/ directory. When Claude proposes the file path, decline and instruct it to use spec/CLAUDE.md instead:
I want you to write it into a spec directory and make this a CLAUDE.md file
Claude will adjust its plan and write the file to spec/CLAUDE.md. Approve this action.
The Generated Spec File
What Claude Produces
After approving the plan and the file path, Claude generates a comprehensive specification. The content reflects the research Claude conducted — it includes real hook categories, a realistic data model, and actionable implementation steps. Below is an example of what a generated spec/CLAUDE.md looks like for HookHub:
Why This Spec Is Valuable
Notice that the spec includes specific implementation guidance — the stack, the project structure, the component breakdown, and the build steps. This information did not come from guessing; Claude researched Claude Code hooks and drew on its knowledge of Angular and modern web development to produce a coherent plan.
Every time you open a new Claude Code session, this spec is loaded automatically because it lives in a CLAUDE.md file. Claude always knows what HookHub is, what is in scope, what the data model looks like, and how the project should be structured. This dramatically reduces the chance of the model making wrong assumptions during implementation.
Organizing Specs Inside the Memory Directory
The Memory Directory Pattern
As your project grows, you will accumulate multiple context files: frontend conventions, backend standards, deployment guides, and the product spec itself. A clean practice is to centralise all long-term context under a single memory/ directory at the project root. This makes it easy to manage, version, and extend your agent's persistent context.
Move the spec file you just created into the memory directory:
The memory/frontend/CLAUDE.md file contains Angular-specific rules — component naming, signal patterns, file structure conventions, and what CSS libraries are (or are not) allowed. The memory/spec/CLAUDE.md is the product specification. Together, they give Claude everything it needs to write consistent, well-aligned code without being reminded each time.
How CLAUDE.md Files Are Loaded
Claude Code walks up the directory tree from the current working directory and loads all CLAUDE.md files it finds. Because memory/spec/CLAUDE.md is a CLAUDE.md file within the project, it will be discovered and loaded automatically each session.
You can also use the @import directive inside a parent CLAUDE.md to explicitly include specific files. This gives you fine-grained control over what is loaded and when:
This pattern scales well. As the project grows, you add new files to the memory/ directory and import them in the root CLAUDE.md. Claude automatically picks up all the new context at the start of the next session.
Summary
Spec-driven design is a disciplined practice that separates the thinking phase from the coding phase. By asking Claude to research the domain and write a specification first — using Plan Mode and a capable model like Opus — you produce a document that dramatically improves the quality and consistency of everything Claude generates afterwards.
The key workflow is:
- Press Shift + Tab to enter Plan Mode
- Run
/modelsand select Claude Opus for deep reasoning - Submit a clear prompt describing the project, its scope, and its data model
- Review Claude's proposed plan and approve it
- Redirect the output to
spec/CLAUDE.md, then move it tomemory/spec/CLAUDE.md - Use the spec throughout implementation — Claude loads it automatically
This is one of the simplest and most effective ways to get consistently good results from Claude Code on real-world projects.