@ironbee-ai/cli 0.7.3 → 0.8.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 (59) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +62 -3
  3. package/dist/clients/claude/index.d.ts +10 -0
  4. package/dist/clients/claude/index.d.ts.map +1 -1
  5. package/dist/clients/claude/index.js +102 -22
  6. package/dist/clients/claude/index.js.map +1 -1
  7. package/dist/clients/cursor/index.d.ts +8 -0
  8. package/dist/clients/cursor/index.d.ts.map +1 -1
  9. package/dist/clients/cursor/index.js +67 -9
  10. package/dist/clients/cursor/index.js.map +1 -1
  11. package/dist/clients/registry.d.ts +35 -6
  12. package/dist/clients/registry.d.ts.map +1 -1
  13. package/dist/clients/registry.js +73 -6
  14. package/dist/clients/registry.js.map +1 -1
  15. package/dist/commands/config.d.ts +79 -0
  16. package/dist/commands/config.d.ts.map +1 -0
  17. package/dist/commands/config.js +558 -0
  18. package/dist/commands/config.js.map +1 -0
  19. package/dist/commands/install.d.ts +14 -0
  20. package/dist/commands/install.d.ts.map +1 -1
  21. package/dist/commands/install.js +122 -16
  22. package/dist/commands/install.js.map +1 -1
  23. package/dist/commands/register.d.ts +24 -0
  24. package/dist/commands/register.d.ts.map +1 -0
  25. package/dist/commands/register.js +67 -0
  26. package/dist/commands/register.js.map +1 -0
  27. package/dist/commands/uninstall.d.ts +18 -0
  28. package/dist/commands/uninstall.d.ts.map +1 -1
  29. package/dist/commands/uninstall.js +160 -16
  30. package/dist/commands/uninstall.js.map +1 -1
  31. package/dist/commands/unregister.d.ts +23 -0
  32. package/dist/commands/unregister.d.ts.map +1 -0
  33. package/dist/commands/unregister.js +67 -0
  34. package/dist/commands/unregister.js.map +1 -0
  35. package/dist/import/claude/discovery.js +4 -4
  36. package/dist/import/claude/discovery.js.map +1 -1
  37. package/dist/import/claude/encoding.d.ts.map +1 -1
  38. package/dist/import/claude/encoding.js +102 -21
  39. package/dist/import/claude/encoding.js.map +1 -1
  40. package/dist/index.js +10 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/lib/config.d.ts.map +1 -1
  43. package/dist/lib/config.js +6 -1
  44. package/dist/lib/config.js.map +1 -1
  45. package/dist/lib/projects-registry.d.ts +102 -0
  46. package/dist/lib/projects-registry.d.ts.map +1 -0
  47. package/dist/lib/projects-registry.js +282 -0
  48. package/dist/lib/projects-registry.js.map +1 -0
  49. package/dist/lib/prompt.d.ts +40 -0
  50. package/dist/lib/prompt.d.ts.map +1 -0
  51. package/dist/lib/prompt.js +101 -0
  52. package/dist/lib/prompt.js.map +1 -0
  53. package/dist/lib/telemetry.d.ts +8 -0
  54. package/dist/lib/telemetry.d.ts.map +1 -1
  55. package/dist/lib/telemetry.js +44 -0
  56. package/dist/lib/telemetry.js.map +1 -1
  57. package/package.json +7 -5
  58. package/scripts/run-postinstall.js +35 -0
  59. package/scripts/run-preuninstall.js +19 -0
@@ -1,50 +1,156 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.installCommand = void 0;
4
+ exports.runInstallAll = runInstallAll;
4
5
  const commander_1 = require("commander");
5
6
  const fs_1 = require("fs");
6
7
  const path_1 = require("path");
7
8
  const registry_1 = require("../clients/registry");
8
9
  const claude_1 = require("../clients/claude");
9
10
  const output_1 = require("../lib/output");
11
+ const projects_registry_1 = require("../lib/projects-registry");
12
+ const prompt_1 = require("../lib/prompt");
10
13
  const telemetry_1 = require("../lib/telemetry");
