Skip to content

harn claude-desktop

harn claude-desktop [accounts|sessions|mirror|tidy] [options]

Use the Claude Desktop session guide for the full mirror and cleanup workflow. Read the Session state feature page for the lifecycle model behind tidy.

The Claude desktop app scopes its Claude Code session sidebar per signed-in account: sign out of one Claude account and into another (a common move when one account hits its usage limit) and every session the first account created disappears from the sidebar. Nothing is deleted; the transcripts live account-agnostically under ~/.claude/projects/ in the runtime environment, and the sidebar entries themselves are plain JSON files under the desktop app’s data directory:

<dataDir>/claude-code-sessions/<account-uuid>/<env-id>/local_<uuid>.json

Each file is one sidebar entry ({ cliSessionId, title, cwd, model, … }) with no account binding inside it; the account scoping is purely which directory it sits in. harn claude-desktop mirror copies entry files across account directories so each account’s sidebar lists the union. Fully quit and relaunch the desktop app afterward; opening a mirrored session resumes it with full history.

harn claude-desktop tidy handles the other side of the index. It finds sidebar rows whose mapped Harnery task is done and can archive them in one batch.

Auto-discovered per platform: ~/Library/Application Support/Claude (macOS), %APPDATA%\Claude (Windows), ~/.config/Claude (Linux). Under WSL (the desktop app runs on the Windows side but the CLI runs in the distro), every /mnt/c/Users/<user>/AppData/Roaming/Claude is scanned. Only directories containing a claude-code-sessions/ index count. Override with --data-dir <path> or HARNERY_CLAUDE_DESKTOP_DIR.

Terminal window
harn claude-desktop # summary: data dir(s) + accounts + CLI account
harn claude-desktop accounts # account dirs + session counts; labels the CLI's account
harn claude-desktop sessions # every entry across accounts, newest first
harn claude-desktop sessions --account 6d725f2a # one account (uuid prefix)
harn claude-desktop sessions --archived # include archived entries
harn claude-desktop mirror --all # dry-run: plan the union copy
harn claude-desktop mirror --all --yes # apply
harn claude-desktop mirror --session "shopify theme" --yes # by title substring
harn claude-desktop mirror --session <cli-session-id> --yes # by exact session id
harn claude-desktop mirror --all --to 6d725f2a --yes # only INTO one account
harn claude-desktop mirror --all --from e6c7dc4f --yes # only FROM one account
harn claude-desktop tidy # dry-run: plan archives for done sessions
harn claude-desktop tidy --account 6d725f2a # limit the plan to one account prefix
harn claude-desktop tidy --yes # archive the planned entries
harn claude-desktop tidy --include-legacy-prefix # include old hand-labeled [DONE] rows

mirror is dry-run by default: it prints the planned copies and exits; --yes applies them. It is idempotent: entries the target account already lists (matched by cliSessionId, falling back to filename) are skipped, so re-running after every account switch is safe and cheap. Archived entries are skipped unless --include-archived.

tidy joins each desktop entry’s cliSessionId to Harnery’s canonical event ledger. An entry qualifies only when its latest coord.lifecycle_changed event is done. The command reports active, blocked, and unmatched entries, plus counts for each skip reason. Already archived entries appear in the counts instead of filling the output with old rows. A title that merely starts with [DONE] does not qualify, and [BLOCKED] entries are always skipped.

The default is a dry-run. Add --yes to set isArchived: true in each qualifying entry. Each update rereads the current JSON, changes only the archive flag, and replaces the file atomically. Repeating the command is safe because already archived entries become skips.

--include-legacy-prefix is an explicit compatibility mode for sessions labeled by hand before lifecycle events existed. It accepts an unmatched [DONE] title, but it never overrides a matching active or blocked lifecycle event. Use --account <uuid-prefix> to limit either a dry-run or an applied batch to selected account directories.

After an applied batch, fully quit and relaunch the desktop app. Closing its window usually leaves it running, so the sidebar may not refresh until the app process restarts.

  • The entry-file format is the desktop app’s private state, not a public API. Mirror copies files verbatim (never rewrites them), so a format change degrades to “copies stop being useful”, not corruption, though a future app version could change the layout entirely.
  • After mirroring, both accounts list the same session, backed by one transcript file. Don’t drive the same session from two signed-in accounts at once.
  • The desktop app reads the index at startup: fully quit it (system tray → quit; the window X usually just minimizes) and relaunch to see mirrored sessions.