rmb32 / barnspec-cli
Barnspec CLI — the wizard plus Writer/Glossary/StoryMap rendering commands as a standalone CLI transport package
Requires
- php: ^8.5
- ext-ds: ^2.0
- php-ds/php-ds: ^2.0
- rmb32/barnspec: ^1.0
- rmb32/menu: ^1.0
- rmb32/typed-input: ^1.0
- symfony/console: ^7.0
Requires (Dev)
- deptrac/deptrac: ^4.7
- infection/infection: ^0.35.4
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^12.0
- rmb32/barnspec-gui: ^1.0
- squizlabs/php_codesniffer: ^4.0
Suggests
- rmb32/barnspec-gui: Adds `barnspec gui`, which serves the browser UI and opens it
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-07 18:34:19 UTC
README
Part of BarnSuite.
The command line for Barnspec: capture user stories and acceptance scenarios through an interactive wizard (or from scripts), then turn them into readable Markdown, a glossary, a visual story map, and tracked work tickets.
Requirements
- PHP 8.5+
Installation
composer require --dev rmb32/barnspec rmb32/barnspec-cli
Everything you capture is saved as JSON under .barnspec/ in your project — safe
to commit.
Capture stories
vendor/bin/barnspec draft # capture a rough story (role / goal / reward)
vendor/bin/barnspec review # reword it field by field into a real Story
vendor/bin/barnspec refine # build out its Given/When/Then Scenarios
vendor/bin/barnspec show # list captured areas of business
vendor/bin/barnspec show commerce --json # one area's full outline
draft, review and refine need a real terminal. For scripts and CI:
vendor/bin/barnspec create-area-of-business --title="Commerce" --meaning="Selling things online" \
--phase="Launch" --phase-meaning="First release"
vendor/bin/barnspec create-story --area-of-business="Commerce" --role="Customer" --role-meaning="Someone who buys" \
--goal="Update basket quantities" --reward="get exactly what they want" --stage=adjust
vendor/bin/barnspec create-scenario --file=scenario.json
A new area of business always starts with its first phase (--phase defaults
to "Phase 1"). Areas, roles, stories, subjects and facts can be named by their
slug (commerce) or by the title they were created with (Commerce). A
story's reward follows "so that they…".
scenario.json names everything by title or slug. A parameter is only described
(meaning, type) the first time its Fact or action uses it — a new Fact needs
its parameters described even when another Fact of the same Subject already has
one by that name. One fact can appear more than once:
{
"area-of-business": "reservations",
"role": "guest",
"story": "find which rooms are free for their nights",
"title": "search for rooms free from 10 November for 2 nights",
"actionSentence": "search for rooms free for some nights",
"actionParameters": {
"check-in-date": { "meaning": "the first night of the stay", "type": "string", "value": "2026-11-10" },
"nights": { "meaning": "how many nights the stay lasts", "type": "integer", "value": 2 }
},
"given": [
{ "subject": "room", "subjectMeaning": "a room the hotel lets", "fact": "is on offer",
"factMeaning": "the room is part of what the hotel lets to guests",
"parameters": { "room-number": { "meaning": "the number on the door", "type": "string", "value": "101" } } },
{ "subject": "room", "fact": "is on offer", "parameters": { "room-number": { "value": "102" } } }
],
"outcome": "accepted",
"then": []
}
title and meaning are optional and default to the action sentence, which
lets several Scenarios share one action. A Fact's meaning is a state — it is
read after both "Given" and "Then".
Change what you captured
vendor/bin/barnspec reword --area-of-business=front-desk --subject=stay --fact="is under way" \
--meaning="the guest has arrived and is in the room"
vendor/bin/barnspec reword --area-of-business=front-desk --role=receptionist --meaning="receiving guests"
vendor/bin/barnspec reword --area-of-business=front-desk --action="check a guest in" --meaning="check an arriving guest in"
vendor/bin/barnspec reword --area-of-business=front-desk --phase="Phase 1" --meaning="checking guests in and out"
reword changes a meaning only: the title, the slug and every Scenario using it
stay as they are. A Phase can be reworded after its release too, so a placeholder
meaning never has to stay on the map.
Phases
vendor/bin/barnspec release-phase --area-of-business=commerce # the active phase
vendor/bin/barnspec release-phase --area-of-business=commerce --phase=launch
vendor/bin/barnspec create-phase --area-of-business=commerce --title="Growth" --meaning="More to sell"
One phase is active at a time: release it before starting the next.
Before releasing, release-phase asks about every story released in an
earlier phase whose reward nobody has settled yet (see below). Leave an answer
blank to come back to it next time. Pass --skip-impact-review, or run it
without a terminal, and it lists them instead. Either way, the phase is
released.
Record whether a reward was delivered
A story's Scenarios prove the role can do what it wanted. Its Impact says whether that gave them what the story promised:
vendor/bin/barnspec record-impact --area-of-business=reservations --story=book-a-room \
--state=achieved --observation="I booked without phoning the front desk" \
--source=role --who="Sam (guest)"
vendor/bin/barnspec record-impact --area-of-business=reservations --story=book-a-room --phase=suites \
--state=none --observation="guests still phone to book a suite" \
--source=measured --who="front desk call log" --observed-at=2026-10-01
--state:evaluating(too early to say),achieved,none(works, but did not deliver) orsuperseded(the need moved on).--source:role,on-their-behalf(the client, a manager, a support desk),measuredorteam.achievedis settled only byroleoron-their-behalf. Frommeasuredorteamit stays open until they say so too.noneandsupersededare settled whoever says them.--phaseis needed only when the story shipped in more than one released phase that is still being evaluated (its own, and each elaboration's).--observed-atdefaults to today. Left out in a terminal, the other answers are asked for.
write adds an Impact line to each released story, and the story map
gives each released card a 🎯 badge. Neither changes a story's colour: a story
can pass every Scenario and still have delivered nothing.
Change a released story
A released story's Scenarios no longer change directly; create-scenario
refuses and tells you what to run. Elaborate the story in the active phase
instead — it is merged into the story when that phase is released:
vendor/bin/barnspec elaborate-story --area-of-business=reservations --story=cancel-their-booking \
--reward="they are not held to a stay they will not take, and asking twice does no harm"
vendor/bin/barnspec elaborate-story --area-of-business=reservations --story=cancel-their-booking \
--goal="cancel their booking" --revise # change the open elaboration's wording
Capture into it with create-scenario, adding one key to the usual file:
{ "...": "...", "elaboration": true }
{ "...": "...", "amends": "cancel-a-booking-that-has-already-been-cancelled" }
amends replaces one of the story's Scenarios with this one (it may keep the
same title). refine offers a released story once it is elaborated and
captures into the elaboration.
vendor/bin/barnspec retire-scenario --area-of-business=reservations --story=cancel-their-booking \
--scenario=cancel-a-confirmed-booking # stops holding when the phase is released
vendor/bin/barnspec withdraw-from-elaboration --area-of-business=reservations --story=cancel-their-booking \
--scenario=cancel-a-confirmed-booking # undo a pending addition, amendment or retirement
show lists each elaboration under its story; write adds an "Elaboration
in …" section while it is open and a "Changes in …" record once merged; the
story map draws it as its own card in its phase.
Place a story on the lifecycle backbone
Every story can sit at one stage of the role's life with the business. The vocabulary is fixed across the whole suite, so maps line up area for area:
| Stage | The role… |
|---|---|
establish | gains what it needs to take part — signs up, registers, is granted access, or creates the thing later stories act on |
adjust | changes something that already exists without completing the core exchange — edits details, reconfigures, corrects a mistake |
transact | completes the exchange the area of business exists for — pays, places the order, submits, publishes |
resolve | gets what already happened to a settled state — tracks it, chases it, disputes a charge, claims a refund, asks for help |
close | ends something for good — cancels, closes, deletes, archives |
--stage is optional everywhere. A story without one is Unassigned, which
is a permanent home for stories that are not about a lifespan at all
(reporting, compliance, notification), not a to-do list. review asks for a
stage as a skippable step.
vendor/bin/barnspec restage-story --area-of-business=commerce --story=update-basket-quantities --stage=transact
vendor/bin/barnspec restage-story --area-of-business=commerce --story=update-basket-quantities --clear
Render what you've captured
vendor/bin/barnspec write commerce --output-dir=docs/stories/commerce # one doc per Story
vendor/bin/barnspec glossary commerce --output=docs/glossary.md
vendor/bin/barnspec glossary --output-dir=docs/glossary # every area + index.md
vendor/bin/barnspec map --output-dir=docs/map --stories-dir='../stories/{area-of-business}' # HTML story map
The map links each card to its Story's document and each area to its glossary.
--stories-dir and --glossary-dir are relative to --output-dir;
{area-of-business} in --stories-dir stands for each area's slug, so Stories
written one folder per area (as above) are found. Story slugs are only unique
within an area, so one folder per area is the safe layout. --glossary-dir
defaults to ../glossary, the folder glossary --output-dir=docs/glossary
writes.
The story map's columns are the five lifecycle stages (plus Unassigned, when
anything sits there) and its rows are Phases; each card carries its role as a
chip. write includes a story's stage and that stage's meaning in the Markdown
document; show prints it in square brackets after each story.
write, glossary and story-map are the same three renderers as standalone binaries.
Track work
vendor/bin/barnspec work:create commerce basket-quantity-updates caps-at-the-stock-level \
--title="Cap quantity" --description="Never add more than is in stock" --reference=SHOP-42
vendor/bin/barnspec work:list commerce basket-quantity-updates caps-at-the-stock-level
vendor/bin/barnspec work:status commerce SHOP-42 in-progress
work:status takes the ticket's id or the reference it was created with. A
reference shared by two tickets in the same area is refused; name one by its id.
A ticket belongs to a Scenario, so each command names the area, the Story and
the Scenario within it. There is no work:confirm: a Scenario goes green only
when vendor/bin/scenario-bridge run passes against it, and work:list prints
that last run beside the colour. Run work:create with no arguments in a real terminal
to pick an area, role, Story and Scenario instead. A Story with no Scenario
captured yet is refused — run refine first.
Start over
vendor/bin/wizard-reset # preview what would be deleted
vendor/bin/wizard-reset --force # delete the areas of business, Scenarios and drafts under .barnspec/
Prefer a browser?
Install Barnspec GUI alongside this package and the
barnspec binary gains a gui command that serves it and opens it:
composer require --dev rmb32/barnspec-gui
vendor/bin/barnspec gui
Run any command with --help. The Barnspec quick start (docs/quick-start.md in
rmb32/barnspec) shows the wizard
and the scripted commands side by side.
Related packages
- Barnspec — the core library and full documentation.
- Barnspec GUI — the same capture and Work board in a browser.
- Port Generator and Scenario Bridge — turn Scenarios into runnable tests.
- Scenario Runner CLI — scaffold unit tests for Work tickets.
More docs
License
Proprietary. See LICENSE. Copyright (c) Roger Barnfather.