14
+ /**
15
+ * Resolve the client list for a single registered project during
16
+ * `install --all`.
17
+ *
18
+ * - No `--client` flag → use **current detection** (`detectClients`).
19
+ * The user's disk state is the source of truth: if `.cursor/` was
20
+ * deleted after registering, we should NOT recreate it. The
21
+ * inventory's historical `entry.clients` field is intentionally
22
+ * ignored on this path.
23
+ * - `--client <name>` / `--client all` → override detection per-project
24
+ * and force-install the named client(s) everywhere. Used to roll out
25
+ * a client uniformly across every registered project.
26
+ */
27
+ function clientsForBatchEntry(entry, clientOpt) {
28
+ if (clientOpt !== undefined) {
29
+ return (0, registry_1.resolveTargetClients)(entry.path, clientOpt);
30
+ }
31
+ return (0, registry_1.detectClients)(entry.path);
32
+ }
33
+ /**
34
+ * `install --all` driver — iterate every active registered project and
35
+ * run install on each, using either the project's recorded clients or an
36
+ * explicit `--client` override.
37
+ *
38
+ * Per-project failures are logged and the loop continues; the function
39
+ * returns the failure count so the action handler can pick the exit code.
40
+ */
41
+ async function runInstallAll(opts) {
42
+ const projects = (0, registry_1.listActiveProjects)();
43
+ if (projects.length === 0) {
44
+ output_1.log.info("No registered projects to install. Run `ironbee install` somewhere first.");
45
+ return { failures: 0, total: 0 };
46
+ }
47
+ output_1.log.info(`Installing across ${output_1.pc.bold(String(projects.length))} registered project(s)…`);
48
+ output_1.log.blank();
49
+ let failures = 0;
50
+ const installedClientNames = [];
51
+ for (const entry of projects) {
52
+ try {
53
+ const clients = clientsForBatchEntry(entry, opts.client);
54
+ if (clients.length === 0) {
55
+ output_1.log.warn(`Skipping ${entry.path} — no resolvable clients`);
56
+ continue;
57
+ }
58
+ const names = clients.map((c) => c.name);
59
+ output_1.log.label("project", output_1.pc.dim(entry.path));
60
+ output_1.log.step(`installing ${output_1.pc.bold(names.join(", "))}`);
61
+ (0, claude_1.prepareIronBeeDir)(entry.path);
62
+ for (const client of clients) {
63
+ client.install(entry.path);
64
+ }
65
+ (0, projects_registry_1.upsertProject)(entry.path, names);
66
+ installedClientNames.push(...names);
67
+ }
68
+ catch (e) {
69
+ failures++;
70
+ output_1.log.error(` ${entry.path}: ${e instanceof Error ? e.message : String(e)}`);
71
+ }
72
+ }
73
+ output_1.log.blank();
74
+ if (failures === 0) {
75
+ output_1.log.success(`Installed across ${projects.length} project(s). ${output_1.pc.dim("Restart your AI coding client(s) to apply.")}`);
76
+ }
77
+ else {
78
+ output_1.log.warn(`Completed with ${failures} failure(s) — see above.`);
79
+ }
80
+ // Best-effort telemetry — dedupe client names so a 10-project batch
81
+ // doesn't ship 10 cli_installed events for the same client.
82
+ const uniqueClients = Array.from(new Set(installedClientNames));
83
+ if (uniqueClients.length > 0) {
84
+ await (0, telemetry_1.trackInstall)(uniqueClients);
85
+ }
86
+ return { failures, total: projects.length };
87
+ }
11
88
  exports.installCommand = new commander_1.Command("install")
12
- .description("Install IronBee hooks and guidance files into a project")
89
+ .description("Install IronBee hooks and guidance files into a project. Use --all to install across every registered project (e.g. after a global config change).")
13
90
  .argument("[project-dir]", "target project directory", ".")
14
91
  .option("--client <name>", `client to install for (${(0, registry_1.clientNames)()}), or "all"`)
