@biswaviraj/cc-setup 1.0.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "enabledPlugins": {
3
+ "superpowers@claude-plugins-official": true,
4
+ "context-mode@context-mode": true,
5
+ "feature-dev@claude-plugins-official": true
6
+ }
7
+ }
package/index.mjs ADDED
@@ -0,0 +1,275 @@
1
+ #!/usr/bin/env node
2
+
3
+ import * as p from "@clack/prompts";
4
+ import { execSync } from "node:child_process";
5
+ import { existsSync, readFileSync } from "node:fs";
6
+ import { homedir } from "node:os";
7
+ import { join } from "node:path";
8
+ import pc from "picocolors";
9
+
10
+ // ── Built-in Registry ───────────────────────────────────────
11
+ // Popular plugins & servers. Users can extend via ~/.cc-setup.json
12
+
13
+ const BUILTIN_PLUGINS = [
14
+ {
15
+ value: "superpowers",
16
+ label: "Superpowers",
17
+ hint: "brainstorming, TDD, debugging, plans, worktrees",
18
+ install: "superpowers",
19
+ },
20
+ {
21
+ value: "frontend-design",
22
+ label: "Frontend Design",
23
+ hint: "production-grade UI components",
24
+ install: "frontend-design",
25
+ },
26
+ {
27
+ value: "context-mode",
28
+ label: "Context Mode",
29
+ hint: "context window optimization",
30
+ install: "context-mode@context-mode",
31
+ marketplace: "mksglu/context-mode",
32
+ },
33
+ {
34
+ value: "context7",
35
+ label: "Context7",
36
+ hint: "library & framework docs lookup",
37
+ install: "context7-plugin@context7-marketplace",
38
+ marketplace: "upstash/context7",
39
+ },
40
+ {
41
+ value: "feature-dev",
42
+ label: "Feature Dev",
43
+ hint: "guided feature development",
44
+ install: "feature-dev",
45
+ },
46
+ {
47
+ value: "mongodb",
48
+ label: "MongoDB",
49
+ hint: "database ops, schema design, queries",
50
+ install: "mongodb",
51
+ },
52
+ ];
53
+
54
+ const BUILTIN_MCP = [];
55
+
56
+ // ── Config ──────────────────────────────────────────────────
57
+
58
+ const CONFIG_PATH = join(homedir(), ".cc-setup.json");
59
+
60
+ function loadConfig() {
61
+ if (!existsSync(CONFIG_PATH)) return null;
62
+ try {
63
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
64
+ } catch {
65
+ return null;
66
+ }
67
+ }
68
+
69
+ function merge(builtin, user) {
70
+ if (!user?.length) return builtin;
71
+ const seen = new Set(builtin.map((t) => t.value));
72
+ return [...builtin, ...user.filter((t) => !seen.has(t.value))];
73
+ }
74
+
75
+ // ── Helpers ─────────────────────────────────────────────────
76
+
77
+ function run(cmd) {
78
+ try {
79
+ return {
80
+ ok: true,
81
+ output: execSync(cmd, { encoding: "utf-8", stdio: "pipe" }).trim(),
82
+ };
83
+ } catch (e) {
84
+ return { ok: false, output: (e.stderr || e.message).trim() };
85
+ }
86
+ }
87
+
88
+ function parseArgs() {
89
+ const args = process.argv.slice(2);
90
+ return {
91
+ quick: args.includes("--quick") || args.includes("-q"),
92
+ scope: args.find((_, i, a) => a[i - 1] === "--scope") || null,
93
+ help: args.includes("--help") || args.includes("-h"),
94
+ };
95
+ }
96
+
97
+ // ── Main ────────────────────────────────────────────────────
98
+
99
+ async function main() {
100
+ const args = parseArgs();
101
+
102
+ if (args.help) {
103
+ console.log(`
104
+ ${pc.bold("cc-setup")} — Add Claude Code plugins & MCP servers to any project
105
+
106
+ ${pc.dim("Usage:")}
107
+ cc-setup Interactive picker
108
+ cc-setup --quick Install defaults from config
109
+ cc-setup --quick --scope local Fully non-interactive
110
+
111
+ ${pc.dim("Config:")} ~/.cc-setup.json
112
+
113
+ {
114
+ "defaults": ["superpowers", "playwright"],
115
+ "plugins": [
116
+ { "value": "id", "label": "Name", "hint": "description", "install": "id@marketplace", "marketplace": "org/repo" }
117
+ ],
118
+ "mcpServers": [
119
+ { "value": "id", "label": "Name", "hint": "description", "command": "npx my-server" }
120
+ ]
121
+ }
122
+
123
+ ${pc.dim("Fields:")}
124
+ plugins.marketplace Optional. GitHub repo for non-official marketplaces.
125
+ defaults Tool IDs to install with --quick.
126
+ `);
127
+ process.exit(0);
128
+ }
129
+
130
+ console.clear();
131
+ p.intro(`${pc.bgCyan(pc.black(" cc-setup "))} ${pc.dim("v1.0.0")}`);
132
+
133
+ // Preflight
134
+ const check = run("claude --version");
135
+ if (!check.ok) {
136
+ p.cancel(
137
+ "Claude Code CLI not found. Install: npm i -g @anthropic-ai/claude-code",
138
+ );
139
+ process.exit(1);
140
+ }
141
+ p.log.info(`${pc.dim("Claude Code")} ${check.output}`);
142
+
143
+ // Load & merge
144
+ const config = loadConfig();
145
+ if (config) p.log.info(`${pc.dim("Config loaded from")} ${CONFIG_PATH}`);
146
+
147
+ const plugins = merge(BUILTIN_PLUGINS, config?.plugins);
148
+ const mcpServers = merge(BUILTIN_MCP, config?.mcpServers);
149
+ const defaults = config?.defaults || [];
150
+
151
+ const pluginMap = new Map(plugins.map((pl) => [pl.value, pl]));
152
+ const mcpMap = new Map(mcpServers.map((m) => [m.value, m]));
153
+
154
+ // ── Select ────────────────────────────────────────────────
155
+
156
+ let selectedIds;
157
+
158
+ if (args.quick) {
159
+ if (!defaults.length) {
160
+ p.cancel('No defaults configured. Add "defaults" to ~/.cc-setup.json');
161
+ process.exit(1);
162
+ }
163
+ selectedIds = defaults;
164
+ p.log.info(`Using defaults: ${defaults.map((d) => pc.cyan(d)).join(", ")}`);
165
+ } else {
166
+ const groups = {};
167
+ if (plugins.length)
168
+ groups["Plugins"] = plugins.map((t) => ({
169
+ value: t.value,
170
+ label: t.label,
171
+ hint: t.hint,
172
+ }));
173
+ if (mcpServers.length)
174
+ groups["MCP Servers"] = mcpServers.map((t) => ({
175
+ value: t.value,
176
+ label: t.label,
177
+ hint: t.hint,
178
+ }));
179
+
180
+ selectedIds = await p.groupMultiselect({
181
+ message: "Pick tools to add",
182
+ options: groups,
183
+ required: false,
184
+ });
185
+
186
+ if (p.isCancel(selectedIds) || !selectedIds.length) {
187
+ p.cancel("Nothing selected.");
188
+ process.exit(0);
189
+ }
190
+ }
191
+
192
+ const pluginIds = selectedIds.filter((id) => pluginMap.has(id));
193
+ const mcpIds = selectedIds.filter((id) => mcpMap.has(id));
194
+
195
+ if (!pluginIds.length && !mcpIds.length) {
196
+ p.cancel("Nothing to install.");
197
+ process.exit(0);
198
+ }
199
+
200
+ // ── Scope ─────────────────────────────────────────────────
201
+
202
+ let scope = args.scope;
203
+
204
+ if (!scope) {
205
+ scope = await p.select({
206
+ message: "Install scope",
207
+ options: [
208
+ {
209
+ value: "local",
210
+ label: "This project",
211
+ hint: ".claude/settings.local.json",
212
+ },
213
+ {
214
+ value: "project",
215
+ label: "Shared with team",
216
+ hint: ".claude/settings.json (committed)",
217
+ },
218
+ {
219
+ value: "user",
220
+ label: "Global",
221
+ hint: "~/.claude/settings.json",
222
+ },
223
+ ],
224
+ });
225
+
226
+ if (p.isCancel(scope)) {
227
+ p.cancel("Cancelled.");
228
+ process.exit(0);
229
+ }
230
+ }
231
+
232
+ // ── Install ───────────────────────────────────────────────
233
+
234
+ const s = p.spinner();
235
+ const results = [];
236
+
237
+ for (const id of pluginIds) {
238
+ const plugin = pluginMap.get(id);
239
+
240
+ if (plugin.marketplace) {
241
+ s.start(`Adding marketplace for ${plugin.label}...`);
242
+ run(`claude plugins marketplace add ${plugin.marketplace}`);
243
+ s.stop(`Marketplace ready for ${plugin.label}`);
244
+ }
245
+
246
+ s.start(`Installing ${plugin.label}...`);
247
+ const result = run(`claude plugins install ${plugin.install} -s ${scope}`);
248
+ s.stop(`${result.ok ? pc.green("✓") : pc.yellow("⚠")} ${plugin.label}`);
249
+ results.push({ name: plugin.label, ...result });
250
+ }
251
+
252
+ for (const id of mcpIds) {
253
+ const mcp = mcpMap.get(id);
254
+ s.start(`Adding ${mcp.label}...`);
255
+ const result = run(
256
+ `claude mcp add ${mcp.value} -s ${scope} -- ${mcp.command}`,
257
+ );
258
+ s.stop(`${result.ok ? pc.green("✓") : pc.yellow("⚠")} ${mcp.label}`);
259
+ results.push({ name: mcp.label, ...result });
260
+ }
261
+
262
+ // ── Summary ───────────────────────────────────────────────
263
+
264
+ const summary = results
265
+ .map((r) => {
266
+ if (r.ok) return ` ${pc.green("✓")} ${r.name}`;
267
+ return ` ${pc.red("✗")} ${r.name} ${pc.dim(`— ${r.output.split("\n")[0]}`)}`;
268
+ })
269
+ .join("\n");
270
+
271
+ p.note(summary, "Results");
272
+ p.outro("Restart Claude Code to activate new tools.");
273
+ }
274
+
275
+ main().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@biswaviraj/cc-setup",
3
+ "version": "1.0.0",
4
+ "description": "Interactive CLI to add Claude Code plugins & MCP servers to any project",
5
+ "type": "module",
6
+ "bin": {
7
+ "cc-setup": "./index.mjs"
8
+ },
9
+ "author": {
10
+ "name": "BiswaViraj",
11
+ "url": "https://github.com/BiswaViraj"
12
+ },
13
+ "keywords": [
14
+ "claude",
15
+ "claude-code",
16
+ "mcp",
17
+ "plugins",
18
+ "cli",
19
+ "setup"
20
+ ],
21
+ "license": "MIT",
22
+ "dependencies": {
23
+ "@clack/prompts": "^0.11.0",
24
+ "picocolors": "^1.1.1"
25
+ }
26
+ }