Claude Code Claude Code Created: 13 Apr 2026 Updated: 13 Apr 2026

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.

# Toggle between write mode and plan mode
Press: Shift + Tab

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.

# Open the model picker inside Claude Code
/models

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:

  1. PreToolUse — runs before Claude calls any tool (e.g., block dangerous commands, validate inputs)
  2. PostToolUse — runs after a tool call completes (e.g., auto-format files after an edit)
  3. UserPromptSubmit — runs when the user submits a prompt (e.g., inject context, load memory files)
  4. Notification — runs when Claude sends a notification (e.g., log alerts or trigger external systems)
  5. 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:

  1. Describes the project name and purpose (HookHub — browse open-source Claude hooks)
  2. Asks Claude to research the domain before writing (search for Claude hooks)
  3. Constrains the scope explicitly — this is an MVP, display-only
  4. Defines the data model: hooks have a name, category, description, and repository link
  5. 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:

  1. Project overview and vision
  2. MVP scope definition — what is in and what is out
  3. Hook data model (fields and types)
  4. UI and UX requirements
  5. Technical architecture and stack recommendation
  6. User stories
  7. 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:

# HookHub — Product Specification (CLAUDE.md)

## Project Overview

**HookHub** is a community-driven directory for discovering and browsing open-source
Claude Code hooks. Claude Code hooks are lifecycle scripts that extend the Claude Code
agent loop — they run at key moments such as before a tool call, after a file edit,
or when a user submits a prompt. HookHub makes it easy for developers to find and
share reusable hooks.

**This is the reference document for all development work. Always consult this file
before adding features or making architectural decisions.**

---

## Vision

A simple, fast, and beautiful directory where Claude Code users can discover community
hooks — searchable by category, viewable in a clean grid, and linked directly to the
source repository.

---

## MVP Scope

The MVP includes only the functionality needed to display hooks. No authentication,
no submissions, no backend CMS.

### In Scope
- Main page displaying hooks in a responsive grid
- Hook cards showing name, category, description, and repo link
- Category filter (client-side)
- Static data source (JSON file in the repository)

### Out of Scope (Post-MVP)
- User submissions
- Authentication
- Search with a backend
- Rating or voting system
- Comments

---

## Hook Data Model

Each hook is represented as a JSON object with the following fields:

| Field | Type | Description |
|---------------|----------|----------------------------------------------|
| id | string | Unique identifier (slug) |
| name | string | Human-readable display name |
| category | string | One of the defined hook categories |
| description | string | Short description (1–2 sentences) |
| repoUrl | string | Link to the GitHub repository |
| author | string | GitHub username of the author |
| hookType | string | Claude Code lifecycle event (e.g. PreToolUse)|

### Hook Categories
- **Security** — blocks dangerous commands, validates inputs
- **Code Quality** — auto-formatting, linting after edits
- **Context Management** — injects memory, loads project files
- **Logging & Auditing** — records tool calls and outputs
- **Notifications** — sends alerts to Slack, email, or desktop
- **Workflow Automation** — CI triggers, commit helpers

---

## UI and UX Requirements

### Main Page
- Responsive grid layout (3 columns on desktop, 2 on tablet, 1 on mobile)
- Each card displays: hook name (heading), category badge, description, and "View Repo" button
- Category filter buttons at the top — clicking a category filters the visible cards
- No pagination needed for MVP (expected: < 50 hooks)
- Clean, minimal aesthetic — focus on readability

### Hook Card
- Card title: hook name
- Badge: category (colour-coded by category)
- Body: description text (max 2 lines, truncated)
- Footer: author username + "View Repo" button linking to repoUrl

---

## Technical Architecture

### Stack
- **Framework**: Angular (standalone components, signals)
- **Data Source**: Static JSON file at `src/assets/hooks.json`
- **Styling**: Plain CSS (no external UI libraries)
- **Hosting**: GitHub Pages or any static host

### Project Structure
\`\`\`
hookhub/
├── src/
│ ├── app/
│ │ ├── app.component.ts
│ │ ├── hook-card/
│ │ │ └── hook-card.component.ts
│ │ └── category-filter/
│ │ └── category-filter.component.ts
│ └── assets/
│ └── hooks.json
├── spec/
│ └── CLAUDE.md <-- this file
└── memory/
├── spec/
│ └── CLAUDE.md
└── frontend/
└── CLAUDE.md
\`\`\`

---

## User Stories

1. **As a developer**, I want to browse available Claude Code hooks so I can find ones
useful for my project.
2. **As a developer**, I want to filter hooks by category so I can quickly find relevant
hooks without scrolling.
3. **As a developer**, I want to see a hook's description and repository link so I can
evaluate and use it.

---

## Build Steps

1. Generate Angular project with `ng new hookhub --standalone`
2. Create the `Hook` interface matching the data model above
3. Create `hooks.json` with at least 6 sample hooks
4. Build `HookCardComponent` — input: `Hook` object, output: styled card
5. Build `CategoryFilterComponent` — emits selected category to parent
6. Wire filtering logic in `AppComponent` using Angular signals
7. Implement responsive grid layout in plain CSS

---

## Future Considerations

- Allow community submissions via GitHub pull requests (hooks.json as the source of truth)
- Add full-text search
- Add hook ratings and view counts (requires backend)
- Add a "copy to clipboard" button for hook configuration snippets
- Add dark mode toggle

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:

memory/
├── frontend/
│ └── CLAUDE.md # Angular conventions, component patterns, CSS rules
└── spec/
└── CLAUDE.md # HookHub product specification (this file)

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:

# Root CLAUDE.md (project root)

@memory/spec/CLAUDE.md
@memory/frontend/CLAUDE.md

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:

  1. Press Shift + Tab to enter Plan Mode
  2. Run /models and select Claude Opus for deep reasoning
  3. Submit a clear prompt describing the project, its scope, and its data model
  4. Review Claude's proposed plan and approve it
  5. Redirect the output to spec/CLAUDE.md, then move it to memory/spec/CLAUDE.md
  6. 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.


Share this lesson: