rmb32 / barntree-cli
Manage Barntree Templates, building blocks, Constructions and history; initialise, check and export
Requires
- php: ^8.5
- rmb32/barn-paths: ^0.1@dev
- rmb32/barntree: ^0.1@dev
- symfony/console: ^8.0
Requires (Dev)
- infection/infection: ^0.35.4
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^13.3
- rector/rector: ^2.6
- rmb32/barntree-gui: ^0.1@dev
- rmb32/typed-json: ^1.0@dev
- squizlabs/php_codesniffer: ^4.0
- symfony/process: ^8.0
Suggests
- rmb32/barntree-gui: Adds `barntree gui`, which serves the browser UI and opens it
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-11 16:47:08 UTC
README
Early, version 0.x. Not ready for real projects yet; the minor version is the breaking one.
Part of Barn.
Use barntree to read Templates, building blocks, Constructions and history; create and
manage Constructions; initialise a barn; check Templates; and export Template projections.
The optional Barntree GUI adds
barntree gui to open the same saved data in a browser.
Requirements
- PHP 8.5+
Installation
composer require rmb32/barntree-cli
Usage
vendor/bin/barntree init
Every Barn tool keeps its files in one .barn/ folder at the project's root, and
a project with that folder is a barn. When there is none, init makes it,
nothing else in the root, and says where the trees live. They are always in
.barn/barntree/trees/, a folder made when the first tree is saved:
my-project/
.barn/
barntree/
trees/ # the trees, one .barntree.json file each
Commit .barn/ with the rest of your project. The files in it are managed by
Barn's tools; edit trees through them rather than by hand.
Run from a folder inside another barn, init names that barn and asks before
making a separate one. With --no-interaction it refuses, unless
--separate-barn says to go ahead.
check, export and gui find the barn from any folder inside it, and say
which barn they are using. Outside any barn check and export refuse, write
nothing and exit with 1, and gui offers to make one in the browser.
Creating and changing Constructions
vendor/bin/barntree construction:create "Garden" --name="Summer garden"
vendor/bin/barntree construction:list
vendor/bin/barntree construction:show CONSTRUCTION_ID --json
vendor/bin/barntree member:add CONSTRUCTION_ID --list=LIST_ITEM_ID --name="Front bed"
vendor/bin/barntree member:rename CONSTRUCTION_ID MEMBER_ITEM_ID --name="Back bed"
vendor/bin/barntree construction:rename CONSTRUCTION_ID "Kitchen garden"
vendor/bin/barntree member:remove CONSTRUCTION_ID MEMBER_ITEM_ID
Replace uppercase placeholders with IDs printed by construction:list and
construction:show. A Construction starts with the Template's required map children
and empty lists, captures its exact current saved source, and receives revision 1.
For an existing Template without History, creating its first Construction records the
Template's baseline once. A file with changes outside its recorded revision must be saved
through the Template editor first. Select a recorded source by ID with --document-id.
Only the Construction's name and real list members can change. Required map children and captured building-block rules are protected. Member IDs and sequence survive renaming; removing a member removes its entire branch. Later Template changes do not alter it. Each successful change saves immediately as one revision; an unchanged rename adds none. The GUI opens these same records and uses the same member-editing rules.
Removal previews every affected item and asks for confirmation, defaulting to No.
Use --yes to confirm explicitly. Scripts, piped input and --no-interaction refuse removal
without --yes; closing or interrupting a prompt does not save. --yes never bypasses
validation or conflict protection.
All five write commands support --json. Results contain schemaVersion: 1, barnRoot,
operation, changed, document/revision metadata (including source and previousRevisionId),
and removedItems (each with id, name, identifier; empty for other operations).
Use construction:show --json to read the resulting full content. Successful JSON stdout
contains only JSON, preserving literal text even with Console markup or --ansi; diagnostics
and interactive previews go to stderr. Success exits 0; validation, conflict or declined
confirmation exits 1. Terminal interruption may return the shell's interrupted status.
For edits based on previously inspected state, supply --expect-revision=REVISION_GUID.
For creation, --expect-token=TEMPLATE_FILE_TOKEN checks the inspected source file.
Every save also checks its base at commit time, including changes made while a confirmation
is open; creation rechecks its source revision. A conflict preserves the newer saved record.
Construction names can repeat. Every deliberate construction:create invocation creates a
new independent document; creation is not an idempotent retry operation. If output is lost,
inspect construction:list before retrying. Item selectors are literal IDs, so member names
containing spaces, slashes or other punctuation need no path escaping.
Templates, Constructions and history
vendor/bin/barntree template:list
vendor/bin/barntree template:show "Garden"
vendor/bin/barntree template:show "Garden" --view=overview
vendor/bin/barntree template:show "Garden" --view=skeleton
vendor/bin/barntree template:show "Garden" --view=types
vendor/bin/barntree template:show "Garden" --view=glossary
vendor/bin/barntree type:show "Garden" Bed
vendor/bin/barntree construction:list
vendor/bin/barntree construction:show <construction-id>
vendor/bin/barntree construction:show <construction-id> --view=overview
vendor/bin/barntree construction:show <construction-id> --view=source
vendor/bin/barntree template:history "Garden"
vendor/bin/barntree construction:history <construction-id> --page=2
The Template catalogue includes existing files without importing them. Tree shows the Template's building-block structure, including a list's allowed member type. Skeleton shows required map children and empty lists. Types group maps, lists and leaves, sorted by identifier; glossary includes their meanings and declared tags. Building-block details include direct uses, saved item IDs and a structure preview. Recursive references are labelled and stop expanding. Maps follow alphabetical display names; real list members keep their sequence.
Constructions use the full document ID printed by construction:list. Their tree shows
real members with the item IDs needed to address them. Source reads the exact captured
Template revision, even after that Template is edited, renamed or deleted.
History shows revision number, full GUID, recording date, events and affected identifiers,
newest first. Every event in a combined save appears. Pages contain 25 revisions by default;
--limit accepts 1–100. Invalid or unavailable pages fail clearly. An existing Template's
first History read records its baseline once, using the same history store as the GUI;
the date records when history began. Other read commands do not create revisions.
Read an immutable snapshot without changing current state:
vendor/bin/barntree template:show "Garden" --revision=<revision-guid>
vendor/bin/barntree construction:show <construction-id> --revision=<revision-guid>
vendor/bin/barntree template:show <template-id> --document-id --revision=<revision-guid>
The last form also works after the current Template has been deleted. Revision IDs and Template file tokens are different: a token identifies the exact current file; a revision GUID identifies an immutable snapshot. An externally edited file can differ from its last recorded revision. Read results say when there is no matching recorded revision.
All seven read commands accept --json. Successful JSON output goes only to stdout,
with diagnostics on stderr. Exit status is 0 on success and 1 on a refusal or a broken
catalogue entry. A catalogue containing a named broken Template returns its readable
entries and an errors array, with status 1. An unnameable or malformed file stops catalogue
reading and produces a diagnostic. Existing check and export retain their output formats.
JSON envelopes have schemaVersion: 1 and barnRoot:
| Command | Result fields |
|---|---|
*:list | documents, errors; each document has the metadata below |
*:show | document metadata, savedAt, view, complete saved content, selected display |
type:show | document metadata and type: identifier, name, meaning, kind, allowed of identifiers, tags, uses, root flag, saved item IDs, structure |
*:history | document ID, current revision ID, matching-file flag, page, limit, pages, total and revisions with metadata, kind, previous revision ID, savedAt and events |
Document metadata contains name, documentId, revisionId, number, token, baseline,
source and matchesSavedRevision. Unrecorded identities and inapplicable tokens are null.
Source contains the Template's document ID, revision ID, number and captured name. Each event
contains event and identifier. Dates use ISO 8601 with a timezone and fractional seconds.
The complete content uses Barntree's existing format-1 document. Structure display nodes
have identifier, name, kind, children and a recursive flag; Construction tree nodes also have
real item IDs. Skeleton nodes have no generated preview IDs. --view=source returns the
captured Template's metadata and content. These commands find the nearest barn from nested
folders and refuse outside a barn.
Checking every Template
check reads every Template in the project and prints one line for each:
vendor/bin/barntree check
Barn: /path/to/project
Checking the trees in /path/to/project/.barn/barntree/trees
Garden: valid
Pond: broken: Type 'Pond' is of 'Fish', which is not one of the tree's types.
A tree is valid when its types and its tree keep every rule, and
broken: <problem> otherwise. A file that doesn't name a tree, or names one
another file already holds, stops the check before any tree is read, as
fault: <file>: <reason>.
It reads the barn's .barn/barntree/trees/. Trees are the .barntree.json files there. It exits with 1 if any tree is broken or any file is faulty, and 0
otherwise. That makes it a CI step:
- run: vendor/bin/barntree check
Exporting a Template
export prints one Template, or writes it with --to:
vendor/bin/barntree export House # the tree, to stdout
vendor/bin/barntree export House --as=markdown
vendor/bin/barntree export House --as=markdown --to=docs/house.md
vendor/bin/barntree export House --as=folder # a preview; writes nothing
vendor/bin/barntree export House --as=folder --to=house # one folder per item
vendor/bin/barntree export House --as=mermaid | mmdc -i - -o house.svg
--as | What you get |
|---|---|
text (the default) | the indented tree |
markdown | a document: a heading per item, its type's meaning beneath |
folder | a folder per item, each with a README.md; without --to, the tree of folders it would write |
mermaid | a Mermaid flowchart, which GitHub draws as it is; pipe it into mermaid-cli for SVG |
$ vendor/bin/barntree export House --as=folder
House/
├── README.md
├── Garden/
│ ├── README.md
│ ├── Beds/
│ │ └── README.md
…
--to never overwrites and never merges: a file must go to a path that does
not exist yet, and folders to one that does not exist or is an empty folder.
An item whose name cannot be a folder (Why?, a trailing dot, two siblings
that differ only in case) is reported, every one at once, rather than renamed.
The barn's root goes to stderr, so a piped export holds only the projection.
An unknown --as lists the kinds there are. Every refusal goes to stderr and
exits with 1, with no stack trace.
Managing Templates and building blocks
barntree template:create --from-file=garden.barntree.json
barntree template:copy "Garden" "Kitchen garden"
barntree template:edit "Garden" --description="A growing space"
barntree type:create "Garden" --kind=leaf --name="Flower"
barntree type:create "Garden" --kind=list --name="Flowers" --of=Flower
barntree type:create "Garden" --kind=map --name="Patch" --of=Flower,Flowers
barntree type:edit "Garden" Flower --meaning="A flowering plant"
barntree map:add-child "Garden" Garden Patch --yes
barntree map:remove-child "Garden" Garden Patch --yes
barntree list:set-member-type "Garden" Flowers Flower --yes
barntree type:delete "Garden" Patch --yes
barntree template:delete "Kitchen garden" --yes
New blocks are unattached; identifiers default to names and can be chosen with
--identifier. Renaming preserves the identifier. Lists require --of=IDENTIFIER;
maps take comma-separated child identifiers. Root changes use template:edit --root.
A building block can be deleted only when unused and not the root. Copies receive fresh
item identities and independent history while retaining saved members and tags.
Every successful change saves immediately through the shared history store. Unchanged
edits add no revision. Structural changes and deletions show a preview and require
confirmation; unattended use requires --yes. All commands support --json and
--expect-token=TOKEN from template:show. Conflicts refuse to overwrite newer work.
Deleting a Template retains recorded snapshots and existing Construction sources.
check continues to check current Templates; Construction reads validate their saved records.
For combined changes, prepare JSON containing name, description, root and types:
barntree template:apply "Garden" --from-file=changes.json --expect-token=TOKEN --yes
barntree type:edit "Garden" Flower --from-file=flower.json
Apply changes metadata and types atomically, fitting the existing tree with the same core
operation as the GUI. It preserves surviving item identities; a supplied tree is ignored.
Tags stay unchanged. Type edit JSON contains editable fields (name, meaning, kind,
of); unspecified fields stay unchanged. Meaning may contain multiple paragraphs.
Both file inputs accept --from-file=- for stdin. JSON output uses the existing metadata
fields plus operation and changed; deletion returns deleted and the document ID.
The GUI
With rmb32/barntree-gui installed in the same project, the CLI also offers:
vendor/bin/barntree gui # http://localhost:8082, opens your browser
vendor/bin/barntree gui --port=9000 # start looking for a free port here
vendor/bin/barntree gui --no-open # don't open a browser
vendor/bin/barntree gui --dry-run # print what would be started
It serves the tree folder of the barn it runs in (outside a barn, the page offers to make one), picking the next free port if the default is taken. Stop it
with Ctrl-C. Without the GUI package installed, gui simply isn't offered.
Related packages
- Barntree — the library of trees, types and items this works on.
- Barntree GUI — browse and edit the trees in a browser.
- Barnscaff — scaffold and scan folders from trees.
- Barnark CLI — ready-made architecture templates.
More docs
License
Proprietary. See LICENSE. Copyright (c) Roger Barnfather.