Parallel agent work runs into the file system, not the model. Two agents in one working directory inevitably step on each other's edits, and no amount of careful wording cures that: they read a file, think about it for a few seconds and write the result back, unaware that the file changed in the meantime. A git worktree solves the problem physically: a separate checkout with its own files, its own branch and its own dependencies. That is why parallelism starts with trees rather than with the number of open chats.
The naive scheme is to launch two agents in one folder and hope they will divide the files. It breaks even without git conflicts: one changes a contract while the other simultaneously adapts to the old version, and the result is a semantic conflict the version control system will not see. Formally everything merged, in fact the behavior is broken - and untangling that costs more than separating the tasks into trees in the first place. Git compares lines, not meanings, and where two edits did not overlap textually it will honestly report success.
Cursor provides trees both through the agents window and through a set of commands in the editor: create a tree for a task, apply the result, delete the tree. A separate technique is to run the same task on several models, where each candidate works in its own tree. That is an honest way to compare approaches without mixing them: the results are visible side by side rather than layered on each other in a shared directory. The value is not that one model turns out to be better in general, but that on this particular task several solutions are visible at once and there is something to choose between.
An important detail about comparing candidates: the winner does not merge itself. After choosing, you have to review the changes and commit or apply the tree by hand. That is not a shortcoming but a deliberate boundary - choosing among several variants remains a human decision rather than an automatic action based on a comparison. Automation could not decide correctly here anyway: the criterion usually lies outside the code, in which approach you are prepared to maintain from now on.
It helps to see the setup of a new tree once. Below is a configuration with preparation commands for different platforms. Cursor reads it first from the tree itself, then from the project root; the value can be either an array of commands or a path to a script next to the configuration. The reading order matters: it lets a tree created for a particular task prepare itself differently from the project default without touching the shared configuration.
Isolation has a price worth recognizing in advance. Every tree is a separate set of files and a separate installation of dependencies, which means disk space and preparation time. Hence the temptation to slip the dependencies in with a symbolic link from the main directory. The official recommendation is different: use a fast package manager and honestly install them again. The reason is that a shared link brings back exactly what the tree was created to remove - shared mutable state: one agent rebuilds a package while another sees it half-updated, and the resulting failures have to be hunted somewhere other than the code.
And a separate warning: setup scripts are executable project content. They run when a tree is created, and they arrived together with the repository. So the same rule applies to them as to any other executable configuration: read first, allow second. An unfamiliar repository with a ready-made setup script is a convenience exactly until you have looked at what is inside it.
There is an operational side too. Trees accumulate, so Cursor can delete old ones by a machine-wide limit, and the default value is not large. External trees can fall under that cleanup as well. The practical conclusion: do not keep uncommitted important results in a tree you consider temporary - either commit or record the state explicitly. Automatic cleanup does not ask whether this draft is dear to you.
One question remains that trees do not answer: how to divide the work. Isolation removes file conflicts but not conflicts of decisions, so tasks are separated by ownership - one agent owns the schema migration, another owns the screen that consumes that schema, and neither touches the other's boundary. The sign that ownership was divided badly has a characteristic look: in each tree separately the tests are green, and after merging both branches they fail. That is a semantic conflict in its pure form, and the cure is not another merge but a decision about whose version of the contract is authoritative.
The typical failures of parallel work are predictable. Letting two agents onto one contract and getting a semantic conflict without a git conflict. Expecting the winner of a comparison to merge itself. Replacing dependency installation with a symbolic link and getting strange build failures. Allowing someone else's setup script to run without reading it. And leaving uncommitted work in a tree that automatic cleanup will remove.
/worktree fix the failing auth tests and update the login copy
/best-of-n sonnet,gpt,composer fix the flaky logout test
# candidates run in separate trees; merging the winner is a manual decision// .cursor/worktrees.json - preparing a new tree
{
"setup-worktree-unix": ["pnpm install", "pnpm run build"],
"setup-worktree-windows": ["pnpm install", "pnpm run build"]
}
// read first from the tree, then from the project root; this is executable content - read it first