@rulemetric/cli 0.3.0 → 0.5.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.
Files changed (127) hide show
  1. package/dist/base-command.js +2 -2
  2. package/dist/{chunk-S56LOTGQ.js → chunk-7DIWBTB5.js} +2 -2
  3. package/dist/{chunk-L674RNKQ.js → chunk-ANOWI23I.js} +51 -1
  4. package/dist/chunk-ANOWI23I.js.map +7 -0
  5. package/dist/chunk-DUQGKWHJ.js +309 -0
  6. package/dist/chunk-DUQGKWHJ.js.map +7 -0
  7. package/dist/{chunk-LCT6MT2V.js → chunk-E32IADV3.js} +13 -12
  8. package/dist/chunk-E32IADV3.js.map +7 -0
  9. package/dist/{chunk-42A3HEEH.js → chunk-F5DPTXRC.js} +30 -2
  10. package/dist/{chunk-42A3HEEH.js.map → chunk-F5DPTXRC.js.map} +3 -3
  11. package/dist/{chunk-YEBBX4HQ.js → chunk-I4GHR6CY.js} +2 -2
  12. package/dist/{chunk-CROYS75W.js → chunk-LJ5OT5XN.js} +4 -4
  13. package/dist/{chunk-MTLAIJED.js → chunk-OWUS3HMA.js} +2 -2
  14. package/dist/{chunk-OGVORIFM.js → chunk-R56PH7YE.js} +11 -3
  15. package/dist/chunk-R56PH7YE.js.map +7 -0
  16. package/dist/{chunk-2BCPVUSF.js → chunk-RYMK7FQL.js} +5 -5
  17. package/dist/chunk-SO3T35U7.js +80 -0
  18. package/dist/chunk-SO3T35U7.js.map +7 -0
  19. package/dist/{chunk-Y2ARLMWZ.js → chunk-VBOTWXJW.js} +5 -5
  20. package/dist/commands/antigravity/backfill.js +2 -2
  21. package/dist/commands/auth/create-key.js +2 -2
  22. package/dist/commands/auth/login.js +2 -2
  23. package/dist/commands/auth/logout.js +2 -2
  24. package/dist/commands/auth/revoke-key.js +2 -2
  25. package/dist/commands/auth/status.js +2 -2
  26. package/dist/commands/catalog/index.js +2 -2
  27. package/dist/commands/catalog/recommend.js +2 -2
  28. package/dist/commands/convert.js +2 -2
  29. package/dist/commands/converters.js +2 -2
  30. package/dist/commands/crons/list.js +2 -2
  31. package/dist/commands/crons/run.js +2 -2
  32. package/dist/commands/dashboard.js +2 -2
  33. package/dist/commands/eval-targets/create.js +2 -2
  34. package/dist/commands/eval-targets/list.js +2 -2
  35. package/dist/commands/evals/agent.js +14 -13
  36. package/dist/commands/evals/agent.js.map +2 -2
  37. package/dist/commands/evals/benchmark.js +2 -2
  38. package/dist/commands/evals/compare.js +2 -2
  39. package/dist/commands/evals/create.js +2 -2
  40. package/dist/commands/evals/optimize-description.js +2 -2
  41. package/dist/commands/evals/optimize.js +2 -2
  42. package/dist/commands/evals/run.js +2 -2
  43. package/dist/commands/gateway/ensure.js +2 -2
  44. package/dist/commands/hooks/emit-instructions.js +25 -0
  45. package/dist/commands/hooks/emit-instructions.js.map +7 -0
  46. package/dist/commands/hooks/install.js +19 -25
  47. package/dist/commands/hooks/install.js.map +2 -2
  48. package/dist/commands/hooks/run.js +2 -2
  49. package/dist/commands/hooks/uninstall.js +6 -6
  50. package/dist/commands/hooks/uninstall.js.map +2 -2
  51. package/dist/commands/import.js +2 -2
  52. package/dist/commands/instructions/create.js +2 -2
  53. package/dist/commands/instructions/delete.js +2 -2
  54. package/dist/commands/instructions/fork.js +2 -2
  55. package/dist/commands/instructions/get.js +2 -2
  56. package/dist/commands/instructions/list.js +2 -2
  57. package/dist/commands/instructions/promote.js +2 -2
  58. package/dist/commands/instructions/pull.js +2 -2
  59. package/dist/commands/instructions/upstream.js +2 -2
  60. package/dist/commands/instructions/versions.js +2 -2
  61. package/dist/commands/launcher.js +2 -2
  62. package/dist/commands/org/current.js +2 -2
  63. package/dist/commands/org/list.js +2 -2
  64. package/dist/commands/org/switch.js +2 -2
  65. package/dist/commands/packs/add-instruction.js +2 -2
  66. package/dist/commands/packs/apply.js +2 -2
  67. package/dist/commands/packs/create.js +2 -2
  68. package/dist/commands/packs/fork.js +2 -2
  69. package/dist/commands/packs/get.js +2 -2
  70. package/dist/commands/packs/list.js +2 -2
  71. package/dist/commands/packs/remove-instruction.js +2 -2
  72. package/dist/commands/proxy/env.js +2 -2
  73. package/dist/commands/proxy/logs.js +2 -2
  74. package/dist/commands/proxy/restart.js +2 -2
  75. package/dist/commands/proxy/setup.js +2 -2
  76. package/dist/commands/proxy/start.js +2 -2
  77. package/dist/commands/proxy/status.js +2 -2
  78. package/dist/commands/proxy/stop.js +2 -2
  79. package/dist/commands/research/backfill.js +5 -5
  80. package/dist/commands/research/tail-transcript.js +5 -5
  81. package/dist/commands/service/install.js +9 -3
  82. package/dist/commands/service/install.js.map +2 -2
  83. package/dist/commands/service/status.js +2 -2
  84. package/dist/commands/service/uninstall.js +2 -2
  85. package/dist/commands/sessions/analyze.js +2 -2
  86. package/dist/commands/sessions/end.js +2 -2
  87. package/dist/commands/sessions/import.js +2 -2
  88. package/dist/commands/sessions/list.js +2 -2
  89. package/dist/commands/sessions/start.js +2 -2
  90. package/dist/commands/setup.js +146 -0
  91. package/dist/commands/setup.js.map +7 -0
  92. package/dist/commands/signals/report.js +2 -2
  93. package/dist/commands/skills/export-approved.js +2 -2
  94. package/dist/commands/skills/install.js +2 -2
  95. package/dist/commands/skills/list.js +2 -2
  96. package/dist/commands/skills/publish.js +2 -2
  97. package/dist/commands/skills/search.js +2 -2
  98. package/dist/commands/skills/update.js +2 -2
  99. package/dist/commands/suggestions/accept.js +2 -2
  100. package/dist/commands/suggestions/dismiss.js +2 -2
  101. package/dist/commands/suggestions/list.js +2 -2
  102. package/dist/commands/suggestions/refresh.js +2 -2
  103. package/dist/dashboard/Dashboard.js +17 -17
  104. package/dist/dashboard/launcher/LauncherOverlay.js +3 -3
  105. package/dist/lib/agent-loop.js +10 -10
  106. package/dist/lib/handlers/process-announcement.js +3 -3
  107. package/dist/lib/handlers/process-changelog.js +2 -2
  108. package/dist/lib/handlers/process-run-cleanup.js +2 -2
  109. package/dist/lib/handlers/process-session-goal.js +2 -2
  110. package/dist/lib/hooks-config.js +7 -1
  111. package/dist/lib/instruction-snapshot.js +8 -0
  112. package/dist/lib/instruction-snapshot.js.map +7 -0
  113. package/dist/lib/manual-tasks.js +2 -2
  114. package/dist/lib/setup-steps.js +26 -0
  115. package/dist/lib/setup-steps.js.map +7 -0
  116. package/dist/lib/version-check.js +3 -1
  117. package/oclif.manifest.json +207 -116
  118. package/package.json +7 -7
  119. package/dist/chunk-L674RNKQ.js.map +0 -7
  120. package/dist/chunk-LCT6MT2V.js.map +0 -7
  121. package/dist/chunk-OGVORIFM.js.map +0 -7
  122. /package/dist/{chunk-S56LOTGQ.js.map → chunk-7DIWBTB5.js.map} +0 -0
  123. /package/dist/{chunk-YEBBX4HQ.js.map → chunk-I4GHR6CY.js.map} +0 -0
  124. /package/dist/{chunk-CROYS75W.js.map → chunk-LJ5OT5XN.js.map} +0 -0
  125. /package/dist/{chunk-MTLAIJED.js.map → chunk-OWUS3HMA.js.map} +0 -0
  126. /package/dist/{chunk-2BCPVUSF.js.map → chunk-RYMK7FQL.js.map} +0 -0
  127. /package/dist/{chunk-Y2ARLMWZ.js.map → chunk-VBOTWXJW.js.map} +0 -0
@@ -4,8 +4,8 @@ import {
4
4
  } from "../../chunk-PQU7GZ7A.js";
5
5
  import {
6
6
  BaseCommand
7
- } from "../../chunk-S56LOTGQ.js";
8
- import "../../chunk-OGVORIFM.js";
7
+ } from "../../chunk-7DIWBTB5.js";
8
+ import "../../chunk-R56PH7YE.js";
9
9
  import "../../chunk-2AM54TUK.js";
