# Ditto CLI
AI · 2026 - Present · active
- Terminal profile switcher that keeps work, personal, and client logins for Claude Code, Codex, opencode, and OMP apart on one machine.
- Each profile gets its own authentication, settings, and session history; no config files are swapped, so switching only affects the process Ditto launches.
- Rust and ratatui, with per-directory workspace binding, shell integration, and a JSON output contract for scripts and agents.
RustratatuiClaude CodeCodexopencodeOMP
- crates.io 262 downloads · all time
## Install
Homebrew installs a prebuilt binary on macOS and Linux, so it needs no Rust toolchain.
$ brew install reyanshgupta/tap/ditto-cli## Or build from source
Cargo needs Rust 1.85 or newer.
$ cargo install ditto-cli## The problem
Claude Code, Codex, opencode, and OMP each keep login state in one place on disk. That works until you need a different account for a different job. Moving auth files around by hand is easy to get wrong, and it is hard to tell which account the next session will use.
Ditto gives every profile its own authentication, settings, and session history, then launches each tool pointed at the profile you picked. Nothing is swapped, so a switch only affects the process Ditto started.
## How profiles stay separate
- Claude Code
CLAUDE_CONFIG_DIR=~/.ditto/profiles/<name>/claude - Codex
CODEX_HOME=~/.ditto/profiles/<name>/codex - opencode
XDG data, config, and state homes under the selected profile - OMP
omp --profile <name> and OMP_PROFILE=<name>
## The picker
┌ Profiles ──────────────┐┌ Selected profile ──────────────────┐ │ default existing ││work Isolated profile │ │› work ★ ││ │ │ personal ││Sign-in status │ │ ││Claude Code ● Signed in │ │ ││Codex ○ Sign in required │ │ ││opencode ⠹ Checking │ │ ││OMP · Use /login inside OMP│ └────────────────────────┘└────────────────────────────────────┘ c Claude Code · x Codex · o opencode · p OMP ↑↓ select · n new · e rename · d default · q quit
## Beyond the picker
Every action has a command behind it, so Ditto scripts as well as it clicks. Workspaces remember which profile a repository uses, and shell integration can put Ditto in front of each supported tool under its own command name.
$ ditto-cli create work$ ditto-cli default work$ ditto-cli claude work -- --model opus$ ditto-cli workspace use work$ ditto-cli status work --json