dmux + Ravi
dmux + Ravi
dmux is a terminal-based orchestrator that runs multiple AI coding agents in isolated git worktrees using tmux. Each “pane” gets its own full working copy of the repo, its own branch, and its own agent session — so five parallel Claude Code instances can work on five different features simultaneously without stepping on each other.
Ravi closes the gap dmux doesn’t address: identity. When agents share a machine, they share credentials. Ravi makes per-agent identity isolation as clean as per-agent code isolation.
The Problem
Parallel agents in dmux are well-isolated at the code level. But they still share the host machine’s environment:
- Credential conflicts. Two agents testing the same third-party API fight over one API key. Rate limits hit, logs get entangled, and it’s impossible to tell which agent caused which side effect.
- No real comms for testing. Agents building sign-up flows, email verification, or SMS OTPs have no clean parallel test path — they’d need real inboxes and phone numbers, not mocks.
- Blocked on external sign-ups. When an agent needs to register for an external service mid-task, it blocks or requires human intervention.
Ravi solves all three.
What Ravi Adds
Per-worktree credential bundles
Ravi’s secrets store provisions isolated credential sets per worktree via its CLI. Each dmux pane gets its own scoped API keys — tracked, auditable, and revocable after the task merges.
Real email and phone per agent
Each Ravi identity includes a real email address and phone number. An agent building a sign-up flow can provision a fresh Ravi identity, receive the verification email, extract the OTP, and continue — fully autonomously, in parallel with sibling panes doing the same thing with different identities.
Autonomous external service registration
When a task requires creating an account on an external service, a Ravi identity lets the agent handle the entire flow: provision identity → fill the form → receive verification → confirm → proceed. No human required.
Audit trail across agents
Every Ravi identity’s activity is logged. After a parallel run, you can trace exactly which agent used which credentials, what emails were sent or received, and which pane registered where.
Integration via dmux Lifecycle Hooks
dmux’s hook system makes Ravi injection automatic. The worktree-create hook fires when a new pane starts; post-merge fires when the task completes.
Setup
Install the Ravi CLI alongside dmux:
npm install -g dmux
npm install -g @ravi/cli # or per your Ravi CLI install instructions
Configure your Ravi API key once on the host:
ravi auth login
Hook: inject credentials at pane creation
Create .dmux/hooks/worktree-create.sh in your project root:
#!/usr/bin/env bash
# .dmux/hooks/worktree-create.sh
set -e
PANE_ID=$1
WORKTREE_PATH=$2
# Provision a fresh Ravi identity for this pane (idempotent — safe on re-create)
IDENTITY_NAME="agent-pane-${PANE_ID}"
IDENTITY_JSON=$(
ravi identity create --name "$IDENTITY_NAME" --json 2>/dev/null \
|| ravi identity list --json | jq -r ".[] | select(.name == \"$IDENTITY_NAME\")"
)
IDENTITY_UUID=$(echo "$IDENTITY_JSON" | jq -r '.uuid')
# Write a per-directory config so all ravi commands in this worktree use this identity
mkdir -p "${WORKTREE_PATH}/.ravi"
echo "{\"identity_uuid\":\"${IDENTITY_UUID}\",\"identity_name\":\"${IDENTITY_NAME}\"}" \
> "${WORKTREE_PATH}/.ravi/config.json"
# Inject the agent's email and phone into the worktree's .env
AGENT_EMAIL=$(cd "${WORKTREE_PATH}" && ravi get email --json | jq -r '.email')
AGENT_PHONE=$(cd "${WORKTREE_PATH}" && ravi get phone --json | jq -r '.phone_number')
printf "AGENT_EMAIL=%s\nAGENT_PHONE=%s\n" "$AGENT_EMAIL" "$AGENT_PHONE" \
>> "${WORKTREE_PATH}/.env"
echo "Ravi identity ${IDENTITY_NAME} ready: ${AGENT_EMAIL} / ${AGENT_PHONE}"
Make it executable:
chmod +x .dmux/hooks/worktree-create.sh
Hook: clean up credentials after merge
Create .dmux/hooks/post-merge.sh:
#!/usr/bin/env bash
# .dmux/hooks/post-merge.sh
PANE_ID=$1
# Delete the identity provisioned for this pane
IDENTITY_NAME="agent-pane-${PANE_ID}"
ravi identity delete "$IDENTITY_NAME" 2>/dev/null || true
echo "Ravi identity ${IDENTITY_NAME} deleted"
What agents see
Inside each worktree, the .ravi/config.json scopes all ravi commands to the pane’s identity — no flags needed. The .env file contains the pane’s email and phone for use in application code:
AGENT_EMAIL=pane3-abc@in.ravi.app
AGENT_PHONE=+15551234567
The agent uses these without any awareness of sibling panes. There’s no risk of collision.
Example Workflow
- Open a project in dmux:
cd my-project && dmux - Press
n→ type “Implement user sign-up with email verification” - Pick your agent (e.g., Claude Code)
- dmux fires
worktree-create→ Ravi provisions a fresh identity for the pane - The agent builds the feature, uses
AGENT_PANE_X_RAVI_EMAILfor test registrations, receives real verification emails, extracts OTPs, and completes the flow autonomously - Press
m→ Merge - dmux fires
post-merge→ Ravi revokes the pane’s identity - Your main branch gets the feature; the identity is cleaned up
Run five of these in parallel. Each pane has its own inbox, its own phone number, its own API keys. No conflicts.
Why This Matters
dmux gives you code isolation. Ravi gives you identity isolation. Together, you get parallel agents that are fully independent — not just at the git level, but at the credential and communication level. That’s what fully autonomous parallel development actually requires.
The fact that this integration is possible at all is Ravi’s core thesis made concrete: agents need persistent, accountable identities to do real work in the world. dmux makes that visible by exposing exactly where shared identity breaks down.