@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.
- package/CHANGELOG.md +29 -0
- package/dist/{breakdown-AX6QNTQH.js → breakdown-DXSN7KUF.js} +2 -2
- package/dist/{chunk-EEG7T6WT.js → chunk-EGWK6SRQ.js} +5 -0
- package/dist/{chunk-LLWKCA3H.js → chunk-F6D645LF.js} +19 -7
- package/dist/{chunk-EBJMOX3Q.js → chunk-PZV55KAR.js} +6 -1
- package/dist/{chunk-AGXMZFUU.js → chunk-XIHOCIYM.js} +1 -1
- package/dist/{chunk-XOXQPUR6.js → chunk-ZN3VMRWG.js} +191 -51
- package/dist/cli.js +34 -30
- package/dist/{configs-update-VROBC2HI.js → configs-update-BBENU2PG.js} +2 -2
- package/dist/{create-XTCUNT2C.js → create-SXPAFMPT.js} +2 -2
- package/dist/{drift-VOKQJ36G.js → drift-WJD2Z5ZB.js} +2 -2
- package/dist/{found-A5HRTJCJ.js → found-4UY3IC5T.js} +2 -2
- package/dist/{healthcheck-AQUXVKAO.js → healthcheck-XTQN64DB.js} +2 -2
- package/dist/{list-PLZ67PNY.js → list-2PBVBN5K.js} +2 -2
- package/dist/{list-5ENZAOFL.js → list-6ELSECNR.js} +2 -2
- package/dist/{list-EYRN5JYC.js → list-BGI7IZ55.js} +3 -3
- package/dist/{list-CVFXTKNX.js → list-BVUG6RUF.js} +2 -2
- package/dist/{list-CGRHTFAS.js → list-IJS66PYW.js} +2 -2
- package/dist/{list-json-LEKCCWQU.js → list-json-DWHMAA6S.js} +2 -2
- package/dist/{login-C66GRR3Y.js → login-AMEXCOGT.js} +11 -2
- package/dist/{login-json-XGMXT5VJ.js → login-json-MPLXCSP4.js} +2 -2
- package/dist/{login-plain-CWKOUZKE.js → login-plain-NIJDS3D2.js} +2 -2
- package/dist/{logout-LA7VEKON.js → logout-T6Q4IVPU.js} +10 -1
- package/dist/{logout-json-4GIJZJ46.js → logout-json-ACXBI6PN.js} +11 -1
- package/dist/{run-YHDUUP66.js → run-3W7LSPX2.js} +3 -3
- package/dist/{run-OT2X46GT.js → run-4S244KUM.js} +2 -2
- package/dist/{run-MS5SA5YL.js → run-M25F7TWI.js} +2 -2
- package/dist/{setup-skill-BTR2IZ4E.js → setup-skill-J7PZYVCE.js} +1 -1
- package/dist/{snapshot-4QR4I67P.js → snapshot-MEOOARL3.js} +2 -2
- package/dist/{summary-JOCABBCO.js → summary-JYDAPBYX.js} +2 -2
- package/dist/{validate-27RUCN7R.js → validate-RI7YKHKH.js} +2 -2
- 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-
|
|
8
|
-
import "./chunk-
|
|
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-
|
|
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
|
|
31
|
+
const getCredential = options?.getCredential ?? (options?.getToken ? () => ({ kind: "bearer", value: options.getToken() }) : defaultGetCredential);
|
|
25
32
|
async function request(path, body) {
|
|
26
|
-
const
|
|
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-
|
|
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 });
|
|
@@ -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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
70
|
-
var SKILL_FILE =
|
|
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 (!
|
|
1086
|
+
if (!existsSync2(SKILL_FILE)) return void 0;
|
|
975
1087
|
try {
|
|
976
|
-
const raw =
|
|
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
|
|
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
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
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:
|
|
1137
|
+
status: overallStatus,
|
|
1023
1138
|
path: SKILL_FILE,
|
|
1024
|
-
|
|
1139
|
+
skill: { status: skillStatus, path: SKILL_FILE },
|
|
1140
|
+
completions: completionResult,
|
|
1141
|
+
loginHook: loginHookResult
|
|
1025
1142
|
})
|
|
1026
1143
|
);
|
|
1027
|
-
|
|
1028
|
-
|
|
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
|
-
|
|
1165
|
+
`Installed ${completionResult.shell} completions at ${completionResult.path}`
|
|
1031
1166
|
);
|
|
1032
|
-
|
|
1033
|
-
|
|
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
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
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({
|
|
1183
|
+
JSON.stringify({
|
|
1184
|
+
status: removedAnything ? "uninstalled" : "not-installed",
|
|
1185
|
+
path: SKILL_FILE,
|
|
1186
|
+
removedCompletions,
|
|
1187
|
+
loginHook: loginHookResult
|
|
1188
|
+
})
|
|
1058
1189
|
);
|
|
1059
|
-
|
|
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
|
-
|
|
1062
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
11
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
8
|
-
import "./chunk-
|
|
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-
|
|
7
|
+
} from "./chunk-F6D645LF.js";
|
|
8
8
|
import {
|
|
9
9
|
AuthCorruptedError,
|
|
10
10
|
AuthExpiredError,
|
|
11
11
|
AuthNotLoggedInError
|
|
12
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
10
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-F6D645LF.js";
|
|
12
|
+
import "./chunk-EGWK6SRQ.js";
|
|
13
13
|
import "./chunk-TFCNKBRC.js";
|
|
14
14
|
import "./chunk-U73SABXK.js";
|
|
15
15
|
|
|
@@ -5,15 +5,16 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
formatUserCode,
|
|
7
7
|
isHeadlessEnv
|
|
8
|
-
} from "./chunk-
|
|
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-
|
|
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,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
clearCredentials,
|
|
3
|
+
hasApiKeyEnv,
|
|
3
4
|
isLoggedIn
|
|
4
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
11
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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-
|
|
8
|
-
import "./chunk-
|
|
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-
|
|
12
|
-
import "./chunk-
|
|
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.
|
|
5
|
+
"version": "0.8.0",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"homepage": "https://chainpatrol.com/docs/cli",
|
|
8
8
|
"keywords": [
|