| name | gitbutler-get-fresh-workspace |
|---|---|
| description | Use when starting new work in a GitButler repo and you want the workspace cleared and synced to origin/main. Triggers include "fresh workspace", "start fresh", "clean up workspace", "sync to main", "reset to main", or starting a new bead or feature on a stale workspace. |
Bring a GitButler workspace to a clean state: nothing applied except branches with active WIP, no floating uncommitted changes, target advanced to latest origin/main.
Core principle: every piece of workspace state must have a disposition before syncing. Applied branches that are merged or submitted as PRs are "done" — clear them locally. Anything else (local commits with no PR, unassigned changes) requires the user.
- Starting a new bead/feature and want a clean base
- After merging PRs, to drop stale applied branches
- User says: "start fresh", "clean up my workspace", "sync to main", "reset to main"
Do NOT use when:
- Mid-conflict resolution
- Not a GitButler-managed repo (check
but statussucceeds)
Read but status --json and classify each item:
| State | Signal | Action |
|---|---|---|
| Applied branch, merged to main | branchStatus == "integrated" |
Auto-unapply |
| Applied branch with open PR | reviewId != null |
Auto-unapply |
| Applied branch, local commits, no PR, not integrated | neither above | STOP — ask user |
| Empty branch | no commits, no changes | handled by but clean |
| Unassigned changes (floating code) | unassignedChanges non-empty |
STOP — ask user |
| Conflicted commits | conflicted: true on any commit |
STOP — resolve first |
Never guess a disposition for the stop-and-ask cases. The user's in-flight work and loose files are theirs to direct.
-
Survey. Run
but status -fvfor the human view, and capturebut status --jsonfor programmatic inspection. -
Scan for stop-and-ask triggers. If any apply, STOP and ask the user before touching anything. Show branch names, commit counts, and the floating-file list. Offer concrete options (commit+push+PR, leave applied and skip sync, or explicit discard with confirmation).
-
Unapply done branches. For each branch with
branchStatus == "integrated"OR a non-nullreviewId:but unapply <branch-name> --status-afterUse the branch name from the JSON (not the CLI ID — names are stable across refreshes).
-
Sync to origin/main.
but pull --check but pull --status-afterIf
--checkreports issues, STOP and ask the user. -
Remove empty branches.
but clean --status-after -
Verify. Final
but status -fvmust show:- No
unassignedChanges - Only branches with active WIP still applied (or none)
- Target at latest origin/main HEAD
- No
Report the final state back to the user with a one-line summary: "Clean workspace, target at origin/main@, N branches still applied: [...]".
Write scratch files to ./tmp/ (project-local), never /tmp — many users restrict /tmp access.
Never chain commands with &&, ;, or | in this workflow. Each chained step requires a separate permission approval from the user; running them as individual Bash calls is faster and less noisy than approving a compound command. One command per call.
# Step A — set up scratch dir (one call)
mkdir -p ./tmp
# Step B — capture state (one call)
but status --json > ./tmp/bstate.json
# Step C — classify (one call)
jq '{unassigned_count: (.unassignedChanges | length), branches: [.stacks[].branches[] | {name, branchStatus, reviewId}]}' ./tmp/bstate.json
# Step D — for each done branch, one unapply per call
but unapply old-merged-feature --status-after
but unapply branch-with-open-pr --status-after
# Step E — pull in two calls (check first, then pull)
but pull --check
but pull --status-after
# Step F — sweep empties
but clean --status-after
# Step G — verify
but status -fv- Using
git fetch/git pull/git checkout main. Forbidden — usebut pull. See the gitbutler skill. - Auto-unapplying a branch with local unpushed commits and no PR. Those commits exist only on the branch; unapplying keeps them but the user may lose track. Always ask.
- Discarding unassigned changes without asking. Floating files are often in-progress work, screenshots, or plans. Always ask.
- Skipping
but pull --check. Runningbut pullon a conflicted state makes a mess. - Using CLI IDs instead of branch names for
unapply. CLI IDs can shift betweenbut statuscalls; branch names don't. - Chaining commands with
&&/;/|. Each chained segment costs a separate permission prompt. Run each step as its own Bash call instead.
- gitbutler skill — base commands, workspace model, stacking/move recipes
but clean --help— flags for handling upstream-only branchesbut unapply --help— branch removal from workspace (keeps branch, drops from applied set)