@ztffn/presentation-generator-plugin 1.0.5 → 1.0.7

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 (2) hide show
  1. package/bin/index.js +82 -17
  2. package/package.json +1 -1
package/bin/index.js CHANGED
@@ -5,6 +5,7 @@ const { execSync } = require("child_process");
5
5
  const fs = require("fs");
6
6
  const path = require("path");
7
7
  const os = require("os");
8
+ const readline = require("readline");
8
9
 
9
10
  const NPM_PACKAGE = "@ztffn/presentation-generator-plugin";
10
11
  const PLUGIN_NAME = "presentation-generator";
@@ -100,14 +101,58 @@ async function downloadAndExtract(version, tarballUrl) {
100
101
  fs.rmSync(tmpDir, { recursive: true, force: true });
101
102
  }
102
103
 
103
- function registerPlugin() {
104
+ function promptChoice(title, choices) {
105
+ return new Promise((resolve) => {
106
+ console.log(`\n◆ ${title}`);
107
+ choices.forEach((c, i) => {
108
+ const bullet = i === 0 ? "●" : "○";
109
+ console.log(`│ ${bullet} ${i + 1}) ${c.label}`);
110
+ if (c.hint) console.log(`│ ${c.hint}`);
111
+ });
112
+ console.log("│");
113
+
114
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
115
+ rl.question(`└ Enter choice [1-${choices.length}]: `, (answer) => {
116
+ rl.close();
117
+ const idx = parseInt(answer.trim(), 10) - 1;
118
+ resolve(idx >= 0 && idx < choices.length ? idx : 0);
119
+ });
120
+ });
121
+ }
122
+
123
+ async function resolveSettingsPath() {
124
+ const projectClaudeDir = path.join(process.cwd(), ".claude");
125
+ const userSettingsPath = path.join(os.homedir(), ".claude", "settings.json");
126
+
127
+ if (!fs.existsSync(projectClaudeDir)) {
128
+ return { settingsPath: userSettingsPath, scope: "user" };
129
+ }
130
+
131
+ const idx = await promptChoice("Installation scope", [
132
+ {
133
+ label: "Global",
134
+ hint: "Registered in ~/.claude/settings.json — available in all sessions",
135
+ },
136
+ {
137
+ label: "Project",
138
+ hint: "Registered in .claude/settings.json — commit to share with your team",
139
+ },
140
+ ]);
141
+
142
+ if (idx === 1) {
143
+ return {
144
+ settingsPath: path.join(projectClaudeDir, "settings.json"),
145
+ scope: "project",
146
+ };
147
+ }
148
+
149
+ return { settingsPath: userSettingsPath, scope: "user" };
150
+ }
151
+
152
+ async function registerPlugin() {
104
153
  console.log("\nRegistering plugin with Claude Code...");
105
154
 
106
- // Prefer project-level settings if .claude/ exists in cwd, else user-level
107
- const projectDir = path.join(process.cwd(), ".claude");
108
- const settingsPath = fs.existsSync(projectDir)
109
- ? path.join(projectDir, "settings.json")
110
- : path.join(os.homedir(), ".claude", "settings.json");
155
+ const { settingsPath, scope } = await resolveSettingsPath();
111
156
 
112
157
  try {
113
158
  let settings = {};
@@ -126,18 +171,17 @@ function registerPlugin() {
126
171
  fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
127
172
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
128
173
 
129
- const label = settingsPath.startsWith(process.cwd())
130
- ? ".claude/settings.json"
131
- : settingsPath;
132
- console.log(`Plugin registered in ${label} ✓`);
133
-
134
- if (settingsPath.startsWith(process.cwd())) {
135
- console.log("Commit that file to share the plugin with your team.");
174
+ if (scope === "project") {
175
+ console.log(`Plugin registered in .claude/settings.json ✓`);
176
+ console.log(
177
+ "Each teammate still needs to run: npx @ztffn/presentation-generator-plugin install"
178
+ );
179
+ } else {
180
+ console.log(`Plugin registered in ~/.claude/settings.json ✓`);
181
+ console.log("Available in all your Claude Code sessions.");
136
182
  }
137
183
  } catch {
138
- console.log(
139
- "\nCould not write settings. Add manually to .claude/settings.json:"
140
- );
184
+ console.log("\nCould not write settings. Add manually to ~/.claude/settings.json:");
141
185
  console.log(JSON.stringify({ enabledPlugins: [INSTALL_DIR] }, null, 2));
142
186
  console.log(`\nOr load for a single session:`);
143
187
  console.log(` claude --plugin-dir "${INSTALL_DIR}"`);
@@ -235,13 +279,34 @@ async function checkUpdate() {
235
279
  }
236
280
  }
237
281
 
282
+ function removeFromSettings(settingsPath) {
283
+ if (!fs.existsSync(settingsPath)) return;
284
+ try {
285
+ const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
286
+ if (!Array.isArray(settings.enabledPlugins)) return;
287
+ const before = settings.enabledPlugins.length;
288
+ settings.enabledPlugins = settings.enabledPlugins.filter((p) => p !== INSTALL_DIR);
289
+ if (settings.enabledPlugins.length !== before) {
290
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
291
+ console.log(`Removed from ${settingsPath}`);
292
+ }
293
+ } catch {
294
+ // ignore
295
+ }
296
+ }
297
+
238
298
  function uninstall() {
239
299
  if (!fs.existsSync(INSTALL_DIR)) {
240
300
  console.log("\nPlugin not installed.\n");
241
301
  return;
242
302
  }
243
303
  fs.rmSync(INSTALL_DIR, { recursive: true, force: true });
244
- console.log(`\nRemoved: ${INSTALL_DIR}\n`);
304
+ console.log(`\nRemoved: ${INSTALL_DIR}`);
305
+
306
+ // Clean up both possible settings locations
307
+ removeFromSettings(path.join(os.homedir(), ".claude", "settings.json"));
308
+ removeFromSettings(path.join(process.cwd(), ".claude", "settings.json"));
309
+ console.log();
245
310
  }
246
311
 
247
312
  function help() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ztffn/presentation-generator-plugin",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Claude Code plugin for generating graph-based presentations",
5
5
  "bin": {
6
6
  "presentation-generator-plugin": "bin/index.js"