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/passwdis blocked - Files over 50 KB are skipped entirely
- Binary files (null bytes) are skipped
@claude,@codex,@both,@masterare 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:
yor the Approve button — allows that specific command and continuesn,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
⎘ Copyto copy the raw diff to the clipboard - Click
Xto 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| akritrim_colab-0.1.66.tar.gz | 165.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.