add Claude session storage view with user-driven cleanup

The claude.session-storage command opens a modal listing the workspace's
session transcripts with their on-disk sizes (the <id>.jsonl plus the
<id>/ subagents dir) and a total. Each row deletes with a deliberate
two-click confirm; deletion is guarded against unsafe ids and clide never
removes transcripts on its own. SessionSummary gains a sizeBytes field and
session_index gains formatBytes + deleteSession.

T-148.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-23 17:02:20 +02:00
co-authored by Claude Opus 4.7
parent 849024b7ee
commit 8907abeca7
8 changed files with 377 additions and 1 deletions
+26
View File
@@ -6,6 +6,8 @@ import 'package:clide/builtin/claude/src/claude_config.dart';
import 'package:clide/builtin/claude/src/claude_session_host.dart';
import 'package:clide/builtin/claude/src/session_naming.dart';
import 'package:clide/builtin/claude/src/pane_context_status.dart';
import 'package:clide/builtin/claude/src/session_index.dart';
import 'package:clide/builtin/claude/src/session_storage.dart';
import 'package:clide/builtin/claude/src/team_observer.dart';
import 'package:clide/builtin/claude/src/team_panel_host.dart';
import 'package:clide/builtin/claude/src/tmux_session.dart' as tmux;
@@ -60,6 +62,12 @@ class ClaudeExtension extends ClideExtension {
title: 'Claude: kill all tmux sessions for this repo',
run: _killAllSessions,
),
CommandContribution(
id: 'claude.session-storage',
command: 'claude.session-storage',
title: 'Claude: session storage (disk usage + cleanup)',
run: _manageStorage,
),
// In-pane status slot (T-145): the active Claude pane publishes
// its model · permission-mode · context line here.
StatusItemContribution(
@@ -171,6 +179,24 @@ class ClaudeExtension extends ClideExtension {
return IpcResponse.ok(id: '', data: const {'status': 'killed'});
}
/// Open the session-storage manager: per-session transcript sizes, a total,
/// and a user-driven cleanup (T-148). Enumerates the workspace's sessions
/// and shows the modal; deletion happens inside the dialog.
Future<IpcResponse> _manageStorage(List<String> args) async {
final ctx = _ctx;
if (ctx == null) return IpcResponse.ok(id: '', data: const {});
final resp = await ctx.ipc.request('files.root');
final root = resp.ok ? resp.data['path'] as String? : null;
final home = Platform.environment['HOME'];
if (root == null || home == null) return IpcResponse.ok(id: '', data: const {});
final dir = Directory('$home/.claude/projects/${root.replaceAll('/', '-')}');
final sessions = await listSessions(dir);
await ctx.dialog.show<Object>(
(c, dismiss) => SessionStorageDialog(dir: dir, sessions: sessions, onClose: dismiss),
);
return IpcResponse.ok(id: '', data: const {'status': 'shown'});
}
Future<String?> _primarySessionName() async {
final ctx = _ctx;
if (ctx == null) return null;