# Env Isolation

> Generates environment isolation configuration artefacts for per-worktree agent isolation. Produces .env files, docker-compose service overrides, and shell export scripts that assign each worktree its own port, PostgreSQL schema, SQLite database file, or container — without launching any process. Use when: (1) setting up environment variables for an isolated worktree before starting the app, (2) generating a .env file to commit alongside the worktree, (3) creating docker-compose overrides for per-agent containers, (4) scripting CI environments where each job needs its own isolated service, (5) auto-assigning a collision-free port from a pool. Triggers on: generate env config, environment isolation, worktree isolation, per-worktree env, dotenv generation, docker-compose override, port assignment, database schema isolation, isolate worktree.

- Skill: `bowen31337/env-isolation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add bowen31337/env-isolation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/bowen31337/env-isolation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: bowen31337 (https://skillmd.com/u/bowen31337)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/bowen31337/env-isolation

---


# Env Isolation Skill

## Overview

The `env-isolation` skill generates **environment isolation configuration
documents** for per-worktree agent instances.  Each worktree receives its own:

| Resource | Strategies |
|---|---|
| **Port** | Explicit or auto-assigned from a collision-free pool |
| **Database** | PostgreSQL schema, SQLite file, or container-per-worktree |
| **Docker service** | Named container derived from the worktree ID |

Three output formats are supported:

| Format | Use case |
|---|---|
| `.env` (dotenv) | Source with `env $(cat .env)` or load via `python-dotenv` |
| `docker-compose` | Merge override with `docker compose -f base.yml -f override.yml up` |
| `shell` | Source into a bash session: `source .harness_env_<id>.sh` |

---

## Workflow

**Need a .env file for an isolated worktree?**
→ [Generate a dotenv config](#generate-a-dotenv-config)

**Need a docker-compose service override with per-worktree ports and DB?**
→ [Generate a docker-compose override](#generate-a-docker-compose-override)

**Need bash exports to source before running the app?**
→ [Generate shell exports](#generate-shell-exports)

**Need a collision-free port from a shared pool?**
→ [Auto-assign a port](#auto-assign-a-port)

---

## Generate a Dotenv Config

```python
from harness_skills.env_isolation import (
    EnvIsolationSpec,
    DbIsolation,
    OutputFormat,
    generate_env_config,
)

spec = EnvIsolationSpec(
    worktree_id="fb563322",        # task-UUID prefix or branch slug
    port=8001,
    db_isolation=DbIsolation.SCHEMA,
    # db_schema omitted → auto-derived as "worktree_fb563322"
)

dotenv_content = generate_env_config(spec, OutputFormat.DOTENV)

with open(".env.fb563322", "w") as f:
    f.write(dotenv_content)
```

Sample output:

```dotenv
# -----------------------------------------------------------------------
# harness env-isolation — worktree: fb563322
# Generated by harness_skills.env_isolation
# -----------------------------------------------------------------------
PORT=8001
DB_SCHEMA=worktree_fb563322
```

---

## Generate a Docker-Compose Override

```python
spec = EnvIsolationSpec(
    worktree_id="fb563322",
    port=8001,
    db_isolation=DbIsolation.CONTAINER,
)

override = generate_env_config(spec, OutputFormat.DOCKER_COMPOSE)

with open("docker-compose.fb563322.yml", "w") as f:
    f.write(override)
```

Run with:

```bash
docker compose -f docker-compose.yml -f docker-compose.fb563322.yml up
```

When `db_isolation=CONTAINER` a companion Postgres service named
`harness_fb563322_db` is generated automatically.

---

## Generate Shell Exports

```python
spec = EnvIsolationSpec(
    worktree_id="fb563322",
    port=8001,
    db_isolation=DbIsolation.FILE,
    # db_file omitted → auto-derived as /tmp/harness_fb563322.db
)

shell_script = generate_env_config(spec, OutputFormat.SHELL)

with open(".harness_env_fb563322.sh", "w") as f:
    f.write(shell_script)
