Skip to main content

akritrim-colab

A three-pane collaboration TUI that puts you between Claude and Codex inside any repository. You direct, they implement and review.

Proudly made by Claude code, Codex and me :)

Requires Claude CLI and Codex CLI installed and authenticated.

Demo Video

https://github.com/user-attachments/assets/fa969809-ceba-4762-aa98-525625b0d9ef

Install

pip install akritrim-colab

Or, for an isolated CLI install:

pipx install akritrim-colab

Quick Start

cd /path/to/your-repo
akritrim-colab

On first run, collaboration files are scaffolded into .collab/. Then the TUI launches.

Layout

Pane Contents
Left Shared session chat
Upper right Claude output
Lower right Codex output
Bottom Master input

Resizing panes: Two draggable dividers let you adjust the layout:

  • Vertical divider (between chat and agent panels) — drag left/right to give more space to the chat or to the agent output columns
  • Horizontal divider (between Claude and Codex panels) — drag up/down to give more space to Claude or Codex output

Click and hold on a divider, then drag to resize. The layout adjusts in real time.

Input

Key Action
Enter Send message
Ctrl+Enter Insert newline
Tab Accept autocomplete suggestion
↑ / ↓ Browse command history or navigate autocomplete
Escape Cancel active agent work
Ctrl+C Copy the mouse-selected text if any, otherwise quit

Drag with the mouse inside the chat, Claude, Codex, or diff panes to select text. It is copied to the clipboard as soon as you release the mouse (copy_on_select, on by default), and Ctrl+C copies it again. While text is selected, new output in the Claude and Codex panes is held and appears once the selection is cleared (after copying, or by clicking elsewhere); the chat pane keeps appending but stops auto-scrolling. Panes only auto-follow new output when you are already scrolled to the bottom, so you can scroll up and read while an agent works.

Type / to open the command autocomplete palette.

Routing

Direct a message to a specific agent:

@claude propose a UI improvement
@codex review the current changes
@both compare these two approaches

Or use /ask for a one-off direct message without changing the default routing:

/ask claude explain this function
/ask codex run the tests
/ask both what are the risks here

File Mentions

Inject file content directly into your message using @path/to/file:

@claude refactor this — @src/auth.py
@both compare the two implementations: @src/v1.py and @src/v2.py

The TUI expands the token at submit time. The agent receives the file content inline — no need to ask the agent to read it separately.

Line limit: Files over 150 lines are automatically truncated. A notice is appended showing how many lines were omitted and how to use a range:

[first 150 of 892 lines — 742 lines omitted. Use @src/auth.py:START-END for a specific range.]

Line ranges: Inject a specific section of a file:

@src/auth.py:40-80        lines 40 to 80 inclusive

The header shows (lines 40–80 of 892) so the agent knows the context position. The end of the range is clamped to the actual file length.

Safety guards:

  • Path must resolve inside the repository root — @../../etc/passwd is blocked
  • Files over 50 KB are skipped entirely
  • Binary files (null bytes) are skipped
  • @claude, @codex, @both, @master are never treated as file paths

Work Flows

Structured multi-agent flows that coordinate Claude and Codex automatically:

/fix <bug>           isolate → patch → review
/audit <target>      independent dual review → merged typed findings → cross-check
/review [scope]      Codex built-in review (read-only) → Claude triages findings
/race <task>         both agents implement it in separate copies; you pick one
/feature <desc>      design → implement → review
/refactor <target>   map call sites → refactor → verify
/analyze <question>  dual analysis + position comparison
/decide <text>       log a decision to collaboration memory

/audit asks Claude and Codex for typed findings (severity, file, line, title, detail), matches the two lists, and then has each agent verify the findings only the other reported. The chat shows one list tagged confirmed (both agents, or the other agent agreed), disputed or unverified, and the result is saved to .collab/session/findings.json. Codex runs read-only for audits. If structured output ever fails, /audit --prose <target> runs the older free-text comparison.

/review accepts one scope — --uncommitted (default), --base <branch>, or --commit <sha> — or free-text review focus (Codex cannot combine a scope with custom instructions). Codex runs codex exec review in a read-only sandbox, then Claude checks each finding as VALID or INVALID and fixes the valid ones.

Models, Effort and Usage

/model                           show each agent's model
/model claude <id|default>       change Claude's model for this run
/model codex <id|default>        change Codex's model for this run
/effort claude <level|default>   low | medium | high | xhigh | max
/effort codex <level|default>    passed to Codex as model_reasoning_effort

