{"id":3511,"date":"2026-05-15T02:08:01","date_gmt":"2026-05-15T02:08:01","guid":{"rendered":"https:\/\/aiopsschool.com\/blog\/?p=3511"},"modified":"2026-05-15T02:08:50","modified_gmt":"2026-05-15T02:08:50","slug":"writing-spec-files-your-features-memory-for-claude","status":"publish","type":"post","link":"https:\/\/aiopsschool.com\/blog\/writing-spec-files-your-features-memory-for-claude\/","title":{"rendered":"Writing Spec Files \u2014 Your Feature&#8217;s Memory for Claude"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">What is a spec file?<\/h2>\n\n\n\n<p>A spec file is a short markdown document that describes <strong>what<\/strong> you want built, <strong>before<\/strong> you ask Claude to write any code. It&#8217;s the second most important habit when working with Claude (after <code>CLAUDE.md<\/code>), and it&#8217;s the single biggest quality multiplier for non-trivial features.<\/p>\n\n\n\n<p>Think of it like a mini-brief: durable, reviewable, and read by Claude as authoritative context every time you reference it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why bother? Why not just chat?<\/h2>\n\n\n\n<p>Most people skip specs and dump requirements into a chat message. That works for tiny tasks, but for real features it causes three problems:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Claude makes assumptions you didn&#8217;t intend<\/strong> \u2014 without a clear scope, it fills gaps with guesses<\/li>\n\n\n\n<li><strong>Context dies with the chat session<\/strong> \u2014 next week, you&#8217;re re-explaining the same thing<\/li>\n\n\n\n<li><strong>You can&#8217;t review or share it<\/strong> \u2014 teammates have no idea what was asked<\/li>\n<\/ul>\n\n\n\n<p>A spec file fixes all three. Half a page is usually enough \u2014 the point isn&#8217;t a formal PRD, it&#8217;s forcing yourself to think clearly before code starts.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What goes in a spec file<\/h2>\n\n\n\n<p>Four sections, kept short:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Goal<\/strong> \u2014 one or two sentences on what this feature does and why<\/li>\n\n\n\n<li><strong>User stories \/ scenarios<\/strong> \u2014 concrete examples of how it&#8217;s used<\/li>\n\n\n\n<li><strong>Acceptance criteria<\/strong> \u2014 a checklist of what &#8220;done&#8221; looks like<\/li>\n\n\n\n<li><strong>Out of scope<\/strong> \u2014 what this feature explicitly does NOT do (this prevents Claude from over-building, which is a common failure mode)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Where to put it<\/h2>\n\n\n\n<p>Use a per-feature folder structure under <code>docs\/<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docs\/features\/login\/\n\u251c\u2500\u2500 spec.md           \u2190 what to build\n\u251c\u2500\u2500 design.md         \u2190 how to build it (added later)\n\u251c\u2500\u2500 decisions.md      \u2190 why we chose X over Y\n\u2514\u2500\u2500 notes.md          \u2190 session notes, open questions\n<\/code><\/pre>\n\n\n\n<p>This scales: by feature 20, a flat <code>specs\/<\/code> folder is unfindable. Grouping by feature keeps related files together, and you can sit <code>docs\/architecture\/<\/code>, <code>docs\/runbooks\/<\/code>, <code>docs\/adr\/<\/code> alongside without anything getting tangled.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A note on filenames and paths<\/h2>\n\n\n\n<p>Neither the filename <code>spec.md<\/code> nor the path <code>docs\/features\/&lt;name&gt;\/<\/code> has any built-in significance to Claude \u2014 they&#8217;re just regular files and folders. Claude only reads them when you point to them. You could call the file <code>requirements.md<\/code> or <code>brief.md<\/code> and Claude would treat it identically.<\/p>\n\n\n\n<p>What gives them significance is <strong>consistency<\/strong> and <strong>your <code>CLAUDE.md<\/code><\/strong>. Add one line to your root <code>CLAUDE.md<\/code>:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Feature work lives in <code>docs\/features\/&lt;feature-name&gt;\/<\/code>. Each folder contains <code>spec.md<\/code> (requirements), <code>design.md<\/code> (implementation plan), and <code>decisions.md<\/code> (key choices and rationale).<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Now when you say <em>&#8220;start work on the login feature,&#8221;<\/em> Claude knows where to look without you spelling out paths every time. Pick a convention, document it, stick with it \u2014 consistency beats cleverness.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to use a spec file with Claude<\/h2>\n\n\n\n<p>The pattern is <strong>spec first, plan second, code third<\/strong>. Instead of saying <em>&#8220;build me a login feature with email and password,&#8221;<\/em> you say:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>&#8220;Read <code>docs\/features\/login\/spec.md<\/code> and propose an implementation plan. Don&#8217;t write code yet.&#8221;<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>Claude reads the spec, asks clarifying questions, proposes a plan. You review the plan, push back, refine. <strong>Only then<\/strong> do you let it write code. This three-step rhythm catches misunderstandings before they become diffs you have to throw away.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quick start<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create <code>docs\/features\/&lt;feature-name>\/spec.md<\/code> with the four sections above<\/li>\n\n\n\n<li>Add the convention line to your root <code>CLAUDE.md<\/code><\/li>\n\n\n\n<li>Reference the spec by full path when prompting Claude<\/li>\n\n\n\n<li>After implementation, add <code>decisions.md<\/code> to capture key choices for future you<\/li>\n<\/ol>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>What is a spec file? A spec file is a short markdown document that describes what you want built, before [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[916],"tags":[],"class_list":["post-3511","post","type-post","status-publish","format-standard","hentry","category-claude"],"_links":{"self":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/3511","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=3511"}],"version-history":[{"count":1,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/3511\/revisions"}],"predecessor-version":[{"id":3512,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/3511\/revisions\/3512"}],"wp:attachment":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=3511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=3511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=3511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}