cchost 0.4.3 → 0.5.0
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 +78 -0
- package/README.md +103 -149
- package/lib/banner.js +3 -1
- package/lib/cli.js +220 -98
- package/lib/color.js +3 -1
- package/lib/copy.js +31 -29
- package/lib/doctor.js +201 -68
- package/lib/env.js +65 -9
- package/lib/profiles.js +47 -14
- package/lib/share.js +63 -6
- package/lib/spawn.js +2 -1
- package/package.json +8 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,84 @@ 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.5.0] - 2026-11-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`cchost` command.** The CLI now installs as both `cchost` (primary) and
|
|
13
|
+
`cc` (legacy alias). `cc` is the system C compiler on macOS and Linux, so
|
|
14
|
+
docs, help, and new scripts use `cchost`; the alias stays for backwards
|
|
15
|
+
compatibility.
|
|
16
|
+
- **Inherited-auth warning.** `cchost use` now warns when `ANTHROPIC_API_KEY`,
|
|
17
|
+
`ANTHROPIC_AUTH_TOKEN`, or `CLAUDE_CODE_OAUTH_TOKEN` is set in the shell for a
|
|
18
|
+
subscription profile, because those variables can silently override the
|
|
19
|
+
profile's login. It does not strip them.
|
|
20
|
+
- **Endpoint environment isolation.** Endpoint profiles now drop inherited
|
|
21
|
+
`ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`, and
|
|
22
|
+
`ANTHROPIC_BASE_URL` values the profile does not set itself, with a short
|
|
23
|
+
notice listing what was removed.
|
|
24
|
+
- **macOS login visibility.** `cchost list` reports an inferred Keychain login
|
|
25
|
+
as `true` instead of `false`, exposes `credentialSource` in `--json`, and
|
|
26
|
+
`cchost doctor` explains that Keychain entries are namespaced by the profile's
|
|
27
|
+
exact `CLAUDE_CONFIG_DIR` path.
|
|
28
|
+
- **See what a profile shares.** `cchost list <profile>` prints each of the 7
|
|
29
|
+
resources as `shared`, `private`, `empty`, `missing`, or `foreign-link`;
|
|
30
|
+
`--json` adds a `resources` object.
|
|
31
|
+
- **`--dry-run`** on `cchost link`, `unlink`, and `copy` prints what would
|
|
32
|
+
change without touching the filesystem.
|
|
33
|
+
- **`cchost help sharing`**: a task-oriented guide to what is shared and how to
|
|
34
|
+
make a resource private, share it again, or copy into a profile.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- All README examples, help text, and error hints now use `cchost`.
|
|
39
|
+
- `cchost doctor` no longer reports `/usr/bin/cc` or a real C compiler
|
|
40
|
+
(clang, gcc, ccache) as cchost; a `cc` entry counts only when it resolves to
|
|
41
|
+
cchost, and the two shims from one install still count as one entry.
|
|
42
|
+
- README now separates **credential** isolation from the default shared pool.
|
|
43
|
+
`projects/` (full session transcripts) and `settings.json` / `mcp.json`
|
|
44
|
+
(code-executing config) are shared across profiles by default, and are
|
|
45
|
+
documented as a privacy/security trade-off rather than as isolated state.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- `cchost link` reports a symlink that points outside `~/.claude/` as
|
|
50
|
+
`foreign-link` instead of claiming it is already linked.
|
|
51
|
+
- `cchost doctor --fix` prints and uses the post-fix results; `--json --fix`
|
|
52
|
+
is supported again and emits one post-fix JSON report (fix logs go to stderr).
|
|
53
|
+
- `cchost doctor` no longer warns that macOS subscription profiles may share
|
|
54
|
+
one Keychain login; it explains that entries are namespaced by the exact
|
|
55
|
+
profile path (renaming or moving a profile requires a new login), and stays
|
|
56
|
+
silent when no profile uses a Keychain login.
|
|
57
|
+
- `cchost help migrate` prints command-specific help.
|
|
58
|
+
- `.cc-env.json` is created user-only; optional non-string fields are ignored
|
|
59
|
+
instead of making the profile unusable.
|
|
60
|
+
- Help banner shows the version again, and `NO_COLOR` follows no-color.org
|
|
61
|
+
(a non-empty value disables color; `NO_COLOR=""` leaves it enabled).
|
|
62
|
+
|
|
63
|
+
### Known limitations
|
|
64
|
+
|
|
65
|
+
- **macOS Keychain entries are keyed by the exact profile path.** Claude Code
|
|
66
|
+
(verified with 2.1.319) stores each profile's OAuth token under a service
|
|
67
|
+
name derived from the `CLAUDE_CONFIG_DIR` string, so renaming, moving, or copying a profile — or
|
|
68
|
+
accessing it through a different path spelling or symlinked home — requires a
|
|
69
|
+
fresh login. `cchost list` infers the login from `.claude.json`; it does not
|
|
70
|
+
read the Keychain secret or verify that the token is still live.
|
|
71
|
+
|
|
72
|
+
## [0.4.4] - 2026-06-19
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- **macOS officially supported.** CI has been running the full test matrix on
|
|
77
|
+
`macos-latest` since v0.4.0; documentation now reflects that. README, package
|
|
78
|
+
description, and keywords updated. No code change — macOS users were already
|
|
79
|
+
on a verified path, the claim was just stale.
|
|
80
|
+
- Sharper `package.json` description — leads with the value prop
|
|
81
|
+
("multi-account profile manager for Claude Code") instead of the implementation
|
|
82
|
+
detail. Improves discoverability on `npm search` and the npm package page.
|
|
83
|
+
- README tagline added under the H1 ("nvm, but for your Claude Code accounts")
|
|
84
|
+
and a platforms badge for at-a-glance OS support.
|
|
85
|
+
|
|
8
86
|
## [0.4.3] - 2026-06-07
|
|
9
87
|
|
|
10
88
|
### Fixed
|
package/README.md
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
# cchost
|
|
2
2
|
|
|
3
|
+
> **nvm, but for your Claude Code accounts.** Works on Windows, Linux, and macOS — see [Platform notes](#platform-notes) for macOS credential-storage caveats.
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/cchost)
|
|
4
6
|
[](https://github.com/allenhack638/cchost/actions/workflows/ci.yml)
|
|
5
7
|
[](./LICENSE)
|
|
6
8
|
[](https://nodejs.org)
|
|
9
|
+
[](#install)
|
|
7
10
|
|
|
8
11
|
<p align="center">
|
|
9
|
-
<img src="https://raw.githubusercontent.com/allenhack638/cchost/master/docs/demo.png" alt="cchost CLI —
|
|
12
|
+
<img src="https://raw.githubusercontent.com/allenhack638/cchost/master/docs/demo.png" alt="cchost CLI — cchost list showing masked emails and shared resource counts" width="100%">
|
|
10
13
|
</p>
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
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.
|
|
15
|
+
`cchost` is a multi-account profile manager for [Claude Code](https://code.claude.com).
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
- **Isolated credentials** — each profile is a complete `CLAUDE_CONFIG_DIR` with its own login, endpoint, and credential files. Credentials are never copied between profiles (on macOS, see [Platform notes](#platform-notes) for Keychain caveats). Switch with `cchost use <name>`.
|
|
18
|
+
- **Shared tooling and history by default** — `skills/`, `agents/`, `commands/`, `projects/`, and the config files (`mcp.json`, `settings.json`, `CLAUDE.md`) link across all profiles. That includes session transcripts and code-executing config; see [Sharing model](#sharing-model) before using profiles for separated trust boundaries.
|
|
19
|
+
- **Custom endpoints** — route a profile through any Anthropic-compatible API (Moonshot, OpenRouter, self-hosted vLLM, corporate proxies) instead of Anthropic OAuth.
|
|
20
|
+
- **Zero runtime dependencies** — single Node CLI on your `PATH`. Identical behavior across PowerShell, cmd, bash, zsh, and fish.
|
|
17
21
|
|
|
18
22
|
## Install
|
|
19
23
|
|
|
@@ -21,212 +25,162 @@ Each profile is a complete, isolated `CLAUDE_CONFIG_DIR`: credentials, session h
|
|
|
21
25
|
npm install -g cchost
|
|
22
26
|
```
|
|
23
27
|
|
|
24
|
-
Requires Node.js 18+ and Claude Code 2.1.140+
|
|
28
|
+
Requires Node.js 18+ and Claude Code 2.1.140+ (`npm install -g @anthropic-ai/claude-code`).
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
`cchost` is the primary command. The same binary is also installed as `cc` for
|
|
31
|
+
backwards compatibility, but `cc` is the standard C compiler on macOS and
|
|
32
|
+
Linux — prefer `cchost` in scripts, build files, and daily use.
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
| --- | --- |
|
|
30
|
-
| `cc add <profile>` | Create a subscription profile (logs in with Anthropic OAuth on first use). Auto-symlinks artifact dirs into `~/.claude/`. |
|
|
31
|
-
| `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). |
|
|
32
|
-
| `cc use <profile> [...args]` | Launch Claude under that profile. Profile must already exist. Args after the name are forwarded verbatim to `claude`. |
|
|
33
|
-
| `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. |
|
|
34
|
-
| `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. |
|
|
35
|
-
| `cc link <profile> [<profile>...] [--projects\|--tools\|--config]` | (Re-)link a profile's resources to `~/.claude/`. No flag = all 7. Refuses to overwrite private content. |
|
|
36
|
-
| `cc unlink <profile> [--projects\|--tools\|--config]` | Break the links and copy current `~/.claude/` content into the profile as private resources. Non-destructive. |
|
|
37
|
-
| `cc remove <profile> [--force]` | Delete a profile. Requires typing the profile name to confirm. `--force` is required when private (unlinked) resources exist. |
|
|
38
|
-
| `cc doctor [--fix [--force]] [--json]` | Diagnose environment, storage, and platform issues. |
|
|
39
|
-
| `cc help [command]` | Print usage (top-level, or for a single command). |
|
|
40
|
-
|
|
41
|
-
### Examples
|
|
34
|
+
## Quickstart
|
|
42
35
|
|
|
43
36
|
```bash
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
cc remove old-profile
|
|
37
|
+
cchost add work # create a profile
|
|
38
|
+
cchost use work # launch Claude under it (prompts for login on first run)
|
|
39
|
+
cchost use work --resume # resume the last conversation
|
|
40
|
+
cchost list # see all profiles
|
|
41
|
+
cchost remove old-profile # delete a profile
|
|
50
42
|
```
|
|
51
43
|
|
|
52
|
-
|
|
44
|
+
## Commands
|
|
45
|
+
|
|
46
|
+
| Command | What it does |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `cchost add <profile>` | Create a subscription profile. Logs in via Anthropic OAuth on first `cchost use`. Auto-shares all 7 resources with `~/.claude/`. |
|
|
49
|
+
| `cchost add <profile> --custom [...]` | Create or edit a custom-endpoint profile. Interactive wizard, or `--base-url=URL --token=TOKEN [--model=…]`. See [Custom endpoints](#custom-endpoints). |
|
|
50
|
+
| `cchost use <profile> [...args]` | Launch Claude under that profile. Extra args are forwarded to `claude`. |
|
|
51
|
+
| `cchost list [<profile>] [--json] [--reveal]` | List all profiles, or show one in detail including the state of each of its 7 resources. Emails and tokens are masked by default; `--reveal` prints them in full. |
|
|
52
|
+
| `cchost copy default <profile> [--force] [--dry-run]` | Seed an unlinked profile resource from `~/.claude/`. No-op for fully-shared profiles. |
|
|
53
|
+
| `cchost link <profile> [--projects\|--tools\|--config] [--dry-run]` | Link a profile's resources to `~/.claude/`. Defaults to all 7 when no flag is passed. |
|
|
54
|
+
| `cchost unlink <profile> [--projects\|--tools\|--config] [--dry-run]` | Break the link and make those resources private to the profile. Non-destructive. |
|
|
55
|
+
| `cchost remove <profile> [--force]` | Delete a profile. Requires typing the profile name. `--force` required when private resources exist. |
|
|
56
|
+
| `cchost doctor [--fix [--force]] [--json]` | Diagnose environment, storage, and platform issues. `--fix` applies safe auto-fixes; `--force` is required for destructive ones. |
|
|
57
|
+
| `cchost help [command]` | Print usage. `cchost help sharing` is a task guide to linking, unlinking, and copying. |
|
|
58
|
+
|
|
59
|
+
Sample `cchost list` output:
|
|
53
60
|
|
|
54
61
|
```
|
|
55
62
|
Profile LoggedIn Email Shared Endpoint
|
|
56
63
|
kimi false - 7/7 api.moonshot.ai
|
|
57
64
|
personal true p************.com 7/7 subscription
|
|
58
|
-
scratch false - 7/7 subscription
|
|
59
65
|
work true w************.com 7/7 subscription
|
|
60
66
|
```
|
|
61
67
|
|
|
62
|
-
`
|
|
63
|
-
|
|
64
|
-
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).
|
|
65
|
-
|
|
66
|
-
The **Shared** column is a count: how many of the 7 shareable resources symlink into `~/.claude/`.
|
|
67
|
-
|
|
68
|
-
- `7/7` — the default since v0.4.1. All four artifact dirs *and* the three
|
|
69
|
-
config files point at the shared pool; a tool, server, or hook configured
|
|
70
|
-
under any profile is immediately visible to every other profile.
|
|
71
|
-
- `6/7`, `5/7`, … — one or more resources were `cc unlink`ed and now hold
|
|
72
|
-
private content.
|
|
73
|
-
- `0/7` — fully isolated; the profile keeps its own copy of everything.
|
|
74
|
-
- `4/7` — typical of a profile created on v0.4.0 before the file resources
|
|
75
|
-
were added. Run `cc doctor --fix` to backfill them.
|
|
68
|
+
The `Shared` column counts how many of the 7 shareable resources are linked into `~/.claude/`. `7/7` is the default; lower numbers mean one or more resources have been `cchost unlink`ed and now hold private content.
|
|
76
69
|
|
|
77
|
-
|
|
70
|
+
## Sharing model
|
|
78
71
|
|
|
79
|
-
|
|
72
|
+
On Windows and Linux, anything that authenticates a profile stays per-profile and everything else is shared. On macOS, OAuth credentials live in the login Keychain rather than the profile directory — see [Platform notes](#platform-notes).
|
|
80
73
|
|
|
81
|
-
| Resource |
|
|
82
|
-
| --- |
|
|
83
|
-
| `projects/` |
|
|
84
|
-
| `skills
|
|
85
|
-
| `
|
|
86
|
-
|
|
|
87
|
-
| `
|
|
88
|
-
| `settings.json` | `~/.claude/settings.json` | ✓ (file symlink / hard link) | `--config` |
|
|
89
|
-
| `CLAUDE.md` | `~/.claude/CLAUDE.md` | ✓ (file symlink / hard link) | `--config` |
|
|
90
|
-
| `sessions/` | per-profile | — | (never shared) |
|
|
91
|
-
| `plugins/` | per-profile | — | (never shared) |
|
|
92
|
-
| `.credentials.json` | per-profile | — | Anthropic OAuth token. Never touched. |
|
|
93
|
-
| `.claude.json` | per-profile | — | Account identity (re-synced on every launch). |
|
|
94
|
-
| `.cc-env.json` | per-profile | — | Custom-endpoint API key. Never copied, never linked. |
|
|
74
|
+
| Resource | Shared by default | Flag group |
|
|
75
|
+
| --- | :---: | --- |
|
|
76
|
+
| `projects/` | ✓ | `--projects` |
|
|
77
|
+
| `skills/`, `agents/`, `commands/` | ✓ | `--tools` |
|
|
78
|
+
| `mcp.json`, `settings.json`, `CLAUDE.md` | ✓ | `--config` |
|
|
79
|
+
| `.credentials.json`, `.claude.json`, `.cc-env.json` | never | — |
|
|
80
|
+
| `sessions/`, `plugins/` | never | — |
|
|
95
81
|
|
|
96
|
-
|
|
82
|
+
Sharing uses POSIX symlinks on Linux/macOS and directory junctions on Windows (no admin or Developer Mode required). File resources fall back to a hard link on Windows when symlink creation would require elevation. Note that `mcp.json` and `settings.json` can execute arbitrary code through MCP servers and hooks — if a profile needs an isolated copy of either, run `cchost unlink <profile> --config`.
|
|
97
83
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
cc copy default work # copies anything unlinked from ~/.claude/ → work
|
|
104
|
-
cc copy default work --force # same, overwriting if already present
|
|
105
|
-
```
|
|
84
|
+
> **Privacy note:** the defaults above are convenient, not isolated. `projects/`
|
|
85
|
+
> contains full conversation transcripts, and `settings.json` / `mcp.json` can
|
|
86
|
+
> execute hooks and MCP servers. For a work/personal split, unlink the resources
|
|
87
|
+
> that must not cross over before first use, or use a separate OS account.
|
|
106
88
|
|
|
107
|
-
|
|
89
|
+
To see exactly what a profile shares, run `cchost list <profile>` — it prints each resource as `shared`, `private`, `empty`, `missing`, or `foreign-link`. `cchost help sharing` walks through the common tasks.
|
|
108
90
|
|
|
109
|
-
|
|
91
|
+
To break sharing for a single profile (add `--dry-run` to any of these to preview first):
|
|
110
92
|
|
|
111
93
|
```bash
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
cc link work --config # re-share just the config files
|
|
94
|
+
cchost unlink work --tools # private skills/agents/commands
|
|
95
|
+
cchost unlink work --projects # private projects/
|
|
96
|
+
cchost unlink work --config # private mcp.json/settings.json/CLAUDE.md
|
|
97
|
+
cchost unlink work # all 7 private
|
|
98
|
+
cchost link work --tools # re-share
|
|
118
99
|
```
|
|
119
100
|
|
|
120
|
-
`
|
|
101
|
+
`cchost unlink` is non-destructive — pool content is copied into the profile before the link is broken. `cchost link` refuses to overwrite existing private content; remove or relocate the private resource manually, then re-run.
|
|
121
102
|
|
|
122
|
-
|
|
103
|
+
Use `cchost copy default <profile>` to seed an unlinked resource from the current `~/.claude/`. For fully-shared profiles this is a no-op.
|
|
123
104
|
|
|
124
|
-
|
|
105
|
+
## Custom endpoints
|
|
125
106
|
|
|
126
|
-
|
|
107
|
+
A profile can route through any Anthropic-compatible API — Moonshot/Kimi, OpenRouter, Requesty, self-hosted vLLM, or a corporate proxy — instead of Anthropic's subscription OAuth.
|
|
127
108
|
|
|
128
|
-
|
|
129
|
-
- 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.
|
|
109
|
+
> **Billing:** custom-endpoint profiles bill through the **third-party provider**, not your Anthropic subscription.
|
|
130
110
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
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.
|
|
134
|
-
|
|
135
|
-
`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.
|
|
136
|
-
|
|
137
|
-
## Custom endpoints (Kimi, OpenRouter, etc.)
|
|
138
|
-
|
|
139
|
-
A profile can route through any Anthropic-compatible API endpoint instead of Anthropic's subscription OAuth — Moonshot/Kimi, OpenRouter, Requesty, a self-hosted vLLM, or a corporate proxy. You declare this when you create the profile, with `cc add <profile> --custom`.
|
|
140
|
-
|
|
141
|
-
> **Billing:** a custom-endpoint profile bills through the **third-party provider**, using the API key you supply — **not** your Anthropic subscription. You are responsible for that provider's usage charges. A subscription profile is unaffected.
|
|
142
|
-
|
|
143
|
-
A custom-endpoint profile and a subscription profile are mutually exclusive: a profile is born one or the other and stays that way. `cc add --custom` refuses to run on a profile that already has Anthropic OAuth credentials — create custom-endpoint profiles fresh.
|
|
144
|
-
|
|
145
|
-
### Worked example — Moonshot / Kimi
|
|
111
|
+
Inherited Anthropic auth/endpoint variables (`ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`, `ANTHROPIC_BASE_URL`) are removed for endpoint profiles when the profile doesn't set them, so a shell-level key cannot override the endpoint.
|
|
146
112
|
|
|
147
113
|
```bash
|
|
148
|
-
|
|
149
|
-
--token=sk-your-
|
|
114
|
+
cchost add kimi --custom --base-url=https://api.moonshot.ai/anthropic \
|
|
115
|
+
--token=sk-your-key \
|
|
150
116
|
--model=kimi-k2.5
|
|
151
|
-
|
|
117
|
+
cchost use kimi
|
|
152
118
|
```
|
|
153
119
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Run `cc add <profile> --custom` with no value flags for an interactive wizard instead — it prompts for every field and never echoes the token. `cc add --custom` is atomic: if you cancel the wizard, no profile is left behind.
|
|
157
|
-
|
|
158
|
-
### Editing a custom-endpoint profile
|
|
159
|
-
|
|
160
|
-
Re-run `cc add <profile> --custom` on a profile that already has a custom endpoint and it switches to **edit mode**: the wizard prefills current values, and with flags only the flags you pass are changed.
|
|
120
|
+
Run `cchost add <profile> --custom` with no value flags for an interactive wizard — it prompts for every field and never echoes the token. Re-running on an existing custom-endpoint profile enters **edit mode**: the wizard prefills current values, and with flags only the flags you pass are changed.
|
|
161
121
|
|
|
162
122
|
```bash
|
|
163
|
-
|
|
164
|
-
|
|
123
|
+
cchost add kimi --custom --model=kimi-k3 # change just the model
|
|
124
|
+
cchost add kimi --custom --token=sk-rotated # rotate the API key
|
|
165
125
|
```
|
|
166
126
|
|
|
167
|
-
|
|
127
|
+
Subscription and custom-endpoint profiles are mutually exclusive: a profile is either one or the other for its entire lifetime. To switch, remove the profile with `cchost remove` and recreate it.
|
|
128
|
+
|
|
129
|
+
Inspect with `cchost list <profile>` (token masked) or `cchost list <profile> --reveal` (full). The endpoint URL should not include `/v1` — Claude Code appends `/v1/messages` itself. Most providers serve a single model; `--model` applies to every tier (`opus`/`sonnet`/`haiku`/`subagent`), or override per-tier with `--opus=`, `--sonnet=`, etc.
|
|
130
|
+
|
|
131
|
+
On launch, `cchost use` prints a one-line endpoint banner to stderr:
|
|
168
132
|
|
|
169
133
|
```
|
|
170
|
-
Profile
|
|
171
|
-
Directory: /home/you/.claude-profiles/kimi
|
|
172
|
-
LoggedIn: false
|
|
173
|
-
Email: -
|
|
174
|
-
Shared: 7/7
|
|
175
|
-
Endpoint: api.moonshot.ai
|
|
176
|
-
Base URL: https://api.moonshot.ai/anthropic
|
|
177
|
-
Token: sk-you...key9 (32 chars)
|
|
178
|
-
Model: kimi-k2.5
|
|
179
|
-
Opus: kimi-k2.5
|
|
180
|
-
Sonnet: kimi-k2.5
|
|
181
|
-
Haiku: kimi-k2.5
|
|
182
|
-
Subagent: kimi-k2.5
|
|
134
|
+
[cchost] Profile 'kimi' → api.moonshot.ai (custom endpoint billing applies)
|
|
183
135
|
```
|
|
184
136
|
|
|
185
|
-
|
|
137
|
+
## Platform notes
|
|
186
138
|
|
|
187
|
-
|
|
139
|
+
### macOS
|
|
188
140
|
|
|
189
|
-
|
|
141
|
+
Claude Code stores OAuth credentials in the login **Keychain**, not in
|
|
142
|
+
`<profile>/.credentials.json`. Claude Code namespaces the Keychain entry by
|
|
143
|
+
the exact `CLAUDE_CONFIG_DIR` path (verified with Claude Code 2.1.319):
|
|
190
144
|
|
|
191
145
|
```
|
|
192
|
-
|
|
146
|
+
Claude Code-credentials-<first 8 hex of sha256(path)>
|
|
193
147
|
```
|
|
194
148
|
|
|
195
|
-
|
|
149
|
+
So each profile gets its own Keychain entry. Two consequences:
|
|
196
150
|
|
|
197
|
-
|
|
151
|
+
- `cchost list` infers the login from `.claude.json`; it does not read the
|
|
152
|
+
Keychain secret. Treat `LoggedIn` as a login hint, not proof of a live token.
|
|
153
|
+
- The entry is keyed by the exact path string. Renaming, moving, or copying a
|
|
154
|
+
profile — or addressing it through a different path spelling or symlinked
|
|
155
|
+
home — changes the key and looks like a logout. Run `claude` under the new
|
|
156
|
+
path to log in again.
|
|
198
157
|
|
|
199
|
-
|
|
158
|
+
If you need guaranteed account separation on macOS, **custom-endpoint profiles**
|
|
159
|
+
(each has its own token in `.cc-env.json`) or separate macOS user accounts are
|
|
160
|
+
still the most explicit option.
|
|
200
161
|
|
|
201
|
-
|
|
202
|
-
2. Sets `CLAUDE_CONFIG_DIR` in its **own** spawn environment
|
|
203
|
-
3. Spawns `claude` with `stdio: 'inherit'` so the TUI works correctly
|
|
204
|
-
4. Forwards the child's exit code
|
|
162
|
+
### Windows and Linux
|
|
205
163
|
|
|
206
|
-
|
|
164
|
+
Credentials are file-based (`.credentials.json` in the profile directory), so
|
|
165
|
+
the `LoggedIn` column reflects the profile's own credential file.
|
|
207
166
|
|
|
208
|
-
##
|
|
167
|
+
## Security
|
|
209
168
|
|
|
210
|
-
`~/.claude-profiles/<profile>/` holds real OAuth credentials. Treat it like
|
|
211
|
-
|
|
212
|
-
`.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.
|
|
169
|
+
`~/.claude-profiles/<profile>/` holds real OAuth credentials and API keys. Treat it like `~/.ssh`: don't commit it, don't share it, don't sync it to public cloud storage. The shipped `.gitignore` excludes profile directories. `cchost copy` and `cchost link` never touch credential files (`.credentials.json`, `.claude.json`, `.cc-env.json`); each profile keeps its own auth state. On macOS, OAuth tokens are stored in the login Keychain instead — see [Platform notes](#platform-notes).
|
|
213
170
|
|
|
214
171
|
## Troubleshooting
|
|
215
172
|
|
|
216
|
-
|
|
217
|
-
|
|
173
|
+
Run `cchost doctor` first — it checks Node, Claude Code version, profile integrity, symlinks, and the shared pool.
|
|
174
|
+
|
|
175
|
+
**`Claude Code does not appear to be installed`** — install with `npm install -g @anthropic-ai/claude-code` and verify `claude --version` runs in a fresh terminal.
|
|
218
176
|
|
|
219
|
-
**`warning: Claude Code <version> is older than 2.1.140`**
|
|
220
|
-
Earlier versions had bugs where Windows read `.claude.json` from `%USERPROFILE%` regardless of `CLAUDE_CONFIG_DIR`, breaking isolation. Run `claude update`.
|
|
177
|
+
**`warning: Claude Code <version> is older than 2.1.140`** — earlier versions on Windows read `.claude.json` from `%USERPROFILE%` regardless of `CLAUDE_CONFIG_DIR`, breaking isolation. Run `claude update`.
|
|
221
178
|
|
|
222
|
-
**`
|
|
223
|
-
`cc use` does not auto-create profiles — that prevents typos like `cc use wokr` from silently creating a new, blank one. Run `cc add <name>` first.
|
|
179
|
+
**`warning: ANTHROPIC_API_KEY ... may override the subscription login`** — a globally exported API key takes precedence over a profile's OAuth login. Unset it in that shell (`unset ANTHROPIC_API_KEY`, and the same for `ANTHROPIC_AUTH_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN`) or use a custom-endpoint profile.
|
|
224
180
|
|
|
225
|
-
|
|
226
|
-
Names must be free of path separators, whitespace, `..`, leading dots, and reserved DOS names (CON, PRN, COM1…). Stick to letters, digits, dashes, underscores.
|
|
181
|
+
**`Profile "<name>" does not exist`** — `cchost use` does not auto-create profiles. Run `cchost add <name>` first.
|
|
227
182
|
|
|
228
|
-
**
|
|
229
|
-
That was a known bug in the cmd-based predecessor (`%*` ignored `shift`). This package forwards only the argv after `<profile>` to `claude`; the action and profile name themselves are consumed by `cc`.
|
|
183
|
+
**Profile name rejected** — names must not contain path separators, whitespace, `..`, leading dots, or DOS reserved names (`CON`, `PRN`, `COM1`…). Use letters, digits, dashes, and underscores.
|
|
230
184
|
|
|
231
185
|
## License
|
|
232
186
|
|
package/lib/banner.js
CHANGED
|
@@ -14,9 +14,11 @@ function renderBanner() {
|
|
|
14
14
|
try {
|
|
15
15
|
version = require('../package.json').version;
|
|
16
16
|
} catch {
|
|
17
|
+
// Not fatal — help still works if package.json is unreadable.
|
|
17
18
|
}
|
|
18
19
|
const tagline = 'Multi-profile launcher for Claude Code';
|
|
19
|
-
|
|
20
|
+
const label = version ? `cchost ${version} — ${tagline}` : `cchost — ${tagline}`;
|
|
21
|
+
return BANNER + ' ' + label + '\n\n';
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
module.exports = { renderBanner, BANNER };
|