The operating model

Every piece of work is a change.

/sulis:change is the one command for the whole life of a piece of work — start, focus, ship, rebase, discard. Everything else in Sulis happens inside a change. If you're going to learn one Sulis command, learn this one.

The lifecycle

A piece of work moves through six stages, all bounded by a single change:

// Start a piece of work /sulis:change start "fix the login bug" │ ▼ A new terminal opens, focused on this change. │ ▼ Recon ▸ Specify ▸ Design ▸ Implement ▸ Review // stages 0–4 happen inside │ ▼ /sulis:change ship CH-01HQ8X │ ▼ Reviewed, merged into dev, archived as audit trail.

Every change gets a six-character handle (CH-01HQ8X), its own Git branch (change/fix-login-bug), and its own isolated worktree directory. The handle is what you'll use to reference the change in conversation; the branch and worktree are where the work actually lives.

Two things to know about how Sulis runs

When you start a change, Sulis does two things that are worth knowing about up front. Both are deliberate; both are shaped by the realities of autonomous engineering.

01 A new terminal window opens for the change.

Each piece of work gets its own terminal, its own working directory (a Git worktree), and its own focused Sulis session. The reason: context isolation. If you're working on auth in one change and storage in another, the two sessions don't bleed into each other — each Sulis knows about its own change and nothing else.

You can have three or four changes in flight without any of them getting confused about what they're building. /sulis:change focus CH-xxxx jumps you back to the terminal for a specific change.

02 The spawned terminal runs with --dangerously-skip-permissions.

Claude Code asks for permission before every shell command, file edit, and network call by default. That's the right safe default for casual use — but it makes autonomous engineering impractical (a full change might need 200+ permission prompts before it ships).

The spawned terminal opts out of those prompts so Sulis can run the full lifecycle — spec, design, build, review, secure — without you sitting on the prompt button. The trade-off is explicit: Sulis runs more autonomously inside the isolated worktree.

The six subcommands

Each subcommand maps to one decision the founder makes about a piece of work. Three are safe (no destructive side effects); two prompt before acting; one is destructive and explicit.

/sulis:change start <intent> Safe

Opens a new focused workspace for a piece of work. The most common entry point.

/sulis:change start "fix the login bug" # or with explicit primitive: /sulis:change start --primitive fix --intent "fix the login bug"
What happens. Sulis picks a primitive (e.g. fix) from the 22-primitive vocabulary, creates a branch (change/fix-login-bug) and a worktree, writes a reconnaissance note about the existing repo, then spawns a new terminal already focused on the change. The handle (CH-01HQ8X) is what you'll use to reference the change later.

If your system can't spawn a terminal automatically (some platforms or terminal apps don't support it), Sulis tells you the path to cd into and the command to run yourself. No silent fail.

/sulis:change list Safe

Shows every change in flight, in one scannable list.

/sulis:change list
What it shows. The 10 most recent changes, each one row: human name + handle + primitive (translated to plain English — "bug fix", "new feature", "restructuring") + branch + whether the workspace is still live. Capped at 10 with a +N more line if there are more.

The list is file-based — Sulis reads change manifests on disk, your local session state, and the Git branches that exist. There's no database, no service to be down.

/sulis:change focus <CH-handle> Safe

Reattaches to a change you started earlier.

/sulis:change focus CH-01HQ8X
Two cases. If the terminal for that change is still running, Sulis points you at it — no duplicate spawn. If the session is dead (you closed the terminal, restarted your machine, etc.), Sulis opens a fresh terminal with the same change context restored.
/sulis:change ship <CH-handle> Prompts first

Lands a finished change into the shared dev branch. This is the only subcommand that changes shared state — so Sulis runs through a four-step gate before the merge happens.

/sulis:change ship CH-01HQ8X
The gate, in order.

1. Confirm. Sulis echoes the exact branch + the irreversible step and asks for an explicit yes/no.
2. Push + open PR to dev. Never to main; promotion to main is a separate, deliberate founder act.
3. Wait for automated checks. The PR's branch-ci must go green before the merge proceeds. If it fails, Sulis stops and surfaces what broke.
4. Run the review gate. /sulis:review composes code-health + security and returns PASS (proceed), CONCERN (ask the founder), or CRITICAL (stop, do not merge).

