@vinh0809it/claude-sessions 0.3.0 → 0.3.2
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 +1 -1
- package/index.js +15 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ Sessions are grouped by profile in the UI. Press `m` to move a session to a diff
|
|
|
89
89
|
|----------|---------|-------|
|
|
90
90
|
| **Kitty** | ✅ new tab | Requires `allow_remote_control yes` in `kitty.conf` |
|
|
91
91
|
| **WezTerm** | ✅ new tab | Uses `wezterm cli spawn` |
|
|
92
|
-
| **tmux** | ✅ new window | In the current session |
|
|
92
|
+
| **tmux** | ✅ new window | In the current session, also when tmux runs inside kitty or WezTerm |
|
|
93
93
|
| **iTerm2** | ✅ new tab | Via `osascript` |
|
|
94
94
|
| **Terminal.app** | ✅ new window | Via `osascript` |
|
|
95
95
|
| **Windows Terminal** | ✅ new tab | Via `wt new-tab` (native Windows; in WSL it resumes in place) |
|
package/index.js
CHANGED
|
@@ -457,9 +457,11 @@ function tabComplete(input) {
|
|
|
457
457
|
|
|
458
458
|
function detectTerminal(env = process.env, platform = process.platform) {
|
|
459
459
|
if (env.CLAUDE_SESSIONS_TERMINAL) return env.CLAUDE_SESSIONS_TERMINAL;
|
|
460
|
+
// tmux first: it is always the innermost layer, and a tmux started from kitty or
|
|
461
|
+
// WezTerm inherits their variables even though their tab commands can't reach it.
|
|
462
|
+
if (env.TMUX) return 'tmux';
|
|
460
463
|
if (env.KITTY_WINDOW_ID !== undefined) return 'kitty';
|
|
461
464
|
if (env.WEZTERM_PANE !== undefined) return 'wezterm';
|
|
462
|
-
if (env.TMUX) return 'tmux';
|
|
463
465
|
if (env.TERM_PROGRAM === 'iTerm.app') return 'iterm2';
|
|
464
466
|
if (env.TERM_PROGRAM === 'Apple_Terminal') return 'apple-terminal';
|
|
465
467
|
// WSL also sees WT_SESSION, but there `wt` would open a Windows shell, not Linux.
|
|
@@ -471,8 +473,10 @@ function shellEsc(s) { return "'" + String(s).replace(/'/g, "'\\''") + "'"; }
|
|
|
471
473
|
function appleStr(s) { return '"' + String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"'; }
|
|
472
474
|
|
|
473
475
|
function trySpawn(cmd, args) {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
+
// Tab commands return at once; the timeout keeps a stuck one (e.g. `kitty @`
|
|
477
|
+
// waiting for a reply that never comes) from freezing the UI.
|
|
478
|
+
const r = spawnSync(cmd, args, { stdio: ['ignore', 'ignore', 'pipe'], timeout: 5000 });
|
|
479
|
+
if (r.error) return { ok: false, msg: `${cmd}: ${r.error.code === 'ENOENT' ? 'not found' : r.error.code === 'ETIMEDOUT' ? 'timed out' : r.error.message}` };
|
|
476
480
|
return r.status === 0
|
|
477
481
|
? { ok: true }
|
|
478
482
|
: { ok: false, msg: r.stderr?.toString().trim() || `${cmd} exited with ${r.status}` };
|
|
@@ -872,23 +876,6 @@ class Picker {
|
|
|
872
876
|
}
|
|
873
877
|
}
|
|
874
878
|
|
|
875
|
-
// Word-wraps text to `width` columns; words longer than a line are split.
|
|
876
|
-
function wrapWords(text, width) {
|
|
877
|
-
const lines = [];
|
|
878
|
-
let cur = '';
|
|
879
|
-
for (let word of text.split(' ')) {
|
|
880
|
-
while (word.length > width) {
|
|
881
|
-
if (cur) { lines.push(cur); cur = ''; }
|
|
882
|
-
lines.push(word.slice(0, width)); word = word.slice(width);
|
|
883
|
-
}
|
|
884
|
-
if (!cur) cur = word;
|
|
885
|
-
else if (cur.length + 1 + word.length <= width) cur += ' ' + word;
|
|
886
|
-
else { lines.push(cur); cur = word; }
|
|
887
|
-
}
|
|
888
|
-
if (cur || !lines.length) lines.push(cur);
|
|
889
|
-
return lines;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
879
|
// A stdin chunk may hold several keys (fast typing, paste): split into single
|
|
893
880
|
// chars, keeping escape sequences like "\x1b[A" or "\x1b[5~" whole.
|
|
894
881
|
function splitKeys(chunk) {
|
|
@@ -1123,16 +1110,14 @@ class TUI {
|
|
|
1123
1110
|
const key = s.jsonlPath + ':' + s.lastModified.valueOf();
|
|
1124
1111
|
let msgs = this._previewCache.get(key);
|
|
1125
1112
|
if (!msgs) { msgs = readRecentMessages(s.jsonlPath); this._previewCache.set(key, msgs); }
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
}
|
|
1133
|
-
if (!lines.length) lines.push(dim(' (no messages)'));
|
|
1113
|
+
// One line per message with a blank line between, newest at the bottom.
|
|
1114
|
+
const width = Math.max(10, W - 8);
|
|
1115
|
+
const lines = msgs.flatMap(m => ['',
|
|
1116
|
+
` ${m.role === 'user' ? fgc('92', 'you ') : fgc('96', 'cc ')} ${trunc(m.text.replace(/\s+/g, ' ').trim(), width)}`]);
|
|
1117
|
+
const body = lines.slice(-(H - 2));
|
|
1118
|
+
if (body[0] === '') body.shift();
|
|
1134
1119
|
const head = dim(` ${fmtDate(s.lastModified)} · ${fmtSize(s.size)} · ${s.sessionId}`);
|
|
1135
|
-
return [head, ...
|
|
1120
|
+
return [head, '', ...(body.length ? body : [dim(' (no messages)')])];
|
|
1136
1121
|
}
|
|
1137
1122
|
|
|
1138
1123
|
// ── Render ──────────────────────────────────────────────────────────────────
|
|
@@ -1425,6 +1410,6 @@ if (require.main === module) {
|
|
|
1425
1410
|
module.exports = {
|
|
1426
1411
|
encodePathToDir, projectDirNameFor, tabComplete, resolveProjectPath, moveSession, readSession,
|
|
1427
1412
|
readRecentMessages, renameSession, deleteSessionFiles, emptyTrash, scanConfigDir, sortSessions,
|
|
1428
|
-
detectTerminal, wtArgs, parseArgs, fmtAgo, fmtSize, splitKeys,
|
|
1413
|
+
detectTerminal, wtArgs, parseArgs, fmtAgo, fmtSize, splitKeys, cache, LineInput,
|
|
1429
1414
|
};
|
|
1430
1415
|
}
|
package/package.json
CHANGED