# Claude Code and Supabase Worktrees: Give Every Agent Its Own Local Database

> Source: <https://pub.towardsai.net/claude-code-and-supabase-worktrees-give-every-agent-its-own-local-database-8b9809c1ea7a?source=rss----98111c9905da---4>
> Published: 2026-10-20 23:01:03+00:00

Two Claude Code agents can work in separate Git worktrees and still break each other’s tests. If both apps connect to the same local database, one agent’s reset can erase the other’s test data.

The fix is to give each worktree its own local Supabase project, then prove that the application and tests actually use it. This guide walks through the setup, the traps around ports and named stacks, and a simple isolation test you can run before trusting parallel migrations.

It is for developers using Claude Code with a Supabase-backed app. The same setup can help with Codex or another coding agent, because the important boundary is the local project, not the agent’s name.

A Git worktree gives a branch its own directory and working files. It does not automatically create a new Postgres server, allocate a separate application port, or change a copied environment variable. Two checkouts can look independent while sending requests to the same database.

Imagine one agent adding billing tables while another changes sign-in. Both run the app. Both load the same old .env.local. The billing agent resets its local database to test a migration, and the sign-in agent suddenly loses its fixture users. A failing test may look like an auth bug even though the code is fine.

Developers have raised this exact problem in [worktree testing discussions](https://www.reddit.com/r/ClaudeCode/comments/1wyc4g4/git_worktrees_solved_our_parallelagent_file/): a healthy API can still be the wrong API. Separate folders solve file collisions; they do not prove which process or data your test reaches.

Supabase now offers an experimental local stack system that assigns separate project identities, ports, database data, and Storage data. The [official guide](https://supabase.com/docs/guides/local-development/running-multiple-local-projects) explains the setup. The feature is experimental, so pin and check your CLI version and re-read the current docs before adopting it across a team.

*A successful start is not proof of isolation. The useful proof is that each app reaches its intended project and changes in one database do not appear in the other.*

In the experimental stack system, Supabase identifies a local project using its project root, Git branch, and optional stack name. Separate worktree directories normally produce separate identities. Two agents in the same checkout on the same branch, however, share the default local project unless you deliberately use different named stacks.

There is a subtle monorepo wrinkle: the CLI finds the nearest project root containing supabase/config.toml. Two packages beneath the same root can share one local project. Separate package directories alone do not guarantee separate databases.

Each worktree needs its own app configuration and local data path. Local isolation alone does not block remote access.

Isolation also has limits. A local project does not automatically isolate your app server, Redis, third-party webhooks, cloud credentials, or a separately configured MCP server. Nor does it prevent a process from choosing a remote URL. Those connections need their own controls.

Use synthetic local data. A local service key can bypass normal row-level security, so it belongs on the server side and should not be exposed to a browser or committed to Git. Isolated test databases are a convenience for development, not a security sandbox for untrusted code.

Start with a repository that already contains supabase/config.toml. Check the installed Supabase CLI version. The feature requires CLI 2.119.0 or later; some behavior described in the docs needs a newer version. Pin the version in your team’s tooling so an agent cannot silently switch command behavior.

For an existing app, add the following setting under the existing [experimental] section. If that section already exists, add only the setting; a duplicate TOML section makes the config invalid.

```
[experimental]stack = true
```

Next, follow the [port-removal checklist](https://supabase.com/docs/guides/local-development/running-multiple-local-projects#remove-fixed-ports-from-configtoml). Fixed port values in the config or environment are exact requests. If both worktrees request the same port, the second stack can fail to start. Do not delete unrelated settings; review the documented port keys and any port overrides your team uses.

If you already have a fixed-port local project, stop it first and read the version-specific migration guidance. In CLI 2.121.0 or later, the documented port transition can preserve that stopped project’s data. Older versions may require a new named project or a destructive reset of the stack. Back up anything valuable before changing local state.

```
supabase --versionsupabase stack --help
```

The help should describe the experimental stack commands. Without the setting, the stack subcommand is unavailable. For a new app, Supabase documents SUPABASE_EXPERIMENTAL_STACK=1 supabase init; do not rerun initialization over an existing project just to add the setting.

Commit the reviewed config before creating the worktrees, so both branches start with the same intended settings. The experimental system stores data separately from a local project started with the default engine; turning it on does not copy the old database for you.

From a clean repository with the config committed, create one worktree per task. The example assumes your base branch is named main; change it to the branch your team actually uses.

```
git worktree add -b agent/billing ../app-billing maingit worktree add -b agent/signup ../app-signup main
```

In a terminal for each worktree, start its own local project:

```
cd ../app-billingsupabase startsupabase status
```

In a second terminal:

```
cd ../app-signupsupabase startsupabase status
```

Compare the project details shown by each status command. The database and API endpoints should differ. Keep both terminals associated with their own directories when running later commands; the current directory is part of how the CLI finds the project.

Supabase recommends the container runtime for several simultaneous local projects. It uses Docker or Podman to give each project its own network namespace and filesystem. The native runtime runs processes on the host and is useful where a container engine is unavailable, including supported CI or agent sandboxes. The supported platforms and requirements are listed in the [runtime documentation](https://supabase.com/docs/guides/local-development/running-multiple-local-projects#choose-a-runtime).

Both are useful choices, but neither turns an agent with broad host access into an untrusted-code sandbox. If your threat model includes hostile code or production credentials, apply separate host, network, and credential controls.

This is where many setups quietly fail. A new worktree usually does not contain ignored files. Copying the main checkout’s entire environment file can bring back the shared database URL — or a remote project credential.

Get the endpoints from the local project in the current worktree. The experimental CLI can expose machine-readable status and lets you rename output variables:

```
supabase status --env --override-name \  API_URL=NEXT_PUBLIC_SUPABASE_URL,ANON_KEY=NEXT_PUBLIC_SUPABASE_ANON_KEY
```

The status output can include sensitive local keys and database credentials. Treat it like a secret: do not paste it into a public issue, chat, CI log, or article screenshot. For a browser app, copy only the local API URL and the intended publishable or anon key into that worktree’s ignored local configuration. Keep service-role and secret keys out of browser-exposed variables.

Framework names differ. The example above uses common Next.js names; adapt them to your app. Server-side database clients, background workers, and test runners may use different variables. Check every path that can write data, not just the frontend.

Before integration tests, have the launcher compare the app’s configured URL with the URL returned for the current stack. Require a local address and an exact match; abort if either value is missing or different. This example checks an already-loaded app variable against an explicitly supplied expected local URL:

``` python
python3 - <<'PY'import osfrom urllib.parse import urlsplit
actual = os.environ.get("APP_SUPABASE_URL", "")expected = os.environ.get("EXPECTED_LOCAL_SUPABASE_URL", "")local_hosts = {"localhost", "127.0.0.1", "::1"}
if not actual or not expected or actual != expected:    raise SystemExit("Stop: app URL does not match the expected stack")url = urlsplit(actual)if url.scheme not in {"http", "https"} or url.hostname not in local_hosts:    raise SystemExit("Stop: expected a loopback API URL")if url.username or url.password or url.query or url.fragment:    raise SystemExit("Stop: unexpected URL fields")print("Local API endpoint matches the expected stack")PY
```

Populate EXPECTED_LOCAL_SUPABASE_URL from the current worktree’s trusted CLI status, not from the application variable you are trying to check. Load APP_SUPABASE_URL from the same configuration your app actually uses. In containerized setups, loopback may not be the correct host from inside a container; use a reviewed environment-specific allowlist rather than weakening the check blindly.

This snippet checks an API URL only. It does not validate database URLs, credentials, an app process that ignores the variable, or DNS and network controls. A stronger harness inspects the effective database target, confirms the running app’s build revision, and verifies access at the network boundary.

Do not stop at seeing two different port numbers. Run a small test against disposable local projects before giving agents permission to reset anything.

A marker can be a row in a disposable test table. Use a different value for each project and remove it afterward. If you share a cache, queue, object store, email catcher, or external webhook, test those boundaries separately. A database-only check will not discover a shared worker consuming another task’s jobs.

When a check fails, pause both agents. Inspect the effective app environment, status output, project root, branch, and fixed ports. Do not keep rerunning resets until the symptom disappears; that can erase useful evidence.

Give each agent a clear assignment. The billing agent may create a migration for invoice data; the sign-in agent may change auth-related tables. Each tests against its own project using the migrations and synthetic seed data present in its worktree.

Independent green tests do not guarantee the migrations work together. One branch may rename a column the other expects, or both may introduce incompatible changes. After integrating the first branch, update the second against the new base and run the relevant checks on a clean combined database.

Parallel testing is useful; the combined migrations still need a fresh check.

Keep the review simple: inspect migration order, destructive statements, data backfills, application compatibility, and row-level security. Check that a fresh environment can apply the full sequence and that an upgrade from the previous schema works with representative synthetic data. A migration that works only on one developer’s existing database is not ready.

Separate local projects do not authorize remote changes. Supabase notes that commands such as db push, db pull, and db dump target the linked project unless the documented local option is used. Treat remote operations and --linked targets as a separate, reviewed deployment workflow. Do not hand production tokens to agents that only need local tests.

Named stacks can separate a dev and test project within the same app directory:

```
supabase start --stack devsupabase start --stack testsupabase status --stack test
```

Here is the easy mistake: database and migration commands do not accept --stack in the documented workflow. When they operate locally, they use the current branch’s default local project. Starting a stack named test does not make a later plain supabase db reset target that named stack.

For a command that supports --db-url, the documentation directs you to obtain the named stack’s database URL from its status and pass it explicitly. Verify the exact command and its flags on your pinned version. If a command has no safe explicit target, use a separate worktree with its own default project or redesign the test instead of guessing.

Named stacks under one project root can also share project files such as SQL snippets. They separate local service data, not every file in the checkout.

A good task brief tells the agent where it may work and how to prove the result. It should describe the constraints in plain language, but the environment should enforce them where possible.

```
Task: implement billing migration and tests.Worktree: app-billing; use only its default local stack.Data: synthetic fixtures only; no cloud credentials.Allowed: edit migration files and run approved local tests.Before reset: verify the current local project and target.Do not: link, push, deploy, or modify remote databases.Deliver: diff, migration order, test results, and open risks.
```

Replace “approved local tests” with actual commands your team has reviewed. The agent should report what ran and what did not. If the database could not start, a clean diff is still useful, but it is not a tested migration.

Use permissions, network restrictions, and short-lived credentials to support the brief. Instructions alone cannot stop a process that already has unrestricted access. If a task needs a remote staging project, grant that access as a separate decision with a clear owner and explicit target.

When a task ends, check the worktree for uncommitted work, capture the test results, and stop its local project from that worktree:

```
supabase stop
```

Stopping keeps the local project’s data and ports. Destroying a stack deletes its database data without a backup, although the docs describe some retained upload files and container cleanup cases. Before destroying anything, identify the project, save needed data, and read the current [cleanup guidance](https://supabase.com/docs/guides/local-development/running-multiple-local-projects#stop-and-destroy-local-projects). Avoid automatic machine-wide cleanup in a shared development environment.

Finally, remove the worktree only after its owner has reviewed or saved the work. Track which worktree owns each local project, app process, and test fixture. A small private run record can save hours when a later test points at an old service.

For a single isolated test with no need for Auth, Storage, or Supabase APIs, a plain disposable Postgres instance may be simpler. If you need the full Supabase behavior, separate local projects offer a closer development environment. For a shared review environment, a hosted branch may be useful, but it has different costs, data rules, and access boundaries.

Choose based on what the test must prove. A unit test should not start a full local stack just because an agent is available. A database migration test should not claim to validate Auth or Storage unless those services were actually exercised.

The biggest practical win is not “more agents.” It is knowing which code, process, and data produced a result. Once that path is clear, parallel work becomes easier to review — and failures become much easier to explain.

Not by itself. A worktree separates checked-out files. You must start and configure a separate local project or use another deliberate database-isolation method.

Yes, named experimental stacks can create separate local projects in one checkout. Check command-target limitations carefully: database and migration commands do not automatically follow a named stack.

A fixed config port or environment override may be requesting a port already in use. Follow the official port-removal checklist and inspect your app’s own server ports too.

Yes, the experimental native runtime works on supported macOS and Linux platforms. Supabase recommends containers for several projects on one machine; verify current platform requirements before choosing.

It separates local project data, but it does not remove remote credentials or block commands aimed at a linked project. Restrict credentials, network access, and remote operations independently.

No. Each should test its own change, and the combined migration sequence should be tested again after integration against a clean environment and a representative upgrade path.

Stopping preserves its local data and ports. Destroying it deletes database data, so identify the target and preserve anything needed before cleanup.

[Claude Code and Supabase Worktrees: Give Every Agent Its Own Local Database](https://pub.towardsai.net/claude-code-and-supabase-worktrees-give-every-agent-its-own-local-database-8b9809c1ea7a) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.
