mcpocket 0.1.0 → 0.1.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.
Files changed (41) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +261 -37
  3. package/dist/cli.js +9 -7
  4. package/dist/cli.js.map +1 -1
  5. package/dist/clients/claude-code.js +2 -2
  6. package/dist/clients/claude-desktop.js +2 -2
  7. package/dist/clients/opencode.js +2 -2
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js +111 -43
  10. package/dist/commands/init.js.map +1 -1
  11. package/dist/commands/pull.d.ts.map +1 -1
  12. package/dist/commands/pull.js +45 -31
  13. package/dist/commands/pull.js.map +1 -1
  14. package/dist/commands/push.d.ts.map +1 -1
  15. package/dist/commands/push.js +56 -32
  16. package/dist/commands/push.js.map +1 -1
  17. package/dist/commands/status.d.ts.map +1 -1
  18. package/dist/commands/status.js +38 -23
  19. package/dist/commands/status.js.map +1 -1
  20. package/dist/config.d.ts +10 -6
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +13 -8
  23. package/dist/config.js.map +1 -1
  24. package/dist/storage/gist.d.ts +21 -0
  25. package/dist/storage/gist.d.ts.map +1 -0
  26. package/dist/storage/gist.js +139 -0
  27. package/dist/storage/gist.js.map +1 -0
  28. package/dist/storage/github.d.ts +1 -1
  29. package/dist/storage/github.js +8 -8
  30. package/dist/sync/plugins.js +2 -2
  31. package/dist/utils/crypto.d.ts +1 -1
  32. package/dist/utils/crypto.js +2 -2
  33. package/dist/utils/paths.d.ts +4 -4
  34. package/dist/utils/paths.d.ts.map +1 -1
  35. package/dist/utils/paths.js +8 -8
  36. package/dist/utils/paths.js.map +1 -1
  37. package/dist/utils/sparkle.d.ts +60 -0
  38. package/dist/utils/sparkle.d.ts.map +1 -0
  39. package/dist/utils/sparkle.js +114 -0
  40. package/dist/utils/sparkle.js.map +1 -0
  41. package/package.json +4 -4
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 davidsmorais
3
+ Copyright (c) 2026 David Morais <david@davidmorais.com>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,12 +1,33 @@
1
- # carry-on
1
+ <p align="center">
2
+ <img src="https://img.shields.io/npm/v/mcpocket?color=blue&label=npm" alt="npm version" />
3
+ <img src="https://img.shields.io/node/v/mcpocket" alt="node version" />
4
+ <img src="https://img.shields.io/github/license/davidsmorais/carry-on" alt="license" />
5
+ </p>
2
6
 
3
- > Your AI setup. Everywhere you work.
7
+ # mcpocket
4
8
 
5
- `carry-on` syncs your Claude Code agents, skills, plugins, and MCP server configurations across machines — so your full AI loadout follows you everywhere.
9
+ > Your AI setup. Every pocket.
10
+
11
+ **mcpocket** syncs your Claude Code agents, skills, plugins, and MCP server configurations across machines — so your full AI loadout follows you everywhere, like magic.
12
+
13
+ ---
6
14
 
7
15
  ## The Problem
8
16
 
9
- You install 8 MCP servers, configure your Claude Code plugins, and build up a library of agents on your Linux machine. Then you switch to Windows and have nothing. `carry-on` fixes that with two commands.
17
+ You install 8 MCP servers, configure your Claude Code plugins, and build up a library of agents on your Linux workstation. Then you switch to your Windows laptop and nothing. You start from scratch. Again.
18
+
19
+ **mcpocket** fixes that with two commands: `push` from your source machine, `pull` on any other.
20
+
21
+ ## Features
22
+
23
+ - **Multi-client sync** — Claude Desktop, Claude Code, and OpenCode configs in one shot
24
+ - **Two storage backends** — private GitHub repo (full git history) or lightweight GitHub Gist
25
+ - **End-to-end encryption** — all secrets (API keys, tokens in MCP `env` vars) are encrypted with AES-256-GCM using a passphrase you choose
26
+ - **Cross-platform paths** — Windows ↔ Linux ↔ macOS paths round-trip seamlessly
27
+ - **Additive pull** — pulling merges remote servers into your local config without overwriting anything
28
+ - **Zero dependencies on external services** — only GitHub and Git
29
+
30
+ ---
10
31
 
