Skip to content

Releases: 4nkur/draftwise

v0.2.5 — clarify, refine, and a constitution

30 Apr 04:47
dbdcc5d

Choose a tag to compare

Install

npm install -g draftwise

Or upgrade:

npm install -g draftwise@0.2.5

Slash 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 draftwise

The 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.md gains depends_on: / related: frontmatter. draftwise list surfaces 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.md by default, technical-spec.md for --type=tech, tasks.md for --type=tasks) plus the upstream source-of-truth (scanner output for product/tech brownfield, overview.md for 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 of product-spec.md verbatim. Hard rules in the prompt: no fabricated code references, no scope creep, don't touch sections that are already strong.
  • draftwise clarify [<feature>] — reads product-spec.md and 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.md opens with optional YAML frontmatter declaring depends_on: and related: slugs; draftwise list surfaces them. draftwise new instructs the agent to list .draftwise/specs/ first and only reference slugs that exist on disk. draftwise list grew a fourth column — DEPENDS ON — between STATUS and TITLE. Frontmatter parsing in a new src/utils/frontmatter.js (handles CRLF, malformed YAML, and non-object roots gracefully).
  • .draftwise/constitution.mddraftwise init writes 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, greenfield Phase 3) reads the file before drafting; scan and 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 ran init before this feature landed.

Changed

  • draftwise skills install auto-detects which AI harnesses are on the machine instead of writing to all three by default. detectInstalledProviders checks which of ~/.claude / ~/.cursor / ~/.gemini exist at the chosen scope root and installs only to those; the detected set is logged. --provider=all is the explicit opt-in for the old behavior; --provider=<name> still targets one harness regardless of detection. skills uninstall keeps its existing "iterate every known dir, skip empty" behavior — different goal (cleanup whether or not the harness is still on disk). skills help now prints the auto-detect set so you can see it without running install.

Removed

  • @inquirer/prompts dropped; 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 / tasks with multiple specs and no slug arg now error with the available list; scaffold requires --yes to confirm; init greenfield without --idea always prints the structured agent handoff. The TTY/non-TTY distinction is gone entirely — src/utils/tty.js, test/setup.js, and vitest.config.js are deleted.
  • API mode dropped — Draftwise runs only inside coding agents now. The api path that called Claude directly via @anthropic-ai/sdk and wrote specs from the CLI is gone. init loses its --ai-mode, --provider, --api-key-env, --stack, and --answers flags; new/tech/tasks lose --force (and --answers on new). config.yaml's ai: block is no longer used; existing configs keep working — loadConfig prints a one-line notice telling you the block is safe to delete, then ignores it. Every prompt module now exports just buildAgentInstruction (or AGENT_INSTRUCTION for scan).

Full changelog: CHANGELOG.md

v0.2.1 — skills everywhere, init that just works

29 Apr 12:21
c93d9ae

Choose a tag to compare

Install

npm install -g draftwise

Or upgrade:

npm install -g draftwise@0.2.1

Slash 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 draftwise

The 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 draftdraftwise 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 init auto-detects new vs existing project. No more "are you greenfield or brownfield?" question — Draftwise walks the cwd for source files and decides. --mode=greenfield|brownfield still 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 under skills. install writes plugin/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/); uninstall removes them; help prints a 3×2 state table (3 harnesses × 2 scopes). --provider=claude|cursor|gemini|all narrows; --scope=user|project switches between ~ and <cwd>; --force overwrites on install. Same SKILL.md across providers with a tiny per-provider frontmatter trim — Claude-only user-invocable / argument-hint / allowed-tools stripped for Cursor + Gemini; body identical.

