Releases: 4nkur/draftwise
v0.2.5 — clarify, refine, and a constitution
Install
npm install -g draftwiseOr upgrade:
npm install -g draftwise@0.2.5Slash commands in your AI harness — pick one (both can coexist):
# bare /draftwise <verb> across Claude Code, Cursor, and Gemini CLI
draftwise skills install
# Claude Code marketplace plugin (slash form is /draftwise:draftwise <verb>)
/plugin marketplace add 4nkur/draftwise
/plugin install draftwiseThe host-agent-first release. API mode is gone — Draftwise runs only inside coding agents now (Claude Code, Cursor, Gemini CLI), printing scanner data plus an instruction for the host agent's model to synthesize. The interactive prompt layer (@inquirer/prompts) is gone with it: every command takes its full input set as flags or positional args, and the CLI never blocks on stdin. With synthesis moved entirely into the host agent, voice and spec-quality rules now live in .draftwise/constitution.md — a user-editable, version-controlled file every drafting prompt tells the agent to read before drafting. Two new commands fill out the spec lifecycle: draftwise clarify audits an existing product spec for ambiguities + missing edge cases before drafting tech; draftwise refine re-grounds a spec while preserving PM hand-edits.
Highlights
draftwise clarify [<feature>]— audit a product spec for ambiguities, untested assumptions, internal contradictions, and missing edge cases before drafting tech. The agent walks you through each issue (defer / reject / answer) and rewrites the file in place. Catches gaps before the engineering plan gets built on a shaky foundation.draftwise refine [<feature>] [--type=product|tech|tasks]— re-ground a spec without clobbering PM hand-edits. The agent audits each section as strong-leave-alone or weak-rewrite and only re-grounds the weak ones; strong sections survive character-for-character. Resolves the long-standing "AI-assisted spec merge mode" open question..draftwise/constitution.md— user-editable rules file every drafting command reads. Five stable sections — Voice, Spec language, Edge case discipline, Project conventions, Domain glossary — that prompts reference by name. Tune Draftwise's voice and spec discipline without editing prompts in the npm package.product-spec.mdgainsdepends_on:/related:frontmatter.draftwise listsurfaces a fourth DEPENDS ON column. The cheap version of cross-spec tracking — declarative, in the spec, no graph traversal.- API mode + interactive prompts dropped. Draftwise is purely a host-agent executor now: load context, print an instruction, exit.
Added
draftwise refine [<feature>] [--type=product|tech|tasks]— reads the chosen file (product-spec.mdby default,technical-spec.mdfor--type=tech,tasks.mdfor--type=tasks) plus the upstream source-of-truth (scanner output for product/tech brownfield,overview.mdfor greenfield, plus the upstream spec for tech/tasks), then prints a three-phase instruction telling the host coding agent to (1) audit each section as strong-leave-alone or weak-rewrite — bar is "actively misleads or under-specifies," not "could be tighter"; (2) re-ground the weak sections, removing or marking(unverified)any code reference the scanner doesn't surface; (3) save the refined file back, preserving strong sections character-for-character and any YAML frontmatter at the top ofproduct-spec.mdverbatim. Hard rules in the prompt: no fabricated code references, no scope creep, don't touch sections that are already strong.draftwise clarify [<feature>]— readsproduct-spec.mdand prints an instruction telling the host coding agent to audit the spec across four categories (ambiguities, untested assumptions, internal contradictions, missing edge cases), present each issue with a specific line/section pointer, walk the PM through them one at a time (defer / reject / answer), and rewrite the file in place — preserving the YAML frontmatter and any sections the PM didn't touch. Hard rule: don't widen scope; if the PM's answer expands the feature, push back — that's a new spec, not a clarification.product-spec.mdopens with optional YAML frontmatter declaringdepends_on:andrelated:slugs;draftwise listsurfaces them.draftwise newinstructs the agent to list.draftwise/specs/first and only reference slugs that exist on disk.draftwise listgrew a fourth column — DEPENDS ON — between STATUS and TITLE. Frontmatter parsing in a newsrc/utils/frontmatter.js(handles CRLF, malformed YAML, and non-object roots gracefully)..draftwise/constitution.md—draftwise initwrites a default template into the project on both the brownfield and greenfield paths. Five stable section headings every prompt module references by name: Voice, Spec language, Edge case discipline, Project conventions, Domain glossary. Every drafting prompt (new,tech,tasks,scan,explain,greenfieldPhase 3) reads the file before drafting;scanand the greenfield Phase 3 additionally refine the Project conventions section from observed code / chosen stack. Skip-silently-if-absent for back-compat with projects that raninitbefore this feature landed.
Changed
draftwise skills installauto-detects which AI harnesses are on the machine instead of writing to all three by default.detectInstalledProviderschecks which of~/.claude/~/.cursor/~/.geminiexist at the chosen scope root and installs only to those; the detected set is logged.--provider=allis the explicit opt-in for the old behavior;--provider=<name>still targets one harness regardless of detection.skills uninstallkeeps its existing "iterate every known dir, skip empty" behavior — different goal (cleanup whether or not the harness is still on disk).skills helpnow prints the auto-detect set so you can see it without running install.
Removed
@inquirer/promptsdropped; CLI is purely flag-driven now. Init's idea input, tech/tasks' spec picker, and scaffold's confirm are all gone. Concrete behavior changes:tech/taskswith multiple specs and no slug arg now error with the available list;scaffoldrequires--yesto confirm;initgreenfield without--ideaalways prints the structured agent handoff. The TTY/non-TTY distinction is gone entirely —src/utils/tty.js,test/setup.js, andvitest.config.jsare deleted.- API mode dropped — Draftwise runs only inside coding agents now. The api path that called Claude directly via
@anthropic-ai/sdkand wrote specs from the CLI is gone.initloses its--ai-mode,--provider,--api-key-env,--stack, and--answersflags;new/tech/taskslose--force(and--answersonnew).config.yaml'sai:block is no longer used; existing configs keep working —loadConfigprints a one-line notice telling you the block is safe to delete, then ignores it. Every prompt module now exports justbuildAgentInstruction(orAGENT_INSTRUCTIONforscan).
Full changelog: CHANGELOG.md
v0.2.1 — skills everywhere, init that just works
Install
npm install -g draftwiseOr upgrade:
npm install -g draftwise@0.2.1Slash commands in your AI harness — pick one (both can coexist):
# bare /draftwise <verb> across Claude Code, Cursor, and Gemini CLI
draftwise skills install
# Claude Code marketplace plugin (slash form is /draftwise:draftwise <verb>)
/plugin marketplace add 4nkur/draftwise
/plugin install draftwiseThe polish + cleanup release. Half ergonomic improvements (draftwise init now auto-detects new project vs existing codebase from the filesystem; plain-language UX throughout init), half code-quality work (five small dedup + tidy PRs that shrink the public API surface, fix two draft → draftwise typos in error messages, and consolidate drafting-command boilerplate behind shared helpers). One genuinely new surface: draftwise skills <install|uninstall|help> drops standalone slash-command skills into Claude Code, Cursor, and Gemini CLI's user-level skill dirs — independent of the Claude Code marketplace plugin.
Highlights
draftwise skills <install|uninstall|help>— standalone slash-command skill across Claude Code, Cursor, and Gemini CLI. Bare/draftwise <verb>chat form, matching the CLI binary. Independent of the marketplace plugin; both can coexist.draftwise initauto-detects new vs existing project. No more "are you greenfield or brownfield?" question — Draftwise walks the cwd for source files and decides.--mode=greenfield|brownfieldstill available as an override.- Plain-language UX. "Greenfield" / "brownfield" demoted from user-facing copy to internal flag values. Now reads "new project (no code yet)" / "existing codebase".
Added
draftwise skills <install|uninstall|help>— three subcommands grouped underskills.installwritesplugin/skills/draftwise/(SKILL.md + per-verb references) into each known harness's user-level skill dir (~/.claude/skills/draftwise/,~/.cursor/skills/draftwise/,~/.gemini/skills/draftwise/);uninstallremoves them;helpprints a 3×2 state table (3 harnesses × 2 scopes).--provider=claude|cursor|gemini|allnarrows;--scope=user|projectswitches between~and<cwd>;--forceoverwrites on install. Same SKILL.md across providers with a tiny per-provider frontmatter trim — Claude-onlyuser-invocable/argument-hint/allowed-toolsstripped for Cursor + Gemini; body identical.
Changed
draftwise initauto-detects from the filesystem. Walks the cwd using scanner.js'sIGNORE_DIRS+CODE_EXTENSIONSand bails on the first source file: zero → greenfield; one or more → brownfield. Logged in plain language with an explicit override hint.- Plain-language init UX. "Greenfield" / "brownfield" still surface in three places where they're load-bearing (canonical
--modeflag values,config.yaml'sproject.statefield, detailed flag-help text). Everywhere else leads with "new project" / "existing codebase". - Five dedup + tidy PRs across the codebase.
draftwise scanreuses the sharedcompactScanprojection helper.extractJsonFromFence(used byinitgreenfield +new's plan call) andloadAnswersFlag(used byinitandnew) extracted into shared utility modules. The greenfield/brownfield scan-context branch (innew/tech/tasks), the overwrite-confirm dance (same three commands), and the.draftwise/existence guard (eight commands) consolidated intoscan-context.js,overwrite-guard.js, anddraftwise-dir.js. 12 new direct unit tests for the extracted helpers; 332 tests passing total, lint clean.
Fixed
- Two user-visible error messages referenced a non-existent
draftbinary instead ofdraftwise.src/commands/show.js(when a missing spec type was requested) andsrc/ai/provider.js(when the OpenAI / Gemini stub adapter was hit). Relics from a pre-rename era.
Removed
- Dead backwards-compat aliases on the prompt modules.
PLAN_SYSTEM/SPEC_SYSTEMfromsrc/ai/prompts/new.jsand the top-levelSYSTEMaliases fromtech.js/tasks.js— three exports marked "Backwards compatibility — keep the old names alive" that never had real callers (verified by grep acrosssrc/andtest/).scan.jsandexplain.jskeep theirSYSTEMexports — those are primary, not aliases.
Full changelog: CHANGELOG.md
v0.2.0 — Mode 1, for real
Install
npm install -g draftwiseFor Claude Code slash commands:
/plugin marketplace add 4nkur/draftwise
/plugin install draftwise
After that, /draftwise init, /draftwise new "<idea>", /draftwise tech, etc. work in Claude Code chat. The plugin shells out to the npm-installed draftwise CLI under the hood.
The "Mode 1, for real" release. Draftwise now ships a Claude Code plugin so PMs drive spec drafting from /draftwise <verb> slash commands in chat — backed by a CLI that's been refactored to flags-first so non-TTY shells (CI, coding-agent harnesses) work without inquirer hanging on prompts.
Highlights
/draftwiseslash commands inside Claude Code. Install the plugin via/plugin marketplace add 4nkur/draftwisethen/plugin install draftwise. Drives/draftwise init,/draftwise new "<idea>",/draftwise tech,/draftwise tasks,/draftwise scan,/draftwise explain,/draftwise list,/draftwise show,/draftwise scaffold— each one shells out to the CLI under the hood and walks the user through any missing input in chat.- Non-interactive everywhere. Every CLI command takes its full input set as flags (
--mode,--ai-mode,--idea,--answers @file.json,--force,--yes, etc.). Non-TTY shells are the default execution context; inquirer is a TTY-only convenience that fills missing values when available. Mode 1 (host-agent-driven) actually works now. draftwise initsmart non-TTY handoff. When run with insufficient flags in a non-TTY shell, prints a structured handoff (questions + re-invocation template) for the host coding agent to consume — instead of erroring. The agent walks the user through it in chat, then re-invokes with collected flags.
Added
- Claude Code plugin:
/draftwiseslash commands. New.claude-plugin/marketplace.jsonat repo root declares a singledraftwiseplugin withsource: ./plugin. Insideplugin/lives the install manifest (.claude-plugin/plugin.json) plus a single skillskills/draftwise/SKILL.mdthat routes user input to per-verb references atskills/draftwise/reference/<verb>.md(one per CLI verb). Each reference walks the model through how to drive that verb in chat — collect inputs, shell out to the npm-installeddraftwiseCLI, parse the structured handoff or streamed output, report back. Plugin name = skill name =draftwiseso the slash form is/draftwise <verb>(no<plugin>:<skill>namespacing in command logs). Plugin is distributed separately from the npm package —package.jsonfilesdoes not include the plugin directories. SKILL.md includes a "Setup gates" table making the verb-dependency chain explicit and a "Conversation standards" section that pulls in the eight collaboration principles fromsrc/ai/prompts/principles.jsby reference, so the chat-driven flow matches what the CLI's api-mode synthesis enforces. Per-verb references add pre-flight gate checks (catch missing prerequisites in chat instead of letting the CLI throw), tone-shaping guidance for ambiguous flag questions, idea-concreteness check fornew(one-word ideas get one elaboration ask before invoking), and review nudges fortech/tasks. Closes #42.
Changed
draftwise initnon-TTY: structured agent handoff instead of bare error. Whendraftwise initruns in a non-TTY shell with too few flags to proceed, it now prints a structured handoff underAGENT_HANDOFF_PREFIX— a numbered list of the questions still to answer (project state, AI mode, optionally provider and idea) plus a re-invocation template — and exits cleanly. The host coding agent reads the handoff from stderr, asks the user in chat, and re-invokesdraftwise initwith the collected flags. Replaces the earlier "Missing --mode flag" / "Missing --ai-mode flag" / "Missing --provider flag" / "Missing --idea" hard errors. Validation errors (invalid flag values, unknown flags) still throw; the handoff is specifically for "I need more input" cases. Closes #41.- Flags-first input across every command; inquirer becomes a TTY-only convenience. Every command (
init,new,tech,tasks,scaffold) now takes its full input set as named flags parsed via Node's built-inutil.parseArgs. When stdin is a TTY and a value is missing, inquirer fires to fill it in — that's the only place inquirer lives. When stdin is not a TTY (CI, coding-agent shell like Claude Code/Cursor), required values must come from flags; missing ones error with a specific usage hint instead of hanging on a prompt. New flags:initgains--mode,--ai-mode,--provider,--api-key-env,--idea,--stack,--answers <json|@file>;newgains--answers <json|@file>;scaffoldgains--yes(-y);tech/tasksreject the inquirer picker in non-TTY when multiple specs exist (must pass slug positionally). Overwrite-confirms innew/tech/taskserror in non-TTY without--forceinstead of falling through. Closes #40.
Full changelog: CHANGELOG.md
v0.1.5 — sharper specs, safer edits, live streaming
The "shipped quality" release. Specs read sharper, hand-edits are safer, and the toolchain has CI, lint, cache versioning, and prompt-quality rules that actually do work.
Highlights
- Specs read sharper. Two new shared prompt blocks shape every drafted spec:
CORE_PRINCIPLES(no filler, redirect drift, push back on weak ideas, extend before adding, flag bad assumptions, verify before asserting, offer the counter-case) injected into every drafting / conversational prompt; andspec-quality.js(specific over generic, active voice, same term every time, cut filler, examples for ambiguous claims, don't blame users, equal-effort sections) injected into the synthesis prompts fornewandtech.techalso gets an edge-case discipline block — every endpoint / model / component must name empty data, errors, loading, permissions, concurrency, and large-data behavior inline. - Hand-edits stay safe. Re-running
draftwise new/tech/tasksagainst an existing target file now prompts to confirm before overwriting; default is to cancel. New--forceflag skips the prompt for scripted use. Agent mode is exempt (the host agent does the write). - Live token streaming.
scan,explain,new(spec phase),tech, andtasksstream the model's output to stdout token-by-token. The 10–30s "Synthesizing…" pause is gone. - First-run polish. CLI copy is sharper end-to-end. Init AI-config prompts read as questions instead of bare labels, the greenfield Q&A drops stiff suffixes, agent-mode handoffs prepend an orienting line for plain-terminal users,
scanends with aNext: ...nudge, andscaffoldshort-circuits cleanly on brownfield. - Hardening. CI workflow runs lint + test on every PR (Node 20 + 22). Scan cache gains a schema version. Path-traversal guard in
scaffold. Error chains preserved across re-throws. ESLint config that actually works (thelintscript was broken before).prepublishOnlyblocks releases on broken main.
Added
- Spec-quality rules baked into the drafting prompts. New module
src/ai/prompts/spec-quality.jsexportsSPEC_LANGUAGE_RULESandEDGE_CASE_DISCIPLINE, injected into the synthesis SYSTEM fornewandtech. Same single-source-of-truth pattern asprinciples.js. (#35) - Overwrite protection on
new,tech, andtasks. Confirm prompt with--forceto bypass; positioned before the synthesis API call so a cancel doesn't burn tokens. Agent mode exempt. (#36) - Shared collaboration principles in every drafting / conversational AI prompt.
CORE_PRINCIPLESinjected at the top ofinitgreenfield's QUESTIONS_SYSTEM and STACKS_SYSTEM, all fournewsystem prompts, and bothtechandtasks. (#23) - Live token streaming for synthesis calls via the Anthropic SDK's
messages.stream()API. (#28) - End-to-end integration test driving every command in sequence against real temp directories. (#29)
- Dependabot config — weekly npm bumps + monthly GitHub Actions bumps. (#30)
- Streaming wiring assertions in
scan,new,tech,taskstests so a refactor that drops streaming silently can't slip through. (#30) - HELP consistency test set verifying every command exports a
HELPstring starting withdraftwise <cmd>. (#30) stream.abort()on errors insrc/ai/providers/claude.js— closes the underlying HTTP request when iteration oronTokenthrows. (#30)mapConcurrentno-cancel doc note. (#30)--version/-vflag on the CLI. (#27)- Per-command
--help/-h. (#27) .prettierrc— explicit Prettier defaults. (#27)- CI workflow running
npm ci,npm run lint, andnpm teston Node 20 and Node 22. (#26) - Cache schema version —
.draftwise/.cache/scan.jsonnow carries acacheVersionfield. (#26) eslint.config.js— ESLint v10 flat config;npm run lintactually works now. (#22)- Tests for
src/ai/provider.jsandsrc/ai/providers/claude.js— provider router and Claude SDK adapter both got direct unit coverage. (#22) - Path-traversal guard in
draftwise scaffold— paths that escape the project root are blocked instead of written. (#22) DRAFTWISE_DEBUG=1for stack traces. (#22)prepublishOnlyscript — runs lint + tests before publish so a broken main can't ship. (#22)
Changed
- First-run polish — three small UX fixes from the pre-release critique:
scannext-step nudge, agent-mode orienting prefix across all six commands,scaffoldbrownfield short-circuit. (#37) - Clarify pass over CLI copy — init prompts read as questions, greenfield Q&A drops stiff suffixes, error messages get parity, jargon dropped from HELP. (#33)
- Informational
log()output moved to stderr sodraftwise scan > overview.mdcaptures only the streamed content. (#30) - Document the dep-pinning asymmetry in CLAUDE.md —
@anthropic-ai/sdkexact-pinned,@inquirer/prompts/yamlcaret. (#30) - Pin
@anthropic-ai/sdkto exact version (was^0.91.1). (#27) - Bump Anthropic SDK retry budget from 2 to 4 for transient blips. (#26)
- Parallelize per-file reads in scanner detectors via a 50-way bounded
mapConcurrent. (#25) - Bump default Claude
max_tokensto 16384 and exposeai.max_tokensin config. (#25) - Extract shared
pathExistsandcompactScanhelpers — pure refactor, closes audit P2 #1 and #2. (#24)
Fixed
- Preserve error chains across re-throws — five
throw new Error(...)sites now pass{ cause: err }. (#22) - Useless escapes in scanner regexes. (#22)
- Drop unused
cwdarg fromrunGreenfield. (#22)
Install: `npm install -g draftwise@0.1.5`
Full diff: v0.1.0...v0.1.5
v0.1.0 — PMs starting from scratch
The "PMs starting from scratch" release. Draftwise now meets you wherever the project is — empty directory or established codebase — and the scanner reaches beyond JavaScript.
Highlights
- Greenfield project support.
initnow asks whether you have an existing codebase or you're starting from scratch. Greenfield: walks you through 4–6 clarifying questions and proposes 2–3 stack options with rationale, pros, cons, directory structure, and setup commands. A newdraftwise scaffoldcommand turns the chosen plan into actual files.new/tech/tasksadapt their prompts when there's no code yet (every file marked(new), scaffolding tasks first). - Python scanner support. FastAPI, Starlette, Flask, Django, Tornado, plus SQLAlchemy and Django ORM. Reads
requirements.txtorpyproject.toml(PEP 621 + Poetry). Parses decorator routes, Djangourls.py, SQLAlchemy column bindings, and Django model fields. - Faster repeat runs. Fingerprinted scan cache (
.draftwise/.cache/scan.json) auto-invalidates on any file change. Configurable file cap viascan.max_filesfor monorepos.explainfilters scan output to flow-relevant items so prompts stay tight. - Better feedback. Friendly warnings when the scanner truncates due to file cap, when no framework is detected, and when running brownfield-only commands in a greenfield project.
Added
- Greenfield routing in
draftwise init. First prompt asks whether the project is greenfield or brownfield. Greenfield path runs a conversational stack-picking flow and writes a full plan tooverview.mdplus a structuredscaffold.json. Agent-mode greenfield init dumps a 3-phase instruction for the host coding agent.config.yamlgains aprojectsection (state,stack). — Ankur (#12) - Greenfield-aware
new/tech/tasks. Each command checksconfig.projectState. Greenfield path skips the scanner, readsoverview.md, and uses prompt variants that drop scanner-grounded constraints —affected_flows/adjacent_opportunitiesremoved fornew, every file marked(new)fortech, scaffolding tasks first fortasks.scanandexplainshort-circuit gracefully in greenfield. — Ankur (#13) draftwise scaffoldcommand. Reads the greenfield plan from.draftwise/scaffold.json, confirms with the user before writing, creates eachinitial_filesentry with placeholder content, skips files that already exist, prints (does not run) the setup commands. — Ankur (#14)- Scanner robustness — file cap and framework warnings. Default
maxFilesof 5000, configurable viascan.max_files. Truncation surfaces a warning across every command. Missing-framework hint listed ininit/scanwhen the scanner returns emptyframeworks. Closes Q1 and Q5. — Ankur (#15) - Python scanner support. Detects FastAPI / Starlette / Flask / Django / Tornado from
requirements.txtorpyproject.toml(PEP 621 + Poetry tables). Parses FastAPI / Flask decorator-based routes, Djangourls.pypath()/re_path(), SQLAlchemy and Django ORM models. Excludes Python test files (tests/,test_*.py,_test.py,conftest.py) from route detection. — Ankur (#16) - Scanner cache and flow filter.
cachedScan(root, opts)fingerprints the tree by mtime +maxFilesand persists results at.draftwise/.cache/scan.json;filterScanForFlow(scan, flow)narrows routes / components / models to flow-keyword matches with per-category fallback.initwrites a.draftwise/.gitignoreexcluding.cache/. Closes Q2 and Q4. — Ankur (#17) CHANGELOG.md. Single source of truth for release-by-release changes by tag ID / date / author. — Ankur (#19).gitattributesfor cross-platform line-ending consistency. Forces LF on commit and on checkout for source / config / docs / shell files. Silences "LF will be replaced by CRLF" warnings on Windows and keepsbin/draftwise.js's shebang portable. — Ankur (#20)
Changed
- Docs synced with v1 reality. CLAUDE.md "Build order for v1" replaced with "v1 status — all commands shipped". "Templates are authoritative" replaced with "Prompts are authoritative" pointing at
src/ai/prompts/<command>.js. README roadmap items checked off. — Ankur (#10) - README compatibility claims qualified. Agent-host list now reads "designed host-agnostic, smoke-tested in plain terminal so far" rather than implying every host on the list is verified. Standalone API providers explicitly marked: ✅ Claude / ⏳ GPT / ⏳ Gemini. Antigravity added to the agent-host list. — Ankur (#11)
- Pruned resolved questions out of CLAUDE.md's Open questions section. Resolved items moved to a new "Past decisions" section with implementation pointers, leaving "Open questions" for actually-open ones only. — Ankur (#18)
Fixed
- JS route detection no longer matches Python decorator syntax. A doc comment in
src/core/scanner.js(@app.get("/path")) was triggering the JS-route regex on a self-scan. Added a(?<!@)lookbehind. — Ankur (#16)