ccexport 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/CHANGELOG.md +23 -0
- data/CLAUDE.md +156 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +21 -0
- data/README.md +534 -0
- data/Rakefile +8 -0
- data/bin/ccexport +95 -0
- data/ccexport.gemspec +49 -0
- data/exe/ccexport +156 -0
- data/lib/assets/prism-bash.js +1 -0
- data/lib/assets/prism-json.js +1 -0
- data/lib/assets/prism-markdown.js +1 -0
- data/lib/assets/prism-python.js +1 -0
- data/lib/assets/prism-typescript.js +1 -0
- data/lib/assets/prism-yaml.js +1 -0
- data/lib/assets/prism.css +1 -0
- data/lib/assets/prism.js +16 -0
- data/lib/ccexport/version.rb +5 -0
- data/lib/ccexport.rb +9 -0
- data/lib/claude_conversation_exporter.rb +1177 -0
- data/lib/markdown_code_block_parser.rb +268 -0
- data/lib/secret_detector.rb +89 -0
- data/lib/templates/default.html.erb +241 -0
- data/lib/templates/github.html.erb +369 -0
- data/lib/templates/solarized.html.erb +467 -0
- metadata +101 -0
data/README.md
ADDED
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
# Claude Code Conversation Exporter (Ruby)
|
|
2
|
+
|
|
3
|
+
A Ruby tool to export Claude Code conversations to GitHub-flavored Markdown format, or using templates, styled to look similar to Claude Desktop conversations, GitHub or, really any other style, for easy reading.
|
|
4
|
+
|
|
5
|
+
<noai>
|
|
6
|
+
I created this tool because, as I'm exploring using agentic coding tools, I've found myself wanting to share examples with friends and colleagues, so we can learn from each other. I have tried to fully vibe code this project, but I have, on occasion, gone rogue and hand coded tooling to help me and Claude better understand the JSONL structure or fix issues that it seemed to struggle with. I've used other tools, like Claude Desktop with Opus 4.1 and the humble web search. In fact, the very beginning of this project was conducted in Claude Desktop where I asked it to research tooling that already does what I was trying to do.
|
|
7
|
+
</noai>
|
|
8
|
+
|
|
9
|
+
> **⚠️ Security Notice**: This tool includes automatic secret detection, but **always review your exports before sharing**. You are responsible for ensuring no sensitive information is included in shared conversation exports.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### Core Functionality
|
|
14
|
+
- Exports complete Claude Code conversations including prompts, responses, and tool calls
|
|
15
|
+
- GitHub-flavored Markdown output optimized for readability
|
|
16
|
+
- Automatically discovers Claude Code session files
|
|
17
|
+
- Claude Desktop-inspired formatting with user/assistant message indicators
|
|
18
|
+
- Comprehensive RSpec test suite with 96 tests
|
|
19
|
+
- HTML Preview Generation: Convert Markdown to HTML with GitHub styling and embedded syntax highlighting
|
|
20
|
+
|
|
21
|
+
### Enhanced Tool Formatting
|
|
22
|
+
- **Write Tool**: Shows relative file paths in summary with syntax-highlighted code blocks
|
|
23
|
+
- **Bash Tool**: Displays command descriptions in summary with bash syntax highlighting
|
|
24
|
+
- **Edit Tool**: Before/After sections showing old and new code with syntax highlighting
|
|
25
|
+
- **TodoWrite Tool**: Emoji-enhanced task lists (✅ completed, 🔄 in progress, ⏳ pending)
|
|
26
|
+
|
|
27
|
+
### Advanced Features
|
|
28
|
+
- **Universal Path Relativization**: All absolute project paths converted to relative paths
|
|
29
|
+
- **Smart Tool Pairing**: Automatically pairs tool_use with corresponding tool_result messages
|
|
30
|
+
- **Embedded Syntax Highlighting**: Self-contained HTML exports with Prism.js supporting Ruby, JavaScript, Python, TypeScript, JSON, Markdown, YAML, Bash and more
|
|
31
|
+
- **Robust Message Processing**: Handles edge cases like tool-only messages and system filtering
|
|
32
|
+
- **Date Filtering**: Filter conversations by date range or today only (timezone-aware)
|
|
33
|
+
- **Multiple Session Combining**: Automatically combines multiple sessions into single chronologically ordered output
|
|
34
|
+
- **Thinking Message Support**: Displays thinking content with blockquotes and special emoji (🤖💭)
|
|
35
|
+
- **Skip Logging**: Comprehensive JSONL logs of skipped messages during export with reasons
|
|
36
|
+
- **Message ID Tracking**: HTML comments with Claude message IDs for cross-referencing
|
|
37
|
+
- **Individual File Processing**: Process specific JSONL files instead of scanning directories
|
|
38
|
+
- **Secret Detection & Redaction**: Automatic detection and redaction of API keys, tokens, and other secrets using TruffleHog's industry-standard detection engine
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
### Quick Install (If you already have Ruby)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
gem install ccexport
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Full Setup (For non-Ruby developers)
|
|
49
|
+
|
|
50
|
+
If you don't have Ruby installed or aren't familiar with Ruby development, follow these steps:
|
|
51
|
+
|
|
52
|
+
#### 1. Install Package Manager (if needed)
|
|
53
|
+
|
|
54
|
+
**macOS users:** If you don't have Homebrew installed:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Install Homebrew
|
|
58
|
+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
59
|
+
|
|
60
|
+
# Follow the "Next steps" instructions shown after installation to add Homebrew to your PATH
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Windows users with WSL (Windows Subsystem for Linux):**
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# First, ensure you're running Ubuntu/Debian in WSL
|
|
67
|
+
# Install Homebrew for Linux
|
|
68
|
+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
69
|
+
|
|
70
|
+
# Add Homebrew to your PATH (replace USERNAME with your actual username)
|
|
71
|
+
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bashrc
|
|
72
|
+
source ~/.bashrc
|
|
73
|
+
|
|
74
|
+
# Install build dependencies
|
|
75
|
+
sudo apt-get update
|
|
76
|
+
sudo apt-get install build-essential
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Ubuntu/Debian users (native Linux):**
|
|
80
|
+
|
|
81
|
+
**Recommended: Use Homebrew for easier dependency management**
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Install Homebrew for Linux (same as WSL instructions)
|
|
85
|
+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
86
|
+
|
|
87
|
+
# Add Homebrew to your PATH
|
|
88
|
+
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bashrc
|
|
89
|
+
source ~/.bashrc
|
|
90
|
+
|
|
91
|
+
# Install build dependencies
|
|
92
|
+
sudo apt-get update
|
|
93
|
+
sudo apt-get install build-essential
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
<details>
|
|
97
|
+
<summary>Alternative: System package manager (more complex dependency management)</summary>
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Install basic dependencies
|
|
101
|
+
sudo apt-get update
|
|
102
|
+
sudo apt-get install curl git build-essential
|
|
103
|
+
|
|
104
|
+
# Note: You'll need to manually install TruffleHog and cmark-gfm
|
|
105
|
+
# TruffleHog: https://github.com/trufflesecurity/trufflehog#installation
|
|
106
|
+
# cmark-gfm: You may need to build from source or find alternative packages
|
|
107
|
+
```
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
#### 2. Install Ruby Version Manager
|
|
111
|
+
|
|
112
|
+
**If you don't have a Ruby version manager yet, we recommend rbenv:**
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# macOS with Homebrew
|
|
116
|
+
brew install rbenv ruby-build
|
|
117
|
+
|
|
118
|
+
# Ubuntu/Debian
|
|
119
|
+
sudo apt install rbenv
|
|
120
|
+
|
|
121
|
+
# Add rbenv to your shell
|
|
122
|
+
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
|
|
123
|
+
# or for zsh users:
|
|
124
|
+
echo 'eval "$(rbenv init -)"' >> ~/.zshrc
|
|
125
|
+
|
|
126
|
+
# Restart your terminal or run:
|
|
127
|
+
source ~/.bashrc # or ~/.zshrc
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**If you already use a different Ruby version manager:**
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary>RVM Users</summary>
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Install latest Ruby 3.4
|
|
137
|
+
rvm install 3.4
|
|
138
|
+
rvm use 3.4 --default
|
|
139
|
+
```
|
|
140
|
+
</details>
|
|
141
|
+
|
|
142
|
+
<details>
|
|
143
|
+
<summary>asdf Users</summary>
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Add Ruby plugin if not already added
|
|
147
|
+
asdf plugin add ruby
|
|
148
|
+
|
|
149
|
+
# Install latest Ruby 3.4
|
|
150
|
+
asdf install ruby latest:3.4
|
|
151
|
+
asdf global ruby latest:3.4
|
|
152
|
+
```
|
|
153
|
+
</details>
|
|
154
|
+
|
|
155
|
+
<details>
|
|
156
|
+
<summary>mise Users (formerly rtx)</summary>
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# Install latest Ruby 3.4
|
|
160
|
+
mise install ruby@3.4
|
|
161
|
+
mise global ruby@3.4
|
|
162
|
+
```
|
|
163
|
+
</details>
|
|
164
|
+
|
|
165
|
+
#### 3. Install Ruby 3.4 (rbenv users)
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Install latest Ruby 3.4
|
|
169
|
+
rbenv install 3.4.3
|
|
170
|
+
rbenv global 3.4.3
|
|
171
|
+
|
|
172
|
+
# Verify installation
|
|
173
|
+
ruby --version # Should show Ruby 3.4.3
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### 4. Install ccexport and dependencies
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Install the gem
|
|
180
|
+
gem install ccexport
|
|
181
|
+
|
|
182
|
+
# Install required external tools (if you installed Homebrew)
|
|
183
|
+
brew install trufflehog cmark-gfm
|
|
184
|
+
|
|
185
|
+
# If you're using system package managers instead of Homebrew:
|
|
186
|
+
# - TruffleHog: https://github.com/trufflesecurity/trufflehog#installation
|
|
187
|
+
# - cmark-gfm: May require building from source on some Linux distributions
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### From Source (Development)
|
|
191
|
+
|
|
192
|
+
1. Clone this repository
|
|
193
|
+
2. Install dependencies: `bundle install`
|
|
194
|
+
3. Install TruffleHog for secret detection: `brew install trufflehog`
|
|
195
|
+
|
|
196
|
+
### Prerequisites Summary
|
|
197
|
+
|
|
198
|
+
- **Ruby**: 3.0.0 or higher (3.4.3 recommended)
|
|
199
|
+
- **TruffleHog**: For secret detection ([installation guide](https://github.com/trufflesecurity/trufflehog#installation))
|
|
200
|
+
- **cmark-gfm**: For HTML preview generation (`brew install cmark-gfm` on macOS)
|
|
201
|
+
|
|
202
|
+
## Usage
|
|
203
|
+
|
|
204
|
+
### Simple Usage
|
|
205
|
+
|
|
206
|
+
Run the exporter in any directory where you've used Claude Code:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Basic usage - export all conversations
|
|
210
|
+
ccexport
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Ruby API Usage
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
require 'ccexport'
|
|
217
|
+
|
|
218
|
+
ClaudeConversationExporter.export
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Command Line Usage
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Basic usage - export all conversations
|
|
225
|
+
ccexport
|
|
226
|
+
|
|
227
|
+
# Filter by date range
|
|
228
|
+
ccexport --from 2024-01-01 --to 2024-01-31
|
|
229
|
+
|
|
230
|
+
# Filter using timestamp format (copy from --timestamps output)
|
|
231
|
+
ccexport --from "August 09, 2025 at 06:03:43 PM"
|
|
232
|
+
|
|
233
|
+
# Export only today's conversations
|
|
234
|
+
ccexport --today
|
|
235
|
+
|
|
236
|
+
# Export from different project directory
|
|
237
|
+
ccexport --in /path/to/project
|
|
238
|
+
|
|
239
|
+
# Custom output directory
|
|
240
|
+
ccexport --out /path/to/output
|
|
241
|
+
|
|
242
|
+
# Export to specific markdown file with preview
|
|
243
|
+
ccexport --out myconversation.md --preview
|
|
244
|
+
|
|
245
|
+
# Include timestamps
|
|
246
|
+
ccexport --timestamps
|
|
247
|
+
|
|
248
|
+
# Generate HTML preview and open in browser
|
|
249
|
+
ccexport --preview
|
|
250
|
+
|
|
251
|
+
# Generate HTML preview without opening browser
|
|
252
|
+
ccexport --preview --no-open
|
|
253
|
+
|
|
254
|
+
# Use custom template
|
|
255
|
+
ccexport --preview --template mytemplate
|
|
256
|
+
|
|
257
|
+
# Use GitHub template
|
|
258
|
+
ccexport --preview --template github
|
|
259
|
+
|
|
260
|
+
# Process specific JSONL file
|
|
261
|
+
ccexport --jsonl /path/to/conversation.jsonl --out specific-conversation.md
|
|
262
|
+
|
|
263
|
+
# Silent mode (suppress all output)
|
|
264
|
+
ccexport --silent
|
|
265
|
+
|
|
266
|
+
# Complex example: custom project, date range, output, timestamps, and preview
|
|
267
|
+
ccexport --in /path/to/project --from 2024-01-15 --out ./my-exports --timestamps --preview
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
#### Command Line Options
|
|
271
|
+
|
|
272
|
+
- `--in PATH`: Project path to export conversations from (default: current directory)
|
|
273
|
+
- `--from DATE`: Filter messages from this date (YYYY-MM-DD or timestamp format from --timestamps output)
|
|
274
|
+
- `--to DATE`: Filter messages to this date (YYYY-MM-DD or timestamp format from --timestamps output)
|
|
275
|
+
- `--today`: Filter messages from today only (in your local timezone)
|
|
276
|
+
- `--out PATH`: Custom output directory or specific file path (supports relative paths, use .md extension for specific file)
|
|
277
|
+
- `--timestamps`: Show precise timestamps with each message for easy reference
|
|
278
|
+
- `--preview`: Generate HTML preview and open in browser automatically
|
|
279
|
+
- `--no-open`: Generate HTML preview without opening in browser (requires --preview)
|
|
280
|
+
- `--template NAME_OR_PATH`: HTML template name (from templates dir) or file path (default: default)
|
|
281
|
+
- `--jsonl FILE`: Process a specific JSONL file instead of scanning directories
|
|
282
|
+
- `-s`, `--silent`: Silent mode - suppress all output except errors
|
|
283
|
+
- `--help`: Show usage information
|
|
284
|
+
|
|
285
|
+
### Custom Usage
|
|
286
|
+
|
|
287
|
+
```ruby
|
|
288
|
+
require_relative 'lib/claude_conversation_exporter'
|
|
289
|
+
|
|
290
|
+
# Export from specific project path to custom output directory
|
|
291
|
+
exporter = ClaudeConversationExporter.new('/path/to/project', 'my-conversations')
|
|
292
|
+
result = exporter.export
|
|
293
|
+
|
|
294
|
+
puts "Exported #{result[:sessions_exported]} conversations"
|
|
295
|
+
puts "Total messages: #{result[:total_messages]}"
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Available Templates
|
|
299
|
+
|
|
300
|
+
The exporter includes several built-in templates:
|
|
301
|
+
|
|
302
|
+
- **`default`**: Clean, modern styling with rounded corners and a warm color palette
|
|
303
|
+
- **`github`**: Mimics GitHub's markdown rendering with GitHub's official color scheme and typography
|
|
304
|
+
- **`solarized`**: Beautiful Solarized color scheme with automatic light/dark mode detection based on user's system preference
|
|
305
|
+
|
|
306
|
+
You can also create custom templates by placing `.html.erb` files in the `lib/templates/` directory or by specifying a full file path.
|
|
307
|
+
|
|
308
|
+
## Output Format
|
|
309
|
+
|
|
310
|
+
The exporter creates Markdown files with:
|
|
311
|
+
|
|
312
|
+
- **Session metadata**: Session ID, timestamps (in local timezone), message counts
|
|
313
|
+
- **User messages**: Marked with 👤 User
|
|
314
|
+
- **Assistant messages**: Marked with 🤖 Assistant
|
|
315
|
+
- **Thinking messages**: Marked with 🤖💭 Assistant with blockquoted content
|
|
316
|
+
- **Tool use**: Marked with 🤖🔧 Assistant with collapsible sections and syntax highlighting
|
|
317
|
+
- **Multiple sessions**: Combined into single file with clear session separators
|
|
318
|
+
- **Relative paths**: All project paths converted to relative format
|
|
319
|
+
- **Message IDs**: HTML comments with Claude message IDs for reference
|
|
320
|
+
- **Skip logging**: Separate JSONL files documenting skipped messages with reasons
|
|
321
|
+
- **Secret detection logs**: JSONL files documenting detected and redacted secrets with security warnings
|
|
322
|
+
- **Clean formatting**: Optimized for GitHub and other Markdown viewers
|
|
323
|
+
|
|
324
|
+
### Example Output
|
|
325
|
+
|
|
326
|
+
For complete examples of the exported format, see the sample files in this repository:
|
|
327
|
+
|
|
328
|
+
- **[VIBE.md](VIBE.md)** - Full conversation export showing all features including tool use, thinking messages, message IDs, and formatting
|
|
329
|
+
- **[VIBE.html](VIBE.html)** - HTML preview version with default template styling and embedded Prism.js syntax highlighting
|
|
330
|
+
|
|
331
|
+
These files demonstrate real conversation exports with:
|
|
332
|
+
- Multiple message types (user, assistant, thinking)
|
|
333
|
+
- Tool use with collapsible sections and syntax highlighting
|
|
334
|
+
- Message ID HTML comments for cross-referencing
|
|
335
|
+
- Path relativization and clean formatting
|
|
336
|
+
- All advanced formatting features in action
|
|
337
|
+
|
|
338
|
+
The VIBE files showcase advanced features like collapsible tool sections, syntax highlighting, thinking message formatting, and proper message threading that would be impractical to show in README snippets.
|
|
339
|
+
|
|
340
|
+
## Skip Logging
|
|
341
|
+
|
|
342
|
+
The exporter automatically generates detailed logs of any messages that were skipped during processing. These logs are saved as JSONL files alongside your exported Markdown.
|
|
343
|
+
|
|
344
|
+
### Skip Log Features
|
|
345
|
+
|
|
346
|
+
- **Comprehensive tracking**: Every filtered message is logged with full context
|
|
347
|
+
- **Structured format**: JSONL format for easy programmatic analysis
|
|
348
|
+
- **Detailed reasons**: Specific explanations for why each message was skipped
|
|
349
|
+
- **Line references**: Exact line numbers from the original JSONL file
|
|
350
|
+
- **Full message data**: Complete JSON data for each skipped message
|
|
351
|
+
|
|
352
|
+
### Common Skip Reasons
|
|
353
|
+
|
|
354
|
+
- `leaf summary message`: Summary messages at conversation ends
|
|
355
|
+
- `api error or meta message`: System errors and metadata
|
|
356
|
+
- `empty or system-generated message`: Empty content or system messages
|
|
357
|
+
- `outside date range`: Messages filtered by --from/--to options (not logged)
|
|
358
|
+
|
|
359
|
+
### Example Skip Log Entry
|
|
360
|
+
|
|
361
|
+
```json
|
|
362
|
+
{"line":42,"reason":"api error or meta message","data":{"type":"meta","error":"rate_limit"}}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Message ID Tracking
|
|
366
|
+
|
|
367
|
+
Each message in the exported Markdown includes HTML comments with Claude message IDs for easy cross-referencing. You can see this in action throughout the [VIBE.md](VIBE.md) file where each message heading includes a comment like `<!-- msg_01RMr1PPo2ZiRmwHQzgYfovs -->`.
|
|
368
|
+
|
|
369
|
+
This allows you to:
|
|
370
|
+
- Track specific messages across different exports
|
|
371
|
+
- Reference messages in documentation or bug reports
|
|
372
|
+
- Correlate with Claude's internal logging if needed
|
|
373
|
+
|
|
374
|
+
## Secret Detection
|
|
375
|
+
|
|
376
|
+
**⚠️ IMPORTANT SECURITY NOTICE ⚠️**
|
|
377
|
+
|
|
378
|
+
The exporter automatically scans conversation content for common secrets and sensitive information, then **automatically redacts detected secrets** before export. However, **you are still responsible for reviewing your exports** before sharing them publicly.
|
|
379
|
+
|
|
380
|
+
### Automatic Detection & Redaction
|
|
381
|
+
|
|
382
|
+
The tool uses [TruffleHog](https://github.com/trufflesecurity/trufflehog), the industry-standard secret detection engine, to detect and redact:
|
|
383
|
+
|
|
384
|
+
- **AWS Credentials**: Access keys and secret keys (requires both for detection)
|
|
385
|
+
- **GitHub Tokens**: Personal access tokens, fine-grained tokens, OAuth tokens
|
|
386
|
+
- **Slack Webhooks**: Incoming webhook URLs and service integrations
|
|
387
|
+
- **API Keys**: Google Cloud, Azure, Stripe, and 800+ other services
|
|
388
|
+
- **Authentication Tokens**: JWT tokens, OAuth tokens, session tokens
|
|
389
|
+
- **Private Keys**: SSH keys, TLS certificates, PGP keys
|
|
390
|
+
- **Database Credentials**: Connection strings, passwords
|
|
391
|
+
- **And 800+ other secret types** from TruffleHog's actively maintained detection rules
|
|
392
|
+
|
|
393
|
+
### Detection & Redaction Process
|
|
394
|
+
|
|
395
|
+
When secrets are detected, the exporter:
|
|
396
|
+
|
|
397
|
+
1. **Automatically redacts** detected secrets with `[REDACTED]` placeholders
|
|
398
|
+
2. **Continues the export** with redacted content (non-blocking)
|
|
399
|
+
3. **Creates a detailed log** file: `*_secrets.jsonl`
|
|
400
|
+
4. **Shows a warning** with the count of detected secrets
|
|
401
|
+
5. **Logs structured data** including detector name, verification status, and context
|
|
402
|
+
|
|
403
|
+
### Example Warning Output
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
⚠️ Detected 3 potential secrets in conversation content (see conversation_secrets.jsonl)
|
|
407
|
+
Please review and ensure no sensitive information is shared in exports.
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Secret Log Format
|
|
411
|
+
|
|
412
|
+
The generated `*_secrets.jsonl` file contains structured data for each detection:
|
|
413
|
+
|
|
414
|
+
```json
|
|
415
|
+
{"context":"message_msg_01ABC123_text","type":"secret","pattern":"AWS","confidence":false}
|
|
416
|
+
{"context":"message_msg_01XYZ789_text","type":"secret","pattern":"SlackWebhook","confidence":false}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Field explanations:**
|
|
420
|
+
- `context`: Unique identifier for the message location
|
|
421
|
+
- `type`: Always "secret" for TruffleHog detections
|
|
422
|
+
- `pattern`: TruffleHog detector name (e.g., "AWS", "Github", "SlackWebhook")
|
|
423
|
+
- `confidence`: Boolean indicating if the secret was verified against the actual service
|
|
424
|
+
|
|
425
|
+
### Best Practices
|
|
426
|
+
|
|
427
|
+
1. **Review both the export and secrets log** before sharing
|
|
428
|
+
2. **Check for context-specific secrets** the detector might miss
|
|
429
|
+
3. **Consider using fake/example data** in conversations you plan to export
|
|
430
|
+
4. **Manually review redacted areas** to ensure proper masking
|
|
431
|
+
5. **Use the `--jsonl` option** to process specific conversations when unsure
|
|
432
|
+
|
|
433
|
+
### Redaction Examples
|
|
434
|
+
|
|
435
|
+
Original content with secrets:
|
|
436
|
+
```
|
|
437
|
+
Here's my GitHub token: ghp_1234567890123456789012345678901234567890
|
|
438
|
+
AWS credentials: AKIA1234567890123456 secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
|
|
439
|
+
Slack webhook: https://hooks.slack.com/services/T1234567890/B1234567890/abcdefghijklmnopqrstuvwx
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Automatically redacted output:
|
|
443
|
+
```
|
|
444
|
+
Here's my GitHub token: [REDACTED]
|
|
445
|
+
AWS credentials: [REDACTED] secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
|
|
446
|
+
Slack webhook: [REDACTED]
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Note:** TruffleHog focuses on high-confidence secret patterns. Some parts may remain unredacted if they don't match specific detection patterns, which reduces false positives but requires manual review.
|
|
450
|
+
|
|
451
|
+
### Limitations
|
|
452
|
+
|
|
453
|
+
- Detection uses **800+ proven patterns** but may miss context-specific secrets
|
|
454
|
+
- **TruffleHog is conservative** - it prioritizes avoiding false positives over catching everything
|
|
455
|
+
- **Custom/internal secrets** (like internal URLs, custom API endpoints) may not be detected
|
|
456
|
+
- **AWS detection requires both** access key and secret key for optimal detection
|
|
457
|
+
- **Slack tokens** may not be detected if they don't match exact format patterns
|
|
458
|
+
- **Human review is always required** before sharing
|
|
459
|
+
|
|
460
|
+
## Testing
|
|
461
|
+
|
|
462
|
+
Run the test suite:
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
bundle exec rspec
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Credits
|
|
469
|
+
|
|
470
|
+
This Ruby implementation is based on the excellent [claude-code-exporter](https://github.com/developerisnow/claude-code-exporter) JavaScript project by developerisnow. The original project provides the foundation for understanding Claude Code's session storage format and export patterns.
|
|
471
|
+
|
|
472
|
+
The GitHub-flavored Markdown formatting features were implemented with reference to the [GitHub Markdown Cheatsheet](https://ml-run.github.io/github_markdown_cheatsheet.html), particularly the collapsed sections functionality.
|
|
473
|
+
|
|
474
|
+
### Key Enhancements in This Ruby Version
|
|
475
|
+
- **Enhanced tool formatting**: Specialized formatting for Write, Edit, and Bash tools
|
|
476
|
+
- **Syntax highlighting**: Automatic language detection and code block formatting
|
|
477
|
+
- **Path relativization**: Clean, portable output with relative paths
|
|
478
|
+
- **Advanced tool pairing**: Smart matching of tool_use with tool_result messages
|
|
479
|
+
- **Integrated HTML Preview**: Generate and open HTML previews with GitHub styling and embedded Prism.js syntax highlighting
|
|
480
|
+
- **Skip Logging & Message Tracking**: JSONL logs of filtered messages and HTML comment message IDs
|
|
481
|
+
- **Individual File Processing**: Direct JSONL file processing with `--jsonl` option
|
|
482
|
+
- **Secret Detection & Redaction**: Automatic security scanning and redaction using TruffleHog's industry-standard detection engine
|
|
483
|
+
- **Comprehensive testing**: 96 RSpec tests covering all functionality including secret detection
|
|
484
|
+
- **Ruby-idiomatic**: Clean, maintainable Ruby code structure
|
|
485
|
+
|
|
486
|
+
## Requirements
|
|
487
|
+
|
|
488
|
+
- Ruby 2.7+
|
|
489
|
+
- Claude Code installed and configured
|
|
490
|
+
- TruffleHog (for secret detection): `brew install trufflehog`
|
|
491
|
+
- RSpec (for testing)
|
|
492
|
+
- cmark-gfm (for HTML preview generation): `brew install cmark-gfm`
|
|
493
|
+
|
|
494
|
+
## Example Files
|
|
495
|
+
|
|
496
|
+
The repository includes comprehensive examples generated from the actual Claude Code conversation that was used to build this tool:
|
|
497
|
+
|
|
498
|
+
### Generated Examples
|
|
499
|
+
|
|
500
|
+
- **[VIBE.md](VIBE.md)** - Conversation export showing all features including tool use, thinking messages, message IDs, and formatting (67 messages)
|
|
501
|
+
- **[VIBE_default.html](VIBE_default.html)** - HTML preview with default template styling and embedded Prism.js syntax highlighting
|
|
502
|
+
- **[VIBE_github.html](VIBE_github.html)** - HTML preview with GitHub-style template mimicking GitHub's markdown rendering
|
|
503
|
+
- **[VIBE_solarized.html](VIBE_solarized.html)** - HTML preview with Solarized template featuring automatic dark/light mode detection and clickable theme toggle
|
|
504
|
+
|
|
505
|
+
### Full Scale Example
|
|
506
|
+
|
|
507
|
+
- **[VIBE_full.md](VIBE_full.md)** - Complete conversation export with all 3,806 messages across 5 sessions (7.3MB)
|
|
508
|
+
- **[VIBE_full.html](VIBE_full.html)** - Complete HTML preview with default template (7.9MB)
|
|
509
|
+
|
|
510
|
+
> **Note:** The full version demonstrates the exporter's capability to handle large, multi-session conversations that span the entire development of this tool. The regular VIBE examples above are filtered to a manageable size for easy browsing and template comparison.
|
|
511
|
+
|
|
512
|
+
### Features Demonstrated
|
|
513
|
+
|
|
514
|
+
These examples showcase:
|
|
515
|
+
- Multiple message types (user, assistant, thinking)
|
|
516
|
+
- Tool use with collapsible sections and syntax highlighting
|
|
517
|
+
- Message ID HTML comments for cross-referencing
|
|
518
|
+
- Path relativization and clean formatting
|
|
519
|
+
- All advanced formatting features in action
|
|
520
|
+
- Template comparison across different styling approaches
|
|
521
|
+
|
|
522
|
+
### Regenerating Examples
|
|
523
|
+
|
|
524
|
+
Use the included script to regenerate examples for all templates:
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
./generate_vibe_samples
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
This automatically creates VIBE sample files for each available template, making it easy to compare styling and features across all templates.
|
|
531
|
+
|
|
532
|
+
## License
|
|
533
|
+
|
|
534
|
+
MIT License - feel free to use and modify as needed.
|
data/Rakefile
ADDED
data/bin/ccexport
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/claude_conversation_exporter'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'time'
|
|
6
|
+
|
|
7
|
+
options = {}
|
|
8
|
+
|
|
9
|
+
OptionParser.new do |parser|
|
|
10
|
+
parser.banner = "Usage: ccexport [options]"
|
|
11
|
+
|
|
12
|
+
parser.on("--from DATE", "Filter messages from this date (YYYY-MM-DD)") do |date|
|
|
13
|
+
options[:from] = date
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
parser.on("--to DATE", "Filter messages to this date (YYYY-MM-DD)") do |date|
|
|
17
|
+
options[:to] = date
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
parser.on("--today", "Filter messages from today only") do
|
|
21
|
+
options[:today] = true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
parser.on("--in PATH", "Project path to export conversations from (default: current directory)") do |path|
|
|
25
|
+
options[:in] = path
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
parser.on("--out PATH", "Output directory or file path (default: claude-conversations)") do |path|
|
|
29
|
+
options[:out] = path
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
parser.on("--timestamps", "Show timestamps with each message") do
|
|
33
|
+
options[:timestamps] = true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
parser.on("--preview", "Generate HTML preview and open in browser") do
|
|
37
|
+
options[:preview] = true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
parser.on("--no-open", "Generate HTML preview without opening in browser (requires --preview)") do
|
|
41
|
+
options[:no_open] = true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
parser.on("--template NAME_OR_PATH", "HTML template name (from templates dir) or file path (default: default)") do |template|
|
|
45
|
+
options[:template] = template
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
parser.on("--jsonl FILE", "Process a specific JSONL file instead of scanning directories") do |file|
|
|
49
|
+
options[:jsonl] = file
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
parser.on("-s", "--silent", "Silent mode - suppress all output") do
|
|
53
|
+
options[:silent] = true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
parser.on("-h", "--help", "Show this help message") do
|
|
57
|
+
puts parser
|
|
58
|
+
exit
|
|
59
|
+
end
|
|
60
|
+
end.parse!
|
|
61
|
+
|
|
62
|
+
begin
|
|
63
|
+
# Validate options
|
|
64
|
+
if options[:no_open] && !options[:preview]
|
|
65
|
+
puts "Error: --no-open requires --preview" unless options[:silent]
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if options[:jsonl] && !File.exist?(options[:jsonl])
|
|
70
|
+
puts "Error: JSONL file not found: #{options[:jsonl]}" unless options[:silent]
|
|
71
|
+
exit 1
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if options[:jsonl] && !options[:jsonl].end_with?('.jsonl')
|
|
75
|
+
puts "Error: File must have .jsonl extension: #{options[:jsonl]}" unless options[:silent]
|
|
76
|
+
exit 1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
project_path = options[:in] || Dir.pwd
|
|
80
|
+
output_dir = options[:out] || 'claude-conversations'
|
|
81
|
+
result = ClaudeConversationExporter.export(project_path, output_dir, options)
|
|
82
|
+
|
|
83
|
+
# Generate preview if requested
|
|
84
|
+
if options[:preview]
|
|
85
|
+
# Use the actual output file if it was specified, otherwise use the directory
|
|
86
|
+
preview_target = result[:output_file] || output_dir
|
|
87
|
+
template_name = options[:template] || 'default'
|
|
88
|
+
ClaudeConversationExporter.generate_preview(preview_target, !options[:no_open], result[:leaf_summaries] || [], template_name, options[:silent])
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
exit 0
|
|
92
|
+
rescue StandardError => e
|
|
93
|
+
puts "Error: #{e.message}" unless options[:silent]
|
|
94
|
+
exit 1
|
|
95
|
+
end
|
data/ccexport.gemspec
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/ccexport/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "ccexport"
|
|
7
|
+
spec.version = CcExport::VERSION
|
|
8
|
+
spec.authors = ["Marc Heiligers"]
|
|
9
|
+
spec.email = ["marc@silvermerc.net"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Export and preview Claude Code conversations with syntax highlighting"
|
|
12
|
+
spec.description = <<~DESC
|
|
13
|
+
A Ruby tool to export Claude Code conversations from JSONL session files
|
|
14
|
+
into beautifully formatted Markdown and HTML files with syntax highlighting,
|
|
15
|
+
secret detection, and multiple template options.
|
|
16
|
+
DESC
|
|
17
|
+
spec.homepage = "https://github.com/marcheiligers/ccexport"
|
|
18
|
+
spec.license = "MIT"
|
|
19
|
+
spec.required_ruby_version = ">= 3.0.0"
|
|
20
|
+
|
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
22
|
+
spec.metadata["source_code_uri"] = "#{spec.homepage}.git"
|
|
23
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
24
|
+
|
|
25
|
+
# Specify which files should be added to the gem when it is released.
|
|
26
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
27
|
+
spec.files = Dir.chdir(__dir__) do
|
|
28
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
29
|
+
(File.expand_path(f) == __FILE__) ||
|
|
30
|
+
f.start_with?(*%w[bin/fetch_secrets_patterns spec/ VIBE claude-conversations/ debug_compacted.rb discover_structure.out discover_structure.rb generate_vibe_samples]) ||
|
|
31
|
+
f.end_with?('.gem')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
spec.bindir = "exe"
|
|
35
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
36
|
+
spec.require_paths = ["lib"]
|
|
37
|
+
|
|
38
|
+
# Runtime dependencies
|
|
39
|
+
spec.add_dependency "json", "~> 2.0"
|
|
40
|
+
|
|
41
|
+
# Development dependencies
|
|
42
|
+
spec.add_development_dependency "rspec", "~> 3.12"
|
|
43
|
+
|
|
44
|
+
# Specify the minimum version of RubyGems required
|
|
45
|
+
spec.required_rubygems_version = ">= 1.8.11"
|
|
46
|
+
|
|
47
|
+
# For more information and examples about making a new gem, check out our
|
|
48
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
|
49
|
+
end
|