Changes apply from the next turn and last until you quit; to keep them, set claude_model, codex_model, claude_effort, codex_effort or claude_fallback_model (a model, or a comma-separated list, tried when the main one is overloaded) in .collab/settings.toml.

The status bar shows the app version and, once agents have run, their token use this session, for example claude 42.2k in/955 out ~$0.10 | codex 95k in/2.3k out. Claude reports an estimated cost; Codex reports tokens only, so no cost is shown for it. Counts reset when you quit.

/settings                        open the settings picker: every setting with what it does, its effect and when it applies
/settings list                   print all settings with descriptions in the chat
/settings status_bar_items       choose which status bar items are shown (and in what order); `models` shows each agent's model/effort
/settings <name> [value|default] show a setting with its options, or change it (saved to .collab/settings.toml)
/gate                            show what the approval gate protects
/gate legacy claude              turn Claude's pre-execution gate off for this run (loud in the status bar)
/gate required claude            turn it back on (verified again on Claude's next turn)
/gate legacy codex               Codex back to `codex exec` with a notice after the command ran
/gate required codex             Codex's pre-execution gate on again

The status bar also shows the gate state, for example gate claude=ON codex=ON; see Dangerous Operation Enforcement.

Race mode

/race <task> gives Claude and Codex the same task and lets them work at the same time, each in its own private git worktree of your last commit (under .collab/session/race/). Both agents are instructed to work only inside those copies, and the app changes your files only when you pick a result. One caveat: Claude is not sandboxed and is only told to stay in its copy, so when the race finishes (or is cancelled) the TUI runs a limited check of your working tree and warns you if something changed. The check is git status, so it cannot see ignored files or changes inside .git, and if the check itself fails you get a warning to look yourself.

/race <task>              start (needs a clean working tree and at least one commit)
/race pick claude|codex   apply that agent's result to your working tree
/race discard             throw both results away
/race status              show the pending race
/race clean               remove leftovers from a crashed run

When both finish, each pane shows [DIFF] links for the files that agent changed and the chat shows a one-line summary per agent (files changed, lines added and removed). pick applies the winner as uncommitted changes: nothing is staged or committed, and if your files changed in the meantime and the patch no longer applies cleanly, nothing is changed and you can pick the other result. Press Escape to cancel a race at any point, including while the results are being collected; its copies are removed. If a cancel arrives while git is still collecting results and it does not finish within 30 seconds, the copies are left in place with a warning rather than removed from under git; /race clean removes them later, and skips any folder git is still working in until that finishes.

Limits: both agents start from the last commit, so uncommitted work is refused rather than silently left out. Race agents cannot ask you for approval, so a Claude step that needs one (such as git push) ends that agent's attempt. Codex is confined to its worktree by its sandbox; Claude is not sandboxed and is only told to stay inside its directory, which is why the working-tree check exists (it can flag some stray writes; it cannot prevent one and is not proof that nothing changed). A race reply never replaces what the chat remembers from each agent, and cancelling a race leaves the chat's state alone.

Session Commands

/fresh                   start a new session (clears history)
/resume                  resume from last saved state
/status                  show current session state
/save                    persist session state to disk
/exit                    exit the TUI

Dangerous Operation Enforcement

Certain operations require your explicit approval before an agent executes them:

git push (any form)        git tag
npm publish / npm pack     twine upload
pip install --user         rm -rf
docker push                kubectl apply / kubectl delete
CI/CD pipeline file edits  (.github/workflows/, .gitlab-ci.yml, Jenkinsfile)

Claude (approval gate, on by default): Claude Code asks the TUI before it runs a shell command or changes a file. If the call matches a dangerous operation, a full-screen approval dialog appears and Claude waits for your answer:

  • y or the Approve button — allows that specific command and continues
  • n, Escape, or the Deny button — blocks it; Claude is told it was blocked and not to look for a way around

Each approval covers exactly one call: if Claude later runs the same git push origin main again, you are asked again, and approving one command never approves another. Nothing remembered from earlier (including a command Codex already ran, which only produces a notice) lets a Claude call through unasked. CI/CD file edits are enforced through Claude's file tools (Write, Edit, NotebookEdit) using the real, resolved path, so ./x/../Jenkinsfile or a symlinked folder does not slip past; a shell command that both mentions a CI file and looks like it writes (sed -i, cp, >, ...) also asks.

The gate is checked before any task is sent. Claude is started with no prompt, and the task is written only after the approval hook has reported to the TUI with a one-time code; a short test run once per app launch also proves the hook really intercepts tool calls. If the gate cannot be established (hooks not loaded, Claude Code older than 2.1.295, the private socket cannot open), the turn does not run and you get an error saying why. It never downgrades by itself. Switch deliberately with /gate legacy claude (shown loudly in the status bar as claude=LEGACY) or claude_approval_gate = "legacy"; /gate required claude turns it back on.

Limits, stated plainly: shell-command matching is pattern based, so a determined or unlucky command can evade it (variables, globs, interpreters); tools reached through MCP servers are not covered; and Claude Code's own protections are not relied on. Race attempts (/race) cannot ask you, so gated operations there are denied. For the same reason, if you turn codex_ask_every_command on, Codex's race attempt is not started; set codex_race_without_dialogs = true to let it run ordinary commands in its sandboxed copy without a dialog (dangerous operations, CI-file edits and requests marked as extra access stay blocked), or race with /gate legacy codex.

Codex (approval gate, on by default): writable Codex turns run through codex app-server with the untrusted approval policy, so every command or file change Codex does not consider known-safe is sent to the TUI before it runs. Dangerous operations and CI-file edits open the same approval dialog as for Claude (one call per approval); a request that carries a reason for extra access, a network target or a write outside its folder also asks you, and a malformed network request is declined. By default other commands run without a dialog inside Codex's workspace sandbox, as with Claude (codex_ask_every_command = false). Codex does not reliably mark every request to leave its sandbox, so for strict protection set codex_ask_every_command = true to be asked about every command Codex wants approved (many more dialogs). Same rules as Claude: the gate is verified before the task is sent (version check plus one short test run per app launch), and if it cannot be established the turn does not run; switch deliberately with /gate legacy codex or codex_approval_gate = "legacy" (then Codex only gets a ⚠ POST-EXEC notice after the fact, and the status bar says codex=advisory). Read-only turns (/audit, /review, the reviewer read-only setting) run in a read-only sandbox and need no gate. App-server is marked experimental by OpenAI; it was verified against Codex 0.163.0.

The permission policy is also injected into every agent prompt, asking both agents to request Master: requesting permission to ... before executing dangerous operations.

To configure which operations are gated, see the dangerous_ops key in Configuration below.

Agent Control

/approve                 approve a pending agent request
/deny                    deny a pending agent request
/compare                 run a manual comparison round between agents
/mode <value>            broadcast a mode change to both agents
/role <target> <role>    reassign agent roles at runtime

Role targets: claude, codex, both. Role values: implementer, reviewer, collaborator.

Example:

/role codex implementer
/role both reviewer

Collaboration Memory

/decision D-XXX | Title | Decision | Rationale    log a structured decision
/topic T-XXX | Title | Codex pos | Claude pos      open a scratchpad topic
/resolve-topic T-XXX | D-XXX                       mark a topic resolved

Decisions are appended to .collab/memory.md. Topics go to .collab/scratchpad.md. Both files are read by agents at session start and on update.

Export

/export claude session_claude.txt     export Claude pane to file
/export codex session_codex.txt       export Codex pane to file
/export master session_chat.txt       export the shared chat to file

Diff Viewer

After each agent turn, ▶ [DIFF] <file> links appear inline for every file the agent changed. Each link is permanently bound to the exact patch from that turn — later edits to the same file do not overwrite earlier diff history.

  • Click a link to open a full-screen diff overlay (colour-coded: + green, - red, @@ cyan)
  • Click ⎘ Copy to copy the raw diff to the clipboard
  • Click X to close

Themes

/theme akritrim    (default)
/theme nord
/theme dracula
/theme solarized

The active theme is saved to .collab/settings.toml and restored on next launch.

Configuration

Invalid values never silently loosen safety: a bad claude_dangerously_skip_permissions turns the bypass off, a malformed dangerous_ops uses the full default set, and every such problem is reported as a warning at launch and in the chat.

Settings live in .collab/settings.toml inside your repository. The file is created with defaults on first run. Edit it directly — changes take effect on the next launch.

[app]
# Session identity and default agent roles
identity = "codex"
role = "collaborator"
codex_role = "reviewer"
claude_role = "implementer"

# Maximum number of automatic agent relay turns before pausing for Master input
max_auto_turns = 12

# UI theme: akritrim | nord | dracula | solarized
theme = "akritrim"

# Model overrides — change to use a different model for either agent
claude_model = "claude-sonnet-5-5"
codex_model = "gpt-6-sol"

# Opt-in: run Codex in a read-only sandbox whenever its role is "reviewer".
# Codex cannot modify files, but review runs that write caches/temp files (e.g. pytest) may fail.
codex_reviewer_read_only = false

# Copy mouse-selected pane text to the clipboard as soon as the mouse is released.
copy_on_select = true

# Approval gate. "required" (default): Claude asks you BEFORE a dangerous command or CI-file edit runs, and a
# turn that cannot establish the gate does not run. "legacy": the older stop-and-resume check.
# Codex works the same way through `codex app-server` (writable turns only).
claude_approval_gate = "required"
codex_approval_gate = "required"

# Set to false to allow running outside a git repository.
# Codex will receive --skip-git-repo-check; diff display still works.
# Can also be overridden per run: --no-require-git
require_git = true

# Dangerous-operation gate.
# Agents must request Master approval before executing the listed operations.
# Stream-level interception aborts Claude's subprocess before the tool runs.
# Codex receives a post-execution warning (its event stream fires after execution).
#
# Set to an empty list to disable the gate entirely:
# dangerous_ops = []
#
# Or restrict to specific operations:
# dangerous_ops = ["git push", "npm publish", "rm -rf"]
#
# Omit the key to use the full default set (all operations listed above).

# TUI debug log — records lifecycle events, routing decisions, and stream activity.
# Useful for diagnosing unexpected routing or stuck sessions.
# The Claude stream JSONL log (one entry per turn) is always written to
# .collab/session/stream_debug.jsonl separately.
# debug_log = ".collab/session/tui_debug.log"

Run Options

CLI flags override the corresponding settings.toml values for that run only:

akritrim-colab run --codex-role reviewer --claude-role implementer
akritrim-colab run --claude-model claude-opus-4-6
akritrim-colab run --no-require-git
akritrim-colab run --debug-log .collab/session/tui_debug.log

Development

Clone and install in editable mode:

git clone https://github.com/akritrim/akritrim-colab
cd akritrim-colab
pip install -e ".[dev]"

Or with uv:

uv pip install -e ".[dev]"

Run from source (after editable install):

akritrim-colab
# or
python -m akritrim_colab

Run the test suite:

pytest

Tests use pytest-asyncio (auto mode). No live agent connections are required — the test suite mocks all CLI subprocess calls.

Project layout:

src/akritrim_colab/
  app.py                     Main TUI — CollabApp, all UI, routing, and relay logic
  cli.py                     Entry point — init / run subcommands, settings wiring
  config.py                  ProjectConfig, AppSettings, path resolution
  agents/
    claude_adapter.py        Claude CLI wrapper — streaming, session resume
    codex_adapter.py         Codex CLI wrapper — streaming, thread resume
    stream_events.py         StreamEvent dataclass shared by both adapters
tests/                       pytest test suite
.collab/                     Per-repo collaboration files (created on first run)
  memory.md                  Permanent decisions log
  scratchpad.md              Open topics and working notes
  rules.md                   Collaboration protocol rules
  settings.toml              User configuration
  session/                   Runtime state (gitignored)

Metadata

Release files for akritrim-colab 0.1.66

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for akritrim-colab 0.1.66
File Size Uploaded Provenance
akritrim_colab-0.1.66.tar.gz 165.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for akritrim-colab 0.1.66
File Interpreter ABI Platform
akritrim_colab-0.1.66-py3-none-any.whl Python 3 none any Details

Total release size: 283.7 kB

Release files / akritrim_colab-0.1.66.tar.gz

Download URL akritrim_colab-0.1.66.tar.gz
Size 165.7 kB
Tags Source
SHA-256 checksum
How to use checksums
7fc4bc40af8d5a0d7ee284ad062b51fa40e76366d6e65e71f133dfa58dc6251a
BLAKE2b-256 checksum
How to use checksums
b5a1348774c96ed1886d9bbf5fb75ebd372c45395bfc776d19e38298cbb239be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / akritrim_colab-0.1.66-py3-none-any.whl

Download URL akritrim_colab-0.1.66-py3-none-any.whl
Size 118.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
295f792d9c7c9c7d3a01f608f40f13465b6c657840d82ada58557dc8013c9ed8
BLAKE2b-256 checksum
How to use checksums
b4732db3805349fd14b580bddf490e736400bc8de8983722362e8cffe9cc76d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Security for akritrim-colab 0.1.66

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page