Metadata-Version: 2.4
Name: harness-exchange
Version: 0.1.0
Summary: Exchange agent/chat sessions between codex, opencode, and claude-code
Author: harness-exchange contributors
License: MIT
Project-URL: Source, https://github.com/cnmoro/harness-exchange
Project-URL: Tracker, https://github.com/cnmoro/harness-exchange/issues
Keywords: codex,opencode,claude,harness,session,exchange,cli
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: questionary>=2.0
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Dynamic: license-file

# harness-exchange

Exchange sessions between **codex**, **opencode**, and **claude-code**.

Rate-limited on one tool but still have context you need? Port your session to another harness and keep going.

```text
harness-exchange --from codex --to opencode
```

## Installation

```bash
pip install harness-exchange
```

Requires Python 3.11+.

## Usage

### Interactive (arrow-key selection)

```bash
harness-exchange --from codex --to opencode
```

Lists the 15 most recent sessions from the source harness, each with a preview of the first and last message. Use arrow keys to select, Enter to transfer.

### Non-interactive (session ID)

```bash
harness-exchange --from claude --to codex --session-id <session-uuid>
```

Combine with `--non-interactive` for scripting:

```bash
harness-exchange --from codex --to opencode --session-id <id> --non-interactive
```

### All combinations

| From | To |
|------|----|
| `codex` | `opencode` |
| `codex` | `claude` |
| `opencode` | `codex` |
| `opencode` | `claude` |
| `claude` | `codex` |
| `claude` | `opencode` |

### Options

| Flag | Description |
|------|-------------|
| `--from` | Source harness (`codex`, `opencode`, `claude`) |
| `--to` | Target harness (`codex`, `opencode`, `claude`) |
| `--session-id` | Transfer a specific session by ID (skips selection) |
| `--limit` | Number of recent sessions to show (default: 15) |
| `--non-interactive` | Skip interactive prompts (requires `--session-id`) |

## Storage locations

Each tool stores sessions in a different format:

| Tool | Format | Location |
|------|--------|----------|
| **codex** | JSONL rollouts | `~/.codex/sessions/YYYY/MM/DD/*.jsonl` |
| **opencode** | SQLite | `~/.local/share/opencode/opencode.db` |
| **claude-code** | JSONL transcript | `~/.claude/projects/<cwd>/<sessionId>.jsonl` (+ `sessions/<pid>.json` and `history.jsonl`) |

The tool detects these paths automatically (uses `$HOME`). Writing to opencode
uses opencode's own `import` command so the schema stays valid; writing to
claude-code produces a real `projects/` transcript so the session is resumable
with `claude --resume`.

## What gets transferred

- All conversation messages, with **user and assistant roles preserved**
- Tool calls and their outputs (where the target format supports them)
- Session title, working directory (`cwd`), and timestamps
- Agent and model information (where available)

Codex injects system prompts and context (`AGENTS.md`, `<environment_context>`,
permissions/personality specs) as hidden turns; these are filtered out so only
the real conversation is carried over.

## How it works

1. **Lists** the most recent sessions from the source harness (default: 15)
2. **Shows** a preview of the first and last real user message for each session
3. **Reads** the full session (metadata + all messages) from source storage
4. **Writes** the session into the target harness's storage format

The interactive selector uses `questionary` with a plain-text fallback if the library isn't available.

## Development

```bash
git clone https://github.com/cnmoro/harness-exchange.git
cd harness-exchange

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest
```

## License

MIT
