dupe

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 28, 2026 License: MIT

README

dupe

Isolated runtimes for parallel AI coding agents. One command per agent: its own worktree, its own ports, its own database — zero collisions.

  ██████╗ ██╗   ██╗██████╗ ███████╗
  ██╔══██╗██║   ██║██╔══██╗██╔════╝   isolated runtimes for
  ██║  ██║██║   ██║██████╔╝█████╗     parallel AI coding agents
  ██║  ██║██║   ██║██╔═══╝ ██╔══╝
  ██████╔╝╚██████╔╝██║     ███████╗
  ╚═════╝  ╚═════╝ ╚═╝     ╚══════╝

         o                       o      two agents.
        /|► :3960         :3637 ◄|\    two ports.
        / \                     / \    two databases.
      agent A                   agent B  zero collisions.

The $20 disaster dupe prevents

You run two AI coding agents in parallel on the same repo — one per task, each in its own git worktree. Worktrees isolate the code. They do not isolate the runtime. So both agents' dev servers try to bind port 3000, and the second one gets EADDRINUSE.

Here's the expensive part: the agent misreads EADDRINUSE as a bug in the application and starts rewriting working code to "fix" it — burning hours and $20+ of tokens corrupting a codebase that was never broken.

dupe makes the collision impossible. It allocates each agent a free port and a private database, writes them into .env.local, and hands the agent a context note that says, in plain terms: if you see EADDRINUSE, it's not a code bug — stop. The wiring prevents the collision; the note is the insurance.

Install

go install github.com/hduddala/dupe/cmd/dupe@latest

Or grab a prebuilt binary from Releases (macOS + Linux, amd64 + arm64).

Quickstart

# 1. In your repo, scaffold a dupe.yaml (it detects your stack)
dupe init

# 2. Spin up an isolated runtime for a task — creates a worktree,
#    allocates a free port + private SQLite DB, runs your setup hooks
dupe start auth-fix

#    ✓ worktree  ~/.dupe/worktrees/ab12cd/auth-fix
#    ✓ web       http://localhost:3960
#    ✓ db        file:.../auth-fix.sqlite
#
#    Run your agent:
#      cd ~/.dupe/worktrees/ab12cd/auth-fix && claude

# 3. Do it again for a second task — different port, different DB, no collision
dupe start billing-fix      # ✓ web http://localhost:3637

# 4. See everything that's running
dupe ls

# 5. Tear one down (frees the port, removes the DB + worktree)
dupe rm auth-fix

If your dev server doesn't read .env.local, run it through dupe so the allocated port/DB are injected directly:

dupe run -- npm run dev

How it works

dupe start <task>
   │
   ├─ git worktree add   ~/.dupe/worktrees/<repo-hash>/<task>/   (OUTSIDE your repo)
   ├─ allocate ports     hash(worktree+service) → probe free → record in ledger
   ├─ provision db       per-worktree SQLite file → DATABASE_URL
   ├─ write .env.local   PORT=… DATABASE_URL=…   (managed block)
   ├─ write context note .dupe-context.md  (EADDRINUSE insurance first)
   └─ run setup hooks    pnpm install, db:migrate, … with the allocated env
  • Ports never collide. Each worktree hashes to a candidate port, then probes upward past anything bound and anything another worktree already reserved in the ledger — so even two idle agents never get the same port.
  • Databases are private. Each worktree gets its own SQLite file. Migrate it, seed it, drop it — no other agent is affected.
  • Worktrees live outside your repo (~/.dupe/worktrees/…), so they never bloat your project dir or confuse file-search tools.
  • The agent gets told. dupe writes a .dupe-context.md (and points CLAUDE.md/AGENTS.md at it) describing the agent's ports, its private DB, and what to do on EADDRINUSE.

Commands

Command What it does
dupe init Scaffold dupe.yaml by detecting your stack
dupe start <task> Create a worktree + provision an isolated runtime
dupe provision Adopt the current directory (no git changes)
dupe run -- <cmd> Run a command with the allocated env injected
dupe ls List active worktrees (read-only)
dupe rm [--force] <task> Tear down a worktree and free its runtime

Configuration (dupe.yaml)

services:
  - name: web
    port_env: PORT       # env var dupe writes the allocated port into
    default_port: 3000   # search starts here
db:
  engine: sqlite         # v0.1: sqlite only
  url_env: DATABASE_URL
setup:                   # run in the worktree, in order, after wiring
  - pnpm install
  - pnpm db:migrate

Why now / how it compares

Tools like Claude Code and Conductor already create worktrees. They isolate code, not runtime — ports and databases still collide. dupe is the runtime layer: point it at a worktree (yours or one it creates) and it makes that runtime safe to run in parallel. The differentiator is the agent-context handoff — the note that gives the agent permission to treat its DB as private and the instruction to not rewrite code over a port error.

Scope (v0.1)

SQLite only · Node/pnpm setup hooks · macOS + Linux · single static Go binary. Postgres, more agent targets, and a reverse proxy are on the roadmap.

License

MIT © Himesh Duddala

Directories

Path Synopsis
cmd
dupe command
Command dupe provisions isolated runtimes for parallel AI coding agents.
Command dupe provisions isolated runtimes for parallel AI coding agents.
internal
banner
Package banner renders the dupe startup splash — a colored wordmark plus the "two agents pointing at each other" motif (the Spider-Man meme), themed so the joke is that dupe makes the two agents DIFFERENT (different ports/DBs) instead of colliding.
Package banner renders the dupe startup splash — a colored wordmark plus the "two agents pointing at each other" motif (the Spider-Man meme), themed so the joke is that dupe makes the two agents DIFFERENT (different ports/DBs) instead of colliding.
config
Package config loads dupe.yaml (the per-repo service declaration) into an engine.Spec, and scaffolds one via `dupe init` with best-effort stack detection.
Package config loads dupe.yaml (the per-repo service declaration) into an engine.Spec, and scaffolds one via `dupe init` with best-effort stack detection.
context
Package context writes the runtime config into a worktree.
Package context writes the runtime config into a worktree.
db
Package db provisions an isolated database per worktree.
Package db provisions an isolated database per worktree.
engine
Package engine is the git-free provisioning core of dupe.
Package engine is the git-free provisioning core of dupe.
index
Package index is the thin, denormalized store at ~/.dupe/index/<hash>.json.
Package index is the thin, denormalized store at ~/.dupe/index/<hash>.json.
layout
Package layout centralizes every on-disk path dupe uses under ~/.dupe, plus the hashing that keeps repos and worktrees from colliding.
Package layout centralizes every on-disk path dupe uses under ~/.dupe, plus the hashing that keeps repos and worktrees from colliding.
managedblock
Package managedblock writes and removes a delimited, idempotent block inside an otherwise user-owned file.
Package managedblock writes and removes a delimited, idempotent block inside an otherwise user-owned file.
ports
Package ports allocates non-conflicting ports for parallel worktrees.
Package ports allocates non-conflicting ports for parallel worktrees.
worktree
Package worktree wraps git worktree plumbing.
Package worktree wraps git worktree plumbing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL