Pinned sidebar section fills up with sessions and cannot be cleared

Status Open
Reported on v2.1.234
Maintainer reply None cached
Activity 0 comments · opened Aug 20, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Pinned sidebar section fills up with sessions and cannot be cleared

Environment: Claude Code 2.1.234, desktop shell 1.32885.1, Windows 11 Home 10.0.26200,
MSIX (Microsoft Store) install, Node 24.18.1. ~500 local sessions, 184 of them pinned.

What happens

The "Pinned" section in the left sidebar contained 184 sessions and was unnavigable —
it renders as one flat list and pushes the rest of the sidebar out of reach.

I did not pin 184 sessions and leave them pinned. Many of these had been unpinned earlier;
they reappeared in the Pinned list on their own. I cannot point at the moment it happened —
the IndexedDB history had been compacted and only covers the last day, and the app logs
that record unpin events go back one day as well — but the mechanism that would produce it
is present and measurable right now, see the section after next.

For scale, of the 184: 67 were last active in June, 107 in July, 10 in August. 170 of them
are also assigned to a sidebar folder (Boxy 94, CRM 49, and five smaller ones), so the
Pinned section was largely a duplicate of the folder contents.

There is no "Unpin all", no multi-select, and no bulk action on the section header. The
only supported way out is unpinning 184 sessions one at a time.

Why this is a dead end rather than an annoyance

The pin state is mirrored across four layers, and each one is silently rebuilt from the
layer above it on the next launch:

  1. IndexedDB (master) — origin https://claude.ai, record key

store:pin-state:dframe-starred-code, value is a JSON string:
{"state":{"starredIds":[...]},"version":0,"updatedAt":<ms>}
(a sibling record store:pin-state:dframe-starred-cowork-remote holds 1 id)

  1. localStorage — LSS-persisted.starred-local-code-sessions, same origin
  2. claude_desktop_config.jsonpreferences.epitaxyPrefs
  3. per-session claude-code-sessions/<account>/<org>/local_*.jsonisStarred

Clearing layers 2, 3 and 4 with the app fully closed appears to succeed and is then undone
at the next start. main.log shows, seconds after startup, one call per pinned session in
exactly the order of the old array:

LocalSessions.updateSession: sessionId=local_30f037c7-..., options={"isStarred":true}
   ... x184

Layer 1 cannot be reached with ordinary leveldb tooling, because Chromium uses its custom
idb_cmp1 comparator for IndexedDB — the database refuses to open. The only route that
worked was enabling developer mode (developer_settings.json containing
{"allowDevTools":true} in the user data dir), pressing Ctrl+Alt+I, and rewriting the
record from the DevTools console. That succeeded and the lower layers picked up the new
value on the next restart — but it should not be the only way for a user to undo their own
pins.

Unpinning never clears the underlying flag, so stale pins accumulate

isStarred in layer 4 is only ever set to true, never cleared. The startup reconcile
issues one updateSession {"isStarred":true} per pinned session and does nothing for the
rest. The result is a permanent record of every session that was ever pinned, and
pinnedOrder grows the same way.

This is measurable right now, minutes after I reduced the pin set to 12:

IndexedDB (master)           12
claude_desktop_config.json   12
pinnedOrder                 192
session files isStarred     186    <-- 174 stale flags

So the data still holds a full list of everything ever pinned. Anything that rebuilds the
pinned set from layer 4 instead of from IndexedDB would resurrect all of them at once,
which matches what I experienced. pinnedOrder shows the same unbounded growth — it held
190 entries against 184 starred ids this morning, and holds 192 against 12 now.

Suggested fixes

  • Clear isStarred on unpin, and drop the id from pinnedOrder, so no stale pool builds

up and nothing can be resurrected from it.

  • A bulk "Unpin all" action on the Pinned section header, plus multi-select. This alone

would have resolved the whole situation.

  • Cap or collapse the Pinned list in the sidebar (show N, then "show all"), so it cannot

