@cantinasecurity/apex-cli 0.1.23 → 0.1.24
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.mcp.claude.json +1 -1
- package/.mcp.codex.json +1 -1
- package/MARKETPLACE.md +1 -1
- package/README.md +15 -13
- package/dist/setup.js +53 -22
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Cantina agent plugins for security review workflows.",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.24"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"source": {
|
|
15
15
|
"source": "npm",
|
|
16
16
|
"package": "@cantinasecurity/apex-cli",
|
|
17
|
-
"version": "0.1.
|
|
17
|
+
"version": "0.1.24"
|
|
18
18
|
},
|
|
19
19
|
"description": "Run Apex security scans and review findings from Claude Code.",
|
|
20
|
-
"version": "0.1.
|
|
20
|
+
"version": "0.1.24",
|
|
21
21
|
"author": {
|
|
22
22
|
"name": "Cantina",
|
|
23
23
|
"email": "support@cantina.xyz"
|
package/.mcp.claude.json
CHANGED
package/.mcp.codex.json
CHANGED
package/MARKETPLACE.md
CHANGED
|
@@ -13,7 +13,7 @@ This package is prepared as both a Claude Code plugin and a Codex plugin. The pu
|
|
|
13
13
|
The plugin MCP configs launch the pinned npm CLI package with:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
16
|
+
npx -y -p @cantinasecurity/apex-cli@0.1.24 apex-mcp
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
That keeps marketplace installs independent of a user's global `apex` install.
|
package/README.md
CHANGED
|
@@ -145,30 +145,30 @@ unclaimed local trial proof so `apex claim` can still use it.
|
|
|
145
145
|
Agent-safe copy/paste prompt (substitute the issued code):
|
|
146
146
|
|
|
147
147
|
```text
|
|
148
|
-
Install and run Cantina Apex CLI 0.1.
|
|
148
|
+
Install and run Cantina Apex CLI 0.1.24 to start one free standard security scan of this repository immediately.
|
|
149
149
|
|
|
150
150
|
Use this trial code only where <TRIAL_CODE> appears below: SPBT-DEVREL-XXXXXXXX
|
|
151
151
|
|
|
152
152
|
Run the commands yourself from the repository root; do not stop after setup or only explain the steps. Use terminal CLI commands only. Do not use an Apex MCP tool or run `apex setup`, `apex mcp`, `apex login`, `apex-auth-start`, or `apex-auth-wait`. Never use `--replace` or `--force`.
|
|
153
153
|
|
|
154
154
|
Use this exact command prefix for every Apex command:
|
|
155
|
-
npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
155
|
+
npx -y -p @cantinasecurity/apex-cli@0.1.24 apex
|
|
156
156
|
|
|
157
157
|
1. Before redeeming, confirm every command will use the same persistent, user-accessible machine or container, HOME, filesystem, and repository root. Confirm Node.js 20+ and npx are available. If `APEX_BASE_URL` is set, continue only when its origin is `https://ai.cantina.xyz`. Run the exact prefix with `--help` and continue only if help lists both `redeem` and `claim`. If any check fails, STOP before sending the code; do not install system packages.
|
|
158
158
|
2. Redeem, with at most one response-loss recovery retry:
|
|
159
|
-
npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
159
|
+
npx -y -p @cantinasecurity/apex-cli@0.1.24 apex redeem <TRIAL_CODE> --json
|
|
160
160
|
This terminal command is the only allowed tool call containing the code. Never echo or restate the code, store it in a file or environment variable, put it in a URL or MCP call, or include it in your response. Continue when the command exits 0 and stdout is JSON with `redeemed: true` and `outcome` equal to `redeemed` or `idempotent`. If and only if the first attempt ends with an ambiguous transport/connection failure or an interrupted/missing response and no typed server error code, retry this exact same command once on the same machine, HOME, and repository root. Never retry a typed server rejection and never make more than one recovery retry. If the allowed retry does not return a successful JSON outcome, STOP.
|
|
161
161
|
3. Immediately start exactly one scan; do not wait for another instruction:
|
|
162
|
-
npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
162
|
+
npx -y -p @cantinasecurity/apex-cli@0.1.24 apex scan --mode standard --non-interactive --no-open --json
|
|
163
163
|
On any error or nonzero exit, STOP. After a successful scan JSON response, inspect `localPersistence.workspaceBindingSaved`. If it is `false`, the server scan already started: capture and report `binding.lastScanId`, then STOP; do not run status or findings until local repository permissions are repaired. Otherwise capture `binding.lastScanId` from the JSON as <SCAN_ID>; if it is absent, STOP.
|
|
164
164
|
4. About every 60 seconds, poll that exact scan:
|
|
165
|
-
npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
165
|
+
npx -y -p @cantinasecurity/apex-cli@0.1.24 apex status --scan <SCAN_ID> --json
|
|
166
166
|
Read `progress.progress.status`. Wait while it is `created`, `pending`, `queued`, `starting`, `running`, `in_progress`, or `processing`. Continue on `completed`. STOP on `failed`, `cancelled`, a missing or unknown status, or a command failure.
|
|
167
167
|
5. Fetch that exact scan's findings:
|
|
168
|
-
npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
168
|
+
npx -y -p @cantinasecurity/apex-cli@0.1.24 apex findings --scan <SCAN_ID> --json
|
|
169
169
|
On success, summarize findings by severity, most severe first, including identifier, title, status, and confidence. This command does not return file locations, so do not invent them. On failure, STOP.
|
|
170
170
|
6. Do not claim automatically. Tell me the claim deadline from step 2 and remind me to run this exact command myself from the same repository root, machine, and HOME:
|
|
171
|
-
npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
171
|
+
npx -y -p @cantinasecurity/apex-cli@0.1.24 apex claim
|
|
172
172
|
It may open a browser so I can create or sign in to a Cantina account and keep the results. Claim moves the trial into the currently selected Cantina workspace when I can run scans there, or into my existing personal workspace. If the selected workspace cannot run scans, tell me to switch to one that can and retry before the claim deadline.
|
|
173
173
|
|
|
174
174
|
Never paste raw command transcripts. For any failure, report only the step, exit code, and sanitized error. Redact the trial code and every `apex_at_`, `apex_rt_`, or `apex_ct_` value from all reports.
|
|
@@ -421,14 +421,16 @@ codex mcp add apex \
|
|
|
421
421
|
For Claude Code:
|
|
422
422
|
|
|
423
423
|
```bash
|
|
424
|
-
claude mcp add
|
|
424
|
+
claude mcp add apex \
|
|
425
|
+
--scope user \
|
|
425
426
|
-e APEX_MCP_CLIENT=claude \
|
|
426
427
|
-e APEX_CLIENT_INTEGRATION=claude \
|
|
427
|
-
-- apex
|
|
428
|
+
-- apex-mcp
|
|
428
429
|
```
|
|
429
430
|
|
|
430
|
-
`apex setup claude`
|
|
431
|
-
|
|
431
|
+
`apex setup claude` uses Claude's name-first stdio command syntax and checks
|
|
432
|
+
whether the installed Claude CLI supports `--scope user`. If a Claude build
|
|
433
|
+
omits that option or advertises it but rejects it at runtime, setup safely
|
|
432
434
|
merges the same user-level `mcpServers.apex` entry into `~/.claude.json`
|
|
433
435
|
without replacing other settings or servers.
|
|
434
436
|
|
|
@@ -567,7 +569,7 @@ Telemetry event posts do not include bearer tokens. The telemetry endpoint is `P
|
|
|
567
569
|
{
|
|
568
570
|
"schemaVersion": 1,
|
|
569
571
|
"event": "apex.invocation.completed",
|
|
570
|
-
"cliVersion": "0.1.
|
|
572
|
+
"cliVersion": "0.1.24",
|
|
571
573
|
"invocation": {
|
|
572
574
|
"surface": "mcp",
|
|
573
575
|
"command": "apex-scan",
|
|
@@ -598,7 +600,7 @@ The npm package also includes marketplace-ready plugin artifacts:
|
|
|
598
600
|
- `.claude-plugin/plugin.json` and `.mcp.claude.json` for Claude Code plugin installs
|
|
599
601
|
- `.claude-plugin/marketplace.json` for a Claude marketplace entry backed by the public npm package
|
|
600
602
|
|
|
601
|
-
These plugin installs launch the pinned npm package with `npx -y -p @cantinasecurity/apex-cli@0.1.
|
|
603
|
+
These plugin installs launch the pinned npm package with `npx -y -p @cantinasecurity/apex-cli@0.1.24 apex-mcp`, so users do not need to install `apex` globally before enabling the plugin.
|
|
602
604
|
|
|
603
605
|
The repository also includes `.agents/plugins/marketplace.json` for local Codex marketplace testing from a checkout.
|
|
604
606
|
|
package/dist/setup.js
CHANGED
|
@@ -55,6 +55,20 @@ async function tryExecText(command, args, cwd) {
|
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
function isUnknownClaudeScopeOption(error) {
|
|
59
|
+
if (!error || typeof error !== "object") {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const processError = error;
|
|
63
|
+
const output = [
|
|
64
|
+
processError.message,
|
|
65
|
+
processError.stdout,
|
|
66
|
+
processError.stderr,
|
|
67
|
+
]
|
|
68
|
+
.filter((value) => typeof value === "string")
|
|
69
|
+
.join("\n");
|
|
70
|
+
return /(?:unknown|unrecognized) option(?::)?\s+['"]?--scope['"]?/i.test(output);
|
|
71
|
+
}
|
|
58
72
|
async function resolveMcpLaunchSpec(packageRoot = PACKAGE_ROOT) {
|
|
59
73
|
const repoLocalBinary = path.join(packageRoot, "bin", "apex-mcp");
|
|
60
74
|
if ((await pathExists(path.join(packageRoot, ".git"))) &&
|
|
@@ -315,35 +329,52 @@ async function configureClaude(cwd, launch) {
|
|
|
315
329
|
const existing = await readClaudeUserMcpConfig();
|
|
316
330
|
const env = mcpClientEnv("claude");
|
|
317
331
|
const supportsUserScope = await claudeSupportsUserScope();
|
|
332
|
+
let usedConfigFallback = supportsUserScope === false;
|
|
318
333
|
const mcpStatus = existing === null
|
|
319
334
|
? "installed"
|
|
320
335
|
: claudeConfigMatches(existing, launch)
|
|
321
336
|
? "unchanged"
|
|
322
337
|
: "updated";
|
|
323
|
-
if (
|
|
324
|
-
// Older Claude Code releases reject --scope. Merge the same stdio
|
|
325
|
-
// registration into the user config while preserving all other settings.
|
|
338
|
+
if (usedConfigFallback) {
|
|
326
339
|
await writeClaudeUserMcpConfig(launch);
|
|
327
340
|
}
|
|
328
341
|
else {
|
|
329
|
-
|
|
330
|
-
|
|
342
|
+
try {
|
|
343
|
+
if (existing) {
|
|
344
|
+
await execText("claude", [
|
|
345
|
+
"mcp",
|
|
346
|
+
"remove",
|
|
347
|
+
MCP_SERVER_NAME,
|
|
348
|
+
"--scope",
|
|
349
|
+
"user",
|
|
350
|
+
]);
|
|
351
|
+
}
|
|
352
|
+
// Keep the server name before `--`, which separates Claude options from
|
|
353
|
+
// the stdio command and its arguments.
|
|
354
|
+
await execText("claude", [
|
|
355
|
+
"mcp",
|
|
356
|
+
"add",
|
|
357
|
+
MCP_SERVER_NAME,
|
|
358
|
+
"--scope",
|
|
359
|
+
"user",
|
|
360
|
+
"-e",
|
|
361
|
+
`${MCP_CLIENT_ENV_NAME}=${env[MCP_CLIENT_ENV_NAME]}`,
|
|
362
|
+
"-e",
|
|
363
|
+
`${MCP_CLIENT_INTEGRATION_ENV_NAME}=${env[MCP_CLIENT_INTEGRATION_ENV_NAME]}`,
|
|
364
|
+
"--",
|
|
365
|
+
launch.command,
|
|
366
|
+
...launch.args,
|
|
367
|
+
]);
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
if (!isUnknownClaudeScopeOption(error)) {
|
|
371
|
+
throw error;
|
|
372
|
+
}
|
|
373
|
+
// Some Claude Code builds advertise --scope in help but reject it when
|
|
374
|
+
// the command runs. Preserve the user-level registration directly.
|
|
375
|
+
await writeClaudeUserMcpConfig(launch);
|
|
376
|
+
usedConfigFallback = true;
|
|
331
377
|
}
|
|
332
|
-
// Claude's variadic --env option consumes later tokens until `--`.
|
|
333
|
-
await execText("claude", [
|
|
334
|
-
"mcp",
|
|
335
|
-
"add",
|
|
336
|
-
"--scope",
|
|
337
|
-
"user",
|
|
338
|
-
"-e",
|
|
339
|
-
`${MCP_CLIENT_ENV_NAME}=${env[MCP_CLIENT_ENV_NAME]}`,
|
|
340
|
-
"-e",
|
|
341
|
-
`${MCP_CLIENT_INTEGRATION_ENV_NAME}=${env[MCP_CLIENT_INTEGRATION_ENV_NAME]}`,
|
|
342
|
-
"--",
|
|
343
|
-
MCP_SERVER_NAME,
|
|
344
|
-
launch.command,
|
|
345
|
-
...launch.args,
|
|
346
|
-
]);
|
|
347
378
|
}
|
|
348
379
|
const skillSource = path.join(PACKAGE_ROOT, ".claude", "skills", CODEX_SKILL_NAME, "SKILL.md");
|
|
349
380
|
const skillTarget = path.join(cwd, ".claude", "skills", CODEX_SKILL_NAME, "SKILL.md");
|
|
@@ -355,8 +386,8 @@ async function configureClaude(cwd, launch) {
|
|
|
355
386
|
kind: "mcp",
|
|
356
387
|
status: mcpStatus,
|
|
357
388
|
path: path.join(os.homedir(), ".claude.json"),
|
|
358
|
-
detail:
|
|
359
|
-
? `Registered ${MCP_SERVER_NAME} -> ${launch.label} in Claude Code user config (
|
|
389
|
+
detail: usedConfigFallback
|
|
390
|
+
? `Registered ${MCP_SERVER_NAME} -> ${launch.label} in Claude Code user config (CLI compatibility fallback)`
|
|
360
391
|
: `Registered ${MCP_SERVER_NAME} -> ${launch.label} in Claude Code user config`,
|
|
361
392
|
},
|
|
362
393
|
{
|