Skip to content
v0.8.2history

Changelog

How ccpm has grown, release by release. Each chapter below is one minor series, with the themed changes and patch fixes that shipped under it. For every tagged build, see GitHub Releases.

  1. v0.7.x

    current

    Session 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.
  2. v0.6.x

    Per-profile token usage with a contribution heatmap and cost estimates, and the optional macOS desktop app.

    • Added

      CCPM Desktop: download for macOS

      • The optional desktop app is now a downloadable .dmg on GitHub Releases — a ~3–4 MB build for your Mac's chip (Apple Silicon or Intel). Open it and drag CCPM into Applications. No more building from source to try the GUI.
      • First launch needs a one-time Gatekeeper bypass (right-click → Open) because the app isn't notarized yet. The app uses the ccpm CLI for write actions, so keep the CLI installed.
      • The app now updates itself: it checks for new releases on launch and, on your click, downloads and swaps in the new version in place — no re-downloading or re-dragging to Applications. The desktop app versions independently of the CLI, shipping on its own `desktop-v*` release tags.
    • ImprovedAddedFixed

      Usage: more accurate counts, cost estimates, and 5-hour blocks

      • Fixed a token undercount: usage is now deduplicated by (message id + request id) with the largest usage snapshot winning, matching how Claude Code appends growing snapshots for one response. This corrects both cross-request collisions and a first-seen under-count. Existing usage stores re-ingest once to adopt the corrected numbers.
      • The desktop app's Usage tab now shows an API-equivalent dollar-cost estimate per total, model, and project (estimated from public list prices — not subscription billing).
      • New live "current 5-hour block" card in the desktop Usage tab: cost so far, burn rate ($/hr), time left in the window, and projected end-of-block cost — inspired by ccusage.
      • The desktop app also gained a Settings editor tab and plugin install/remove.
    • Added

      CCPM Desktop — an optional native app for managing profiles

      • A new desktop GUI (in `ccpm/desktop/`, built with Wails) sits alongside the CLI: a sidebar of profiles plus per-profile tabs for Overview, Cascade, Assets, MCP & Plugins, Permissions, Usage, and Health. It reuses ccpm's own engine for reads and shells out to the CLI for writes, so it stays exactly in sync with what `ccpm` does.
      • The Cascade tab shows the effective host→global→profile config with provenance badges on every asset and setting, and flags overrides/shadowing — so you can finally see what actually resolves, and why.
      • Clone, rename, delete, open, and run profiles from the toolbar; add/remove assets and MCP servers, toggle plugins, and edit permissions/env without touching JSON. The view auto-refreshes when the CLI changes things underneath it.
      • Build it with `make desktop` (needs the Wails CLI). It's local-first, no signup, and unsigned for now (one-time Gatekeeper bypass on macOS). Creating a profile or importing `~/.claude` opens a Terminal to complete sign-in.
    • Improved

      `ccpm usage` heatmap is now amber

      • The contribution heatmap switched from purple to amber so the CLI matches the new CCPM Desktop theme. `NO_COLOR` still renders plain glyphs.
    • Added

      `ccpm usage` — per-profile token usage with a contribution heatmap

      • New `ccpm usage [profile]` reports token usage (input, output, cache-write, cache-read) read straight from a profile's Claude Code session transcripts — fully retroactive over your existing history, with no dollar cost computed.
      • On a terminal it opens an interactive dashboard — tabbed Overview/Days/Models/Projects/Sessions, switch profile with `[`/`]`, cycle the time window with `w`, scroll with arrows. The Overview shows totals and a GitHub-style contribution heatmap rendered in purple. Use `--plain`, `--json`, or `--by-model`/`--by-project`/`--sessions`/`--all`/`--since` for static, scriptable output.
      • Counts are correct by construction: Claude Code writes each response as several transcript lines sharing one message id, so totals are deduplicated by message id (a naive sum over-counts ~3x).
      • Data is maintained incrementally in a local per-profile store (`<profileDir>/usage/`) — each run reads only new transcript bytes. Opt in to `ccpm config set usage_tracking true` to keep it warm via a SessionEnd hook; `ccpm usage` works without it.
  3. v0.5.x

    Profile backup & cloning, shell completions, prompt and in-TUI status-line integration, and concurrency-safe credential handling.

    • Improved

      Status line now matches /usage and is colour-coded

      • The `5h`/`7d` usage segments now show the percentage **used**, matching Claude's own `/usage` panel, so the numbers line up instead of reading as the inverse.
      • The line is now colour-coded: the usage percentage shades green → amber → red as your remaining headroom shrinks, with orange window labels and a yellow reset clock. Set `NO_COLOR` for plain text.
    • Added

      In-TUI status line: see which profile is running, plus usage and limits

      • `ccpm run` now shows which profile a session is using right inside the Claude Code window — a status line pinned to the bottom that reads e.g. `⬢ work · Sonnet 4.6 · ctx 34% · 5h 58% ↺16:15 · 7d 88% · $1.23`.
      • For Claude Pro/Max accounts it surfaces how much of your rolling **5-hour and 7-day usage windows** is left (remaining %, with the reset time), plus current context fill and session cost. API-key profiles show profile, model, and cost.
      • It's wired in automatically when a profile has no status line of its own, and never overwrites one you set in `~/.claude/settings.json`, a profile, or a trusted project. Opt out with `ccpm config set statusline false`, per-launch with `ccpm run <profile> --no-statusline`, or remove an injected one with `ccpm settings statusline "" --profile <name>`.
    • v0.5.0
      Added

      Profile backup, cloning, shell completions, and prompt integration

      • `ccpm export <profile>` packages a profile's skills, agents, commands, rules, hooks, MCP servers, plugins, and settings into a portable `.tar.gz`. `ccpm import-bundle <file>` restores it on another machine (path-traversal-safe). Credentials are excluded by default — re-authenticate with `ccpm auth refresh` after restoring, or pass `--include-credentials` for a trusted same-user move.
      • `ccpm clone <source> <new-name>` duplicates an existing profile (assets, settings, and auth). Pass `--no-auth` for an assets-only copy. Note: OAuth clones share the source account's tokens, so for a long-lived clone prefer `--no-auth` and a fresh login.
      • `ccpm completion bash|zsh|fish|powershell` emits shell completion scripts, including live completion of your profile names for `run`, `use`, `remove`, `rename`, `set-default`, `clone`, and `export`.
      • `ccpm prompt` prints the active profile name for embedding in your shell prompt (PS1, starship, powerlevel10k), so a terminal always shows which account it's bound to. Supports `--format` and `--show-default`.
      • `ccpm list --json` emits machine-readable JSON for scripting, CI, and status lines.
      • `ccpm doctor --fix` prunes dangling shared-asset symlinks (doctor was previously read-only).
      • Distribution: the macOS/Linux/Windows builds now ship with cosign-signed checksums.
    • FixedSecurity

      Concurrency-safe credential handling and hardening

      • Credential- and config-mutating commands (`set-default`, `rename`, `remove`, `add`, `clone`) now take a global advisory lock, so running two ccpm commands at once can no longer interleave a stale read with a fresh write and clobber a valid refresh token (a cause of spurious `401` re-logins).
      • `config.json`, the shared-asset manifest, and the trust list are now written through the crash-safe atomic-write path, eliminating a window where a crash or concurrent write could corrupt them.
      • Profile/vault directories and ccpm-created `~/.claude` directories are now created `0700` (owner-only), so credential files aren't enumerable by other local users on a shared host.
      • `ccpm rename` reordered its keychain migration and plugin-metadata rewrite so a mid-rename failure can't leave plugin metadata pointing at a directory that was rolled back.
      • Fixed a crash where a malformed or truncated stored API key could panic `ccpm status` / `list` / `auth status`; keys are now masked safely and validated on entry.
      • The npm installer now verifies the downloaded binary's SHA-256 against the release checksums and pins the download to the installed package version (no more silently fetching `latest`).
  4. v0.4.x

    Default-profile UX across IDEs, OAuth correctness on macOS, host-asset cascade, and atomic writes.

    • ImprovedFixed

      `ccpm set-default` now applies to Cursor, VSCode, and Antigravity (macOS)

      • `ccpm set-default <profile>` now registers the chosen profile system-wide on macOS via a user-level LaunchAgent and `launchctl setenv CLAUDE_CONFIG_DIR`. Every newly-launched claude process (terminal, Cursor, VSCode, Antigravity, any GUI app) inherits the profile automatically. Restart any open IDE windows once to pick up the change; future launches and future logins are automatic.
      • `ccpm unset-default` removes the LaunchAgent and unsets the env.
      • Works around a Claude Code v2.1.x bug where the startup OAuth refresh path misfires when CLAUDE_CONFIG_DIR resolves to bare `~/.claude` even with valid tokens in the keychain.
      • Linux and Windows: keychain and identity sync work as before; the GUI-wide env mechanism is macOS-only for now. Terminal use on those platforms is already covered by `ccpm shell-init`.
    • ImprovedFixed

      `ccpm shell-init` now wraps `claude` for terminal use

      • `ccpm shell-init` now emits a `claude()` shell function alongside `ccpm()`. When `CLAUDE_CONFIG_DIR` is unset, plain `claude` invocations from your terminal transparently route through whichever profile `ccpm set-default` selected. This sidesteps a Claude Code v2.1.138 startup-refresh path that 401s when `CLAUDE_CONFIG_DIR` resolves to the bare `~/.claude` even with valid OAuth tokens in the keychain.
      • Added `ccpm config get default_dir`. Prints the default profile's absolute path, or empty if no default is set. Used by the `claude()` wrapper; useful for scripts that need the same lookup.
      • After upgrading, open a fresh terminal (or `source ~/.zshrc`) to pick up the new wrapper. IDE extensions launch claude directly and are not covered by the wrapper.
    • Fixed

      `set-default` no longer reintroduces stale OAuth tokens

      • `ccpm set-default` now folds the current default-slot OAuth payload (and identity in `~/.claude.json`) back into the previously-default profile before loading the new selection. Without this, plain `claude` / VSCode invocations would silently rotate the refresh token in the default slot only, and a later `set-default` of the same profile could copy a stale, already-rotated refresh token back into the default slot, causing the next `claude` call to fail with `401 Invalid authentication credentials`.
      • Save-back is best-effort: any failure prints a yellow warning and the new default still applies.
    • FixedImproved

      Profile rename and default IDE account

      • `ccpm rename` rewrites absolute profile paths inside plugin metadata so renamed profiles keep plugins and skills resolving.
      • `ccpm set-default` for OAuth profiles syncs cached identity fields into `~/.claude.json` so the CLI welcome banner matches the selected default profile.
    • Added

      Consolidate and audit tooling

      • `ccpm consolidate` audits drift across host, share, and profile scopes with safe auto-fixes for dangling symlinks and stale plugin caches; a bundled slash skill documents deeper cleanup.
    • FixedImproved

      OAuth on macOS after renames and status accuracy

      • `ccpm rename` migrates namespaced macOS keychain OAuth entries when a profile directory moves.
      • `ccpm list` and auth status treat short-lived access tokens paired with a refresh token as healthy instead of warning on hourly expiry.
      • macOS keychain writes for OAuth use the Security CLI so stored payloads match what Claude Code reads (no go-keyring base64 wrapper).
    • Improved

      Windows OAuth path (experimental)

      • Experimental Windows credential-manager path for OAuth, mirroring the macOS namespacing model. Still needs real-host verification.
    • ImprovedSecurity

      Atomic writes and managed plugins

      • Multi-file updates (settings + `.claude.json`, manifest + symlinks) go through transactional atomic writes.
      • First-class `ccpm plugin` marketplace install, per-profile enable/disable, and garbage collection of shared cache.
    • AddedImproved

      Host asset cascade

      • Skills, agents, commands, rules, hooks, and host plugin trees under `~/.claude/` can auto-adopt into profiles (opt-out via config or `--no-auto-adopt`).
      • `ccpm doctor` reports cascade and shadowed names where profile-local assets win.
  5. v0.3.x

    Parity with native Claude Code: scoped MCP, transports, permissions, sessions, and a simpler settings model.

    • AddedImproved

      Parity with native Claude Code CLI

      • `ccpm run` forwards unknown flags to `claude` without a `--` separator; `--ccpm-env` for one-shot env overrides.
      • MCP: scopes (global / profile / project), HTTP and SSE transports, `ccpm mcp auth` via native Claude in profile scope.
      • `ccpm env`, `ccpm permissions`, `ccpm sessions list`, managed-settings merge layer, and project settings/MCP discovery from CWD.
    • ImprovedFixed

      Settings model simplification

      • Removed the ccpm-managed global settings fragment. Cross-profile baseline is `~/.claude/settings.json`, with per-profile fragments and owned-keys for durable overrides.
    • FixedImproved

      MCP materialization and imports

      • MCP servers materialize into `<profile>/.claude.json` (where Claude Code reads them), not `settings.json`.
      • `MaterializeMCP` merges host `~/.claude.json` user-scope MCPs so installs outside ccpm still appear in profiles.
      • `ccpm import default` can import MCP entries from `~/.claude.json` with per-item selection.
  6. v0.2.x

    Release automation and cross-platform path handling.

    • AddedImproved

      Release automation and quality

      • `scripts/release.sh` automates version bump, checks, tag, GitHub Release, and npm publish with optional `--stash` for partial trees.
      • Import and fingerprint paths handle symlinked directories and Windows test sandboxes (`USERPROFILE`) correctly.
  7. v0.1.x

    The first public ccpm: profile isolation via `CLAUDE_CONFIG_DIR`, OAuth + API key auth, encrypted vault, shared assets, and a Go-built single binary on npm, curl, and go install.

    • Added

      First public release

      • Core CLI commands: `ccpm add`, `list`, `status`, `use`, `set-default`, `remove`, `auth`, `run`, `shell-init`, `uninstall`.
      • Per-profile isolation by setting `CLAUDE_CONFIG_DIR` to `~/.ccpm/profiles/<name>/`. Two terminals, two accounts, zero conflicts.
      • OAuth and API key flows. API keys live in the OS keychain (macOS Keychain, Linux Secret Service, Windows Credential Manager).
      • Encrypted credential vault under `~/.ccpm/vault/` using AES-256-GCM with a master key in the OS keychain.
      • Shared asset store at `~/.ccpm/share/` for skills and other assets, symlinked into profiles to avoid duplication.
      • Distribution: single static Go binary published to npm (`@ngcodes/ccpm`), curl installer, and `go install`. CI via GitHub Actions; release packaging via GoReleaser.

Have a question about a change? Open the docs and use Ask Me (⌘K / Ctrl+K).