cchost 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,119 @@ All notable changes to `cchost` are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [0.4.1] - 2026-06-04
9
+
10
+ ### Changed
11
+
12
+ - **Shared resources expanded from 4 to 7.** Profiles now also auto-link
13
+ `mcp.json`, `settings.json`, and `CLAUDE.md` into `~/.claude/`, in addition
14
+ to the four directories (`projects/`, `skills/`, `agents/`, `commands/`).
15
+ MCP servers, user settings, and user-level memory are now visible to every
16
+ profile by default — the trust boundary becomes clean: only the three
17
+ credential files (`.credentials.json`, `.claude.json`, `.cc-env.json`) stay
18
+ per-profile.
19
+ - **`cc copy` replaces `cc migrate`.** Same direction (`default → <profile>`),
20
+ same `--force` flag — the verb just matches what the command actually does.
21
+ `cc migrate` still works as a deprecation alias and forwards to `cc copy`
22
+ with a one-line warning; it will be removed in a future version.
23
+ - **`cc link` / `cc unlink` accept `--config`** to target the three single
24
+ files. The three groups now: `--projects`, `--tools`, `--config`. No flag
25
+ still means all 7.
26
+ - **`cc unlink` is non-destructive.** Materializes the current pool content
27
+ into a private directory or file as part of breaking the link, so the
28
+ profile's view of that resource is preserved. Same-name collisions in the
29
+ profile (if any) are kept untouched.
30
+ - **`cc link` refuses to overwrite private content.** If a profile's resource
31
+ already has non-empty private content, `cc link` reports it as `refused`
32
+ and leaves it alone (other resources still link). Move or remove the
33
+ content manually, then re-run.
34
+ - **`cc remove` requires `--force` when private (unlinked) content exists.**
35
+ Symlinked resources are still removed silently (the shared pool is
36
+ untouched); private content prompts the user to acknowledge that its
37
+ content is unique and will be lost.
38
+ - **`cc list` uses a single `--reveal` flag.** Drops `--reveal-email`;
39
+ `--reveal` now shows both the API token (where applicable) and the full
40
+ email. Email mask format also changed for stronger redaction:
41
+ `allen@cyber.co.in` → `a*************.in` (first char + TLD only; the
42
+ domain is no longer visible).
43
+ - **`cc list` "Shared" column is `N/7`.**
44
+
45
+ ### Added
46
+
47
+ - `cc doctor` now backfills missing resource symlinks on existing profiles
48
+ (e.g. v0.4.0 profiles that pre-date `mcp.json` / `settings.json` /
49
+ `CLAUDE.md` sharing). Safe auto-fix when the resource is missing or empty;
50
+ warning-only with manual guidance when private content exists.
51
+ - Windows file symlink fallback: when `fs.symlinkSync(..., 'file')` fails
52
+ with EPERM/UNKNOWN (Developer Mode not enabled), `cc link` falls back to a
53
+ hard link so editing-in-place still propagates between profiles. The
54
+ fallback is noted in the link command output.
55
+
56
+ ### Help
57
+
58
+ - Per-command help (`cc help <cmd>`) now spells out the 7 resources, the
59
+ three flag groups, and what stays per-profile.
60
+
61
+ ## [0.4.0] - 2026-06-04
62
+
63
+ ### Changed (breaking)
64
+
65
+ - **`~/.claude/` is now the shared pool.** Every profile's `projects/`,
66
+ `skills/`, `agents/`, `commands/` symlink directly into Claude Code's own
67
+ default config dir. There is no longer a parallel `~/.claude-shared/` pool:
68
+ the two locations are unified. A profile is now a credential set + a
69
+ symlinked view onto the shared pool.
70
+ - **`cc add` auto-links all four artifact dirs.** New profiles ship with the
71
+ symlinks in place, so a skill, agent, or command installed under any profile
72
+ is immediately visible to every other profile. Bare `claude` (without
73
+ `cc use`) sees the same set too — there is no profile-vs-bare split.
74
+ - **`cc link <profile>` and `cc unlink <profile>` accept `--tools` and
75
+ `--projects` flags** to target a subset:
76
+ - `--tools` → `skills/`, `agents/`, `commands/`
77
+ - `--projects` → `projects/`
78
+ - No flag → all four (current default behavior)
79
+ - **`cc list` "Shared" column expects `4/4`** as the steady state for v0.4
80
+ profiles. `0/4`, `3/4`, etc. show profiles whose tool or project sharing has
81
+ been turned off via `cc unlink --tools` / `--projects`.
82
+
83
+ ### Removed
84
+
85
+ - **`cc migrate default shared` and `cc migrate shared <profile>`.** The shared
86
+ pool was the destination of the first and the source of the second; with the
87
+ pool unified into `~/.claude/`, both directions are no-ops. Use
88
+ `cc link <profile>` / `cc unlink <profile>` to control sharing.
89
+
90
+ ### Migration from 0.3.x
91
+
92
+ The v0.3 pool at `~/.claude-shared/` is folded into `~/.claude/` automatically
93
+ on the next `cc add` or `cc doctor --fix`. The migration:
94
+
95
+ - Moves every entry in `~/.claude-shared/{projects,skills,agents,commands}/`
96
+ into the matching `~/.claude/<sub>/`, renaming on collision (existing
97
+ `~/.claude/` content is never overwritten — duplicates get an `__legacy`
98
+ suffix).
99
+ - Re-points any existing profile symlink that targets `~/.claude-shared/<sub>/`
100
+ to `~/.claude/<sub>/`.
101
+ - Removes `~/.claude-shared/` once empty.
102
+
103
+ Idempotent and non-destructive — re-running is a no-op once the legacy dir is
104
+ gone. `cc doctor` surfaces an explicit warning while the legacy dir still
105
+ exists, with a `--fix` action that runs the migration.
106
+
107
+ ## [0.3.2] - 2026-06-04
108
+
109
+ ### Changed
110
+
111
+ - **`cc list` masks account emails by default.** Emails are shown as
112
+ `i***@example.com` in both the table view and the per-profile detail view,
113
+ including the `--json` output. Pass `--reveal-email` to print them in full.
114
+ The list is now safe to paste in screenshots or issue reports.
115
+ - `--reveal-email` is rejected together with `--json` — same precedent as
116
+ `--reveal`. Scripts that need the real address can read `.claude.json`
117
+ directly.
118
+ - Token masking is unchanged: `--reveal` still works on `cc list <profile>`
119
+ and `--reveal-email` does not affect it.
120
+
8
121
  ## [0.3.1] - 2026-05-19
