OpenKanban + Ravi

OpenKanban + Ravi

OpenKanban is a terminal UI kanban board for managing AI coding agents across projects. Its core abstraction is ticket-as-worktree: every task card gets its own isolated git branch, embedded terminal, and agent session. You spawn Claude Code, Codex, Aider, Gemini, or any CLI agent directly from the board, then watch it work or jump to the next ticket. Multi-project support means one board covers all your repositories.

OpenKanban solves the orchestration problem — how do you run five agents in parallel without branch conflicts and terminal chaos? It does not solve the identity problem — how does each of those five agents get the credentials it needs to do real work?

That’s the gap Ravi fills.

The Problem

When agents are isolated in worktrees but share a credential environment, the isolation is incomplete. The friction shows up in three recurring patterns.

Shared credentials across tickets. An agent working in the integrate-stripe worktree and an agent in the deploy-staging worktree both reach for the same STRIPE_SECRET_KEY and AWS_ACCESS_KEY_ID from the host environment. A leaked key on one ticket is a leaked key everywhere. A rotation on one ticket breaks the other mid-run.

Service sign-ups and verification loops. Agents frequently need to register for third-party services mid-task — package registries, API consoles, cloud accounts. Every sign-up requires a valid email and phone. Without a real inbox the agent controls, verification becomes a human-in-the-loop step that kills automation.

2FA walls on service access. Services requiring TOTP-based 2FA (GitHub, AWS, npm) stall agents that don’t have access to the authenticator app. Storing TOTP seeds in plaintext on the developer’s machine defeats the security model.

What Ravi Adds

Ravi maps directly onto OpenKanban’s ticket model. Each ticket gets a Ravi identity — its own provisioned email, phone number, and secrets namespace. The agent running in that worktree operates with scoped credentials that exist only for the duration of the task.

Secrets per Worktree

Ravi’s secrets store supports per-ticket namespacing. An agent assigned to the integrate-stripe ticket fetches TICKET_INTEGRATE_STRIPE_SECRET_KEY; an agent on deploy-staging fetches TICKET_DEPLOY_STAGING_AWS_KEY. The two never overlap.

When a ticket moves to done, a cleanup hook revokes the credentials and deletes the vault entries. The host machine never accumulates orphaned keys from completed work.

Agent Identity per Ticket

When an agent needs to sign up for a service mid-task — a new API tier, a CI/CD provider, a package registry — Ravi provisions a real isolated email address and phone number for that ticket. The agent registers, receives the verification email or SMS, confirms the account, and continues without any human intervention.

The identity is scoped to the ticket. Credentials created by the integrate-stripe agent go into the integrate-stripe Ravi vault namespace. Clean separation, full audit trail.

TOTP/2FA Unblocking

Agents stall on TOTP prompts because the authenticator is on the developer’s phone, not in the agent’s context. Ravi’s TOTP store holds the seed securely and returns the current code on request. The agent calls Ravi at the 2FA checkpoint, gets the code, completes the flow — without any plaintext secrets exposed in the worktree.

Async Notifications

OpenKanban’s embedded terminal is great for watching agents work live. For truly parallel workflows, you also need async signals. When a ticket hits a blocker or completes successfully, the agent sends an email or SMS via Ravi. You get a notification without watching the board — and every notification is logged with the ticket identity as sender, so the audit trail is automatic.

Concrete Integration: Ticket Identity Lifecycle

The cleanest integration wires Ravi into OpenKanban’s ticket config via a ravi block:

// ~/.config/openkanban/config.json (excerpt)
{
  "agents": [
    {
      "name": "claude",
      "command": "claude",
      "args": ["--dangerously-skip-permissions"]
    }
  ],
  "hooks": {
    "on_ticket_create": "./scripts/ravi-provision.sh",
    "on_ticket_done": "./scripts/ravi-teardown.sh"
  }
}

Provision script (scripts/ravi-provision.sh):

#!/bin/bash
# Called by OpenKanban when a ticket moves to in-progress
# Argument: ticket slug (e.g. "integrate-stripe")
TICKET=$1

# Set the RAVI_IDENTITY env var for agents in this worktree
export RAVI_IDENTITY="ticket-${TICKET}"

# Pull scoped secrets and inject into the worktree environment
GH_TOKEN=$(ravi secrets get "TICKET_${TICKET^^}_GITHUB_TOKEN" 2>/dev/null || echo "")
if [ -n "$GH_TOKEN" ]; then
  echo "export GH_TOKEN=$GH_TOKEN" >> ".env.${TICKET}"
fi

echo "Ravi identity provisioned for ticket: $TICKET"

