Catalog npm
Back to packageRELEASE DETAILS

0.1.0

npm

2heads

A tmux-backed terminal REPL for making Claude and Codex challenge each other before you decide.

aiclaudeclicodexdecision-makingrepltmux
Published25 Apr 2026
Direct dependencies6
Transitive dependenciesNot calculated

README

Current package documentation

2heads

2HEADS helps you think through complex decisions by forcing two models to reason in public, challenge each other's assumptions, and expose trade-offs before you commit.

2heads is a tmux-backed terminal REPL that passes a prompt between Claude and Codex for a fixed number of rounds, then asks a separate recap worker to summarize the exchange.

Usage

npm install
npm run build
node dist/cli.js --rounds 1

The CLI requires tmux, claude, and codex on PATH. This repository does not install those tools automatically.

Inside the REPL:

  • :quit exits and cleans up the tmux session.
  • :rounds <n> changes the number of two-agent rounds.
  • :first claude|codex changes which agent starts.
  • :attach attaches to the background tmux session.
  • :last prints the last recorded model answer.
  • :help shows available commands.

You can tag files in a prompt with @path, for example:

Compare the CLI flow in @src/cli.ts with the worker protocol in @src/worker.ts

Use quotes for paths with spaces:

Review @"docs/decision note.md"

Tagged files are resolved relative to the active workdir. Their contents are sent to Claude and Codex only in the seeded prompts for the current exchange; later model-to-model handoffs still pass only the latest answer.

In an interactive terminal, typing @ opens a live file picker in the bottom composer. Continue typing to filter files, use Up/Down to move through matches, and press Tab to insert the selected path. Directory matches end in /, so you can keep navigating deeper before tagging a file.

Architecture

2heads has one foreground process and three background workers.

The foreground CLI owns the terminal UI, command parsing, transcript writing, and turn orchestration. It starts a dedicated tmux session for each run, then opens three panes inside it:

  • Claude worker: runs Claude turns.
  • Codex worker: runs Codex turns.
  • Recap worker: runs the final summary in a separate model session.

The workers communicate with the CLI through JSON files under .2heads/sessions/<session-id>/. For each turn, the CLI writes a request file, the worker picks it up, streams events back into event files, and writes a final response file. The CLI records those events and final answers into the transcript.

Within one REPL run, Claude and Codex keep persistent model sessions. The first handoff seeds a model with the user prompt and any tagged file context; later turns send only the latest model answer, relying on that model's existing session context instead of resending the whole transcript. Each handoff explicitly asks the next model to push back on the previous answer before building on it. Starting the CLI again creates fresh tmux and model sessions.

The recap worker is intentionally separate from the active Claude/Codex exchange. It receives the full back-and-forth once, after the exchange is done, and produces the final recap without contaminating either active debate session.

On exit, 2heads kills the tmux server for the run and removes its socket unless you start with --keep-tmux.

Agents are prompted to use Markdown math notation for formulas: $...$ inline and $$...$$ for display formulas. The terminal UI highlights those formulas while preserving the raw notation in transcripts.

The terminal output is rendered as full-width chat bubbles. Claude, Codex, and the recap all align left while keeping distinct background colors. Model answers are buffered per turn so each bubble can be wrapped cleanly. Basic Markdown is formatted inside bubbles, including headings, bold, italic, inline code, bullets, numbered lists, horizontal rules, and simple pipe tables.

In an interactive terminal, the bottom composer is rendered as a fixed textbox-style panel. It stays active while agents are thinking, so you can type the next message during an exchange; 2heads queues it and runs it after the current exchange finishes. The composer shows a small spinner with the active agent and turn count so it is clear whether Claude, Codex, or the recap worker is currently running.

Transcripts are saved under .2heads/sessions/.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 6

Native requirements
6 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
execa
Environment
{
  "local_name": "execa",
  "alias": false,
  "peer_metadata": null
}
^9.6.0runtime
commander
Environment
{
  "local_name": "commander",
  "alias": false,
  "peer_metadata": null
}
^14.0.2runtime
picocolors
Environment
{
  "local_name": "picocolors",
  "alias": false,
  "peer_metadata": null
}
^1.1.1runtime
vitest
Environment
{
  "local_name": "vitest",
  "alias": false,
  "peer_metadata": null
}
^4.0.8development
typescript
Environment
{
  "local_name": "typescript",
  "alias": false,
  "peer_metadata": null
}
^5.9.3development
@types/node
Environment
{
  "local_name": "@types/node",
  "alias": false,
  "peer_metadata": null
}
^24.0.0development

Distribution files

1 collected
Distribution 1

Source distribution

Source file
Checksums from source
{
  "shasum": "7b6990be775506c61aec864fbb60326d49961df6",
  "tarball": "https://registry.npmjs.org/2heads/-/2heads-0.1.0.tgz",
  "fileCount": 51,
  "integrity": "sha512-saGjV1I8b8A7EImYk25KmYpXYgK5fnuiTNKCpdzxxSWsXXJA3po+tBmvZPiPHAzNqYkARwpHFPsbqHQmpy4YJg==",
  "signatures": [
    {
      "sig": "MEUCIC0MW1VE4rpWKuP8m5sR7TUqdyf7qPVUuQ8a0K1x58fxAiEAhf/laz84ZLrAh6J3D1S9YNiqHMytANgsBJt1iDfwhQ8=",
      "keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
    }
  ],
  "unpackedSize": 157705
}

Repository

PENDING
jsanzolac/2heads

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 19:13 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:83d549be2d5ddc2c549e765a094bbdff50b6f25c4f9768cc21fa4f4fc1eedb2b

Other collected versions

0.1.326 Apr0.1.225 Apr0.1.125 AprView all collected versions →