block / block/berd

No way to permanently delete a chat — archive just hides the transcript

Open
#242 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TypeScript
Stars
909
Forks
116
Avg merge
1d 1h
Merged PRs (30d)
156

Description

### Before filing

- [x] I searched [open and closed issues](https://github.com/block/berd/issues?q=is%3Aissue) for duplicates.
- [x] I am using a recent [release](https://github.com/block/berd/releases) and this doesn't already exist.
- [x] This is one request, not several bundled together.

### Closest existing issue

#229 (No way to edit a message after sending it) — adjacent but a different problem. No dedicated "delete chat" issue found in open or closed issues.

### Is this new, or an improvement?

New capability — Berd can't do this at all today

### The problem, in your terms

I use Berd for a mix of throwaway experiments and chats that contain data I don't want sitting on disk long-term: API keys pasted into prompts, snippets from internal docs, customer data. The chat lifecycle only has Archive — the session context menu (both in the sidebar and on Session History cards) has no Delete. So archiving is the only "I'm done with this" state, but the full transcript stays in the store and remains browsable in the Archived section of Session History. For confidentiality, that's the difference between "hidden" and "gone".

I verified this on my own install: archiving sets the `archived_at` field on the session row; the messages table is untouched, so the whole conversation (every user and assistant message) is still in the store.

It compounds over time because of auto-archive: inactive chats get archived in the background, so transcripts quietly accumulate on disk without the user doing anything.

### What you do today

- For most chats: archive and accept that the text stays on disk.
- For genuinely confidential chats: quit Berd and run a script against the goose session store (`~/.local/share/goose/sessions/sessions.db`) — delete the session row plus its `messages` and `usage_ledger` rows, then VACUUM so the freed pages are actually overwritten rather than left in the file. It works, but it's fragile, out-of-band, and has to be run while the app is closed or the running goose backend can re-append a session you just deleted.

### What you'd like to see

A "Delete" action in the session context menu, next to Archive, with a confirmation that says the transcript is removed from the store. Specifically:
- Works for active and archived chats, and with multi-select (the menu already supports bulk actions)
- Cleans up the session row, its messages, its usage/cost ledger entries, and Goose-managed resources the chat created (e.g. worktrees) — or at least states in the confirmation which of those are and aren't touched
- The plumbing largely exists: `deleteSession()` is already implemented in `src/shared/api/acpApi.ts` (ACP `session/delete` method). It's currently used only for hidden one-shot inference sessions in `src/features/security/lib/inferExplanation.ts`. So this is primarily a UI + lifecycle-scope question, not new backend work.

### Why this belongs in Berd itself

A skill or automation could shell out to the store, but: (a) the store path and schema are internals of goose, Berd's default backend — Berd already owns that boundary; (b) deletion has to coordinate with the running goose backend, because an in-memory session can re-append data to a row you just deleted; (c) the menu plumbing, confirmation UX, and bulk selection for this exact menu already exist. An out-of-band script racing a live backend is exactly the kind of fragile workaround a built-in action exists to avoid.

### Non-goals

- Not asking for a trash bin / undo — confirm-then-delete is enough. A "recently deleted" bin would be nice, not required.
- Not asking for per-message deletion (that's #229 territory).
- Not asking for encryption at rest.
- Not asking for `berdctl session delete` — natural companion, but the menu action is the core ask.

### Alternatives you considered

- Just live with archive — fine until the first pasted API key.
- Custom automation running a delete script — what I use now; out-of-band and needs care around the running backend.
- Nuke the whole store — a sledgehammer; loses every chat.

### Mockups, prior art, or other context

- ChatGPT's chat list, Claude's projects, and Cursor all expose Delete next to rename/archive in the chat list.
- Verified on 0.6.3-dev.78+ge89beafe: the session menu (`src/features/sessions/ui/SessionActionsMenuItems.tsx`) exposes mark read/unread, pin, rename, open in window, duplicate, edit project, copy link, export, archive, restore — no delete. `deleteSession` in `src/shared/api/acpApi.ts` is only called from `src/features/security/lib/inferExplanation.ts` for ephemeral inference sessions.

Contributor guide

Open the contributing guide

Research direction

Start with src/features/sessions/ui/SessionActionsMenuItems.tsx and inspect the existing bulk-action and archive flows. Then read deleteSession() in src/shared/api/acpApi.ts and its use in src/features/security/lib/inferExplanation.ts to understand the available lifecycle plumbing. Done means active and archived sessions can be deleted with confirmation, bulk selection behaves consistently, and the confirmation states what data and resources are removed.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
desktop
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.