A CLI tool for migrating conversation history between AI coding tools.
- Claude Code (Anthropic)
- Codex (OpenAI)
- Gemini CLI (Google)
- Cursor
All pairs are supported bidirectionally.
Requires uv.
Install globally (recommended):
uv tool install agent-migratorOr run without installing:
uvx agent-migratorRun from inside a project directory:
agent-migratorThe CLI walks you through:
- Tool selection — choose source and destination.
- Conversation selection — pick conversations to migrate, sorted most-recent-first.
- Migration progress — each conversation is processed in sequence;
Ctrl+Ccancels and rolls back. - Summary — a results table shows successes and errors.
Cursor: the project path must be a directory that has been opened as a workspace in Cursor at least once.
Two subcommands expose the same engine for scripting and agentic use. Both accept --dir <path> (defaults to cwd) and print JSON to stdout; errors go to stderr as {"error": "..."} with exit 1.
List conversations:
agent-migrator list --from claude-code --dir /path/to/project[{"id": "63ec7bb1-...", "name": "pwa-capabilities-demo", "updated_at": "2026-05-21T23:23:00", ...}]Migrate a conversation:
agent-migrator move --from claude-code --to codex --id 63ec7bb1-... --dir /path/to/project[{"source_id": "63ec7bb1-...", "destination_id": "019e51f7-...", "name": "pwa-capabilities-demo"}]Omit --id to migrate all conversations for the project. Run agent-migrator list --help or agent-migrator move --help for full options.
All pairs support:
| Feature | Status |
|---|---|
| Text messages (user and assistant) | ✓ |
| Tool calls (Read, Write, Edit, Bash, Glob, and equivalents) | ✓ |
| Plan (presented natively in the destination tool's plan UI) | ✓ |
(Any) → Cursor is the one exception: plans are migrated as context documents but are not surfaced in Cursor's native plan mode UI.
(Any) → Cursor also requires a server upload to Cursor's ConvertOALToNAL endpoint to make all models available. If that fails (e.g. not logged in), the CLI offers a local fallback that provides full context but restricts model selection to Anthropic models.
Conversations are read into a tool-agnostic normalized format (TextMessage and ToolCallMessage turns) and written out in the destination format. Each tool is implemented as a AgentAdapter subclass in agent_migrator/agents/. This decouples all source/destination pairs — adding a new tool requires only a new adapter; all existing migration paths continue to work unchanged.
To add support for a new coding agent, implement the AgentAdapter interface in agent_migrator/agents/ and register it in cli.py:
class MyAgentAdapter(AgentAdapter):
name = "My Agent"
tool_id = "myagent"
def is_available(self) -> bool: ...
def list_conversations(self, project_path: Path) -> list[ConversationInfo]: ...
def read_conversation(self, conv_id: str, project_path: Path) -> Conversation: ...
def write_conversation(self, conv: Conversation, project_path: Path, *, use_local_backend: bool = False) -> str: ...
def delete_conversation(self, conv_id: str, project_path: Path) -> None: ...| Tool | Location |
|---|---|
| Claude Code | ~/.claude/projects/<encoded-path>/<session>.jsonl |
| Codex | ~/.codex/sessions/YYYY/MM/DD/rollout-<timestamp>-<id>.jsonl |
| Gemini CLI | ~/.gemini/tmp/<project-slug>/chats/session-<timestamp>-<id>.jsonl |
| Cursor | %APPDATA%/Cursor/User/globalStorage/state.vscdb (SQLite) |