cchost 0.1.1 → 0.1.3
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/README.md +6 -4
- package/lib/cli.js +20 -15
- package/lib/migrate.js +3 -1
- package/lib/share.js +4 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# cchost
|
|
2
2
|
|
|
3
|
-
Host multiple isolated Claude Code accounts on one machine via a single `cc` command.
|
|
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.
|
|
4
4
|
|
|
5
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>`.
|
|
6
6
|
|
|
@@ -20,8 +20,8 @@ Requires Node.js 18+ and Claude Code 2.1.140+ already installed. Get Claude Code
|
|
|
20
20
|
| `cc use <profile> [...args]` | Launch Claude under that profile. Profile must already exist. Args after the name are forwarded verbatim to `claude`. |
|
|
21
21
|
| `cc list [--original] [--json]` | Show every profile: login state, account email, and storage mode (`shared` / `isolated`). |
|
|
22
22
|
| `cc migrate <src> <dest>` | Copy projects from `default`\|`shared` to `shared`\|`<profile>`. Skip-on-collision; credential files never copied. |
|
|
23
|
-
| `cc link <profile> [<profile>...]` | Link a profile's `projects/`
|
|
24
|
-
| `cc unlink <profile>` | Restore a profile to its own private `projects/`
|
|
23
|
+
| `cc link <profile> [<profile>...]` | Link a profile's `projects/` to `~/.claude-shared/projects`. Migrates existing content; renames on collision. |
|
|
24
|
+
| `cc unlink <profile>` | Restore a profile to its own private `projects/` (copies shared content back). |
|
|
25
25
|
| `cc remove <profile>` | Delete a profile. Requires typing the profile name to confirm. |
|
|
26
26
|
| `cc help [command]` | Print usage (top-level, or for a single command). |
|
|
27
27
|
|
|
@@ -66,7 +66,9 @@ cc link work
|
|
|
66
66
|
cc link personal
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
`work/projects` and `personal/projects` become links to `~/.claude-shared/projects`.
|
|
69
|
+
`work/projects` and `personal/projects` become links to `~/.claude-shared/projects`. On Windows this uses directory junctions (no admin/Developer Mode required); on macOS/Linux, regular symlinks.
|
|
70
|
+
|
|
71
|
+
**Only `projects/` is shared.** That's the directory Claude Code uses for resumable conversation transcripts (`projects/<project>/<session>.jsonl`). The sibling `sessions/` folder holds transient per-process registry state — PID, working directory, status, timestamps — and is **never** linked, migrated, or copied across profiles. Sharing it would corrupt Claude's running-process bookkeeping. `sessions/` stays per-profile under `~/.claude-profiles/<name>/sessions/`.
|
|
70
72
|
|
|
71
73
|
`cc link a b c` links several profiles at once; per-profile failures are reported but don't abort the rest of the batch.
|
|
72
74
|
|
package/lib/cli.js
CHANGED
|
@@ -18,10 +18,11 @@ Usage:
|
|
|
18
18
|
cc use <profile> [...args] Launch Claude under a named profile
|
|
19
19
|
cc list [--original] [--json] Show all profiles: login state, email, storage (shared/isolated)
|
|
20
20
|
cc migrate <src> <dest> Copy projects from default|shared to shared|<profile>
|
|
21
|
-
cc link <p>... Replace each profile's projects/
|
|
22
|
-
cc unlink <profile> Restore a profile's private projects/
|
|
21
|
+
cc link <p>... Replace each profile's projects/ with a link to shared
|
|
22
|
+
cc unlink <profile> Restore a profile's private projects/
|
|
23
23
|
cc remove <profile> Delete a profile and all its data (typed confirmation)
|
|
24
24
|
cc help [command] Show usage (optionally for a single command)
|
|
25
|
+
cc --version Print the installed cchost version
|
|
25
26
|
|
|
26
27
|
Profiles live in ~/.claude-profiles/<profile>/ and become CLAUDE_CONFIG_DIR
|
|
27
28
|
for that launch. Args after the profile name are forwarded verbatim to claude.
|
|
@@ -61,8 +62,8 @@ Columns:
|
|
|
61
62
|
Profile - profile name
|
|
62
63
|
LoggedIn - true if .credentials.json exists
|
|
63
64
|
Email - account email (alias-aware; - if not yet logged in)
|
|
64
|
-
Storage - 'shared' if projects/
|
|
65
|
-
|
|
65
|
+
Storage - 'shared' if projects/ is linked to ~/.claude-shared, 'isolated' otherwise
|
|
66
|
+
(sessions/ is transient per-process state and is never shared)
|
|
66
67
|
|
|
67
68
|
By default, the displayed email reflects any alias set via 'cc add'.
|
|
68
69
|
With --original, shows the real value from .claude.json.
|
|
@@ -71,8 +72,8 @@ With --json, emits an array of {name, dir, loggedIn, email, storage, alias}.
|
|
|
71
72
|
`,
|
|
72
73
|
migrate: `cc migrate <src> <dest>
|
|
73
74
|
|
|
74
|
-
Copy projects/
|
|
75
|
-
This is a COPY — the source is left untouched.
|
|
75
|
+
Copy projects/ from a source to a destination. sessions/ (transient per-process
|
|
76
|
+
registry state) is never migrated. This is a COPY — the source is left untouched.
|
|
76
77
|
|
|
77
78
|
<src>: default | shared
|
|
78
79
|
default = ~/.claude/ (Claude's built-in non-profile data)
|
|
@@ -90,9 +91,10 @@ Examples:
|
|
|
90
91
|
`,
|
|
91
92
|
link: `cc link <profile> [<profile>...]
|
|
92
93
|
|
|
93
|
-
Replace each profile's projects/
|
|
94
|
+
Replace each profile's projects/ with a link to ~/.claude-shared/projects/.
|
|
94
95
|
Existing content is migrated into shared first; collisions are renamed with a
|
|
95
|
-
__<profile> suffix (never overwritten).
|
|
96
|
+
__<profile> suffix (never overwritten). sessions/ (transient per-process state)
|
|
97
|
+
is intentionally never linked — it stays per-profile.
|
|
96
98
|
|
|
97
99
|
On Windows, link uses directory junctions (no admin/Developer Mode needed).
|
|
98
100
|
On macOS/Linux, regular symlinks.
|
|
@@ -102,8 +104,8 @@ are reported but don't abort the rest of the batch.
|
|
|
102
104
|
`,
|
|
103
105
|
unlink: `cc unlink <profile>
|
|
104
106
|
|
|
105
|
-
Remove a profile's
|
|
106
|
-
into the profile as private
|
|
107
|
+
Remove a profile's projects/ link to ~/.claude-shared/ and copy shared content
|
|
108
|
+
back into the profile as a private dir.
|
|
107
109
|
`,
|
|
108
110
|
remove: `cc remove <profile>
|
|
109
111
|
|
|
@@ -111,8 +113,8 @@ Delete a profile and everything inside its directory: credentials, sessions,
|
|
|
111
113
|
projects, plugins, and history. To confirm, you must type the exact profile
|
|
112
114
|
name — y/n is intentionally not accepted because credential loss is unrecoverable.
|
|
113
115
|
|
|
114
|
-
If the profile's projects/
|
|
115
|
-
|
|
116
|
+
If the profile's projects/ is a link to ~/.claude-shared/, only the link is
|
|
117
|
+
removed — the shared target is preserved.
|
|
116
118
|
`,
|
|
117
119
|
help: `cc help [command]
|
|
118
120
|
|
|
@@ -272,9 +274,7 @@ function cmdList(rest) {
|
|
|
272
274
|
const enriched = list.map((p) => {
|
|
273
275
|
const alias = p.alias || {};
|
|
274
276
|
const displayEmail = useOriginal ? p.email : (alias.email || p.email);
|
|
275
|
-
const
|
|
276
|
-
const sessionsLink = isLinkLike(path.join(p.dir, 'sessions'));
|
|
277
|
-
const storage = (projectsLink || sessionsLink) ? 'shared' : 'isolated';
|
|
277
|
+
const storage = isLinkLike(path.join(p.dir, 'projects')) ? 'shared' : 'isolated';
|
|
278
278
|
return {
|
|
279
279
|
name: p.name,
|
|
280
280
|
dir: p.dir,
|
|
@@ -383,6 +383,11 @@ async function run(argv) {
|
|
|
383
383
|
printHelp();
|
|
384
384
|
return 0;
|
|
385
385
|
}
|
|
386
|
+
if (action === '--version' || action === '-v') {
|
|
387
|
+
const { version } = require('../package.json');
|
|
388
|
+
process.stdout.write(version + '\n');
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
386
391
|
if (action === 'help') {
|
|
387
392
|
printHelp(rest[0]);
|
|
388
393
|
return 0;
|
package/lib/migrate.js
CHANGED
|
@@ -6,7 +6,9 @@ const os = require('os');
|
|
|
6
6
|
|
|
7
7
|
const profiles = require('./profiles');
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// Only projects/ holds the resumable conversation transcripts. sessions/ is transient
|
|
10
|
+
// per-process state and is intentionally not migrated.
|
|
11
|
+
const SUBDIRS = ['projects'];
|
|
10
12
|
const EXCLUDED_FILES = new Set(['.credentials.json', '.claude.json']);
|
|
11
13
|
|
|
12
14
|
function defaultClaudeDir() {
|
package/lib/share.js
CHANGED
|
@@ -5,7 +5,10 @@ const path = require('path');
|
|
|
5
5
|
|
|
6
6
|
const profiles = require('./profiles');
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// Only projects/ holds the resumable conversation transcripts (projects/<proj>/<session>.jsonl).
|
|
9
|
+
// sessions/ is transient per-process registry state (PID, cwd, status, timestamps) and
|
|
10
|
+
// must stay per-profile — sharing it would corrupt Claude's running-process bookkeeping.
|
|
11
|
+
const SHARED_SUBDIRS = ['projects'];
|
|
9
12
|
|
|
10
13
|
function symlinkType() {
|
|
11
14
|
return process.platform === 'win32' ? 'junction' : 'dir';
|