11
32
  ## Install
12
33
 
@@ -14,73 +35,276 @@ You install 8 MCP servers, configure your Claude Code plugins, and build up a li
14
35
  npm install -g mcpocket
15
36
  ```
16
37
 
17
- ## Usage
38
+ Or with pnpm / yarn:
18
39
 
19
- ### 1. Initialize (once per machine)
40
+ ```bash
41
+ pnpm add -g mcpocket
42
+ # or
43
+ yarn global add mcpocket
44
+ ```
45
+
46
+ ## Quick Start
20
47
 
21
48
  ```bash
22
- carry-on init
49
+ # 1. Initialize (once per machine)
50
+ mcpocket init
51
+
52
+ # 2. Push your setup to the cloud
53
+ mcpocket push
54
+
55
+ # 3. Pull on a new machine
56
+ mcpocket pull
57
+
58
+ # 4. Check sync status
59
+ mcpocket status
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Commands
65
+
66
+ ### `mcpocket init`
67
+
68
+ Interactive setup wizard. Links your GitHub account, chooses a storage backend, and creates the remote pocket.
69
+
70
+ ```
71
+ $ mcpocket init
72
+
73
+ ✦ First, let's link your GitHub account.
74
+ Required scopes: repo (full control of private repositories)
75
+
76
+ 🔑 GitHub token: ****
77
+
78
+ ✦ Authenticated as davidsmorais — nice to meet you!
79
+
80
+ ✦ Where should mcpocket store your config?
81
+ [1] GitHub repo (private repo, full git history)
82
+ [2] GitHub gist (lighter, no git clone needed)
83
+
84
+ Pick one [1/2]: 1
23
85
  ```
24
86
 
