MemoryLake
Back to all articles
TutorialSeptember 21, 2026·11 min read

How to Export a Claude Code Session So Another Machine Can Pick It Up (2026 Guide)

You spent three hours on a migration in Claude Code on your work laptop. Tomorrow you are on a different machine. The obvious move is to find the session file, copy it across, and resume.

That move fails, and it fails in the least helpful way possible: Claude Code reports that no conversation matches the ID. Not a warning, not a partial load — not found. The documentation explains why, and the reason is deliberate.

This guide covers what /export actually produces, what the transcript file is and is not for, why a hand-copied transcript is rejected on purpose, and what to carry instead so the next machine can pick up where you left off.

Why copying the session file does not work

A Claude Code session is a saved conversation tied to a project directory. By default the transcript lives as JSONL at ~/.claude/projects/<project>/<session-id>.jsonl, where the project segment is your working directory path with non-alphanumeric characters replaced by hyphens.

So the file is right there, and copying it looks like the answer. Here is the documented behaviour when you do:

"The cross-project search resolves the ID only when exactly one other project holds a transcript with messages for it, so a hand-copied duplicate makes Claude Code report not-found rather than resume an arbitrary copy."

Read that twice. The lookup is not failing to find your copy. It is finding two candidates and refusing to guess. Copying the file is the action that breaks the resume, and the more careful you were — copying rather than moving, keeping the original safe — the more certainly you land in the failure.

There is a second reason not to build on that file, stated just as plainly:

"The entry format is internal to Claude Code and changes between versions, so scripts that parse these files directly can break on any release. To build on session data, use /export or the script interfaces instead."

And a third thing worth knowing before you plan around the file at all: transcripts age out. The retention sweep runs on a thirty-day default, adjustable through a settings key. A transcript is a working artifact, not an archive.

This is a different problem from rewinding a session to an earlier point, which stays inside one machine and one session, and a different problem again from forking a remote session from the Claude app, where the copy is made by the tool and registered properly. Here the question is how a conversation's substance reaches a machine that never had it.

What people try instead

Copying the JSONL and resuming by ID. Covered above. The duplicate is what causes the not-found.

Copying the whole project directory under ~/.claude/projects. Same mechanism, larger blast radius. You now have two directories holding transcripts with messages for the same IDs.

Writing a script that parses the JSONL into a summary. This works until the next release. The format is explicitly internal and documented as changing between versions.

Resuming and hoping the launch configuration comes with it. It does not, and the list of what needs passing again is specific: "If the session depended on --mcp-config, --settings, --plugin-dir, --fallback-model, or directories added with --add-dir, pass them again when you resume." Directories added mid-session with the add-directory command are not restored either. Settings files are re-read at launch, so anything living in them does come back.

Assuming everything in the conversation survives. Most of it does. A resumed session restores the full history including tool calls and results. But a tool still running when the previous process ended "doesn't finish or run again when you resume; Claude continues without its output." If your last action was a long build, its result is not in the resumed conversation.

Relying on a summary you did not ask for. On a Pro or Max plan, resuming a session that has been inactive for more than about an hour and is over 100,000 tokens opens a dialog first. One option runs the compaction immediately and "replaces the history with the summary, your most recent exchanges, and up to five recently read files." That is a reasonable default and a poor archive, for the same reasons that make choosing what survives compaction a deliberate act.

The Fix: Export a readable record, then carry the decisions separately

Two artifacts do two different jobs. Export gives you the conversation as a document. The decisions inside it need to travel as facts, not as a transcript.

Step 1: Export the conversation while the session is still open

Run the export command inside the session. It opens a menu that lets you copy the conversation to the clipboard or save it as a plain-text file, with messages and tool outputs rendered as readable text. Pass a filename and it skips the menu and writes straight to that file.

What you get is described precisely: "/export produces a rendered transcript for a person to read." That is the right expectation. It is a document you or a colleague can read on any machine, in any editor, with no dependency on a Claude Code version.

Do this before you stop for the day rather than after. The export runs against the live conversation, and it is the one step that gets harder once the retention sweep or a compaction dialog has had a turn.

Step 2: Pull the decisions out of the export into standalone facts

Open the exported file and read it for conclusions rather than narrative. You are looking for the small number of lines that would change what someone does tomorrow.

Three kinds are worth extracting. Decisions that were argued and settled — the migration runs before the backfill, and the reason. Constraints discovered the hard way — this table cannot be altered while the job is running. Vocabulary the next session will otherwise get wrong — what your team means by a tenant.

Write each as one sentence that stands on its own, without reference to the conversation. "We decided to run the migration first" is not portable. "The migration must run before the backfill because the backfill reads the new column" is. The test is whether the sentence still makes sense to someone who never saw the session, which is the same test that separates an indexed log of what happened from usable memory.

Step 3: Resume by ID on the original machine, start fresh on the new one

On the machine that ran the session, resume by ID from any directory. The lookup searches the current project and its worktrees first, then every other project on the machine, so a session that started elsewhere or moved still resolves — provided exactly one transcript holds messages for it. Pass the launch flags the session depended on.

On the new machine, do not try to resume. Start a session and give it the facts from Step 2. That is the whole handoff, and it is faster than it sounds, because the facts are short by construction.

If you want the export file itself available on both machines, keep it wherever you keep working documents. Just keep it out of ~/.claude/projects, because a copy of a transcript in a second project directory is exactly the duplicate that causes the not-found.

Setting this up in MemoryLake

Step 2 produces a set of one-sentence facts that need to be readable from whichever machine you sit at next. MemoryLake is a place to put them so the handoff does not depend on a file you remembered to sync.