Changed

  • draftwise init auto-detects from the filesystem. Walks the cwd using scanner.js's IGNORE_DIRS + CODE_EXTENSIONS and 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 --mode flag values, config.yaml's project.state field, detailed flag-help text). Everywhere else leads with "new project" / "existing codebase".
  • Five dedup + tidy PRs across the codebase. draftwise scan reuses the shared compactScan projection helper. extractJsonFromFence (used by init greenfield + new's plan call) and loadAnswersFlag (used by init and new) extracted into shared utility modules. The greenfield/brownfield scan-context branch (in new / tech / tasks), the overwrite-confirm dance (same three commands), and the .draftwise/ existence guard (eight commands) consolidated into scan-context.js, overwrite-guard.js, and draftwise-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 draft binary instead of draftwise. src/commands/show.js (when a missing spec type was requested) and src/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_SYSTEM from src/ai/prompts/new.js and the top-level SYSTEM aliases from tech.js / tasks.js — three exports marked "Backwards compatibility — keep the old names alive" that never had real callers (verified by grep across src/ and test/). scan.js and explain.js keep their SYSTEM exports — those are primary, not aliases.

Full changelog: CHANGELOG.md

v0.2.0 — Mode 1, for real

29 Apr 07:33
324d1fa

Choose a tag to compare

Install

npm install -g draftwise

For 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

  • /draftwise slash commands inside Claude Code. Install the plugin via /plugin marketplace add 4nkur/draftwise then /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 init smart 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: /draftwise slash commands. New .claude-plugin/marketplace.json at repo root declares a single draftwise plugin with source: ./plugin. Inside plugin/ lives the install manifest (.claude-plugin/plugin.json) plus a single skill skills/draftwise/SKILL.md that routes user input to per-verb references at skills/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-installed draftwise CLI, parse the structured handoff or streamed output, report back. Plugin name = skill name = draftwise so the slash form is /draftwise <verb> (no <plugin>:<skill> namespacing in command logs). Plugin is distributed separately from the npm package — package.json files does 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 from src/ai/prompts/principles.js by 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 for new (one-word ideas get one elaboration ask before invoking), and review nudges for tech / tasks. Closes #42.

Changed

  • draftwise init non-TTY: structured agent handoff instead of bare error. When draftwise init runs in a non-TTY shell with too few flags to proceed, it now prints a structured handoff under AGENT_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-invokes draftwise init with 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-in util.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: init gains --mode, --ai-mode, --provider, --api-key-env, --idea, --stack, --answers <json|@file>; new gains --answers <json|@file>; scaffold gains --yes (-y); tech/tasks reject the inquirer picker in non-TTY when multiple specs exist (must pass slug positionally). Overwrite-confirms in new/tech/tasks error in non-TTY without --force instead of falling through. Closes #40.

Full changelog: CHANGELOG.md

v0.1.5 — sharper specs, safer edits, live streaming

26 Apr 13:27
9536c58

Choose a tag to compare

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; and spec-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 for new and tech. tech also 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 / tasks against an existing target file now prompts to confirm before overwriting; default is to cancel. New --force flag 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, and tasks stream 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, scan ends with a Next: ... nudge, and scaffold short-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 (the lint script was broken before). prepublishOnly blocks releases on broken main.

Added

  • Spec-quality rules baked into the drafting prompts. New module src/ai/prompts/spec-quality.js exports SPEC_LANGUAGE_RULES and EDGE_CASE_DISCIPLINE, injected into the synthesis SYSTEM for new and tech. Same single-source-of-truth pattern as principles.js. (#35)
  • Overwrite protection on new, tech, and tasks. Confirm prompt with --force to 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_PRINCIPLES injected at the top of init greenfield's QUESTIONS_SYSTEM and STACKS_SYSTEM, all four new system prompts, and both tech and tasks. (#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, tasks tests so a refactor that drops streaming silently can't slip through. (#30)
  • HELP consistency test set verifying every command exports a HELP string starting with draftwise <cmd>. (#30)
  • stream.abort() on errors in src/ai/providers/claude.js — closes the underlying HTTP request when iteration or onToken throws. (#30)
  • mapConcurrent no-cancel doc note. (#30)
  • --version / -v flag on the CLI. (#27)
  • Per-command --help / -h. (#27)
  • .prettierrc — explicit Prettier defaults. (#27)
  • CI workflow running npm ci, npm run lint, and npm test on Node 20 and Node 22. (#26)
  • Cache schema version.draftwise/.cache/scan.json now carries a cacheVersion field. (#26)
  • eslint.config.js — ESLint v10 flat config; npm run lint actually works now. (#22)
  • Tests for src/ai/provider.js and src/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=1 for stack traces. (#22)
  • prepublishOnly script — 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: scan next-step nudge, agent-mode orienting prefix across all six commands, scaffold brownfield 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 so draftwise scan > overview.md captures only the streamed content. (#30)
  • Document the dep-pinning asymmetry in CLAUDE.md@anthropic-ai/sdk exact-pinned, @inquirer/prompts / yaml caret. (#30)
  • Pin @anthropic-ai/sdk to 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_tokens to 16384 and expose ai.max_tokens in config. (#25)
  • Extract shared pathExists and compactScan helpers — 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 cwd arg from runGreenfield. (#22)

Install: `npm install -g draftwise@0.1.5`

Full diff: v0.1.0...v0.1.5

v0.1.0 — PMs starting from scratch

25 Apr 11:58
a48a484

Choose a tag to compare

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. init now 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 new draftwise scaffold command turns the chosen plan into actual files. new / tech / tasks adapt 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.txt or pyproject.toml (PEP 621 + Poetry). Parses decorator routes, Django urls.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 via scan.max_files for monorepos. explain filters 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 to overview.md plus a structured scaffold.json. Agent-mode greenfield init dumps a 3-phase instruction for the host coding agent. config.yaml gains a project section (state, stack). — Ankur (#12)
  • Greenfield-aware new / tech / tasks. Each command checks config.projectState. Greenfield path skips the scanner, reads overview.md, and uses prompt variants that drop scanner-grounded constraints — affected_flows / adjacent_opportunities removed for new, every file marked (new) for tech, scaffolding tasks first for tasks. scan and explain short-circuit gracefully in greenfield. — Ankur (#13)
  • draftwise scaffold command. Reads the greenfield plan from .draftwise/scaffold.json, confirms with the user before writing, creates each initial_files entry 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 maxFiles of 5000, configurable via scan.max_files. Truncation surfaces a warning across every command. Missing-framework hint listed in init / scan when the scanner returns empty frameworks. Closes Q1 and Q5. — Ankur (#15)
  • Python scanner support. Detects FastAPI / Starlette / Flask / Django / Tornado from requirements.txt or pyproject.toml (PEP 621 + Poetry tables). Parses FastAPI / Flask decorator-based routes, Django urls.py path() / 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 + maxFiles and persists results at .draftwise/.cache/scan.json; filterScanForFlow(scan, flow) narrows routes / components / models to flow-keyword matches with per-category fallback. init writes a .draftwise/.gitignore excluding .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)
  • .gitattributes for 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 keeps bin/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)