crowd out the folders and recent sessions below it.

  • Keep pinnedOrder in sync with the starred set.
  • If filing a session into a folder implies pinning it, decouple the two — that duplication

is what made the sidebar unusable.

Reproducing on Windows

This is an MSIX install, so %APPDATA%\Claude exists only inside the app container. From
outside the container the real path is
%LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude — a script launched from
Explorer gets ENOENT on the %APPDATA% path, while the same path resolves fine for
processes started by the app.

What Should Happen?

keep doing this fantasting job!

Error Messages/Logs

Steps to Reproduce

Environment: Claude Code 2.1.234, desktop shell 1.32885.1, Windows 11 Home 10.0.26200,
MSIX (Microsoft Store) install. ~500 local sessions, 184 of them pinned.

A. The Pinned list grows without bound and cannot be cleared

  1. Use the desktop app normally over a few months, pinning sessions from the left

sidebar as you go, and filing sessions into sidebar folders/groups.
(In my case this reached 184 pinned sessions: 67 last active in June, 107 in July,
10 in August. 170 of the 184 are also assigned to a folder, so the Pinned section
is largely a duplicate of the folder contents.)

  1. Open the left sidebar and look at the "Pinned" section.

-> It renders all 184 entries as one flat list. Scrolling to anything is impractical
and the rest of the sidebar is pushed out of reach.

  1. Right-click the "Pinned" section header, and right-click an individual pinned session.

-> There is no "Unpin all", no multi-select, no bulk action of any kind.
The only way out is unpinning 184 sessions one at a time.

Expected: a bulk "Unpin all" action on the Pinned header, and/or the Pinned list
capped/collapsed in the sidebar ("show N more"), and/or pins pruned automatically.

B. The state is mirrored across four layers, so it cannot be fixed outside the app

This is what makes A a dead end rather than an annoyance. Each layer below is silently
rebuilt from the one above it on the next launch:

  1. IndexedDB (master) - origin https://claude.ai, record key

store:pin-state:dframe-starred-code, value is a JSON string:
{"state":{"starredIds":[...184 ids...]},"version":0,"updatedAt":<ms>}
(sibling record store:pin-state:dframe-starred-cowork-remote holds 1 id)

  1. localStorage - LSS-persisted.starred-local-code-sessions (same origin)
  2. claude_desktop_config.json -> preferences.epitaxyPrefs
  3. per-session claude-code-sessions/<account>/<org>/local_*.json -> "isStarred"

To reproduce the mirroring:

  1. Fully quit the app (including the tray icon).
  2. Edit layer 3 and layer 4 on disk: set starred-local-code-sessions to a short list in

claude_desktop_config.json, and set "isStarred": false in the corresponding
local_*.json session files.

  1. Start the app.

-> Both files are back to their previous contents. main.log shows, seconds after
startup, one call per pinned session, in exactly the order of the old array:
LocalSessions.updateSession: sessionId=local_30f037c7-..., options={"isStarred":true}
... x184

  1. Quit again and this time also clear layer 2 (the localStorage key above, writing

directly into Local Storage/leveldb), then start the app.
-> Still restored. Layer 2 is repopulated from layer 1.

  1. Only editing layer 1 works, and layer 1 cannot be opened by ordinary leveldb tooling

because Chromium uses its custom idb_cmp1 comparator for IndexedDB. The only route
left is enabling developer mode (developer_settings.json with {"allowDevTools":true}
in the user data dir), pressing Ctrl+Alt+I, and rewriting the record from the DevTools
console.

That last step is what I ended up doing, and it worked - but it should not be the only
way for a user to undo their own pins.

Note for anyone reproducing on Windows: this is an MSIX install, so %APPDATA%\Claude
only exists inside the app container. From outside the container the real path is
%LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude - a script run from
Explorer gets ENOENT on the %APPDATA% path.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

Claude Code: 2.1.234

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

_No response_

View original on GitHub ↗