25
- Connects to GitHub, creates a private `carry-on-sync` repo, and clones it locally. Requires a [GitHub personal access token](https://github.com/settings/tokens/new) with `repo` scope.
87
+ **Storage options:**
88
+
89
+ | Option | Backend | Requires Git? | History |
90
+ |---|---|---|---|
91
+ | `1` — Repo | Private `mcpocket-sync` repo | Yes | Full git log |
92
+ | `2` — Gist | Private GitHub Gist | No | Gist revisions |
93
+
94
+ Requires a [GitHub personal access token](https://github.com/settings/tokens/new) with **`repo`** scope (for repo mode) or **`gist`** scope (for gist mode).
95
+
96
+ ### `mcpocket push`
26
97
 
27
- ### 2. Push your setup
98
+ Reads MCP configs, plugin manifests, agents, and skills from the current machine. Encrypts secrets with a passphrase you choose, then uploads to your private pocket.
28
99
 
29
100
  ```bash
30
- carry-on push
101
+ mcpocket push
31
102
  ```
32
103
 
33
- Reads MCP configs, plugin manifests, agents, and skills from your current machine. Encrypts any secrets (API keys in MCP env vars) with a passphrase you choose, then commits and pushes to your private GitHub repo.
104
+ - In **repo mode**: commits and pushes to your private GitHub repo.
105
+ - In **gist mode**: uploads files to your private GitHub Gist (directory structure is flattened with `__` separators).
34
106
 
35
- ### 3. Pull on a new machine
107
+ ### `mcpocket pull`
108
+
109
+ Downloads your config from the remote pocket, decrypts secrets with your passphrase, and writes everything to the appropriate client config files:
36
110
 
37
111
  ```bash
38
- carry-on pull
112
+ mcpocket pull
39
113
  ```
40
114
 
41
- Pulls your config from GitHub, decrypts secrets with your passphrase, and writes everything to:
42
- - **Claude Desktop** — `claude_desktop_config.json`
43
- - **Claude Code** `~/.claude/settings.json`
44
- - **OpenCode** `~/.config/opencode/config.json`
115
+ | Client | Config file |
116
+ |---|---|
117
+ | Claude Desktop | `claude_desktop_config.json` |
118
+ | Claude Code | `~/.claude/settings.json` |
119
+ | OpenCode | `~/.config/opencode/config.json` |
120
+
121
+ Pull is **additive** — it adds servers that exist remotely but not locally, without overwriting your existing local config. Restart Claude Desktop after pulling to apply MCP changes.
45
122
 
46
- Then restart Claude Desktop to apply MCP changes.
123
+ ### `mcpocket status`
47
124
 
48
- ### Check sync status
125
+ Shows a diff of what's synced, what's local-only, and what's remote-only:
49
126
 
50
127
  ```bash
51
- carry-on status
128
+ mcpocket status
129
+ ```
130
+
52
131
  ```
132
+ ── MCP Servers ──
53
133
 
54
- Shows which MCP servers, plugins, agents, and skills are synced vs. local-only vs. remote-only.
134
+ Synced:
135
+ ✓ filesystem
136
+ ✓ github
137
+
138
+ Local only (run push):
139
+ ↑ sqlite
140
+
141
+ In pocket, not here (run pull):
142
+ ↓ postgres
143
+ ```
144
+
145
+ ---
55
146
 
56
147
  ## What Gets Synced
57
148
 
58
- | What | Where |
59
- |---|---|
60
- | MCP server configs | All clients — Claude Desktop, Claude Code, OpenCode |
61
- | Plugin manifests | `installed_plugins.json`, `blocklist.json`, `known_marketplaces.json` |
62
- | Agents | `~/.claude/agents/**/*.md` |
63
- | Skills | `~/.claude/skills/**` (excluding `node_modules`) |
149
+ | Category | Source | Details |
150
+ |---|---|---|
151
+ | MCP server configs | Claude Desktop, Claude Code, OpenCode | Merged across all clients |
152
+ | Plugin manifests | `~/.claude/plugins/` | `installed_plugins.json`, `blocklist.json`, `known_marketplaces.json` |
153
+ | Agents | `~/.claude/agents/` | All `*.md` files, recursively |
154
+ | Skills | `~/.claude/skills/` | All files, recursively (excluding `node_modules`) |
64
155
 
65
- **Never synced:** `.credentials.json`, `plugins/cache/`, sessions, telemetry.
156
+ ### Never Synced
157
+
158
+ - `.credentials.json`
159
+ - `plugins/cache/`
160
+ - Sessions and telemetry data
161
+ - Your GitHub token (stays in local `~/.mcpocket/config.json`)
162
+
163
+ ---
66
164
 
67
165
  ## Security
68
166
 
69
- - Secrets (MCP `env` vars) are encrypted with AES-256-GCM before upload
70
- - Your passphrase is never stored anywhere
71
- - Config repo is always private
72
- - GitHub token is stored in `~/.carry-on/config.json` (chmod 600 on Linux/Mac)
167
+ | Concern | How mcpocket handles it |
168
+ |---|---|
169
+ | API keys & tokens | Encrypted with **AES-256-GCM** (via `scrypt` key derivation) before leaving your machine |
170
+ | Passphrase storage | **Never stored** you enter it on every push/pull |
171
+ | Remote storage | Always **private** (private repo or secret gist) |
172
+ | Local config | `~/.mcpocket/config.json` is `chmod 600` on Linux/macOS |
173
+ | Git auth | Token is injected at runtime into HTTPS URLs, never persisted in git config |
174
+ | Error output | Git errors are sanitized to strip tokens before display |
175
+
176
+ ### Encryption Format
177
+
178
+ Encrypted values are stored as:
179
+
180
+ ```
181
+ ENCRYPTED:<iv_hex>:<salt_hex>:<authTag_hex>:<ciphertext_hex>
182
+ ```
183
+
184
+ Each value uses a unique random salt and IV, so identical plaintext values produce different ciphertexts.
185
+
186
+ ---
73
187
 
74
188
  ## Path Handling
75
189
 
76
- `carry-on` normalizes paths on push (`/home/user/...` → `~/...`) and expands them for the current platform on pull. Windows and Linux absolute paths round-trip correctly.
190
+ mcpocket normalizes paths for portability:
191
+
192
+ | Direction | Transformation |
193
+ |---|---|
194
+ | Push | `/home/user/...` or `C:\Users\user\...` → `~/...` |
195
+ | Pull | `~/...` → platform-native absolute path |
196
+ | Commands | `.cmd` / `.exe` extensions stripped on push, restored on pull (Windows) |
197
+
198
+ This means a config pushed from Linux works on Windows and vice versa.
199
+
200
+ ---
201
+
202
+ ## Configuration
203
+
204
+ mcpocket stores its own config at `~/.mcpocket/config.json`:
205
+
206
+ ```jsonc
207
+ {
208
+ "githubToken": "ghp_...",
209
+ "storageType": "repo", // "repo" or "gist"
210
+ // Repo mode:
211
+ "repoFullName": "user/mcpocket-sync",
212
+ "repoCloneUrl": "https://github.com/user/mcpocket-sync.git",
213
+ "repoHtmlUrl": "https://github.com/user/mcpocket-sync",
214
+ // Gist mode:
215
+ "gistId": "abc123...",
216
+ "gistUrl": "https://gist.github.com/abc123..."
217
+ }
218
+ ```
219
+
220
+ The local repo clone (used as a staging area) lives at `~/.mcpocket/repo/`.
221
+
222
+ ---
77
223
 
78
224
  ## Requirements
79
225
 
80
- - Node.js 18+
81
- - Git (must be in PATH)
82
- - A GitHub account
226
+ - **Node.js** 18+
227
+ - **Git** in PATH (repo mode only — gist mode doesn't need git)
228
+ - A **GitHub account** with a personal access token
229
+
230
+ ---
231
+
232
+ ## Project Structure
233
+
234
+ ```
235
+ src/
236
+ cli.ts # Entry point, Commander setup
237
+ config.ts # Config read/write, storage type definitions
238
+ clients/
239
+ claude-desktop.ts # Claude Desktop config reader/writer
240
+ claude-code.ts # Claude Code settings reader/writer
241
+ opencode.ts # OpenCode config reader/writer
242
+ types.ts # Shared MCP server type definitions
243
+ commands/
244
+ init.ts # Interactive setup wizard
245
+ push.ts # Push local config to remote
246
+ pull.ts # Pull remote config to local
247
+ status.ts # Diff local vs. remote
248
+ storage/
249
+ github.ts # GitHub repo CRUD + git operations
250
+ gist.ts # GitHub Gist CRUD + file flattening
251
+ sync/
252
+ agents.ts # Agent file sync logic
253
+ mcp.ts # MCP server merge, pack/unpack, encrypt/decrypt
254
+ plugins.ts # Plugin manifest sync logic
255
+ skills.ts # Skills file sync logic
256
+ utils/
257
+ crypto.ts # AES-256-GCM encrypt/decrypt helpers
258
+ paths.ts # Cross-platform path normalization
259
+ prompt.ts # Interactive CLI input helpers
260
+ sparkle.ts # CLI banners, spinners, and personality
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Troubleshooting
266
+
267
+ ### "mcpocket is not initialized"
268
+
269
+ Run `mcpocket init` first to set up your GitHub connection and storage backend.
270
+
271
+ ### "Decryption failed — wrong passphrase"
272
+
273
+ The passphrase you entered doesn't match the one used during `mcpocket push`. Passphrases are never stored — you need to remember the one you used.
274
+
275
+ ### Push says "Nothing changed"
276
+
277
+ Your local config matches what's already in the remote pocket. No commit/upload needed.
278
+
279
+ ### MCP servers not appearing after pull
280
+
281
+ Restart Claude Desktop to reload MCP server configurations. Claude Code and OpenCode pick up changes automatically.
282
+
283
+ ### Git errors on push/pull (repo mode)
284
+
285
+ Make sure `git` is installed and in your PATH. If you see auth errors, your GitHub token may have expired — run `mcpocket init` to re-authenticate.
286
+
287
+ ---
288
+
289
+ ## Contributing
290
+
291
+ Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/davidsmorais/carry-on).
292
+
293
+ ```bash
294
+ git clone https://github.com/davidsmorais/carry-on.git
295
+ cd carry-on
296
+ pnpm install
297
+ pnpm build
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Author
303
+
304
+ **David Morais** — [david@davidmorais.com](mailto:david@davidmorais.com)
305
+
306
+ - GitHub: [@davidsmorais](https://github.com/davidsmorais)
83
307
 
84
308
  ## License
85
309
 
86
- MIT
310
+ [MIT](LICENSE) © David Morais
package/dist/cli.js CHANGED
@@ -6,30 +6,32 @@ const init_js_1 = require("./commands/init.js");
6
6
  const push_js_1 = require("./commands/push.js");
7
7
  const pull_js_1 = require("./commands/pull.js");
8
8
  const status_js_1 = require("./commands/status.js");
9
+ const sparkle_js_1 = require("./utils/sparkle.js");
9
10
  const program = new commander_1.Command();
11
+ (0, sparkle_js_1.printBanner)();
10
12
  program
11
- .name('carry-on')
12
- .description('Your AI setup. Everywhere you work.\nSyncs Claude Code agents, skills, plugins, and MCPs across machines.')
13
+ .name('mcpocket')
14
+ .description('Your AI setup. Every pocket.\nSyncs agents, skills, plugins, and MCPs across all your machines like magic.')
13
15
  .version('0.1.0');
14
16
  program
15
17
  .command('init')
16
- .description('Set up carry-on: connect GitHub, create sync repo')
18
+ .description('Set up mcpocket: connect GitHub, create your sync pocket')
17
19
  .action(() => (0, init_js_1.initCommand)().catch(die));
18
20
  program
19
21
  .command('push')
20
- .description('Upload your current AI setup to the cloud')
22
+ .description('Tuck your AI setup into the cloud pocket')
21
23
  .action(() => (0, push_js_1.pushCommand)().catch(die));
22
24
  program
23
25
  .command('pull')
24
- .description('Restore your AI setup from the cloud')
26
+ .description('Unpack your AI setup from the cloud pocket')
25
27
  .action(() => (0, pull_js_1.pullCommand)().catch(die));
26
28
  program
27
29
  .command('status')
28
- .description('Show what\'s synced vs. local-only vs. remote-only')
30
+ .description('Peek inside: what\'s synced, what\'s local, what\'s remote')
29
31
  .action(() => (0, status_js_1.statusCommand)().catch(die));
30
32
  program.parse();
31
33
  function die(err) {
32
- console.error(`\nError: ${err.message}`);
34
+ (0, sparkle_js_1.oops)(err.message);
33
35
  process.exit(1);
34
36
  }
35
37
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,gDAAiD;AACjD,gDAAiD;AACjD,gDAAiD;AACjD,oDAAqD;AAErD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,2GAA2G,CAAC;KACxH,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,mDAAmD,CAAC;KAChE,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1C,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1C,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1C,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oDAAoD,CAAC;KACjE,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,yBAAa,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE5C,OAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,SAAS,GAAG,CAAC,GAAU;IACrB,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,gDAAiD;AACjD,gDAAiD;AACjD,gDAAiD;AACjD,oDAAqD;AACrD,mDAAuD;AAEvD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,IAAA,wBAAW,GAAE,CAAC;AAEd,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,4GAA4G,CAAC;KACzH,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1C,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1C,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,4CAA4C,CAAC;KACzD,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,qBAAW,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1C,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,4DAA4D,CAAC;KACzE,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,yBAAa,GAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAE5C,OAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,SAAS,GAAG,CAAC,GAAU;IACrB,IAAA,iBAAI,EAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -49,7 +49,7 @@ function readClaudeCodeSettings() {
49
49
  return JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
50
50
  }
51
51
  catch {
52
- console.warn(`[carry-on] Could not read Claude Code settings at ${settingsPath}`);
52
+ console.warn(`[mcpocket] Could not read Claude Code settings at ${settingsPath}`);
53
53
  return {};
54
54
  }
55
55
  }
@@ -65,7 +65,7 @@ function writeClaudeCodeMcpServers(servers) {
65
65
  settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
66
66
  }
67
67
  catch {
68
- console.warn(`[carry-on] Could not parse existing Claude Code settings, will overwrite mcpServers only`);
68
+ console.warn(`[mcpocket] Could not parse existing Claude Code settings, will overwrite mcpServers only`);
69
69
  }
70
70
  }
71
71
  else {
@@ -50,7 +50,7 @@ function readClaudeDesktopMcpServers() {
50
50
  return config.mcpServers ?? {};
51
51
  }
52
52
  catch {
53
- console.warn(`[carry-on] Could not read Claude Desktop config at ${configPath}`);
53
+ console.warn(`[mcpocket] Could not read Claude Desktop config at ${configPath}`);
54
54
  return {};
55
55
  }
56
56
  }
@@ -63,7 +63,7 @@ function writeClaudeDesktopMcpServers(servers) {
63
63
  config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
64
64
  }
65
65
  catch {
66
- console.warn(`[carry-on] Could not parse existing Claude Desktop config, will overwrite mcpServers only`);
66
+ console.warn(`[mcpocket] Could not parse existing Claude Desktop config, will overwrite mcpServers only`);
67
67
  }
68
68
  }
69
69
  else {
@@ -49,7 +49,7 @@ function readOpenCodeMcpServers() {
49
49
  return config.mcp?.servers ?? {};
50
50
  }
51
51
  catch {
52
- console.warn(`[carry-on] Could not read OpenCode config at ${configPath}`);
52
+ console.warn(`[mcpocket] Could not read OpenCode config at ${configPath}`);
53
53
  return {};
54
54
  }
55
55
  }
@@ -62,7 +62,7 @@ function writeOpenCodeMcpServers(servers) {
62
62
  config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
63
63
  }
64
64
  catch {
65
- console.warn(`[carry-on] Could not parse existing OpenCode config, will overwrite mcp.servers only`);
65
+ console.warn(`[mcpocket] Could not parse existing OpenCode config, will overwrite mcp.servers only`);
66
66
  }
67
67
  }
