Plans
Plans are markdown documents that derive items. Two ways to derive: canonical format (deterministic, free, zero AI cost) or freeform (AI parses, costs one daily call).
This is the substrate Vibstr ships on. Every release of Vibstr starts as a plan in Vibstr's own project — 30+ consecutive plan-driven releases through 1.18.x. The same machinery is available to your project from day one.
The canonical format (SPEC §22)
# Plan title
## Goal
One paragraph describing what this plan accomplishes.
## Tasks
- [ ] {type, area} @assignee: description
- [ ] {type: bug, area: Auth} @chris: Fix login redirect
- [ ] {type: feature, area: Onboarding} fix the trial nudge copy
## Target build
v1.18.x
## Acceptance gate
- [ ] All tasks done
- [ ] Smoke test passes
## Out of scope
- Anything not in tasks above
This is the format. Six recognised sections (# Title, ## Goal, ## Tasks, ## Target build, ## Acceptance gate, ## Out of scope). Unknown sections are silently collected for forward-compat — adding ## Notes or ## Design references is fine; the parser just ignores them.
Task line semantics
- [ ] {type, area} @assignee: description
- Checkbox:
[ ]or[x](we currently always create items asopenregardless of the box state). {type, area}block (optional): comma-separated. Both{bug, Auth}and{type: bug, area: Auth}syntaxes work. Type matches the project'scategoriesarray case-insensitively; area matches theareasarray. Unknown values fall back to the first project category (and a yellow warning chip shows in the preview row so you can fix it before approving).@assigneetoken (optional): email or display_name. Resolves against project members case-insensitively. Unknown values preserve the raw token in the description and surface a warning chip.- Description (required): 1–2000 chars. Anything after the optional
@assignee:separator. Long descriptions get sliced at 2000 chars with a warning chip.
Blank lines inside ## Tasks are skipped silently. Non-checkbox prose lines under ## Tasks are skipped silently. This means you can write narrative prose between checkbox lines and the parser ignores the prose.
The Vibstr Plan Prompt
The Vibstr Plan Prompt is a per-project tailored prompt you copy out of Vibstr, paste into any LLM, and get back canonical-format markdown. It surfaces in three places:
- Plan modal header. Click "Copy Vibstr Plan Prompt" on any plan modal. Clipboard receives the per-project tailored prompt with your categories, areas, and labels inlined.
- Settings → PROJECT → Prompt templates. Pinned at the top of the pane. Same prompt, same Copy button.
- AI Assist value-add library. The flagship card. Copy button writes to clipboard; Insert button prefills the AI Assist conversation textarea.
All three surfaces resolve to the same buildVibstrPlanPrompt(project) helper. Single source of truth.
The round-trip
- Copy the Vibstr Plan Prompt for the project you want to plan against.
- Paste into ChatGPT / Claude / Cursor / Gemini / any LLM you have access to.
- Describe what you want to build. Free-form. The LLM has your project's categories + areas + labels in its context.
- The LLM returns canonical-format markdown.
- Open a new plan in Vibstr. Paste the body. The parser auto-detects the canonical format within 400 ms and the "Derive items with AI" button swaps to "Parse N tasks → preview".
- Click Parse. Instant preview — no Vibstr AI call, no daily-call cost.
- Edit any preview rows (fix stale types, change assignees, skip irrelevant rows). Approve.
- Items derive with
plan_idpointing back at the plan. They inherittarget_build_idif you set one. Build progress chip on the Build tab hero card ticks toward done as items close.
Full round-trip from any LLM. Zero AI cost on Vibstr's side. The LLM did the natural-language → structured-format conversion; Vibstr's parser does the structured-format → DB-rows conversion deterministically.
Auto-detect
isCanonicalFormat(body) is a heuristic: first 50 lines of the body, looking for ## Tasks heading AND at least one - [ ] line below it. The check fires 400ms after each keystroke (debounced) when the plan modal textarea is active.
When canonical-format detected:
- "Derive items with AI" button → "Parse N tasks → preview". Count updates live as you type more
- [ ]lines. - Click → instant preview, no network round-trip, no AI cost.
When NOT canonical-format:
- "Derive items with AI" button stays. Click → AI parses your freeform body, costs one daily call, returns the same preview shape.
The auto-detect is the routing layer. You never have to think about which path you're on.
Freeform plans · bulk-adding items from unstructured text
Sometimes you have a Notion doc, a Linear comment thread, a chat log, an email forward, or a brain-dump of bugs to file. This is where bulk-add lives. Paste the raw text into a plan body. The parser doesn't detect canonical format. Click "Derive items with AI". Costs one daily call (or zero if you've BYO'd your Anthropic key — see Pricing).
The AI returns the same preview shape as the deterministic parser. Edit rows, skip irrelevant ones, approve. Same outcome — items land with plan_id back-link and inherit the plan's target_build_id if you've set one.
Why route bulk-add through the plan modal instead of a standalone "Import multiple items" surface? Because items without a plan are orphans. The Activity tab, the Builds-tab hero, the drawer From-plan chip — all assume items trace back to something. A plan is that something. If you really just want "N items added with no narrative", make a "Brain dump 2026-05-16" plan, paste, derive, done — the plan title is the narrative and you can archive it once the items are closed.
The freeform path is the escape hatch for content that wasn't authored as canonical-format. Use it when you have it; don't use it when you don't.
Other bulk paths:
- VivifyScrum migration → Settings → PROJECT → Import (structured JSON file upload with per-column status/stage/area mapping)
- Programmatic from CI / scripts → Path A
vibstr-item-bulk-createendpoint, up to 100 items per call (External automation) - Canonical-format markdown plan from an LLM → same plan modal flow, but the deterministic Parse-N-tasks button fires instead of the AI Derive button (zero AI cost, instant)
Plan linkage
Items derived from a plan carry plan_id FK (schema since 1.9.0). Two surfaces render this:
- Drawer. "From plan: {title}" chip below the description. Click → opens the plan modal.
- Build tab hero card. "Plans for this build" section lists every active plan whose
target_build_idmatches. Each plan row shows progress (X of Y tasks done · Z%). Click → plan modal.
The plan + items + closing build all cohabit naturally because the FKs link them. You can be on any one of the three and navigate to the other two.
Idempotency
Re-parse the same canonical body — already-imported rows are locked. They render with a yellow warning chip "Already imported as #NN" + the Skip button is disabled. The approve count reflects only non-imported rows.
The dedupe key is (plan_id, type, description) tuple. Edit a row's description in the preview to force a "new" task; the parser then treats it as un-imported because the tuple no longer matches.
This means you can iterate on a plan body, re-parse multiple times, and only the genuinely new tasks land each time. Useful for iterative planning where you add tasks over the course of a sprint without splitting the plan into N separate documents.
Why we standardised the format
Real-user signal from our beta cohort flagged it first (SPEC §16 items 22–26): every team's plan format is different, and Vibstr was implicitly assuming one specific shape. The 2026-05-12 reframe locked it in:
Standardise the input (one artifact), not the workflow.
Plans bridge the spec → tickets → commits gap. Different teams have different commit conventions, different sprint cadences, different release pipelines — but they all benefit from "write markdown, get items, close via closes #NN". The format is the smallest standardisation that lets the rest of each team's workflow stay untouched.
SPEC §22 has the full reasoning. The short version: we'd rather standardise a 30-line markdown schema than build a "workflow picker" UI that makes every team configure how-they-work as a first-run step.
What's NOT in canonical format v1
- No per-task
[label-name]syntax. Labels are project-scoped and resolved against the project's labels dictionary; they don't fit inline cleanly. Set labels in the drawer after the item lands. (Best practices goes deep on labels-as-workflow-stages.) - No
[x]auto-mark-done. Checked boxes (- [x] ...) still create items asopenon approve. We considered it; the gain (~10 seconds saved per imported task) wasn't worth the implicit-state risk (a plan author marking boxes done before items existed in Vibstr). - No strict format enforcement. Auto-detect + AI fallback is the contract. Non-canonical bodies still work — they just route through the AI path. We don't reject anything.
Related pages
- Claude Code — the
closes #NNparser that closes plan-derived items. - The AI sidebar — knows about the linked plan when you press
aon a derived item. - Best practices — categories, areas, labels patterns that show up in the canonical format.
- External automation — the
vibstr-plan-createPath A endpoint (POST a canonical plan from any HTTP client). - Onboarding — where the Vibstr Plan Prompt first lands for new users.