The commands
A tour of the nouns. Every command takes --base to point at a deployment, --json for one machine-readable envelope on stdout, and --no-input and --yes for scripts; the exact flags and defaults are generated into the CLI reference.
How the tree is shaped
Nouns carry their verbs, gh-style — vitrinka board push, vitrinka task create, vitrinka sprint complete. Only three leaf verbs sit at the top: status, doctor and update (plus help and completion); bare vitrinka on a terminal opens the dashboard. There are no aliases: an old spelling (install, open, set push) is an unknown command — exit 2, naming the nearest spelling when one is close, and vitrinka --help. Every noun, verb, flag and default is generated from the binary itself into the CLI reference; this page says what each noun is for and which verb you reach for first.
Capture and publish
| Noun | For |
|---|---|
board | Everything on or into a board. A capture set: init, capture, push, meta, rename — sets. The board itself: create (another slug, or a --journey tree), upload, dump, import-chat, cards rm, list, view, open, edit, share — boards. Beside them artifact init and artifact create for self-contained pages, diagram import and diagram schema push for refreshable diagrams. |
tag | The third axis beside project and subgroup: list, add, remove. |
Work and QA
| Noun | For |
|---|---|
work | The annotation queue: watch leases this repo and branch and wakes the session per item, listen --harness <name> hosts Codex, Gemini CLI or OpenCode over ACP and feeds it the queue, list shows what is open — the work queue. |
qa | The QA record: run -- <test command> publishes any runner's results, usertest records exploratory testing (start, case, verdict, finish), pair supervises the app during live pairing, session keeps coding-agent transcripts behind tasks (archive, continue) — live pairing, sessions. |
The task engine
The PM engine is reachable from the terminal, with the same vocabulary the browser and the MCP tools use.
| Group | For |
|---|---|
task | list (sorted by up to four keys — --sort priority,-due), get, create, update, comment, rank before or after another task, search, delete (soft), and mine for your cross-project slice; field, label, link and upload for what a task carries — and the work loop: pickup, start and stop, spot, handback — work loop. |
sprint | list, create with start and end dates, start, and complete — unfinished work carries to the next sprint or back to the backlog. |
intake | Propose and list drafts, then accept, decline or merge them — see intake. |
vitrinka task list --sort priority,-due
vitrinka task create "Discount applies twice" --type bug --priority high
vitrinka sprint complete 12 --carry nextYou, search and review
| Noun | For |
|---|---|
me | Your own seat: todos with server-evaluated --when conditions, reminders (me schedule), milestones, automatic work time (me time), the diary and your project brief — todos, reminders and time. |
search | One call across tasks, annotations, pages, boards, tags, cards, sessions and shots; search query runs read-only SQL over the agent-calls ledger; search resolve turns a pasted app link into what it names — below. |
fav | Your bookmark tree: add, list and rm a star on a board, card, session, task or project. |
review | The review brief and its rules — brief, rules, lint, judge, file, stats — review toolkit. |
Search from the terminal
vitrinka search is the ⌘K palette in a shell: one call runs every group and prints each group's ranked hits. A number (№432 or #432) pins that annotation thread or task; any fragment of three or more characters matches, mid-word included. Task and page rows carry their canonical URL — paste it as printed. --resolve reads the text as ONE task reference — title words, any id spelling, a URL, a branch, bugs under <epic>, mine — and answers a verdict with at most five candidates instead of every group. task search is the ranked search over everything a task carries — title, body, fields, refs and comments, a typo searching its correction too — in this checkout's project unless --all; --type, --state, --parent and --epic (any depth) narrow it, a value naming nothing fails with the allowed ones, and --within <task> searches one task's own tree.
vitrinka search "checkout crash"
vitrinka search onboarding --groups tasks,pages --project shop
vitrinka search "bugs under checkout" --resolve
vitrinka task search coupon --epic 461 --type bug
vitrinka search query "select name, count(*) n from agent_calls group by name order by n desc"
vitrinka search resolve https://app.vitrinka.ai/w/acme/p/shop/t/461
vitrinka fav add task 461 --folder Releasessearch query is the read side of the agent-calls ledger — every agent-driven call lands in agent_calls as one row — beside the board and task facts (ai_usage, boards, board_cards, sets, project_settings, tasks, task_events, task_labels, workspace_events, review_rules, project_deploys, and sqlite_master for the schema). It runs ONE read-only SELECT, for the workspace owner only, capped at 1000 rows and 5 seconds, and every call is audited; --param binds each ? in turn. search resolve answers what a vitrinka link points at — kind, workspace, title, canonical URL — in any workspace you belong to; a link you cannot see is one "not found", whatever the reason. The MCP twins are search, query and resolve_url.
Machine, repo and session
| Noun | For |
|---|---|
auth | One credential per deployment: login is a browser approval, logout, status, token. |
config | This machine's wiring: bind a repo to a workspace, default and prefix workspaces, operator persona, writes mode — setup. |
project | This repository's wiring: index keeps the @ index fresh, link and unlink file the checkout under a project, commits sets the commit convention, tidy sweeps litter into .vitrinka/ — setup. The project itself: release drives the release track, fields defines custom fields, deploy-mark records that a commit reached an environment, merge folds a stray project into another of the same workspace (a dry run until --apply; merge-plan lists the strays), transfer copies a whole project into another workspace you own — projects. |
workspace | Workspace-wide settings: commit-prefix — commit trailers. |
status | The session dashboard: the live board, the open queue and the listener lease — the work queue. |
Setup and administration
| Noun | For |
|---|---|
setup | The one first run — sign in, agent plugin + MCP, this repository, the index, agent hooks — then setup uninstall, setup extension (setup, update), setup modules (a module is a plugin: list, enable, disable) and setup skills (one skill shown or hidden) — install. |
update · doctor | Refresh every installed surface through the channel that installed you; check the machine and this repository and name each repair, --fix to apply them — check and repair. |
docs | Read this deployment's unified reference — elements, card kinds, kit components, the composing guides — the same pages the docs MCP tool serves; docs ask turns plain words into one command — below. |
admin | Administration: the deployment's one mailer (admin smtp, changed only by platform admins and, when the operator names one, the admins of the organization that runs the install) and the workspace's project registry (admin projects check lists the rows that still need a decision). |
Ask in plain words
docs ask translates a plain-language request into one vitrinka command through a local claude -p call, shows it to you, and runs it only after you agree.
vitrinka docs ask "show me open work on this branch"The suggestion is validated against the real command tree and is never shell-evaluated. VITRINKA_NO_AI=1 disables the whole thing.
Scripts and agents
Every command takes --base, --json (one envelope on stdout — v, ok, verb, data, diagnostics, next, exit_code; --json=id,title keeps only those fields of data), --jq '<expr>', --no-input (never prompt; also VITRINKA_NO_INPUT=1 or CI) and --yes (accept the proposed plan). Exit codes: 0 ok · 1 failed · 2 misuse · 3 nothing found (work watch --once) · 4 sign in first · 5 a step needs a human — the plan is in data, and next[].cmd is the rerun with --yes · 130 cancelled — help guides.
Offline: the outbox
A write the deployment cannot receive is not lost. When the network is down, or an agent's MCP connection has dropped and the network went with it, these commands queue their request on this machine instead of failing: task comment, task update, task create, task label, task upload, task handback (without --transcript), me todo add (without a milestone or dependencies), me todo done and board compose <board> --file -. board compose takes the same arguments as the compose_board MCP tool.
A queued write exits 0 and prints ⧗ queued offline. Under --json, data.queued names the entry and a queued diagnostic lets a script branch on it. The queue lives beside the CLI config in ~/.config/vitrinka/outbox/ ($XDG_CONFIG_HOME/vitrinka/outbox/ when set) and keeps the workspace each write was made in.
Before its first request, the next command that reaches the deployment replays the queue, oldest first. The SessionStart hook replays it too and reports the result. Every write carries an idempotency key from its first attempt, so it lands exactly once, even when the first attempt reached the server but its answer was lost.
vitrinka outbox list # pending, parked (with the server's reason), recently replayed
vitrinka outbox flush # replay now
vitrinka outbox retry <id> # put a parked write back in the queue
vitrinka outbox drop <id> # give one up for goodThe server parks a write it refuses, such as one aimed at a deleted task. A parked write stays put until you retry or drop it. An expired sign-in parks nothing: the queue waits for vitrinka auth login. Pass --no-queue, or set VITRINKA_NO_QUEUE=1, to make CI and scripts fail instead of queueing.
Publishing without the CLI
Nothing about publishing requires the CLI. From any job you already run, mint a set key and stream a tarball into it — no SDK to install, nothing to keep up to date in the pipeline.
tar czf - -C ./shots . | curl -sS -X PUT --data-binary @- \
-H "Authorization: Bearer $VITRINKA_TOKEN" \
"$VITRINKA_URL/api/v1/sets/myapp/main/nightly/content?kind=screenshots"MAX_SET_MB (default 200) caps both the request body and the unpacked size of a single set. The key is yours to choose; the full contract is on the HTTP API page.