The trivial-change carve-out (CW-05): if the change is ≤30 lines, 1 file, and no new files were added, Sulis skips the full review automatically — and tells you it skipped, with the reason. Otherwise the review runs.

The audit trail. After the squash-merge, the remote branch is deleted (it's just the merge artefact). The local branch and worktree stay intact, marked stage='shipped'. The cockpit's "Shipped" section reads from this; you can always retrace what shipped and why.

/sulis:change rebase <CH-handle> Safe

Pulls the latest dev work into the change branch so your work stays current with the team.

/sulis:change rebase CH-01HQ8X
It's a merge, not a rebase. Despite the name, Sulis uses a merge under the hood — this preserves the commit SHAs of work already done inside the change (important for any in-flight executor sessions or pull-request comments anchored to specific commits).

If the merge clean: Sulis reports the commit count and you keep going. If there are conflicts (the team touched the same lines as your change), Sulis tells you which files clash and lets you decide whether to resolve now or carry on with the current work and handle conflicts later. Sulis won't auto-resolve.

/sulis:change nuke <CH-handle> Destructive

Throws a change away. Deletes its branch, its worktree, its local state, and its manifest. Use for abandoned experiments, dead-ends, and orphaned changes you don't want taking up cognitive space.

/sulis:change nuke CH-01HQ8X
Dry-run first, always. The first invocation shows exactly what would be removed — branch path, worktree directory, manifest file — without touching anything. You confirm by running again with --force, or Sulis surfaces the dry-run summary and asks for explicit yes.

Shipped changes are protected by default. nuke won't destroy the audit trail of a shipped change unless you pass an explicit --include-shipped flag.

The 22 primitives

Every change carries a primitive — the kind of architectural move it represents. Sulis picks one from your intent ("fix the login bug" → fix; "split the god-class" → decompose) and falls back to feat when nothing clearly fits. The primitive shapes the branch name, the conventional commit prefix, and the kind of review the change goes through.

The 22 primitives sit inside 5 mutually-exclusive groups, ordered by the dominant relationship the change has to existing code:

Expand 5 primitives

Introduce new code, or new usage of existing code. Adds behaviour.

reuseUse an existing component as-is in a new place.
composeCombine existing components in a new arrangement.
extendAdd behaviour to an existing component.
generateCreate code from a schema, a template, or a contract.
createIntroduce something genuinely new — no precedent in the codebase.
Reorganise 6 primitives

Change the structure of existing code without changing behaviour.

moveRelocate code to a more appropriate place.
refactorImprove structure while preserving behaviour.
inlineFold a helper back into its caller when the indirection isn't paying.
mergeCombine two near-duplicate components into one.
decomposeSplit a too-large component into smaller, focused parts.
abstractPull out a shared abstraction over several similar pieces.
Substitute 3 primitives

Change the implementation behind a preserved surface.

replaceSwap one implementation for another, same contract (e.g. Redis → Valkey).
strangleGradually route calls from an old implementation to a new one (Strangler Fig).
wrapPut a clean facade over a messy existing surface.
Contract 2 primitives

Remove existing code or behaviour.

deprecateMark something for removal, route callers elsewhere over time.
deleteRemove dead code, unused exports, or features that no longer pay.
Reinforce 6 primitives

Add cross-cutting concerns over existing behaviour. Non-functional changes.

testAdd tests around existing behaviour for confidence before changing it.
instrumentAdd logs, traces, metrics so you can see what's happening in production.
secureClose a specific security gap (validation, authorisation, scope check).
hardenClose a class of gaps across the codebase (rate limits, idempotency).
gateAdd a pre-condition or post-condition guard around an existing path.
documentAdd the missing words around code that already does the right thing.
Conventional Commit aliases. Sulis also accepts fix, feat, chore, and other Conventional Commit prefixes as friendlier shorthands — they map to the appropriate primitive internally. So --primitive fix works as well as --primitive secure; pick whichever you're more comfortable with.

What lives inside a change

Once a change is started, the six stages — Recon, Specify, Design, Implement, Review, Ship — all happen inside it. Each stage has its own entry-point skill that Sulis runs when it arrives there. The Plugin reference page lays out every skill under its parent stage; the change is the container around all of them.

Working with multiple changes

Because each change has its own terminal, its own worktree, and its own focused Sulis session, you can have several pieces of work in flight without context-switching cost. Typical pattern:

Read next From vibe to viable — the philosophy