283 lines
11 KiB
TypeScript
283 lines
11 KiB
TypeScript
import { createFileRoute } from '@tanstack/react-router'
|
|
|
|
export const Route = createFileRoute('/docs/worktrees')({
|
|
head: () => ({
|
|
meta: [
|
|
{ title: 'Git Worktrees - Paseo Docs' },
|
|
{
|
|
name: 'description',
|
|
content: 'Run agents in isolated git worktrees for parallel feature development.',
|
|
},
|
|
],
|
|
}),
|
|
component: Worktrees,
|
|
})
|
|
|
|
function Code({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<div className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto">
|
|
{children}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function Worktrees() {
|
|
return (
|
|
<div className="space-y-10">
|
|
<div>
|
|
<h1 className="text-3xl font-medium font-title mb-4">Git Worktrees</h1>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Git worktrees let you have multiple working directories from the same repository.
|
|
Paseo uses them to run agents in isolated branches without switching contexts.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Why worktrees */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Why worktrees?</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Without worktrees, running multiple agents on the same repo means they share the
|
|
working directory. One agent's changes interfere with another's. You can't safely
|
|
run parallel tasks.
|
|
</p>
|
|
<p className="text-white/60 leading-relaxed">
|
|
With worktrees, each agent gets its own directory and branch. They can work
|
|
simultaneously without conflict. When an agent finishes, you review the diff,
|
|
merge the branch, and archive the worktree.
|
|
</p>
|
|
</section>
|
|
|
|
{/* Directory structure */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Directory structure</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Paseo creates worktrees under <code className="font-mono">$PASEO_HOME/worktrees/</code>,
|
|
organized by a short hash of the source checkout path:
|
|
</p>
|
|
<Code>
|
|
<pre className="text-white/80">{`~/.paseo/worktrees/
|
|
├── 1vnnm9k3/
|
|
│ ├── tidy-fox/ # random slug
|
|
│ └── bold-owl/ # random slug
|
|
└── 4k8q2d1p/
|
|
└── swift-hare/ # random slug`}</pre>
|
|
</Code>
|
|
<p className="text-white/60 leading-relaxed">
|
|
The hash avoids collisions between repositories that share the same directory or
|
|
remote name. Worktree directory names are random slugs — the branch name is
|
|
separate and chosen when you first launch an agent in the worktree.
|
|
</p>
|
|
</section>
|
|
|
|
{/* Branches */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Branches</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
When you create a worktree, Paseo generates a random directory name. The branch name
|
|
is set when you first launch an agent — Paseo generates one automatically.
|
|
</p>
|
|
<p className="text-white/60 leading-relaxed">
|
|
This means the worktree directory and branch are independent. You can rename the
|
|
branch later without affecting the worktree path.
|
|
</p>
|
|
</section>
|
|
|
|
{/* Multiple agents */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Multiple agents per worktree</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
You can launch multiple agents into the same worktree. They share the working
|
|
directory and branch, which is useful when you want agents to collaborate on
|
|
the same feature or when one agent hands off to another.
|
|
</p>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Be mindful of conflicts — agents working on the same files simultaneously can
|
|
step on each other. This works best when agents have distinct responsibilities
|
|
or run sequentially.
|
|
</p>
|
|
</section>
|
|
|
|
{/* paseo.json */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Setup with paseo.json</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
When Paseo creates a worktree, it's a fresh checkout. Dependencies aren't installed,
|
|
config files aren't copied. You can automate setup by creating a{' '}
|
|
<code className="font-mono">paseo.json</code> file in your repository root:
|
|
</p>
|
|
<Code>
|
|
<pre className="text-white/80">{`{
|
|
"worktree": {
|
|
"setup": [
|
|
"npm ci",
|
|
"cp \\"$PASEO_SOURCE_CHECKOUT_PATH/.env\\" \\"$PASEO_WORKTREE_PATH/.env\\""
|
|
]
|
|
}
|
|
}`}</pre>
|
|
</Code>
|
|
<p className="text-white/60 leading-relaxed">
|
|
The <code className="font-mono">setup</code> array contains shell commands that run
|
|
after the worktree is created. Use it to install dependencies, copy local config
|
|
files, or run any other initialization.
|
|
</p>
|
|
<div className="bg-yellow-500/10 border border-yellow-500/30 rounded-lg p-4 text-white/80">
|
|
<strong>Important:</strong> Setup commands come from{' '}
|
|
<code className="font-mono">paseo.json</code> in the selected base branch. If you pick{' '}
|
|
<code className="font-mono">main</code>, Paseo reads the committed file on{' '}
|
|
<code className="font-mono">main</code>. Local or uncommitted changes in another branch
|
|
are not used for that worktree.
|
|
</div>
|
|
</section>
|
|
|
|
{/* Environment variables */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Environment variables</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Setup commands have access to these environment variables:
|
|
</p>
|
|
<ul className="text-white/60 space-y-2 list-disc list-inside">
|
|
<li>
|
|
<code className="font-mono">$PASEO_SOURCE_CHECKOUT_PATH</code> — your source checkout
|
|
path (original repository root)
|
|
</li>
|
|
<li>
|
|
<code className="font-mono">$PASEO_ROOT_PATH</code> — legacy alias of{' '}
|
|
<code className="font-mono">$PASEO_SOURCE_CHECKOUT_PATH</code>
|
|
</li>
|
|
<li>
|
|
<code className="font-mono">$PASEO_WORKTREE_PATH</code> — the new worktree directory
|
|
</li>
|
|
<li>
|
|
<code className="font-mono">$PASEO_BRANCH_NAME</code> — the branch name created
|
|
</li>
|
|
<li>
|
|
<code className="font-mono">$PASEO_WORKTREE_PORT</code> — an available local port for setup scripts
|
|
</li>
|
|
</ul>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Use <code className="font-mono">$PASEO_SOURCE_CHECKOUT_PATH</code> to copy files that
|
|
shouldn't be in git (like <code className="font-mono">.env</code>) from your source
|
|
checkout to the worktree.
|
|
</p>
|
|
</section>
|
|
|
|
{/* Common patterns */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Common patterns</h2>
|
|
|
|
<h3 className="text-lg font-medium mt-6">Node.js / npm</h3>
|
|
<Code>
|
|
<pre className="text-white/80">{`{
|
|
"worktree": {
|
|
"setup": ["npm ci"]
|
|
}
|
|
}`}</pre>
|
|
</Code>
|
|
|
|
<h3 className="text-lg font-medium mt-6">Python / Poetry</h3>
|
|
<Code>
|
|
<pre className="text-white/80">{`{
|
|
"worktree": {
|
|
"setup": ["poetry install"]
|
|
}
|
|
}`}</pre>
|
|
</Code>
|
|
|
|
<h3 className="text-lg font-medium mt-6">Copy environment files</h3>
|
|
<Code>
|
|
<pre className="text-white/80">{`{
|
|
"worktree": {
|
|
"setup": [
|
|
"npm ci",
|
|
"cp \\"$PASEO_SOURCE_CHECKOUT_PATH/.env\\" \\"$PASEO_WORKTREE_PATH/.env\\"",
|
|
"cp \\"$PASEO_SOURCE_CHECKOUT_PATH/.env.local\\" \\"$PASEO_WORKTREE_PATH/.env.local\\""
|
|
]
|
|
}
|
|
}`}</pre>
|
|
</Code>
|
|
|
|
<h3 className="text-lg font-medium mt-6">Run database migrations</h3>
|
|
<Code>
|
|
<pre className="text-white/80">{`{
|
|
"worktree": {
|
|
"setup": [
|
|
"npm ci",
|
|
"cp \\"$PASEO_SOURCE_CHECKOUT_PATH/.env\\" \\"$PASEO_WORKTREE_PATH/.env\\"",
|
|
"npm run db:migrate"
|
|
]
|
|
}
|
|
}`}</pre>
|
|
</Code>
|
|
</section>
|
|
|
|
{/* Workflow */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Workflow</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
The typical workflow is:
|
|
</p>
|
|
<ol className="text-white/60 space-y-2 list-decimal list-inside">
|
|
<li>
|
|
Create a worktree — Paseo creates the directory and runs setup
|
|
</li>
|
|
<li>
|
|
Launch an agent — Paseo creates or assigns a branch
|
|
</li>
|
|
<li>
|
|
Agent works in isolation — changes stay in its worktree
|
|
</li>
|
|
<li>
|
|
Review the diff — compare against the base branch
|
|
</li>
|
|
<li>
|
|
Merge or discard — if approved, merge the branch; otherwise archive
|
|
</li>
|
|
<li>
|
|
Archive the worktree — cleans up the directory and optionally the branch
|
|
</li>
|
|
</ol>
|
|
<p className="text-white/60 leading-relaxed">
|
|
You can run multiple agents in different worktrees simultaneously. Each worktree
|
|
has its own branch and working directory.
|
|
</p>
|
|
</section>
|
|
|
|
{/* CLI reference */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">CLI reference</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Create an agent in a new worktree:
|
|
</p>
|
|
<Code>
|
|
<pre className="text-white/80">{`paseo run --worktree feature-auth --base main "implement auth"`}</pre>
|
|
</Code>
|
|
<p className="text-white/60 leading-relaxed">
|
|
List all worktrees:
|
|
</p>
|
|
<Code>
|
|
<pre className="text-white/80">{`paseo worktree ls`}</pre>
|
|
</Code>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Archive a worktree (stops agents, removes directory):
|
|
</p>
|
|
<Code>
|
|
<pre className="text-white/80">{`paseo worktree archive feature-auth`}</pre>
|
|
</Code>
|
|
</section>
|
|
|
|
{/* Metadata */}
|
|
<section className="space-y-4">
|
|
<h2 className="text-xl font-medium">Metadata</h2>
|
|
<p className="text-white/60 leading-relaxed">
|
|
Paseo stores metadata in each worktree's git directory to track the base branch.
|
|
This is used for diff operations and to know what branch to merge into.
|
|
</p>
|
|
<p className="text-white/60 leading-relaxed">
|
|
You don't need to manage this manually — Paseo handles it when creating and
|
|
archiving worktrees.
|
|
</p>
|
|
</section>
|
|
</div>
|
|
)
|
|
}
|