```

Source and run:

```bash
source .harness_env_fb563322.sh
uvicorn myapp.main:app
```

---

## Auto-Assign a Port

Use `assign_port` to pick a collision-free port from the range
`[base, base + max_search)`:

```python
from harness_skills.env_isolation import assign_port

# Ports already in use by other worktrees
taken = [8000, 8001, 8002]

port = assign_port(
    worktree_id="fb563322",
    taken=taken,
    base=8000,
)
# → deterministic, collision-free port in [8000, 8200)
```

The function uses a hash of `worktree_id` to produce a deterministic starting
offset so that different worktrees tend to receive different ports even when no
registry is available.

---

## Database Isolation Strategies

### PostgreSQL schema per worktree

```python
spec = EnvIsolationSpec(
    worktree_id="fb563322",
    port=8001,
    db_isolation=DbIsolation.SCHEMA,
    db_schema="worktree_fb563322",   # omit to auto-derive
)
```

Sets `DB_SCHEMA=worktree_fb563322`.  Your app must honour that variable when
constructing its database connection (e.g.
`SET search_path TO worktree_fb563322;`).

### SQLite file per worktree

```python
spec = EnvIsolationSpec(
    worktree_id="fb563322",
    port=8001,
    db_isolation=DbIsolation.FILE,
    db_file="/tmp/harness_fb563322.db",  # omit to auto-derive
)
```

Sets `DATABASE_URL=sqlite:////tmp/harness_fb563322.db`.

### Container per worktree

```python
spec = EnvIsolationSpec(
    worktree_id="fb563322",
    port=8001,
    db_isolation=DbIsolation.CONTAINER,
)
```

Sets `DB_CONTAINER=harness_fb563322`.  `DATABASE_URL` is expected to be
injected by the container orchestrator.  In docker-compose mode a companion
Postgres service is added to the override automatically.

### No database isolation (default)

```python
spec = EnvIsolationSpec(worktree_id="fb563322", port=8001)
# db_isolation defaults to DbIsolation.NONE
```

Only `PORT` is emitted.

---

## Extra Environment Variables

Inject arbitrary variables into every output format:

```python
spec = EnvIsolationSpec(
    worktree_id="fb563322",
    port=8001,
    extra_vars={
        "FEATURE_FLAG_PAYMENTS": "false",
        "LOG_LEVEL": "debug",
    },
)
```

---

## Helper Utilities

### `schema_name(worktree_id)` — safe PostgreSQL identifier

```python
from harness_skills.env_isolation import schema_name

schema_name("fb563322")           # → "worktree_fb563322"
schema_name("feature/my-branch")  # → "worktree_feature_my_branch"
```

### `container_name(worktree_id, suffix)` — safe Docker resource name

```python
from harness_skills.env_isolation import container_name

container_name("fb563322")        # → "harness_fb563322"
container_name("fb563322", "db")  # → "harness_fb563322_db"
```

---

## Reference: `EnvIsolationSpec` Fields

| Field | Type | Default | Description |
|---|---|---|---|
| `worktree_id` | `str` | — | Short ID for this worktree (task-UUID prefix or branch slug). |
| `port` | `int` | `8000` | TCP port the isolated instance binds to. |
| `db_isolation` | `DbIsolation` | `NONE` | Database isolation strategy. |
| `db_schema` | `str` | `""` | PostgreSQL schema name (auto-derived when empty). |
| `db_file` | `str` | `""` | SQLite file path (auto-derived when empty). |
| `container_suffix` | `str` | `""` | Suffix appended to Docker container name (defaults to worktree_id). |
| `extra_vars` | `dict[str, str]` | `{}` | Additional env-var key/value pairs. |

---

## Key Files

| Path | Purpose |
|---|---|
| `harness_skills/env_isolation.py` | All public API — `generate_env_config`, format-specific generators, `assign_port`, `schema_name`, `container_name`, data models. |
| `skills/env-isolation/SKILL.md` | This skill definition. |

