BuildWithMatija
  1. Home
  2. Blog
  3. AI
  4. Export Claude Code Session to Markdown: Recover Plans

Export Claude Code Session to Markdown: Recover Plans

Step-by-step guide to locate Claude Code .jsonl sessions, parse transcripts with Python, and export readable Markdown.

19th June 2026·Updated on:22nd June 2026··
AI
Export Claude Code Session to Markdown: Recover Plans

📚 Get Practical Development Guides

Join developers getting comprehensive guides, code examples, optimization tips, and time-saving prompts to accelerate their development workflow.

No spam. Unsubscribe anytime.

📄View markdown version
0

Frequently Asked Questions

About the author

Matija Žiberna

Matija Žiberna

Full-stack developer, co-founder

AboutResume

Self-taught full-stack developer sharing lessons from building software and startups.

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

Contents

  • Where Claude Code Stores Session Transcripts
  • Searching for the Right Session by Name
  • Setting Up the Session File for Inspection
  • Viewing the Raw Transcript
  • Exporting the Session to Readable Markdown
  • Reading and Searching the Exported File
  • Filtering Down to the Relevant Sections
  • Resuming the Original Session
  • Using the Built-In Export Command
  • Quick Reference Script
  • FAQ
  • Wrapping Up
On this page:
  • Where Claude Code Stores Session Transcripts
  • Searching for the Right Session by Name
  • Setting Up the Session File for Inspection
  • Viewing the Raw Transcript
  • Exporting the Session to Readable Markdown
Build with Matija logo

Build with Matija

Modern websites, content systems, and AI workflows built for long-term growth.

Services

  • Headless CMS Websites
  • Next.js & Headless CMS Advisory
  • AI Systems & Automation
  • Website & Content Audit

Resources

  • Case Studies
  • How I Work
  • Blog
  • Topics
  • CMS Hub
  • E-commerce Hub
  • B2B Website Strategy
  • Dashboard

Headless CMS

  • Payload CMS Developer
  • CMS Migration
  • Multi-Tenant CMS
  • Payload vs Sanity
  • Payload vs WordPress
  • Payload vs Contentful

Get in Touch

Ready to modernize your stack? Let's talk about what you're building.

Book a discovery callContact me →
© 2026Build with Matija•All rights reserved•Privacy Policy•Terms of Service
BuildWithMatija
Get In Touch

If you've lost track of a Claude Code session and need to recover a plan, a todo list, or a specific decision buried in the transcript, you can find it by searching the local .jsonl session files Claude Code stores on disk, then export that file into a readable Markdown document. This guide walks through locating the right session by agent or plan name, inspecting the raw transcript, and converting it into something you can actually read and search.

I ran into this last week while working on a multi-step product onboarding flow for an Etsy-style storefront. I'd planned out a whole approach in a Claude Code session days earlier, moved on to other work, and then needed to go back and check exactly what we'd agreed on. The session was still on disk, just buried inside a raw JSONL file with every tool call and tool result mixed in with the actual plan. Here's the workflow I used to dig it out.

Where Claude Code Stores Session Transcripts

Claude Code keeps local session transcripts at:

bash
~/.claude/projects/<encoded-project-path>/<session-id>.jsonl

The project path gets encoded by replacing slashes with dashes. So a project at:

bash
/home/matija/etsy-slo

ends up stored under:

bash
~/.claude/projects/-home-matija-etsy-slo/

and an individual session file looks like this:

bash
~/.claude/projects/-home-matija-etsy-slo/d54cb123-ae10-48f3-9e8f-bb805061cc88.jsonl

Each line in that file is a JSON object representing one message, tool call, or tool result from the session.

Searching for the Right Session by Name

If you remember the agent name or plan name but not the session ID, grep across the whole Claude folder:

bash
grep -RIn 'multi-step-product-onboarding' ~/.claude/projects ~/.claude/tasks ~/.claude/plans 2>/dev/null

When you know which project the session belongs to, narrow the search to that project folder to cut down on noise:

bash
grep -RIn 'multi-step-product-onboarding' ~/.claude/projects/-home-matija-etsy-slo ~/.claude/tasks ~/.claude/plans 2>/dev/null

The match will point you to a .jsonl file. That's your session.

Setting Up the Session File for Inspection

Once you've found the file, store its path in a variable so the rest of the commands stay short:

bash
FILE="/home/matija/.claude/projects/-home-matija-etsy-slo/d54cb123-ae10-48f3-9e8f-bb805061cc88.jsonl"

Confirm it exists before doing anything else:

bash
ls -lh "$FILE"

Viewing the Raw Transcript

You can page through the file directly:

bash
less "$FILE"

Add line numbers if you'll need to reference specific spots later:

bash
nl -ba "$FILE" | less

Or jump straight to a line range you already suspect is relevant:

bash
nl -ba "$FILE" | sed -n '80,220p'

This works for a quick look, but raw JSONL is awkward to read for anything longer than a few lines, since every message is wrapped in tool call metadata and JSON escaping. For anything beyond a quick peek, export it.

Exporting the Session to Readable Markdown

This Python script reads the JSONL file line by line, pulls out the role and content of each message, and prints it as Markdown with clear ## USER / ## ASSISTANT headers. It also surfaces tool calls and tool results so you can see what Claude actually ran, not just what it said.

python
# File: export_session.py
import json

file = "/home/matija/.claude/projects/-home-matija-etsy-slo/d54cb123-ae10-48f3-9e8f-bb805061cc88.jsonl"

