@aiplumber/session-recall 1.6.0 → 1.6.7
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/package.json +1 -1
- package/session-recall +87 -58
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiplumber/session-recall",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.7",
|
|
4
4
|
"description": "Pull context from previous Claude Code sessions. Sessions end, context resets - this tool lets you continue where you left off.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"session-recall": "./session-recall"
|
package/session-recall
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
const VERSION = '1.6.7';
|
|
4
|
+
|
|
3
5
|
const fs = require('fs');
|
|
4
6
|
const path = require('path');
|
|
5
7
|
|
|
8
|
+
// Cross-platform home directory
|
|
9
|
+
const HOME = HOME || process.env.USERPROFILE;
|
|
10
|
+
|
|
6
11
|
// Filter patterns
|
|
7
12
|
const SHELL_PREFIXES = ['ls ', 'cat ', 'npm ', 'cd ', 'git ', 'mkdir ', 'rm ', 'cp ', 'mv ', 'grep ', 'find '];
|
|
8
13
|
const NOISE_TYPES = ['progress', 'file-history-snapshot', 'system', 'queue-operation'];
|
|
@@ -983,7 +988,7 @@ function cwdToProjectFolder() {
|
|
|
983
988
|
// Both / and . are replaced with -
|
|
984
989
|
const cwd = process.cwd();
|
|
985
990
|
const projectName = cwd.replace(/[\/\.]/g, '-');
|
|
986
|
-
const projectsDir = path.join(
|
|
991
|
+
const projectsDir = path.join(HOME, '.claude', 'projects');
|
|
987
992
|
const projectPath = path.join(projectsDir, projectName);
|
|
988
993
|
|
|
989
994
|
if (fs.existsSync(projectPath)) {
|
|
@@ -996,7 +1001,7 @@ function cmdLast(arg1, arg2, opts) {
|
|
|
996
1001
|
// Usage: last [N] [folder]
|
|
997
1002
|
// arg1 could be: undefined, a number string, or a folder path
|
|
998
1003
|
// arg2 could be: undefined, or a folder path (if arg1 was a number)
|
|
999
|
-
const projectsDir = path.join(
|
|
1004
|
+
const projectsDir = path.join(HOME, '.claude', 'projects');
|
|
1000
1005
|
|
|
1001
1006
|
let n = 1;
|
|
1002
1007
|
let dir = null;
|
|
@@ -1200,26 +1205,31 @@ function cmdLast(arg1, arg2, opts) {
|
|
|
1200
1205
|
return;
|
|
1201
1206
|
}
|
|
1202
1207
|
|
|
1203
|
-
//
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
allMsgs.sort((a, b) => new Date(a.timestamp || 0) - new Date(b.timestamp || 0));
|
|
1208
|
+
// Print header
|
|
1209
|
+
console.log(`[session-recall v${VERSION}] This context has been stripped of most tool results to reduce noise.`);
|
|
1210
|
+
console.log(`---`);
|
|
1207
1211
|
|
|
1208
|
-
//
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
return msgTs > filterAfterTs;
|
|
1213
|
-
});
|
|
1214
|
-
}
|
|
1212
|
+
// Process each session separately to add separators
|
|
1213
|
+
for (let sessionIdx = 0; sessionIdx < selected.length; sessionIdx++) {
|
|
1214
|
+
const session = selected[sessionIdx];
|
|
1215
|
+
let sessionMsgs = session.msgs;
|
|
1215
1216
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1217
|
+
// Sort by timestamp
|
|
1218
|
+
sessionMsgs.sort((a, b) => new Date(a.timestamp || 0) - new Date(b.timestamp || 0));
|
|
1219
|
+
|
|
1220
|
+
// Filter by checkpoint timestamp if --after was specified
|
|
1221
|
+
if (filterAfterTs) {
|
|
1222
|
+
sessionMsgs = sessionMsgs.filter(msg => {
|
|
1223
|
+
const msgTs = msg.timestamp ? new Date(msg.timestamp).getTime() : 0;
|
|
1224
|
+
return msgTs > filterAfterTs;
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1218
1227
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1228
|
+
// Build tool result metadata (size, duration)
|
|
1229
|
+
const resultMeta = buildToolResultMeta(sessionMsgs);
|
|
1230
|
+
|
|
1231
|
+
// Build tag map for this session
|
|
1232
|
+
const tagMap = {};
|
|
1223
1233
|
const sessionTags = scanSessionTags(session.filePath);
|
|
1224
1234
|
for (const tag of sessionTags) {
|
|
1225
1235
|
if (tag.targetUuid) {
|
|
@@ -1230,62 +1240,69 @@ function cmdLast(arg1, arg2, opts) {
|
|
|
1230
1240
|
};
|
|
1231
1241
|
}
|
|
1232
1242
|
}
|
|
1233
|
-
}
|
|
1234
1243
|
|
|
1235
|
-
|
|
1236
|
-
|
|
1244
|
+
for (const msg of sessionMsgs) {
|
|
1245
|
+
if (NOISE_TYPES.includes(msg.type)) continue;
|
|
1237
1246
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1247
|
+
// Check if this message has a tag
|
|
1248
|
+
const toolId = getToolUseId(msg);
|
|
1249
|
+
const msgUuid = toolId || msg.uuid;
|
|
1250
|
+
const tag = msgUuid ? tagMap[msgUuid] : null;
|
|
1242
1251
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1252
|
+
// Determine if we should show this tag
|
|
1253
|
+
const showTag = tag && (
|
|
1254
|
+
tag.level === 'critical' ||
|
|
1255
|
+
(tag.level === 'important' && opts.showImportant)
|
|
1256
|
+
);
|
|
1248
1257
|
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1258
|
+
if (msg.type === 'user') {
|
|
1259
|
+
if (isToolResult(msg)) continue;
|
|
1260
|
+
const text = getUserText(msg);
|
|
1261
|
+
if (text) {
|
|
1262
|
+
const ts = msg.timestamp ? new Date(msg.timestamp).toISOString().substring(11, 19) : '';
|
|
1263
|
+
if (showTag) {
|
|
1264
|
+
const marker = tag.level === 'critical' ? '\u26A0' : '\u2139';
|
|
1265
|
+
console.log(`[${ts}] ${marker} ${tag.level.toUpperCase()} [${tag.type}] USER: ${text.substring(0, 500)}`);
|
|
1266
|
+
console.log(` Reason: "${tag.reason}"`);
|
|
1267
|
+
} else {
|
|
1268
|
+
console.log(`[${ts}] USER: ${text.substring(0, 500)}`);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
} else if (msg.type === 'assistant') {
|
|
1272
|
+
const text = getAssistantText(msg);
|
|
1273
|
+
const toolSummary = collapseToolCall(msg, resultMeta);
|
|
1253
1274
|
const ts = msg.timestamp ? new Date(msg.timestamp).toISOString().substring(11, 19) : '';
|
|
1275
|
+
|
|
1254
1276
|
if (showTag) {
|
|
1255
1277
|
const marker = tag.level === 'critical' ? '\u26A0' : '\u2139';
|
|
1256
|
-
|
|
1278
|
+
if (text) {
|
|
1279
|
+
console.log(`[${ts}] ${marker} ${tag.level.toUpperCase()} [${tag.type}] ASSISTANT: ${text.substring(0, 500)}`);
|
|
1280
|
+
} else if (toolSummary) {
|
|
1281
|
+
console.log(`[${ts}] ${marker} ${tag.level.toUpperCase()} [${tag.type}] ${toolSummary}`);
|
|
1282
|
+
}
|
|
1257
1283
|
console.log(` Reason: "${tag.reason}"`);
|
|
1258
1284
|
} else {
|
|
1259
|
-
|
|
1285
|
+
if (text) {
|
|
1286
|
+
console.log(`[${ts}] ASSISTANT: ${text.substring(0, 500)}`);
|
|
1287
|
+
} else if (toolSummary) {
|
|
1288
|
+
console.log(`[${ts}] ASSISTANT: ${toolSummary}`);
|
|
1289
|
+
}
|
|
1260
1290
|
}
|
|
1261
1291
|
}
|
|
1262
|
-
}
|
|
1263
|
-
const text = getAssistantText(msg);
|
|
1264
|
-
const toolSummary = collapseToolCall(msg, resultMeta);
|
|
1265
|
-
const ts = msg.timestamp ? new Date(msg.timestamp).toISOString().substring(11, 19) : '';
|
|
1292
|
+
}
|
|
1266
1293
|
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
console.log(`[${ts}] ${marker} ${tag.level.toUpperCase()} [${tag.type}] ${toolSummary}`);
|
|
1273
|
-
}
|
|
1274
|
-
console.log(` Reason: "${tag.reason}"`);
|
|
1275
|
-
} else {
|
|
1276
|
-
if (text) {
|
|
1277
|
-
console.log(`[${ts}] ASSISTANT: ${text.substring(0, 500)}`);
|
|
1278
|
-
} else if (toolSummary) {
|
|
1279
|
-
console.log(`[${ts}] ASSISTANT: ${toolSummary}`);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1294
|
+
// Print session separator if not the last session
|
|
1295
|
+
if (sessionIdx < selected.length - 1) {
|
|
1296
|
+
const nextSession = selected[sessionIdx + 1];
|
|
1297
|
+
const nextTs = nextSession.lastTs ? nextSession.lastTs.toISOString().replace('T', ' ').substring(0, 16) : 'unknown';
|
|
1298
|
+
console.log(`\n=== END SESSION ${sessionIdx + 1} === NEXT SESSION: ${nextSession.project} (${nextTs}) ===\n`);
|
|
1282
1299
|
}
|
|
1283
1300
|
}
|
|
1284
1301
|
|
|
1285
1302
|
// Print instructions for Claude
|
|
1286
1303
|
console.log(``);
|
|
1287
1304
|
console.log(`---`);
|
|
1288
|
-
console.log(`
|
|
1305
|
+
console.log(`Tool results: Most are noise. Only fetch with "session-recall tools --show <id>" when you see something you actually need.`);
|
|
1289
1306
|
console.log(`Session file: ${selected[0]?.filePath || 'unknown'}`);
|
|
1290
1307
|
}
|
|
1291
1308
|
|
|
@@ -1349,6 +1366,10 @@ TAGGING:
|
|
|
1349
1366
|
tags [filter] List all tags in current project
|
|
1350
1367
|
Filter by type or level
|
|
1351
1368
|
|
|
1369
|
+
OPTIONS:
|
|
1370
|
+
-v, --version Show version number
|
|
1371
|
+
-h, --help Show this help
|
|
1372
|
+
|
|
1352
1373
|
EXAMPLES:
|
|
1353
1374
|
session-recall last 1 -d # Check what's available
|
|
1354
1375
|
session-recall last 1 -f text # Pull last session
|
|
@@ -1797,6 +1818,8 @@ function parseArgs(args) {
|
|
|
1797
1818
|
opts.showImportant = true;
|
|
1798
1819
|
} else if (arg === '-h' || arg === '--help') {
|
|
1799
1820
|
opts.help = true;
|
|
1821
|
+
} else if (arg === '-v' || arg === '--version') {
|
|
1822
|
+
opts.version = true;
|
|
1800
1823
|
} else if (!arg.startsWith('-')) {
|
|
1801
1824
|
positional.push(arg);
|
|
1802
1825
|
}
|
|
@@ -1810,6 +1833,12 @@ function parseArgs(args) {
|
|
|
1810
1833
|
const args = process.argv.slice(2);
|
|
1811
1834
|
const { opts, positional } = parseArgs(args);
|
|
1812
1835
|
|
|
1836
|
+
// Handle --version flag
|
|
1837
|
+
if (opts.version) {
|
|
1838
|
+
console.log(`session-recall v${VERSION}`);
|
|
1839
|
+
process.exit(0);
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1813
1842
|
// Handle --checkpoint flag first (no-op marker that gets logged)
|
|
1814
1843
|
if (opts.checkpoint) {
|
|
1815
1844
|
// Output marker format - this IS the checkpoint storage (searched in tool_result)
|
|
@@ -1818,7 +1847,7 @@ if (opts.checkpoint) {
|
|
|
1818
1847
|
|
|
1819
1848
|
// Detect current session UUID by finding most recently modified .jsonl
|
|
1820
1849
|
let currentUuid = 'unknown';
|
|
1821
|
-
const claudeProjectsDir = path.join(
|
|
1850
|
+
const claudeProjectsDir = path.join(HOME, '.claude', 'projects');
|
|
1822
1851
|
if (fs.existsSync(claudeProjectsDir)) {
|
|
1823
1852
|
let newestFile = null;
|
|
1824
1853
|
let newestTime = 0;
|