Export your Claude Code CLI sessions to Markdown files for viewing in Obsidian or any other markdown editor.
This Ruby script reads your Claude Code session data from the local storage directory (~/.claude/) and exports each session as a well-formatted Markdown file. The exported files include:
- Session metadata (title, creation date, directory, etc.)
- Full conversation history between you and Claude
- Tool usage and results
- Thinking and reasoning blocks (collapsible)
- Proper formatting for easy reading in Obsidian
- Incremental Export: Only exports sessions that haven't been exported before
- Obsidian Compatible: Generated markdown works seamlessly with Obsidian
- Rich Formatting: Includes frontmatter, timestamps, and organized conversation flow
- No Duplicates: Tracks exported sessions to avoid re-exporting
- Ruby 3.0 or higher
- Claude Code CLI installed and configured
- An Obsidian vault (or any directory for markdown files)
- Clone or download this repository
- Install dependencies:
bundle install- Copy the example environment file and configure it:
cp .env.example .env- Edit
.envand set your Obsidian vault path:
OBSIDIAN_PATH=/path/to/your/obsidian/vault
CLAUDE_SESSIONS_SUBDIR=Claude Sessions # Optional, defaults to "Claude Sessions"
CLAUDE_STORAGE_PATH=~/.claude # Optional, defaults to ~/.claude
Run the export script:
ruby export.rbOr make it executable:
chmod +x export.rb
./export.rbYou can override environment variables with command line options:
ruby export.rb --help # Show all options
ruby export.rb -o /path/to/vault # Specify Obsidian path
ruby export.rb -c ~/.claude -s "My Sessions" # Custom storage and subdirectory
ruby export.rb --debug # Show backtraces on errors| Option | Short | Description |
|---|---|---|
--obsidian-path |
-o |
Path to Obsidian vault (overrides OBSIDIAN_PATH) |
--claude-storage-path |
-c |
Path to Claude storage (default: ~/.claude) |
--sessions-subdir |
-s |
Subdirectory for sessions (default: "Claude Sessions") |
--debug |
-d |
Show debug output including backtraces |
The script will:
- Read all sessions from
~/.claude/(or your custom CLAUDE_STORAGE_PATH) - Parse session history from
~/.claude/history.jsonl - Load session conversations from
~/.claude/projects/{project-path}/{sessionId}.jsonl - Check which sessions have already been exported
- Export new sessions to
<OBSIDIAN_PATH>/Claude Sessions/ - Track exported sessions to avoid duplicates
Starting Claude Code session export...
Obsidian path: /home/user/Documents/Obsidian
Output directory: /home/user/Documents/Obsidian/Claude Sessions
Successfully exported 3 new session(s):
- ses_431b70570ffetNNpEZ3cI5LQwQ
- ses_431a6c7a5ffeCKPQ9aAOzhFkkp
- ses_41d04ee29ffexfKgqz82X5XpTv
Done! Check your Obsidian vault at: /home/user/Documents/Obsidian/Claude Sessions
Each exported session is saved as a markdown file with the following structure:
---
title: Session Title
session_id: ses_xxxxx
slug: session-slug
created: 2024-01-17 12:30:00
updated: 2024-01-17 12:45:00
directory: /path/to/project
version: 1.0.0
tags: [claude-code, session]
---
# Session Title
**Session ID**: `ses_xxxxx`
**Created**: 2024-01-17 12:30:00
**Updated**: 2024-01-17 12:45:00
**Directory**: `/path/to/project`
---
## 👤 User
*2024-01-17 12:30:05*
User message here...
---
## 🤖 Assistant
*2024-01-17 12:30:15*
Assistant response here...
<details>
<summary>💭 Thinking</summary>
Thinking process...
</details>
---The project uses RSpec for testing:
bundle exec rspecTo run tests with verbose output:
bundle exec rspec --format documentation.
├── lib/
│ └── claude_code_session_exporter.rb # Main exporter class
├── spec/
│ ├── spec_helper.rb
│ └── claude_code_session_exporter_spec.rb
├── export.rb # CLI script
├── Gemfile
├── .env.example
├── .gitignore
└── README.md
- Session Discovery: The script reads
~/.claude/history.jsonlto find all session IDs and metadata - Session Loading: For each session, it locates the corresponding JSONL file in
~/.claude/projects/{project-path}/{sessionId}.jsonl - Message Parsing: The JSONL file is parsed line-by-line to extract all conversation messages (user and assistant)
- Content Extraction: Messages contain text, tool usage, thinking blocks, and other conversation elements
- Markdown Generation: Sessions are converted to markdown with YAML frontmatter and formatted conversation
- Export Tracking: A hidden
.exported_sessions.jsonfile tracks which sessions have been exported to avoid duplicates
Configuration can be set via environment variables (in .env) or command line options. CLI options take precedence over environment variables.
OBSIDIAN_PATH(required unless using-o): Path to your Obsidian vault or markdown directoryCLAUDE_SESSIONS_SUBDIR(optional): Subdirectory name within your vault (default: "Claude Sessions")CLAUDE_STORAGE_PATH(optional): Path to Claude Code storage directory (default: "~/.claude")
You can modify lib/claude_code_session_exporter.rb to customize:
- Markdown formatting
- Frontmatter fields
- How tool usage is displayed
- Thinking block styling
- Session title extraction logic
Make sure Claude Code is installed and you've run it at least once. The storage directory (~/.claude/) is created automatically by Claude Code when you first run it.
Check that your OBSIDIAN_PATH in .env points to an existing directory.
If you've just installed Claude Code, you may not have any sessions yet. Use Claude Code to have a conversation, then run the export script again.
MIT License - feel free to use and modify as needed.
Contributions are welcome! Please feel free to submit a Pull Request.