10
10
  import {
11
11
  apiGet
@@ -3,8 +3,8 @@ import {
3
3
  } from "../../chunk-QN34TGD3.js";
4
4
  import {
5
5
  BaseCommand
6
- } from "../../chunk-S56LOTGQ.js";
7
- import "../../chunk-OGVORIFM.js";
6
+ } from "../../chunk-7DIWBTB5.js";
7
+ import "../../chunk-R56PH7YE.js";
8
8
  import "../../chunk-2AM54TUK.js";
9
9
  import {
10
10
  apiGet
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -7,8 +7,8 @@ import {
7
7
  } from "../../chunk-QN34TGD3.js";
8
8
  import {
9
9
  BaseCommand
10
- } from "../../chunk-S56LOTGQ.js";
11
- import "../../chunk-OGVORIFM.js";
10
+ } from "../../chunk-7DIWBTB5.js";
11
+ import "../../chunk-R56PH7YE.js";
12
12
  import "../../chunk-2AM54TUK.js";
13
13
  import {
14
14
  apiGet,
@@ -9,8 +9,8 @@ import {
9
9
  } from "../../chunk-QN34TGD3.js";
10
10
  import {
11
11
  BaseCommand
12
- } from "../../chunk-S56LOTGQ.js";
13
- import "../../chunk-OGVORIFM.js";
12
+ } from "../../chunk-7DIWBTB5.js";
13
+ import "../../chunk-R56PH7YE.js";
14
14
  import "../../chunk-2AM54TUK.js";
15
15
  import {
16
16
  apiGet,
@@ -6,8 +6,8 @@ import {
6
6
  } from "../../chunk-QN34TGD3.js";
7
7
  import {
8
8
  BaseCommand
9
- } from "../../chunk-S56LOTGQ.js";
10
- import "../../chunk-OGVORIFM.js";
9
+ } from "../../chunk-7DIWBTB5.js";
10
+ import "../../chunk-R56PH7YE.js";
11
11
  import "../../chunk-2AM54TUK.js";
12
12
  import {
13
13
  apiGet,
@@ -4,8 +4,8 @@ import {
4
4
  } from "../../chunk-FTJRMUID.js";
5
5
  import {
6
6
  BaseCommand
7
- } from "../../chunk-S56LOTGQ.js";
8
- import "../../chunk-OGVORIFM.js";
7
+ } from "../../chunk-7DIWBTB5.js";
8
+ import "../../chunk-R56PH7YE.js";
9
9
  import "../../chunk-2AM54TUK.js";
10
10
  import "../../chunk-EJOI2ZGU.js";
11
11
  import "../../chunk-KZRFUXGF.js";
@@ -0,0 +1,25 @@
1
+ import {
2
+ buildInstructionSnapshot
3
+ } from "../../chunk-SO3T35U7.js";
4
+ import "../../chunk-NSBPE2FW.js";
5
+
6
+ // src/commands/hooks/emit-instructions.ts
7
+ import { Command, Flags } from "@oclif/core";
8
+ var HooksEmitInstructions = class _HooksEmitInstructions extends Command {
9
+ static description = "Print a synthetic instruction snapshot (on-disk CLAUDE.md) as JSON for zero-proxy instruction linking";
10
+ static hidden = true;
11
+ static flags = {
12
+ "project-dir": Flags.string({ description: "Project directory to scan (defaults to cwd)" })
13
+ };
14
+ async run() {
15
+ const { flags } = await this.parse(_HooksEmitInstructions);
16
+ const snapshot = buildInstructionSnapshot(flags["project-dir"] ?? process.cwd());
17
+ if (snapshot) {
18
+ process.stdout.write(JSON.stringify(snapshot));
19
+ }
20
+ }
21
+ };
22
+ export {
23
+ HooksEmitInstructions as default
24
+ };
25
+ //# sourceMappingURL=emit-instructions.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/commands/hooks/emit-instructions.ts"],
4
+ "sourcesContent": ["import { Command, Flags } from '@oclif/core';\nimport { buildInstructionSnapshot } from '../../lib/instruction-snapshot.js';\n\n/**\n * Prints a synthetic instruction snapshot (built from on-disk CLAUDE.md files) as\n * JSON on stdout. Consumed by `session-end.sh`, which POSTs it to\n * `/api/sessions/:id/context-snapshots` so `link-instructions` can link\n * `claude_md` instructions on a hooks-only (zero-proxy) session.\n *\n * Extends raw oclif `Command` (not BaseCommand): it does no network or auth \u2014 it\n * only reads local files \u2014 and stdout MUST be clean JSON for the curl in\n * session-end.sh. Prints nothing when the project has no instruction files.\n */\nexport default class HooksEmitInstructions extends Command {\n static override description =\n 'Print a synthetic instruction snapshot (on-disk CLAUDE.md) as JSON for zero-proxy instruction linking';\n\n static override hidden = true;\n\n static override flags = {\n 'project-dir': Flags.string({ description: 'Project directory to scan (defaults to cwd)' }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(HooksEmitInstructions);\n const snapshot = buildInstructionSnapshot(flags['project-dir'] ?? process.cwd());\n if (snapshot) {\n process.stdout.write(JSON.stringify(snapshot));\n }\n }\n}\n"],
5
+ "mappings": ";;;;;;AAAA,SAAS,SAAS,aAAa;AAa/B,IAAqB,wBAArB,MAAqB,+BAA8B,QAAQ;AAAA,EACzD,OAAgB,cACd;AAAA,EAEF,OAAgB,SAAS;AAAA,EAEzB,OAAgB,QAAQ;AAAA,IACtB,eAAe,MAAM,OAAO,EAAE,aAAa,8CAA8C,CAAC;AAAA,EAC5F;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,sBAAqB;AACxD,UAAM,WAAW,yBAAyB,MAAM,aAAa,KAAK,QAAQ,IAAI,CAAC;AAC/E,QAAI,UAAU;AACZ,cAAQ,OAAO,MAAM,KAAK,UAAU,QAAQ,CAAC;AAAA,IAC/C;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -9,6 +9,8 @@ import {
9
9
  } from "../../chunk-BO76WKJR.js";
10
10
  import {
11
11
  installMacOSProxyEnv,
12
+ mergeClaudeCodeHooks,
13
+ removeClaudeCodeHooks,
12
14
  writeAntigravityHooks,
13
15
  writeAntigravityUserHooks,
14
16
  writeCopilotHooks,
@@ -18,7 +20,7 @@ import {
18
20
  writeCursorUserProxyConfig,
19
21
  writeVSCodeProxyConfig,
20
22
  writeVSCodeUserProxyConfig
21
- } from "../../chunk-L674RNKQ.js";
23
+ } from "../../chunk-ANOWI23I.js";
22
24
  import "../../chunk-KRBQLMOP.js";
23
25
  import {
24
26
  GATEWAY_PORT,
@@ -27,8 +29,8 @@ import {
27
29
  } from "../../chunk-FTJRMUID.js";
28
30
  import {
29
31
  BaseCommand
30
- } from "../../chunk-S56LOTGQ.js";
31
- import "../../chunk-OGVORIFM.js";
32
+ } from "../../chunk-7DIWBTB5.js";
33
+ import "../../chunk-R56PH7YE.js";
32
34
  import {
33
35
  bootstrapActiveOrg
34
36
  } from "../../chunk-2AM54TUK.js";