9
122
 
10
123
  ### Changed
package/README.md CHANGED
@@ -1,8 +1,21 @@
1
1
  # cchost
2
2
 
3
- Host multiple isolated Claude Code accounts on one machine via a single `cc` command. `cc` is a plain Node CLI on your PATH, so it runs the same from PowerShell, cmd, bash, zsh, or fish — there are no shell scripts or rc-file edits involved. Tested on Windows and Linux; macOS is expected to work but is not yet verified.
3
+ > Run multiple isolated Claude Code accounts on one machine — switch between them with a single `cc` command.
4
4
 
5
- Each profile is a complete, isolated `CLAUDE_CONFIG_DIR` — credentials, session history, project state, plugins, and settings. Create one with `cc add <name>`; launch under it with `cc use <name>`.
5
+ [![npm version](https://img.shields.io/npm/v/cchost.svg)](https://www.npmjs.com/package/cchost)
6
+ [![CI](https://github.com/allenhack638/cchost/actions/workflows/ci.yml/badge.svg)](https://github.com/allenhack638/cchost/actions/workflows/ci.yml)
7
+ [![license](https://img.shields.io/npm/l/cchost.svg)](./LICENSE)
8
+ [![node](https://img.shields.io/node/v/cchost.svg)](https://nodejs.org)
9
+
10
+ <!-- Demo: record a ~15s clip of `cc add` → `cc use` → `cc list`, save it as
11
+ docs/demo.gif, and uncomment the line below. -->
12
+ <!-- ![cchost in action](docs/demo.gif) -->
13
+
14
+ Claude Code keeps one account's login, history, and settings in a single config directory. To use a second account you normally have to log out and back in, which loses your place. cchost gives each account its own directory so you can keep several side by side and pick one when you launch.
15
+
16
+ Each profile is a complete, isolated `CLAUDE_CONFIG_DIR`: credentials, session history, project state, plugins, and settings. Create one with `cc add <name>`, launch under it with `cc use <name>`. Nothing is shared between profiles unless you ask for it.
17
+
18
+ `cc` is a plain Node CLI on your PATH, so it works the same from PowerShell, cmd, bash, zsh, or fish. No shell scripts, no rc-file edits. Tested on Windows, Linux, and macOS in CI.
6
19
 
7
20
  ## Install
8
21
 
@@ -16,14 +29,14 @@ Requires Node.js 18+ and Claude Code 2.1.140+ already installed. Get Claude Code
16
29
 
17
30
  | Command | What it does |
18
31
  | --- | --- |
19
- | `cc add <profile>` | Create a subscription profile (logs in with Anthropic OAuth on first use). |
32
+ | `cc add <profile>` | Create a subscription profile (logs in with Anthropic OAuth on first use). Auto-symlinks artifact dirs into `~/.claude/`. |
20
33
  | `cc add <profile> --custom [...]` | Create — or, if it already exists, edit — a profile routed through a custom API endpoint. Opens a wizard, or takes `--base-url=URL --token=TOKEN [--model=…]`. See [Custom endpoints](#custom-endpoints-kimi-openrouter-etc). |
21
34
  | `cc use <profile> [...args]` | Launch Claude under that profile. Profile must already exist. Args after the name are forwarded verbatim to `claude`. |
22
- | `cc list [<profile>] [--json] [--reveal]` | List every profile (login state, email, shared dirs N/4, endpoint), or show one profile in detail. `--reveal` unmasks a custom endpoint's API token. |
23
- | `cc migrate <src> <dest> [--force]` | Copy artifacts from `default`\|`shared` to `shared`\|`<profile>`. Skip-on-collision by default; `--force` overwrites. |
24
- | `cc link <profile> [<profile>...]` | Link a profile's artifact dirs to `~/.claude-shared/`. Migrates existing content; renames on collision. |
25
- | `cc unlink <profile>` | Restore a profile to its own private artifact dirs (copies shared content back). |
26
- | `cc remove <profile>` | Delete a profile. Requires typing the profile name to confirm. |
35
+ | `cc list [<profile>] [--json] [--reveal]` | List every profile (login state, email, shared count N/7, endpoint), or show one profile in detail. Emails and tokens are masked by default; `--reveal` shows both in full. |
36
+ | `cc copy default <profile> [--force]` | Copy `~/.claude/` resources into a profile. Meaningful only when one or more resources have been unlinked via `cc unlink`; otherwise every resource resolves to the same on-disk path and is skipped. Skip-on-collision by default; `--force` overwrites. `cc migrate` is a deprecated alias. |
37
+ | `cc link <profile> [<profile>...] [--projects\|--tools\|--config]` | (Re-)link a profile's resources to `~/.claude/`. No flag = all 7. Refuses to overwrite private content. |
38
+ | `cc unlink <profile> [--projects\|--tools\|--config]` | Break the links and copy current `~/.claude/` content into the profile as private resources. Non-destructive. |
39
+ | `cc remove <profile> [--force]` | Delete a profile. Requires typing the profile name to confirm. `--force` is required when private (unlinked) resources exist. |
27
40
  | `cc doctor [--fix [--force]] [--json]` | Diagnose environment, storage, and platform issues. |
28
41
  | `cc help [command]` | Print usage (top-level, or for a single command). |
29
42
 
@@ -41,88 +54,87 @@ cc remove old-profile
41
54
  `cc list` output:
42
55
 
43
56
  ```
44
- Profile LoggedIn Email Shared Endpoint
45
- kimi false - 0/4 api.moonshot.ai
46
- personal true personal@example.com 4/4 subscription
47
- scratch false - 0/4 subscription
48
- work true work@example.com 0/4 subscription
57
+ Profile LoggedIn Email Shared Endpoint
58
+ kimi false - 7/7 api.moonshot.ai
59
+ personal true p************.com 7/7 subscription
60
+ scratch false - 7/7 subscription
61
+ work true w************.com 7/7 subscription
49
62
  ```
50
63
 
51
- The **Shared** column is a count: how many of the 4 shareable directories
52
- (`projects`, `skills`, `agents`, `commands`) are linked to `~/.claude-shared/`.
64
+ `7/7` is the steady state since v0.4.1 — every profile auto-shares 4 dirs (`projects`, `skills`, `agents`, `commands`) **and** 3 files (`mcp.json`, `settings.json`, `CLAUDE.md`) with `~/.claude/`. A lower number means one or more resources were unlinked via `cc unlink <profile> --projects|--tools|--config`.
53
65
 
54
- - `0/4` — fully isolated; the profile keeps its own private copies.
55
- - `4/4` — fully shared; all four point at the common pool.
56
- - `1/4`, `2/4`, `3/4` — **partial**, and not a normal state. `cc link` links
57
- all four at once and `cc unlink` unlinks all four at once, so you should
58
- normally see only `0/4` or `4/4`.
66
+ Emails are masked by default so the list is safe to paste in screenshots and issue reports. Pass `--reveal` to show them in full (same flag also reveals the API token on custom-endpoint profiles).
59
67
 
60
- A partial count has two causes:
68
+ The **Shared** column is a count: how many of the 7 shareable resources symlink into `~/.claude/`.
61
69
 
62
- 1. **A link partially failed** — one directory could not be linked (a
63
- permission issue, or it was locked) while the others succeeded. `cc link`
64
- reports per-directory failures so this is never silent.
65
- 2. **An upgrade from an older cchost.** Versions before `0.2.1` linked only
66
- `projects/` — the other three shareable directories did not exist yet. A
67
- profile linked under an older version therefore shows `1/4` after you
68
- upgrade.
70
+ - `7/7` — the default since v0.4.1. All four artifact dirs *and* the three
71
+ config files point at the shared pool; a tool, server, or hook configured
72
+ under any profile is immediately visible to every other profile.
73
+ - `6/7`, `5/7`, … — one or more resources were `cc unlink`ed and now hold
74
+ private content.
75
+ - `0/7` — fully isolated; the profile keeps its own copy of everything.
76
+ - `4/7` — typical of a profile created on v0.4.0 before the file resources
77
+ were added. Run `cc doctor --fix` to backfill them.
69
78
 
70
- In both cases the fix is the same — re-run `cc link <profile>`. Already-linked
71
- directories are skipped and the missing ones are linked, bringing the profile
72
- to `4/4`.
79
+ ### What's shared, what's per-profile
73
80
 
74
- ### What migrate copies and what link shares
81
+ Since v0.4.1, **`~/.claude/` is the shared pool**, and **all 7 resources** auto-link into it on `cc add`. The trust boundary is simple: anything that authenticates this profile's identity stays per-profile; everything else is global.
75
82
 
76
- | Artifact | `cc migrate` copies it | `cc link` shares it | Notes |
77
- | --- | :---: | :---: | --- |
78
- | `projects/` | ✓ | ✓ | Resumable conversation transcripts |
79
- | `skills/` | ✓ | ✓ | Custom slash-command scripts |
80
- | `agents/` | ✓ | ✓ | Custom agent definitions |
81
- | `commands/` | ✓ | ✓ | Custom command configs |
82
- | `mcp.json` | ✓ (default→profile only) | — | Per-profile MCP server config; may carry auth tokens |
83
- | `settings.json` | ✓ (default→profile only) | — | Per-profile UI/feature settings |
84
- | `CLAUDE.md` | ✓ (default→profile only) | — | Per-profile project instructions |
85
- | `sessions/` | — | — | Transient per-process state; sharing would corrupt bookkeeping |
86
- | `plugins/` | — | — | Carries auth tokens; deferred to a future opt-in flag |
87
- | `.credentials.json` | — | — | Never touched — each profile keeps its own auth |
88
- | `.claude.json` | — | — | Never touched — re-synced from server on every launch |
89
- | `.cc-env.json` | — | — | Per-profile custom-endpoint config; holds an API key. Never migrated, never linked. |
83
+ | Resource | Location | Shared? | Flag group |
84
+ | --- | --- | :---: | --- |
85
+ | `projects/` | `~/.claude/projects/` | ✓ (symlink) | `--projects` |
86
+ | `skills/` | `~/.claude/skills/` | ✓ (symlink) | `--tools` |
87
+ | `agents/` | `~/.claude/agents/` | ✓ (symlink) | `--tools` |
88
+ | `commands/` | `~/.claude/commands/` | ✓ (symlink) | `--tools` |
89
+ | `mcp.json` | `~/.claude/mcp.json` | ✓ (file symlink / hard link) | `--config` |
90
+ | `settings.json` | `~/.claude/settings.json` | ✓ (file symlink / hard link) | `--config` |
91
+ | `CLAUDE.md` | `~/.claude/CLAUDE.md` | ✓ (file symlink / hard link) | `--config` |
92
+ | `sessions/` | per-profile | — | (never shared) |
93
+ | `plugins/` | per-profile | — | (never shared) |
94
+ | `.credentials.json` | per-profile | — | Anthropic OAuth token. Never touched. |
95
+ | `.claude.json` | per-profile | — | Account identity (re-synced on every launch). |
96
+ | `.cc-env.json` | per-profile | — | Custom-endpoint API key. Never copied, never linked. |
90
97
 
91
- `mcp.json`, `settings.json`, and `CLAUDE.md` are **not** copied to `shared` and are **not** linked because they typically carry auth tokens or per-profile configuration that should not leak across accounts.
98
+ `mcp.json` carries MCP server tokens and `settings.json` carries hooks that can run arbitrary commands. Sharing them means every profile sees the same set — if you need per-profile separation for one of them, `cc unlink <profile> --config` breaks the link and makes that profile's copies private.
92
99
 
93
- ### Migrating existing artifacts
100
+ ### Seeding a private profile from `~/.claude/`
94
101
 
95
- If you've been using Claude Code without profiles, your history lives in `~/.claude/`. Pull it into a profile or the shared pool:
102
+ If a profile has unlinked resources (`cc unlink <p>`) and you want to seed them from the current `~/.claude/`:
96
103
 
97
104
  ```bash
98
- cc migrate default work # copy ~/.claude/* → ~/.claude-profiles/work/
99
- cc migrate default shared # copy ~/.claude/projects,skills,agents,commands → ~/.claude-shared/
100
- cc migrate shared personal # copy ~/.claude-shared/* → ~/.claude-profiles/personal/
101
- cc migrate default work --force # same as first, overwriting anything that already exists
105
+ cc copy default work # copies anything unlinked from ~/.claude/ → work
106
+ cc copy default work --force # same, overwriting if already present
102
107
  ```
103
108
 
104
- This is a **copy** — the source is left untouched. By default, if an entry already exists at the destination it is silently skipped. Pass `--force` to overwrite instead — existing destination content will be cleared.
105
-
106
- Credential files (`.credentials.json`, `.claude.json`) are never copied: each profile keeps its own auth state.
109
+ For a fresh `cc add` profile this is a no-op — every resource already resolves to `~/.claude/` via its symlink, so there's nothing to copy. `cc copy` becomes meaningful only after `cc unlink`. (`cc migrate` is a deprecated alias for `cc copy` and still works.)
107
110
 
108
- ### Shared artifacts across profiles
109
-
110
- If you want each profile to keep separate credentials but share project history and skills (e.g. rotate accounts on the same project when usage limits hit):
111
+ ### Opting out of sharing for a profile
111
112
 
112
113
  ```bash
113
- cc link work
114
- cc link personal
114
+ cc unlink work --tools # private skills/agents/commands for "work" only
115
+ cc unlink work --projects # private projects/ for "work" only
116
+ cc unlink work --config # private mcp.json/settings.json/CLAUDE.md
117
+ cc unlink work # private everything (all 7 unlinked)
118
+ cc link work --tools # re-share just the tools
119
+ cc link work --config # re-share just the config files
115
120
  ```
116
121
 
117
- `work/` and `personal/` each get four linked dirs (`projects`, `skills`, `agents`, `commands`) pointing to `~/.claude-shared/`. On Windows this uses directory junctions (no admin/Developer Mode required); on macOS/Linux, regular symlinks.
122
+ `cc unlink` is non-destructive — current pool content is copied into the profile as a private dir or file before the link is broken, so your view of the resource is preserved. `cc link` refuses to overwrite existing private content; move or remove it manually and re-run.
123
+
124
+ Credential files (`.credentials.json`, `.claude.json`, `.cc-env.json`) are never touched: each profile keeps its own auth state.
125
+
126
+ ### How sharing works under the hood
127
+
128
+ Every profile created by `cc add` ships with 7 links pointing at `~/.claude/<resource>`:
118
129
 
119
- `sessions/` is **never** linked. It holds transient per-process registry state — PID, working directory, status, timestamps — and sharing it would corrupt Claude's running-process bookkeeping. It stays per-profile under `~/.claude-profiles/<name>/sessions/`.
130
+ - Directories use Windows junctions (no admin / Developer Mode required) or POSIX symlinks.
131
+ - Files (`mcp.json`, `settings.json`, `CLAUDE.md`) use file symlinks where possible. On Windows without Developer Mode, file symlinks require elevation — `cc link` falls back to a **hard link** there, which works without admin and behaves identically for edit-in-place flows.
120
132
 
121
- `cc link a b c` links several profiles at once; per-profile failures are reported but don't abort the rest of the batch.
133
+ `sessions/` and `plugins/` are **never** linked. `sessions/` holds transient per-process registry state (PID, status, timestamps) and sharing it would corrupt Claude's running-process bookkeeping. `plugins/` carries auth tokens.
122
134
 
123
- If two profiles share history and you launch them against the same project at the same time, both will write to the same session files (last write wins). Don't do that.
135
+ If two profiles open the same project at the same time, both will write to the same conversation files in `~/.claude/projects/<cwd>/` (last write wins). Either avoid that or run `cc unlink <profile> --projects` on one of them.
124
136
 
125
- `cc remove` is safe with shared profiles — it deletes only the links, never recursing into the shared target.
137
+ `cc remove` is safe with fully-shared profiles — it deletes only the symlinks, leaving `~/.claude/` untouched. If a profile has *private* (unlinked) resources, `cc remove` requires `--force` because that content is unique to the profile and will be lost.
126
138
 
127
139
  ## Custom endpoints (Kimi, OpenRouter, etc.)
128
140
 
@@ -161,7 +173,7 @@ Profile: kimi
161
173
  Directory: /home/you/.claude-profiles/kimi
162
174
  LoggedIn: false
163
175
  Email: -
164
- Shared: 0/4
176
+ Shared: 7/7
165
177
  Endpoint: api.moonshot.ai
166
178
  Base URL: https://api.moonshot.ai/anthropic
167
179
  Token: sk-you...key9 (32 chars)
@@ -172,7 +184,7 @@ Endpoint: api.moonshot.ai
172
184
  Subagent: kimi-k2.5
173
185
  ```
174
186
 
175
- `cc list <profile> --reveal` prints the full API key instead — do not paste that output anywhere.
187
+ `cc list <profile> --reveal` prints the full API key and the full email — do not paste that output anywhere.
176
188
 
177
189
  There is no way to convert a custom-endpoint profile back to a subscription profile. To stop using an endpoint, `cc remove` the profile and recreate it.
178
190
 
@@ -197,9 +209,9 @@ The env var is set on the child process only — that's all `claude` needs.
197
209
 
198
210
  ## Sensitive data
199
211
 
200
- `~/.claude-profiles/<profile>/` holds real OAuth credentials. Treat it like SSH keys: don't commit it, don't share it, don't sync it to public cloud storage. The `.gitignore` shipped with this project excludes profile directories from anywhere they might land. `cc migrate` and `cc link` never copy `.credentials.json` or `.claude.json` across profiles.
212
+ `~/.claude-profiles/<profile>/` holds real OAuth credentials. Treat it like SSH keys: don't commit it, don't share it, don't sync it to public cloud storage. The `.gitignore` shipped with this project excludes profile directories from anywhere they might land. `cc copy` and `cc link` never touch `.credentials.json` or `.claude.json`.
201
213
 
202
- `.cc-env.json` (custom-endpoint config) contains a third-party **API key** — treat it exactly like `.credentials.json`. It is written with user-only file permissions, and `cc migrate`/`cc link` never copy or link it across profiles. `cc list <profile>` masks the token; only `cc list <profile> --reveal` prints it in full.
214
+ `.cc-env.json` (custom-endpoint config) contains a third-party **API key** — treat it exactly like `.credentials.json`. It is written with user-only file permissions, and `cc copy`/`cc link` never copy or link it across profiles. `cc list <profile>` masks the token; only `cc list <profile> --reveal` prints it in full.
203
215
 
204
216
  ## Troubleshooting
205
217
 
package/lib/banner.js ADDED
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ // ASCII banner shown on `cc`, `cc help`, `cc --help`, and the unknown-command
4
+ // fallback. Generated once with figlet's "ANSI Shadow" font and frozen as a
5
+ // literal so the runtime has no dependency on figlet. Plain ASCII / no color —
6
+ // works in any terminal, including ones with NO_COLOR or no TTY.
7
+
8
+ const BANNER =
9
+ '\n' +
10
+ ' ██████╗ ██████╗██╗ ██╗ ██████╗ ███████╗████████╗\n' +
11
+ '██╔════╝██╔════╝██║ ██║██╔═══██╗██╔════╝╚══██╔══╝\n' +
12
+ '██║ ██║ ███████║██║ ██║███████╗ ██║ \n' +
13
+ '██║ ██║ ██╔══██║██║ ██║╚════██║ ██║ \n' +
14
+ '╚██████╗╚██████╗██║ ██║╚██████╔╝███████║ ██║ \n' +
15
+ ' ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝ \n';
16
+
17
+ function renderBanner() {
18
+ let version = '';
19
+ try {
20
+ version = require('../package.json').version;
21
+ } catch {
22
+ // package.json missing — banner still renders without a version.
23
+ }
24
+ const tagline = 'Multi-profile launcher for Claude Code';
25
+ const versionLine = version ? `v${version} — ${tagline}` : tagline;
26
+ return BANNER + ' ' + versionLine + '\n\n';
27
+ }
28
+
29
+ module.exports = { renderBanner, BANNER };