Skip to content

portaconv

Your Claude Code conversations are stuck on one machine in one directory. portaconv pulls any session out as paste-ready markdown so you can recover it, move it to another tool, or commit it to a repo.

Three commands. That’s the whole tool.

Terminal window
pconv list # see your recent sessions
pconv dump <session-id> # render one as paste-ready markdown
pconv dump <session-id> | clip.exe # WSL — copy to clipboard
# (use pbcopy on macOS, wl-copy on Wayland)

Paste into a new Claude Code session, claude.ai, opencode, whatever — the conversation keeps going. If the session was authored on a different OS, add --rewrite wsl-to-win (or win-to-wsl) so paths inside the content get translated on the way out.

Even faster, inside a portagenty workspace:

Terminal window
# Skip the list + copy UUID dance — just grab the most recent
# session in this workspace and send it straight to the clipboard.
pconv dump --latest --workspace-toml auto | clip.exe
# Long session? Keep only the last 50 messages.
pconv dump --latest --workspace-toml auto --tail 50 | clip.exe

pconv list

List conversations discoverable on this machine. Filter by --workspace-toml auto, --since 2d, or --grep refactor; sort with --sort msgs|title|started; cap with --limit. Table or JSON output.

pconv dump

Dump one session to stdout. --latest --workspace-toml auto skips the id-copy step. --tail N keeps only the last N messages. --rewrite wsl-to-win|win-to-wsl|strip translates paths. Default output: paste-ready markdown.

pconv mcp serve

Stdio MCP server. list_conversations + get_conversation tools with typed schemas (every CLI flag mirrored), plus each conversation as a convos://conversation/&lt;id&gt; resource. See wiring guide.

JSONL on disk
~/.claude/projects/
event stream, tool-specific shape
Adapter
ConvoAdapter
record-type classification, subagent filter, session split
Shared model
Conversation
OpenAI-shape outside,
Anthropic blocks inside
Transforms (opt-in)

—rewrite wsl-to-win · win-to-wsl · strip
apply to text + tool-call args — not cwd metadata

Renderer
markdown | json
tool results truncated by default · thinking hidden by default
stdout
paste-ready
pipe, clipboard, commit to docs/
WSL-authored message
please read /mnt/c/work/src/main.rs
—rewrite wsl-to-win
paste-ready for Windows
please read C:\work\src\main.rs
Windows-authored tool call
{"file_path": "C:\\work\\src\\main.rs"}
—rewrite win-to-wsl
paste-ready for WSL
{"file_path": "/mnt/c/work/src/main.rs"}
mixed paths
saw /mnt/d/data.csv next to C:\Reports\q1.xlsx
—rewrite strip
paste-ready for web / API
saw <path> next to <path>
The underlying problem (optional reading)
One project · two buckets
launched from WSL
~/.claude/projects/
-mnt-c-Users-…-proj/
launched from Windows
~/.claude/projects/
C—Users-…-proj/

Claude Code keys conversation storage by the absolute path of the CWD at launch. WSL and Windows encode the same project two different ways. /resume from one side doesn’t see the other.

file-level sync seems like the answer — it isn’t

Inside the JSONL · content is path-poisoned
Windows-encoded bucket, one 54 MB session:

9999+  occurrences of /mnt/c/…  ← WSL paths
72      occurrences of C:\…  ← Windows paths

Symlinks, Docker bind mounts, polling sync — all merge storage and leave the content alone. A Windows-launched Claude Code resuming a WSL-authored session fails the first time it tries to Read /mnt/c/….

portaconv flips the approach

Extract · rewrite · paste

Don’t fight the on-disk split. Read the substantive dialogue out, normalize it, optionally rewrite paths on the way out, and let the human (or another agent) paste it into a fresh session anywhere. A fresh session has no embedded paths — no OS-specific failure mode. On-demand reads. No daemon. No race windows. Composes with pipes.

Read-only. No daemon. No file watching. pconv never writes to Claude’s storage — close the process and nothing’s running. Every feature has explicit reliability tiers: what’s always the same, what’s opt-in, what could drift as Claude evolves. See the reliability tiers table for the full breakdown — it’s the first thing to read if you’re scripting against portaconv.

portaconv is a sibling to portagenty (the terminal-native workspace launcher). Use them together or independently:

  • Standalone: cargo install portaconv, run pconv from any terminal. Reads ~/.claude/projects/ directly.
  • With portagenty (planned): a pa convos shim passes workspace context to pconv so list/dump automatically scope to the current workspace’s projects.

v0.0.1 feature-complete for v0.1. Core model, Claude Code adapter, markdown renderer, path-rewrite transforms, stdio MCP server, portagenty workspace scoping, and per-file list cache all landed. See the agents + portagenty page for wiring it into Claude Code / opencode, and the Claude Code adapter notes for the v0.1 record-type contract.