vibe-tree

vibe-tree — Parallel AI Development in Git Worktrees

vibe-tree is a cross-platform application (macOS, Windows, Linux, mobile) that lets you run AI coding agents in parallel across multiple git worktrees. Each worktree gets its own persistent terminal session with full Claude CLI integration — so you can develop five features simultaneously without context switching or branch stashing. It ships as a desktop binary, a LAN-accessible web UI, and a Docker image for cloud VM deployment. Mobile access works via WebSocket discovery over LAN.

Where Ravi Fits

Running multiple parallel agents quickly creates credential and identity management problems: where do you store the cloud instance password, how do you give each agent a distinct inbox, and how does a long-running agent signal completion without keeping a WebSocket open forever? Ravi solves all three.

1. Credential Vault for Cloud Deployments

When vibe-tree is deployed on a cloud VM (EC2, DigitalOcean, etc.) it uses a USERNAME and PASSWORD env var to protect the WebSocket interface. Any agent connecting to a shared vibe-tree instance needs those credentials — and hardcoding them in a script or .env file is a security risk.

Store the vibe-tree host credentials in Ravi’s password vault and retrieve them at runtime:

// Retrieve stored vibe-tree credentials at agent startup
const creds = await ravi.passwords.get({ domain: "vibe-tree" });
// creds.username, creds.password — never hardcoded

The credentials are E2E encrypted at rest and only decrypted when needed. No secrets in environment files or CI configs.

2. Per-Worktree Agent Identity

Each parallel Claude session is an independent agent context. If those agents need to interact with external services — sign up for a SaaS trial, receive a verification email, respond to a CI notification — they need distinct inboxes. A single shared inbox creates cross-contamination: OTPs and verification emails from different worktrees arrive in the same place, and it’s impossible to route them correctly.

Provision one Ravi identity per worktree:

// When creating a new worktree, provision a matching Ravi identity
const identity = await ravi.identities.create({
  name: `vibe-tree-${worktreeName}`,
  email: `${worktreeName}@agents.yourdomain.app`
});

// The agent running in that worktree uses this identity exclusively
// - isolated inbox for verifications and OTPs
// - distinct phone number for SMS-gated signups
// - separate secrets store for that task's credentials

Clean separation of inboxes means no cross-contamination, and every external interaction is auditable per-worktree.

3. Async Notification Routing

vibe-tree already sends Claude notifications for task completion and input requests. The natural extension: route those notifications to the agent’s Ravi email inbox, and have the orchestrating agent poll ravi_inbox_email rather than keeping a persistent WebSocket connection open.

// Wire a worktree's completion notification to its Ravi inbox
await vibeTree.onComplete(worktreeId, async (result) => {
  await ravi.email.send({
    to: worktreeIdentity.email,
    subject: `Worktree ${worktreeName} complete`,
    body: result.summary
  });
});

// Orchestrating agent polls for completions
const completions = await ravi.inbox.email({ unread: true });
// Route each completion to the appropriate downstream handler

This decouples the orchestrator from live WebSocket state and makes the notification log durable and queryable.

Concrete Setup Guide

Step 1: Store vibe-tree credentials in Ravi

After deploying your cloud vibe-tree instance, store its access credentials:

# Via Ravi CLI or SDK
ravi passwords create \
  --domain "vibe-tree" \
  --username "your-username" \
  --password "your-password" \
  --notes "Cloud VM vibe-tree instance at <IP>"

Step 2: Provision per-worktree identities

Add identity provisioning to your worktree creation workflow:

import { RaviClient } from "@ravi/sdk";

const ravi = new RaviClient({ apiKey: process.env.RAVI_API_KEY });

async function createWorktreeWithIdentity(taskName, repoPath) {
  // Create the git worktree
  await exec(`git worktree add ${repoPath}/${taskName} -b ${taskName}`);

  // Provision a Ravi identity for this worktree
  const identity = await ravi.identities.create({
    name: `${taskName}-agent`,
    email: taskName.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
  });

  return { worktreePath: `${repoPath}/${taskName}`, identity };
}

Step 3: Launch the Claude session with identity context

Pass the identity credentials into the Claude session running in the worktree:

RAVI_IDENTITY_ID=<worktree-identity-id> \
RAVI_API_KEY=<key> \
claude --worktree <path> "Implement feature: <task>"

Step 4: Poll for completions from the orchestrator

async function checkWorktreeCompletions() {
  const unread = await ravi.inbox.email({ unread: true });
  for (const thread of unread) {
    if (thread.subject.startsWith("Worktree")) {
      const worktreeId = parseWorktreeId(thread.subject);
      await handleCompletion(worktreeId, thread);
    }
  }
}

Why Ravi Adds Value Here

vibe-tree solves the parallelism problem at the terminal/session layer. Ravi solves the identity and credential layer that parallel agents inevitably need:

  • Credential isolation: each agent pulls its own secrets, never sharing a credential file
  • Inbox isolation: verifications and OTPs route to the right worktree, not a shared catch-all
  • Durable notifications: async email-based signaling survives WebSocket disconnects
  • Auditability: every external interaction by every worktree agent is attributed to a distinct, named identity

The combination turns vibe-tree from a local development tool into a production-grade multi-agent environment.

Resources