v0.7.x
currentSession history you can read and search, a two-row status line you choose the segments of, a usage notch for the desktop app, and one-line installers that work.
- Security
Security fixes
- A cloned repo could plant a command that ran in every later Claude Code session of a profile: its `.claude/settings.json` could set keys like `apiKeyHelper`, `awsAuthRefresh`, `gcpAuthRefresh`, `otelHeadersHelper`, `fileSuggestion`, `subagentStatusLine` or `processWrapper`, and the first `ccpm run` inside it copied them into the profile for good. An untrusted project may now contribute only a short allowlist of display, editor and model keys, and project settings are never written into a profile at all: Claude Code reads them from the repo itself, behind its own trust prompt.
- `ccpm import-bundle` restored a bundle's hooks, MCP servers, command settings and `env` keys without asking, so a shared "team profile" could run a command or redirect your token on the next launch. It now lists everything the bundle would run and asks, defaulting to no. Without a terminal it refuses unless you pass `--trust-bundle`.
- `ccpm plugin remove` deleted whatever file a plugin's recorded install path named. It now removes only that plugin's own link under the profile's plugin cache.
- `ccpm export` no longer puts your session history (transcripts, todos, shell snapshots, prompt history) in the bundle, since it can hold secrets you pasted into a session. Pass `--include-history` for a move between your own machines.
- `ccpm sessions list` printed transcript text raw, so a crafted prompt could send terminal control sequences, including one that writes your clipboard. Every field is now sanitized.
- `ccpm settings apply` now treats the command-running keys above as dangerous, the same as hooks and permissions: a patch that sets them needs `--i-know-what-this-does`.
- Fixed
Profile lifecycle and settings fixes
- Removing or renaming a profile left its settings and MCP fragments behind, so a new profile created under the old name inherited the removed profile's MCP servers, including their tokens. `remove` now deletes them, `rename` carries them to the new name, and `add` clears anything an older ccpm left under that name.
- `ccpm remove` now deletes the profile's OAuth login from the keychain. Before, adding a profile with the same name came back signed in as the old account.
- Removing or renaming the default profile, or running `ccpm uninstall`, left IDEs and GUI apps pointed at a directory that no longer existed. Remove and uninstall now clear the system default and rename moves it to the new name. Uninstall also deletes every OAuth login and the vault master key, as its help always said.
- `ccpm clone` and `ccpm import from-profile` now copy the whole profile, including profile-scoped skills, settings and MCP servers. `import from-profile` used to fail on almost every real profile.
- Removing a setting or MCP server at its source (`ccpm mcp remove`, `ccpm settings unset`, or deleting it from `~/.claude/settings.json`) now removes it from the profile too. Before, anything that reached a profile once stayed there. Keys Claude Code or you wrote during a session, such as `/model`, are kept.
- Enterprise managed settings on Windows are now read from `C:\Program Files\ClaudeCode`, where Claude Code keeps them. The old path never loaded.
- `ccpm trust` now only changes what ccpm shows in `ccpm settings show` and the desktop app. Claude Code applies a repo's settings and MCP servers itself, so trusting a repo no longer copies its hooks and servers into your profile.
- Saving a login larger than about 4 KB to the macOS keychain (possible once several MCP servers hold OAuth tokens) silently wrote a truncated, broken copy over the good one. `set-default`, `clone`, `rename` and `auth restore` now stop with a clear error and leave the keychain unchanged.
- A locked keychain or a dismissed prompt while reading the vault master key made ccpm replace it, leaving every existing backup undecryptable. A new key is now created only when none exists, and `ccpm auth restore` never creates one.
- Adopting host assets on `ccpm run` could delete a profile's own skill or agent folder when `~/.claude` had one with the same name. The profile's copy now always wins and is never removed.
- `remove` and `uninstall` without `--force` and without a terminal now fail instead of printing "Cancelled." and exiting 0. `uninstall --force` works; it used to fail with an unknown flag.
- FixedImproved
CLI fixes: environment, concurrency, sessions and usage
- `ccpm run` added `CLAUDE_CONFIG_DIR`, `ANTHROPIC_API_KEY` and the profile's env on top of copies inherited from your shell, and an npm-installed `claude` read the inherited ones. After `ccpm use`, with a system default set, or inside a Claude Bash tool, `ccpm run b` could start as another profile. Inherited values are now replaced: profile env beats your shell, and `--ccpm-env` beats both.
- Running ccpm commands in parallel no longer loses writes. `env`, `settings`, `permissions`, `hooks` and `trust` edits now wait for each other; 40 parallel `env set` calls used to keep one key.
- The `ccpm use` shell hook now works in fish and PowerShell, and in bash and zsh it returns a failure code when the profile does not exist.
- A mistyped subcommand such as `ccpm config sett` now fails with `unknown command` and exits 1 instead of printing help and exiting 0. A bare group command still prints help.
- `ccpm doctor` exits 4 when `config.json` is corrupt, `ccpm sync --all --dry-run` with no profiles reports an error instead of crashing, and a symlink loop under `~/.claude` no longer hangs `doctor`, `import default` or `run`.
- `ccpm sessions list` no longer fills the list with subagent transcripts, which outnumber real sessions about nine to one. It finds sessions in directories reached through a symlink, and its date column is now LAST ACTIVE, matching the sort order. `--json` gives `started` (the first timestamp) and a new `last_active`.
- A symlinked or special file among a profile's transcripts could make `ccpm usage`, the usage hook and the desktop Usage tab read without end. They now skip anything that is not a regular file and cap line length.
- Plugins whose content changed without a version bump are now cached as `<version>+<commit>` next to the old copy, instead of keeping stale files under the new commit. `ccpm plugin gc` stops, naming the profile, when a profile's plugin list cannot be read, instead of deleting caches it still uses.
- `ccpm export` now includes the profile's skills, agents and commands (it used to drop every linked one) and its settings and MCP fragments. Older bundles still import.
- FixedImproved
CCPM Desktop fixes
- The notch's hover card no longer stays on screen after the pointer leaves, and it stays up with fresh numbers when usage refreshes under a resting pointer. The notch now always appears on the main display (the one with the menu bar), and a hidden notch no longer reacts to the mouse.
- The MCP & Plugins tab listed other profiles' MCP servers, and removing one of those did nothing useful. It now shows only the selected profile's servers, and `ccpm mcp remove --scope profile` refuses a profile that does not hold the server.
- Removing an MCP server, uninstalling a plugin, removing a permission rule and unsetting an env var now ask for confirmation.
- Env values are masked until you reveal them, so tokens no longer show up on screen shares.
- Error messages show in full, and a broken `settings.json` is reported on the Permissions, Settings and Cascade tabs instead of showing them empty.
- When the app cannot replace itself (it is running from a read-only folder, or from the temporary location macOS uses for apps that were never moved), the updater says so instead of quitting. A failed update reopens the old app.
- A usage window whose reset time has passed shows 0% instead of its old reading, and the plan now reads like "Max 5x" instead of the raw tier name.
- With ten or more profiles on a short screen edge, the notch drew some rings outside its panel. It now lays out as many rings as fit.
- Dialogs return focus to the button that opened them and no longer submit twice when you press Enter quickly, and a failed add keeps what you typed. Add server, Install plugin and New key reopen empty.
- Fixed
Update check right after upgrading
- Right after upgrading from an older version, `ccpm version --check-latest` could report "Up to date (latest release: desktop-v0.1.1)" for up to a day, because it trusted a result the older version had cached. A cached result is now used only if it is a CLI release; anything else is checked again.
- Fixed
Quieter, safer one-line installers
- Both one-line installers printed "curl: (56) Failure writing output to destination" before installing. The install itself succeeded; the message came from the script stopping its read of the release list early. They now read the whole list and print nothing alarming.
- The desktop installer quit any running CCPM, even when installing into a different folder. It now quits only the copy it is about to replace.
- AddedImproved
CCPM Desktop: the usage notch
- The usage rail is now a notch that grows out of the screen edge. Folded, it is a slim pill; reach for it and it opens to show a ring per profile. On the top edge of a Mac with a camera notch, it joins the camera notch.
- Its settings moved out of the title bar into a new Usage notch section in the Settings tab. One switch turns the notch on or off. While it is on, choose whether it opens on hover or stays open, which edge it sits on (Top, Left, Right or Bottom), and which profiles get a ring. Turning it off and back on keeps your choices.
- Pick the 5-hour or the weekly window as the main ring; the other becomes the thin inner ring. You can also hide the percentage under each ring, which gives the rings more room: useful on the top edge with several profiles, where the labels get very small.
- If no profile has a reading yet, the section tells you why. The notch shows the limits that ccpm's own status line records while you use Claude Code, so a profile with a custom statusLine shows a dash.
- AddedFixed
Installers that work, and a desktop app that opens
- The desktop app now installs with one line: `curl -fsSL https://raw.githubusercontent.com/nitin-1926/claude-code-profile-manager/main/scripts/install-desktop.sh | sh`. It picks your chip, verifies the checksum and installs to Applications. Open CCPM from there as usual and it starts with no warning: a browser-downloaded copy is refused by macOS as "damaged" because the app is not notarized, but `curl` does not mark what it downloads.
- The CLI's curl installer failed with a download error whenever the newest GitHub release was a desktop build, which it has been since the desktop app first shipped. It now picks the newest CLI release by tag, and desktop releases no longer claim GitHub's "Latest" badge.
- `ccpm version --check-latest` reported "Up to date" against the desktop app's version for the same reason, so it never told anyone a CLI update existed. It now compares against the newest CLI release.
- Fixed
History: honest failures and accurate counts
- A transcript the reader cannot open now says why, with a Retry, instead of rendering as an empty conversation. A pruned file, a permission error and a genuinely empty session all looked identical before.
- Opening a search hit in a transcript written since the tab last listed — a subagent file a running session just spawned — used to show a blank page. The session index is now rebuilt on demand rather than the hit being refused.
- Search no longer claims a result was truncated when it was complete. A session holding exactly its per-session match budget reported "3+ matches, results truncated" for a result that had found everything.
- Search reports how many transcripts it skipped because a session had already filled its budget. It previously said "truncated" while reporting zero skipped, with whole subagent transcripts left unread.
- `ccpm sessions list` now finds sessions in directories containing emoji or other non-BMP characters. Claude Code encodes those paths per UTF-16 unit, so its directory name carries two dashes where ccpm wrote one, and the lookup silently matched nothing.
- Opening the History tab twice at once can no longer drop a just-added session from the list, and the tab no longer triggers its own refresh by writing its index inside the watched directory.
- Search now finds text inside code Claude wrote even when it contains quotes or backslashes: `"use strict"` or `C:\Users` inside a Write or Edit used to match nothing, because tool inputs were searched in their escaped JSON form.
- The reader's Next and Previous prompt buttons now step to the right prompt from anywhere, including from a search hit on a tool call, where they used to jump the wrong way. They also work across long stretches of tool calls with no prompts, and at the last prompt they stay put instead of leaving you on the final page.
- Subagent transcripts opened from a search hit showed an empty page; their turns now show, and a new toggle shows or hides subagent turns anywhere.
- Going Back from the reader to your search results keeps them and your scroll position, instead of re-running the whole search.
- Saving the global status line layout no longer leaves the profile editor showing changes you did not make.
- Added
Status line: choose your own segments
- `ccpm statusline configure` picks which of the nine segments the status line shows, and on which row. It asks for row 1, then row 2 from what is left, and switches off anything you do not pick — then prints the result against sample data so you can see it before starting a session. You are offered it automatically the first time you run `ccpm config set statusline true`.
- Layouts have two scopes: a **global default** for every profile, and a **per-profile override** that wins over it. `ccpm statusline configure --profile work` sets one; `--reset --profile work` drops it again.
- The desktop app's **Settings** tab has the same controls — a row per segment with Off / Row 1 / Row 2, a live preview of both rows, and a switch between the global default and this profile's override.
- Scripts can skip the prompts: `--row1`/`--row2`/`--off` take comma-separated keys and must name all nine between them. An incomplete list is refused rather than filled in, because a segment named nowhere is treated as newly introduced — that is how a layout saved today picks up a segment added in a later release instead of silently never showing it.
- Switching a segment on never invents data: the 5h and 7d windows still show nothing on an API-key profile, because Claude Code sends no rate limits for one. Switching `branch` off also stops ccpm reading `.git/HEAD` on every assistant message.
- Order within a row is yours as well — move-up/move-down controls in the desktop app, and `--row1 a,b,c` renders in the order you give. The interactive picker keeps an order you already set instead of re-sorting it.
- Fixed: every ccpm command printed its error message twice, once from cobra and once from ccpm. Now once.
- Improved
Status line: two rows, with repo, branch and effort
- The in-TUI status line is now **two rows** instead of one. Row 1 is the session — profile, repo (with the subdirectory you are in), git branch, model, context used. Row 2 is the budget — reasoning effort, the 5h and 7d usage windows with the date each renews, session cost. The split is by what you consult them for: row 1 is what you check when you switch windows and need to know you are in the right place, row 2 is the separate question of how much is left. It also makes room for four fields the single line had no space for.
- Reset times now give the day and date when the renewal is not today. A bare "08:25" on the seven-day window read as this morning when it was four days out, and a bare weekday still left you counting forward to work out the date.
- The branch is read straight from `.git/HEAD` rather than by shelling out to git — this runs on every assistant message, and a subprocess each time is exactly the cost Claude Code's own docs warn about.
- AddedFixed
History: browse, read and search your past sessions
- New **History** tab in the desktop app. Every session the profile has run, listed newest first with a real title (Claude Code's own generated one where it exists, otherwise your opening prompt), the project and branch, the model, response and turn counts, tokens, and an estimated cost.
- Click a session to read the actual conversation. Tool calls fold to a one-line chip you can expand; thinking blocks and subagent turns sit behind toggles. Long sessions page rather than loading whole — the largest transcript on a real machine is 77 MB and decodes to over ten thousand turns.
- Full-text search across every transcript in a profile, with no index to build or keep fresh. Results are snippets grouped by session, newest first; clicking one opens the reader at that exact message, expanding whatever chip it is hiding inside. Search covers your prompts, Claude's replies, the commands and file paths it ran, and the work its subagents did — which is roughly three quarters of what a profile actually contains. Tool *output* is one toggle away, and is excluded by default because that is where pasted credentials tend to end up.
- Resume any listed session in Terminal, in the directory it was originally started from.
- The Usage tab's "Recent sessions" list now points at History instead of duplicating it.
- Fixed `ccpm sessions list <profile>`: scoped to the current project it reported no sessions, because the directory-name encoder dropped a leading dash and collapsed repeated separators, so it never matched what Claude Code actually writes on disk. It now matches, and `--all` is no longer the only way to see anything.
- Added
CCPM Desktop: the usage rail
- A floating usage rail for macOS: one ring per profile, pinned to a screen edge, showing your Claude limits at a glance. The outer arc is the 5-hour window, the inner one the 7-day window, coloured by how much headroom is left — on the same thresholds `ccpm statusline` uses, so the rail and your terminal never disagree.
- Hover a ring for the detail: which account and plan it belongs to, how old the reading is, and per window a reset time, a bar, and the percentage used. Its settings live in the Settings tab (see the usage notch entry above).
- The numbers come from the rate-limit windows Claude Code already sends to `ccpm statusline`, cached per profile. No API call and no credentials are read. The trade-off is that a profile's reading only refreshes when you use Claude Code on it, so the rail always tells you how old the number is and marks it stale rather than passing it off as live.
- Profiles that cannot report limits say so: an unused profile shows an empty ring and "No reading yet" instead of a misleading 0%, and non-subscription profiles explain that their plan never reports limits.