How to Set Up Agent Worktrees Without Port or Database Collisions
A new Git worktree isolates repository files, not the environment around them. To run several coding agents reliably, each checkout needs repeatable dependencies, the right ignored configuration, a unique port, and an explicit policy for databases and other mutable services.

Agentastic runs .agentastic/setup.sh whenever it creates a worktree. This guide builds a safe baseline you can adapt to your stack.
The environment contract#
For every new workspace, answer these questions before the agent starts:
- How are dependencies installed?
- Which ignored files are copied, generated, or fetched?
- Which ports belong to this worktree?
- Does it get a database, schema, container, or serialized test lane?
- Which generated artifacts must be refreshed?
- How can a human rerun and debug setup?
If the answer exists only in a developer's memory, agents will improvise.
Start with an idempotent setup script#
Create .agentastic/setup.sh in the repository and make it executable:
mkdir -p .agentastic
touch .agentastic/setup.sh
chmod +x .agentastic/setup.shAgentastic supplies these useful values:
| Variable | Meaning |
|---|---|
AGENTASTIC_BRANCH | New worktree branch |
AGENTASTIC_BASE_BRANCH | Selected base branch |
AGENTASTIC_WORKTREE_PATH | Absolute path to the new checkout |
AGENTASTIC_MAIN_REPO_PATH | Absolute path to the original repository |
AGENTASTIC_COMMIT | Starting commit |
AGENTASTIC_REPO_NAME | Repository folder name |
The script runs from the new worktree. Agentastic shows its output in the setup task and lets you rerun it.
A practical Node.js example#
#!/usr/bin/env bash
set -euo pipefail
echo "Preparing $AGENTASTIC_REPO_NAME on $AGENTASTIC_BRANCH"
# 1. Copy only the ignored local files this project actually needs.
for file in .env .env.local; do
source_file="$AGENTASTIC_MAIN_REPO_PATH/$file"
if [ -f "$source_file" ] && [ ! -f "$file" ]; then
cp "$source_file" "$file"
echo "Copied $file"
fi
done
# 2. Install from the committed lockfile.
if [ -f pnpm-lock.yaml ]; then
pnpm install --frozen-lockfile
elif [ -f package-lock.json ]; then
npm ci
elif [ -f yarn.lock ]; then
yarn install --frozen-lockfile
fi
# 3. Allocate a stable local port from a dedicated range.
branch_checksum=$(printf '%s' "$AGENTASTIC_BRANCH" | cksum | awk '{print $1}')
app_port=$((4100 + branch_checksum % 700))
cat > .env.agentastic.local <<EOF
AGENTASTIC_WORKTREE=1
APP_PORT=$app_port
EOF
echo "APP_PORT=$app_port"
# 4. Generate code only after dependencies and environment exist.
if npm run | grep -q 'generate'; then
npm run generate
fi
echo "Setup complete"The port range is an example, not a universal standard. Reserve a range that does not overlap with normal local services, CI, or other repositories. Your run script must actually read the generated value.
Handle environment files deliberately#
Do not recursively copy every .env* file from the main repository. That can pull production credentials, stale overrides, or files belonging to another package into the worktree.
Prefer one of these patterns:
- Copy an explicit allowlist of development-only files.
- Generate
.envfrom a committed.env.exampleand fetch secrets from your normal secret manager. - Write worktree-specific values to a separate ignored file such as
.env.agentastic.local. - Use container environment configuration for sensitive or highly isolated tasks.
Never commit the copied result. Add generated local files to .gitignore.
Choose a database strategy#
Relative SQLite databases#
If the database file lives inside the repository directory and is ignored, each worktree naturally gets a separate path. Confirm the application does not resolve it back to one global directory.
One Postgres database per worktree#
Create a safe database identifier from the branch name:
safe_branch=$(printf '%s' "$AGENTASTIC_BRANCH" \
| tr '[:upper:]' '[:lower:]' \
| tr -c 'a-z0-9_' '_' \
| cut -c1-40)
database_name="${AGENTASTIC_REPO_NAME}_${safe_branch}"
echo "DATABASE_NAME=$database_name" >> .env.agentastic.localDatabase creation needs credentials and permissions. Keep those operations in a trusted local script or development service rather than granting every agent unrestricted administrative access.
One schema per worktree#
A schema is lighter than a full database, but only if the application and migrations consistently respect the search path. Test cleanup and cross-schema extensions before adopting it.
One container stack per worktree#
For stateful applications, a container-backed Agentastic workspace is often simpler. Give the task its own application process and database service, then remove the runtime when the workspace is discarded.
Serialize shared-state tasks#
Some systems cannot cheaply duplicate their dependencies. In that case, run only one migration or integration-test task at a time. Honest serialization is safer than pretending shared mutable state is isolated.
Prevent package and build-cache surprises#
Each worktree should have its own repository-local dependency directory unless your package manager provides a concurrency-safe global store. Avoid symlinking one live node_modules directory between checkouts.
Use committed lockfiles and deterministic install commands:
npm cipnpm install --frozen-lockfileyarn install --frozen-lockfileuv sync --frozen- a new Python virtual environment per worktree
Shared download caches are usually fine. Shared mutable build output is not.
Make setup observable#
Setup failures should be obvious before the coding agent begins reasoning about application code.
Use:
set -euo pipefail
echo "Step 1/4: copying local config"
echo "Step 2/4: installing dependencies"
echo "Step 3/4: generating clients"
echo "Step 4/4: preparing services"Validate syntax locally:
bash -n .agentastic/setup.shTest with explicit values in a disposable checkout. Do not use /tmp/test if the script can delete or migrate resources without a unique namespace.
Keep setup fast#
A perfect ten-minute bootstrap encourages people to bypass it. Improve the feedback loop:
- Use package-manager stores and lockfile installs.
- Build base container images with slow system dependencies already present.
- Generate only what the task needs.
- Keep databases as small development fixtures.
- Move optional checks out of workspace creation and into a validation task.
Cleanup is part of the design#
Before removing a worktree:
- Stop its local processes.
- Remove its database, schema, or container if the data is disposable.
- Preserve logs or fixtures only when they matter to the pull request.
- Remove or archive the Agentastic workspace.
- Run
git worktree pruneonly for stale Git metadata, not as a substitute for intentional cleanup.
Agentastic automatically removes the runtime for container-backed workspaces. Local services started by project scripts still need a project-specific shutdown path.
A good setup script is product infrastructure#
Every agent benefits from the same reproducible environment: Claude Code, Codex, Gemini, Cursor, review agents, and your own terminal. Treat setup as part of the repository, test it, and improve it whenever a workspace fails for an environmental reason.
Download Agentastic for macOS or read the complete Setup & Teardown Scripts documentation.