12. Advanced workflows
The basics get you a good conversation. This page is about the things that make a long one hold together: exploring more than one approach, keeping context clean over hours, and not losing work when an approach turns out to be wrong.
Branching: exploring more than one answer
The core insight is that a conversation is a tree, not a line. You asked for something, the model did it, and now you want to know what a different approach would have looked like โ without throwing away the one you have.
/tree # where am I, and what can I fork from?
/fork 3 # rewind to just before my 3rd prompt, go a different way
/clone # freeze this branch, continue on a copy
/fork โ try a
different prompt
/fork n rewinds the live transcript to just before your
n-th real prompt. That prompt and everything the model did
after it stay in the tree as a sibling branch, still listed in
/tree and still reachable.
Use it when the prompt was wrong. You asked for a caching layer, got one, and realised the real problem was the query. Fork back to before you asked, ask the better question, and the caching detour is preserved rather than argued with.
Fork points are your real prompts โ tool results do not
count โ so /fork 2 means "the second thing I actually
asked."
/clone โ try a
different continuation
/clone duplicates the current branch and makes the copy
live, freezing the original exactly where it stands.
Use it when the conversation is good and the next step is
risky. You have twenty turns of hard-won context about a
subsystem and you are about to ask for a refactor that might go badly.
Clone first: if it goes badly, /tree still shows the branch
where it had not happened yet.
Fork, clone, or checkpoint?
All three let you go back. They differ in what "back" means:
| Rewinds to | Keeps the discarded work | Survives compaction | Persisted | |
|---|---|---|---|---|
/fork n |
before one of your prompts | yes, as a sibling branch | yes | yes, in the session file |
/clone |
nowhere โ copies forward | yes, the frozen original | yes | yes |
/checkpoint + /rollback |
a point you marked | yes, as pre-rollback |
yes, exactly | no, in-memory only |
The practical split: checkpoints are for undo, branches are for comparison. A checkpoint is the thing you take before a risky operation and forget about if it went fine. A branch is the thing you keep because you genuinely want both versions available.
Checkpoints are also dropped by /new,
/switch, and /resume; branches are written
into the session file and come back with it.
Why branching is cheap
Both operations are shaped so the model does not have to re-read the conversation. A fork leaves the transcript a strict prefix of what it was; a clone leaves it byte-identical. Nothing about the engine's cached state is copied or reinterpreted โ the next turn reconciles the prompt against what is already loaded and only pays for what genuinely differs.
Practically: forking back ten turns is not a ten-turn penalty. Cloning is nearly free.
A worked pattern
โฆ fifteen turns establishing how the scheduler works โฆ
/checkpoint understood (cheap insurance)
/clone (freeze the understanding)
"rewrite the scheduler to be lock-free"
โฆ it goes badly โฆ
/tree (the frozen branch is right there)
/fork 16 (back to just after the understanding)
"what would it take to make the existing scheduler lock-free?
don't write anything yet"
You now have two branches from the same fifteen turns of context: one that tried it, one that scoped it first. Neither cost you the understanding.
Keeping a long session sharp
Delegate the detours
The single biggest cause of a session going vague is a research detour eating the context. Hand those to a subagent:
/subagent find every place we assume the config is loaded before the logger,
and report the ones that would break if that changed
The subagent does the reading in its own scoped context and only its
final report enters your transcript. Twenty file reads
become one paragraph. The model does the same thing on its own with the
agent tool when it recognises a bounded chore.
If you fan several subagents out over work that touches the same
files, give them worktrees โ isolation: worktree in the
definition, or worktree.isolateAgents for all of them.
Otherwise two agents editing one file is a race, and the loser's work is
simply gone. A subagent that leaves changes in its worktree keeps it,
and reports the path back so you can merge.
Ask sideways with /btw
/btw what's the difference between Arc<Mutex<T>> and RwLock again?
The running generation genuinely suspends, answers in a split panel, and resumes byte-for-byte โ and nothing is written to the conversation. Use it for the question you would otherwise open a browser for. The main task does not learn that you asked.
Esc at an idle prompt dismisses a panel left open from
an earlier turn.
Compact deliberately
Do not wait for the automatic pass to fire in the middle of something delicate. Before handing the model a large new job:
/context # see what is actually taking up room
/compact # rebuild: summary + recent tail + recently read files
When you already know what the next stretch of work needs, say so and the summary will keep it:
/compact keep the failing test cases verbatim
A /checkpoint taken beforehand makes even that
reversible โ a checkpoint stores the whole transcript, so
/rollback reconstructs the pre-compaction conversation
exactly.
Give it a plan that survives
Ask the model to keep a task list. The task tool's list
survives compaction by design, so a long job does not lose its plan when
the transcript is summarized. /tasks shows it and the
status bar counts it.
Write down what it cannot re-derive
/remember the integration tests need DOCKER_HOST set; CI sets it, local shells don't
Anything the model would otherwise rediscover โ or worse, get wrong
the same way twice โ belongs in memory or AGENTS.md.
Anything it can read out of the repository does not; that is context you
pay for twice.
Working carefully
Plan before editing
For anything risky or ambiguous, ask for a plan first:
plan this out before you touch anything
The model enters read-only plan mode, where every mutating tool is refused until it proposes a plan and you approve it. Rejecting the plan keeps the gate on, so you can iterate on the approach with no risk of an edit landing mid-discussion.
Isolate the edit instead of holding it back
Plan mode stops the model from editing. A worktree lets it edit somewhere else. When the change is large or speculative and you would rather see it finished than approve it up front, ask for a worktree:
in a worktree called big-refactor, split this module in two and make the tests pass
The model works in a second checkout on its own branch, under
.plank/worktrees/big-refactor. Your files never move, so
you can keep reading, editing, and running things in the main tree while
it goes. When it finishes it leaves the worktree in place and tells you
where: review the branch, merge it, or delete it, the same as any other
branch.
The safety property worth knowing is what happens on the way out. If the model tries to delete a worktree that still holds uncommitted files or commits that exist nowhere else, plank refuses and names what would be lost. It refuses too when it cannot check โ a git failure is not evidence that there was nothing there. Work has to be discarded on purpose, never by accident.
For a whole session rather than one task, start in the worktree:
plank --worktree big-refactor
plank --worktree-pr 412
This is the form to reach for when you want two plank sessions on the same repository at once. Give each its own worktree and they cannot overwrite each other, which the same checkout shared between them absolutely can.
Phrasings that hold the model back
You do not have to name plan mode to get its effect. These work, and they are worth keeping in your fingers:
don't make changes, just investigate
show me, without writing anything, what a reasonable plan would look like
give it a fast review and save the findings in
docs/CODE-REVIEW.md
The last one is the general shape worth internalising: say where the output goes. A review that lands in a file survives the session; a review that lands in the transcript is gone at the next compaction.
The same applies to delegation and to style. "Use a subagent to โฆ" is
a valid instruction, not just something the model decides on its own.
And handing over a style file โ "write this using the style in
local/medium-post-style.md" โ beats describing the style in
the prompt every time.
Tighten the sandbox
The bash sandbox already limits writes to the working directory and temp. If a project needs more, name it explicitly rather than switching the sandbox off:
{ "writablePaths": ["/Users/me/.cache/my-build"] }
excludedCommands is a convenience, not a boundary โ a
command it matches runs unsandboxed.
Do the interactive things yourself
The model's bash tool cannot drive a login prompt, a
pager, or an editor. Use !:
!!gh auth login
Your command, your shell, never sandboxed. Use !! when
the output is only for you โ a login flow is noise the model does not
need โ and plain ! when you want the result recorded so the
model can act on it in your next message.
Making it repeatable
Skills for procedures
Anything you have explained twice should be a skill. A skill is both a slash command and something the model can invoke itself when the task matches:
~/.plank/skills/release/SKILL.md โ /release 2.8.0
Templates for prompt shapes
Anything you retype with small variations should be a template โ one
file, {{named}} holes:
~/.plank/templates/review.md โ /review src/parser.rs "error handling"
Hooks for policy
Anything that must happen every time belongs in a hook, not
in your memory of what to check. A PreToolUse hook exiting
2 blocks a tool and tells the model why, which is how you enforce "never
edit generated files" without repeating it every session.
{
"PreToolUse": [
{ "matcher": "edit(*/generated/*)|write(*/generated/*)",
"hooks": [ { "type": "command", "command": "echo 'generated code โ edit the template instead' >&2; exit 2" } ] }
]
}
Project settings in the repo
./.plank/settings.json is committable, and sharing it is
the point: everyone on the project gets the same context size, the same
sandbox policy, the same display defaults. Keep secrets out โ the file
is inside the working tree.
Getting more out of the hardware
/power <1..100>caps GPU draw mid-session, for when you want the laptop to stay cool or quiet.--ssd-streamingstreams experts from SSD rather than loading them resident, which is how you run a model that does not fit in RAM.--ssd-streaming-cache-expertsand--ssd-streaming-preload-expertstrade memory for latency.--mtp PATHadds a multi-token-prediction draft model, with--mtp-draftand--mtp-margintuning how aggressively drafts are accepted.plank serve+--remoteputs the work on the machine with the GPU and the typing on the machine you are sitting at. See Remote and hosted engines.
When something goes wrong
/repro
before you change anything. It captures the exact rendered prompt the engine would see plus every runtime knob โ model, backend, context size, sampling, think mode, engine tuning โ in one self-contained file, without touching the live session. That is a far better bug report than a description, and it is the only artifact that makes a generation bug reproducible after the fact.
Next: Troubleshooting โ