ga-plugins-cli 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.
@@ -0,0 +1,53 @@
1
+ import { ClaudeConfig, PluginConfig } from './types.js';
2
+ /**
3
+ * Returns the absolute path to ~/.claude.json (or %USERPROFILE%\.claude.json on Windows).
4
+ *
5
+ * Claude Code reads its global config from this file on all platforms.
6
+ */
7
+ export declare function getClaudeConfigPath(): string;
8
+ /**
9
+ * Returns the absolute path to the plugins directory (~/.claude/plugins/).
10
+ *
11
+ * On Windows this resolves to %USERPROFILE%\.claude\plugins\.
12
+ */
13
+ export declare function getPluginsDir(): string;
14
+ /**
15
+ * Reads and parses ~/.claude.json.
16
+ *
17
+ * Returns an empty object `{}` if the file does not exist or is empty.
18
+ * Throws if the file exists but contains invalid JSON.
19
+ */
20
+ export declare function readClaudeConfig(): ClaudeConfig;
21
+ /**
22
+ * Atomically writes `config` to ~/.claude.json.
23
+ *
24
+ * Strategy:
25
+ * 1. Back up the existing file to .claude.json.bak-<timestamp> (if it exists)
26
+ * 2. Write the new content to .claude.json.tmp-<timestamp>
27
+ * 3. Rename (atomic on POSIX; best-effort on Windows) to .claude.json
28
+ *
29
+ * This ensures a partially-written file never leaves Claude in a broken state.
30
+ */
31
+ export declare function writeClaudeConfig(config: ClaudeConfig): void;
32
+ /**
33
+ * Adds a plugin entry to the config's `plugins` array.
34
+ *
35
+ * Idempotent: if an entry with the same `id` already exists, it is replaced
36
+ * with the new entry (path update). No duplicate entries are created.
37
+ *
38
+ * Returns the modified config (does NOT write to disk — caller must call writeClaudeConfig).
39
+ */
40
+ export declare function addPluginEntry(config: ClaudeConfig, entry: PluginConfig): ClaudeConfig;
41
+ /**
42
+ * Removes a plugin entry from the config's `plugins` array by ID.
43
+ *
44
+ * Safe to call even if the entry does not exist — returns config unchanged.
45
+ *
46
+ * Returns the modified config (does NOT write to disk — caller must call writeClaudeConfig).
47
+ */
48
+ export declare function removePluginEntry(config: ClaudeConfig, pluginId: string): ClaudeConfig;
49
+ /**
50
+ * Returns the path to the versions tracking file inside the plugins directory.
51
+ */
52
+ export declare function getVersionsFilePath(): string;
53
+ //# sourceMappingURL=config-patcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-patcher.d.ts","sourceRoot":"","sources":["../src/config-patcher.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAIxD;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,CAiB/C;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CA0B5D;AAID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAYtF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAOtF;AAID;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getClaudeConfigPath = getClaudeConfigPath;
7
+ exports.getPluginsDir = getPluginsDir;
8
+ exports.readClaudeConfig = readClaudeConfig;
9
+ exports.writeClaudeConfig = writeClaudeConfig;
10
+ exports.addPluginEntry = addPluginEntry;
11
+ exports.removePluginEntry = removePluginEntry;
12
+ exports.getVersionsFilePath = getVersionsFilePath;
13
+ const fs_extra_1 = __importDefault(require("fs-extra"));
14
+ const os_1 = __importDefault(require("os"));
15
+ const path_1 = __importDefault(require("path"));
16
+ // ─── Path resolution (cross-platform) ─────────────────────────────────────────
17
+ /**
18
+ * Returns the absolute path to ~/.claude.json (or %USERPROFILE%\.claude.json on Windows).
19
+ *
20
+ * Claude Code reads its global config from this file on all platforms.
21
+ */
22
+ function getClaudeConfigPath() {
23
+ return path_1.default.join(os_1.default.homedir(), '.claude.json');
24
+ }
25
+ /**
26
+ * Returns the absolute path to the plugins directory (~/.claude/plugins/).
27
+ *
28
+ * On Windows this resolves to %USERPROFILE%\.claude\plugins\.
29
+ */
30
+ function getPluginsDir() {
31
+ return path_1.default.join(os_1.default.homedir(), '.claude', 'plugins');
32
+ }
33
+ // ─── Config I/O ───────────────────────────────────────────────────────────────
34
+ /**
35
+ * Reads and parses ~/.claude.json.
36
+ *
37
+ * Returns an empty object `{}` if the file does not exist or is empty.
38
+ * Throws if the file exists but contains invalid JSON.
39
+ */
40
+ function readClaudeConfig() {
41
+ const configPath = getClaudeConfigPath();
42
+ if (!fs_extra_1.default.existsSync(configPath)) {
43
+ return {};
44
+ }
45
+ const raw = fs_extra_1.default.readFileSync(configPath, 'utf-8').trim();
46
+ if (!raw) {
47
+ return {};
48
+ }
49
+ try {
50
+ return JSON.parse(raw);
51
+ }
52
+ catch (err) {
53
+ throw new Error(`Failed to parse ${configPath}: ${err.message}`);
54
+ }
55
+ }
56
+ /**
57
+ * Atomically writes `config` to ~/.claude.json.
58
+ *
59
+ * Strategy:
60
+ * 1. Back up the existing file to .claude.json.bak-<timestamp> (if it exists)
61
+ * 2. Write the new content to .claude.json.tmp-<timestamp>
62
+ * 3. Rename (atomic on POSIX; best-effort on Windows) to .claude.json
63
+ *
64
+ * This ensures a partially-written file never leaves Claude in a broken state.
65
+ */
66
+ function writeClaudeConfig(config) {
67
+ const configPath = getClaudeConfigPath();
68
+ const timestamp = Date.now();
69
+ // Step 1 — back up existing file
70
+ if (fs_extra_1.default.existsSync(configPath)) {
71
+ const backupPath = `${configPath}.bak-${timestamp}`;
72
+ fs_extra_1.default.copyFileSync(configPath, backupPath);
73
+ }
74
+ // Step 2 — write to temp file
75
+ const tmpPath = `${configPath}.tmp-${timestamp}`;
76
+ const content = JSON.stringify(config, null, 2) + '\n';
77
+ fs_extra_1.default.writeFileSync(tmpPath, content, 'utf-8');
78
+ // Step 3 — atomic rename
79
+ // On Windows, rename over an existing file may fail; remove first if needed.
80
+ try {
81
+ fs_extra_1.default.renameSync(tmpPath, configPath);
82
+ }
83
+ catch (err) {
84
+ // Fallback for Windows: remove target then rename
85
+ if (fs_extra_1.default.existsSync(configPath)) {
86
+ fs_extra_1.default.unlinkSync(configPath);
87
+ }
88
+ fs_extra_1.default.renameSync(tmpPath, configPath);
89
+ }
90
+ }
91
+ // ─── Plugin entry management ──────────────────────────────────────────────────
92
+ /**
93
+ * Adds a plugin entry to the config's `plugins` array.
94
+ *
95
+ * Idempotent: if an entry with the same `id` already exists, it is replaced
96
+ * with the new entry (path update). No duplicate entries are created.
97
+ *
98
+ * Returns the modified config (does NOT write to disk — caller must call writeClaudeConfig).
99
+ */
100
+ function addPluginEntry(config, entry) {
101
+ const plugins = Array.isArray(config.plugins) ? [...config.plugins] : [];
102
+ const existingIndex = plugins.findIndex((p) => p.id === entry.id);
103
+ if (existingIndex >= 0) {
104
+ // Replace existing entry (e.g. path update on reinstall)
105
+ plugins[existingIndex] = entry;
106
+ }
107
+ else {
108
+ plugins.push(entry);
109
+ }
110
+ return { ...config, plugins };
111
+ }
112
+ /**
113
+ * Removes a plugin entry from the config's `plugins` array by ID.
114
+ *
115
+ * Safe to call even if the entry does not exist — returns config unchanged.
116
+ *
117
+ * Returns the modified config (does NOT write to disk — caller must call writeClaudeConfig).
118
+ */
119
+ function removePluginEntry(config, pluginId) {
120
+ if (!Array.isArray(config.plugins)) {
121
+ return config;
122
+ }
123
+ const plugins = config.plugins.filter((p) => p.id !== pluginId);
124
+ return { ...config, plugins };
125
+ }
126
+ // ─── Versions file helpers ────────────────────────────────────────────────────
127
+ /**
128
+ * Returns the path to the versions tracking file inside the plugins directory.
129
+ */
130
+ function getVersionsFilePath() {
131
+ return path_1.default.join(getPluginsDir(), '.ga-versions.json');
132
+ }
133
+ //# sourceMappingURL=config-patcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-patcher.js","sourceRoot":"","sources":["../src/config-patcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const fs_extra_1 = __importDefault(require("fs-extra"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const registry_js_1 = require("./registry.js");
13
+ const installer_js_1 = require("./installer.js");
14
+ const uninstaller_js_1 = require("./uninstaller.js");
15
+ const updater_js_1 = require("./updater.js");
16
+ const config_patcher_js_1 = require("./config-patcher.js");
17
+ // ─── Package metadata ─────────────────────────────────────────────────────────
18
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
19
+ const pkg = require('../package.json');
20
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
21
+ /**
22
+ * Reads the installed versions record, returning defaults if missing.
23
+ */
24
+ function readInstalledVersions() {
25
+ const versionsPath = (0, config_patcher_js_1.getVersionsFilePath)();
26
+ if (!fs_extra_1.default.existsSync(versionsPath)) {
27
+ return { version: pkg.version, installedAt: new Date().toISOString(), plugins: {} };
28
+ }
29
+ try {
30
+ return fs_extra_1.default.readJSONSync(versionsPath);
31
+ }
32
+ catch {
33
+ return { version: pkg.version, installedAt: new Date().toISOString(), plugins: {} };
34
+ }
35
+ }
36
+ /**
37
+ * Returns true if a plugin folder exists in the plugins directory.
38
+ */
39
+ function isPluginInstalled(pluginId) {
40
+ return fs_extra_1.default.existsSync(path_1.default.join((0, config_patcher_js_1.getPluginsDir)(), pluginId));
41
+ }
42
+ /**
43
+ * Validates an array of plugin IDs against the registry.
44
+ * Prints an error and exits with code 1 if any are unknown.
45
+ */
46
+ function requireValidPluginIds(ids) {
47
+ const unknown = ids.filter((id) => !(0, registry_js_1.validatePluginId)(id));
48
+ if (unknown.length > 0) {
49
+ console.error(chalk_1.default.red(`Unknown plugin(s): ${unknown.map((id) => `"${id}"`).join(', ')}\n` +
50
+ `Run ${chalk_1.default.bold('ga-plugins-cli list')} to see available plugins.`));
51
+ process.exit(1);
52
+ }
53
+ }
54
+ /**
55
+ * Wraps an async command handler with error handling + process.exit(1) on failure.
56
+ */
57
+ function wrapAsync(fn) {
58
+ return (...args) => {
59
+ fn(...args).catch((err) => {
60
+ const message = err instanceof Error ? err.message : String(err);
61
+ console.error(chalk_1.default.red(`\nError: ${message}`));
62
+ process.exit(1);
63
+ });
64
+ };
65
+ }
66
+ // ─── CLI definition ───────────────────────────────────────────────────────────
67
+ const program = new commander_1.Command();
68
+ program
69
+ .name('ga-plugins-cli')
70
+ .version(pkg.version, '-v, --version', 'Print version and exit')
71
+ .description(pkg.description)
72
+ .addHelpText('after', `\nAvailable plugins:\n${registry_js_1.PLUGINS.map((p) => ` ${chalk_1.default.cyan(p.id.padEnd(20))} ${p.description}`).join('\n')}`);
73
+ // ─── install ──────────────────────────────────────────────────────────────────
74
+ program
75
+ .command('install [plugin...]')
76
+ .description('Install one or more GA plugins to ~/.claude/plugins/. ' +
77
+ 'If no plugin names are given, installs ALL available plugins.')
78
+ .option('-n, --dry-run', 'Print actions without making any changes')
79
+ .action(wrapAsync(async (plugins, options) => {
80
+ const dryRun = options.dryRun ?? false;
81
+ let targetIds;
82
+ if (plugins.length === 0) {
83
+ targetIds = (0, registry_js_1.getAllPluginIds)();
84
+ console.log(chalk_1.default.bold(`\nInstalling all ${targetIds.length} GA plugins...\n`));
85
+ }
86
+ else {
87
+ requireValidPluginIds(plugins);
88
+ targetIds = plugins;
89
+ console.log(chalk_1.default.bold(`\nInstalling ${targetIds.length} plugin(s): ${targetIds.join(', ')}\n`));
90
+ }
91
+ if (dryRun) {
92
+ console.log(chalk_1.default.yellow('Dry-run mode: no files will be written.\n'));
93
+ }
94
+ const spinner = (0, ora_1.default)({
95
+ text: 'Installing plugins...',
96
+ isSilent: dryRun, // suppress spinner output in dry-run so lines aren't interleaved
97
+ }).start();
98
+ try {
99
+ await (0, installer_js_1.install)(targetIds, { dryRun });
100
+ spinner.succeed(chalk_1.default.green(`Done. ${targetIds.length} plugin(s) installed to ~/.claude/plugins/`));
101
+ }
102
+ catch (err) {
103
+ spinner.fail(chalk_1.default.red('Installation failed'));
104
+ throw err;
105
+ }
106
+ }));
107
+ // ─── uninstall ────────────────────────────────────────────────────────────────
108
+ program
109
+ .command('uninstall [plugin...]')
110
+ .description('Uninstall one or more GA plugins. ' +
111
+ 'If no plugin names are given, uninstalls ALL installed plugins.')
112
+ .option('-n, --dry-run', 'Print actions without making any changes')
113
+ .option('-y, --yes', 'Skip confirmation prompt when uninstalling all')
114
+ .action(wrapAsync(async (plugins, options) => {
115
+ const dryRun = options.dryRun ?? false;
116
+ const skipConfirm = options.yes ?? false;
117
+ if (dryRun) {
118
+ console.log(chalk_1.default.yellow('\nDry-run mode: no files will be removed.\n'));
119
+ }
120
+ if (plugins.length === 0) {
121
+ // Uninstall all
122
+ const spinner = (0, ora_1.default)({ text: 'Removing all GA plugins...', isSilent: dryRun }).start();
123
+ try {
124
+ await (0, uninstaller_js_1.uninstallAll)({ dryRun, skipConfirm });
125
+ spinner.succeed(chalk_1.default.green('All GA plugins uninstalled.'));
126
+ }
127
+ catch (err) {
128
+ spinner.fail(chalk_1.default.red('Uninstall failed'));
129
+ throw err;
130
+ }
131
+ }
132
+ else {
133
+ requireValidPluginIds(plugins);
134
+ console.log(chalk_1.default.bold(`\nUninstalling ${plugins.length} plugin(s): ${plugins.join(', ')}\n`));
135
+ const spinner = (0, ora_1.default)({ text: 'Removing plugins...', isSilent: dryRun }).start();
136
+ try {
137
+ await (0, uninstaller_js_1.uninstall)(plugins, { dryRun });
138
+ spinner.succeed(chalk_1.default.green(`${plugins.length} plugin(s) uninstalled.`));
139
+ }
140
+ catch (err) {
141
+ spinner.fail(chalk_1.default.red('Uninstall failed'));
142
+ throw err;
143
+ }
144
+ }
145
+ }));
146
+ // ─── list ─────────────────────────────────────────────────────────────────────
147
+ program
148
+ .command('list')
149
+ .description('Show all available plugins with installed/not-installed status and version')
150
+ .action(wrapAsync(async () => {
151
+ const versions = readInstalledVersions();
152
+ console.log(chalk_1.default.bold(`\nGA Migration Claude Code Plugins (package v${pkg.version})\n`));
153
+ console.log(chalk_1.default.dim(`${'ID'.padEnd(22)} ${'STATUS'.padEnd(15)} ${'VERSION'.padEnd(12)} DESCRIPTION`));
154
+ console.log(chalk_1.default.dim('─'.repeat(100)));
155
+ for (const plugin of registry_js_1.PLUGINS) {
156
+ const installed = isPluginInstalled(plugin.id);
157
+ const versionRecord = versions.plugins[plugin.id];
158
+ const statusStr = installed
159
+ ? chalk_1.default.green('installed'.padEnd(15))
160
+ : chalk_1.default.dim('not installed'.padEnd(15));
161
+ const versionStr = versionRecord
162
+ ? chalk_1.default.cyan(versionRecord.version.padEnd(12))
163
+ : chalk_1.default.dim('—'.padEnd(12));
164
+ const idStr = installed
165
+ ? chalk_1.default.bold(plugin.id.padEnd(22))
166
+ : chalk_1.default.dim(plugin.id.padEnd(22));
167
+ console.log(`${idStr} ${statusStr} ${versionStr} ${plugin.description}`);
168
+ }
169
+ const installedCount = registry_js_1.PLUGINS.filter((p) => isPluginInstalled(p.id)).length;
170
+ console.log(chalk_1.default.dim(`\n${installedCount} of ${registry_js_1.PLUGINS.length} plugins installed.` +
171
+ ` Install path: ${(0, config_patcher_js_1.getPluginsDir)()}\n`));
172
+ }));
173
+ // ─── update ───────────────────────────────────────────────────────────────────
174
+ program
175
+ .command('update [plugin...]')
176
+ .description('Update installed GA plugins to the versions bundled in the current package. ' +
177
+ 'If no plugin names are given, updates ALL installed plugins.')
178
+ .option('-n, --dry-run', 'Print actions without making any changes')
179
+ .action(wrapAsync(async (plugins, options) => {
180
+ const dryRun = options.dryRun ?? false;
181
+ if (dryRun) {
182
+ console.log(chalk_1.default.yellow('\nDry-run mode: no files will be written.\n'));
183
+ }
184
+ if (plugins.length > 0) {
185
+ requireValidPluginIds(plugins);
186
+ }
187
+ // Show update check summary first
188
+ const { current, available } = await (0, updater_js_1.checkUpdates)();
189
+ const outdated = Object.entries(current).filter(([id, ver]) => ver !== 'not installed' &&
190
+ ver !== available &&
191
+ (plugins.length === 0 || plugins.includes(id)));
192
+ const alreadyUpToDate = Object.entries(current).filter(([id, ver]) => ver !== 'not installed' &&
193
+ ver === available &&
194
+ (plugins.length === 0 || plugins.includes(id)));
195
+ if (alreadyUpToDate.length > 0) {
196
+ console.log(chalk_1.default.dim(`\nAlready up to date (v${available}):`));
197
+ for (const [id] of alreadyUpToDate) {
198
+ console.log(chalk_1.default.dim(` ✓ ${id}`));
199
+ }
200
+ }
201
+ if (outdated.length === 0 && plugins.length === 0) {
202
+ console.log(chalk_1.default.green(`\nAll installed plugins are already at v${available}.`));
203
+ return;
204
+ }
205
+ const spinner = (0, ora_1.default)({ text: 'Updating plugins...', isSilent: dryRun }).start();
206
+ try {
207
+ await (0, updater_js_1.update)(plugins, { dryRun });
208
+ spinner.succeed(chalk_1.default.green('Update complete.'));
209
+ }
210
+ catch (err) {
211
+ spinner.fail(chalk_1.default.red('Update failed'));
212
+ throw err;
213
+ }
214
+ }));
215
+ // ─── Entry ────────────────────────────────────────────────────────────────────
216
+ program.parseAsync(process.argv).catch((err) => {
217
+ const message = err instanceof Error ? err.message : String(err);
218
+ console.error(chalk_1.default.red(`Fatal: ${message}`));
219
+ process.exit(1);
220
+ });
221
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface InstallOptions {
2
+ /** When true, prints what would happen without actually doing it. */
3
+ dryRun?: boolean;
4
+ }
5
+ /**
6
+ * Installs the given plugin IDs to ~/.claude/plugins/ and registers them in ~/.claude.json.
7
+ *
8
+ * Each plugin:
9
+ * 1. Gets its bundled source path resolved from the npm package
10
+ * 2. Is copied to ~/.claude/plugins/<pluginId>/ (overwrites any existing version)
11
+ * 3. Gets an entry added/updated in ~/.claude.json under the `plugins` array
12
+ * 4. Gets its version recorded in ~/.claude/plugins/.ga-versions.json
13
+ *
14
+ * All actions are printed to stdout. In dry-run mode, no files are written.
15
+ *
16
+ * @throws if a bundled plugin source directory cannot be found
17
+ */
18
+ export declare function install(pluginIds: string[], options?: InstallOptions): Promise<void>;
19
+ /**
20
+ * Installs ALL known GA plugins.
21
+ * Convenience wrapper around `install(getAllPluginIds(), options)`.
22
+ */
23
+ export declare function installAll(options?: InstallOptions): Promise<void>;
24
+ //# sourceMappingURL=installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA2CD;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA6Df;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.install = install;
7
+ exports.installAll = installAll;
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const config_patcher_js_1 = require("./config-patcher.js");
12
+ const registry_js_1 = require("./registry.js");
13
+ // ─── Versions file helpers ────────────────────────────────────────────────────
14
+ /** Reads the versions tracking file, returning defaults if missing. */
15
+ function readVersions() {
16
+ const versionsPath = (0, config_patcher_js_1.getVersionsFilePath)();
17
+ if (!fs_extra_1.default.existsSync(versionsPath)) {
18
+ return {
19
+ version: require('../package.json').version,
20
+ installedAt: new Date().toISOString(),
21
+ plugins: {},
22
+ };
23
+ }
24
+ try {
25
+ return fs_extra_1.default.readJSONSync(versionsPath);
26
+ }
27
+ catch {
28
+ return {
29
+ version: require('../package.json').version,
30
+ installedAt: new Date().toISOString(),
31
+ plugins: {},
32
+ };
33
+ }
34
+ }
35
+ /** Writes the versions tracking file to disk. */
36
+ function writeVersions(versions, dryRun) {
37
+ const versionsPath = (0, config_patcher_js_1.getVersionsFilePath)();
38
+ if (dryRun) {
39
+ console.log(chalk_1.default.dim(` [DRY RUN] Would write versions to ${versionsPath}`));
40
+ return;
41
+ }
42
+ fs_extra_1.default.outputJSONSync(versionsPath, versions, { spaces: 2 });
43
+ }
44
+ // ─── Prefix helper ────────────────────────────────────────────────────────────
45
+ function prefix(dryRun) {
46
+ return dryRun ? chalk_1.default.yellow('[DRY RUN] ') : '';
47
+ }
48
+ // ─── Core install logic ───────────────────────────────────────────────────────
49
+ /**
50
+ * Installs the given plugin IDs to ~/.claude/plugins/ and registers them in ~/.claude.json.
51
+ *
52
+ * Each plugin:
53
+ * 1. Gets its bundled source path resolved from the npm package
54
+ * 2. Is copied to ~/.claude/plugins/<pluginId>/ (overwrites any existing version)
55
+ * 3. Gets an entry added/updated in ~/.claude.json under the `plugins` array
56
+ * 4. Gets its version recorded in ~/.claude/plugins/.ga-versions.json
57
+ *
58
+ * All actions are printed to stdout. In dry-run mode, no files are written.
59
+ *
60
+ * @throws if a bundled plugin source directory cannot be found
61
+ */
62
+ async function install(pluginIds, options = {}) {
63
+ const dryRun = options.dryRun ?? false;
64
+ const pluginsDir = (0, config_patcher_js_1.getPluginsDir)();
65
+ const pkgVersion = require('../package.json').version ?? '0.1.0';
66
+ const now = new Date().toISOString();
67
+ // Ensure ~/.claude/plugins/ exists
68
+ if (!dryRun) {
69
+ fs_extra_1.default.ensureDirSync(pluginsDir);
70
+ }
71
+ else {
72
+ console.log(chalk_1.default.dim(` [DRY RUN] Would ensure directory: ${pluginsDir}`));
73
+ }
74
+ // Load current state
75
+ const config = (0, config_patcher_js_1.readClaudeConfig)();
76
+ const versions = readVersions();
77
+ let updatedConfig = config;
78
+ for (const pluginId of pluginIds) {
79
+ const srcPath = (0, registry_js_1.getBundledPluginPath)(pluginId); // throws if unknown id
80
+ const destPath = path_1.default.join(pluginsDir, pluginId);
81
+ // ── Copy plugin folder ──────────────────────────────────────────────────
82
+ if (!fs_extra_1.default.existsSync(srcPath)) {
83
+ console.warn(chalk_1.default.yellow(` Warning: bundled plugin source not found for "${pluginId}" at ${srcPath}. ` +
84
+ `Skipping copy (the entry will still be registered).`));
85
+ }
86
+ else {
87
+ console.log(`${prefix(dryRun)}${chalk_1.default.cyan('copy')} ${chalk_1.default.dim(srcPath)}\n` +
88
+ ` ${chalk_1.default.dim('→')} ${destPath}`);
89
+ if (!dryRun) {
90
+ fs_extra_1.default.copySync(srcPath, destPath, { overwrite: true });
91
+ }
92
+ }
93
+ // ── Register in ~/.claude.json ──────────────────────────────────────────
94
+ console.log(`${prefix(dryRun)}${chalk_1.default.cyan('register')} ${pluginId} in ${chalk_1.default.dim('~/.claude.json')}`);
95
+ if (!dryRun) {
96
+ updatedConfig = (0, config_patcher_js_1.addPluginEntry)(updatedConfig, { id: pluginId, path: destPath });
97
+ }
98
+ // ── Update versions record ──────────────────────────────────────────────
99
+ versions.plugins[pluginId] = { version: pkgVersion, installedAt: now };
100
+ console.log(chalk_1.default.green(` ✓ ${pluginId} installed (v${pkgVersion})`));
101
+ }
102
+ // Write updated config and versions atomically (once, after all plugins)
103
+ if (!dryRun) {
104
+ (0, config_patcher_js_1.writeClaudeConfig)(updatedConfig);
105
+ versions.version = pkgVersion;
106
+ versions.installedAt = now;
107
+ }
108
+ writeVersions(versions, dryRun);
109
+ }
110
+ /**
111
+ * Installs ALL known GA plugins.
112
+ * Convenience wrapper around `install(getAllPluginIds(), options)`.
113
+ */
114
+ async function installAll(options = {}) {
115
+ return install((0, registry_js_1.getAllPluginIds)(), options);
116
+ }
117
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { PluginEntry } from './types.js';
2
+ /**
3
+ * Canonical list of all GA Migration plugins shipped in this package.
4
+ * The `path` field is relative to the `plugins/` directory bundled with the npm package.
5
+ */
6
+ export declare const PLUGINS: PluginEntry[];
7
+ /**
8
+ * Returns the absolute path to a bundled plugin folder inside the installed npm package.
9
+ *
10
+ * At runtime `__dirname` points to `<package-root>/dist/` (compiled output).
11
+ * The bundled plugins live at `<package-root>/plugins/<pluginId>/`.
12
+ *
13
+ * @throws {Error} if pluginId is not in the registry
14
+ */
15
+ export declare function getBundledPluginPath(pluginId: string): string;
16
+ /**
17
+ * Returns true if `id` is a known plugin ID.
18
+ */
19
+ export declare function validatePluginId(id: string): boolean;
20
+ /**
21
+ * Returns the list of all known plugin IDs.
22
+ */
23
+ export declare function getAllPluginIds(): string[];
24
+ /**
25
+ * Returns a PluginEntry by ID, or undefined if not found.
26
+ */
27
+ export declare function getPluginById(id: string): PluginEntry | undefined;
28
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,WAAW,EAyChC,CAAC;AAOF;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEjE"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PLUGINS = void 0;
7
+ exports.getBundledPluginPath = getBundledPluginPath;
8
+ exports.validatePluginId = validatePluginId;
9
+ exports.getAllPluginIds = getAllPluginIds;
10
+ exports.getPluginById = getPluginById;
11
+ const path_1 = __importDefault(require("path"));
12
+ /**
13
+ * Canonical list of all GA Migration plugins shipped in this package.
14
+ * The `path` field is relative to the `plugins/` directory bundled with the npm package.
15
+ */
16
+ exports.PLUGINS = [
17
+ {
18
+ id: 'go-standards',
19
+ name: 'Go Standards',
20
+ description: 'Enforces Garuda Airlines Go coding standards: naming conventions, error handling, ' +
21
+ 'context propagation, and module structure for the Java→Go migration.',
22
+ path: 'go-standards',
23
+ },
24
+ {
25
+ id: 'go-scaffolder',
26
+ name: 'Go Scaffolder',
27
+ description: 'Scaffolds new Go packages, services, and handlers following the go-ga-lib ' +
28
+ 'project layout conventions (github.com/zokypesch/go-ga-lib).',
29
+ path: 'go-scaffolder',
30
+ },
31
+ {
32
+ id: 'java2go-porter',
33
+ name: 'Java→Go Porter',
34
+ description: 'Translates Java source files to idiomatic Go, eliminating Java anti-patterns ' +
35
+ '(getters/setters, Exception hierarchies, Abstract* types) during migration.',
36
+ path: 'java2go-porter',
37
+ },
38
+ {
39
+ id: 'migration-safety',
40
+ name: 'Migration Safety',
41
+ description: 'Pre-merge safety checks for the Java→Go migration: API compatibility, ' +
42
+ 'data model drift, SQL schema consistency, and rollback readiness assessment.',
43
+ path: 'migration-safety',
44
+ },
45
+ {
46
+ id: 'go-reviewer',
47
+ name: 'Go Reviewer',
48
+ description: 'Incremental Go code review (new findings only, diff-based) + auto-fix in isolated ' +
49
+ 'git worktree. Integrates external linters (golangci-lint, gopls, semgrep) via MCP shim.',
50
+ path: 'go-reviewer',
51
+ },
52
+ ];
53
+ /**
54
+ * Returns the set of known plugin IDs for fast membership checks.
55
+ */
56
+ const KNOWN_IDS = new Set(exports.PLUGINS.map((p) => p.id));
57
+ /**
58
+ * Returns the absolute path to a bundled plugin folder inside the installed npm package.
59
+ *
60
+ * At runtime `__dirname` points to `<package-root>/dist/` (compiled output).
61
+ * The bundled plugins live at `<package-root>/plugins/<pluginId>/`.
62
+ *
63
+ * @throws {Error} if pluginId is not in the registry
64
+ */
65
+ function getBundledPluginPath(pluginId) {
66
+ if (!validatePluginId(pluginId)) {
67
+ throw new Error(`Unknown plugin ID: "${pluginId}". Run "ga-plugins-cli list" to see available plugins.`);
68
+ }
69
+ const entry = exports.PLUGINS.find((p) => p.id === pluginId);
70
+ // __dirname = .../dist → go up one level to package root, then into plugins/
71
+ return path_1.default.resolve(__dirname, '..', 'plugins', entry.path);
72
+ }
73
+ /**
74
+ * Returns true if `id` is a known plugin ID.
75
+ */
76
+ function validatePluginId(id) {
77
+ return KNOWN_IDS.has(id);
78
+ }
79
+ /**
80
+ * Returns the list of all known plugin IDs.
81
+ */
82
+ function getAllPluginIds() {
83
+ return exports.PLUGINS.map((p) => p.id);
84
+ }
85
+ /**
86
+ * Returns a PluginEntry by ID, or undefined if not found.
87
+ */
88
+ function getPluginById(id) {
89
+ return exports.PLUGINS.find((p) => p.id === id);
90
+ }
91
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":";;;;;;AA+DA,oDAOC;AAKD,4CAEC;AAKD,0CAEC;AAKD,sCAEC;AA3FD,gDAAwB;AAGxB;;;GAGG;AACU,QAAA,OAAO,GAAkB;IACpC;QACE,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,cAAc;QACpB,WAAW,EACT,oFAAoF;YACpF,sEAAsE;QACxE,IAAI,EAAE,cAAc;KACrB;IACD;QACE,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,4EAA4E;YAC5E,8DAA8D;QAChE,IAAI,EAAE,eAAe;KACtB;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,+EAA+E;YAC/E,6EAA6E;QAC/E,IAAI,EAAE,gBAAgB;KACvB;IACD;QACE,EAAE,EAAE,kBAAkB;QACtB,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,wEAAwE;YACxE,8EAA8E;QAChF,IAAI,EAAE,kBAAkB;KACzB;IACD;QACE,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,oFAAoF;YACpF,yFAAyF;QAC3F,IAAI,EAAE,aAAa;KACpB;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,eAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEpD;;;;;;;GAOG;AACH,SAAgB,oBAAoB,CAAC,QAAgB;IACnD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,wDAAwD,CAAC,CAAC;IAC3G,CAAC;IACD,MAAM,KAAK,GAAG,eAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAE,CAAC;IACtD,+EAA+E;IAC/E,OAAO,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,EAAU;IACzC,OAAO,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe;IAC7B,OAAO,eAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,EAAU;IACtC,OAAO,eAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface PluginManifest {
2
+ name: string;
3
+ version: string;
4
+ description: string;
5
+ plugins: PluginEntry[];
6
+ }
7
+ export interface PluginEntry {
8
+ id: string;
9
+ name: string;
10
+ description: string;
11
+ path: string;
12
+ }
13
+ export interface InstalledVersions {
14
+ version: string;
15
+ installedAt: string;
16
+ plugins: Record<string, {
17
+ version: string;
18
+ installedAt: string;
19
+ }>;
20
+ }
21
+ export interface ClaudeConfig {
22
+ plugins?: PluginConfig[];
23
+ [key: string]: unknown;
24
+ }
25
+ export interface PluginConfig {
26
+ id: string;
27
+ path: string;
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ export interface UninstallOptions {
2
+ /** When true, prints what would happen without actually doing it. */
3
+ dryRun?: boolean;
4
+ }
5
+ export interface UninstallAllOptions extends UninstallOptions {
6
+ /** When true, skips the interactive confirmation prompt. */
7
+ skipConfirm?: boolean;
8
+ }
9
+ /**
10
+ * Uninstalls the given plugin IDs from ~/.claude/plugins/ and removes them from ~/.claude.json.
11
+ *
12
+ * For each plugin:
13
+ * - If the plugin folder exists: removes it
14
+ * - If the folder is missing but an entry exists in ~/.claude.json: cleans up the stale entry
15
+ * and prints a warning
16
+ * - Removes the entry from .ga-versions.json
17
+ *
18
+ * In dry-run mode, no files are removed.
19
+ */
20
+ export declare function uninstall(pluginIds: string[], options?: UninstallOptions): Promise<void>;
21
+ /**
22
+ * Uninstalls ALL installed GA plugins.
23
+ *
24
+ * Discovers installed plugins by:
25
+ * 1. Checking which known plugin IDs have a folder in ~/.claude/plugins/
26
+ * 2. Checking which known plugin IDs have an entry in ~/.claude.json
27
+ * The union of both sets is uninstalled.
28
+ *
29
+ * When `skipConfirm` is false (default), prompts for interactive confirmation.
30
+ */
31
+ export declare function uninstallAll(options?: UninstallAllOptions): Promise<void>;
32
+ //# sourceMappingURL=uninstaller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstaller.d.ts","sourceRoot":"","sources":["../src/uninstaller.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAoED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CA2Df;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDnF"}
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.uninstall = uninstall;
7
+ exports.uninstallAll = uninstallAll;
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const readline_1 = __importDefault(require("readline"));
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const config_patcher_js_1 = require("./config-patcher.js");
13
+ const registry_js_1 = require("./registry.js");
14
+ // ─── Versions file helpers ────────────────────────────────────────────────────
15
+ function readVersions() {
16
+ const versionsPath = (0, config_patcher_js_1.getVersionsFilePath)();
17
+ if (!fs_extra_1.default.existsSync(versionsPath)) {
18
+ return {
19
+ version: require('../package.json').version,
20
+ installedAt: new Date().toISOString(),
21
+ plugins: {},
22
+ };
23
+ }
24
+ try {
25
+ return fs_extra_1.default.readJSONSync(versionsPath);
26
+ }
27
+ catch {
28
+ return {
29
+ version: require('../package.json').version,
30
+ installedAt: new Date().toISOString(),
31
+ plugins: {},
32
+ };
33
+ }
34
+ }
35
+ function writeVersions(versions, dryRun) {
36
+ const versionsPath = (0, config_patcher_js_1.getVersionsFilePath)();
37
+ if (dryRun) {
38
+ console.log(chalk_1.default.dim(` [DRY RUN] Would write versions to ${versionsPath}`));
39
+ return;
40
+ }
41
+ fs_extra_1.default.outputJSONSync(versionsPath, versions, { spaces: 2 });
42
+ }
43
+ // ─── Prefix helper ────────────────────────────────────────────────────────────
44
+ function prefix(dryRun) {
45
+ return dryRun ? chalk_1.default.yellow('[DRY RUN] ') : '';
46
+ }
47
+ // ─── Confirmation prompt ──────────────────────────────────────────────────────
48
+ /**
49
+ * Prompts the user for confirmation on stdin.
50
+ * Returns true if user typed "yes" (case-insensitive).
51
+ */
52
+ function promptConfirm(message) {
53
+ return new Promise((resolve) => {
54
+ const rl = readline_1.default.createInterface({
55
+ input: process.stdin,
56
+ output: process.stdout,
57
+ terminal: false,
58
+ });
59
+ process.stdout.write(message);
60
+ rl.once('line', (answer) => {
61
+ rl.close();
62
+ resolve(answer.trim().toLowerCase() === 'yes');
63
+ });
64
+ rl.once('close', () => {
65
+ resolve(false);
66
+ });
67
+ });
68
+ }
69
+ // ─── Core uninstall logic ─────────────────────────────────────────────────────
70
+ /**
71
+ * Uninstalls the given plugin IDs from ~/.claude/plugins/ and removes them from ~/.claude.json.
72
+ *
73
+ * For each plugin:
74
+ * - If the plugin folder exists: removes it
75
+ * - If the folder is missing but an entry exists in ~/.claude.json: cleans up the stale entry
76
+ * and prints a warning
77
+ * - Removes the entry from .ga-versions.json
78
+ *
79
+ * In dry-run mode, no files are removed.
80
+ */
81
+ async function uninstall(pluginIds, options = {}) {
82
+ const dryRun = options.dryRun ?? false;
83
+ const pluginsDir = (0, config_patcher_js_1.getPluginsDir)();
84
+ const config = (0, config_patcher_js_1.readClaudeConfig)();
85
+ const versions = readVersions();
86
+ let updatedConfig = config;
87
+ for (const pluginId of pluginIds) {
88
+ const destPath = path_1.default.join(pluginsDir, pluginId);
89
+ const folderExists = fs_extra_1.default.existsSync(destPath);
90
+ if (!folderExists) {
91
+ // Check if a stale config entry exists
92
+ const hasEntry = Array.isArray(updatedConfig.plugins) &&
93
+ updatedConfig.plugins.some((p) => p.id === pluginId);
94
+ if (hasEntry) {
95
+ console.warn(chalk_1.default.yellow(` Warning: plugin folder not found for "${pluginId}" at ${destPath} ` +
96
+ `but a config entry exists — cleaning up stale entry.`));
97
+ }
98
+ else {
99
+ console.log(chalk_1.default.dim(` ${pluginId}: not installed (nothing to remove)`));
100
+ continue;
101
+ }
102
+ }
103
+ else {
104
+ // ── Remove plugin folder ──────────────────────────────────────────────
105
+ console.log(`${prefix(dryRun)}${chalk_1.default.red('remove')} ${destPath}`);
106
+ if (!dryRun) {
107
+ fs_extra_1.default.removeSync(destPath);
108
+ }
109
+ }
110
+ // ── Remove from ~/.claude.json ────────────────────────────────────────
111
+ console.log(`${prefix(dryRun)}${chalk_1.default.red('deregister')} ${pluginId} from ${chalk_1.default.dim('~/.claude.json')}`);
112
+ if (!dryRun) {
113
+ updatedConfig = (0, config_patcher_js_1.removePluginEntry)(updatedConfig, pluginId);
114
+ }
115
+ // ── Remove from versions record ───────────────────────────────────────
116
+ delete versions.plugins[pluginId];
117
+ console.log(chalk_1.default.green(` ✓ ${pluginId} uninstalled`));
118
+ }
119
+ // Write updated config and versions once, after all plugins
120
+ if (!dryRun) {
121
+ (0, config_patcher_js_1.writeClaudeConfig)(updatedConfig);
122
+ }
123
+ writeVersions(versions, dryRun);
124
+ }
125
+ /**
126
+ * Uninstalls ALL installed GA plugins.
127
+ *
128
+ * Discovers installed plugins by:
129
+ * 1. Checking which known plugin IDs have a folder in ~/.claude/plugins/
130
+ * 2. Checking which known plugin IDs have an entry in ~/.claude.json
131
+ * The union of both sets is uninstalled.
132
+ *
133
+ * When `skipConfirm` is false (default), prompts for interactive confirmation.
134
+ */
135
+ async function uninstallAll(options = {}) {
136
+ const dryRun = options.dryRun ?? false;
137
+ const skipConfirm = options.skipConfirm ?? false;
138
+ // Discover what is actually installed
139
+ const pluginsDir = (0, config_patcher_js_1.getPluginsDir)();
140
+ const config = (0, config_patcher_js_1.readClaudeConfig)();
141
+ const allKnownIds = (0, registry_js_1.getAllPluginIds)();
142
+ const installedIds = new Set();
143
+ // Check filesystem
144
+ for (const id of allKnownIds) {
145
+ if (fs_extra_1.default.existsSync(path_1.default.join(pluginsDir, id))) {
146
+ installedIds.add(id);
147
+ }
148
+ }
149
+ // Check config entries (catches stale entries without folders)
150
+ if (Array.isArray(config.plugins)) {
151
+ for (const entry of config.plugins) {
152
+ if ((0, registry_js_1.validatePluginId)(entry.id)) {
153
+ installedIds.add(entry.id);
154
+ }
155
+ }
156
+ }
157
+ if (installedIds.size === 0) {
158
+ console.log(chalk_1.default.dim('No GA plugins are currently installed.'));
159
+ return;
160
+ }
161
+ const idList = [...installedIds];
162
+ if (!skipConfirm && !dryRun) {
163
+ console.log(chalk_1.default.yellow(`\nAbout to remove ALL GA plugins (${idList.length}):`));
164
+ for (const id of idList) {
165
+ console.log(chalk_1.default.dim(` - ${id}`));
166
+ }
167
+ const confirmed = await promptConfirm(chalk_1.default.yellow("\nType 'yes' to confirm: "));
168
+ if (!confirmed) {
169
+ console.log(chalk_1.default.dim('Aborted. No plugins were removed.'));
170
+ return;
171
+ }
172
+ }
173
+ await uninstall(idList, { dryRun });
174
+ }
175
+ //# sourceMappingURL=uninstaller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstaller.js","sourceRoot":"","sources":["../src/uninstaller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Compares the versions in .ga-versions.json against the current npm package version.
3
+ *
4
+ * Returns:
5
+ * - `current`: map of pluginId → installed version string (or "not installed")
6
+ * - `available`: the version shipped in the current npm package
7
+ *
8
+ * A plugin needs an update when its installed version differs from `available`.
9
+ */
10
+ export declare function checkUpdates(): Promise<{
11
+ current: Record<string, string>;
12
+ available: string;
13
+ }>;
14
+ export interface UpdateOptions {
15
+ /** When true, prints what would happen without actually doing it. */
16
+ dryRun?: boolean;
17
+ }
18
+ /**
19
+ * Updates (re-installs) the given plugin IDs with the versions bundled in the current
20
+ * npm package. Overwrites existing plugin folders and updates .ga-versions.json.
21
+ *
22
+ * If `pluginIds` is empty, updates all currently installed plugins.
23
+ *
24
+ * Skips plugins that are not currently installed (warns instead of error).
25
+ * Skips unknown plugin IDs with a warning.
26
+ */
27
+ export declare function update(pluginIds: string[], options?: UpdateOptions): Promise<void>;
28
+ //# sourceMappingURL=updater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"AA+BA;;;;;;;;GAQG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAYD;AAID,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAID;;;;;;;;GAQG;AACH,wBAAsB,MAAM,CAC1B,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAwDf"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.checkUpdates = checkUpdates;
7
+ exports.update = update;
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const config_patcher_js_1 = require("./config-patcher.js");
11
+ const installer_js_1 = require("./installer.js");
12
+ const registry_js_1 = require("./registry.js");
13
+ // ─── Versions file helpers ────────────────────────────────────────────────────
14
+ function readVersions() {
15
+ const versionsPath = (0, config_patcher_js_1.getVersionsFilePath)();
16
+ if (!fs_extra_1.default.existsSync(versionsPath)) {
17
+ return {
18
+ version: '0.0.0',
19
+ installedAt: new Date().toISOString(),
20
+ plugins: {},
21
+ };
22
+ }
23
+ try {
24
+ return fs_extra_1.default.readJSONSync(versionsPath);
25
+ }
26
+ catch {
27
+ return {
28
+ version: '0.0.0',
29
+ installedAt: new Date().toISOString(),
30
+ plugins: {},
31
+ };
32
+ }
33
+ }
34
+ // ─── Update check ─────────────────────────────────────────────────────────────
35
+ /**
36
+ * Compares the versions in .ga-versions.json against the current npm package version.
37
+ *
38
+ * Returns:
39
+ * - `current`: map of pluginId → installed version string (or "not installed")
40
+ * - `available`: the version shipped in the current npm package
41
+ *
42
+ * A plugin needs an update when its installed version differs from `available`.
43
+ */
44
+ async function checkUpdates() {
45
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
46
+ const pkgVersion = require('../package.json').version ?? '0.1.0';
47
+ const versions = readVersions();
48
+ const allIds = (0, registry_js_1.getAllPluginIds)();
49
+ const current = {};
50
+ for (const id of allIds) {
51
+ current[id] = versions.plugins[id]?.version ?? 'not installed';
52
+ }
53
+ return { current, available: pkgVersion };
54
+ }
55
+ // ─── Core update logic ────────────────────────────────────────────────────────
56
+ /**
57
+ * Updates (re-installs) the given plugin IDs with the versions bundled in the current
58
+ * npm package. Overwrites existing plugin folders and updates .ga-versions.json.
59
+ *
60
+ * If `pluginIds` is empty, updates all currently installed plugins.
61
+ *
62
+ * Skips plugins that are not currently installed (warns instead of error).
63
+ * Skips unknown plugin IDs with a warning.
64
+ */
65
+ async function update(pluginIds, options = {}) {
66
+ const dryRun = options.dryRun ?? false;
67
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
68
+ const pkgVersion = require('../package.json').version ?? '0.1.0';
69
+ const versions = readVersions();
70
+ // Determine which IDs to actually update
71
+ let targetIds;
72
+ if (pluginIds.length === 0) {
73
+ // Update all that are recorded as installed
74
+ targetIds = Object.keys(versions.plugins).filter((id) => (0, registry_js_1.validatePluginId)(id));
75
+ if (targetIds.length === 0) {
76
+ console.log(chalk_1.default.dim('No GA plugins are currently installed. Nothing to update.'));
77
+ return;
78
+ }
79
+ }
80
+ else {
81
+ // Validate and filter supplied IDs
82
+ targetIds = [];
83
+ for (const id of pluginIds) {
84
+ if (!(0, registry_js_1.validatePluginId)(id)) {
85
+ console.warn(chalk_1.default.yellow(` Warning: unknown plugin "${id}" — skipping.`));
86
+ continue;
87
+ }
88
+ if (!versions.plugins[id]) {
89
+ console.warn(chalk_1.default.yellow(` Warning: plugin "${id}" is not installed — run "ga-plugins-cli install ${id}" first.`));
90
+ continue;
91
+ }
92
+ targetIds.push(id);
93
+ }
94
+ }
95
+ if (targetIds.length === 0) {
96
+ console.log(chalk_1.default.dim('Nothing to update.'));
97
+ return;
98
+ }
99
+ // Show what will change
100
+ console.log(chalk_1.default.bold(`\nUpdating ${targetIds.length} plugin(s) to v${pkgVersion}:\n`));
101
+ for (const id of targetIds) {
102
+ const current = versions.plugins[id]?.version ?? 'unknown';
103
+ const arrow = current === pkgVersion
104
+ ? chalk_1.default.dim(` ${id}: v${current} → v${pkgVersion} (already up to date)`)
105
+ : ` ${id}: ${chalk_1.default.dim(`v${current}`)} → ${chalk_1.default.green(`v${pkgVersion}`)}`;
106
+ console.log(arrow);
107
+ }
108
+ console.log('');
109
+ // Re-install (install handles the copy + config patch + versions update)
110
+ await (0, installer_js_1.install)(targetIds, { dryRun });
111
+ console.log(chalk_1.default.green(`\nUpdate complete.`));
112
+ }
113
+ //# sourceMappingURL=updater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updater.js","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "ga-plugins-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI to install GA Migration Claude Code plugins globally at user level (~/.claude/plugins/)",
5
+ "bin": {
6
+ "ga-plugins-cli": "./dist/index.js"
7
+ },
8
+ "main": "./dist/index.js",
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "ts-node src/index.ts",
12
+ "prepublishOnly": "npm run build",
13
+ "lint": "eslint src/**/*.ts"
14
+ },
15
+ "dependencies": {
16
+ "commander": "^12.1.0",
17
+ "chalk": "^5.3.0",
18
+ "ora": "^8.1.1",
19
+ "fs-extra": "^11.2.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^22.0.0",
23
+ "@types/fs-extra": "^11.0.4",
24
+ "typescript": "^5.6.0"
25
+ },
26
+ "files": [
27
+ "dist/",
28
+ "plugins/"
29
+ ],
30
+ "engines": {
31
+ "node": ">=18"
32
+ },
33
+ "license": "MIT"
34
+ }