cpm 0.3.0: profil je teď prostředí, ne jen účet

cpm 0.3.0: profil je teď prostředí, ne jen účet

Nová verze Claude Profile Manageru: vlastní MCP servery a settings pro každý profil, oddělená historie sessions, správa profilů z příkazové řádky, cpm exec pro skripty a CI a kontrola API klíčů před cloud syncem.

Jakub Kontra
Jakub Kontra
Developer

Firemní profil má od dneška vlastní Jira MCP server, který osobní profil nikdy neuvidí. Stačí na to tři řádky v config.toml. V dubnu jsem tu psal o cpm jako o nástroji na víc účtů Claude Code na jednom počítači. Verze 0.2.0 mezitím přidala cloud sync nastavení (settings.json, CLAUDE.md, commands/…) přes privátní git repo. Verze 0.3.0 rozšiřuje, co všechno se s účtem přepíná. Vybírám jen věci, které mění použití.

Profil je teď prostředí, ne jen token

Každý profil může mít vlastní MCP servery. mcp_exclude skryje nechtěné globální servery a [profiles.work.mcp_servers.jira] přidá server jen pro tenhle profil se stejnými klíči jako v ~/.claude.json. Při shodě jmen vyhrává profilový server nad globálním.

Stejně funguje [profiles.work.settings]: hodnoty se do settings.json hluboce slučují (deep merge). Mapy se spojí, pole a skalární hodnoty profil nahradí. Attribution, dosud jediné profilové nastavení v settings.json, je teď jen jeden z klíčů.

Sdílené adresáře jsou v profilu symlinky na ~/.claude/<dir>. isolate = ["projects"] symlink nahradí prázdným skutečným adresářem, takže profil má vlastní historii sessions – tu Claude Code drží v projects/. Skutečný adresář s daty cpm nikdy nemaže.

Nový profil dostane z ~/.claude.json jen vybrané klíče: onboarding flagy, theme a způsob instalace, nikdy oauthAccount ani projects. Do profilu pak cpm hned zapíše i MCP servery, tedy globální bez mcp_exclude a profilové. První claude-work tak přeskočí onboarding a servery vidí hned.

[profiles.work]
description = "Firemní účet"
isolate = ["projects"]
mcp_exclude = ["personal-notes"]

[profiles.work.mcp_servers.jira]
type = "http"
url = "https://jira.example.com/mcp"

[profiles.work.settings]
model = "sonnet"

Profily bez ručního editování configu

cpm add work -d "Firemní účet" -m sonnet -e JIRA_TOKEN=… zapíše profil do configu a rovnou ho nainstaluje. cpm remove work --purge odstraní wrapper, adresář, credentials i záznam v Keychainu; potvrzení přeskočí --yes. cpm clone nový profil zapíše sám.

Wrapper claude-work umí spustit jen claude. cpm exec <profile> -- <cmd> spustí s prostředím profilu cokoli jiného: skript volající claude -p, git hook, krok v CI nebo nástroj, který potřebuje třeba Vertex proměnné z [profiles.vertex.env].

cpm exec work -- ./scripts/review.sh
cpm exec work -- .git/hooks/prepare-commit-msg

Co cpm hlídá za tebe

Před pushem do cloudu cpm projde env blok v settings*.json a s API klíčem push zastaví – klíč v historii gitu už nevezmeš zpět. Přebiješ to přes --allow-secrets.

Shell hook (eval "$(cpm hook)") při odchodu z projektu s .claude-profile maže jen proměnné, které sám nastavil (CPM_MANAGED_VARS), takže tvoje vlastní proměnné ANTHROPIC_* přežijí změnu adresáře. cpm hook --default personal mimo takové projekty přepne na výchozí profil.

Na macOS list, credentials i běžný doctor jen ověří, že záznam v Keychainu existuje, a token nečtou, aby macOS nevyskakoval s dotazem na přístup. Proto cpm list ukáže „authenticated“, ale expiraci a typ předplatného uvidíš až s doctor --verify, který token přečte. Na Linuxu je token v .credentials.json a expiraci ukáže cpm credentials i doctor. doctor vrací exit 1, když některá kontrola skončí chybou, takže se hodí do CI.

Baseline v <profil>/.cpm/baseline/ pamatuje stav po syncu. Díky ní install --sync rozliší lokální úpravu od změny upstream a nepřepíše ti rozdělanou práci.

A dál: --json u čtecích příkazů, fish, cpm completion, cloud diff, push --dry-run, auto_push a auto_pull_on_install.

Co se opravilo

  • cpm cloud pull zapisuje profily z cloudu do config.toml.
  • cpm cloud remote uloží URL i vedle zakomentovaného # [cloud] z example configu.
  • cpm list na macOS ukazuje „authenticated“ (viz výše).
  • Parser expirace čte claudeAiOauth.expiresAt správně v milisekundách.
  • auto_push funguje.
  • cpm upgrade ověřuje SHA-256 checksum a nahrazuje běžící binárku.
  • Hodnoty env proměnných ve wrapperech jsou escapované a HTTP volání mají timeout 10 s.
  • Zbytek je pod „Fixed“ v CHANGELOGu.

Zpětná kompatibilita

Nová pole jsou volitelná, starý config funguje dál. Záměrné změny jsou tři. Jména profilů smí obsahovat jen [A-Za-z0-9_-]. Cloud sync vynechává settings.local.json, protože ten patří ke konkrétnímu stroji; vrátíš ho přes include = ["settings.local.json"]. A první cpm install po upgradu přegeneruje wrappery – pokud jsi je ručně neupravoval, nemusíš dělat nic.

Jak to vzniklo

Jeden prompt v plan módu Claude Code: „Podívej se, co by se dalo zlepšit, případně přidat za feature.“ Plán jsem schválil celý, proběhl v jedné session a každý krok má vlastní commit, který prošel go test, go vet a golangci-lint. Výstupy jsem četl průběžně a před merge verzi ověřil na svém stroji: cpm install je idempotentní, po cpm add a cpm remove --purge se config vrátil byte po bytu a hook v zsh přepíná, jak má. PR #3 má 19 commitů, 58 souborů a +6 312 / −1 189 řádků. Testovacích funkcí je 174, bylo jich 72.

V dubnu cpm přepínal účty, teď přepíná celé prostředí. brew upgrade cpm, zbytek najdeš v repu.