Agent boot — when OpenKanban spawns the agent (s key in the TUI), pass the identity context:

RAVI_IDENTITY=ticket-integrate-stripe claude --dangerously-skip-permissions

The agent now has access to a scoped Ravi context: its own email, phone, and secrets namespace keyed to the ticket.

Handling Email Verification Inside a Ticket

When the agent needs to complete an account verification loop, the Ravi inbox tools handle it without leaving the agent’s context:

import time
import ravi

def sign_up_and_verify(service_url: str, service_name: str):
    """
    Register for a service using the ticket's Ravi-provisioned email,
    then complete verification autonomously.
    """
    identity = ravi.get_info()
    ticket_email = identity["email"]

    # Submit the sign-up form with the Ravi-provisioned email
    submit_registration(service_url, email=ticket_email)

    # Wait for the verification email (typically arrives within seconds)
    time.sleep(10)

    threads = ravi.inbox_email(unread=True)
    for thread in threads:
        if service_name.lower() in thread["subject"].lower():
            messages = ravi.read_email(thread["thread_id"])
            for msg in messages["messages"]:
                import re
                urls = re.findall(r"https://[^\s\"]+verif[^\s\"]*", msg["text_content"])
                if urls:
                    return urls[0]

    raise RuntimeError(f"No verification email from {service_name}")

Sending Async Notifications When a Ticket Completes

When the agent finishes a ticket, it fires a notification via Ravi so you hear about it without watching the board:

import ravi

def notify_ticket_complete(ticket_name: str, summary: str, notify_email: str):
    ravi.email_compose(
        to=notify_email,
        subject=f"Ticket done: {ticket_name}",
        body=f"<p>The agent working on <strong>{ticket_name}</strong> has completed.</p>"
             f"<p>{summary}</p>"
             f"<p>Credentials used during this ticket have been scoped to the Ravi vault "
             f"under <code>TICKET_{ticket_name.upper()}</code>.</p>"
    )

TOTP Retrieval at a 2FA Checkpoint

import ravi

def get_totp_code(service_key: str) -> str:
    """
    Retrieve a TOTP code from Ravi's vault for a service that requires 2FA.
    The agent calls this at the 2FA challenge screen.
    """
    secret = ravi.secrets_get(f"TICKET_TOTP_{service_key.upper()}")
    # Ravi returns the current TOTP code alongside the stored seed
    return secret["totp_code"]

Setup Guide

Prerequisites

  • OpenKanban installed (brew install TechDufus/tap/openkanban)
  • Ravi CLI configured (ravi identity list shows your active identity)

Step 1: Create ticket-scoped identities in Ravi

For tasks where agents will register external services, provision a Ravi identity per ticket type (or use one identity per project and namespace within it):

# Create a project-level identity with scoped namespacing
ravi identity create "openkanban-project-myapp"

# Confirm provisioned email and phone
ravi get-info

Step 2: Move existing credentials into Ravi

Replace scattered environment variables with Ravi-managed secrets before your first ticket run:

# Store credentials under ticket-namespaced keys
ravi secrets set TICKET_INTEGRATE_STRIPE_SECRET_KEY sk_live_your_key
ravi secrets set TICKET_DEPLOY_STAGING_AWS_KEY AKIAIOSFODNN7EXAMPLE

Step 3: Wire up lifecycle hooks

Add the provision and teardown scripts to your OpenKanban config (see snippet above). The hooks fire when tickets move between columns — provision on todo → in-progress, teardown on in-progress → done.

Step 4: Test the full loop

Create a test ticket, spawn an agent, run a sign_up_and_verify call against a staging service, confirm the Ravi inbox received and parsed the verification email, move the ticket to done, verify credentials were cleaned up from the vault.

Why Ravi Fits OpenKanban Specifically

OpenKanban’s insight is that isolated worktrees let agents work in parallel without stepping on each other’s code. Ravi extends that isolation to the credential layer — the part OpenKanban doesn’t touch.

Without RaviWith Ravi
All tickets share host environment credentialsEach ticket gets a scoped secrets namespace
Service sign-ups require human email verificationAgents handle verification autonomously via Ravi inbox
2FA checkpoints stall agentsAgents retrieve TOTP codes from Ravi’s vault
Completed tickets leave orphaned credentialsTeardown hooks revoke and delete on ticket close
No audit trail for agent actionsEvery notification and sign-up is logged with ticket identity

The ticket-as-worktree model makes agent parallelism tractable. Ravi makes it secure — each ticket’s agent has a real, isolated, accountable identity that lives and expires with the task.

Resources