Top-Level Commands#
The commands registered directly on the fractal executable operate on
the tree as a whole: they install the plugin skills, initialize and tear
down a fractal, commit work, and brake or release every loop at once. Node-
and message-level commands live in the sub-apps (fractal node,
fractal radio, fractal plan).
fractal --version prints the package version and exits.
install#
$ fractal install [--project] [--link]
Install the fractal and wiki skills for Claude Code and Codex.
The bundled skills are copied into the Claude Code (.claude/skills) and
Codex (.agents/skills) skill directories under the home directory by
default. The wiki skill ships with fractal’s plasma-wiki dependency
and is installed alongside. Any prior install at a destination is replaced;
each placement echoes Installed <skill> -> <dest>. (or
Linked <skill> -> <dest>. with --link).
--projectInstall into the current working directory instead of the home directory. Default: off (the home directory).
--linkSymlink the bundled skills instead of copying, so source edits apply without re-installing. Requires the package files on disk (an editable install); a zipped install refuses because the bundled skills are not real directories. Default: off (copy).
$ fractal install
Installed fractal -> /home/user/.claude/skills/fractal.
Installed fractal -> /home/user/.agents/skills/fractal.
...
init#
$ fractal init [PATH] [--agent <command>] [--provider <route>]
Initialize fractal for a repository (or a monorepo sub-project), creating the user (root) node on the currently checked-out branch. The user node anchors the tree: it carries configuration, the central SQLite database, and the radio, but runs no loop of its own (see Architecture). Init creates:
the data directory
<project>/.fractal/<branch>/withconfig.json(markeduser: true), the central database, and the radio’s default channels;the project wiki at
<project>/wiki/when absent;fractal’s block in the repo-local
.git/info/exclude(worktrees, databases, status markers, agent logs), and a.gitignoreof*inside the seed directory itself, so.fractal/<branch>/is git-ignored by default (fractal trackremoves that file to opt in).
An existing project wiki (a wiki/ carrying _index.md) is adopted as
is — init rewrites nothing in it. It warns when wiki/_index.md carries no
frontmatter stamps (run wiki update --path=wiki and commit the result
before initializing nodes) and when .gitattributes lacks the
**/_index.md merge=wiki line (append it and commit), since sibling nodes
otherwise conflict on the index when they merge.
The command ends by printing the required next step: the baseline commit
(fractal commit "<message>" --init). Node worktrees can only branch
from a committed tree.
Re-running on an initialized tree is idempotent — it never clobbers existing data. A re-run repairs a partial prior init (a stranded database, radio, or missing wiki) and updates the stored agent and provider defaults when the flags are given.
PATHRepository root or monorepo sub-project folder. Default:
..--agentDefault agent command that spawned nodes inherit (e.g.
claude). The name is validated against the agent registry at init, so a typo refuses immediately. Default: unset — an agent must then be named somewhere in each node’s ancestor chain at spawn time. See Agent Backends.--providerDefault provider route for spawned nodes (e.g.
openrouter). Default: the vendor-native endpoint.
Refuses when:
HEAD is detached (check out a branch first);
the branch name contains
/(per-branch artifacts key on the branch as a single path component);the branch dot-nests with an existing tree’s root (
v1.0beside a tree rooted atv1, in either order) —.is the node hierarchy separator, so one would read as a node inside the other. A dotted root alone is fine; switch to a branch that is not dot-nested with an existing root;PATHlies under.worktrees/(run from the repo root or a sub-project folder);PATHlies in a linked git worktree outside the main repository root (runfractal initfrom the main checkout);the branch is already mapped to a different project — one branch maps to a single project;
<project>/wiki/exists, is not empty, and is not a project wiki (it carries no.wiki/marker): adopting it would rewrite its files in place. Move the directory aside and re-run init, or convert it first withwiki init --path=wiki; the refusal lands after the data directory is written, and the re-run completes the partial init;the command runs from a draining seat (an agent invocation of a
fractal node start --continue --drainrun, or any process in its process group — see--drainin fractal node): a drain forbids every spawn, a whole new tree included;another live fractal on the machine shares this repository’s directory basename: tmux session names carry the basename, so two fractals under one basename would collide. Rename one repository directory.
$ cd myproject
$ fractal init --agent claude
Initialized user node on branch main
Created .fractal/main/ (config, database, radio) and the project wiki at wiki/
Next: commit the baseline: fractal commit "<message>" --init
track#
$ fractal track [NAME] [--path <dir>]
Track the user node’s .fractal/<branch>/ seed directory on the
top-level branch: remove the seed directory’s self-ignore file (a
.gitignore of * written at init) so the directory is no longer
ignored, then print the git command to stage it. The git index is never
touched — staging is left to you. The toggle is per tree and idempotent,
anchors on the tree’s user node by configuration (so it works from any
checkout inside the repo), and fractal untrack is its inverse. Untracked
is the default state after fractal init.
NAMETree root branch. Default: the tree this checkout belongs to.
--pathRepository path. Default:
..
Refuses when the tree has no user node: No user node found under <repo>.
Run `fractal init` at the repo root. An unknown NAME refuses with
No fractal tree '<name>' under <repo>. Trees here: <roots>.
$ fractal track
Tracking .fractal/main/ on the top-level branch.
Next: stage it with: git add -- .fractal/main
untrack#
$ fractal untrack [NAME] [--path <dir>]
Git-ignore the user node’s .fractal/<branch>/ seed directory again —
the default state. Restore the seed directory’s self-ignore file (a
.gitignore of * inside it), then print the git command to unstage
an already-committed seed; the index is never touched. Repo-wide,
idempotent, and anchored on the user node from any checkout, exactly like
fractal track.
NAMETree root branch. Default: the tree this checkout belongs to.
--pathRepository path. Default:
..
Refuses when the tree has no user node.
$ fractal untrack
Ignoring .fractal/main/ on the top-level branch.
Next: unstage a committed seed with: git rm -r --cached -- .fractal/main
commit#
$ fractal commit [MESSAGE] [--init] [--check] [--ignore-scope] [--force]
[--path <dir>]
Commit the current iteration’s work through the commit pipeline: scope
check, wiki index refresh, lint (the node’s scripts/lint.sh), stage,
commit, and push — the push is skipped when the node’s local
configuration is set. The commit subject is wrapped as
<branch>: iteration <run>.<iter> (<message>); a message that already
carries the branch prefix or begins with an iteration label is refused,
since the tool adds the wrapping itself. Node loops run this command at the
end of every iteration; an operator can run it from a node worktree.
On a user node only the --init baseline is accepted. The baseline
commits fractal’s own artifacts — the project wiki, plus the seed directory
when the tree is tracked — using an explicit pathspec, so any other staged
work is never swept in, and it does not push. Its subject is
<branch>: init (<message>).
MESSAGEShort description appended to the commit message. Required unless
--check.--initBaseline commit labeled
initinstead ofiteration <run>.<iter>. Skips the wiki index refresh and lint. The only commit form a user node accepts. Default: off.--checkExit
1if uncommitted changes exist instead of committing: the noticeUncommitted changes remain (agent should have committed).rides stderr without theError:prefix. A clean tree exits0and prints nothing; command and usage errors exit2, so a script can gate on the tree state by exit code. Default: off.--ignore-scopeCommit out-of-scope changes but still lint — a narrower escape hatch than
--force. Default: off.--forceBypass the scope check, lint, and git hooks. Default: off.
--pathWorktree directory. Default:
..
Refuses when:
any two of
--init,--check,--ignore-scope, and--forceare combined — all pairs are mutually exclusive;MESSAGEis missing and--checkis not set;the command runs on a user node without
--init(Cannot commit from a user node (only --init is supported).);changes fall outside the node’s configured
scopeand neither--ignore-scopenor--forceis set;lint.shfails;--checkfinds uncommitted changes — exit1with the bare notice, not theError:/ exit2refusal shape.
$ fractal commit "add the parser skeleton"
open#
$ fractal open [NAME] [--path <dir>] [--light | --dark]
Open the TUI cockpit (see The TUI), anchored on the tree’s user node and focused on the named node, or on the tree’s root when none is named.
NAMEA tree root branch (opens that tree’s cockpit at its root) or a node branch to focus (opens the tree owning it, focused there; a unique trailing segment resolves). Default: the caller’s own tree, at its root.
--pathRepository path. Default:
..--lightOpen with the light palette. Default: off.
--darkOpen with the dark palette — the default. Mutually exclusive with
--light.
Refuses when --light and --dark are combined, or when the tree has
no user node.
$ fractal open parser --light
pause#
$ fractal pause [NAME] [--reason <text>] [--path <dir>]
The tree-wide brake. It latches the root first — a .paused marker
beside the central database — then fans a pause out over every active
node, parent-first, aborting each in-flight agent invocation. Every loop
parks with status paused, leaving its run and iteration rows open for
fractal resume to adopt; a parked node has no tmux session — that is
its normal state, not a crash. While the tree is latched, spawning
(fractal node init) and fractal node start refuse everywhere in the
tree. The command anchors on the user node by configuration, so it works
from any checkout inside the repo. To pause a single subtree instead, use
fractal node pause (fractal node); pause semantics are covered in
Node Lifecycle.
Output: Pause signal sent to N node(s) (in-flight agents aborted; loops
park paused), or No active nodes to pause (tree latched until
resume). when nothing is running — the latch still lands.
NAMETree root branch. Default: the tree this checkout belongs to.
--reasonOptional reason, recorded on the pause events and appended to the confirmation. Default: none.
--pathRepository path. Default:
..
Refuses when the tree has no user node.
$ fractal pause --reason "budget review"
Pause signal sent to 2 nodes (in-flight agents aborted; loops park paused): budget review
resume#
$ fractal resume [NAME] [--path <dir>]
The tree-wide release. It lifts the root latch first — spawns and starts are legal again the moment the release begins — withdraws the pending pause on any node still parking, then relaunches every parked loop leaf-first. Each relaunched loop adopts its open run where the pause left it: the same budgets and iteration count, the interrupted step re-entered (resuming the recorded agent session when one exists, re-orienting fresh otherwise), and run and iteration deadlines credited for the paused span.
Output: Resumed N node(s) (parked loops relaunched leaf-first; live
pauses withdrawn), or No paused nodes to resume..
NAMETree root branch. Default: the tree this checkout belongs to.
--pathRepository path. Default:
..
Refuses when the tree has no user node.
$ fractal resume
Resumed 2 nodes (parked loops relaunched leaf-first; live pauses withdrawn)
reset#
$ fractal reset [NAME] [--force | -f] [--path <dir>]
The middle teardown tier, between fractal node delete (one subtree) and
fractal destroy (one tree, or the whole fractal with --all). It
removes every one of the tree’s node worktrees, local branches, and
registry registrations. Sibling trees and the user node’s data —
configuration, memory, and the central database with every history row —
plus the project wiki and baseline commits survive, so fresh nodes can spawn
immediately after. Remote branches are left on the remote and listed.
A stale tree-wide pause latch is also cleared.
Without --force an interactive confirmation names the node count; when
paused nodes exist, a separate warning names how many hold frozen mid-step
work. Confirming (or passing --force) authorizes killing those paused
nodes as part of the teardown.
NAMETree root branch. Default: the tree this checkout belongs to. Only that tree’s nodes are removed; sibling trees are untouched.
--force,-fSkip the confirmation prompt; paused nodes are killed without asking. Default: off.
--pathRepository path. Default:
..
Refuses when:
any of the tree’s nodes’ loop runtime is alive (a tmux session, or a headless or bare loop’s recorded process group) — kill it first with
fractal node kill <branch>;--forcenever overrides this, it only skips the prompt;the runtime probe is inconclusive for a node that still has something to protect — an unsettled status, or a lingering
.pgid,.socket, or.headlessrecord (restore tmux visibility or checkps, then retry); a settled node with none of those records proceeds;any of the tree’s node worktrees is locked;
the caller stands inside one of the tree’s node worktrees (run from the repo root).
$ fractal reset
Warning: This permanently removes every one of the tree's node worktrees, branches, and registrations. The user node, project wiki, and all history are left in place.
Reset the tree 'main' at /home/user/myproject (5 nodes)? [y/N]: y
destroy#
$ fractal destroy (NAME | --all) [--force | -f] [--path <dir>]
The top teardown tier, database included. fractal destroy NAME removes
one tree by its root branch: everything fractal reset removes for that
tree, plus its user node’s data directory (configuration and the
central database). Sibling trees survive, along with the shared
.worktrees/ directory and fractal’s block in .git/info/exclude;
when the destroyed tree was the last one, those go too. With --all the
command is the full inverse of fractal init: it removes every tree’s
worktrees, branches, and data directories, the .worktrees/ directory,
and the exclude block. Exactly one scope must be named — a bare
fractal destroy is refused as ambiguous. In both forms committed
artifacts — the project wiki and baseline commits — remote branches, and
the tree’s own root branch remain. The confirmation prompt, paused-node
kill policy, and refusal conditions are the same as fractal reset.
--all on a repository with no fractal is a clean no-op (the
confirmation still asks, reporting 0 nodes); a NAME that matches no
tree is refused with No fractal tree '<name>' under <repo>.
NAMERoot branch of the tree to destroy. Mutually exclusive with
--all; exactly one is required — the tree is never inferred from the checkout.--allDestroy every tree and remove
.worktrees/(the full inverse offractal init). Mutually exclusive withNAME.--force,-fSkip the confirmation prompt; paused nodes are killed without asking. Default: off.
--pathRepository path. Default:
..
Refuses when neither or both of NAME and --all are given
(Name a tree or pass --all (exactly one).).
$ fractal destroy main
Warning: This permanently removes the tree's node worktrees and branches plus its fractal data, including its user node. Sibling trees, the project wiki, and commit history are left in place.
Destroy the tree 'main' at /home/user/myproject (5 nodes)? [y/N]: y
$ fractal destroy --all
Warning: This permanently removes every node worktree and branch plus all fractal data, including every user node. The project wiki and commit history are left in place.
Destroy the fractal at /home/user/myproject (5 nodes)? [y/N]: y