Lean Spec Format
Lean Mode is the evolution of Planu's Spec Driven Development workflow. It replaces the old two-file layout (separate spec.md + technical.md) with a single unified document carrying rich frontmatter. The result is less context overhead, less drift between files, and a machine-readable header that Planu tools can act on autonomously.
What is Lean Mode
Before Lean Mode, every spec required two files:
spec.md— acceptance criteria and problem statementtechnical.md— implementation detail, types, and file lists
Keeping both in sync was error-prone. Lean Mode collapses them into a single spec.md with:
- A structured YAML frontmatter block carrying identity, status, model guidance, and budget constraints
- A
## Technicalsection at the bottom of the same file (see Unified spec.md)
Token impact. Legacy specs pulled ~50–100 K tokens of context per request. Lean specs load in ~5 K tokens because Planu reads only the frontmatter to route requests and only expands the full body when needed.
Frontmatter Reference
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique identifier, format SPEC-NNN |
title | string | yes | Human-readable spec title (sentence case) |
status | enum | yes | draft / review / approved / implementing / done / blocked |
type | enum | yes | feature / fix / docs / refactor / chore |
target | string | no | Primary layer — frontend, backend, infra, cross-module |
scope | string | no | Blast radius — module, cross-module, system |
difficulty | 1–5 | no | Complexity score (1 trivial, 5 architectural) |
risk | enum | no | low / medium / high |
model | enum | yes | Recommended model for implementation — haiku / sonnet / opus |
budget | number | yes | Max token budget for a single implementation run |
estimation.devHours | number | yes | Dev effort in hours |
estimation.reviewHours | number | no | Review effort in hours |
estimation.totalCostUsd | number | yes | Estimated USD cost at the given model's rate |
tags | string[] | yes | Searchable tags (e.g. [website, docs, vitepress]) |
branch | string | no | Git branch name — auto-set by create_spec |
created | YYYY-MM-DD | yes | Date the spec was created |
completedAt | YYYY-MM-DD | no | Date the spec reached done — auto-set by update_status |
Annotated Example
---
id: SPEC-659 # Unique identifier — never reuse
title: "Website — 5 new guide pages for Lean Mode features"
# Human-readable, sentence case, no trailing period
status: implementing # Current lifecycle stage — drives autopilot
type: docs # One of: feature / fix / docs / refactor / chore
target: frontend # Layer most affected by this work
scope: cross-module # How widely the change spreads
difficulty: 2 # 1–5 scale (2 = moderate, mainly content work)
risk: low # Expected blast radius
tags: [website, docs, lean-mode, guide, vitepress]
# Used by handoffs/skills to load focused context
branch: docs/spec-659-website-5-new-guide-pages-for-lean-mode-features
created: 2026-04-24
model: sonnet # Planu uses this to recommend which Claude model to use
budget: 2000 # Max tokens for a single implementation agent run
estimation:
devHours: 6 # Human dev effort (used in velocity reports)
reviewHours: 1
totalCostUsd: 8 # Sonnet rate × budget ÷ 1000
---Why model and budget matter
Planu reads model and budget to pre-validate that the implementation plan fits within the token envelope before spawning sub-agents. Setting them correctly prevents mid-run truncation.
Status Lifecycle
The status field is the control plane for Auto-Status Transitions. Moving through statuses triggers autopilot cascades:
draft → review → approved → implementing → doneEach transition is driven by calling update_status. See Auto-Status Transitions for the full cascade table.
Cross-links
- Unified spec.md (SPEC-630) — the
## Technicalsection that lives inside the same file - Focused MCP Surface — why Planu keeps the public MCP tool list small
- Auto-Status Transitions — what happens when
statuschanges