@chainpatrol/cli 0.6.0 → 0.8.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 (32) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/{breakdown-AX6QNTQH.js → breakdown-DXSN7KUF.js} +2 -2
  3. package/dist/{chunk-EEG7T6WT.js → chunk-EGWK6SRQ.js} +5 -0
  4. package/dist/{chunk-LLWKCA3H.js → chunk-F6D645LF.js} +19 -7
  5. package/dist/{chunk-EBJMOX3Q.js → chunk-PZV55KAR.js} +6 -1
  6. package/dist/{chunk-AGXMZFUU.js → chunk-XIHOCIYM.js} +1 -1
  7. package/dist/{chunk-XOXQPUR6.js → chunk-ZN3VMRWG.js} +191 -51
  8. package/dist/cli.js +34 -30
  9. package/dist/{configs-update-VROBC2HI.js → configs-update-BBENU2PG.js} +2 -2
  10. package/dist/{create-XTCUNT2C.js → create-SXPAFMPT.js} +2 -2
  11. package/dist/{drift-VOKQJ36G.js → drift-WJD2Z5ZB.js} +2 -2
  12. package/dist/{found-A5HRTJCJ.js → found-4UY3IC5T.js} +2 -2
  13. package/dist/{healthcheck-AQUXVKAO.js → healthcheck-XTQN64DB.js} +2 -2
  14. package/dist/{list-PLZ67PNY.js → list-2PBVBN5K.js} +2 -2
  15. package/dist/{list-5ENZAOFL.js → list-6ELSECNR.js} +2 -2
  16. package/dist/{list-EYRN5JYC.js → list-BGI7IZ55.js} +3 -3
  17. package/dist/{list-CVFXTKNX.js → list-BVUG6RUF.js} +2 -2
  18. package/dist/{list-CGRHTFAS.js → list-IJS66PYW.js} +2 -2
  19. package/dist/{list-json-LEKCCWQU.js → list-json-DWHMAA6S.js} +2 -2
  20. package/dist/{login-C66GRR3Y.js → login-AMEXCOGT.js} +11 -2
  21. package/dist/{login-json-XGMXT5VJ.js → login-json-MPLXCSP4.js} +2 -2
  22. package/dist/{login-plain-CWKOUZKE.js → login-plain-NIJDS3D2.js} +2 -2
  23. package/dist/{logout-LA7VEKON.js → logout-T6Q4IVPU.js} +10 -1
  24. package/dist/{logout-json-4GIJZJ46.js → logout-json-ACXBI6PN.js} +11 -1
  25. package/dist/{run-YHDUUP66.js → run-3W7LSPX2.js} +3 -3
  26. package/dist/{run-OT2X46GT.js → run-4S244KUM.js} +2 -2
  27. package/dist/{run-MS5SA5YL.js → run-M25F7TWI.js} +2 -2
  28. package/dist/{setup-skill-BTR2IZ4E.js → setup-skill-J7PZYVCE.js} +1 -1
  29. package/dist/{snapshot-4QR4I67P.js → snapshot-MEOOARL3.js} +2 -2
  30. package/dist/{summary-JOCABBCO.js → summary-JYDAPBYX.js} +2 -2
  31. package/dist/{validate-27RUCN7R.js → validate-RI7YKHKH.js} +2 -2
  32. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @chainpatrol/cli
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 11d074f: Support non-interactive authentication via the `CHAINPATROL_API_KEY` env
8
+ var. When set, the CLI sends it as the `x-api-key` header on API calls and
9
+ skips the device-code login flow entirely. `chainpatrol login` reports
10
+ "already authenticated via env var" instead of polling, and
11
+ `chainpatrol logout` refuses to no-op (it tells you to unset the env var).
12
+ Stored Better Auth bearer credentials are still used as a fallback when
13
+ the env var is unset. Headless service accounts (e.g. agent42) should mint
14
+ a USER-type API key via `/staff/api-keys` and set
15
+ `CHAINPATROL_API_KEY=cp_live_…` in their deployment env.
16
+
17
+ ## 0.7.0
18
+
19
+ ### Minor Changes
20
+
21
+ - c170343: Add `chainpatrol setup --cloud` flag that also installs a Claude Code
22
+ SessionStart hook at `~/.claude/hooks/chainpatrol-login.sh` and registers
23
+ it in `~/.claude/settings.json`. When the user has no chainpatrol
24
+ credentials, the hook emits SessionStart `additionalContext` so Claude
25
+ surfaces the device-code login URL on the first user turn — useful for
26
+ cloud Claude Code environments that can't run the interactive login from
27
+ a container startup script. The hook is a silent no-op once the user is
28
+ authenticated. Local installs (without `--cloud`) leave Claude Code
29
+ hooks untouched. `chainpatrol uninstall` always removes the hook if
30
+ present, without disturbing unrelated hooks or settings.
31
+
3
32
  ## 0.6.0
4
33
 
5
34
  ### Minor Changes
@@ -4,8 +4,8 @@ import {
4
4
  } from "./chunk-VFT3TD3E.js";
5
5
  import {
6
6
  createApiClient
7
- } from "./chunk-LLWKCA3H.js";
8
- import "./chunk-EEG7T6WT.js";
7
+ } from "./chunk-F6D645LF.js";
8
+ import "./chunk-EGWK6SRQ.js";
9
9
  import "./chunk-TFCNKBRC.js";
10
10
  import "./chunk-U73SABXK.js";
11
11
 
@@ -139,6 +139,7 @@ function clearCredentials() {
139
139
  }
140
140
  }
