@claude-sessions/core 0.4.4 → 0.4.5-beta.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.
- package/README.md +37 -40
- package/dist/index.d.ts +6 -4
- package/dist/index.js +34 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,14 +33,10 @@ const sessions = await Effect.runPromise(listSessions(projectName))
|
|
|
33
33
|
const messages = await Effect.runPromise(readSession(projectName, sessionId))
|
|
34
34
|
|
|
35
35
|
// Search sessions (title only)
|
|
36
|
-
const titleResults = await Effect.runPromise(
|
|
37
|
-
searchSessions('query', { searchContent: false })
|
|
38
|
-
)
|
|
36
|
+
const titleResults = await Effect.runPromise(searchSessions('query', { searchContent: false }))
|
|
39
37
|
|
|
40
38
|
// Search sessions (title + content)
|
|
41
|
-
const allResults = await Effect.runPromise(
|
|
42
|
-
searchSessions('query', { searchContent: true })
|
|
43
|
-
)
|
|
39
|
+
const allResults = await Effect.runPromise(searchSessions('query', { searchContent: true }))
|
|
44
40
|
|
|
45
41
|
// Rename a session
|
|
46
42
|
await Effect.runPromise(renameSession(projectName, sessionId, 'New Title'))
|
|
@@ -53,51 +49,52 @@ await Effect.runPromise(deleteSession(projectName, sessionId))
|
|
|
53
49
|
|
|
54
50
|
### Session Operations
|
|
55
51
|
|
|
56
|
-
| Function
|
|
57
|
-
|
|
58
|
-
| `listProjects()`
|
|
59
|
-
| `listSessions(projectName)`
|
|
60
|
-
| `readSession(projectName, sessionId)`
|
|
61
|
-
| `searchSessions(query, options?)`
|
|
62
|
-
| `renameSession(projectName, sessionId, title)` | Rename a session
|
|
63
|
-
| `deleteSession(projectName, sessionId)`
|
|
64
|
-
| `deleteMessage(projectName, sessionId, uuid)`
|
|
65
|
-
| `splitSession(projectName, sessionId, uuid)`
|
|
66
|
-
| `moveSession(source, sessionId, target)`
|
|
67
|
-
| `getSessionFiles(projectName, sessionId)`
|
|
68
|
-
| `previewCleanup(projectName?)`
|
|
69
|
-
| `clearSessions(options)`
|
|
52
|
+
| Function | Description |
|
|
53
|
+
| ---------------------------------------------- | ----------------------------------- |
|
|
54
|
+
| `listProjects()` | List all Claude Code projects |
|
|
55
|
+
| `listSessions(projectName)` | List sessions in a project |
|
|
56
|
+
| `readSession(projectName, sessionId)` | Read all messages in a session |
|
|
57
|
+
| `searchSessions(query, options?)` | Search sessions by title or content |
|
|
58
|
+
| `renameSession(projectName, sessionId, title)` | Rename a session |
|
|
59
|
+
| `deleteSession(projectName, sessionId)` | Delete a session (backup) |
|
|
60
|
+
| `deleteMessage(projectName, sessionId, uuid)` | Delete a message |
|
|
61
|
+
| `splitSession(projectName, sessionId, uuid)` | Split session at a message |
|
|
62
|
+
| `moveSession(source, sessionId, target)` | Move session to another project |
|
|
63
|
+
| `getSessionFiles(projectName, sessionId)` | Get files changed in session |
|
|
64
|
+
| `previewCleanup(projectName?)` | Preview cleanup candidates |
|
|
65
|
+
| `clearSessions(options)` | Clear empty/invalid sessions |
|
|
70
66
|
|
|
71
67
|
### Path Utilities
|
|
72
68
|
|
|
73
|
-
| Function
|
|
74
|
-
|
|
75
|
-
| `getSessionsDir()`
|
|
76
|
-
| `getTodosDir()`
|
|
77
|
-
| `folderNameToDisplayPath(name)`
|
|
78
|
-
| `
|
|
69
|
+
| Function | Description |
|
|
70
|
+
| ----------------------------------- | ----------------------------------------------------------------- |
|
|
71
|
+
| `getSessionsDir()` | Get Claude Code sessions directory |
|
|
72
|
+
| `getTodosDir()` | Get Claude Code todos directory |
|
|
73
|
+
| `folderNameToDisplayPath(name)` | Convert folder name to display path |
|
|
74
|
+
| `pathToFolderName(path)` | Convert absolute path to folder name (official Claude Code logic) |
|
|
75
|
+
| `resolvePathFromClaudeConfig(name)` | Resolve folder name to path via ~/.claude.json |
|
|
79
76
|
|
|
80
77
|
### Message Utilities
|
|
81
78
|
|
|
82
|
-
| Function
|
|
83
|
-
|
|
84
|
-
| `extractTextContent(message)`
|
|
85
|
-
| `extractTitle(messages)`
|
|
79
|
+
| Function | Description |
|
|
80
|
+
| --------------------------------- | ------------------------------------------ |
|
|
81
|
+
| `extractTextContent(message)` | Extract text from message content |
|
|
82
|
+
| `extractTitle(messages)` | Extract session title from messages |
|
|
86
83
|
| `isInvalidApiKeyMessage(message)` | Check if message has invalid API key error |
|
|
87
|
-
| `isContinuationSummary(message)`
|
|
84
|
+
| `isContinuationSummary(message)` | Check if message is a continuation summary |
|
|
88
85
|
|
|
89
86
|
### Agent & Todo Management
|
|
90
87
|
|
|
91
|
-
| Function
|
|
92
|
-
|
|
88
|
+
| Function | Description |
|
|
89
|
+
| ------------------------------------------ | ----------------------------- |
|
|
93
90
|
| `findLinkedAgents(projectName, sessionId)` | Find agents linked to session |
|
|
94
|
-
| `findOrphanAgents(projectName?)`
|
|
95
|
-
| `deleteOrphanAgents(projectName?)`
|
|
96
|
-
| `findLinkedTodos(projectName, sessionId)`
|
|
97
|
-
| `sessionHasTodos(projectName, sessionId)`
|
|
98
|
-
| `findOrphanTodos(projectName?)`
|
|
99
|
-
| `deleteOrphanTodos(projectName?)`
|
|
91
|
+
| `findOrphanAgents(projectName?)` | Find orphan agent files |
|
|
92
|
+
| `deleteOrphanAgents(projectName?)` | Delete orphan agents |
|
|
93
|
+
| `findLinkedTodos(projectName, sessionId)` | Find todos linked to session |
|
|
94
|
+
| `sessionHasTodos(projectName, sessionId)` | Check if session has todos |
|
|
95
|
+
| `findOrphanTodos(projectName?)` | Find orphan todo files |
|
|
96
|
+
| `deleteOrphanTodos(projectName?)` | Delete orphan todos |
|
|
100
97
|
|
|
101
98
|
## License
|
|
102
99
|
|
|
103
|
-
MIT
|
|
100
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ interface FileSystem {
|
|
|
17
17
|
declare const getSessionsDir: () => string;
|
|
18
18
|
/** Get Claude todos directory (~/.claude/todos) */
|
|
19
19
|
declare const getTodosDir: () => string;
|
|
20
|
+
/** Expand ~ path to absolute path with OS-native separators */
|
|
21
|
+
declare const expandHomePath: (tildePath: string, homeDir: string) => string;
|
|
20
22
|
/**
|
|
21
23
|
* Convert project folder name to display path
|
|
22
24
|
* Unix: -home-user-projects -> /home/user/projects
|
|
@@ -32,8 +34,8 @@ declare const folderNameToDisplayPath: (folderName: string) => string;
|
|
|
32
34
|
declare const displayPathToFolderName: (displayPath: string) => string;
|
|
33
35
|
/**
|
|
34
36
|
* Convert absolute path to project folder name
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
+
* All non-alphanumeric characters are converted to '-'
|
|
38
|
+
* Matches official Claude Code: A.replace(/[^a-zA-Z0-9]/g, '-')
|
|
37
39
|
*/
|
|
38
40
|
declare const pathToFolderName: (absolutePath: string) => string;
|
|
39
41
|
/**
|
|
@@ -48,7 +50,7 @@ declare const getRealPathFromSession: (folderName: string, sessionsDir?: string,
|
|
|
48
50
|
* Convert folder name to relative or absolute path for display
|
|
49
51
|
* If path is under home directory, show relative (~/...)
|
|
50
52
|
*/
|
|
51
|
-
declare const folderNameToPath: (folderName: string) => string
|
|
53
|
+
declare const folderNameToPath: (folderName: string) => Promise<string>;
|
|
52
54
|
/**
|
|
53
55
|
* Find project folder name that matches the given workspace path
|
|
54
56
|
* Searches through all projects and checks if any session's cwd matches
|
|
@@ -662,4 +664,4 @@ declare const getLogger: () => Logger;
|
|
|
662
664
|
*/
|
|
663
665
|
declare const createLogger: (namespace: string) => Logger;
|
|
664
666
|
|
|
665
|
-
export { AgentInfo, type ChainError, CompressSessionOptions, ConversationLine, FileChange, type GenericMessage, type Logger, Message, MessagePayload$1 as MessagePayload, MoveSessionResult, type ProgressError, Project, ProjectTreeData, SearchResult, SessionIndexEntry, SessionSortOptions, SessionTodos, SessionsIndex, SummarizeSessionOptions, SummaryInfo, TREE_ICONS, type ToolUseResultError, type TreeItemType, type ValidationResult, analyzeSession, autoRepairChain, canMoveSession, clearSessions, compressSession, createLogger, deleteLinkedTodos, deleteMessage, deleteMessageWithChainRepair, deleteOrphanAgents, deleteOrphanTodos, deleteSession, displayPathToFolderName, extractProjectKnowledge, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, findProjectByWorkspacePath, folderNameToDisplayPath, folderNameToPath, formatRelativeTime, generateTreeNodeId, getDisplayTitle, getIndexEntryDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionSortTimestamp, getSessionTooltip, getSessionsDir, getTodoIcon, getTodosDir, getTotalTodoCount, hasSessionsIndex, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, loadSessionsIndex, maskHomePath, moveSession, parseCommandMessage, parseJsonlLines, parseTreeNodeId, pathToFolderName, previewCleanup, readJsonlFile, readSession, renameSession, repairChain, repairParentUuidChain, restoreMessage, searchSessions, sessionHasSubItems, sessionHasTodos, setLogger, sortIndexEntriesByModified, sortProjects, splitSession, summarizeSession, tryParseJsonLine, updateSessionSummary, validateChain, validateProgressMessages, validateToolUseResult };
|
|
667
|
+
export { AgentInfo, type ChainError, CompressSessionOptions, ConversationLine, FileChange, type GenericMessage, type Logger, Message, MessagePayload$1 as MessagePayload, MoveSessionResult, type ProgressError, Project, ProjectTreeData, SearchResult, SessionIndexEntry, SessionSortOptions, SessionTodos, SessionsIndex, SummarizeSessionOptions, SummaryInfo, TREE_ICONS, type ToolUseResultError, type TreeItemType, type ValidationResult, analyzeSession, autoRepairChain, canMoveSession, clearSessions, compressSession, createLogger, deleteLinkedTodos, deleteMessage, deleteMessageWithChainRepair, deleteOrphanAgents, deleteOrphanTodos, deleteSession, displayPathToFolderName, expandHomePath, extractProjectKnowledge, extractTextContent, extractTitle, findLinkedAgents, findLinkedTodos, findOrphanAgents, findOrphanTodos, findProjectByWorkspacePath, folderNameToDisplayPath, folderNameToPath, formatRelativeTime, generateTreeNodeId, getDisplayTitle, getIndexEntryDisplayTitle, getLogger, getRealPathFromSession, getSessionFiles, getSessionSortTimestamp, getSessionTooltip, getSessionsDir, getTodoIcon, getTodosDir, getTotalTodoCount, hasSessionsIndex, isContinuationSummary, isInvalidApiKeyMessage, listProjects, listSessions, loadAgentMessages, loadProjectTreeData, loadSessionTreeData, loadSessionsIndex, maskHomePath, moveSession, parseCommandMessage, parseJsonlLines, parseTreeNodeId, pathToFolderName, previewCleanup, readJsonlFile, readSession, renameSession, repairChain, repairParentUuidChain, restoreMessage, searchSessions, sessionHasSubItems, sessionHasTodos, setLogger, sortIndexEntriesByModified, sortProjects, splitSession, summarizeSession, tryParseJsonLine, updateSessionSummary, validateChain, validateProgressMessages, validateToolUseResult };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/paths.ts
|
|
2
2
|
import * as fs2 from "fs";
|
|
3
|
+
import * as fsp from "fs/promises";
|
|
3
4
|
import * as os from "os";
|
|
4
5
|
import * as path from "path";
|
|
5
6
|
|
|
@@ -238,8 +239,6 @@ var parseWindowsFolderName = (name) => {
|
|
|
238
239
|
return match ? { isWindows: true, drive: match[1], rest: name.slice(3) } : { isWindows: false };
|
|
239
240
|
};
|
|
240
241
|
var isWindowsPath = (p) => WINDOWS_PATTERNS.absolutePath.test(p);
|
|
241
|
-
var convertNonAscii = (str) => [...str].map((c) => c.charCodeAt(0) <= 127 ? c : "-").join("");
|
|
242
|
-
var pathCharsToFolderName = (str) => str.replace(/[/\\]\./g, "--").replace(/[/\\]/g, "-").replace(/\./g, "-");
|
|
243
242
|
var separatorsToFolderName = (str) => str.replace(/[/\\]\./g, "--").replace(/[/\\]/g, "-");
|
|
244
243
|
var extractCwdFromContent = (content, filePath) => {
|
|
245
244
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
@@ -252,6 +251,11 @@ var extractCwdFromContent = (content, filePath) => {
|
|
|
252
251
|
return null;
|
|
253
252
|
};
|
|
254
253
|
var isSessionFile = (filename) => filename.endsWith(".jsonl") && !filename.startsWith("agent-");
|
|
254
|
+
var expandHomePath = (tildePath, homeDir) => {
|
|
255
|
+
if (!tildePath.startsWith("~")) return tildePath;
|
|
256
|
+
const relativePart = tildePath.slice(1);
|
|
257
|
+
return path.join(homeDir, ...relativePart.split("/").filter(Boolean));
|
|
258
|
+
};
|
|
255
259
|
var toRelativePath = (absolutePath, homeDir) => {
|
|
256
260
|
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
257
261
|
const normalizedHome = homeDir.replace(/\\/g, "/");
|
|
@@ -263,11 +267,10 @@ var toRelativePath = (absolutePath, homeDir) => {
|
|
|
263
267
|
}
|
|
264
268
|
const startsWithHome = isWin ? pathLower.startsWith(homeLower + "/") : normalizedPath.startsWith(normalizedHome + "/");
|
|
265
269
|
if (startsWithHome) {
|
|
266
|
-
const sep = isWin ? "\\" : "/";
|
|
267
270
|
const relativePart = absolutePath.slice(homeDir.length);
|
|
268
|
-
return "~" + relativePart.replace(
|
|
271
|
+
return "~" + relativePart.replace(/\\/g, "/");
|
|
269
272
|
}
|
|
270
|
-
return absolutePath;
|
|
273
|
+
return absolutePath.replace(/\\/g, "/");
|
|
271
274
|
};
|
|
272
275
|
var folderNameToDisplayPath = (folderName) => {
|
|
273
276
|
const parsed = parseWindowsFolderName(folderName);
|
|
@@ -283,13 +286,7 @@ var displayPathToFolderName = (displayPath) => {
|
|
|
283
286
|
}
|
|
284
287
|
return displayPath.replace(/^\//g, "-").replace(/\/\./g, "--").replace(/\//g, "-");
|
|
285
288
|
};
|
|
286
|
-
var pathToFolderName = (absolutePath) =>
|
|
287
|
-
const parsed = parseWindowsAbsPath(absolutePath);
|
|
288
|
-
if (parsed.isWindows) {
|
|
289
|
-
return parsed.drive.toLowerCase() + "--" + pathCharsToFolderName(convertNonAscii(parsed.rest));
|
|
290
|
-
}
|
|
291
|
-
return convertNonAscii(absolutePath).replace(/^\//g, "-").replace(/\/\./g, "--").replace(/\//g, "-").replace(/\./g, "-");
|
|
292
|
-
};
|
|
289
|
+
var pathToFolderName = (absolutePath) => absolutePath.replace(/[^a-zA-Z0-9]/g, "-");
|
|
293
290
|
var tryGetCwdFromFile = (filePath, fileSystem = fs2, logger2 = log) => {
|
|
294
291
|
const basename3 = path.basename(filePath);
|
|
295
292
|
try {
|
|
@@ -323,20 +320,39 @@ var getRealPathFromSession = (folderName, sessionsDir = getSessionsDir(), fileSy
|
|
|
323
320
|
logger2.warn(
|
|
324
321
|
`getRealPathFromSession: ${folderName} -> no match, cwds found: ${cwdList.join(", ")}`
|
|
325
322
|
);
|
|
326
|
-
} else {
|
|
327
|
-
logger2.warn(`getRealPathFromSession: ${folderName} -> no valid cwd in any session`);
|
|
328
323
|
}
|
|
329
324
|
return null;
|
|
330
325
|
} catch {
|
|
331
326
|
return null;
|
|
332
327
|
}
|
|
333
328
|
};
|
|
334
|
-
var
|
|
329
|
+
var getClaudeConfigPath = () => path.join(os.homedir(), ".claude.json");
|
|
330
|
+
var resolvePathFromClaudeConfig = async (folderName, fileSystem = fsp) => {
|
|
331
|
+
try {
|
|
332
|
+
const configPath = getClaudeConfigPath();
|
|
333
|
+
const content = await fileSystem.readFile(configPath, "utf-8");
|
|
334
|
+
const config = JSON.parse(content);
|
|
335
|
+
if (!config.projects) return null;
|
|
336
|
+
for (const projectPath of Object.keys(config.projects)) {
|
|
337
|
+
if (pathToFolderName(projectPath) === folderName) {
|
|
338
|
+
return projectPath;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return null;
|
|
342
|
+
} catch {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
var folderNameToPath = async (folderName) => {
|
|
335
347
|
const homeDir = os.homedir();
|
|
336
348
|
const realPath = getRealPathFromSession(folderName);
|
|
337
349
|
if (realPath) {
|
|
338
350
|
return toRelativePath(realPath, homeDir);
|
|
339
351
|
}
|
|
352
|
+
const configPath = await resolvePathFromClaudeConfig(folderName);
|
|
353
|
+
if (configPath) {
|
|
354
|
+
return toRelativePath(configPath, homeDir);
|
|
355
|
+
}
|
|
340
356
|
const absolutePath = folderNameToDisplayPath(folderName);
|
|
341
357
|
return toRelativePath(absolutePath, homeDir);
|
|
342
358
|
};
|
|
@@ -808,9 +824,10 @@ var listProjects = Effect4.gen(function* () {
|
|
|
808
824
|
const projectPath = path4.join(sessionsDir, entry.name);
|
|
809
825
|
const files = yield* Effect4.tryPromise(() => fs5.readdir(projectPath));
|
|
810
826
|
const sessionFiles = files.filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
827
|
+
const displayName = yield* Effect4.tryPromise(() => folderNameToPath(entry.name));
|
|
811
828
|
return {
|
|
812
829
|
name: entry.name,
|
|
813
|
-
displayName
|
|
830
|
+
displayName,
|
|
814
831
|
path: projectPath,
|
|
815
832
|
sessionCount: sessionFiles.length
|
|
816
833
|
};
|
|
@@ -2343,6 +2360,7 @@ export {
|
|
|
2343
2360
|
deleteOrphanTodos,
|
|
2344
2361
|
deleteSession,
|
|
2345
2362
|
displayPathToFolderName,
|
|
2363
|
+
expandHomePath,
|
|
2346
2364
|
extractProjectKnowledge,
|
|
2347
2365
|
extractTextContent,
|
|
2348
2366
|
extractTitle,
|