@ngcodes/ccpm 0.1.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/LICENSE +21 -0
- package/README.md +286 -0
- package/bin/ccpm +26 -0
- package/install.js +128 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nitin Gupta
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# ccpm
|
|
2
|
+
|
|
3
|
+
**Claude Code Profile Manager** — run multiple Claude Code accounts simultaneously with full isolation.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/nitin-1926/claude-code-profile-manager/actions/workflows/ci.yml)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://goreportcard.com/report/github.com/nitin-1926/ccpm)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Privacy & Security
|
|
12
|
+
|
|
13
|
+
**ccpm is 100% local.** Your data never leaves your machine.
|
|
14
|
+
|
|
15
|
+
- No telemetry, analytics, or tracking of any kind
|
|
16
|
+
- No network calls — ccpm never contacts any server
|
|
17
|
+
- No data collection — we don't know you exist
|
|
18
|
+
- Credentials stored in your **OS keychain** (macOS Keychain, Linux Secret Service, Windows Credential Manager)
|
|
19
|
+
- Vault backups use **AES-256-GCM encryption** with a master key in your keychain
|
|
20
|
+
- Config files live in `~/.ccpm/` on your filesystem — nowhere else
|
|
21
|
+
- Fully open source — [audit the code yourself](https://github.com/nitin-1926/claude-code-profile-manager)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## The Problem
|
|
26
|
+
|
|
27
|
+
You have multiple Claude Code accounts — personal, work, side projects — and switching between them is painful:
|
|
28
|
+
|
|
29
|
+
- Manual logout/login cycles break your flow
|
|
30
|
+
- No way to run two accounts in parallel
|
|
31
|
+
- Settings, MCP servers, and memory bleed across accounts
|
|
32
|
+
- VS Code extension hardcoded to one account
|
|
33
|
+
|
|
34
|
+
**ccpm** fixes this. One command per terminal, full isolation, zero conflicts.
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Install
|
|
40
|
+
curl -fsSL https://raw.githubusercontent.com/nitin-1926/claude-code-profile-manager/main/scripts/install.sh | sh
|
|
41
|
+
|
|
42
|
+
# Create profiles
|
|
43
|
+
ccpm add personal # Choose OAuth or API key — first profile auto-sets as default
|
|
44
|
+
ccpm add work # Each profile is fully isolated
|
|
45
|
+
|
|
46
|
+
# Run in parallel — one per terminal
|
|
47
|
+
ccpm run personal # Terminal 1
|
|
48
|
+
ccpm run work # Terminal 2
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
That's it. Each terminal runs a completely isolated Claude Code instance with its own credentials, settings, and memory.
|
|
52
|
+
|
|
53
|
+
## How It Works
|
|
54
|
+
|
|
55
|
+
ccpm is built on one official Claude Code mechanism:
|
|
56
|
+
|
|
57
|
+
> Setting `CLAUDE_CONFIG_DIR` to a directory path causes Claude Code to read all credentials, settings, MCP config, memory, and project data from that directory instead of `~/.claude`.
|
|
58
|
+
|
|
59
|
+
ccpm manages isolated directories under `~/.ccpm/profiles/<name>/` and launches Claude with the correct environment. Each profile gets its own keychain entry on macOS, its own credentials file on Linux/Windows, and its own config.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
~/.ccpm/
|
|
63
|
+
├── config.json # Global ccpm config
|
|
64
|
+
├── profiles/
|
|
65
|
+
│ ├── personal/ # CLAUDE_CONFIG_DIR for "personal"
|
|
66
|
+
│ │ ├── .claude.json # Account data, settings
|
|
67
|
+
│ │ ├── settings.json # MCP servers, preferences
|
|
68
|
+
│ │ └── sessions/ # Chat history
|
|
69
|
+
│ └── work/ # Fully isolated from "personal"
|
|
70
|
+
└── vault/
|
|
71
|
+
├── personal.enc # Encrypted credential backup
|
|
72
|
+
└── work.enc
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
### curl (macOS / Linux)
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
curl -fsSL https://raw.githubusercontent.com/nitin-1926/claude-code-profile-manager/main/scripts/install.sh | sh
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Go
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
go install github.com/nitin-1926/ccpm@latest
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### npm
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npm install -g ccpm
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### From source
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
git clone https://github.com/nitin-1926/claude-code-profile-manager.git
|
|
99
|
+
cd claude-code-profile-manager/cli
|
|
100
|
+
make build # Binary at ./bin/ccpm
|
|
101
|
+
go install . # Install to $GOPATH/bin
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Shell Integration (Optional)
|
|
105
|
+
|
|
106
|
+
For `ccpm use` (setting a profile for your whole shell session), add this to your `~/.zshrc` or `~/.bashrc`:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
eval "$(ccpm shell-init)"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then reload: `source ~/.zshrc`
|
|
113
|
+
|
|
114
|
+
> **Note:** `ccpm run` works without any shell setup. Shell integration is only needed for `ccpm use`.
|
|
115
|
+
|
|
116
|
+
## Commands
|
|
117
|
+
|
|
118
|
+
### Profile Management
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
ccpm add <name> # Create profile (OAuth or API key)
|
|
122
|
+
ccpm list # List all profiles with auth status
|
|
123
|
+
ccpm remove <name> # Delete a profile
|
|
124
|
+
ccpm status # Full system overview
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Running Claude
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
ccpm run <name> # Launch Claude with this profile (recommended)
|
|
131
|
+
ccpm use <name> # Set profile for current shell session
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Authentication
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
ccpm auth status # Check auth health across all profiles
|
|
138
|
+
ccpm auth refresh <n> # Re-authenticate a profile
|
|
139
|
+
ccpm auth backup <n> # Encrypted credential backup to vault
|
|
140
|
+
ccpm auth restore <n> # Restore credentials from vault backup
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### IDE / VS Code
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
ccpm set-default <name> # Set profile for VS Code extension
|
|
147
|
+
ccpm unset-default # Clear default
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Uninstall
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
ccpm uninstall # Remove all ccpm data, profiles, and keychain entries
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Auth Methods
|
|
157
|
+
|
|
158
|
+
ccpm supports both authentication methods:
|
|
159
|
+
|
|
160
|
+
### OAuth (Browser Login)
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
$ ccpm add personal
|
|
164
|
+
Choose authentication method:
|
|
165
|
+
1) OAuth (browser login via claude /login)
|
|
166
|
+
2) API Key
|
|
167
|
+
Enter choice [1/2]: 1
|
|
168
|
+
|
|
169
|
+
Claude Code will launch. Run /login to authenticate.
|
|
170
|
+
# ...browser auth flow...
|
|
171
|
+
|
|
172
|
+
✓ Profile "personal" authenticated via OAuth
|
|
173
|
+
✓ Set as default profile (first profile)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### API Key
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
$ ccpm add work
|
|
180
|
+
Choose authentication method:
|
|
181
|
+
1) OAuth (browser login via claude /login)
|
|
182
|
+
2) API Key
|
|
183
|
+
Enter choice [1/2]: 2
|
|
184
|
+
|
|
185
|
+
Enter your Anthropic API key: ****
|
|
186
|
+
✓ Profile "work" authenticated via API key
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
API keys are stored in your OS keychain (macOS Keychain / Linux Secret Service / Windows Credential Manager) — never in plaintext files.
|
|
190
|
+
|
|
191
|
+
## Parallel Sessions
|
|
192
|
+
|
|
193
|
+
Run different accounts simultaneously in different terminals:
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
┌─────────────────────┐ ┌─────────────────────┐
|
|
197
|
+
│ Terminal 1 │ │ Terminal 2 │
|
|
198
|
+
│ │ │ │
|
|
199
|
+
│ $ ccpm run personal │ │ $ ccpm run work │
|
|
200
|
+
│ │ │ │
|
|
201
|
+
│ Claude Code │ │ Claude Code │
|
|
202
|
+
│ (personal@gmail.com) │ │ (work@company.com) │
|
|
203
|
+
│ │ │ │
|
|
204
|
+
│ Own settings │ │ Own settings │
|
|
205
|
+
│ Own MCP servers │ │ Own MCP servers │
|
|
206
|
+
│ Own memory │ │ Own memory │
|
|
207
|
+
└─────────────────────┘ └─────────────────────┘
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Platform Support
|
|
211
|
+
|
|
212
|
+
| Feature | macOS | Linux | Windows |
|
|
213
|
+
|---------|-------|-------|---------|
|
|
214
|
+
| OAuth auth | Keychain (per-profile isolation) | `.credentials.json` in profile dir | `.credentials.json` in profile dir |
|
|
215
|
+
| API key auth | Keychain | Secret Service (D-Bus) | Credential Manager |
|
|
216
|
+
| Parallel sessions | Yes | Yes | Yes |
|
|
217
|
+
| Vault backup | Yes | Yes | Yes |
|
|
218
|
+
| Shell hook | zsh, bash, fish | zsh, bash, fish | PowerShell |
|
|
219
|
+
|
|
220
|
+
## Known Limitations
|
|
221
|
+
|
|
222
|
+
We believe in being honest about constraints:
|
|
223
|
+
|
|
224
|
+
| # | Limitation | Severity | Workaround |
|
|
225
|
+
|---|---|---|---|
|
|
226
|
+
| L1 | **VS Code extension ignores `CLAUDE_CONFIG_DIR`** — reads from `~/.claude` always | High | Use `ccpm set-default <profile>` to set the VS Code account |
|
|
227
|
+
| L2 | **`CLAUDE_CONFIG_DIR` path with `~/`** — Claude has a bug resolving `~/` paths on Linux | Medium | ccpm always uses absolute paths (handled automatically) |
|
|
228
|
+
| L3 | **Same-account parallel sessions** — running one profile in two terminals hits Anthropic's refresh token race | Medium | Use different profiles in different terminals |
|
|
229
|
+
| L4 | **Headless Linux** — `go-keyring` requires D-Bus + secret service | Low | API key profiles need a running secret service |
|
|
230
|
+
|
|
231
|
+
## Project Structure
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
claude-code-profile-manager/
|
|
235
|
+
├── cli/ # Go source code (ccpm binary)
|
|
236
|
+
│ ├── cmd/ # CLI commands
|
|
237
|
+
│ ├── internal/ # Core packages (config, profile, vault, etc.)
|
|
238
|
+
│ └── Makefile
|
|
239
|
+
├── docs/ # Documentation website (Next.js, deploy to Vercel)
|
|
240
|
+
├── npm/ # npm wrapper package
|
|
241
|
+
├── scripts/ # Install script
|
|
242
|
+
└── .github/ # CI/CD workflows
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Roadmap
|
|
246
|
+
|
|
247
|
+
- [x] Profile management (add, list, remove, run)
|
|
248
|
+
- [x] OAuth + API key authentication
|
|
249
|
+
- [x] Encrypted vault backup/restore
|
|
250
|
+
- [x] Shell integration (use, shell-init)
|
|
251
|
+
- [x] VS Code default profile (set-default)
|
|
252
|
+
- [x] Uninstall command
|
|
253
|
+
- [ ] Per-profile MCP server management
|
|
254
|
+
- [ ] Shared vs isolated config (skills, commands, CLAUDE.md)
|
|
255
|
+
- [ ] Token optimization presets
|
|
256
|
+
- [ ] Diagnostics (`ccpm doctor`)
|
|
257
|
+
- [ ] GUI companion app
|
|
258
|
+
- [ ] Multi-tool support (Codex CLI, Cursor CLI, Gemini CLI)
|
|
259
|
+
|
|
260
|
+
## Contributing
|
|
261
|
+
|
|
262
|
+
Contributions welcome! Please open an issue first to discuss what you'd like to change.
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Development setup
|
|
266
|
+
git clone https://github.com/nitin-1926/claude-code-profile-manager.git
|
|
267
|
+
cd claude-code-profile-manager/cli
|
|
268
|
+
go mod tidy
|
|
269
|
+
make build # Build binary to ./bin/ccpm
|
|
270
|
+
go install . # Install to $GOPATH/bin for testing
|
|
271
|
+
make test # Run tests
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Testing the npm package locally
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
cd npm
|
|
278
|
+
npm pack # Creates ccpm-0.1.0.tgz
|
|
279
|
+
npm install -g ccpm-0.1.0.tgz # Install from local tarball
|
|
280
|
+
ccpm --version # Verify
|
|
281
|
+
npm uninstall -g ccpm # Clean up
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
[MIT](LICENSE)
|
package/bin/ccpm
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// JS shim that execs the native ccpm binary downloaded by install.js
|
|
3
|
+
const { spawnSync } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
|
|
7
|
+
const isWin = process.platform === "win32";
|
|
8
|
+
const binary = path.join(__dirname, isWin ? "ccpm-native.exe" : "ccpm-native");
|
|
9
|
+
|
|
10
|
+
if (!fs.existsSync(binary)) {
|
|
11
|
+
console.error("ccpm: native binary not found at " + binary);
|
|
12
|
+
console.error(
|
|
13
|
+
"The postinstall step may have failed. Reinstall with `npm i -g @ngcodes/ccpm`"
|
|
14
|
+
);
|
|
15
|
+
console.error(
|
|
16
|
+
"Or download manually: https://github.com/nitin-1926/claude-code-profile-manager/releases"
|
|
17
|
+
);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
22
|
+
if (result.error) {
|
|
23
|
+
console.error("ccpm: failed to launch native binary:", result.error.message);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
process.exit(result.status ?? 1);
|
package/install.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Downloads the correct ccpm binary for the current platform during npm install
|
|
3
|
+
|
|
4
|
+
const { execSync } = require("child_process");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const https = require("https");
|
|
8
|
+
|
|
9
|
+
const REPO = "nitin-1926/claude-code-profile-manager";
|
|
10
|
+
const BINARY = "ccpm";
|
|
11
|
+
|
|
12
|
+
function getPlatform() {
|
|
13
|
+
const platform = process.platform;
|
|
14
|
+
const arch = process.arch;
|
|
15
|
+
|
|
16
|
+
const osMap = { darwin: "darwin", linux: "linux", win32: "windows" };
|
|
17
|
+
const archMap = { x64: "amd64", arm64: "arm64" };
|
|
18
|
+
|
|
19
|
+
const os = osMap[platform];
|
|
20
|
+
const cpu = archMap[arch];
|
|
21
|
+
|
|
22
|
+
if (!os || !cpu) {
|
|
23
|
+
console.error(`Unsupported platform: ${platform}/${arch}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return { os, arch: cpu };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getLatestVersion() {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const url = `https://api.github.com/repos/${REPO}/releases/latest`;
|
|
33
|
+
https.get(url, { headers: { "User-Agent": "ccpm-npm" } }, (res) => {
|
|
34
|
+
let data = "";
|
|
35
|
+
res.on("data", (chunk) => (data += chunk));
|
|
36
|
+
res.on("end", () => {
|
|
37
|
+
try {
|
|
38
|
+
const json = JSON.parse(data);
|
|
39
|
+
resolve(json.tag_name.replace(/^v/, ""));
|
|
40
|
+
} catch {
|
|
41
|
+
// Fallback to package.json version
|
|
42
|
+
const pkg = require("./package.json");
|
|
43
|
+
resolve(pkg.version);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
res.on("error", reject);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function download(url, dest) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const follow = (url) => {
|
|
54
|
+
https.get(url, { headers: { "User-Agent": "ccpm-npm" } }, (res) => {
|
|
55
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
56
|
+
follow(res.headers.location);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (res.statusCode !== 200) {
|
|
60
|
+
reject(new Error(`Download failed: HTTP ${res.statusCode}`));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const file = fs.createWriteStream(dest);
|
|
64
|
+
res.pipe(file);
|
|
65
|
+
file.on("finish", () => { file.close(); resolve(); });
|
|
66
|
+
file.on("error", reject);
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
follow(url);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function main() {
|
|
74
|
+
const { os, arch } = getPlatform();
|
|
75
|
+
const version = await getLatestVersion();
|
|
76
|
+
|
|
77
|
+
const ext = os === "windows" ? "zip" : "tar.gz";
|
|
78
|
+
const url = `https://github.com/${REPO}/releases/download/v${version}/${BINARY}_${os}_${arch}.${ext}`;
|
|
79
|
+
|
|
80
|
+
console.log(`Installing ccpm v${version} for ${os}/${arch}...`);
|
|
81
|
+
|
|
82
|
+
const binDir = path.join(__dirname, "bin");
|
|
83
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
84
|
+
|
|
85
|
+
// Extract into a temp subdirectory so the archive's `ccpm` binary doesn't
|
|
86
|
+
// overwrite the JS shim that npm uses to create the global `ccpm` command.
|
|
87
|
+
const tmpDir = path.join(binDir, ".extract");
|
|
88
|
+
if (fs.existsSync(tmpDir)) fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
89
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
90
|
+
|
|
91
|
+
const archivePath = path.join(tmpDir, `archive.${ext}`);
|
|
92
|
+
await download(url, archivePath);
|
|
93
|
+
|
|
94
|
+
if (ext === "zip") {
|
|
95
|
+
execSync(`unzip -o -q "${archivePath}" -d "${tmpDir}"`, { stdio: "inherit" });
|
|
96
|
+
} else {
|
|
97
|
+
execSync(`tar -xzf "${archivePath}" -C "${tmpDir}"`, { stdio: "inherit" });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Move the native binary to bin/ccpm-native (or ccpm-native.exe on Windows).
|
|
101
|
+
// The JS shim at bin/ccpm execs this at runtime.
|
|
102
|
+
const extractedName = os === "windows" ? `${BINARY}.exe` : BINARY;
|
|
103
|
+
const nativeName = os === "windows" ? "ccpm-native.exe" : "ccpm-native";
|
|
104
|
+
const extractedPath = path.join(tmpDir, extractedName);
|
|
105
|
+
const nativePath = path.join(binDir, nativeName);
|
|
106
|
+
|
|
107
|
+
if (!fs.existsSync(extractedPath)) {
|
|
108
|
+
throw new Error(`extracted binary not found at ${extractedPath}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (fs.existsSync(nativePath)) fs.unlinkSync(nativePath);
|
|
112
|
+
fs.renameSync(extractedPath, nativePath);
|
|
113
|
+
|
|
114
|
+
if (os !== "windows") {
|
|
115
|
+
fs.chmodSync(nativePath, 0o755);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Clean up temp dir
|
|
119
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
120
|
+
|
|
121
|
+
console.log(`ccpm v${version} installed successfully!`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
main().catch((err) => {
|
|
125
|
+
console.error("Failed to install ccpm:", err.message);
|
|
126
|
+
console.error("You can install manually: https://github.com/" + REPO + "/releases");
|
|
127
|
+
process.exit(1);
|
|
128
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ngcodes/ccpm",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Claude Code Profile Manager — manage multiple Claude Code accounts with isolated profiles",
|
|
5
|
+
"bin": {
|
|
6
|
+
"ccpm": "bin/ccpm"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"install.js",
|
|
10
|
+
"bin/ccpm",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"postinstall": "node install.js",
|
|
19
|
+
"test-local": "echo 'To test locally: npm pack && npm install -g nitin-1926-ccpm-0.1.0.tgz'"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"claude",
|
|
23
|
+
"claude-code",
|
|
24
|
+
"profile-manager",
|
|
25
|
+
"multi-account",
|
|
26
|
+
"anthropic",
|
|
27
|
+
"cli"
|
|
28
|
+
],
|
|
29
|
+
"author": "Nitin Gupta",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/nitin-1926/claude-code-profile-manager.git"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/nitin-1926/claude-code-profile-manager",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/nitin-1926/claude-code-profile-manager/issues"
|
|
38
|
+
},
|
|
39
|
+
"os": ["darwin", "linux", "win32"],
|
|
40
|
+
"cpu": ["x64", "arm64"],
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=16"
|
|
43
|
+
}
|
|
44
|
+
}
|