141
141
  function isLoggedIn() {
142
+ if (hasApiKeyEnv()) return true;
142
143
  try {
143
144
  getValidCredentials();
144
145
  return true;
@@ -146,6 +147,9 @@ function isLoggedIn() {
146
147
  return false;
147
148
  }
148
149
  }
150
+ function hasApiKeyEnv() {
151
+ return Boolean(process.env.CHAINPATROL_API_KEY?.trim());
152
+ }
149
153
  function getValidCredentials() {
150
154
  const creds = getCredentials();
151
155
  const expiresMs = new Date(creds.expiresAt).getTime();
@@ -280,6 +284,7 @@ export {
280
284
  storeCredentials,
281
285
  clearCredentials,
282
286
  isLoggedIn,
287
+ hasApiKeyEnv,
283
288
  getValidCredentials,
284
289
  fetchUserEmail,
285
290
  requestDeviceCode,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getValidCredentials
3
- } from "./chunk-EEG7T6WT.js";
3
+ } from "./chunk-EGWK6SRQ.js";
4
4
  import {
5
5
  DateTime
6
6
  } from "./chunk-TFCNKBRC.js";
@@ -18,20 +18,32 @@ function parseIsoDate(value) {
18
18
  return dt.toJSDate();
19
19
  }
20
20
  var REQUEST_TIMEOUT_MS = 3e4;
21
+ function defaultGetCredential() {
22
+ const envKey = process.env.CHAINPATROL_API_KEY;
23
+ if (envKey && envKey.trim().length > 0) {
24
+ return { kind: "api-key", value: envKey.trim() };
25
+ }
26
+ return { kind: "bearer", value: getValidCredentials().accessToken };
27
+ }
21
28
  function createApiClient(options) {
22
29
  const config = getConfig();
23
30
  const apiUrl = options?.apiUrl ?? config.apiUrl;
24
- const getToken = options?.getToken ?? (() => getValidCredentials().accessToken);
31
+ const getCredential = options?.getCredential ?? (options?.getToken ? () => ({ kind: "bearer", value: options.getToken() }) : defaultGetCredential);
25
32
  async function request(path, body) {
26
- const token = getToken();
33
+ const credential = getCredential();
34
+ const headers = {
35
+ "Content-Type": "application/json"
36
+ };
37
+ if (credential.kind === "api-key") {
38
+ headers["x-api-key"] = credential.value;
39
+ } else {
40
+ headers["Authorization"] = `Bearer ${credential.value}`;
41
+ }
27
42
  let res;
28
43
  try {
29
44
  res = await fetch(`${apiUrl}/api/v2${path}`, {
30
45
  method: "POST",
31
- headers: {
32
- "Content-Type": "application/json",
33
- Authorization: `Bearer ${token}`
34
- },
46
+ headers,
35
47
  body: JSON.stringify(body),
36
48
  signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
37
49
  });
@@ -1,17 +1,22 @@
1
1
  import {
2
2
  fetchUserEmail,
3
3
  getCredentials,
4
+ hasApiKeyEnv,
4
5
  isLoggedIn,
5
6
  pollForToken,
6
7
  requestDeviceCode,
7
8
  storeCredentials
8
- } from "./chunk-EEG7T6WT.js";
9
+ } from "./chunk-EGWK6SRQ.js";
9
10
  import {
10
11
  DateTime
11
12
  } from "./chunk-TFCNKBRC.js";
12
13
 
13
14
  // src/lib/login-flow.ts
14
15
  async function runLoginFlow(emit) {
16
+ if (hasApiKeyEnv()) {
17
+ emit({ type: "already_logged_in", email: null });
18
+ return true;
19
+ }
15
20
  if (isLoggedIn()) {
16
21
  const creds = getCredentials();
17
22
  emit({ type: "already_logged_in", email: creds.email ?? null });
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
11
+ } from "./chunk-F6D645LF.js";
12
12
  import {
13
13
  DateTime
14
14
  } from "./chunk-TFCNKBRC.js";
@@ -4,13 +4,125 @@ import {
4
4
  } from "./chunk-IUZB3DQW.js";
5
5
 
6
6
  // src/commands/setup-skill.ts
7
- import { mkdirSync, writeFileSync, existsSync, readFileSync as readFileSync2, rmSync } from "fs";
8
- import { join } from "path";
7
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, readFileSync as readFileSync3, rmSync } from "fs";
8
+ import { join as join2 } from "path";
9
+ import { homedir as homedir2 } from "os";
10
+
11
+ // src/commands/login-hook.ts
12
+ import { mkdirSync, writeFileSync, readFileSync, existsSync, unlinkSync } from "fs";
9
13
  import { homedir } from "os";
14
+ import { join, dirname } from "path";
15
+ var CLAUDE_DIR = join(homedir(), ".claude");
16
+ var HOOK_DIR = join(CLAUDE_DIR, "hooks");
17
+ var HOOK_FILE = join(HOOK_DIR, "chainpatrol-login.sh");
18
+ var SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
19
+ var HOOK_SCRIPT = `#!/bin/bash
20
+ # chainpatrol auto-login hook \u2014 installed by \`chainpatrol setup\`.
21
+ # On Claude Code session start, if the user has no chainpatrol credentials,
22
+ # emit additionalContext so Claude surfaces the device-code login URL on
23
+ # the first user turn. Safe to run repeatedly: no-ops once authenticated.
24
+ set -uo pipefail
25
+
26
+ CONFIG_DIR="\${CHAINPATROL_CONFIG_DIR:-$HOME/.chainpatrol}"
27
+ if [ -s "$CONFIG_DIR/credentials.json" ]; then
28
+ exit 0
29
+ fi
30
+
31
+ # Only nudge when the CLI is reachable \u2014 otherwise we'd ask Claude to run
32
+ # a command that isn't installed.
33
+ if ! command -v chainpatrol >/dev/null 2>&1 \\
34
+ && [ ! -x /usr/local/bin/chainpatrol ] \\
35
+ && ! ls /opt/node*/bin/chainpatrol >/dev/null 2>&1; then
36
+ exit 0
37
+ fi
38
+
39
+ cat <<'JSON'
40
+ {"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"chainpatrol auto-login: the user is not authenticated with ChainPatrol (no credentials.json found). If the user's task involves ChainPatrol or the chainpatrol CLI, start \`chainpatrol login\` in the background per the /chainpatrol skill's headless runbook (background + tail /tmp/cp-login.out) and surface the verification URL before doing anything else. If the user's task is unrelated, ignore this notice."}}
41
+ JSON
42
+ exit 0
43
+ `;
44
+ function installLoginHook() {
45
+ mkdirSync(HOOK_DIR, { recursive: true });
46
+ const hookWritten = !existsSync(HOOK_FILE) || readFileSync(HOOK_FILE, "utf-8") !== HOOK_SCRIPT;
47
+ if (hookWritten) {
48
+ writeFileSync(HOOK_FILE, HOOK_SCRIPT, { mode: 493 });
49
+ }
50
+ const settingsUpdated = registerHookInSettings();
51
+ return {
52
+ hookPath: HOOK_FILE,
53
+ hookWritten,
54
+ settingsPath: SETTINGS_FILE,
55
+ settingsUpdated
56
+ };
57
+ }
58
+ function uninstallLoginHook() {
59
+ let hookRemoved = false;
60
+ if (existsSync(HOOK_FILE)) {
61
+ unlinkSync(HOOK_FILE);
62
+ hookRemoved = true;
63
+ }
64
+ const settingsUpdated = unregisterHookFromSettings();
65
+ return { hookRemoved, settingsUpdated };
66
+ }
67
+ function readSettings() {
68
+ if (!existsSync(SETTINGS_FILE)) return {};
69
+ const raw = readFileSync(SETTINGS_FILE, "utf-8");
70
+ if (raw.trim() === "") return {};
71
+ return JSON.parse(raw);
72
+ }
73
+ function writeSettings(settings) {
74
+ mkdirSync(dirname(SETTINGS_FILE), { recursive: true });
75
+ writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2) + "\n", {
76
+ mode: 420
77
+ });
78
+ }
79
+ function hasHookEntry(settings) {
80
+ const matchers = settings.hooks?.SessionStart;
81
+ if (!Array.isArray(matchers)) return false;
82
+ return matchers.some(
83
+ (matcher) => Array.isArray(matcher?.hooks) && matcher.hooks.some((h) => h?.command === HOOK_FILE)
84
+ );
85
+ }
86
+ function registerHookInSettings() {
87
+ const settings = readSettings();
88
+ if (hasHookEntry(settings)) return false;
89
+ const hooks = settings.hooks ??= {};
90
+ const sessionStart = hooks.SessionStart ??= [];
91
+ sessionStart.push({
92
+ hooks: [{ type: "command", command: HOOK_FILE }]
93
+ });
94
+ writeSettings(settings);
95
+ return true;
96
+ }
97
+ function unregisterHookFromSettings() {
98
+ if (!existsSync(SETTINGS_FILE)) return false;
99
+ const settings = readSettings();
100
+ const sessionStart = settings.hooks?.SessionStart;
101
+ if (!Array.isArray(sessionStart)) return false;
102
+ let changed = false;
103
+ const filtered = sessionStart.map((matcher) => {
104
+ if (!Array.isArray(matcher?.hooks)) return matcher;
105
+ const remaining = matcher.hooks.filter((h) => h?.command !== HOOK_FILE);
106
+ if (remaining.length === matcher.hooks.length) return matcher;
107
+ changed = true;
108
+ return remaining.length > 0 ? { ...matcher, hooks: remaining } : null;
109
+ }).filter((m) => m !== null);
110
+ if (!changed) return false;
111
+ if (filtered.length === 0) {
112
+ delete settings.hooks.SessionStart;
113
+ if (Object.keys(settings.hooks).length === 0) {
114
+ delete settings.hooks;
115
+ }
116
+ } else {
117
+ settings.hooks.SessionStart = filtered;
118
+ }
119
+ writeSettings(settings);
120
+ return true;
121
+ }
10
122
 
11
123
  // src/lib/version.ts
12
- import { readFileSync } from "fs";
13
- import { dirname, resolve } from "path";
124
+ import { readFileSync as readFileSync2 } from "fs";
125
+ import { dirname as dirname2, resolve } from "path";
14
126
  import { fileURLToPath } from "url";
15
127
  var PACKAGE_NAME = "@chainpatrol/cli";
16
128
  var cached;
@@ -21,7 +133,7 @@ function getCliVersion() {
21
133
  }
22
134
  function resolveCliVersion() {
23
135
  try {
24
- const here = dirname(fileURLToPath(import.meta.url));
136
+ const here = dirname2(fileURLToPath(import.meta.url));
25
137
  const candidates = [
26
138
  resolve(here, "..", "package.json"),
27
139
  resolve(here, "..", "..", "package.json")
@@ -36,7 +148,7 @@ function resolveCliVersion() {
36
148
  }
37
149
  function tryReadVersion(path) {
38
150
  try {
39
- const raw = readFileSync(path, "utf-8");
151
+ const raw = readFileSync2(path, "utf-8");
40
152
  const pkg = JSON.parse(raw);
41
153
  if (pkg.name === PACKAGE_NAME && typeof pkg.version === "string") {
42
154
  return pkg.version;
@@ -66,8 +178,8 @@ function compareVersions(a, b) {
66
178
  }
67
179
 
68
180
  // src/commands/setup-skill.ts
69
- var SKILL_DIR = join(homedir(), ".claude", "skills", "chainpatrol");
70
- var SKILL_FILE = join(SKILL_DIR, "SKILL.md");
181
+ var SKILL_DIR = join2(homedir2(), ".claude", "skills", "chainpatrol");
182
+ var SKILL_FILE = join2(SKILL_DIR, "SKILL.md");
71
183
  function buildSkillContent(version) {
72
184
  return `---
73
185
  name: chainpatrol
@@ -971,16 +1083,16 @@ function getBundledSkillContent() {
971
1083
  return buildSkillContent(getCliVersion());
972
1084
  }
973
1085
  function readInstalledSkillVersion() {
974
- if (!existsSync(SKILL_FILE)) return void 0;
1086
+ if (!existsSync2(SKILL_FILE)) return void 0;
975
1087
  try {
976
- const raw = readFileSync2(SKILL_FILE, "utf-8");
1088
+ const raw = readFileSync3(SKILL_FILE, "utf-8");
977
1089
  return parseSkillVersion(raw);
978
1090
  } catch {
979
1091
  return void 0;
980
1092
  }
981
1093
  }
982
1094
  function isSkillInstalled() {
983
- return existsSync(SKILL_FILE);
1095
+ return existsSync2(SKILL_FILE);
984
1096
  }
985
1097
  function parseSkillVersion(content) {
986
1098
  const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
@@ -1001,66 +1113,94 @@ var LOGO = `
1001
1113
  `;
1002
1114
  function setupSkill(options) {
1003
1115
  const skillContent = buildSkillContent(getCliVersion());
1004
- const alreadyExists = existsSync(SKILL_FILE);
1005
- if (alreadyExists) {
1006
- const existing = readFileSync2(SKILL_FILE, "utf-8");
1007
- if (existing === skillContent) {
1008
- if (options.json) {
1009
- console.log(JSON.stringify({ status: "up-to-date", path: SKILL_FILE }));
1010
- } else {
1011
- console.log("Claude Code skill is already up to date.");
1012
- }
1013
- return;
1014
- }
1116
+ const skillAlreadyExists = existsSync2(SKILL_FILE);
1117
+ const skillUpToDate = skillAlreadyExists && readFileSync3(SKILL_FILE, "utf-8") === skillContent;
1118
+ let skillStatus;
1119
+ if (!skillAlreadyExists) {
1120
+ mkdirSync2(SKILL_DIR, { recursive: true });
1121
+ writeFileSync2(SKILL_FILE, skillContent, { mode: 420 });
1122
+ skillStatus = "installed";
1123
+ } else if (!skillUpToDate) {
1124
+ writeFileSync2(SKILL_FILE, skillContent, { mode: 420 });
1125
+ skillStatus = "updated";
1126
+ } else {
1127
+ skillStatus = "up-to-date";
1015
1128
  }
1016
- mkdirSync(SKILL_DIR, { recursive: true });
1017
- writeFileSync(SKILL_FILE, skillContent, { mode: 420 });
1018
1129
  const completionResult = installCompletions();
1130
+ const loginHookResult = options.cloud ? installLoginHook() : null;
1131
+ const completionsChanged = completionResult.installed || completionResult.configuredShellRc;
1132
+ const loginHookChanged = loginHookResult != null && (loginHookResult.hookWritten || loginHookResult.settingsUpdated);
1133
+ const overallStatus = skillStatus !== "up-to-date" ? skillStatus : completionsChanged || loginHookChanged ? "updated" : "up-to-date";
1019
1134
  if (options.json) {
1020
1135
  console.log(
1021
1136
  JSON.stringify({
1022
- status: alreadyExists ? "updated" : "installed",
1137
+ status: overallStatus,
1023
1138
  path: SKILL_FILE,
1024
- completions: completionResult
1139
+ skill: { status: skillStatus, path: SKILL_FILE },
1140
+ completions: completionResult,
1141
+ loginHook: loginHookResult
1025
1142
  })
1026
1143
  );
1027
- } else {
1028
- console.log(LOGO);
1144
+ return;
1145
+ }
1146
+ if (overallStatus === "up-to-date") {
1147
+ console.log("Claude Code skill, completions, and login hook are already up to date.");
1148
+ return;
1149
+ }
1150
+ console.log(LOGO);
1151
+ if (skillStatus === "installed") {
1152
+ console.log(`Installed Claude Code skill at ${SKILL_FILE}`);
1153
+ } else if (skillStatus === "updated") {
1154
+ console.log(`Updated Claude Code skill at ${SKILL_FILE}`);
1155
+ }
1156
+ console.log("You can now use /chainpatrol in Claude Code from any project.");
1157
+ if (loginHookChanged && loginHookResult) {
1158
+ console.log(`Installed auto-login hook at ${loginHookResult.hookPath}`);
1159
+ if (loginHookResult.settingsUpdated) {
1160
+ console.log(`Registered SessionStart hook in ${loginHookResult.settingsPath}`);
1161
+ }
1162
+ }
1163
+ if (completionResult.installed) {
1029
1164
  console.log(
1030
- alreadyExists ? `Updated Claude Code skill at ${SKILL_FILE}` : `Installed Claude Code skill at ${SKILL_FILE}`
1165
+ `Installed ${completionResult.shell} completions at ${completionResult.path}`
1031
1166
  );
1032
- console.log("You can now use /chainpatrol in Claude Code from any project.");
1033
- if (completionResult.installed) {
1034
- console.log(
1035
- `Installed ${completionResult.shell} completions at ${completionResult.path}`
1036
- );
1037
- if (completionResult.configuredShellRc) {
1038
- console.log("Added completion config to ~/.zshrc");
1039
- }
1040
- console.log('Run "exec zsh" or open a new terminal to enable tab completion.');
1167
+ if (completionResult.configuredShellRc) {
1168
+ console.log("Added completion config to ~/.zshrc");
1041
1169
  }
1170
+ console.log('Run "exec zsh" or open a new terminal to enable tab completion.');
1042
1171
  }
1043
1172
  }
1044
1173
  function uninstallSkill(options) {
1045
- if (!existsSync(SKILL_FILE)) {
1046
- if (options.json) {
1047
- console.log(JSON.stringify({ status: "not-installed" }));
1048
- } else {
1049
- console.log("Claude Code skill is not installed.");
1050
- }
1051
- return;
1174
+ const skillInstalled = existsSync2(SKILL_FILE);
1175
+ if (skillInstalled) {
1176
+ rmSync(SKILL_DIR, { recursive: true });
1052
1177
  }
1053
- rmSync(SKILL_DIR, { recursive: true });
1054
1178
  const removedCompletions = uninstallCompletions();
1179
+ const loginHookResult = uninstallLoginHook();
1180
+ const removedAnything = skillInstalled || removedCompletions || loginHookResult.hookRemoved || loginHookResult.settingsUpdated;
1055
1181
  if (options.json) {
1056
1182
  console.log(
1057
- JSON.stringify({ status: "uninstalled", path: SKILL_FILE, removedCompletions })
1183
+ JSON.stringify({
1184
+ status: removedAnything ? "uninstalled" : "not-installed",
1185
+ path: SKILL_FILE,
1186
+ removedCompletions,
1187
+ loginHook: loginHookResult
1188
+ })
1058
1189
  );
1059
- } else {
1190
+ return;
1191
+ }
1192
+ if (!removedAnything) {
1193
+ console.log("Claude Code skill is not installed.");
1194
+ return;
1195
+ }
1196
+ if (skillInstalled) {
1060
1197
  console.log("Removed Claude Code skill from " + SKILL_DIR);
1061
- if (removedCompletions) {
1062
- console.log("Removed shell completions.");
1063
- }
1198
+ }
1199
+ if (loginHookResult.hookRemoved || loginHookResult.settingsUpdated) {
1200
+ console.log("Removed chainpatrol auto-login hook.");
1201
+ }
1202
+ if (removedCompletions) {
1203
+ console.log("Removed shell completions.");
1064
1204
  }
1065
1205
  }
1066
1206
 
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  getCliVersion,
14
14
  isSkillInstalled,
15
15
  readInstalledSkillVersion
16
- } from "./chunk-XOXQPUR6.js";
16
+ } from "./chunk-ZN3VMRWG.js";
17
17
  import "./chunk-IUZB3DQW.js";
18
18
  import {
19
19
  DateTime
@@ -354,7 +354,10 @@ var HELP = {
354
354
  },
355
355
  setup: {
356
356
  description: "Install Claude Code skill and shell completions.",
357
- usage: "chainpatrol setup"
357
+ usage: "chainpatrol setup [--cloud]",
358
+ options: [
359
+ "--cloud Also install a SessionStart hook that surfaces the device-code login URL when the user is not authenticated. Intended for Claude Code cloud / headless environments; omit for local installs."
360
+ ]
358
361
  },
359
362
  uninstall: {
360
363
  description: "Remove Claude Code skill and shell completions.",
@@ -651,7 +654,8 @@ ${getTopLevelHelp()}
651
654
  version: { type: "boolean", shortFlag: "V" },
652
655
  quiet: { type: "boolean", default: false, shortFlag: "q" },
653
656
  noInput: { type: "boolean", default: false },
654
- noColor: { type: "boolean", default: false }
657
+ noColor: { type: "boolean", default: false },
658
+ cloud: { type: "boolean", default: false }
655
659
  }
656
660
  });
657
661
  var [command, subcommand, action] = cli.input;
@@ -750,12 +754,12 @@ function parseAttachmentUrls() {
750
754
  }
751
755
  async function handleConfigsList(org) {
752
756
  if (jsonMode) {
753
- const { listConfigsJson } = await import("./list-json-LEKCCWQU.js");
757
+ const { listConfigsJson } = await import("./list-json-DWHMAA6S.js");
754
758
  await listConfigsJson({ org });
755
759
  return;
756
760
  }
757
761
  const { render } = await import("ink");
758
- const { default: ConfigsList } = await import("./list-5ENZAOFL.js");
762
+ const { default: ConfigsList } = await import("./list-6ELSECNR.js");
759
763
  const { default: React } = await import("react");
760
764
  render(React.createElement(ConfigsList, { org }));
761
765
  }
@@ -810,14 +814,14 @@ async function main() {
810
814
  );
811
815
  }
812
816
  if (jsonMode) {
813
- const { loginJson } = await import("./login-json-XGMXT5VJ.js");
817
+ const { loginJson } = await import("./login-json-MPLXCSP4.js");
814
818
  await loginJson();
815
819
  } else if (!process.stdout.isTTY) {
816
- const { loginPlain } = await import("./login-plain-CWKOUZKE.js");
820
+ const { loginPlain } = await import("./login-plain-NIJDS3D2.js");
817
821
  await loginPlain();
818
822
  } else {
819
823
  const { render } = await import("ink");
820
- const { default: Login } = await import("./login-C66GRR3Y.js");
824
+ const { default: Login } = await import("./login-AMEXCOGT.js");
821
825
  const { default: React } = await import("react");
822
826
  render(React.createElement(Login));
823
827
  }
@@ -825,11 +829,11 @@ async function main() {
825
829
  }
826
830
  case "logout": {
827
831
  if (jsonMode) {
828
- const { logoutJson } = await import("./logout-json-4GIJZJ46.js");
832
+ const { logoutJson } = await import("./logout-json-ACXBI6PN.js");
829
833
  await logoutJson();
830
834
  } else {
831
835
  const { render } = await import("ink");
832
- const { default: Logout } = await import("./logout-LA7VEKON.js");
836
+ const { default: Logout } = await import("./logout-T6Q4IVPU.js");
833
837
  const { default: React } = await import("react");
834
838
  render(React.createElement(Logout));
835
839
  }
@@ -853,7 +857,7 @@ async function main() {
853
857
  case "detections": {
854
858
  const org = await resolveOrg();
855
859
  if (subcommand === "healthcheck") {
856
- const { runDetectionsHealthcheck } = await import("./healthcheck-AQUXVKAO.js");
860
+ const { runDetectionsHealthcheck } = await import("./healthcheck-XTQN64DB.js");
857
861
  await runDetectionsHealthcheck({
858
862
  org,
859
863
  source: cli.flags.source,
@@ -868,7 +872,7 @@ async function main() {
868
872
  break;
869
873
  }
870
874
  if (subcommand === "validate") {
871
- const { runDetectionsValidate } = await import("./validate-27RUCN7R.js");
875
+ const { runDetectionsValidate } = await import("./validate-RI7YKHKH.js");
872
876
  await runDetectionsValidate({
873
877
  org,
874
878
  source: cli.flags.source,
@@ -883,7 +887,7 @@ async function main() {
883
887
  break;
884
888
  }
885
889
  if (subcommand === "drift") {
886
- const { runDetectionsDrift } = await import("./drift-VOKQJ36G.js");
890
+ const { runDetectionsDrift } = await import("./drift-WJD2Z5ZB.js");
887
891
  await runDetectionsDrift({
888
892
  org,
889
893
  source: cli.flags.source,
@@ -897,7 +901,7 @@ async function main() {
897
901
  break;
898
902
  }
899
903
  if (subcommand === "run") {
900
- const { runDetectionsRun } = await import("./run-OT2X46GT.js");
904
+ const { runDetectionsRun } = await import("./run-4S244KUM.js");
901
905
  await runDetectionsRun({
902
906
  org,
903
907
  configId: cli.flags.configId,
@@ -916,7 +920,7 @@ async function main() {
916
920
  break;
917
921
  }
918
922
  if (action === "run") {
919
- const { runDetectionsRun } = await import("./run-OT2X46GT.js");
923
+ const { runDetectionsRun } = await import("./run-4S244KUM.js");
920
924
  await runDetectionsRun({
921
925
  org,
922
926
  configId: cli.flags.configId,
@@ -934,7 +938,7 @@ async function main() {
934
938
  throw new Error("detections configs update requires --config-id");
935
939
  }
936
940
  const configPatch = getConfigPatchFromSetFlags();
937
- const { runDetectionsConfigsUpdate } = await import("./configs-update-VROBC2HI.js");
941
+ const { runDetectionsConfigsUpdate } = await import("./configs-update-BBENU2PG.js");
938
942
  await runDetectionsConfigsUpdate({
939
943
  org,
940
944
  configId: cli.flags.configId,
@@ -961,7 +965,7 @@ async function main() {
961
965
  case "metrics": {
962
966
  const org = await resolveOrg();
963
967
  if (subcommand === "summary") {
964
- const { runMetricsSummary } = await import("./summary-JOCABBCO.js");
968
+ const { runMetricsSummary } = await import("./summary-JYDAPBYX.js");
965
969
  await runMetricsSummary({
966
970
  org,
967
971
  from: cli.flags.from,
@@ -973,7 +977,7 @@ async function main() {
973
977
  break;
974
978
  }
975
979
  if (subcommand === "found") {
976
- const { runMetricsFound } = await import("./found-A5HRTJCJ.js");
980
+ const { runMetricsFound } = await import("./found-4UY3IC5T.js");
977
981
  await runMetricsFound({
978
982
  org,
979
983
  from: cli.flags.from,
@@ -990,7 +994,7 @@ async function main() {
990
994
  if (!by || !["day", "type", "brand"].includes(by)) {
991
995
  throw new Error("metrics breakdown requires --by <day|type|brand>");
992
996
  }
993
- const { runMetricsBreakdown } = await import("./breakdown-AX6QNTQH.js");
997
+ const { runMetricsBreakdown } = await import("./breakdown-DXSN7KUF.js");
994
998
  await runMetricsBreakdown({
995
999
  org,
996
1000
  by,
@@ -1010,7 +1014,7 @@ async function main() {
1010
1014
  case "reports": {
1011
1015
  if (subcommand === "list") {
1012
1016
  const org = await resolveOrg();
1013
- const { runReportsList } = await import("./list-CVFXTKNX.js");
1017
+ const { runReportsList } = await import("./list-BVUG6RUF.js");
1014
1018
  await runReportsList({
1015
1019
  org,
1016
1020
  limit: cli.flags.limit,
@@ -1026,7 +1030,7 @@ async function main() {
1026
1030
  }
1027
1031
  if (subcommand === "create") {
1028
1032
  const org = await tryResolveOrg();
1029
- const { runReportsCreate } = await import("./create-XTCUNT2C.js");
1033
+ const { runReportsCreate } = await import("./create-SXPAFMPT.js");
1030
1034
  await runReportsCreate({
1031
1035
  org,
1032
1036
  title: cli.flags.title,
@@ -1050,7 +1054,7 @@ async function main() {
1050
1054
  }
1051
1055
  case "queues": {
1052
1056
  if (subcommand === "snapshot") {
1053
- const { runQueuesSnapshot } = await import("./snapshot-4QR4I67P.js");
1057
+ const { runQueuesSnapshot } = await import("./snapshot-MEOOARL3.js");
1054
1058
  await runQueuesSnapshot({
1055
1059
  org: cli.flags.org,
1056
1060
  all: cli.flags.all,
@@ -1068,7 +1072,7 @@ async function main() {
1068
1072
  }
1069
1073
  case "orgs": {
1070
1074
  if (subcommand === "list") {
1071
- const { runOrgsList } = await import("./list-CGRHTFAS.js");
1075
+ const { runOrgsList } = await import("./list-IJS66PYW.js");
1072
1076
  await runOrgsList({
1073
1077
  query: cli.flags.query,
1074
1078
  subscriptionStatus: cli.flags.subscriptionStatus,
@@ -1088,7 +1092,7 @@ async function main() {
1088
1092
  }
1089
1093
  case "healthchecks": {
1090
1094
  if (subcommand === "list") {
1091
- const { runHealthchecksList } = await import("./list-PLZ67PNY.js");
1095
+ const { runHealthchecksList } = await import("./list-2PBVBN5K.js");
1092
1096
  await runHealthchecksList({
1093
1097
  json: jsonMode,
1094
1098
  outputFormat: cliContext.outputFormat
@@ -1102,7 +1106,7 @@ async function main() {
1102
1106
  thresholds.minResults = cli.flags.minResults;
1103
1107
  if (cli.flags.lookbackHours !== void 0)
1104
1108
  thresholds.lookbackHours = cli.flags.lookbackHours;
1105
- const { runHealthchecksRun } = await import("./run-MS5SA5YL.js");
1109
+ const { runHealthchecksRun } = await import("./run-M25F7TWI.js");
1106
1110
  await runHealthchecksRun({
1107
1111
  org,
1108
1112
  id: action,
@@ -1120,7 +1124,7 @@ async function main() {
1120
1124
  }
1121
1125
  case "presets": {
1122
1126
  if (subcommand === "list") {
1123
- const { runPresetsList } = await import("./list-EYRN5JYC.js");
1127
+ const { runPresetsList } = await import("./list-BGI7IZ55.js");
1124
1128
  await runPresetsList({ outputFormat: cliContext.outputFormat });
1125
1129
  break;
1126
1130
  }
@@ -1131,7 +1135,7 @@ async function main() {
1131
1135
  );
1132
1136
  }
1133
1137
  const org = await resolveOrg();
1134
- const { runPresetsRun } = await import("./run-YHDUUP66.js");
1138
+ const { runPresetsRun } = await import("./run-3W7LSPX2.js");
1135
1139
  await runPresetsRun({
1136
1140
  presetId: action,
1137
1141
  org,
@@ -1148,12 +1152,12 @@ async function main() {
1148
1152
  case "setup":
1149
1153
  case "install":
1150
1154
  case "i": {
1151
- const { setupSkill } = await import("./setup-skill-BTR2IZ4E.js");
1152
- setupSkill({ json: jsonMode });
1155
+ const { setupSkill } = await import("./setup-skill-J7PZYVCE.js");
1156
+ setupSkill({ json: jsonMode, cloud: cli.flags.cloud });
1153
1157
  break;
1154
1158
  }
1155
1159
  case "uninstall": {
1156
- const { uninstallSkill } = await import("./setup-skill-BTR2IZ4E.js");
1160
+ const { uninstallSkill } = await import("./setup-skill-J7PZYVCE.js");
1157
1161
  uninstallSkill({ json: jsonMode });
1158
1162
  break;
1159
1163
  }
@@ -7,8 +7,8 @@ import {
7
7
  } from "./chunk-VFT3TD3E.js";
8
8
  import {
9
9
  createApiClient
10
- } from "./chunk-LLWKCA3H.js";
11
- import "./chunk-EEG7T6WT.js";
10
+ } from "./chunk-F6D645LF.js";
11
+ import "./chunk-EGWK6SRQ.js";
12
12
  import "./chunk-TFCNKBRC.js";
13
13
  import "./chunk-U73SABXK.js";
14
14
 
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -4,8 +4,8 @@ import {
4
4
  } from "./chunk-VFT3TD3E.js";
5
5
  import {
6
6
  createApiClient
7
- } from "./chunk-LLWKCA3H.js";
8
- import "./chunk-EEG7T6WT.js";
7
+ } from "./chunk-F6D645LF.js";
8
+ import "./chunk-EGWK6SRQ.js";
9
9
  import {
10
10
  DateTime
11
11
  } from "./chunk-TFCNKBRC.js";
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -4,8 +4,8 @@ import {
4
4
  } from "./chunk-VFT3TD3E.js";
5
5
  import {
6
6
  createApiClient
7
- } from "./chunk-LLWKCA3H.js";
8
- import "./chunk-EEG7T6WT.js";
7
+ } from "./chunk-F6D645LF.js";
8
+ import "./chunk-EGWK6SRQ.js";
9
9
  import "./chunk-TFCNKBRC.js";
10
10
  import "./chunk-U73SABXK.js";
11
11
 
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-JCMWDZYY.js";
5
5
  import {
6
6
  createApiClient
7
- } from "./chunk-LLWKCA3H.js";
7
+ } from "./chunk-F6D645LF.js";
8
8
  import {
9
9
  AuthCorruptedError,
10
10
  AuthExpiredError,
11
11
  AuthNotLoggedInError
12
- } from "./chunk-EEG7T6WT.js";
12
+ } from "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  PRESETS
3
- } from "./chunk-AGXMZFUU.js";
3
+ } from "./chunk-XIHOCIYM.js";
4
4
  import "./chunk-E2LAMILJ.js";
5
5
  import {
6
6
  printOutput,
7
7
  toCsvRows
8
8
  } from "./chunk-VFT3TD3E.js";
9
- import "./chunk-LLWKCA3H.js";
10
- import "./chunk-EEG7T6WT.js";
9
+ import "./chunk-F6D645LF.js";
10
+ import "./chunk-EGWK6SRQ.js";
11
11
  import "./chunk-TFCNKBRC.js";
12
12
  import "./chunk-U73SABXK.js";
13
13
 
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createApiClient
3
- } from "./chunk-LLWKCA3H.js";
4
- import "./chunk-EEG7T6WT.js";
3
+ } from "./chunk-F6D645LF.js";
4
+ import "./chunk-EGWK6SRQ.js";
5
5
  import "./chunk-TFCNKBRC.js";
6
6
  import "./chunk-U73SABXK.js";
7
7
 
@@ -5,15 +5,16 @@ import {
5
5
  import {
6
6
  formatUserCode,
7
7
  isHeadlessEnv
8
- } from "./chunk-EBJMOX3Q.js";
8
+ } from "./chunk-PZV55KAR.js";
9
9
  import {
10
10
  fetchUserEmail,
11
11
  getCredentials,
12
+ hasApiKeyEnv,
12
13
  isLoggedIn,
13
14
  pollForToken,
14
15
  requestDeviceCode,
15
16
  storeCredentials
16
- } from "./chunk-EEG7T6WT.js";
17
+ } from "./chunk-EGWK6SRQ.js";
17
18
  import "./chunk-TFCNKBRC.js";
18
19
  import "./chunk-U73SABXK.js";
19
20
 
@@ -26,6 +27,14 @@ function Login() {
26
27
  const { exit } = useApp();
27
28
  const [state, setState] = useState({ phase: "checking" });
28
29
  useEffect(() => {
30
+ if (hasApiKeyEnv()) {
31
+ setState({
32
+ phase: "already-logged-in",
33
+ email: "(authenticated via CHAINPATROL_API_KEY)"
34
+ });
35
+ setTimeout(() => exit(), 100);
36
+ return;
37
+ }
29
38
  if (isLoggedIn()) {
30
39
  const creds = getCredentials();
31
40
  if (creds.email) {
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  isHeadlessEnv,
3
3
  runLoginFlow
4
- } from "./chunk-EBJMOX3Q.js";
5
- import "./chunk-EEG7T6WT.js";
4
+ } from "./chunk-PZV55KAR.js";
5
+ import "./chunk-EGWK6SRQ.js";
6
6
  import "./chunk-TFCNKBRC.js";
7
7
  import "./chunk-U73SABXK.js";
8
8
 
@@ -2,8 +2,8 @@ import {
2
2
  formatUserCode,
3
3
  isHeadlessEnv,
4
4
  runLoginFlow
5
- } from "./chunk-EBJMOX3Q.js";
6
- import "./chunk-EEG7T6WT.js";
5
+ } from "./chunk-PZV55KAR.js";
6
+ import "./chunk-EGWK6SRQ.js";
7
7
  import "./chunk-TFCNKBRC.js";
8
8
  import "./chunk-U73SABXK.js";
9
9
 
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  clearCredentials,
3
+ hasApiKeyEnv,
3
4
  isLoggedIn
4
- } from "./chunk-EEG7T6WT.js";
5
+ } from "./chunk-EGWK6SRQ.js";
5
6
  import "./chunk-U73SABXK.js";
6
7
 
7
8
  // src/commands/logout.tsx
@@ -9,6 +10,14 @@ import { Text, useApp } from "ink";
9
10
  import { jsx, jsxs } from "react/jsx-runtime";
10
11
  function Logout() {
11
12
  const { exit } = useApp();
13
+ if (hasApiKeyEnv()) {
14
+ setTimeout(() => exit(), 100);
15
+ return /* @__PURE__ */ jsxs(Text, { children: [
16
+ "Authenticated via ",
17
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "CHAINPATROL_API_KEY" }),
18
+ "; unset the env var to log out."
19
+ ] });
20
+ }
12
21
  if (!isLoggedIn()) {
13
22
  setTimeout(() => exit(), 100);
14
23
  return /* @__PURE__ */ jsx(Text, { children: "Not currently logged in." });
@@ -1,11 +1,21 @@
1
1
  import {
2
2
  clearCredentials,
3
+ hasApiKeyEnv,
3
4
  isLoggedIn
4
- } from "./chunk-EEG7T6WT.js";
5
+ } from "./chunk-EGWK6SRQ.js";
5
6
  import "./chunk-U73SABXK.js";
6
7
 
7
8
  // src/commands/logout-json.ts
8
9
  async function logoutJson() {
10
+ if (hasApiKeyEnv()) {
11
+ console.log(
12
+ JSON.stringify({
13
+ status: "api_key_env_active",
14
+ message: "Authenticated via CHAINPATROL_API_KEY; unset the env var to log out."
15
+ })
16
+ );
17
+ return;
18
+ }
9
19
  if (!isLoggedIn()) {
10
20
  console.log(JSON.stringify({ status: "not_logged_in" }));
11
21
  return;
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  getPresetDefinition,
3
3
  runPreset
4
- } from "./chunk-AGXMZFUU.js";
4
+ } from "./chunk-XIHOCIYM.js";
5
5
  import {
6
6
  CliExitError,
7
7
  ExitCode
8
8
  } from "./chunk-E2LAMILJ.js";
9
9
  import "./chunk-VFT3TD3E.js";
10
- import "./chunk-LLWKCA3H.js";
11
- import "./chunk-EEG7T6WT.js";
10
+ import "./chunk-F6D645LF.js";
11
+ import "./chunk-EGWK6SRQ.js";
12
12
  import "./chunk-TFCNKBRC.js";
13
13
  import "./chunk-U73SABXK.js";
14
14
 
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -6,7 +6,7 @@ import {
6
6
  readInstalledSkillVersion,
7
7
  setupSkill,
8
8
  uninstallSkill
9
- } from "./chunk-XOXQPUR6.js";
9
+ } from "./chunk-ZN3VMRWG.js";
10
10
  import "./chunk-IUZB3DQW.js";
11
11
  export {
12
12
  getBundledSkillContent,
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
@@ -4,8 +4,8 @@ import {
4
4
  } from "./chunk-VFT3TD3E.js";
5
5
  import {
6
6
  createApiClient
7
- } from "./chunk-LLWKCA3H.js";
8
- import "./chunk-EEG7T6WT.js";
7
+ } from "./chunk-F6D645LF.js";
8
+ import "./chunk-EGWK6SRQ.js";
9
9
  import "./chunk-TFCNKBRC.js";
10
10
  import "./chunk-U73SABXK.js";
11
11
 
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-LLWKCA3H.js";
12
- import "./chunk-EEG7T6WT.js";
11
+ } from "./chunk-F6D645LF.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
15
15
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@chainpatrol/cli",
3
3
  "description": "The official ChainPatrol CLI — terminal interface for threat detection",
4
4
  "author": "Umar Ahmed <umar@chainpatrol.io>",
5
- "version": "0.6.0",
5
+ "version": "0.8.0",
6
6
  "license": "UNLICENSED",
7
7
  "homepage": "https://chainpatrol.com/docs/cli",
8
8
  "keywords": [