92
+ .option("--all", "Install across every project in the user-home inventory (~/.ironbee/projects.json) instead of just one. The [project-dir] argument is ignored when --all is set.")
15
93
  .action(async (dir, options) => {
94
+ if (options.all === true) {
95
+ const result = await runInstallAll({ client: options.client });
96
+ if (result.failures > 0) {
97
+ process.exit(1);
98
+ }
99
+ return;
100
+ }
16
101
  const projectDir = (0, path_1.resolve)(dir);
17
102
  if (!(0, fs_1.existsSync)(projectDir)) {
18
103
  output_1.log.error(`Directory not found: ${projectDir}`);
19
104
  process.exit(1);
20
105
  }
21
106
  let clients;
22
- try {
23
- clients = (0, registry_1.resolveTargetClients)(projectDir, options.client);
24
- }
25
- catch (e) {
26
- output_1.log.error(e instanceof Error ? e.message : String(e));
27
- process.exit(1);
107
+ if (options.client !== undefined) {
108
+ // Explicit --client (including "all") wins outright.
109
+ try {
110
+ clients = (0, registry_1.resolveTargetClients)(projectDir, options.client);
111
+ }
112
+ catch (e) {
113
+ output_1.log.error(e instanceof Error ? e.message : String(e));
114
+ process.exit(1);
115
+ }
28
116
  }
29
- // User-facing log mirrors the historical install.ts output:
30
- // - explicit --client → no extra noise
31
- // - autodetect with hits → list detected clients
32
- // - autodetect with no hits → warn we're falling back to the first
33
- if (options.client === undefined) {
117
+ else {
34
118
  const detected = (0, registry_1.detectClients)(projectDir);
35
- if (detected.length === 0) {
36
- output_1.log.warn(`No client detected. Defaulting to: ${registry_1.REGISTERED_CLIENTS[0].name}`);
37
- }
38
- else {
119
+ if (detected.length > 0) {
120
+ clients = detected;
39
121
  const names = detected.map((c) => c.name).join(", ");
40
122
  output_1.log.info(`Detected client(s): ${output_1.pc.bold(names)}`);
41
123
  }
124
+ else if ((0, prompt_1.isInteractive)()) {
125
+ // Fresh project with no client artifacts yet — let the user
126
+ // pick which client(s) they actually use. Numeric input or
127
+ // exact name match; default is the first registered client.
128
+ const choices = [
129
+ ...registry_1.REGISTERED_CLIENTS.map((c) => c.name),
130
+ "all",
131
+ ];
132
+ output_1.log.warn(`No client detected in ${output_1.pc.dim(projectDir)}.`);
133
+ const idx = await (0, prompt_1.promptChoice)("Which client(s) to install for?", choices, 0);
134
+ const choice = choices[idx];
135
+ clients = (0, registry_1.resolveTargetClients)(projectDir, choice);
136
+ }
137
+ else {
138
+ // Non-TTY (CI / piped) — keep the historical fall-back so
139
+ // automated `ironbee install` invocations don't hang or fail.
140
+ output_1.log.warn(`No client detected. Defaulting to: ${registry_1.REGISTERED_CLIENTS[0].name}`);
141
+ clients = [registry_1.REGISTERED_CLIENTS[0]];
142
+ }
42
143
  }
43
144
  output_1.log.blank();
44
145
  (0, claude_1.prepareIronBeeDir)(projectDir);
45
146
  for (const client of clients) {
46
147
  client.install(projectDir);
47
148
  }
149
+ // Register the project in the user-home inventory so global config
150
+ // changes (`ironbee config set --global …`) and `ironbee install --all`
151
+ // know which projects to update. Failure inside upsertProject is
152
+ // soft — see projects-registry.ts.
153
+ (0, projects_registry_1.upsertProject)(projectDir, clients.map((c) => c.name));
48
154
  output_1.log.blank();
49
155
  output_1.log.label("project", output_1.pc.dim(projectDir));
50
156
  output_1.log.blank();
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,2BAAgC;AAChC,+BAA+B;AAE/B,kDAA2G;AAC3G,8CAAsD;AACtD,0CAAwC;AACxC,gDAAgD;AAEnC,QAAA,cAAc,GAAY,IAAI,mBAAO,CAAC,SAAS,CAAC;KACxD,WAAW,CAAC,yDAAyD,CAAC;KACtE,QAAQ,CAAC,eAAe,EAAE,0BAA0B,EAAE,GAAG,CAAC;KAC1D,MAAM,CAAC,iBAAiB,EAAE,0BAA0B,IAAA,sBAAW,GAAE,aAAa,CAAC;KAC/E,MAAM,CAAC,KAAK,EAAE,GAAW,EAAE,OAA4B,EAAiB,EAAE;IACvE,MAAM,UAAU,GAAW,IAAA,cAAO,EAAC,GAAG,CAAC,CAAC;IAExC,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;QAC1B,YAAG,CAAC,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,OAAkB,CAAC;IACvB,IAAI,CAAC;QACD,OAAO,GAAG,IAAA,+BAAoB,EAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,YAAG,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,4DAA4D;IAC5D,uCAAuC;IACvC,iDAAiD;IACjD,mEAAmE;IACnE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAc,IAAA,wBAAa,EAAC,UAAU,CAAC,CAAC;QACtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,YAAG,CAAC,IAAI,CAAC,sCAAsC,6BAAkB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjF,CAAC;aAAM,CAAC;YACJ,MAAM,KAAK,GAAW,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9E,YAAG,CAAC,IAAI,CAAC,uBAAuB,WAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtD,CAAC;IACL,CAAC;IAED,YAAG,CAAC,KAAK,EAAE,CAAC;IACZ,IAAA,0BAAiB,EAAC,UAAU,CAAC,CAAC;IAE9B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IAED,YAAG,CAAC,KAAK,EAAE,CAAC;IACZ,YAAG,CAAC,KAAK,CAAC,SAAS,EAAE,WAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IACzC,YAAG,CAAC,KAAK,EAAE,CAAC;IACZ,YAAG,CAAC,OAAO,CAAC,sBAAsB,WAAE,CAAC,GAAG,CAAC,sDAAsD,CAAC,EAAE,CAAC,CAAC;IACpG,MAAM,IAAA,wBAAY,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACpE,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `ironbee register` — add the current project to the user-home inventory
3
+ * at `~/.ironbee/projects.json`. Pure inventory operation: no artifact
4
+ * writes, no `.ironbee/` mkdir, no client install. Just bookkeeping.
5
+ *
6
+ * Use cases:
7
+ * - Project was set up (with `.claude/` / `.cursor/` configured manually,
8
+ * or installed before the inventory feature existed) and the user wants
9
+ * it tracked so cross-project notices (`ironbee config set --global`)
10
+ * surface it.
11
+ * - Recovering a registry that got corrupted or wiped.
12
+ *
13
+ * Note: `ironbee install` already auto-registers — this command is for the
14
+ * case where install isn't being re-run.
15
+ */
16
+ import { Command } from "commander";
17
+ interface RegisterOptions {
18
+ project?: string;
19
+ client?: string;
20
+ }
21
+ export declare function runRegister(options: RegisterOptions): Promise<void>;
22
+ export declare const registerCommand: Command;
23
+ export {};
24
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,UAAU,eAAe;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE;AAED,eAAO,MAAM,eAAe,EAAE,OAMxB,CAAC"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /**
3
+ * `ironbee register` — add the current project to the user-home inventory
4
+ * at `~/.ironbee/projects.json`. Pure inventory operation: no artifact
5
+ * writes, no `.ironbee/` mkdir, no client install. Just bookkeeping.
6
+ *
7
+ * Use cases:
8
+ * - Project was set up (with `.claude/` / `.cursor/` configured manually,
9
+ * or installed before the inventory feature existed) and the user wants
10
+ * it tracked so cross-project notices (`ironbee config set --global`)
11
+ * surface it.
12
+ * - Recovering a registry that got corrupted or wiped.
13
+ *
14
+ * Note: `ironbee install` already auto-registers — this command is for the
15
+ * case where install isn't being re-run.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.registerCommand = void 0;
19
+ exports.runRegister = runRegister;
20
+ const commander_1 = require("commander");
21
+ const fs_1 = require("fs");
22
+ const path_1 = require("path");
23
+ const registry_1 = require("../clients/registry");
24
+ const output_1 = require("../lib/output");
25
+ const projects_registry_1 = require("../lib/projects-registry");
26
+ const telemetry_1 = require("../lib/telemetry");
27
+ async function runRegister(options) {
28
+ const projectDir = (0, path_1.resolve)(options.project ?? ".");
29
+ if (!(0, fs_1.existsSync)(projectDir)) {
30
+ output_1.log.error(`Directory not found: ${projectDir}`);
31
+ process.exit(1);
32
+ }
33
+ let clients;
34
+ if (options.client === "all") {
35
+ clients = registry_1.REGISTERED_CLIENTS;
36
+ }
37
+ else if (options.client !== undefined) {
38
+ const found = (0, registry_1.findClient)(options.client);
39
+ if (found === undefined) {
40
+ output_1.log.error(`Unknown client: '${options.client}'. Available: ${(0, registry_1.clientNames)()}.`);
41
+ process.exit(1);
42
+ }
43
+ clients = [found];
44
+ }
45
+ else {
46
+ clients = (0, registry_1.detectClients)(projectDir);
47
+ if (clients.length === 0) {
48
+ // Unlike `install`, register does NOT fall back to the first
49
+ // registered client — that would mark the project as having a
50
+ // client it doesn't actually have. Force the user to pick.
51
+ output_1.log.error(`No client detected in ${projectDir}. Use --client <name> to register explicitly (${(0, registry_1.clientNames)()}).`);
52
+ process.exit(1);
53
+ }
54
+ }
55
+ const names = clients.map((c) => c.name);
56
+ (0, projects_registry_1.upsertProject)(projectDir, names);
57
+ output_1.log.success(`Registered ${output_1.pc.bold(names.join(", "))} for ${output_1.pc.dim(projectDir)}.`);
58
+ await (0, telemetry_1.trackRegister)(names);
59
+ }
60
+ exports.registerCommand = new commander_1.Command("register")
61
+ .description("Add this project to the user-home inventory (~/.ironbee/projects.json) without writing any client artifacts. `ironbee install` already auto-registers; use this to retrofit an already-configured project into the inventory.")
62
+ .option("-p, --project <dir>", "Project directory to register (default: cwd).")
63
+ .option("--client <name>", `Client to register (${(0, registry_1.clientNames)()}), or "all". Default: detected clients.`)
64
+ .action(async (options) => {
65
+ await runRegister(options);
66
+ });
67
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAgBH,kCAqCC;AAnDD,yCAAoC;AACpC,2BAAgC;AAChC,+BAA+B;AAE/B,kDAAiG;AACjG,0CAAwC;AACxC,gEAAyD;AACzD,gDAAiD;AAO1C,KAAK,UAAU,WAAW,CAAC,OAAwB;IACtD,MAAM,UAAU,GAAW,IAAA,cAAO,EAAC,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC;IAE3D,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;QAC1B,YAAG,CAAC,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,OAAkB,CAAC;IAEvB,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,GAAG,6BAAkB,CAAC;IACjC,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,KAAK,GAAwB,IAAA,qBAAU,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,YAAG,CAAC,KAAK,CAAC,oBAAoB,OAAO,CAAC,MAAM,iBAAiB,IAAA,sBAAW,GAAE,GAAG,CAAC,CAAC;YAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;SAAM,CAAC;QACJ,OAAO,GAAG,IAAA,wBAAa,EAAC,UAAU,CAAC,CAAC;QACpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,6DAA6D;YAC7D,8DAA8D;YAC9D,2DAA2D;YAC3D,YAAG,CAAC,KAAK,CACL,yBAAyB,UAAU,iDAAiD,IAAA,sBAAW,GAAE,IAAI,CACxG,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAa,OAAO,CAAC,GAAG,CAAC,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpE,IAAA,iCAAa,EAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAEjC,YAAG,CAAC,OAAO,CAAC,cAAc,WAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,WAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAClF,MAAM,IAAA,yBAAa,EAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAEY,QAAA,eAAe,GAAY,IAAI,mBAAO,CAAC,UAAU,CAAC;KAC1D,WAAW,CAAC,+NAA+N,CAAC;KAC5O,MAAM,CAAC,qBAAqB,EAAE,+CAA+C,CAAC;KAC9E,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,IAAA,sBAAW,GAAE,yCAAyC,CAAC;KACxG,MAAM,CAAC,KAAK,EAAE,OAAwB,EAAiB,EAAE;IACtD,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC"}
@@ -1,3 +1,21 @@
1
1
  import { Command } from "commander";
2
+ /**
3
+ * Programmatic entry for `ironbee uninstall --all`. Iterates the
4
+ * inventory, removes ironbee artifacts from every project, and prunes
5
+ * the registry. Stale entries (path no longer exists) are quietly
6
+ * dropped from the registry.
7
+ *
8
+ * Per-project: runs `uninstall()` on every REGISTERED_CLIENT (each call
9
+ * is idempotent, only deletes files that exist). This makes the batch
10
+ * insensitive to drift between `entry.clients` and disk state — if the
11
+ * user manually moved between Claude and Cursor, both get cleaned.
12
+ */
13
+ export declare function runUninstallAll(opts: {
14
+ client?: string;
15
+ yes?: boolean;
16
+ }): Promise<{
17
+ failures: number;
18
+ total: number;
19
+ }>;
2
20
  export declare const uninstallCommand: Command;
3
21
  //# sourceMappingURL=uninstall.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,gBAAgB,EAAE,OA6CzB,CAAC"}
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2DpC;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA2F5H;AAED,eAAO,MAAM,gBAAgB,EAAE,OA2DzB,CAAC"}
@@ -1,56 +1,200 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.uninstallCommand = void 0;
4
+ exports.runUninstallAll = runUninstallAll;
4
5
  const commander_1 = require("commander");
5
6
  const fs_1 = require("fs");
6
7
  const path_1 = require("path");
7
8
  const registry_1 = require("../clients/registry");
8
9
  const output_1 = require("../lib/output");
10
+ const prompt_1 = require("../lib/prompt");
11
+ const projects_registry_1 = require("../lib/projects-registry");
9
12
  const telemetry_1 = require("../lib/telemetry");
10
13
  function clientNames() {
11
14
  const names = registry_1.REGISTERED_CLIENTS.map((c) => c.name);
12
15
  return names.join(", ");
13
16
  }
17
+ const NOTICE_PATH_CAP = 10;
18
+ /**
19
+ * Uninstall a single project. Idempotent on a per-client basis (each
20
+ * client's `uninstall()` only removes files that exist), so callers can
21
+ * safely run all REGISTERED_CLIENTS in a batch context.
22
+ */
23
+ function uninstallOne(projectDir, clients) {
24
+ for (const client of clients) {
25
+ client.uninstall(projectDir);
26
+ }
27
+ const names = clients.map((c) => c.name);
28
+ (0, projects_registry_1.removeProject)(projectDir, names);
29
+ const ironbeeDir = (0, path_1.join)(projectDir, ".ironbee");
30
+ if ((0, fs_1.existsSync)(ironbeeDir)) {
31
+ (0, fs_1.rmSync)(ironbeeDir, { recursive: true, force: true });
32
+ }
33
+ return names;
34
+ }
35
+ /**
36
+ * Map a `--client` flag to the IClient list to uninstall: undefined or
37
+ * `"all"` → every registered client (each one's `uninstall()` is
38
+ * idempotent so no-ops on projects that don't have it); `<name>` → that
39
+ * single client. Throws on an unknown name.
40
+ */
41
+ function resolveClientsForUninstall(clientOpt) {
42
+ if (clientOpt === undefined || clientOpt === "all") {
43
+ return registry_1.REGISTERED_CLIENTS;
44
+ }
45
+ const found = (0, registry_1.findClient)(clientOpt);
46
+ if (found === undefined) {
47
+ throw new Error(`Unknown client: '${clientOpt}'. Available: ${clientNames()}.`);
48
+ }
49
+ return [found];
50
+ }
51
+ /**
52
+ * Programmatic entry for `ironbee uninstall --all`. Iterates the
53
+ * inventory, removes ironbee artifacts from every project, and prunes
54
+ * the registry. Stale entries (path no longer exists) are quietly
55
+ * dropped from the registry.
56
+ *
57
+ * Per-project: runs `uninstall()` on every REGISTERED_CLIENT (each call
58
+ * is idempotent, only deletes files that exist). This makes the batch
59
+ * insensitive to drift between `entry.clients` and disk state — if the
60
+ * user manually moved between Claude and Cursor, both get cleaned.
61
+ */
62
+ async function runUninstallAll(opts) {
63
+ const allEntries = (0, projects_registry_1.listProjects)();
64
+ if (allEntries.length === 0) {
65
+ output_1.log.info("No registered projects. Nothing to uninstall.");
66
+ return { failures: 0, total: 0 };
67
+ }
68
+ // Single pass — `isProjectActive` does N×fs.stat per call, so don't
69
+ // run it twice on the same entry.
70
+ const alive = [];
71
+ const stale = [];
72
+ for (const entry of allEntries) {
73
+ ((0, registry_1.isProjectActive)(entry) ? alive : stale).push(entry);
74
+ }
75
+ if (alive.length === 0) {
76
+ // Nothing to do besides cleaning up stale registry entries.
77
+ output_1.log.info("No active registered projects to uninstall from.");
78
+ if (stale.length > 0) {
79
+ for (const entry of stale) {
80
+ (0, projects_registry_1.removeProject)(entry.path);
81
+ }
82
+ output_1.log.step(`Pruned ${output_1.pc.bold(String(stale.length))} stale registry entr${stale.length === 1 ? "y" : "ies"}.`);
83
+ }
84
+ return { failures: 0, total: 0 };
85
+ }
86
+ output_1.log.warn(`About to uninstall ironbee from ${output_1.pc.bold(String(alive.length))} project(s):`);
87
+ const displayed = alive.slice(0, NOTICE_PATH_CAP);
88
+ for (const p of displayed) {
89
+ console.log(` ${output_1.pc.dim("·")} ${output_1.pc.dim(p.path)}`);
90
+ }
91
+ if (alive.length > NOTICE_PATH_CAP) {
92
+ console.log(` ${output_1.pc.dim("…and")} ${output_1.pc.bold(String(alive.length - NOTICE_PATH_CAP))} ${output_1.pc.dim("more")}`);
93
+ }
94
+ if (stale.length > 0) {
95
+ output_1.log.dim(`(${stale.length} stale registry entr${stale.length === 1 ? "y" : "ies"} will also be pruned)`);
96
+ }
97
+ let confirmed;
98
+ if (opts.yes === true) {
99
+ confirmed = true;
100
+ }
101
+ else if ((0, prompt_1.isInteractive)()) {
102
+ // Default NO — destructive, no surprise deletions.
103
+ confirmed = await (0, prompt_1.promptYesNo)("Continue?", false);
104
+ }
105
+ else {
106
+ output_1.log.error("Refusing to batch-uninstall without --yes in a non-interactive context.");
107
+ process.exit(1);
108
+ }
109
+ if (!confirmed) {
110
+ output_1.log.info("Aborted.");
111
+ return { failures: 0, total: 0 };
112
+ }
113
+ output_1.log.blank();
114
+ let failures = 0;
115
+ const uninstalledClientNames = [];
116
+ for (const entry of alive) {
117
+ try {
118
+ output_1.log.label("project", output_1.pc.dim(entry.path));
119
+ const clients = resolveClientsForUninstall(opts.client);
120
+ const names = uninstallOne(entry.path, clients);
121
+ uninstalledClientNames.push(...names);
122
+ }
123
+ catch (e) {
124
+ failures++;
125
+ output_1.log.error(` ${entry.path}: ${e instanceof Error ? e.message : String(e)}`);
126
+ }
127
+ }
128
+ // Prune stale entries unconditionally (they have no on-disk footprint
129
+ // anyway, but the inventory record should reflect reality).
130
+ for (const entry of stale) {
131
+ (0, projects_registry_1.removeProject)(entry.path);
132
+ }
133
+ output_1.log.blank();
134
+ if (failures === 0) {
135
+ output_1.log.success(`Uninstalled from ${alive.length} project(s).${stale.length > 0 ? ` Pruned ${stale.length} stale entr${stale.length === 1 ? "y" : "ies"}.` : ""} ${output_1.pc.dim("Restart your AI coding client(s) to apply.")}`);
136
+ }
137
+ else {
138
+ output_1.log.warn(`Completed with ${failures} failure(s) — see above.`);
139
+ }
140
+ const uniqueClients = Array.from(new Set(uninstalledClientNames));
141
+ if (uniqueClients.length > 0) {
142
+ await (0, telemetry_1.trackUninstall)(uniqueClients);
143
+ }
144
+ return { failures, total: alive.length };
145
+ }
14
146
  exports.uninstallCommand = new commander_1.Command("uninstall")
15
- .description("Remove IronBee hooks and guidance files from a project")
147
+ .description("Remove IronBee hooks and guidance files from a project. Use --all to uninstall across every registered project (destructive — confirms before acting).")
16
148
  .argument("[project-dir]", "target project directory", ".")
17
149
  .option("--client <name>", `client to uninstall for (${clientNames()}), or "all"`)
150
+ .option("--all", "Uninstall across every project in the user-home inventory (~/.ironbee/projects.json). The [project-dir] argument is ignored when --all is set. Prompts before acting unless --yes is also passed.")
151
+ .option("-y, --yes", "Skip the confirmation prompt for --all (required in non-interactive contexts).")
18
152
  .action(async (dir, options) => {
153
+ if (options.all === true) {
154
+ const result = await runUninstallAll({
155
+ client: options.client,
156
+ yes: options.yes,
157
+ });
158
+ if (result.failures > 0) {
159
+ process.exit(1);
160
+ }
161
+ return;
162
+ }
19
163
  const projectDir = (0, path_1.resolve)(dir);
20
164
  if (!(0, fs_1.existsSync)(projectDir)) {
21
165
  output_1.log.error(`Directory not found: ${projectDir}`);
22
166
  process.exit(1);
23
167
  }
24
168
  let clients;
25
- if (options.client === "all") {
26
- clients = registry_1.REGISTERED_CLIENTS;
27
- }
28
- else if (options.client) {
29
- const found = (0, registry_1.findClient)(options.client);
30
- if (!found) {
31
- output_1.log.error(`Unknown client: "${options.client}". Available: ${clientNames()}`);
169
+ if (options.client !== undefined) {
170
+ try {
171
+ clients = resolveClientsForUninstall(options.client);
172
+ }
173
+ catch (e) {
174
+ output_1.log.error(e instanceof Error ? e.message : String(e));
32
175
  process.exit(1);
33
176
  }
34
- clients = [found];
35
177
  }
36
178
  else {
179
+ // No explicit --client → only uninstall what's actually
180
+ // detected. Avoids the surprise of a fresh project (no
181
+ // ironbee artifacts) running through the full strip path.
37
182
  clients = (0, registry_1.detectClients)(projectDir);
38
183
  if (clients.length === 0) {
39
184
  output_1.log.info("No client detected. Nothing to uninstall.");
40
185
  return;
41
186
  }
42
187
  }
43
- for (const client of clients) {
44
- client.uninstall(projectDir);
45
- }
46
- // remove .ironbee runtime directory
188
+ // Check whether .ironbee/ existed before uninstallOne deletes it,
189
+ // so the user-facing log only mentions what was actually removed.
47
190
  const ironbeeDir = (0, path_1.join)(projectDir, ".ironbee");
48
- if ((0, fs_1.existsSync)(ironbeeDir)) {
49
- (0, fs_1.rmSync)(ironbeeDir, { recursive: true, force: true });
191
+ const hadIronbeeDir = (0, fs_1.existsSync)(ironbeeDir);
192
+ const names = uninstallOne(projectDir, clients);
193
+ if (hadIronbeeDir) {
50
194
  output_1.log.step(`Removed ${output_1.pc.dim(ironbeeDir)}`);
51
195
  }
52
196
  output_1.log.blank();
53
197
  output_1.log.success(`IronBee removed. ${output_1.pc.dim("Restart your AI coding client to apply changes.")}`);
54
- await (0, telemetry_1.trackUninstall)(clients.map((c) => c.name));
198
+ await (0, telemetry_1.trackUninstall)(names);
55
199
  });
56
200
  //# sourceMappingURL=uninstall.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,2BAAwC;AACxC,+BAAqC;AAErC,kDAAoF;AACpF,0CAAwC;AACxC,gDAAkD;AAElD,SAAS,WAAW;IAChB,MAAM,KAAK,GAAa,6BAAkB,CAAC,GAAG,CAAC,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAEY,QAAA,gBAAgB,GAAY,IAAI,mBAAO,CAAC,WAAW,CAAC;KAC5D,WAAW,CAAC,wDAAwD,CAAC;KACrE,QAAQ,CAAC,eAAe,EAAE,0BAA0B,EAAE,GAAG,CAAC;KAC1D,MAAM,CAAC,iBAAiB,EAAE,4BAA4B,WAAW,EAAE,aAAa,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,GAAW,EAAE,OAA4B,EAAiB,EAAE;IACvE,MAAM,UAAU,GAAW,IAAA,cAAO,EAAC,GAAG,CAAC,CAAC;IAExC,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;QAC1B,YAAG,CAAC,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,OAAkB,CAAC;IAEvB,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,GAAG,6BAAkB,CAAC;IACjC,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,KAAK,GAAwB,IAAA,qBAAU,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,YAAG,CAAC,KAAK,CAAC,oBAAoB,OAAO,CAAC,MAAM,iBAAiB,WAAW,EAAE,EAAE,CAAC,CAAC;YAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;SAAM,CAAC;QACJ,OAAO,GAAG,IAAA,wBAAa,EAAC,UAAU,CAAC,CAAC;QACpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,YAAG,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;YACtD,OAAO;QACX,CAAC;IACL,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAED,oCAAoC;IACpC,MAAM,UAAU,GAAW,IAAA,WAAI,EAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACxD,IAAI,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;QACzB,IAAA,WAAM,EAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,YAAG,CAAC,IAAI,CAAC,WAAW,WAAE,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,YAAG,CAAC,KAAK,EAAE,CAAC;IACZ,YAAG,CAAC,OAAO,CAAC,oBAAoB,WAAE,CAAC,GAAG,CAAC,iDAAiD,CAAC,EAAE,CAAC,CAAC;IAC7F,MAAM,IAAA,0BAAc,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAU,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `ironbee unregister` — remove the current project from the user-home
3
+ * inventory at `~/.ironbee/projects.json`. Pure inventory operation:
4
+ * does NOT touch `.claude/`, `.cursor/`, `.ironbee/`, or any artifacts.
5
+ *
6
+ * Use cases:
7
+ * - The project dir was deleted manually but the registry still lists it.
8
+ * - You want a project to stop appearing in `config set --global` notices
9
+ * without uninstalling everything.
10
+ *
11
+ * Note: `ironbee uninstall` already auto-unregisters — this command is for
12
+ * cases where uninstall isn't being re-run (e.g. project dir is already
13
+ * gone).
14
+ */
15
+ import { Command } from "commander";
16
+ interface UnregisterOptions {
17
+ project?: string;
18
+ client?: string;
19
+ }
20
+ export declare function runUnregister(options: UnregisterOptions): Promise<void>;
21
+ export declare const unregisterCommand: Command;
22
+ export {};
23
+ //# sourceMappingURL=unregister.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unregister.d.ts","sourceRoot":"","sources":["../../src/commands/unregister.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,UAAU,iBAAiB;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC7E;AAED,eAAO,MAAM,iBAAiB,EAAE,OAM1B,CAAC"}