You write the entries yourself, in your own words. Nothing is read out of, written to, or deleted from Claude Code's transcript files, ~/.claude, or any vendor's store.

Step 1: Create an API key

Sign in and generate a key from the dashboard. The key is what lets an agent on any machine read the entries, which is the part a copied file cannot give you.

The MemoryLake console showing the API keys screen, where a new key is created and copied for use in an agent
The MemoryLake console showing the API keys screen, where a new key is created and copied for use in an agent

Step 2: Upload your first memories

Add the decisions, constraints, and vocabulary from Step 2 above, one fact per entry. Keep the exported transcript as the long-form record; the entries are the part that needs to be read at the start of the next session.

The MemoryLake workspace with the first documents uploaded, listing each file as it becomes searchable memory
The MemoryLake workspace with the first documents uploaded, listing each file as it becomes searchable memory

Step 3: Connect your AI & agents

Point the agents on both machines at the same workspace. A new session then starts with the settled decisions already available, instead of starting from a conversation it cannot open.

The MemoryLake integrations screen listing the AI clients and agent frameworks that can be connected to the memory layer
The MemoryLake integrations screen listing the AI clients and agent frameworks that can be connected to the memory layer

What this changes in practice

The first change is that the handoff stops being a file operation. You are no longer trying to make one machine's local state appear on another machine, which is a problem the tool deliberately refuses to solve for you.

The second is that the two artifacts stop competing. The export is a readable record of how you got somewhere — useful in a pull request description, a handover note, or an incident writeup. The facts are what the next session needs loaded. Trying to make one artifact do both jobs is what produces the giant transcript nobody reads and the new session that knows nothing.

The third is that version churn stops mattering. A rendered export is plain text forever. A JSONL transcript is an internal format that is documented as changing between releases, so anything you built on it is a maintenance commitment you did not mean to take on.

There is also a privacy dimension worth naming, since it changes what you should export at all. Transcript writes can be suppressed entirely through an environment variable, and a single non-interactive run can be told not to persist its session. If you work in a context where conversations should not sit on disk, those switches exist — and it means the export step becomes the only record, so do it deliberately. This is a different artifact from the account-level data export you request from Claude, which covers the consumer apps rather than the CLI's local transcripts.

Teams that work across a laptop and a desktop tend to hit this fastest, and the fix is the same one that stops context going missing when you change machines: the durable part has to live somewhere neither machine owns.

Best practices for moving work between machines

Export at the end of a working session, not at the start of the next one. The export is a live operation against the current conversation. Retention sweeps, compaction dialogs, and simple forgetfulness all sit between you and yesterday's session.

Never place a transcript copy inside a second project directory. This is the single action most likely to make a resume fail. Keep exports with your documents.

Write the launch flags down next to the export. A resumed session does not restore the configuration flags it was started with. A one-line note saying which flags the session needed saves the twenty minutes of working out why the tools are missing.

Treat the thirty-day retention as the real deadline. The default sweep is thirty days and it is a settings key, not a promise. Anything you want in six months needs to be an export or a fact, not a transcript.

Name your sessions. A named session resolves by name across the repository and its worktrees, which makes the original machine's resume trivial and makes your notes legible. An unnamed session is an ID you will not recognise.

Separate "what we decided" from "what we discussed." The first is short and belongs in the handoff. The second is long and belongs in the export. Sessions that lose the thread usually lost it because the project's decisions were never written anywhere outside the conversation.

Use a summary request rather than a parser. If you want structured output from an old session, send it a follow-up prompt by ID and capture the structured response. That is a supported interface. Parsing the JSONL is not.

Conclusion

Claude Code stores your conversation in a file you can see, which makes copying it feel like the obvious way to move work. It is the one approach the tool is built to refuse, and it refuses by reporting not-found rather than resuming a copy it cannot verify.

The supported path is smaller and more durable. Export the conversation as a readable document while the session is open. Pull the handful of decisions, constraints, and terms out of it as standalone sentences. Resume by ID on the machine that has the transcript, and start fresh on the machine that does not, with the facts already loaded.

That split also happens to be what lets more than one person pick the work up, which is the same reason sharing context between sessions is a writing problem before it is a tooling problem.

Frequently asked questions

Can I copy a Claude Code session file to another computer and resume it?

Not reliably, and the failure is by design. The documentation states that the cross-project search resolves a session ID "only when exactly one other project holds a transcript with messages for it, so a hand-copied duplicate makes Claude Code report not-found rather than resume an arbitrary copy."

What does /export actually produce?

A rendered transcript for a person to read. It opens a menu to copy the conversation to your clipboard or save it as a plain-text file, with messages and tool outputs as readable text, and passing a filename writes directly to that file.

Where are Claude Code transcripts stored?

By default as JSONL at ~/.claude/projects/<project>/<session-id>.jsonl, where the project segment is the working directory path with non-alphanumeric characters replaced by hyphens. A converted name over 200 characters is truncated and given a hash of the full path.

Can I parse the JSONL transcript myself?

You can, but the documentation advises against building on it: the entry format "is internal to Claude Code and changes between versions, so scripts that parse these files directly can break on any release."

Does resuming a session restore everything?

The conversation history comes back in full, including tool calls and results, along with the session's agent, permission mode in most cases, and an active goal. Launch flags such as the MCP configuration, settings, plugin directory, fallback model, and added directories must be passed again.

How long do transcripts stay on disk?

The retention sweep uses a thirty-day default, adjustable through a settings key. Deleting a background session with the remove command leaves its transcript on disk and still resumable by ID.