lean_ctx/core/import/
claude_code.rs1use std::path::{Path, PathBuf};
4
5use super::{ImportResult, ImportSource, home_dir, push_error, read_jsonl_files};
6
7#[must_use]
9pub fn import() -> ImportResult {
10 let Some(home) = home_dir() else {
11 return ImportResult::default();
12 };
13 import_from_root(&home.join(".claude/projects"))
14}
15
16#[must_use]
20pub fn import_from_root(root: &Path) -> ImportResult {
21 let projects = match std::fs::read_dir(root) {
22 Ok(projects) => projects,
23 Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
24 return ImportResult::default();
25 }
26 Err(error) => {
27 let mut result = ImportResult::default();
28 push_error(&mut result, format!("{}: {error}", root.display()));
29 return result;
30 }
31 };
32
33 let mut files = Vec::new();
34 for project in projects {
35 let project = match project {
36 Ok(project) => project,
37 Err(error) => {
38 let mut result = ImportResult::default();
39 push_error(&mut result, format!("{}: {error}", root.display()));
40 return result;
41 }
42 };
43 let path = project.path();
44 if !path.is_dir() {
45 continue;
46 }
47 match std::fs::read_dir(&path) {
48 Ok(entries) => collect_jsonl_files(entries, &mut files),
49 Err(error) => {
50 let mut result = read_jsonl_files(ImportSource::ClaudeCode, root, files);
51 push_error(&mut result, format!("{}: {error}", path.display()));
52 return result;
53 }
54 }
55 }
56 files.sort();
57 read_jsonl_files(ImportSource::ClaudeCode, root, files)
58}
59
60fn collect_jsonl_files(entries: std::fs::ReadDir, files: &mut Vec<PathBuf>) {
61 for entry in entries.flatten() {
62 let path = entry.path();
63 if path.is_file()
64 && path
65 .extension()
66 .is_some_and(|extension| extension == "jsonl")
67 {
68 files.push(path);
69 }
70 }
71}