with open(file, "r", encoding="utf-8") as f:
    for line in f:
        try:
            obj = json.loads(line)
        except Exception:
            continue

        msg = obj.get("message") or {}
        role = msg.get("role")
        content = msg.get("content")

        if not role or not content:
            continue

        print(f"\n\n## {role.upper()}\n")

        if isinstance(content, str):
            print(content)

        elif isinstance(content, list):
            for item in content:
                if not isinstance(item, dict):
                    continue

                if item.get("type") == "text":
                    print(item.get("text", ""))

                elif item.get("type") == "tool_use":
                    print("\n```txt")
                    print("TOOL:", item.get("name"))
                    print(item.get("input"))
                    print("```")

                elif item.get("type") == "tool_result":
                    print("\n```txt")
                    print("TOOL RESULT:")
                    result = item.get("content")
                    if isinstance(result, str):
                        print(result[:4000])
                    else:
                        print(str(result)[:4000])
                    print("```")

Each tool result gets truncated to 4000 characters. That keeps massive file dumps or long command outputs from blowing up the export, while still leaving enough context to understand what happened at each step.

Run it and redirect the output into a Markdown file:

bash
python3 export_session.py > /home/matija/etsy-slo/multi-step-product-onboarding-session.md

Reading and Searching the Exported File

Open the Markdown export the same way you'd read any long document:

bash
less /home/matija/etsy-slo/multi-step-product-onboarding-session.md

Inside less, search forward with / followed by your term:

txt
/onboarding

Press n to jump to the next match. This is usually faster than scrolling once you know roughly what you're looking for.

Filtering Down to the Relevant Sections

A full session export can run thousands of lines once tool calls and results are included. To pull out just the parts related to your plan, grep the exported Markdown for the keywords that matter:

bash
grep -niE 'multi|step|product|onboarding|plan|todo|task|approach|implement' /home/matija/etsy-slo/multi-step-product-onboarding-session.md | head -100

Save the matches to their own file if you want something you can hand off or reference later without scrolling through the full export:

bash
grep -niE 'multi|step|product|onboarding|plan|todo|task|approach|implement' /home/matija/etsy-slo/multi-step-product-onboarding-session.md > /home/matija/etsy-slo/multi-step-product-onboarding-matches.md

Then open the smaller file:

bash
cat /home/matija/etsy-slo/multi-step-product-onboarding-matches.md

Resuming the Original Session

If you want to pick the conversation back up instead of just reading it, Claude Code can resume a session directly using its ID. Run the resume command from the same project directory the session was originally created in, since the working directory affects what Claude can see and access:

bash
cd /home/matija/etsy-slo
claude --resume d54cb123-ae10-48f3-9e8f-bb805061cc88

Using the Built-In Export Command

Claude Code also ships with a built-in export command you can run from inside an active session:

txt
/export session-name.md

This produces a readable Markdown export directly, without writing or running the Python script above. It's the quickest path when you're exporting the session you're currently in. The manual JSONL parsing approach earns its place when you need to recover a session you're no longer inside of, want full control over formatting, or need to script the export across many sessions at once.

Quick Reference Script

Here's the whole workflow as one block, ready to adapt for a different session:

bash
# File: export_and_view.sh
FILE="/home/matija/.claude/projects/-home-matija-etsy-slo/d54cb123-ae10-48f3-9e8f-bb805061cc88.jsonl"
OUT="/home/matija/etsy-slo/multi-step-product-onboarding-session.md"

python3 - <<'PY' > "$OUT"
import json

file = "/home/matija/.claude/projects/-home-matija-etsy-slo/d54cb123-ae10-48f3-9e8f-bb805061cc88.jsonl"

with open(file, "r", encoding="utf-8") as f:
    for line in f:
        try:
            obj = json.loads(line)
        except Exception:
            continue

        msg = obj.get("message") or {}
        role = msg.get("role")
        content = msg.get("content")

        if not role or not content:
            continue

        print(f"\n\n## {role.upper()}\n")

        if isinstance(content, str):
            print(content)
        elif isinstance(content, list):
            for item in content:
                if isinstance(item, dict) and item.get("type") == "text":
                    print(item.get("text", ""))
PY

less "$OUT"

Swap in your own FILE path and OUT destination, and this gives you a one-shot export-and-read command for any session.

FAQ

Where exactly does Claude Code store session files on disk? Under ~/.claude/projects/<encoded-project-path>/<session-id>.jsonl, where the encoded project path replaces every slash in your project's absolute path with a dash.

How do I find a session if I only remember a rough description, not the exact agent name? Grep with a broader set of keywords across ~/.claude/projects, ~/.claude/tasks, and ~/.claude/plans. Partial matches on distinctive words from the plan usually surface the right file.

Why does the export script truncate tool results to 4000 characters? Long tool outputs, like full file dumps or verbose command logs, can make the exported Markdown unwieldy. Truncating keeps the file readable while preserving enough of each result to follow the session's logic.

Can I export a session I'm not currently inside of? Yes. The Python script works against any .jsonl file on disk regardless of whether that session is active. The built-in /export command only works for the session you're currently running.

Does resuming a session require being in the original project folder? Yes. Claude Code's resume command ties the session to the working directory it was created in, so running claude --resume from a different folder can change what Claude sees and is able to do.

Wrapping Up

Recovering a Claude Code plan you thought you'd lost comes down to three steps: locate the right .jsonl file by grepping for a name you remember, convert it into Markdown so it's actually readable, and search that export for the specific decision or task you need. Once you've done this a couple of times, the whole loop takes a couple of minutes, and you stop worrying about losing context between sessions.

Let me know in the comments if you have questions, and subscribe for more practical development guides.

Thanks, Matija