68
68
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoEjD"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAsGjD"}
@@ -1,71 +1,139 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.initCommand = initCommand;
4
37
  const github_js_1 = require("../storage/github.js");
38
+ const gist_js_1 = require("../storage/gist.js");
5
39
  const config_js_1 = require("../config.js");
6
40
  const prompt_js_1 = require("../utils/prompt.js");
41
+ const sparkle_js_1 = require("../utils/sparkle.js");
7
42
  async function initCommand() {
8
- console.log('carry-on init\n');
43
+ (0, sparkle_js_1.section)('Init');
9
44
  if ((0, config_js_1.configExists)()) {
10
- const overwrite = await (0, prompt_js_1.ask)('carry-on is already initialized. Re-initialize? [y/N] ');
45
+ const overwrite = await (0, prompt_js_1.ask)(' mcpocket is already set up. Re-initialize? [y/N] ');
11
46
  if (overwrite.toLowerCase() !== 'y') {
12
- console.log('Aborted.');
47
+ (0, sparkle_js_1.sparkle)('No worries, keeping everything as-is.');
13
48
  return;
14
49
  }
15
50
  }
16
51
  // Get GitHub token
17
- console.log('Enter your GitHub personal access token.');
18
- console.log('Required scopes: repo (full control of private repositories)\n');
19
- console.log('Create one at: https://github.com/settings/tokens/new\n');
20
- const token = await (0, prompt_js_1.askSecret)('GitHub token: ');
52
+ console.log('');
53
+ (0, sparkle_js_1.sparkle)('First, let\'s link your GitHub account.');
54
+ console.log(' Required scopes: repo (full control of private repositories)\n');
55
+ console.log(' Create one at: https://github.com/settings/tokens/new\n');
56
+ const token = await (0, prompt_js_1.askSecret)(' 🔑 GitHub token: ');
21
57
  if (!token) {
22
- console.error('Error: token cannot be empty.');
58
+ (0, sparkle_js_1.oops)('Token cannot be empty.');
23
59
  process.exit(1);
24
60
  }
25
61
  // Verify token and get username
26
- console.log('\nVerifying token...');
62
+ (0, sparkle_js_1.sparkle)(sparkle_js_1.WITTY.verifying);
27
63
  let owner = '';
28
64
  try {
29
65
  owner = await (0, github_js_1.getAuthenticatedUser)(token);
30
- console.log(`✓ Authenticated as ${owner}`);
31
- }
32
- catch (err) {
33
- console.error(`Error: ${err.message}`);
34
- process.exit(1);
35
- }
36
- // Create repo
37
- console.log('\nCreating private repo carry-on-sync...');
38
- let repoInfo;
39
- try {
40
- repoInfo = await (0, github_js_1.createRepo)(token, owner);
41
- console.log(`✓ Repo ready: ${repoInfo.htmlUrl}`);
66
+ (0, sparkle_js_1.sparkle)(`Authenticated as \x1b[1m${owner}\x1b[0m — nice to meet you!`);
42
67
  }
43
68
  catch (err) {
44
- console.error(`Error: ${err.message}`);
69
+ (0, sparkle_js_1.oops)(err.message);
45
70
  process.exit(1);
46
71
  }
47
- // Clone repo locally
48
- const localDir = (0, config_js_1.getLocalRepoDir)();
49
- console.log(`\nCloning to ${localDir}...`);
50
- try {
51
- (0, github_js_1.cloneRepo)(repoInfo.cloneUrl, token, localDir);
52
- (0, github_js_1.ensureGitConfig)(localDir);
53
- console.log(' Repo cloned');
72
+ // Choose storage type
73
+ console.log('');
74
+ (0, sparkle_js_1.sparkle)('Where should mcpocket store your config?');
75
+ console.log(' [1] GitHub repo (private repo, full git history)');
76
+ console.log(' [2] GitHub gist (lighter, no git clone needed)\n');
77
+ const storageChoice = await (0, prompt_js_1.ask)(' Pick one [1/2]: ');
78
+ const storageType = storageChoice === '2' ? 'gist' : 'repo';
79
+ if (storageType === 'gist') {
80
+ (0, sparkle_js_1.sparkle)('Creating your private sync gist...');
81
+ let gistInfo;
82
+ try {
83
+ gistInfo = await (0, gist_js_1.createGist)(token);
84
+ (0, sparkle_js_1.sparkle)(`Pocket ready: ${gistInfo.htmlUrl}`);
85
+ }
86
+ catch (err) {
87
+ (0, sparkle_js_1.oops)(err.message);
88
+ process.exit(1);
89
+ }
90
+ // Ensure staging dir exists
91
+ const localDir = (0, config_js_1.getLocalRepoDir)();
92
+ const fs = await Promise.resolve().then(() => __importStar(require('fs')));
93
+ fs.mkdirSync(localDir, { recursive: true });
94
+ (0, config_js_1.writeConfig)({
95
+ githubToken: token,
96
+ storageType: 'gist',
97
+ gistId: gistInfo.id,
98
+ gistUrl: gistInfo.htmlUrl,
99
+ });
54
100
  }
55
- catch (err) {
56
- console.error(`Error: ${err.message}`);
57
- process.exit(1);
101
+ else {
102
+ // Create repo
103
+ (0, sparkle_js_1.sparkle)('Creating your private sync pocket (mcpocket-sync)...');
104
+ let repoInfo;
105
+ try {
106
+ repoInfo = await (0, github_js_1.createRepo)(token, owner);
107
+ (0, sparkle_js_1.sparkle)(`Pocket ready: ${repoInfo.htmlUrl}`);
108
+ }
109
+ catch (err) {
110
+ (0, sparkle_js_1.oops)(err.message);
111
+ process.exit(1);
112
+ }
113
+ // Clone repo locally
114
+ const localDir = (0, config_js_1.getLocalRepoDir)();
115
+ (0, sparkle_js_1.sparkle)(sparkle_js_1.WITTY.cloning);
116
+ try {
117
+ (0, github_js_1.cloneRepo)(repoInfo.cloneUrl, token, localDir);
118
+ (0, github_js_1.ensureGitConfig)(localDir);
119
+ (0, sparkle_js_1.sparkle)(`Stashed at ${localDir}`);
120
+ }
121
+ catch (err) {
122
+ (0, sparkle_js_1.oops)(err.message);
123
+ process.exit(1);
124
+ }
125
+ (0, config_js_1.writeConfig)({
126
+ githubToken: token,
127
+ storageType: 'repo',
128
+ repoFullName: repoInfo.fullName,
129
+ repoCloneUrl: repoInfo.cloneUrl,
130
+ repoHtmlUrl: repoInfo.htmlUrl,
131
+ });
58
132
  }
59
- // Save config
60
- (0, config_js_1.writeConfig)({
61
- githubToken: token,
62
- repoFullName: repoInfo.fullName,
63
- repoCloneUrl: repoInfo.cloneUrl,
64
- repoHtmlUrl: repoInfo.htmlUrl,
65
- });
66
- console.log('\n✓ carry-on initialized!');
67
- console.log('\nNext steps:');
68
- console.log(' carry-on push — sync this machine\'s setup to the cloud');
69
- console.log(' carry-on pull — restore your setup on a new machine');
133
+ (0, sparkle_js_1.celebrate)(sparkle_js_1.WITTY.initDone);
134
+ console.log('\n Next steps:');
135
+ (0, sparkle_js_1.sparkle)('mcpocket push — tuck your setup into the cloud');
136
+ (0, sparkle_js_1.sparkle)('mcpocket pull — unpack your setup on a new machine');
137
+ console.log('');
70
138
  }
71
139
  //# sourceMappingURL=init.js.map