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
Need a docker-compose service override with per-worktree ports and DB? → Generate a docker-compose override
Need bash exports to source before running the app? → Generate shell exports
Need a collision-free port from a shared pool? → Auto-assign a port
Generate a Dotenv Config
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:
# -----------------------------------------------------------------------
# harness env-isolation — worktree: fb563322
# Generated by harness_skills.env_isolation
# -----------------------------------------------------------------------
PORT=8001
DB_SCHEMA=worktree_fb563322
Generate a Docker-Compose Override
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:
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
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:
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):
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
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
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
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)
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:
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
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
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. |