@@ -93,23 +95,11 @@ var HooksInstall = class _HooksInstall extends BaseCommand {
93
95
  if (existsSync(configPath)) {
94
96
  settings = JSON.parse(readFileSync(configPath, "utf-8"));
95
97
  }
96
- if (settings.hooks && typeof settings.hooks === "object") {
97
- const hooks = settings.hooks;
98
- let removed = 0;
99
- for (const event of Object.keys(hooks)) {
100
- const entries = hooks[event];
101
- if (!Array.isArray(entries)) continue;
102
- const kept = entries.filter((entry) => {
103
- const isRulemetric = entry?.hooks?.some((h) => typeof h?.command === "string" && h.command.includes("rulemetric"));
104
- if (isRulemetric) removed += 1;
105
- return !isRulemetric;
106
- });
107
- if (kept.length === 0) delete hooks[event];
108
- else hooks[event] = kept;
109
- }
110
- if (Object.keys(hooks).length === 0) delete settings.hooks;
111
- if (removed > 0) this.log(`[OK] Removed ${removed} legacy rulemetric session hook(s) (no longer needed)`);
112
- }
98
+ const refreshedHooks = removeClaudeCodeHooks(settings);
99
+ mergeClaudeCodeHooks(settings);
100
+ this.log(
101
+ refreshedHooks ? "[OK] Refreshed RuleMetric Claude Code session hooks \u2192 .claude/settings.json" : "[OK] Installed RuleMetric Claude Code session hooks \u2192 .claude/settings.json"
102
+ );
113
103
  if (!noProxy) {
114
104
  const hasMitmproxy = this.findBinary("mitmdump");
115
105
  if (!hasMitmproxy) {
@@ -244,16 +234,20 @@ var HooksInstall = class _HooksInstall extends BaseCommand {
244
234
  this.log("");
245
235
  this.log("The API service starts on login and restarts on crash.");
246
236
  } else if (!noProxy) {
247
- this.log(" 1. Start the capture proxy: rulemetric proxy start");
248
- this.log(" 2. Start Claude Code \u2014 context will be captured automatically");
237
+ this.log(" 1. Start Claude Code \u2014 sessions are captured by hooks immediately");
238
+ this.log(" 2. Start the capture proxy for full depth: rulemetric proxy start");
249
239
  this.log("");
250
- this.log("The gateway routes traffic direct when the proxy is off \u2014 Claude Code always works.");
240
+ this.log("Hooks capture every session (lifecycle + transcript). The proxy adds the");
241
+ this.log("rendered system prompt (instruction-effectiveness linking) + cross-tool capture.");
251
242
  this.log("");
252
243
  this.log("To capture traffic from other clients (Python, curl, etc.):");
253
244
  this.log(' eval "$(rulemetric proxy env --all)"');
254
245
  } else {
255
- this.log(" 1. Start Claude Code \u2014 session events will be tracked");
256
- this.log(" (Run without --no-proxy to also capture system prompts)");
246
+ this.log(" 1. Start Claude Code \u2014 sessions are captured by the hooks just installed");
247
+ this.log("");
248
+ this.log("No proxy means no mitmproxy / CA cert needed. The hooks capture full");
249
+ this.log("sessions on their own; re-run without --no-proxy to also capture system");
250
+ this.log("prompts for instruction-effectiveness linking.");
257
251
  }
258
252
  await bootstrapActiveOrg();
259
253
  const tmux = await detectTmux();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/commands/hooks/install.ts"],
4
- "sourcesContent": ["import { Flags } from '@oclif/core';\nimport { execFileSync, execSync, spawnSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { BaseCommand } from '../../base-command.js';\nimport { isGatewayRunning, spawnGateway, GATEWAY_PORT } from '../../lib/gateway-lifecycle.js';\n\n// True iff `rulemetric service install` has wired the gateway up as a launchd\n// agent. When this returns true, hooks install must NOT spawn its own\n// detached gateway \u2014 two processes fighting for :8787 means one crash-loops\n// and Claude Code's HTTPS_PROXY breaks.\nfunction isGatewayLaunchdManaged(): boolean {\n try {\n execFileSync('launchctl', ['list', 'com.rulemetric.gateway'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n return true;\n } catch {\n // Non-zero exit = label not loaded\n return false;\n }\n}\nimport {\n writeStatuslineShim,\n readCurrentStatusLine,\n isStatuslineShimInstalled,\n STATUSLINE_SETTINGS_VALUE,\n} from '../../lib/statusline-shim.js';\nimport {\n writeCursorProxyConfig,\n writeCursorUserProxyConfig,\n writeVSCodeProxyConfig,\n installMacOSProxyEnv,\n writeVSCodeUserProxyConfig,\n writeCursorHooks,\n writeCursorUserHooks,\n writeCopilotHooks,\n writeAntigravityHooks,\n writeAntigravityUserHooks,\n} from '../../lib/hooks-config.js';\nimport { bootstrapActiveOrg } from '../../lib/active-org-refresh.js';\nimport { detectTmux } from '../../lib/detect-tmux.js';\n\nconst CERT_PATH = join(homedir(), '.mitmproxy', 'mitmproxy-ca-cert.pem');\n\nexport default class HooksInstall extends BaseCommand {\n static override description = 'Install session tracking hooks and context capture proxy for Claude Code';\n\n static override examples = [\n '<%= config.bin %> hooks install',\n '<%= config.bin %> hooks install --global',\n '<%= config.bin %> hooks install --no-proxy',\n ];\n\n static override flags = {\n 'no-proxy': Flags.boolean({\n default: false,\n description: 'Skip proxy/gateway configuration (hooks only)',\n }),\n 'project-dir': Flags.string({\n description: 'Project directory to install hooks in (defaults to cwd)',\n }),\n global: Flags.boolean({\n char: 'g',\n default: false,\n description: 'Install hooks globally (~/.claude/settings.json) so all projects are tracked',\n }),\n 'statusline-usage': Flags.boolean({\n default: false,\n description: 'Install the statusline shim so Claude Code pushes live rate_limits on every refresh (makes /usage rings update in real time without needing the proxy)',\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(HooksInstall);\n const isGlobal = flags.global;\n const projectPath = isGlobal ? homedir() : (flags['project-dir'] ?? process.cwd());\n const configDir = join(projectPath, '.claude');\n const configPath = join(configDir, 'settings.json');\n const noProxy = flags['no-proxy'];\n\n if (isGlobal) {\n this.log(`Installing hooks globally \u2192 ${configPath}`);\n }\n\n // Read or create .claude/settings.json\n let settings: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n settings = JSON.parse(readFileSync(configPath, 'utf-8'));\n }\n\n // \u2500\u2500 1. Remove legacy rulemetric hooks (session data now comes from the\n // proxy + local file providers). Only strip entries whose command invokes\n // rulemetric \u2014 the user's own hooks must survive an install run.\n if (settings.hooks && typeof settings.hooks === 'object') {\n const hooks = settings.hooks as Record<string, Array<{ matcher?: string; hooks?: Array<{ command?: string }> }>>;\n let removed = 0;\n for (const event of Object.keys(hooks)) {\n const entries = hooks[event];\n if (!Array.isArray(entries)) continue;\n const kept = entries.filter((entry) => {\n const isRulemetric = entry?.hooks?.some((h) => typeof h?.command === 'string' && h.command.includes('rulemetric'));\n if (isRulemetric) removed += 1;\n return !isRulemetric;\n });\n if (kept.length === 0) delete hooks[event];\n else hooks[event] = kept;\n }\n if (Object.keys(hooks).length === 0) delete settings.hooks;\n if (removed > 0) this.log(`[OK] Removed ${removed} legacy rulemetric session hook(s) (no longer needed)`);\n }\n\n // \u2500\u2500 2. Configure gateway + proxy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (!noProxy) {\n // Ensure mitmproxy is available\n const hasMitmproxy = this.findBinary('mitmdump');\n if (!hasMitmproxy) {\n this.log('');\n this.log('[!!] mitmproxy not found \u2014 installing...');\n const installed = this.installMitmproxy();\n if (!installed) {\n this.log('[!!] Could not install mitmproxy. Skipping proxy config.');\n this.log(' Install manually: pipx install mitmproxy');\n this.log(' Then re-run: rulemetric hooks install');\n }\n }\n\n // Generate CA cert if missing\n if (!existsSync(CERT_PATH)) {\n this.log('[..] Generating CA certificate...');\n const mitmdump = this.findBinary('mitmdump');\n if (mitmdump) {\n spawnSync(mitmdump, ['--set', 'listen_port=0', '-q'], {\n timeout: 5000,\n stdio: 'ignore',\n });\n if (existsSync(CERT_PATH)) {\n this.log(`[OK] CA certificate generated at ${CERT_PATH}`);\n } else {\n this.log('[!!] Could not generate CA cert');\n }\n }\n } else {\n this.log('[OK] CA certificate found');\n }\n\n // Trust CA cert in system store (if not already trusted)\n if (existsSync(CERT_PATH) && !this.isCACertTrusted()) {\n this.log('[..] Installing CA certificate into system trust store (requires admin)...');\n const trusted = this.trustCACert();\n if (trusted) {\n this.log('[OK] CA certificate trusted by system');\n } else {\n this.log('[!!] Could not install CA cert automatically.');\n if (process.platform === 'darwin') {\n this.log(` Run manually: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${CERT_PATH}`);\n } else if (process.platform === 'linux') {\n this.log(` Run manually: sudo cp ${CERT_PATH} /usr/local/share/ca-certificates/mitmproxy-ca.crt && sudo update-ca-certificates`);\n }\n }\n } else if (existsSync(CERT_PATH)) {\n this.log('[OK] CA certificate already trusted');\n }\n\n // Set permanent HTTPS_PROXY and NODE_EXTRA_CA_CERTS in settings.json\n // These point to the gateway (always running), not mitmproxy directly\n const env = (settings.env ?? {}) as Record<string, string>;\n env.HTTPS_PROXY = `http://localhost:${GATEWAY_PORT}`;\n // Bypass proxy for non-Anthropic traffic (Supabase auth, npm, etc.)\n env.NO_PROXY = 'localhost,127.0.0.1,*.supabase.co,*.supabase.in';\n if (existsSync(CERT_PATH)) {\n env.NODE_EXTRA_CA_CERTS = CERT_PATH;\n }\n settings.env = env;\n this.log(`[OK] HTTPS_PROXY set to gateway on :${GATEWAY_PORT} (permanent)`);\n\n // Configure Cursor proxy (if .cursor/ exists)\n const cursorProxy = writeCursorProxyConfig(projectPath, GATEWAY_PORT, CERT_PATH);\n if (cursorProxy) {\n this.log('[OK] Cursor proxy configured \u2192 .cursor/settings.json');\n }\n\n // Configure VS Code proxy for Copilot capture (workspace settings)\n const vscodeProxy = writeVSCodeProxyConfig(projectPath, GATEWAY_PORT, CERT_PATH);\n if (vscodeProxy) {\n this.log('[OK] VS Code workspace proxy configured \u2192 .vscode/settings.json');\n }\n\n // Set http.proxy in VS Code user settings (workspace-level is silently ignored\n // for http.proxy due to APPLICATION scope \u2014 microsoft/vscode#236932)\n const vscodeUserProxy = writeVSCodeUserProxyConfig(GATEWAY_PORT);\n if (vscodeUserProxy) {\n this.log('[OK] VS Code user proxy configured \u2192 ~/Library/Application Support/Code/User/settings.json');\n }\n\n // Same for Cursor (VS Code fork inherits the APPLICATION-scope restriction).\n const cursorUserProxy = writeCursorUserProxyConfig(GATEWAY_PORT);\n if (cursorUserProxy) {\n this.log('[OK] Cursor user proxy configured \u2192 ~/Library/Application Support/Cursor/User/settings.json');\n }\n\n // Set HTTPS_PROXY for all GUI apps via launchctl + LaunchAgent (macOS)\n // Copilot reads process.env.HTTPS_PROXY directly \u2014 VS Code settings alone\n // are insufficient because workspace http.proxy is ignored and extensions\n // may bypass vscode-proxy-agent (microsoft/vscode#12588)\n const macProxy = installMacOSProxyEnv(GATEWAY_PORT, CERT_PATH);\n if (macProxy) {\n this.log('[OK] HTTPS_PROXY set for GUI apps (launchctl + LaunchAgent)');\n }\n\n // Start gateway if not already running. Three possible owners (in order\n // of precedence):\n // 1. launchd (`rulemetric service install` plist) \u2014 authoritative;\n // hooks must NOT spawn a competing copy that would fight for :8787\n // 2. legacy PID-file (this same code path from a previous run)\n // 3. nothing \u2014 spawn a fresh detached process\n if (isGatewayLaunchdManaged()) {\n this.log('[OK] Gateway managed by launchd (com.rulemetric.gateway)');\n } else if (isGatewayRunning()) {\n this.log('[OK] Gateway already running');\n } else {\n try {\n const pid = spawnGateway(this.config.version);\n this.log(`[OK] Gateway started (PID ${pid})`);\n } catch (err) {\n this.log(`[!!] Could not start gateway: ${(err as Error).message}`);\n this.log(' The session-start hook will auto-start it on next Claude Code session.');\n }\n }\n }\n\n // \u2500\u2500 3. Write Cursor + Copilot hook configs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // These are independent of the proxy (they capture editor lifecycle\n // events, not LLM traffic), so they run regardless of --no-proxy. Both\n // helpers no-op when the target directory (.cursor/ or .github/)\n // doesn't exist.\n if (!isGlobal) {\n const cursorHooks = writeCursorHooks(projectPath);\n if (cursorHooks) {\n this.log(`[OK] Cursor hooks configured \u2192 ${cursorHooks}`);\n }\n\n const copilotHooks = writeCopilotHooks(projectPath);\n if (copilotHooks) {\n this.log(`[OK] Copilot Agent hooks configured \u2192 ${copilotHooks}`);\n }\n\n const antigravityHooks = writeAntigravityHooks(projectPath);\n if (antigravityHooks) {\n this.log(`[OK] Antigravity workspace hooks configured \u2192 ${antigravityHooks}`);\n }\n }\n\n // User-level Antigravity hooks at ~/.gemini/config/hooks.json. Required\n // because the GUI Antigravity process is launched once per machine and\n // covers any workspace the user opens, not just the install-time cwd.\n const antigravityUserHooks = writeAntigravityUserHooks();\n if (antigravityUserHooks) {\n this.log(`[OK] Antigravity user hooks configured \u2192 ${antigravityUserHooks}`);\n }\n\n // User-level Cursor hooks (~/.cursor/hooks.json) are required for global\n // capture because Cursor's chat traffic bypasses HTTP proxies (HTTP/2\n // multiplexed persistent connection \u2014 see cursor.com/docs/hooks). Without\n // hooks, we get zero Cursor visibility for sessions outside this project.\n // Runs in both --global and per-project modes since the user file is\n // machine-wide either way.\n const cursorUserHooks = writeCursorUserHooks();\n if (cursorUserHooks) {\n this.log(`[OK] Cursor user hooks configured \u2192 ${cursorUserHooks}`);\n }\n\n // \u2500\u2500 4. Statusline shim (rate_limits freshness) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // When --statusline-usage is set, write ~/.claude/statusline-rulemetric.sh\n // and point settings.statusLine at it. If the user already has a statusLine\n // command configured, chain it so their prompt text is preserved.\n if (flags['statusline-usage']) {\n if (isStatuslineShimInstalled(settings)) {\n this.log('[OK] Statusline shim already installed');\n } else {\n const prevCmd = readCurrentStatusLine(settings);\n writeStatuslineShim(prevCmd);\n settings.statusLine = STATUSLINE_SETTINGS_VALUE;\n if (prevCmd) {\n this.log(`[OK] Statusline shim installed \u2192 ${STATUSLINE_SETTINGS_VALUE.command} (chains to: ${prevCmd})`);\n } else {\n this.log(`[OK] Statusline shim installed \u2192 ${STATUSLINE_SETTINGS_VALUE.command}`);\n }\n this.log(' Rate-limit rings will now update on Claude Code\\'s statusline refresh cadence');\n }\n }\n\n // \u2500\u2500 5. Write Claude Code settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n mkdirSync(configDir, { recursive: true });\n writeFileSync(configPath, JSON.stringify(settings, null, 2) + '\\n');\n\n this.log('');\n this.log('Setup complete! Next steps:');\n if (isGlobal) {\n this.log(' 1. Install always-on API: rulemetric service install');\n this.log(' 2. Start Claude Code in any project \u2014 all sessions tracked automatically');\n this.log('');\n this.log('The API service starts on login and restarts on crash.');\n } else if (!noProxy) {\n this.log(' 1. Start the capture proxy: rulemetric proxy start');\n this.log(' 2. Start Claude Code \u2014 context will be captured automatically');\n this.log('');\n this.log('The gateway routes traffic direct when the proxy is off \u2014 Claude Code always works.');\n this.log('');\n this.log('To capture traffic from other clients (Python, curl, etc.):');\n this.log(' eval \"$(rulemetric proxy env --all)\"');\n } else {\n this.log(' 1. Start Claude Code \u2014 session events will be tracked');\n this.log(' (Run without --no-proxy to also capture system prompts)');\n }\n\n // Ensure the active-org cache is populated before the user starts a\n // Claude Code session. BaseCommand fired the guarded refresh earlier\n // but may have raced with auth init or hit a transient error; this\n // explicit retry guarantees the cache reflects the user's current\n // active_org_id at the end of `hooks install`.\n await bootstrapActiveOrg();\n\n // Soft tmux capability check \u2014 live message send needs tmux on the\n // user's machine. We do not auto-install; just surface one line.\n const tmux = await detectTmux();\n this.log('');\n if (tmux.available) {\n this.log(`[OK] tmux found${tmux.version ? ` (v${tmux.version})` : ''} \u2014 live send enabled`);\n } else {\n this.log('[!!] tmux not found \u2014 live send will fall back to opening Terminal. Install with: brew install tmux');\n }\n }\n\n private findBinary(name: string): string | null {\n try {\n return execSync(`which ${name} 2>/dev/null`, { encoding: 'utf-8' }).trim() || null;\n } catch {\n return null;\n }\n }\n\n private installMitmproxy(): boolean {\n for (const [cmd, args] of [\n ['pipx', ['install', 'mitmproxy']],\n ['uv', ['tool', 'install', 'mitmproxy']],\n ['brew', ['install', 'mitmproxy']],\n ] as const) {\n if (this.findBinary(cmd)) {\n this.log(` Installing via ${cmd}...`);\n const result = spawnSync(cmd, [...args], { stdio: 'inherit' });\n if (result.status === 0) return true;\n }\n }\n return false;\n }\n\n private isCACertTrusted(): boolean {\n if (process.platform === 'darwin') {\n const result = spawnSync('security', ['verify-cert', '-c', CERT_PATH], {\n stdio: 'pipe',\n });\n return result.status === 0;\n }\n\n if (process.platform === 'linux') {\n return existsSync('/usr/local/share/ca-certificates/mitmproxy-ca.crt');\n }\n\n if (process.platform === 'win32') {\n // On Windows, check if cert is in the Root store\n const result = spawnSync('certutil', ['-verify', CERT_PATH], {\n stdio: 'pipe',\n });\n return result.status === 0;\n }\n\n return false;\n }\n\n private trustCACert(): boolean {\n if (process.platform === 'darwin') {\n const result = spawnSync('sudo', [\n 'security', 'add-trusted-cert', '-d', '-r', 'trustRoot',\n '-k', '/Library/Keychains/System.keychain', CERT_PATH,\n ], { stdio: 'inherit' });\n return result.status === 0;\n }\n\n if (process.platform === 'linux') {\n const cp = spawnSync('sudo', [\n 'cp', CERT_PATH, '/usr/local/share/ca-certificates/mitmproxy-ca.crt',\n ], { stdio: 'inherit' });\n if (cp.status !== 0) return false;\n const update = spawnSync('sudo', ['update-ca-certificates'], { stdio: 'inherit' });\n return update.status === 0;\n }\n\n if (process.platform === 'win32') {\n const result = spawnSync('certutil', [\n '-addstore', '-f', 'Root', CERT_PATH,\n ], { stdio: 'inherit' });\n return result.status === 0;\n }\n\n return false;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Flags } from '@oclif/core';\nimport { execFileSync, execSync, spawnSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { BaseCommand } from '../../base-command.js';\nimport { isGatewayRunning, spawnGateway, GATEWAY_PORT } from '../../lib/gateway-lifecycle.js';\n\n// True iff `rulemetric service install` has wired the gateway up as a launchd\n// agent. When this returns true, hooks install must NOT spawn its own\n// detached gateway \u2014 two processes fighting for :8787 means one crash-loops\n// and Claude Code's HTTPS_PROXY breaks.\nfunction isGatewayLaunchdManaged(): boolean {\n try {\n execFileSync('launchctl', ['list', 'com.rulemetric.gateway'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n return true;\n } catch {\n // Non-zero exit = label not loaded\n return false;\n }\n}\nimport {\n writeStatuslineShim,\n readCurrentStatusLine,\n isStatuslineShimInstalled,\n STATUSLINE_SETTINGS_VALUE,\n} from '../../lib/statusline-shim.js';\nimport {\n mergeClaudeCodeHooks,\n removeClaudeCodeHooks,\n writeCursorProxyConfig,\n writeCursorUserProxyConfig,\n writeVSCodeProxyConfig,\n installMacOSProxyEnv,\n writeVSCodeUserProxyConfig,\n writeCursorHooks,\n writeCursorUserHooks,\n writeCopilotHooks,\n writeAntigravityHooks,\n writeAntigravityUserHooks,\n} from '../../lib/hooks-config.js';\nimport { bootstrapActiveOrg } from '../../lib/active-org-refresh.js';\nimport { detectTmux } from '../../lib/detect-tmux.js';\n\nconst CERT_PATH = join(homedir(), '.mitmproxy', 'mitmproxy-ca-cert.pem');\n\nexport default class HooksInstall extends BaseCommand {\n static override description = 'Install session tracking hooks and context capture proxy for Claude Code';\n\n static override examples = [\n '<%= config.bin %> hooks install',\n '<%= config.bin %> hooks install --global',\n '<%= config.bin %> hooks install --no-proxy',\n ];\n\n static override flags = {\n 'no-proxy': Flags.boolean({\n default: false,\n description: 'Skip proxy/gateway configuration (hooks only)',\n }),\n 'project-dir': Flags.string({\n description: 'Project directory to install hooks in (defaults to cwd)',\n }),\n global: Flags.boolean({\n char: 'g',\n default: false,\n description: 'Install hooks globally (~/.claude/settings.json) so all projects are tracked',\n }),\n 'statusline-usage': Flags.boolean({\n default: false,\n description: 'Install the statusline shim so Claude Code pushes live rate_limits on every refresh (makes /usage rings update in real time without needing the proxy)',\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(HooksInstall);\n const isGlobal = flags.global;\n const projectPath = isGlobal ? homedir() : (flags['project-dir'] ?? process.cwd());\n const configDir = join(projectPath, '.claude');\n const configPath = join(configDir, 'settings.json');\n const noProxy = flags['no-proxy'];\n\n if (isGlobal) {\n this.log(`Installing hooks globally \u2192 ${configPath}`);\n }\n\n // Read or create .claude/settings.json\n let settings: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n settings = JSON.parse(readFileSync(configPath, 'utf-8'));\n }\n\n // \u2500\u2500 1. Install Claude Code session-tracking hooks (hooks-first, zero-proxy\n // capture). Strip any stale rulemetric entries first \u2014 handles old command\n // formats, preserves the user's own hooks \u2014 then merge the current canonical\n // set. Runs regardless of --no-proxy: this is the whole point of the hooks\n // path, which captures full sessions (lifecycle + SessionEnd transcript\n // reimport) without mitmproxy / CA trust / gateway. The proxy adds the\n // rendered system prompt (instruction-linking) + cross-tool capture on top.\n const refreshedHooks = removeClaudeCodeHooks(settings);\n mergeClaudeCodeHooks(settings);\n this.log(\n refreshedHooks\n ? '[OK] Refreshed RuleMetric Claude Code session hooks \u2192 .claude/settings.json'\n : '[OK] Installed RuleMetric Claude Code session hooks \u2192 .claude/settings.json',\n );\n\n // \u2500\u2500 2. Configure gateway + proxy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (!noProxy) {\n // Ensure mitmproxy is available\n const hasMitmproxy = this.findBinary('mitmdump');\n if (!hasMitmproxy) {\n this.log('');\n this.log('[!!] mitmproxy not found \u2014 installing...');\n const installed = this.installMitmproxy();\n if (!installed) {\n this.log('[!!] Could not install mitmproxy. Skipping proxy config.');\n this.log(' Install manually: pipx install mitmproxy');\n this.log(' Then re-run: rulemetric hooks install');\n }\n }\n\n // Generate CA cert if missing\n if (!existsSync(CERT_PATH)) {\n this.log('[..] Generating CA certificate...');\n const mitmdump = this.findBinary('mitmdump');\n if (mitmdump) {\n spawnSync(mitmdump, ['--set', 'listen_port=0', '-q'], {\n timeout: 5000,\n stdio: 'ignore',\n });\n if (existsSync(CERT_PATH)) {\n this.log(`[OK] CA certificate generated at ${CERT_PATH}`);\n } else {\n this.log('[!!] Could not generate CA cert');\n }\n }\n } else {\n this.log('[OK] CA certificate found');\n }\n\n // Trust CA cert in system store (if not already trusted)\n if (existsSync(CERT_PATH) && !this.isCACertTrusted()) {\n this.log('[..] Installing CA certificate into system trust store (requires admin)...');\n const trusted = this.trustCACert();\n if (trusted) {\n this.log('[OK] CA certificate trusted by system');\n } else {\n this.log('[!!] Could not install CA cert automatically.');\n if (process.platform === 'darwin') {\n this.log(` Run manually: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${CERT_PATH}`);\n } else if (process.platform === 'linux') {\n this.log(` Run manually: sudo cp ${CERT_PATH} /usr/local/share/ca-certificates/mitmproxy-ca.crt && sudo update-ca-certificates`);\n }\n }\n } else if (existsSync(CERT_PATH)) {\n this.log('[OK] CA certificate already trusted');\n }\n\n // Set permanent HTTPS_PROXY and NODE_EXTRA_CA_CERTS in settings.json\n // These point to the gateway (always running), not mitmproxy directly\n const env = (settings.env ?? {}) as Record<string, string>;\n env.HTTPS_PROXY = `http://localhost:${GATEWAY_PORT}`;\n // Bypass proxy for non-Anthropic traffic (Supabase auth, npm, etc.)\n env.NO_PROXY = 'localhost,127.0.0.1,*.supabase.co,*.supabase.in';\n if (existsSync(CERT_PATH)) {\n env.NODE_EXTRA_CA_CERTS = CERT_PATH;\n }\n settings.env = env;\n this.log(`[OK] HTTPS_PROXY set to gateway on :${GATEWAY_PORT} (permanent)`);\n\n // Configure Cursor proxy (if .cursor/ exists)\n const cursorProxy = writeCursorProxyConfig(projectPath, GATEWAY_PORT, CERT_PATH);\n if (cursorProxy) {\n this.log('[OK] Cursor proxy configured \u2192 .cursor/settings.json');\n }\n\n // Configure VS Code proxy for Copilot capture (workspace settings)\n const vscodeProxy = writeVSCodeProxyConfig(projectPath, GATEWAY_PORT, CERT_PATH);\n if (vscodeProxy) {\n this.log('[OK] VS Code workspace proxy configured \u2192 .vscode/settings.json');\n }\n\n // Set http.proxy in VS Code user settings (workspace-level is silently ignored\n // for http.proxy due to APPLICATION scope \u2014 microsoft/vscode#236932)\n const vscodeUserProxy = writeVSCodeUserProxyConfig(GATEWAY_PORT);\n if (vscodeUserProxy) {\n this.log('[OK] VS Code user proxy configured \u2192 ~/Library/Application Support/Code/User/settings.json');\n }\n\n // Same for Cursor (VS Code fork inherits the APPLICATION-scope restriction).\n const cursorUserProxy = writeCursorUserProxyConfig(GATEWAY_PORT);\n if (cursorUserProxy) {\n this.log('[OK] Cursor user proxy configured \u2192 ~/Library/Application Support/Cursor/User/settings.json');\n }\n\n // Set HTTPS_PROXY for all GUI apps via launchctl + LaunchAgent (macOS)\n // Copilot reads process.env.HTTPS_PROXY directly \u2014 VS Code settings alone\n // are insufficient because workspace http.proxy is ignored and extensions\n // may bypass vscode-proxy-agent (microsoft/vscode#12588)\n const macProxy = installMacOSProxyEnv(GATEWAY_PORT, CERT_PATH);\n if (macProxy) {\n this.log('[OK] HTTPS_PROXY set for GUI apps (launchctl + LaunchAgent)');\n }\n\n // Start gateway if not already running. Three possible owners (in order\n // of precedence):\n // 1. launchd (`rulemetric service install` plist) \u2014 authoritative;\n // hooks must NOT spawn a competing copy that would fight for :8787\n // 2. legacy PID-file (this same code path from a previous run)\n // 3. nothing \u2014 spawn a fresh detached process\n if (isGatewayLaunchdManaged()) {\n this.log('[OK] Gateway managed by launchd (com.rulemetric.gateway)');\n } else if (isGatewayRunning()) {\n this.log('[OK] Gateway already running');\n } else {\n try {\n const pid = spawnGateway(this.config.version);\n this.log(`[OK] Gateway started (PID ${pid})`);\n } catch (err) {\n this.log(`[!!] Could not start gateway: ${(err as Error).message}`);\n this.log(' The session-start hook will auto-start it on next Claude Code session.');\n }\n }\n }\n\n // \u2500\u2500 3. Write Cursor + Copilot hook configs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // These are independent of the proxy (they capture editor lifecycle\n // events, not LLM traffic), so they run regardless of --no-proxy. Both\n // helpers no-op when the target directory (.cursor/ or .github/)\n // doesn't exist.\n if (!isGlobal) {\n const cursorHooks = writeCursorHooks(projectPath);\n if (cursorHooks) {\n this.log(`[OK] Cursor hooks configured \u2192 ${cursorHooks}`);\n }\n\n const copilotHooks = writeCopilotHooks(projectPath);\n if (copilotHooks) {\n this.log(`[OK] Copilot Agent hooks configured \u2192 ${copilotHooks}`);\n }\n\n const antigravityHooks = writeAntigravityHooks(projectPath);\n if (antigravityHooks) {\n this.log(`[OK] Antigravity workspace hooks configured \u2192 ${antigravityHooks}`);\n }\n }\n\n // User-level Antigravity hooks at ~/.gemini/config/hooks.json. Required\n // because the GUI Antigravity process is launched once per machine and\n // covers any workspace the user opens, not just the install-time cwd.\n const antigravityUserHooks = writeAntigravityUserHooks();\n if (antigravityUserHooks) {\n this.log(`[OK] Antigravity user hooks configured \u2192 ${antigravityUserHooks}`);\n }\n\n // User-level Cursor hooks (~/.cursor/hooks.json) are required for global\n // capture because Cursor's chat traffic bypasses HTTP proxies (HTTP/2\n // multiplexed persistent connection \u2014 see cursor.com/docs/hooks). Without\n // hooks, we get zero Cursor visibility for sessions outside this project.\n // Runs in both --global and per-project modes since the user file is\n // machine-wide either way.\n const cursorUserHooks = writeCursorUserHooks();\n if (cursorUserHooks) {\n this.log(`[OK] Cursor user hooks configured \u2192 ${cursorUserHooks}`);\n }\n\n // \u2500\u2500 4. Statusline shim (rate_limits freshness) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // When --statusline-usage is set, write ~/.claude/statusline-rulemetric.sh\n // and point settings.statusLine at it. If the user already has a statusLine\n // command configured, chain it so their prompt text is preserved.\n if (flags['statusline-usage']) {\n if (isStatuslineShimInstalled(settings)) {\n this.log('[OK] Statusline shim already installed');\n } else {\n const prevCmd = readCurrentStatusLine(settings);\n writeStatuslineShim(prevCmd);\n settings.statusLine = STATUSLINE_SETTINGS_VALUE;\n if (prevCmd) {\n this.log(`[OK] Statusline shim installed \u2192 ${STATUSLINE_SETTINGS_VALUE.command} (chains to: ${prevCmd})`);\n } else {\n this.log(`[OK] Statusline shim installed \u2192 ${STATUSLINE_SETTINGS_VALUE.command}`);\n }\n this.log(' Rate-limit rings will now update on Claude Code\\'s statusline refresh cadence');\n }\n }\n\n // \u2500\u2500 5. Write Claude Code settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n mkdirSync(configDir, { recursive: true });\n writeFileSync(configPath, JSON.stringify(settings, null, 2) + '\\n');\n\n this.log('');\n this.log('Setup complete! Next steps:');\n if (isGlobal) {\n this.log(' 1. Install always-on API: rulemetric service install');\n this.log(' 2. Start Claude Code in any project \u2014 all sessions tracked automatically');\n this.log('');\n this.log('The API service starts on login and restarts on crash.');\n } else if (!noProxy) {\n this.log(' 1. Start Claude Code \u2014 sessions are captured by hooks immediately');\n this.log(' 2. Start the capture proxy for full depth: rulemetric proxy start');\n this.log('');\n this.log('Hooks capture every session (lifecycle + transcript). The proxy adds the');\n this.log('rendered system prompt (instruction-effectiveness linking) + cross-tool capture.');\n this.log('');\n this.log('To capture traffic from other clients (Python, curl, etc.):');\n this.log(' eval \"$(rulemetric proxy env --all)\"');\n } else {\n // --no-proxy still installs the Claude Code session hooks above, so full\n // sessions ARE captured (lifecycle + SessionEnd transcript reimport) with\n // no mitmproxy / CA trust / gateway. Only the proxy-exclusive layer\n // (rendered system prompt \u2192 instruction-linking, cross-tool) is skipped.\n this.log(' 1. Start Claude Code \u2014 sessions are captured by the hooks just installed');\n this.log('');\n this.log('No proxy means no mitmproxy / CA cert needed. The hooks capture full');\n this.log('sessions on their own; re-run without --no-proxy to also capture system');\n this.log('prompts for instruction-effectiveness linking.');\n }\n\n // Ensure the active-org cache is populated before the user starts a\n // Claude Code session. BaseCommand fired the guarded refresh earlier\n // but may have raced with auth init or hit a transient error; this\n // explicit retry guarantees the cache reflects the user's current\n // active_org_id at the end of `hooks install`.\n await bootstrapActiveOrg();\n\n // Soft tmux capability check \u2014 live message send needs tmux on the\n // user's machine. We do not auto-install; just surface one line.\n const tmux = await detectTmux();\n this.log('');\n if (tmux.available) {\n this.log(`[OK] tmux found${tmux.version ? ` (v${tmux.version})` : ''} \u2014 live send enabled`);\n } else {\n this.log('[!!] tmux not found \u2014 live send will fall back to opening Terminal. Install with: brew install tmux');\n }\n }\n\n private findBinary(name: string): string | null {\n try {\n return execSync(`which ${name} 2>/dev/null`, { encoding: 'utf-8' }).trim() || null;\n } catch {\n return null;\n }\n }\n\n private installMitmproxy(): boolean {\n for (const [cmd, args] of [\n ['pipx', ['install', 'mitmproxy']],\n ['uv', ['tool', 'install', 'mitmproxy']],\n ['brew', ['install', 'mitmproxy']],\n ] as const) {\n if (this.findBinary(cmd)) {\n this.log(` Installing via ${cmd}...`);\n const result = spawnSync(cmd, [...args], { stdio: 'inherit' });\n if (result.status === 0) return true;\n }\n }\n return false;\n }\n\n private isCACertTrusted(): boolean {\n if (process.platform === 'darwin') {\n const result = spawnSync('security', ['verify-cert', '-c', CERT_PATH], {\n stdio: 'pipe',\n });\n return result.status === 0;\n }\n\n if (process.platform === 'linux') {\n return existsSync('/usr/local/share/ca-certificates/mitmproxy-ca.crt');\n }\n\n if (process.platform === 'win32') {\n // On Windows, check if cert is in the Root store\n const result = spawnSync('certutil', ['-verify', CERT_PATH], {\n stdio: 'pipe',\n });\n return result.status === 0;\n }\n\n return false;\n }\n\n private trustCACert(): boolean {\n if (process.platform === 'darwin') {\n const result = spawnSync('sudo', [\n 'security', 'add-trusted-cert', '-d', '-r', 'trustRoot',\n '-k', '/Library/Keychains/System.keychain', CERT_PATH,\n ], { stdio: 'inherit' });\n return result.status === 0;\n }\n\n if (process.platform === 'linux') {\n const cp = spawnSync('sudo', [\n 'cp', CERT_PATH, '/usr/local/share/ca-certificates/mitmproxy-ca.crt',\n ], { stdio: 'inherit' });\n if (cp.status !== 0) return false;\n const update = spawnSync('sudo', ['update-ca-certificates'], { stdio: 'inherit' });\n return update.status === 0;\n }\n\n if (process.platform === 'win32') {\n const result = spawnSync('certutil', [\n '-addstore', '-f', 'Root', CERT_PATH,\n ], { stdio: 'inherit' });\n return result.status === 0;\n }\n\n return false;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import "../../chunk-EJOI2ZGU.js";
7
7
  import "../../chunk-KZRFUXGF.js";
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  removeAntigravityHooks,
3
3
  removeAntigravityUserHooks,
4
+ removeClaudeCodeHooks,
4
5
  removeCopilotHooks,
5
6
  removeCursorHooks,
6
7
  removeCursorUserHooks,
@@ -8,14 +9,14 @@ import {
8
9
  removeVSCodeProxyConfig,
9
10
  removeVSCodeUserProxyConfig,
10
11
  uninstallMacOSProxyEnv
11
- } from "../../chunk-L674RNKQ.js";
12
+ } from "../../chunk-ANOWI23I.js";
12
13
  import {
13
14
  stopGateway
14
15
  } from "../../chunk-FTJRMUID.js";
15
16
  import {
16
17
  BaseCommand
17
- } from "../../chunk-S56LOTGQ.js";
18
- import "../../chunk-OGVORIFM.js";
18
+ } from "../../chunk-7DIWBTB5.js";
19
+ import "../../chunk-R56PH7YE.js";
19
20
  import "../../chunk-2AM54TUK.js";
20
21
  import "../../chunk-EJOI2ZGU.js";
21
22
  import "../../chunk-KZRFUXGF.js";
@@ -38,9 +39,8 @@ var HooksUninstall = class extends BaseCommand {
38
39
  }
39
40
  const settings = JSON.parse(readFileSync(configPath, "utf-8"));
40
41
  let changed = false;
41
- if (settings.hooks) {
42
- delete settings.hooks;
43
- this.log("Removed hooks from .claude/settings.json");
42
+ if (removeClaudeCodeHooks(settings)) {
43
+ this.log("Removed RuleMetric hooks from .claude/settings.json");
44
44
  changed = true;
45
45
  }
46
46
  const env = settings.env;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/commands/hooks/uninstall.ts"],
4
- "sourcesContent": ["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { BaseCommand } from '../../base-command.js';\nimport { stopGateway } from '../../lib/gateway-lifecycle.js';\nimport { removeCursorHooks, removeCursorUserHooks, removeCopilotHooks, removeAntigravityHooks, removeAntigravityUserHooks, removeVSCodeProxyConfig, uninstallMacOSProxyEnv, removeVSCodeUserProxyConfig, removeCursorUserProxyConfig } from '../../lib/hooks-config.js';\n\nexport default class HooksUninstall extends BaseCommand {\n static override description = 'Remove session tracking hooks from the current project';\n\n static override examples = [\n '<%= config.bin %> hooks uninstall',\n ];\n\n async run(): Promise<void> {\n const configPath = join(process.cwd(), '.claude', 'settings.json');\n\n if (!existsSync(configPath)) {\n this.log('No .claude/settings.json found \u2014 nothing to uninstall.');\n return;\n }\n\n const settings: Record<string, unknown> = JSON.parse(readFileSync(configPath, 'utf-8'));\n\n let changed = false;\n\n // Remove hooks\n if (settings.hooks) {\n delete settings.hooks;\n this.log('Removed hooks from .claude/settings.json');\n changed = true;\n }\n\n // Remove gateway proxy env\n const env = settings.env as Record<string, string> | undefined;\n if (env?.HTTPS_PROXY || env?.NODE_EXTRA_CA_CERTS) {\n delete env.HTTPS_PROXY;\n delete env.NODE_EXTRA_CA_CERTS;\n if (Object.keys(env).length === 0) {\n delete settings.env;\n }\n this.log('Removed HTTPS_PROXY and NODE_EXTRA_CA_CERTS from .claude/settings.json');\n changed = true;\n }\n\n if (changed) {\n writeFileSync(configPath, JSON.stringify(settings, null, 2) + '\\n');\n } else {\n this.log('No hooks or proxy config found \u2014 nothing to uninstall.');\n }\n\n // Remove Cursor hooks\n // Remove Cursor and Copilot hooks\n if (removeCursorHooks(process.cwd())) {\n this.log('Removed RuleMetric hooks from .cursor/hooks.json');\n changed = true;\n }\n if (removeCursorUserHooks()) {\n this.log('Removed RuleMetric hooks from ~/.cursor/hooks.json');\n changed = true;\n }\n\n // Remove Cursor proxy config\n const cursorSettingsPath = join(process.cwd(), '.cursor', 'settings.json');\n if (existsSync(cursorSettingsPath)) {\n try {\n const cursorSettings = JSON.parse(readFileSync(cursorSettingsPath, 'utf-8'));\n if (cursorSettings['http.proxy']?.includes('localhost')) {\n delete cursorSettings['http.proxy'];\n delete cursorSettings['http.proxyStrictSSL'];\n writeFileSync(cursorSettingsPath, JSON.stringify(cursorSettings, null, 2) + '\\n');\n this.log('Removed proxy config from .cursor/settings.json');\n changed = true;\n }\n } catch { /* not valid JSON, skip */ }\n }\n\n // Remove Copilot hooks\n if (removeCopilotHooks(process.cwd())) {\n this.log('Removed RuleMetric hooks from .github/hooks/');\n changed = true;\n }\n\n // Remove Antigravity hooks (workspace + user)\n if (removeAntigravityHooks(process.cwd())) {\n this.log('Removed RuleMetric block from .agents/hooks.json');\n changed = true;\n }\n if (removeAntigravityUserHooks()) {\n this.log('Removed RuleMetric block from ~/.gemini/config/hooks.json');\n changed = true;\n }\n\n // Remove VS Code proxy config (workspace + user settings)\n if (removeVSCodeProxyConfig(process.cwd())) {\n this.log('Removed proxy config from .vscode/settings.json');\n changed = true;\n }\n if (removeVSCodeUserProxyConfig()) {\n this.log('Removed proxy config from VS Code user settings');\n changed = true;\n }\n if (removeCursorUserProxyConfig()) {\n this.log('Removed proxy config from Cursor user settings');\n changed = true;\n }\n\n // Remove macOS LaunchAgent + launchctl env vars\n if (uninstallMacOSProxyEnv()) {\n this.log('Removed HTTPS_PROXY LaunchAgent');\n changed = true;\n }\n\n // Stop gateway\n if (stopGateway()) {\n this.log('Gateway stopped.');\n }\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,YAAY;AAKrB,IAAqB,iBAArB,cAA4C,YAAY;AAAA,EACtD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,aAAa,KAAK,QAAQ,IAAI,GAAG,WAAW,eAAe;AAEjE,QAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,WAAK,IAAI,6DAAwD;AACjE;AAAA,IACF;AAEA,UAAM,WAAoC,KAAK,MAAM,aAAa,YAAY,OAAO,CAAC;AAEtF,QAAI,UAAU;AAGd,QAAI,SAAS,OAAO;AAClB,aAAO,SAAS;AAChB,WAAK,IAAI,0CAA0C;AACnD,gBAAU;AAAA,IACZ;AAGA,UAAM,MAAM,SAAS;AACrB,QAAI,KAAK,eAAe,KAAK,qBAAqB;AAChD,aAAO,IAAI;AACX,aAAO,IAAI;AACX,UAAI,OAAO,KAAK,GAAG,EAAE,WAAW,GAAG;AACjC,eAAO,SAAS;AAAA,MAClB;AACA,WAAK,IAAI,wEAAwE;AACjF,gBAAU;AAAA,IACZ;AAEA,QAAI,SAAS;AACX,oBAAc,YAAY,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAAA,IACpE,OAAO;AACL,WAAK,IAAI,6DAAwD;AAAA,IACnE;AAIA,QAAI,kBAAkB,QAAQ,IAAI,CAAC,GAAG;AACpC,WAAK,IAAI,kDAAkD;AAC3D,gBAAU;AAAA,IACZ;AACA,QAAI,sBAAsB,GAAG;AAC3B,WAAK,IAAI,oDAAoD;AAC7D,gBAAU;AAAA,IACZ;AAGA,UAAM,qBAAqB,KAAK,QAAQ,IAAI,GAAG,WAAW,eAAe;AACzE,QAAI,WAAW,kBAAkB,GAAG;AAClC,UAAI;AACF,cAAM,iBAAiB,KAAK,MAAM,aAAa,oBAAoB,OAAO,CAAC;AAC3E,YAAI,eAAe,YAAY,GAAG,SAAS,WAAW,GAAG;AACvD,iBAAO,eAAe,YAAY;AAClC,iBAAO,eAAe,qBAAqB;AAC3C,wBAAc,oBAAoB,KAAK,UAAU,gBAAgB,MAAM,CAAC,IAAI,IAAI;AAChF,eAAK,IAAI,iDAAiD;AAC1D,oBAAU;AAAA,QACZ;AAAA,MACF,QAAQ;AAAA,MAA6B;AAAA,IACvC;AAGA,QAAI,mBAAmB,QAAQ,IAAI,CAAC,GAAG;AACrC,WAAK,IAAI,8CAA8C;AACvD,gBAAU;AAAA,IACZ;AAGA,QAAI,uBAAuB,QAAQ,IAAI,CAAC,GAAG;AACzC,WAAK,IAAI,kDAAkD;AAC3D,gBAAU;AAAA,IACZ;AACA,QAAI,2BAA2B,GAAG;AAChC,WAAK,IAAI,2DAA2D;AACpE,gBAAU;AAAA,IACZ;AAGA,QAAI,wBAAwB,QAAQ,IAAI,CAAC,GAAG;AAC1C,WAAK,IAAI,iDAAiD;AAC1D,gBAAU;AAAA,IACZ;AACA,QAAI,4BAA4B,GAAG;AACjC,WAAK,IAAI,iDAAiD;AAC1D,gBAAU;AAAA,IACZ;AACA,QAAI,4BAA4B,GAAG;AACjC,WAAK,IAAI,gDAAgD;AACzD,gBAAU;AAAA,IACZ;AAGA,QAAI,uBAAuB,GAAG;AAC5B,WAAK,IAAI,iCAAiC;AAC1C,gBAAU;AAAA,IACZ;AAGA,QAAI,YAAY,GAAG;AACjB,WAAK,IAAI,kBAAkB;AAAA,IAC7B;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { BaseCommand } from '../../base-command.js';\nimport { stopGateway } from '../../lib/gateway-lifecycle.js';\nimport { removeClaudeCodeHooks, removeCursorHooks, removeCursorUserHooks, removeCopilotHooks, removeAntigravityHooks, removeAntigravityUserHooks, removeVSCodeProxyConfig, uninstallMacOSProxyEnv, removeVSCodeUserProxyConfig, removeCursorUserProxyConfig } from '../../lib/hooks-config.js';\n\nexport default class HooksUninstall extends BaseCommand {\n static override description = 'Remove session tracking hooks from the current project';\n\n static override examples = [\n '<%= config.bin %> hooks uninstall',\n ];\n\n async run(): Promise<void> {\n const configPath = join(process.cwd(), '.claude', 'settings.json');\n\n if (!existsSync(configPath)) {\n this.log('No .claude/settings.json found \u2014 nothing to uninstall.');\n return;\n }\n\n const settings: Record<string, unknown> = JSON.parse(readFileSync(configPath, 'utf-8'));\n\n let changed = false;\n\n // Remove only RuleMetric's hooks \u2014 preserve the user's own. The old wholesale\n // `delete settings.hooks` also nuked unrelated project hooks.\n if (removeClaudeCodeHooks(settings)) {\n this.log('Removed RuleMetric hooks from .claude/settings.json');\n changed = true;\n }\n\n // Remove gateway proxy env\n const env = settings.env as Record<string, string> | undefined;\n if (env?.HTTPS_PROXY || env?.NODE_EXTRA_CA_CERTS) {\n delete env.HTTPS_PROXY;\n delete env.NODE_EXTRA_CA_CERTS;\n if (Object.keys(env).length === 0) {\n delete settings.env;\n }\n this.log('Removed HTTPS_PROXY and NODE_EXTRA_CA_CERTS from .claude/settings.json');\n changed = true;\n }\n\n if (changed) {\n writeFileSync(configPath, JSON.stringify(settings, null, 2) + '\\n');\n } else {\n this.log('No hooks or proxy config found \u2014 nothing to uninstall.');\n }\n\n // Remove Cursor hooks\n // Remove Cursor and Copilot hooks\n if (removeCursorHooks(process.cwd())) {\n this.log('Removed RuleMetric hooks from .cursor/hooks.json');\n changed = true;\n }\n if (removeCursorUserHooks()) {\n this.log('Removed RuleMetric hooks from ~/.cursor/hooks.json');\n changed = true;\n }\n\n // Remove Cursor proxy config\n const cursorSettingsPath = join(process.cwd(), '.cursor', 'settings.json');\n if (existsSync(cursorSettingsPath)) {\n try {\n const cursorSettings = JSON.parse(readFileSync(cursorSettingsPath, 'utf-8'));\n if (cursorSettings['http.proxy']?.includes('localhost')) {\n delete cursorSettings['http.proxy'];\n delete cursorSettings['http.proxyStrictSSL'];\n writeFileSync(cursorSettingsPath, JSON.stringify(cursorSettings, null, 2) + '\\n');\n this.log('Removed proxy config from .cursor/settings.json');\n changed = true;\n }\n } catch { /* not valid JSON, skip */ }\n }\n\n // Remove Copilot hooks\n if (removeCopilotHooks(process.cwd())) {\n this.log('Removed RuleMetric hooks from .github/hooks/');\n changed = true;\n }\n\n // Remove Antigravity hooks (workspace + user)\n if (removeAntigravityHooks(process.cwd())) {\n this.log('Removed RuleMetric block from .agents/hooks.json');\n changed = true;\n }\n if (removeAntigravityUserHooks()) {\n this.log('Removed RuleMetric block from ~/.gemini/config/hooks.json');\n changed = true;\n }\n\n // Remove VS Code proxy config (workspace + user settings)\n if (removeVSCodeProxyConfig(process.cwd())) {\n this.log('Removed proxy config from .vscode/settings.json');\n changed = true;\n }\n if (removeVSCodeUserProxyConfig()) {\n this.log('Removed proxy config from VS Code user settings');\n changed = true;\n }\n if (removeCursorUserProxyConfig()) {\n this.log('Removed proxy config from Cursor user settings');\n changed = true;\n }\n\n // Remove macOS LaunchAgent + launchctl env vars\n if (uninstallMacOSProxyEnv()) {\n this.log('Removed HTTPS_PROXY LaunchAgent');\n changed = true;\n }\n\n // Stop gateway\n if (stopGateway()) {\n this.log('Gateway stopped.');\n }\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,YAAY;AAKrB,IAAqB,iBAArB,cAA4C,YAAY;AAAA,EACtD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,aAAa,KAAK,QAAQ,IAAI,GAAG,WAAW,eAAe;AAEjE,QAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,WAAK,IAAI,6DAAwD;AACjE;AAAA,IACF;AAEA,UAAM,WAAoC,KAAK,MAAM,aAAa,YAAY,OAAO,CAAC;AAEtF,QAAI,UAAU;AAId,QAAI,sBAAsB,QAAQ,GAAG;AACnC,WAAK,IAAI,qDAAqD;AAC9D,gBAAU;AAAA,IACZ;AAGA,UAAM,MAAM,SAAS;AACrB,QAAI,KAAK,eAAe,KAAK,qBAAqB;AAChD,aAAO,IAAI;AACX,aAAO,IAAI;AACX,UAAI,OAAO,KAAK,GAAG,EAAE,WAAW,GAAG;AACjC,eAAO,SAAS;AAAA,MAClB;AACA,WAAK,IAAI,wEAAwE;AACjF,gBAAU;AAAA,IACZ;AAEA,QAAI,SAAS;AACX,oBAAc,YAAY,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAAA,IACpE,OAAO;AACL,WAAK,IAAI,6DAAwD;AAAA,IACnE;AAIA,QAAI,kBAAkB,QAAQ,IAAI,CAAC,GAAG;AACpC,WAAK,IAAI,kDAAkD;AAC3D,gBAAU;AAAA,IACZ;AACA,QAAI,sBAAsB,GAAG;AAC3B,WAAK,IAAI,oDAAoD;AAC7D,gBAAU;AAAA,IACZ;AAGA,UAAM,qBAAqB,KAAK,QAAQ,IAAI,GAAG,WAAW,eAAe;AACzE,QAAI,WAAW,kBAAkB,GAAG;AAClC,UAAI;AACF,cAAM,iBAAiB,KAAK,MAAM,aAAa,oBAAoB,OAAO,CAAC;AAC3E,YAAI,eAAe,YAAY,GAAG,SAAS,WAAW,GAAG;AACvD,iBAAO,eAAe,YAAY;AAClC,iBAAO,eAAe,qBAAqB;AAC3C,wBAAc,oBAAoB,KAAK,UAAU,gBAAgB,MAAM,CAAC,IAAI,IAAI;AAChF,eAAK,IAAI,iDAAiD;AAC1D,oBAAU;AAAA,QACZ;AAAA,MACF,QAAQ;AAAA,MAA6B;AAAA,IACvC;AAGA,QAAI,mBAAmB,QAAQ,IAAI,CAAC,GAAG;AACrC,WAAK,IAAI,8CAA8C;AACvD,gBAAU;AAAA,IACZ;AAGA,QAAI,uBAAuB,QAAQ,IAAI,CAAC,GAAG;AACzC,WAAK,IAAI,kDAAkD;AAC3D,gBAAU;AAAA,IACZ;AACA,QAAI,2BAA2B,GAAG;AAChC,WAAK,IAAI,2DAA2D;AACpE,gBAAU;AAAA,IACZ;AAGA,QAAI,wBAAwB,QAAQ,IAAI,CAAC,GAAG;AAC1C,WAAK,IAAI,iDAAiD;AAC1D,gBAAU;AAAA,IACZ;AACA,QAAI,4BAA4B,GAAG;AACjC,WAAK,IAAI,iDAAiD;AAC1D,gBAAU;AAAA,IACZ;AACA,QAAI,4BAA4B,GAAG;AACjC,WAAK,IAAI,gDAAgD;AACzD,gBAAU;AAAA,IACZ;AAGA,QAAI,uBAAuB,GAAG;AAC5B,WAAK,IAAI,iCAAiC;AAC1C,gBAAU;AAAA,IACZ;AAGA,QAAI,YAAY,GAAG;AACjB,WAAK,IAAI,kBAAkB;AAAA,IAC7B;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../chunk-S56LOTGQ.js";
4
- import "../chunk-OGVORIFM.js";
3
+ } from "../chunk-7DIWBTB5.js";
4
+ import "../chunk-R56PH7YE.js";
5
5
  import "../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -3,8 +3,8 @@ import {
3
3
  } from "../../chunk-7NYKWN7U.js";
4
4
  import {
5
5
  BaseCommand
6
- } from "../../chunk-S56LOTGQ.js";
7
- import "../../chunk-OGVORIFM.js";
6
+ } from "../../chunk-7DIWBTB5.js";
7
+ import "../../chunk-R56PH7YE.js";
8
8
  import "../../chunk-2AM54TUK.js";
9
9
  import {
10
10
  apiDelete,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -7,8 +7,8 @@ import {
7
7
  } from "../../chunk-BZDKEQKU.js";
8
8
  import {
9
9
  BaseCommand
10
- } from "../../chunk-S56LOTGQ.js";
11
- import "../../chunk-OGVORIFM.js";
10
+ } from "../../chunk-7DIWBTB5.js";
11
+ import "../../chunk-R56PH7YE.js";
12
12
  import "../../chunk-2AM54TUK.js";
13
13
  import {
14
14
  apiGet
@@ -5,8 +5,8 @@ import {
5
5
  } from "../../chunk-BZDKEQKU.js";
6
6
  import {
7
7
  BaseCommand
8
- } from "../../chunk-S56LOTGQ.js";
9
- import "../../chunk-OGVORIFM.js";
8
+ } from "../../chunk-7DIWBTB5.js";
9
+ import "../../chunk-R56PH7YE.js";
10
10
  import "../../chunk-2AM54TUK.js";
11
11
  import {
12
12
  apiGet
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiGet
@@ -6,8 +6,8 @@ import {
6
6
  } from "../../chunk-BZDKEQKU.js";
7
7
  import {
8
8
  BaseCommand
9
- } from "../../chunk-S56LOTGQ.js";
10
- import "../../chunk-OGVORIFM.js";
9
+ } from "../../chunk-7DIWBTB5.js";
10
+ import "../../chunk-R56PH7YE.js";
11
11
  import "../../chunk-2AM54TUK.js";
12
12
  import {
13
13
  apiGet
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../chunk-S56LOTGQ.js";
4
- import "../chunk-OGVORIFM.js";
3
+ } from "../chunk-7DIWBTB5.js";
4
+ import "../chunk-R56PH7YE.js";
5
5
  import "../chunk-2AM54TUK.js";
6
6
  import "../chunk-EJOI2ZGU.js";
7
7
  import "../chunk-KZRFUXGF.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  ApiError,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiGet
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiGet,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BaseCommand
3
- } from "../../chunk-S56LOTGQ.js";
4
- import "../../chunk-OGVORIFM.js";
3
+ } from "../../chunk-7DIWBTB5.js";
4
+ import "../../chunk-R56PH7YE.js";
5
5
  import "../../chunk-2AM54TUK.js";
6
6
  import {
7
7
  apiPost