Documentation
Guides and the full command reference for nxf — always in sync with the shipped version.v0.27.0
Getting Started
nxf is the nexus-flow agent CLI: a thin, deterministic, offline-first interface over the engine core. This guide takes you from an empty directory to a planned, tracked piece of work. Every command supports --json for machine-readable, byte-stable output — that is the contract agents build on.
Install
Download and install the latest release with the install script:
curl -fsSL https://nxf.nxsflow.com/install.sh | shIt detects your platform, verifies the download (sha256 + signature), and drops the three suite binaries on your PATH: `nxf` (the issue tracker), `nxm` (durable agent memory), and `nxs` (the umbrella that ties them together). You install once and choose which tools to activate per workspace. Check it:
nxf --versionInitialize a workspace
A workspace is a .nxs/ directory in your project — one shared store that every tool you activate writes into. The quickest way to set one up is the umbrella, which asks which tools to use and wires everything together:
nxs initIt assembles the shared agent files and sets a single nxs prime SessionStart hook, so from then on your agent loads the context of every active tool with one call (see the nxs umbrella). On an agent or in a script it is non-interactive — nxs init --module flow --module memory (or --json) sets up the same state with no prompt.
If you only want the issue tracker, initialize it directly. This is a deliberate plugin choice — there is no default, because the plugin decides the vocabulary you read and write (see plugins). For software work, pick issue-tracker:
nxf init --plugin issue-trackerEither path lands on the same .nxs/ workspace and the same nxs prime hook. Every id in this workspace is minted under a short, stable namespace called the prefix (the examples below use ab12). Run nxf init --help to see the available plugins and their descriptions.
Create your first items
Items are projects and tasks. Create a project to group the work, then the tasks under it. The --json record is the canonical shape — note the engine-level field names (type, belongs_to, status), which never change regardless of the active plugin:
$ nxf create --type epic --title "Ship v1" --description "Cut the first release" --priority P1 --json
{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Cut the first release","design":null,"due":null,"id":"ab12.0001","priority":"1","status":"open","title":"Ship v1","type":"epic"}$ nxf create --type feature --title "Write the CLI" --description "Build the command-line tool" --priority P1 --due 2026-12-31 --parent ab12.0001 --json
{"archived":null,"assignee":null,"belongs_to":"ab12.0001","closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Build the command-line tool","design":null,"due":"2026-12-31","id":"ab12.0002","priority":"1","status":"open","title":"Write the CLI","type":"feature"}The new task belongs_to the project (via --parent), is due by a date, and carries priority 1.
Long fields need no shell-escaping: pass - to read one from STDIN (cat design.md | nxf create … --design -), use --description-file ./desc.md, or pipe the whole item as JSON with nxf create --json -. See commands for the full set.
See what to work on
State like *ready* and *next* is derived, never stored (see core-concepts). With nothing blocking it, the work is ready, and next ranks it by the plugin's policy. The human view speaks the issue-tracker vocabulary — P1, open:
$ nxf next
0001 P1 open [epic] Ship v1
0002 P1 open [feature] Write the CLI
↳ 0001 · Ship v1That is the whole loop: init once, create work, then let ready/next tell you where to go. From here, read core-concepts for the model, or commands for a full working session.
The nxs umbrella
nxs is the platform umbrella over the suite. The same install ships all three binaries; nxs ties together whichever you activate in a workspace, over the one shared .nxs/ store:
nxs init— set up the suite: pick which tools to use (interactively, or--module …/--json
for an agent), assemble the shared agent files, and wire the single nxs prime hook.
nxs prime— the session bootstrap the hook runs: it fans out to theprimeof each active
tool with one shared clock and concatenates the results. A flow-only workspace yields exactly flow's prime; memory's joins after you add it.
nxs sync bind/nxs sync run— sync the shared store with a relay (one op-log, so syncing is
a platform operation, not a per-tool one).
nxs migrate— raise the workspace to the current schema, and upgrade a pre-v0.6.0 workspace to
the umbrella model (it rewrites a legacy nxf prime hook to nxs prime). Idempotent.
nxs doctor(aliasnxs status) — a cross-tool diagnosis: active modules, schema version,
replica identity, sync state, and store integrity.
Each tool keeps its own branded init when you type it directly (nxf init, nxm init); they all land on the same .nxs/ store and the same single nxs prime hook.
Connect an MCP host
MCP-native hosts — Claude Desktop, Claude Code, Cursor, Windsurf — can't drive the nxf CLI, so nexus-flow ships an MCP server (nxs mcp serve) that exposes your board's read and write ops as MCP tools over the same shared .nxs/ store. This guide connects a host to it, including the case where nothing is installed yet.
A host config only launches a *command*. So connecting a host is two decisions: which command launches the server, and which workspace it opens.
The quickest path: the npx runner (no install)
If you have Node (most machines do) you don't need to install anything first. Point the host at the @nexus-flow/mcp runner — it fetches the signed nxs, verifies it, caches it, and starts the server on first launch.
For Claude Desktop, add this to claude_desktop_config.json and restart:
{
"mcpServers": {
"nxs": {
"command": "npx",
"args": ["-y", "@nexus-flow/mcp"]
}
}
}That serves your default board — a per-user workspace nexus-flow creates automatically on first start (the same one the nexflow.it desktop app uses, so you see one board in both). To point it at a specific project instead, append the workspace after --:
{
"mcpServers": {
"nxs": {
"command": "npx",
"args": ["-y", "@nexus-flow/mcp", "--", "--workspace", "/absolute/path/to/your/project"]
}
}
}Everything after -- is passed straight to nxs mcp serve. The first launch downloads and verifies nxs (a few seconds); later launches use the cache and start instantly, offline.
If you already have nxs: nxs mcp install
With nxs on your PATH, one command registers the server in every installed host for you — no hand-editing JSON:
nxs mcp installIt writes an idempotent entry naming the absolute path of your nxs binary plus mcp serve, and patches Claude Desktop, Cursor, and Windsurf if it finds them (re-running changes nothing). Add --setup to also create the board in the same step — one command that both registers the server and materializes the workspace it opens:
# Register + create a personal-todo board at the per-user default (knowledge-worker default):
nxs mcp install --setup
# Register + create a coding board pinned to this project:
nxs mcp install --setup --workspace "$PWD" --plugin issue-trackerTo write the portable, machine-independent npx entry from the command line instead of the direct binary path, add --runner npx.
Choosing the workspace
Because a host has no working directory, the server can't guess "this project" — you say which board it opens:
- Omit `--workspace` → the per-user default workspace, created automatically on first start.
Best for a single personal board shared across your hosts and the desktop app.
- `--workspace <absolute-path>` → that project's board. Create it first (`nxs mcp install --setup
--workspace <path>, or nxs init` there) — an explicit path with no board is an error, not an auto-create.
- A single running server can also be pointed at a different board per tool call by passing a
workspace argument to any tool — one server, many projects, no re-registration.
Bootstrapping nxs when it isn't installed
Two signed ways to get nxs, both fail-closed:
- The one-line installer (installs
nxf/nxm/nxsunder~/.local/bin, no sudo):
``bash curl -fsSL https://nxf.nxsflow.com/install.sh | sh ``
- The `npx` runner (above) — it *is* the bootstrap for GUI hosts: it downloads and verifies
nxs
on demand, so the host config is the only thing you add.
Security
Every fetch path verifies before it runs, and there is no insecure escape hatch on the npx route:
- sha256 proves the bytes weren't mangled in transit.
- minisign (an Ed25519 signature over the tarball, checked against a public key baked into the
installer and the runner) proves the bytes are genuinely ours. A tampered artifact, a wrong key, or a missing signature aborts before anything runs.
Only bytes that pass both gates are cached and executed. install.sh fails closed on a host with no verifier available (rather than install unverified bytes), and nxs self-update always re-verifies.
Other hosts
The same entries work for Cursor and Windsurf (and any MCP host that launches a stdio command). nxs mcp install detects and patches all three; to target one explicitly, pass --host claude-desktop | cursor | windsurf. Once connected, the server sends usage instructions at connect time, and flow_next returns your ready work — call it first in each session.
Core Concepts
This is the plugin-free heart of nexus-flow. Everything here is universal — the same model underlies every plugin; only the words on top change (plugins).
The data model
There are two kinds of item:
- A project groups work (a plugin may call it an *epic* or a *project*).
- A task is a unit of work (an *issue*, a *todo*).
Items carry a small, fixed set of engine-level fields — visible verbatim in any --json record: id, type, title, description, design, status (open / in_progress / closed), priority, due, defer_until, assignee, belongs_to, and a closing_comment. Two relationships connect items:
- belongs-to: a task or project belongs to one parent project (set with
--parent). This is
containment — the breakdown of work.
- dependencies: a directed *must-finish-first* edge between any two items (project or task),
independent of containment.
Beyond dependencies, items can carry mentions — free-text short-id references that record "this text talks about that item" without ever blocking it. Every change is kept as history, and closing an item records a closing comment (the *why*, not just the *that*).
Preserving the original intent
A title and description are fixed shortly after you create an item and then kept stable — they are the record of *what you set out to do*. Correct them once right after creation (for example to fold in a review), and after that leave them alone. New context and everything you learn while working go into the append-only notes stream (nxf note add), not into a rewrite of the original fields. (This is a convention today; a future release may enforce it with an irreversible per-field lock.)
When an item genuinely no longer makes sense, do not reshape it into something unrelated — that would erase its history. Instead open a new item and close the old one with a reason that points to the new one (closing is the only way an item leaves the board; there is no hard delete). The original item stays, closed, as part of the record.
Why this matters: over time it builds the pair "this is what we wanted to achieve" (the description and design) ↔ "this is how we actually closed it" (the closing comment and notes). That intent-vs-outcome pair is exactly what you learn from later. Overwrite the original intent and you lose half of it — and with it the ability to learn. (Preserving intent is only useful if you can find it again: nxf search looks through closed items too, so the pair stays retrievable.)
Dependencies and blocking
A dependency says the *from* item must wait for the *to* item. Suppose ab12.0002 ("Write the CLI") cannot start until ab12.0003 ("Spec sign-off") is done — add the edge:
$ nxf dep add ab12.0002 ab12.0003 --json
{"msg":"ab12.0002 -> ab12.0003","ok":true}
While the blocker is open, the dependent item is blocked:
$ nxf blocked --json
[{"archived":null,"assignee":null,"belongs_to":"ab12.0001","blockers":[{"id":"ab12.0003","status":"open"}],"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Build the command-line tool","design":null,"due":"2026-12-31","id":"ab12.0002","priority":"1","priority_label":"P1","status":"open","title":"Write the CLI","type":"feature","type_label":"feature"}]Derivation: ready / blocked / next
ready, blocked, and next are derived, never stored. They are a deterministic computation over the items and their edges — there is no ready flag to set or forget. An item is ready when it is open and has no open blocker; the project and the unblocked task are ready, while the blocked task is absent:
$ nxf next --json
[{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Cut the first release","design":null,"due":null,"id":"ab12.0001","parent":null,"priority":"1","priority_label":"P1","status":"open","title":"Ship v1","type":"epic","type_label":"epic"},{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Approve the final spec","design":null,"due":null,"id":"ab12.0003","parent":null,"priority":"2","priority_label":"P2","status":"open","title":"Spec sign-off","type":"feature","type_label":"feature"}]next is ready put in order by the active plugin's ranking policy — same derivation, one more step. Because it is all computed, closing the blocker instantly makes the dependent item ready on the next query; nothing has to be re-flagged.
Time: due and defer
Two date fields shape an item over time. due is a target date (it can influence ranking). defer_until hides an item until a date arrives — useful for work you cannot start yet. Derivation is time-sensitive but still deterministic: pass --now to pin the reference instant. In a fresh workspace, a deferred task:
$ nxf create --type feature --title "Pay quarterly taxes" --description "File the quarterly tax return" --priority P3 --defer 2026-07-01 --json
{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":"2026-07-01","deleted":null,"description":"File the quarterly tax return","design":null,"due":null,"id":"ab12.0001","priority":"3","status":"open","title":"Pay quarterly taxes","type":"feature"}Before the defer date it is not ready:
$ nxf next --now 2026-06-15T00:00:00Z --json
[]
On or after it, the very same query returns the task — only --now changed:
$ nxf next --now 2026-08-01T00:00:00Z --json
[{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":"2026-07-01","deleted":null,"description":"File the quarterly tax return","design":null,"due":null,"id":"ab12.0001","parent":null,"priority":"3","priority_label":"P3","status":"open","title":"Pay quarterly taxes","type":"feature","type_label":"feature"}]That determinism — same inputs, same --now, byte-identical output — is what makes nexus-flow safe for agents to drive. Next: see how a plugin renders all of this in plugins, or walk the full command set in commands.
Commands
A tour of the most-used nxf commands, in the order a session tends to use them. Run nxf <command> --help for the terse, generated reference (flags, types, defaults); this guide adds the narrative. Pair any command with --json for deterministic, agent-friendly output.
The session below continues the getting-started workspace under the issue-tracker plugin.
Inspect
show is the full human detail of one item — fields, description, dependencies, and notes:
$ nxf show ab12.0002
0002 P1 Write the CLI
=====================
TYPE: feature
STATUS: in progress
PARENT: 0001
DESCRIPTION
-----------
Build the command-line tool
DEFINITION OF DONE
------------------
DESIGN
------
Thin CLI over the core.
NOTES
-----
- started on the command layerlist dumps every item; with --json it is the canonical, byte-stable snapshot (id-ordered, not ranked):
$ nxf list --json
[{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Cut the first release","design":null,"due":null,"id":"ab12.0001","priority":"1","priority_label":"P1","status":"in_progress","title":"Ship v1","type":"epic","type_label":"epic"},{"archived":null,"assignee":"dev","belongs_to":"ab12.0001","closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Build the command-line tool","design":"Thin CLI over the core.","due":"2026-12-31","id":"ab12.0002","priority":"1","priority_label":"P1","status":"in_progress","title":"Write the CLI","type":"feature","type_label":"feature"},{"archived":null,"assignee":null,"belongs_to":null,"closed_at":"2026-06-23T00:00:00Z","closing_comment":"approved","completion_criterion":null,"defer_until":null,"deleted":null,"description":"Approve the final spec","design":null,"due":null,"id":"ab12.0003","priority":"2","priority_label":"P2","status":"closed","title":"Spec sign-off","type":"feature","type_label":"feature"}]search matches across title, description, and notes:
$ nxf search "thin cli" --json
[{"archived":null,"assignee":"dev","belongs_to":"ab12.0001","closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Build the command-line tool","design":"Thin CLI over the core.","due":"2026-12-31","id":"ab12.0002","priority":"1","priority_label":"P1","status":"in_progress","title":"Write the CLI","type":"feature","type_label":"feature"}]Work an item
claim marks an item in progress and assigns it:
$ nxf claim ab12.0002 --assignee dev --json
{"archived":null,"assignee":"dev","belongs_to":"ab12.0001","closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Build the command-line tool","design":null,"due":"2026-12-31","id":"ab12.0002","priority":"1","status":"in_progress","title":"Write the CLI","type":"feature"}update edits fields — here the design:
$ nxf update ab12.0002 --set "design=Thin CLI over the core." --json
{"archived":null,"assignee":"dev","belongs_to":"ab12.0001","closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Build the command-line tool","design":"Thin CLI over the core.","due":"2026-12-31","id":"ab12.0002","priority":"1","status":"in_progress","title":"Write the CLI","type":"feature"}note add appends a worklog note; note list reads them back:
$ nxf note add ab12.0002 "started on the command layer" --json
{"body":"started on the command layer","id":"[..]"}
$ nxf note list ab12.0002
- started on the command layer
close finishes an item and records a closing comment (the *why*):
$ nxf close ab12.0002 --reason done --json
{"archived":null,"assignee":"dev","belongs_to":"ab12.0001","closed_at":"2026-06-23T00:00:00Z","closing_comment":"done","completion_criterion":null,"defer_until":null,"deleted":null,"description":"Build the command-line tool","design":"Thin CLI over the core.","due":"2026-12-31","id":"ab12.0002","priority":"1","status":"closed","title":"Write the CLI","type":"feature"}Long text without escaping
description, design, the definition of done (--dod), and the closing comment are long, often multi-line prose full of backticks, quotes, and !. Rather than wrestle that through the shell, give any long-text field its value escaping-free from one of three sources. The rule is the same everywhere: exactly one source per field, and at most one field per call may read STDIN; anything ambiguous is rejected before a single write.
Pipe one field from STDIN with the - sentinel — it works on create, update, close, and note add, and the content is stored byte-for-byte:
cat design.md | nxf create --type issue --title "Write the parser" --priority P1 --design -
printf '%s' "$LONG_TEXT" | nxf update ab12.0002 --set description=-
nxf close ab12.0002 --reason - # closing comment from STDIN
nxf note add ab12.0002 - # worklog note from STDINRead fields from files (UTF-8, verbatim) — and unlike STDIN, several fields may each come from their own file in one call:
nxf create --type issue --title "Write the parser" --priority P1 \
--description-file ./desc.md --design-file ./design.md --dod-file ./dod.md
nxf update ab12.0002 --set-file design=./design.mdOr write the whole item as one JSON object on STDIN — no flag combinatorics at all. Pair it with --json (the canonical form --json -) for JSON output too:
echo '{"type":"issue","title":"Write the parser","description":"…","design":"…","priority":"P1"}' \
| nxf create --json -
echo '{"description":"…","design":"…"}' | nxf update ab12.0002 --json -A file path of - is the STDIN sentinel as well; a field given two sources (or a second field also asking for STDIN) is a clear error, and nothing is written.
Structure the work
dep add / dep remove manage the *must-finish-first* edges that drive blocking (see core-concepts):
$ nxf dep add ab12.0002 ab12.0003 --json
{"msg":"ab12.0002 -> ab12.0003","ok":true}
$ nxf dep remove ab12.0002 ab12.0003 --json
{"msg":"removed ab12.0002 -> ab12.0003","ok":true}
mention add / mention list / mention remove record free-text short-id references — a citation that never blocks:
$ nxf mention add ab12.0002 ab12.0001 --json
{"msg":"ab12.0002 mentions ab12.0001","ok":true}
$ nxf mention list ab12.0002 --json
["ab12.0001"]
$ nxf mention remove ab12.0002 ab12.0001 --json
{"msg":"removed mention ab12.0002 -> ab12.0001","ok":true}
Bootstrap an agent
prime is one call that hands an agent the plugin-determined statement of what nxf is (purpose), the working rules, the ranked next recommendation (top 7, in-progress work first), a leverage-aware blocked snapshot, a create example carrying the active plugin's type vocabulary and priority range, and the command reference (whose dep entry spells out the dependency direction). The deterministic entry point for an automated session:
$ nxf prime --json
{"blocked":[],"commands":[{"group":"Finding work","items":[{"name":"next","summary":"ready work in priority order (start here); add --include-in-progress for claimed work"},{"name":"blocked","summary":"list blocked work"},{"name":"show <id>","summary":"item detail with deps and notes"}]},{"group":"Creating & updating","items":[{"name":"create","summary":"create an item — see the `create` section above"},{"name":"update <id> --set k=v","summary":"edit fields"},{"name":"claim <id>","summary":"mark in progress"},{"name":"close <id> --reason","summary":"close with a comment"},{"name":"schema","summary":"introspect this plugin's field model (--json) before create/update"}]},{"group":"Dependencies & references","items":[{"name":"dep add <from> <to>","summary":"<from> depends on <to> (so <to> blocks <from> and must close first)"},{"name":"mention add <from> <to>","summary":"record a free-text short-id reference"}]},{"group":"Notes & search","items":[{"name":"note add <id> <text>","summary":"append a worklog note"},{"name":"search <query>","summary":"search title/description/design/DoD/notes"}]}],"context_recovery":"Run `nxs prime` after a context compaction, /clear, or a new session — hosts auto-call it in Claude Code when a nexus-flow workspace is resolved.","create":{"example":"nxf create --type <bug|chore|decision|epic|feature> --title /".../" --priority <P0|P1|P2|P3|P4>","long_text_hint":"Long text without shell escaping: pipe a field via STDIN (`--description -`), read it from a file (`--description-file <path>`), or pipe the whole item as JSON (`nxf create --json -`).","recommendation":"Always set --priority (named variants, highest first: P0 … P4); an item created without a priority ranks last in `next`."},"next":[{"id":"ab12.0001","parent":null,"priority":"1","status":"in_progress","title":"Ship v1","type":"epic"}],"next_total":1,"purpose":"nexus-flow is a software issue tracker for epics and issues. You record items, the dependencies between them, due/defer dates, and priority; `next` and `blocked` are then derived deterministically from that graph rather than stored, so the work list is always consistent.","rules":["Track all work in nexus-flow itself: open an item for every task rather than keeping a separate TODO list or scratch notes — the board is the single source of truth.","Find what to work on next: `nxf next`.","Claim work before starting it: `nxf claim <id>`.","Close with a reason: `nxf close <id> --reason <text>`.","Use `--json` everywhere for deterministic, machine-readable output.","Choose the containment edge deliberately: `parent` is gating — a child rests when its container rests (a deferred, blocked, or closed parent propagates down and hides or masks the child). For a loose association that must NOT gate the child, use `contributes_to` (e.g. cream belongs to the shopping list but only contributes to the birthday plan, so deferring the birthday never hides the cream).","Defer only for a real calendar date — a day before which the item genuinely cannot start (`--defer <date>` on create, or `nxf update <id> --set defer=<date>`); a placeholder date for /"someday, once X ships/" is an anti-pattern that hides the item on a false promise. To wait on an external DELIVERY instead — there are no cross-workspace dependencies — model the delivery as an open WAIT chore in this workspace (title it `WAIT: <what ships>`, e.g. `WAIT: acme-api v2`), have the dependents `nxf dep add <id> <wait-chore>` onto it, and CLOSE the chore — with the delivered version in the reason — to release the whole chain. Each workspace keeps its own anchor; see `nxf guide deferring-and-waiting`.","Correct an item's fields once shortly after creating it (e.g. to fold in a review); after that keep the fields stable and record what you learn while working as append-only notes (`nxf note add <id> <text>`), not field edits. The original title and description are preserved on purpose: paired with the closing comment they form the intent-vs-outcome pair you learn from, so when an item no longer fits, open a new one and close the old with a reason instead of rewriting it past recognition.","When you cite a task's short-id in free text (body or note), also record the reference: `nxf mention add <this-item> <cited-id>`. It keeps the citation resolvable if ids are remapped on sync, and never blocks (it is not a dependency)."],"session_close":["Capture unfinished work as a note so the next session has the context: `nxf note add <id> <text>`.","Close finished items with the reason they're done: `nxf close <id> --reason <text>`.","If the project is under version control, commit and push your code changes."],"workflows":[{"name":"Starting work","steps":["nxf next","nxf show <id>","nxf claim <id>"]},{"name":"Completing work","steps":["nxf close <id> --reason /".../"","nxf next # pick up the next unblocked item"]},{"name":"Creating dependent work","steps":["nxf create --type <type> --title /".../" --priority <P…>","nxf create --type <type> --title /".../" --priority <P…>","nxf dep add <child> <prereq> # child depends on prereq; prereq must close first"]}]}Plugins
A plugin maps the universal core to a consumer's language and policy. Nothing in the CLI hardcodes vocabulary — it all flows from the active plugin config, chosen once at nxf init. A plugin sets four things:
- Vocabulary: the words for the two item types and the three statuses.
- Priority labels: the names for priority levels 0–4.
- Ranking: how
nextorders the ready set. - Presentation: which fields
listandshowdisplay.
The two shipped plugins
- issue-tracker — Software issue tracking: epics and issues, P0–P4 priorities,
dependency-aware ranking.
- personal-todo — Personal to-do list: lists and todos, now/soon/later priorities for
everyday tasks.
Their vocabularies differ:
- issue-tracker: a project is an
epic, a task is anissue; statuses are
open / in progress / closed; priorities are P0–P4; next ranks by priority, then due date, then id.
- personal-todo: a project is a
project, a task is atodo; statuses are
todo / doing / done; priorities are now / soon / later / someday / icebox; next ranks by priority, then id (no due-date tiebreak).
Resolving named variants: types and priorities
type and priority are both *named variants* — a small, plugin-defined set with a fixed order. nxf schema --json exposes both as a keyed map, so one rule resolves either field on any item:
schema.types[item.type] # "task" -> "issue"
schema.priorities[item.priority] # "0" -> "P0"The value stored on an item is the *handle*, not the label. For priority that handle is an ordinal — "0" is the highest priority, counting up — deliberately plugin-independent so next can rank numerically and synced items never carry another plugin's labels. The schema.priorities map is what turns the ordinal back into a human label.
Ordinal-stability contract. Within a schema version the ordinal→meaning binding is stable and append-only: priority.labels may gain entries at the end, but reordering or inserting shifts the meaning of already-stored items and is therefore a breaking schema change — a schema-version bump with migration, not an in-place edit.
Same data, side by side
The seam is clearest when you run the same commands on the same data under each plugin. Both workspaces below hold three tasks: two at priority 1 (one due 2026-02-01, one due 2026-03-01) and one at priority 2.
next shows two differences at once — the vocabulary and the ranking. Under issue-tracker, the earlier-due P1 issue (Book venue) wins the tiebreak:
$ nxf next
0002 P1 open [feature] Book venue
0001 P1 open [feature] Draft proposal
0003 P2 open [feature] Order badgesUnder personal-todo, the same two soon todos tie on priority and fall back to id, so the first-created (Draft proposal) comes first — and the labels are now/soon/later, todo/doing/done:
$ nxf next
0001 soon todo [todo] Draft proposal
0002 soon todo [todo] Book venue
0003 later todo [todo] Order badgesYet the stored record is the same — list --json is id-ordered and does not depend on the active plugin. The plugin overlays presentation and ranking; it never changes the data. The one field a plugin owns is type: the type set is plugin-declared, so issue-tracker stores feature where personal-todo stores todo. Strip that one field and the records are byte-for-byte the same:
$ nxf list --json
[{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Outline the event proposal","design":null,"due":"2026-03-01","id":"ab12.0001","priority":"1","priority_label":"P1","status":"open","title":"Draft proposal","type":"feature","type_label":"feature"},{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Reserve the event space","design":null,"due":"2026-02-01","id":"ab12.0002","priority":"1","priority_label":"P1","status":"open","title":"Book venue","type":"feature","type_label":"feature"},{"archived":null,"assignee":null,"belongs_to":null,"closed_at":null,"closing_comment":null,"completion_criterion":null,"defer_until":null,"deleted":null,"description":"Print attendee name badges","design":null,"due":null,"id":"ab12.0003","priority":"2","priority_label":"P2","status":"open","title":"Order badges","type":"feature","type_label":"feature"}]show makes the vocabulary difference concrete on a single item. Issue-tracker:
$ nxf show ab12.0002
0002 P1 Book venue
==================
TYPE: feature
STATUS: open
DESCRIPTION
-----------
Reserve the event space
DEFINITION OF DONE
------------------
DESIGN
------
NOTES
-----personal-todo, the same ab12.0002:
$ nxf show ab12.0002
0002 soon Book venue
====================
TYPE: todo
STATUS: todo
WHY
---
Reserve the event space
DONE WHEN
---------
PLAN
----
LOG
---That doubling is not redundancy — it *is* the explanation. The --json is the meaning; the plugin is how a particular audience reads and ranks it. Picking a plugin at init is therefore a real choice; run nxf init --help to see the options before you commit.
Migration
This guide covers two kinds of migration: bringing existing work into nexus-flow, and moving between major versions of nexus-flow itself.
Bringing an existing tracker in
nexus-flow has no bulk importer — and does not need one. Items are created through the same nxf create you use day to day, so a migration is a short script that walks your old tracker and calls nxf once per item, mapping each record onto the core model: a --type (project or task), a --title, optionally a --parent, --priority, --due, and --description. Re-create dependencies afterward with nxf dep add. Because every command takes --json and is deterministic, the script is easy to write and verify:
# sketch: one create per legacy ticket, then wire dependencies
nxf create --type project --title "Imported backlog" --json
nxf create --type task --title "Legacy #1234" --parent ab12.0001 --priority P2 --json
nxf dep add ab12.0002 ab12.0003Pick the plugin whose vocabulary matches the source tracker at nxf init — that is the only up-front decision the import depends on.
Binding a sync stream
nexus-flow is offline-first: you work locally against .nxs/, and a sync stream converges every replica on the durable server truth. Bind a stream once, then run sync whenever you reconnect:
nxs sync bind --create
nxs sync run --remote https://your-relay.example.comWork continues offline between runs; sync run exchanges changes and merges them deterministically (the engine is a CRDT, so concurrent edits converge without a coordinator). The server is the durable record, not a lock — no one has to be online for you to make progress.
Migrating across major versions
nexus-flow follows plain SemVer. Within a major version, upgrades (nxs self-update) are drop-in. A major version bump (e.g. 1.x → 2.0) is the only place a breaking change may land, and every such change ships a migration note describing what is automatic and what needs your attention. Those notes are aggregated per major version into a single upgrade guide.
Read the aggregated notes for a major before upgrading to it — they live alongside this guide on the website /docs and in the release notes for the version. Within a 0.x series there is no stability guarantee yet, so review the changelog on each update.
Command reference
Generated from the CLI's own command tree. Run a command with --help for its full flags and types.
- nxf agent-manifest
- Emit nxf's declared contribution to the shared agent files (the AGENTS.md/CLAUDE.md section, the prime command, the SessionStart hook) as data. The `nxs` umbrella assembles the shared files from each active module's manifest (spec §6.2); `--json` is the machine contract
- nxf archive
- Archive one or more items — "closed and put away". Cascades DOWN: each root and its whole `belongs_to` subtree are archived, but only when the root is closed and every descendant is closed (already-archived counts as closed). Atomic per root, independent between roots; the result reports each root's outcome plus the full list of ids actually archived (incl. cascaded). Archiving is reversible — see `unarchive`
- nxf archived
- List archived items (any status). Ordered by archive-date descending (most recent first); override with `--sort`
- nxf blocked
- List blocked items (open, with an open blocker or in a cycle). Ranked by default; override with `--sort id`
- nxf claim
- Claim an item: mark it in progress (and optionally assign it)
- nxf close
- Close an item, recording why. Closing is final (no hard delete), so a reason is required
- nxf closed
- List closed items (excluding archived). Ordered by close-date descending (most recent first); override with `--sort`
- nxf contributes add
- Record that `from` contributes to `to` (both must exist; never blocks)
- nxf contributes list
- List the items `id` contributes to
- nxf contributes remove
- Remove the `from -> to` contributes-to edge
- nxf create
- Create a new item — a complete item in one call. Title, description, and priority are required; design, the definition of done, a parent, and dependencies are optional. Run `nxf schema` for the active plugin's field model (labels, constraints, required fields)
- nxf deferred
- List deferred items (open, unblocked, with a future defer date) — the lane that is neither ready nor blocked. Ordered by defer-date ascending (soonest first); override with `--sort`
- nxf dep add
- Make `from` depend on `to`: `to` blocks `from`, so `from` stays blocked until `to` closes. Rejected if it would create a cycle
- nxf dep remove
- Remove the dependency where `from` depends on `to`
- nxf guide
- Print an embedded, offline guide; no topic lists the available topics
- nxf init
- Initialize a `.nxs` workspace in the current directory: set up flow, then delegate the shared agent files + the single `nxs prime` SessionStart hook to the `nxs` assembler. To set up the whole suite (and pick tools interactively), use `nxs init` instead
- nxf label add
- Attach a label to an item (idempotent). The label is trimmed; a blank label is rejected
- nxf label list
- List an item's labels (sorted)
- nxf label remove
- Detach a label from an item (observed-remove)
- nxf list
- List items, optionally filtered by status and/or type. Id-ordered by default (so the `--json` record stays plugin-independent); override with `--sort rank`
- nxf mention add
- Record that `from` cites the short-id `to` in its free text (no blocking)
- nxf mention list
- List the short-ids `id` mentions
- nxf mention remove
- Remove the `from -> to` reference
- nxf next
- List ready work — open, unblocked, not deferred — ranked by the active plugin's `next` policy. Add `--include-in-progress` to fold in actionable claimed work; override the order with `--sort id`
- nxf note add
- Append a note to an item. Pass `-` as the text to read the note body from STDIN (escaping-free, multi-line)
- nxf note list
- List an item's notes
- nxf schema
- Describe the active plugin's field model — vocabulary, priorities, and per field whether it is required on create / settable on update and how. `--json` is the machine contract; run it to learn what `create`/`update` accept in this workspace (the static `--help` cannot carry the active plugin's vocabulary)
- nxf search
- Search items by substring over title, description, design, DoD, and notes. Results are grouped by lane priority (next+in-progress → blocked → deferred → closed), each group in its natural order; archived items are excluded by default
- nxf setup claude
- Wire Claude Code: (re)assemble the shared agent files (AGENTS.md/CLAUDE.md) and the single SessionStart hook that runs `nxs prime` (the umbrella fan-out) plus the `nxs`/module permission allowlist, merged into `.claude/settings.json` (idempotent, never overwriting). The canonical verb is `nxs setup claude`; this delegates to it (host setup is an umbrella responsibility)
- nxf show
- Show one item with its dependencies and notes
- nxf unarchive
- Unarchive one or more items, making them visible again. Cascades UP only: each item and its ancestor chain resurface, but its children/siblings stay archived. Partial per root; the result reports each root's outcome plus the full list of ids actually unarchived
- nxf update
- Update item fields via `--set field=value` (repeatable). The long-form `description`/`design`/`completion_criterion` are ordinary `--set` fields. Run `nxf schema` for the settable fields and their plugin names. Convention: correct the field model once shortly after creation; once it is stable, record what you learn as append-only notes (`nxf note add`) rather than further field edits