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 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. Works identically in PowerShell, cmd, bash, zsh, and fish on Windows, macOS, and Linux.
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/` and `sessions/` to `~/.claude-shared`. Migrates existing content; renames on collision. |
24
- | `cc unlink <profile>` | Restore a profile to its own private `projects/` and `sessions/` (copies shared content back). |
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`. Same for `sessions/`. On Windows this uses directory junctions (no admin/Developer Mode required); on macOS/Linux, regular symlinks.
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/sessions with links to shared
22
- cc unlink <profile> Restore a profile's private projects/sessions
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/ or sessions/ is linked to ~/.claude-shared,
65
- 'isolated' otherwise
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/ (and sessions/ if present) from a source to a destination.
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/ and sessions/ with links to ~/.claude-shared.
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 links to ~/.claude-shared/ and copy shared content back
106
- into the profile as private dirs.
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/ or sessions/ is a link to ~/.claude-shared/, only
115
- the link is removed — the shared target is preserved.
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 projectsLink = isLinkLike(path.join(p.dir, 'projects'));
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
- const SUBDIRS = ['projects', 'sessions'];
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
- const SHARED_SUBDIRS = ['projects', 'sessions'];
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cchost",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Host multiple isolated Claude Code accounts on one machine via the `cc` command.",
5
5
  "keywords": [
6
6
  "claude",