1
2
3
4
5
6
7
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! Continuation detection for Claude Code sessions.
//!
//! # Design
//!
//! Claude Code v2.0+ tracks conversations by EXECUTION DIRECTORY.
//! When Claude runs from `/path/to/-session/`, it stores conversation files in
//! `~/.claude/projects/{encoded}/` where `{encoded}` is the v1 lossy encoding
//! of the execution directory path (see [`encode_path`][crate::encode_path]).
//!
//! # Examples
//!
//! ```no_run
//! use claude_storage_core::continuation;
//! use std::path::PathBuf;
//!
//! let session_dir = PathBuf::from( "/tmp/my-session" );
//! if continuation::check_continuation( &session_dir )
//! {
//! println!( "Session has conversation history — resuming" );
//! }
//! else
//! {
//! println!( "No history — starting fresh" );
//! }
//! ```
use ;
use crateencode_path;
/// Compute the Claude storage path for a given execution directory.
///
/// Claude Code stores conversations at `~/.claude/projects/{encoded}/`
/// where `{encoded}` is the v1 lossy encoding of the execution directory path.
///
/// # Parameters
///
/// - `session_dir`: Execution directory to compute storage path for
///
/// # Returns
///
/// `Some(PathBuf)` with the `~/.claude/projects/{encoded}/` path,
/// or `None` if `HOME` is not set or the path cannot be encoded
/// (empty path, invalid UTF-8).
///
/// # Examples
///
/// ```no_run
/// use claude_storage_core::continuation;
/// use std::path::PathBuf;
///
/// let session_dir = PathBuf::from( "/home/user/project/-debug" );
/// if let Some( storage ) = continuation::to_storage_path_for( &session_dir )
/// {
/// println!( "Claude stores sessions at: {}", storage.display() );
/// }
/// ```
/// Check if Claude storage contains conversation history for an execution directory.
///
/// Returns `true` if `~/.claude/projects/{encoded}/` exists and contains at
/// least one non-empty, non-agent conversation file.
///
/// # Conversation File Detection
///
/// A file counts as conversation history if it:
/// - Has a `.jsonl` extension (case-insensitive)
/// - Is named `conversation.json`
/// - Starts with `.claude`
///
/// Excluded from detection:
/// - `agent-*.jsonl` — agent definition files, not user conversations
/// - Empty files (0 bytes) — created by Claude Code during initialization or crash
///
/// # Parameters
///
/// - `session_dir`: Execution directory to check for conversation history
///
/// # Returns
///
/// `true` if at least one valid conversation file exists
///
/// # Examples
///
/// ```no_run
/// use claude_storage_core::continuation;
/// use std::path::PathBuf;
///
/// let session_dir = PathBuf::from( "/home/user/project/-debug" );
/// if continuation::check_continuation( &session_dir )
/// {
/// println!( "Has conversation history" );
/// }
/// ```