Safety, --force, and --dry-run
Workler's mutating commands are conservative by default: nothing that exists is ever overwritten, and every command that changes something can print its plan first.
Nothing is overwritten by default
add and apply never replace an existing destination. Two states count as already done and are reported ok:
- a symlink that already points at the right source (already linked)
- a copy whose destination content matches the source (destination matches source)
Anything else — a symlink pointing somewhere else, a regular file, a directory — is a conflict. The error shows both sides and what is currently in the way:
cannot link node_modules: destination already exists
source: /path/to/project/node_modules
destination: /path/to/project/.worktrees/feature-a/node_modules (existing directory)
re-run with --force to replace the destinationConflicts are detected by content, not timestamps — a copied .env you have since edited in the workspace is a conflict, not silently "up to date".
--dry-run
Prints exactly what would be copied, linked, skipped, replaced, or conflicted — without changing anything:
$ workler apply feature-a --dry-run
dry run: nothing will be changed
ok link node_modules (already linked)
would copy .env -> .worktrees/feature-a/.env
conflict copy config/local.json
1 conflict(s); re-run with --force to replace the destination(s)For add, no clone is created; the whole plan — clone, branch, rules — is printed instead:
$ workler add feature-b --dry-run
cloning /path/to/project
to /path/to/project/.worktrees/feature-b
create branch feature-b from HEAD
would link node_modules -> .worktrees/feature-b/node_modules
would copy .env -> .worktrees/feature-b/.env--force
Replaces conflicting destinations, and says what it replaced:
copied .env (replaced existing file)--force also appears on workler remove, where it means something different: remove the workspace even though it has uncommitted changes.
The same caution everywhere else
The safety-first stance runs through the whole CLI:
workler removerefuses to delete a workspace with any local changes — untracked files included, since deletion is permanent.workler synconly ever fast-forwards; dirty workspaces and diverged branches are skipped, never merged or rebased.workler branch-syncnever moves a checked-out branch or one with local-only commits.- Untracked files created by copy rules never count as "dirty" for
statusandsync. Onlyremovetreats them as blocking — it is the one command that would delete them.