desktopdir: Claude Desktop installed from the Microsoft Store (package AnthropicPBC.Claude_*) has its folders found, as the setup.exe's Claude_* package's are

Desktop 2.31226.1's own code knows two MSIX package families, Claude_pzs8sxrjxfjjc
and AnthropicPBC.Claude_fnn82j28hfe8t (hze/_ze in index.chunk-Cyt2WTko.js).
packageDir only globbed Packages\Claude_*, so a Store install's LocalCache
was never found: magpie wrote Claude Desktop's gateway, MCP servers and
read its sessions and skills in the unpackaged folders instead.

Checked while following up v0.1.1156: the same bundle has a
%LOCALAPPDATA%\Claude-Data folder for 1p userData, but in 2.31226.1 it is
dormant. globalThis.userDataMoved is only read, never set, and the
Claude-Data dir is chosen only when %APPDATA% is a network share, while
relocateUncUserData does nothing in index.pre.js. So 1p userData is still
%APPDATA%\Claude (or the package's copy), and desktopdir is left as it is for
that.

Run: go test ./internal/desktopdir ./internal/library ./internal/agent
(macOS); TestFindMSIX fails on the old packageDir for the Store family;
desktopdir's Windows test binary passes on the Windows box; go vet for
linux, windows and darwin.
This commit is contained in:
yetone committed 2026-10-10 14:55:16 +08:00
1 parent 9e35eef336
commit 494dedcf8f
3 files changed
+18 -7

No files matched your search

+1 -1
View File
@@ -85,7 +85,7 @@ line; agents connected to magpie lose it when it quits.
| Agent | File | Fields |
| ------------ | --------------------------------- | --------------- |
| Claude Code | `~/.claude/settings.json` | provider, model, opus/sonnet/haiku/fable, sign-in (through magpie) |
| Claude Desktop | `Claude/` + `Claude-3p/configLibrary/` in `~/Library/Application Support` (`%LOCALAPPDATA%` on Windows, `~/.config` on Linux). A Desktop installed as an MSIX package on Windows keeps them in its package instead (`%LOCALAPPDATA%\Packages\Claude_<publisher>\LocalCache\Local`, its own data in `LocalCache\Roaming\Claude`). Desktop 2.31226 and later, packaged, reads the real `%LOCALAPPDATA%\Claude-3p` instead, so for a packaged Desktop magpie writes both ([`desktopdir`](../internal/desktopdir/desktopdir.go)) | provider (its third-party gateway mode: Code and Cowork on magpie, no Anthropic sign-in; restart Desktop) |
| Claude Desktop | `Claude/` + `Claude-3p/configLibrary/` in `~/Library/Application Support` (`%LOCALAPPDATA%` on Windows, `~/.config` on Linux). A Desktop installed as an MSIX package on Windows keeps them in its package instead (`%LOCALAPPDATA%\Packages\Claude_<publisher>\LocalCache\Local`, or `AnthropicPBC.Claude_<publisher>` for the Store's package, its own data in `LocalCache\Roaming\Claude`). Desktop 2.31226 and later, packaged, reads the real `%LOCALAPPDATA%\Claude-3p` instead, so for a packaged Desktop magpie writes both ([`desktopdir`](../internal/desktopdir/desktopdir.go)) | provider (its third-party gateway mode: Code and Cowork on magpie, no Anthropic sign-in; restart Desktop) |
| Codex | `~/.codex/config.toml` | provider, model, effort |
| Gemini CLI | `~/.gemini/settings.json`, `~/.gemini/.env` | auth, model |
| OpenCode | `~/.config/opencode/opencode.json(c)` (`$OPENCODE_CONFIG_DIR`) | model, small |
+12 -4
View File
@@ -15,6 +15,8 @@
// %LOCALAPPDATA%\Packages\Claude_<publisher>\LocalCache\Roaming\Claude
// %LOCALAPPDATA%\Packages\Claude_<publisher>\LocalCache\Local\Claude(-3p)
//
// (AnthropicPBC.Claude_<publisher> for the Store's package.)
//
// The packaged app reads its own copy before the real folder's, so a file
// another program writes into %APPDATA%\Claude is not seen once the app has
// one there. Such an install's folders are the package's: those are found,
@@ -156,11 +158,17 @@ func lastRun(dirs ...string) time.Time {
}
// packageDir is the LocalCache folder of Desktop's MSIX package under
// local (%LOCALAPPDATA%): Packages\Claude_<publisher id>, the one Desktop
// has run in first, else the first there is. The publisher id is not
// assumed: it is the one of whoever signed the package.
// local (%LOCALAPPDATA%): Packages\Claude_<publisher id>, or the Store's
// Packages\AnthropicPBC.Claude_<publisher id> (Desktop 2.31226 knows both
// families, Claude_pzs8sxrjxfjjc and AnthropicPBC.Claude_fnn82j28hfe8t),
// the one Desktop has run in first, else the first there is. The publisher
// id is not assumed: it is the one of whoever signed the package.
func packageDir(local string) string {
found, _ := filepath.Glob(filepath.Join(local, "Packages", "Claude_*"))
var found []string
for _, family := range []string{"Claude_*", "AnthropicPBC.Claude_*"} {
m, _ := filepath.Glob(filepath.Join(local, "Packages", family))
found = append(found, m...)
}
var dirs []string
for _, p := range found {
if fi, err := os.Stat(p); err == nil && fi.IsDir() {
+5 -2
View File
@@ -29,11 +29,14 @@ func ran(tb testing.TB, dir string, t time.Time) {
// Discord, Windows 10 LTSC 21H2) keeps its data in the package's
// LocalCache, nothing in %APPDATA%\Claude: those are its folders, whatever
// the package's publisher id.
//
// The Store's package is the AnthropicPBC.Claude family
// (AnthropicPBC.Claude_fnn82j28hfe8t in Desktop 2.31226's own list).
func TestFindMSIX(t *testing.T) {
for _, pub := range []string{"pzs8sxrjxfjjc", "q1w2e3r4t5y6z"} {
for _, pub := range []string{"Claude_pzs8sxrjxfjjc", "Claude_q1w2e3r4t5y6z", "AnthropicPBC.Claude_fnn82j28hfe8t"} {
home := t.TempDir()
local, roaming := filepath.Join(home, "AppData", "Local"), filepath.Join(home, "AppData", "Roaming")
pkg := filepath.Join(local, "Packages", "Claude_"+pub, "LocalCache")
pkg := filepath.Join(local, "Packages", pub, "LocalCache")
ran(t, filepath.Join(pkg, "Roaming", "Claude"), time.Now())
os.MkdirAll(filepath.Join(pkg, "Local", "Claude", "logs"), 0o755)
os.MkdirAll(filepath.Join(local, "Packages", "Microsoft.WindowsStore_8wekyb3d8bbwe"), 0o755)