8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# File 'lib/ccexport/cli.rb', line 8
def self.run(argv = ARGV)
options = {}
OptionParser.new do |parser|
parser.banner = "Usage: ccexport [options]"
parser.on("--from DATE", "Filter messages from this date (YYYY-MM-DD)") do |date|
options[:from] = date
end
parser.on("--to DATE", "Filter messages to this date (YYYY-MM-DD)") do |date|
options[:to] = date
end
parser.on("--today", "Filter messages from today only") do
options[:today] = true
end
parser.on("--in PATH", "Project path to export conversations from (default: current directory)") do |path|
options[:in] = path
end
parser.on("--out PATH", "Output directory or file path (default: claude-conversations)") do |path|
options[:out] = path
end
parser.on("--timestamps", "Show timestamps with each message") do
options[:timestamps] = true
end
parser.on("--preview", "Generate HTML preview and open in browser") do
options[:preview] = true
end
parser.on("--no-open", "Generate HTML preview without opening in browser (requires --preview)") do
options[:no_open] = true
end
parser.on("--template NAME_OR_PATH", "HTML template name (from templates dir) or file path (default: default)") do |template|
options[:template] = template
end
parser.on("--jsonl FILE", "Process a specific JSONL file instead of scanning directories") do |file|
options[:jsonl] = file
end
parser.on("--session ID", "Export a specific session by its UUID") do |id|
options[:session] = id
end
parser.on("--clean", "Export only visible conversation (no tool calls, thinking, or metadata)") do
options[:clean] = true
end
parser.on("--stdout", "Write markdown to stdout instead of a file (implies --silent)") do
options[:stdout] = true
end
parser.on("-s", "--silent", "Silent mode - suppress all output") do
options[:silent] = true
end
parser.on("--skip-dependency-check", "Skip checking for external dependencies") do
options[:skip_dependency_check] = true
end
parser.on("-h", "--help", "Show this help message") do
puts parser
exit
end
end.parse!(argv)
check_dependencies(options[:silent]) unless options[:skip_dependency_check]
begin
if options[:no_open] && !options[:preview]
puts "Error: --no-open requires --preview" unless options[:silent]
exit 1
end
if options[:jsonl] && !File.exist?(options[:jsonl])
puts "Error: JSONL file not found: #{options[:jsonl]}" unless options[:silent]
exit 1
end
if options[:jsonl] && !options[:jsonl].end_with?('.jsonl')
puts "Error: File must have .jsonl extension: #{options[:jsonl]}" unless options[:silent]
exit 1
end
project_path = options[:in] || Dir.pwd
output_dir = options[:out] || 'claude-conversations'
result = ClaudeConversationExporter.export(project_path, output_dir, options)
if options[:preview]
preview_target = result[:output_file] || output_dir
template_name = options[:template] || 'default'
ClaudeConversationExporter.generate_preview(preview_target, !options[:no_open], result[:leaf_summaries] || [], template_name, options[:silent])
end
exit 0
rescue StandardError => e
puts "Error: #{e.message}" unless options[:silent]
exit 1
end
end
|