fullcourtdefense-cli 1.3.1 → 1.3.3

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/dist/config.js CHANGED
@@ -33,11 +33,17 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getHomeConfigPath = getHomeConfigPath;
36
37
  exports.loadConfig = loadConfig;
37
38
  exports.getDefaultConfigPath = getDefaultConfigPath;
38
39
  exports.saveShieldConfig = saveShieldConfig;
40
+ exports.resolveCliCredentials = resolveCliCredentials;
41
+ exports.isCliSetupComplete = isCliSetupComplete;
42
+ exports.requireCliSetup = requireCliSetup;
43
+ exports.saveSetupConfig = saveSetupConfig;
39
44
  exports.resolveSystemPrompt = resolveSystemPrompt;
40
45
  const fs = __importStar(require("fs"));
46
+ const os = __importStar(require("os"));
41
47
  const path = __importStar(require("path"));
42
48
  const CONFIG_FILENAMES = [
43
49
  '.fullcourtdefense.yml',
@@ -120,27 +126,14 @@ function parseValue(s) {
120
126
  return num;
121
127
  return stripped;
122
128
  }
123
- function loadConfig(configPath) {
124
- let filePath;
125
- if (configPath) {
126
- filePath = path.resolve(configPath);
127
- }
128
- else {
129
- for (const name of CONFIG_FILENAMES) {
130
- const candidate = path.resolve(process.cwd(), name);
131
- if (fs.existsSync(candidate)) {
132
- filePath = candidate;
133
- break;
134
- }
135
- }
136
- }
137
- if (!filePath || !fs.existsSync(filePath)) {
129
+ function readConfigFile(filePath) {
130
+ if (!fs.existsSync(filePath))
138
131
  return {};
139
- }
140
132
  const content = fs.readFileSync(filePath, 'utf-8');
141
133
  const raw = parseSimpleYaml(content);
142
134
  return {
143
135
  apiKey: raw.apiKey ? interpolateEnv(String(raw.apiKey)) : undefined,
136
+ organizationId: raw.organizationId ? interpolateEnv(String(raw.organizationId)) : undefined,
144
137
  apiUrl: raw.apiUrl ? interpolateEnv(String(raw.apiUrl)) : undefined,
145
138
  shieldId: raw.shieldId ? interpolateEnv(String(raw.shieldId)) : undefined,
146
139
  shieldKey: raw.shieldKey ? interpolateEnv(String(raw.shieldKey)) : undefined,
@@ -159,11 +152,89 @@ function loadConfig(configPath) {
159
152
  : undefined,
160
153
  };
161
154
  }
155
+ function mergeConfig(base, override) {
156
+ return {
157
+ ...base,
158
+ ...Object.fromEntries(Object.entries(override).filter(([, value]) => value !== undefined && value !== '')),
159
+ scan: override.scan ? { ...base.scan, ...override.scan } : base.scan,
160
+ };
161
+ }
162
+ function getHomeConfigPath() {
163
+ return path.join(os.homedir(), '.fullcourtdefense.yml');
164
+ }
165
+ function loadConfig(configPath) {
166
+ const homeConfig = readConfigFile(getHomeConfigPath());
167
+ let projectConfig = {};
168
+ if (configPath) {
169
+ projectConfig = readConfigFile(path.resolve(configPath));
170
+ }
171
+ else {
172
+ for (const name of CONFIG_FILENAMES) {
173
+ const candidate = path.resolve(process.cwd(), name);
174
+ if (fs.existsSync(candidate)) {
175
+ projectConfig = readConfigFile(candidate);
176
+ break;
177
+ }
178
+ }
179
+ }
180
+ return mergeConfig(homeConfig, projectConfig);
181
+ }
162
182
  function getDefaultConfigPath() {
163
183
  return path.resolve(process.cwd(), '.fullcourtdefense.yml');
164
184
  }
165
185
  function saveShieldConfig(input) {
166
186
  const target = getDefaultConfigPath();
187
+ return writeSetupConfig(target, input);
188
+ }
189
+ const DEFAULT_API_URL = 'https://api.fullcourtdefense.ai';
190
+ /** Merge saved ~/.fullcourtdefense.yml + env + optional CLI flag overrides. */
191
+ function resolveCliCredentials(config, overrides = {}) {
192
+ return {
193
+ apiKey: overrides.apiKey
194
+ || config.apiKey
195
+ || process.env.FULLCOURTDEFENSE_API_KEY
196
+ || process.env.BOTGUARD_API_KEY,
197
+ organizationId: overrides.organizationId || config.organizationId,
198
+ apiUrl: (overrides.apiUrl
199
+ || config.apiUrl
200
+ || process.env.FULLCOURTDEFENSE_API_URL
201
+ || process.env.FCD_API_URL
202
+ || DEFAULT_API_URL).replace(/\/$/, ''),
203
+ shieldId: overrides.shieldId
204
+ || config.shieldId
205
+ || process.env.FCD_SHIELD_ID
206
+ || process.env.FULLCOURTDEFENSE_SHIELD_ID
207
+ || process.env.AGENTGUARD_SHIELD_ID,
208
+ shieldKey: overrides.shieldKey
209
+ || config.shieldKey
210
+ || process.env.FCD_SHIELD_KEY
211
+ || process.env.FULLCOURTDEFENSE_SHIELD_KEY
212
+ || process.env.AGENTGUARD_SHIELD_KEY,
213
+ };
214
+ }
215
+ function isCliSetupComplete(config) {
216
+ const creds = resolveCliCredentials(config);
217
+ return Boolean(creds.shieldId && creds.apiKey && creds.organizationId);
218
+ }
219
+ /** Fail fast with a clear message when setup was not run. */
220
+ function requireCliSetup(config, overrides = {}, options = {}) {
221
+ const creds = resolveCliCredentials(config, overrides);
222
+ const requireApiKey = options.requireApiKey !== false;
223
+ const requireOrganizationId = options.requireOrganizationId !== false;
224
+ const requireShield = options.requireShield !== false;
225
+ const missing = [];
226
+ if (requireShield && !creds.shieldId)
227
+ missing.push('shieldId');
228
+ if (requireApiKey && !creds.apiKey)
229
+ missing.push('apiKey');
230
+ if (requireOrganizationId && !creds.organizationId)
231
+ missing.push('organizationId');
232
+ if (missing.length > 0) {
233
+ throw new Error(`Missing ${missing.join(', ')}. Run \`fullcourtdefense setup\` once — it saves org, API key, Shield ID, and Shield key to ~/.fullcourtdefense.yml so you never pass them again.`);
234
+ }
235
+ return creds;
236
+ }
237
+ function writeSetupConfig(target, input) {
167
238
  const existing = fs.existsSync(target) ? fs.readFileSync(target, 'utf-8') : '';
168
239
  const lines = existing ? existing.split(/\r?\n/) : [
169
240
  '# FullCourtDefense CLI Configuration',
@@ -185,12 +256,17 @@ function saveShieldConfig(input) {
185
256
  lines.push(next);
186
257
  }
187
258
  };
259
+ setTopLevel('apiKey', input.apiKey);
260
+ setTopLevel('organizationId', input.organizationId);
188
261
  setTopLevel('shieldId', input.shieldId);
189
262
  setTopLevel('shieldKey', input.shieldKey);
190
263
  setTopLevel('apiUrl', input.apiUrl);
191
264
  fs.writeFileSync(target, `${lines.filter((line, idx, arr) => !(line === '' && arr[idx - 1] === '')).join('\n').trim()}\n`, 'utf-8');
192
265
  return target;
193
266
  }
267
+ function saveSetupConfig(input, targetPath) {
268
+ return writeSetupConfig(targetPath || getHomeConfigPath(), input);
269
+ }
194
270
  function resolveSystemPrompt(value) {
195
271
  if (fs.existsSync(value)) {
196
272
  return fs.readFileSync(value, 'utf-8').trim();
package/dist/index.js CHANGED
@@ -1,5 +1,38 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
3
36
  Object.defineProperty(exports, "__esModule", { value: true });
4
37
  const config_1 = require("./config");
5
38
  const scan_1 = require("./commands/scan");
@@ -11,7 +44,20 @@ const discover_1 = require("./commands/discover");
11
44
  const hook_1 = require("./commands/hook");
12
45
  const installCursorHook_1 = require("./commands/installCursorHook");
13
46
  const mcpGateway_1 = require("./commands/mcpGateway");
14
- const VERSION = '1.1.17';
47
+ const installAll_1 = require("./commands/installAll");
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ function readCliVersion() {
51
+ try {
52
+ const versionFile = path.join(__dirname, 'version.json');
53
+ const parsed = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
54
+ return parsed.version || 'unknown';
55
+ }
56
+ catch {
57
+ return 'unknown';
58
+ }
59
+ }
60
+ const VERSION = readCliVersion();
15
61
  function parseArgs(argv) {
16
62
  const flags = {};
17
63
  let command = '';
@@ -63,29 +109,38 @@ function printHelp() {
63
109
  \x1b[1mCommands:\x1b[0m
64
110
  help Show this onboarding guide and command reference.
65
111
  doctor First step. Checks outbound HTTPS access to FullCourtDefense.
66
- configure Saves Shield ID, Shield key, and API URL to .fullcourtdefense.yml.
112
+ configure Saves org API key, Organization ID, Shield ID, and Shield key to ~/.fullcourtdefense.yml.
113
+ After setup, other commands read credentials automatically — no --shield-id/--api-key needed.
114
+ setup Same as configure — validates credentials against the server before saving.
115
+ install-all One-click: MCP gateway in every AI client + Cursor hooks + optional upload.
116
+ install Alias for install-all.
67
117
  scan Runs the scan. Use --local for inside-organization scans.
68
- discover Finds MCP servers configured on this machine (Cursor, Claude,
69
- VS Code, Windsurf, Codex, Gemini CLI) and reports their risk.
70
- Use --upload to add them to your AI Inventory. Use --deep for
71
- live HTTP/SSE tools/list. Use --silent for fleet/MDM scripts.
118
+ discover Finds MCP servers, local secrets, agent rules/skills, and machine
119
+ blast radius on this laptop. Use --surface all --upload for AI Fleet.
72
120
  install-cursor-hook
73
121
  Installs a Cursor hook so every AI prompt + agent action
74
122
  (shell, MCP) on this machine is scanned by your Shield.
75
123
  uninstall-cursor-hook
76
124
  Removes the FullCourtDefense Cursor hook entries.
77
125
  install-mcp-gateway
78
- One command to install the AgentGuard MCP Gateway into detected
79
- clients (Cursor, Claude Code, Claude Desktop).
80
- mcp-gateway
81
- Runs a local MCP gateway that checks AgentGuard runtime/action
82
- policies before forwarding tool calls to a real MCP server.
126
+ Install MCP gateway into selected clients (--clients all for every tool).
83
127
  install-cursor-mcp-gateway
84
- Adds the AgentGuard MCP Gateway to Cursor's mcp.json.
128
+ Cursor only adds gateway to mcp.json.
85
129
  install-claude-code-mcp-gateway
86
- Adds the AgentGuard MCP Gateway to Claude Code using claude mcp add.
130
+ Claude Code only uses claude mcp add or .mcp.json.
87
131
  install-claude-desktop-mcp-gateway
88
- Adds the AgentGuard MCP Gateway to Claude Desktop config.
132
+ Claude Desktop only.
133
+ install-codex-mcp-gateway
134
+ Codex only — writes ~/.codex/config.toml.
135
+ install-gemini-mcp-gateway
136
+ Gemini CLI only — writes settings.json mcpServers.
137
+ install-windsurf-mcp-gateway
138
+ Windsurf only.
139
+ install-vscode-mcp-gateway
140
+ VS Code only — .vscode/mcp.json or user settings.
141
+ mcp-gateway
142
+ Runs a local MCP gateway that checks AgentGuard runtime/action
143
+ policies before forwarding tool calls to a real MCP server.
89
144
  hook Internal: invoked by Cursor per agent event (reads stdin JSON,
90
145
  returns an allow/deny verdict). Not run by hand.
91
146
  credits Shows hosted scan credits for CI/CD API-key scans.
@@ -99,17 +154,21 @@ function printHelp() {
99
154
  fullcourtdefense doctor
100
155
  This confirms the machine can reach https://api.fullcourtdefense.ai over HTTPS.
101
156
 
102
- 3. Save Shield credentials locally:
103
- fullcourtdefense configure
104
- This creates or updates .fullcourtdefense.yml.
157
+ 3. Save org + Shield credentials locally (one time):
158
+ fullcourtdefense setup
159
+ Saves to ~/.fullcourtdefense.yml — install, discover --upload, scan, and hooks use it automatically.
160
+
161
+ 4. One-click protect every AI client on this machine:
162
+ fullcourtdefense install-all --mcp-command npm --mcp-args "run mcp" --upload
163
+ Or install one client: fullcourtdefense install-cursor-mcp-gateway ...
105
164
 
106
- 4. Run a guided local scan:
165
+ 5. Run a guided local scan:
107
166
  fullcourtdefense scan --local
108
167
  The CLI asks whether to scan endpoint, mcp, or rag.
109
168
  To open the localhost web scan UI first:
110
169
  fullcourtdefense scan --local --open-ui
111
170
 
112
- 5. Review results:
171
+ 6. Review results:
113
172
  Use --format summary for CI, --format table for terminal view,
114
173
  --format report for evidence, --format full-report for every row,
115
174
  or --format json for raw output.
@@ -152,8 +211,8 @@ function printHelp() {
152
211
  --mcp-args <args> MCP server args/path, for example ./server.js
153
212
  --mcp-tool <tool> MCP tool to test, or all
154
213
  --server-name <name> MCP gateway server name for client installers
155
- --clients <list> Gateway install clients: auto, all, cursor,
156
- claude-code, claude-desktop
214
+ --clients <list> Gateway clients: all, auto, cursor, claude-code,
215
+ claude-desktop, codex, gemini-cli, windsurf, vscode
157
216
  --developer-name <name> Runtime identity for user-scoped policies (auto-detected if omitted)
158
217
  --agent-name <name> Runtime agent name (auto-generated from identity + client if omitted)
159
218
  --scope <scope> Claude Code MCP scope: local, project, or user
@@ -178,7 +237,7 @@ function printHelp() {
178
237
  --mode <sync|async> Hosted mode, or local mode: quick, full, targeted, deep
179
238
  --categories <list> Comma-separated attack categories
180
239
  --attack-count <n> Number of attacks to run
181
- --progress <mode> MCP progress: verbose, compact, silent (default: verbose)
240
+ --surface <list> Discover surfaces: mcp, secrets, agent-files, posture, all
182
241
  --fail-threshold <n> Exit code 1 if score below n (default: 0)
183
242
  --format <fmt> Output: table, json, summary, report, full-report (default: table)
184
243
  --open Open browser scan UI and saved local scan report
@@ -199,23 +258,27 @@ function printHelp() {
199
258
  $ fullcourtdefense scan --local --type mcp --mcp-transport sse --mcp-url https://internal.company.com/sse --mcp-tool all --mode full
200
259
  $ fullcourtdefense scan --local --type mcp --mcp-command node --mcp-args ./server.js --mcp-tool all --mode full --format report
201
260
  $ fullcourtdefense discover
202
- $ fullcourtdefense discover --upload
261
+ $ fullcourtdefense discover --surface all --upload
262
+ $ fullcourtdefense discover --surface secrets
263
+ $ fullcourtdefense discover --surface agent-files
203
264
  $ fullcourtdefense discover --deep --upload --silent --user-email you@company.com
204
265
  $ fullcourtdefense discover --type mcp --json
205
- $ fullcourtdefense install-cursor-hook --shield-id <id> --shield-key <key>
266
+ $ fullcourtdefense install-cursor-hook
206
267
  $ fullcourtdefense install-cursor-hook --shadow true # monitor only
207
268
  $ fullcourtdefense install-cursor-hook --events prompt,shell,mcp,file
208
269
  $ fullcourtdefense install-cursor-hook --project true # this repo only
209
270
  $ fullcourtdefense uninstall-cursor-hook
210
- $ fullcourtdefense install-mcp-gateway --clients auto --shield-id <id> --shield-key <key> --mcp-command npm --mcp-args "run mcp"
211
- $ fullcourtdefense install-mcp-gateway --clients all --shield-id <id> --shield-key <key> --mcp-command npm --mcp-args "run mcp" --upload --api-key <key>
212
- $ fullcourtdefense install-cursor-mcp-gateway --project true --shield-id <id> --shield-key <key> --mcp-command npm --mcp-args "run mcp"
213
- $ fullcourtdefense install-claude-code-mcp-gateway --scope local --shield-id <id> --shield-key <key> --mcp-command npm --mcp-args "run mcp"
214
- $ fullcourtdefense install-claude-code-mcp-gateway --scope project --shield-id <id> --mcp-command npm --mcp-args "run mcp"
215
- $ fullcourtdefense install-claude-desktop-mcp-gateway --shield-id <id> --shield-key <key> --mcp-command npm --mcp-args "run mcp"
216
- $ fullcourtdefense mcp-gateway --shield-id <id> --mcp-command npm --mcp-args "run mcp"
217
- $ fullcourtdefense configure
218
- $ fullcourtdefense doctor
271
+ $ fullcourtdefense install-mcp-gateway --clients auto --mcp-command npm --mcp-args "run mcp"
272
+ $ fullcourtdefense install-mcp-gateway --clients all --mcp-command npm --mcp-args "run mcp" --upload
273
+ $ fullcourtdefense install-cursor-mcp-gateway --project true --mcp-command npm --mcp-args "run mcp"
274
+ $ fullcourtdefense install-claude-code-mcp-gateway --scope local --mcp-command npm --mcp-args "run mcp"
275
+ $ fullcourtdefense install-claude-code-mcp-gateway --scope project --mcp-command npm --mcp-args "run mcp"
276
+ $ fullcourtdefense install-claude-desktop-mcp-gateway --mcp-command npm --mcp-args "run mcp"
277
+ $ fullcourtdefense mcp-gateway --mcp-command npm --mcp-args "run mcp"
278
+ $ fullcourtdefense setup
279
+ $ fullcourtdefense install-all --mcp-command npm --mcp-args "run mcp" --upload
280
+ $ fullcourtdefense install-mcp-gateway --clients cursor,codex --mcp-command npm --mcp-args "run mcp"
281
+ $ fullcourtdefense install-codex-mcp-gateway --mcp-command npm --mcp-args "run mcp"
219
282
  $ fullcourtdefense scan --system-prompt ./prompts/system.md --fail-threshold 80
220
283
  $ fullcourtdefense scan --config .fullcourtdefense.yml --format json
221
284
  $ fullcourtdefense credits
@@ -226,6 +289,47 @@ function printHelp() {
226
289
  }
227
290
  async function main() {
228
291
  const { command, flags } = parseArgs(process.argv.slice(2));
292
+ const buildInstallArgs = () => ({
293
+ clients: flags.clients,
294
+ cursorProject: flags['cursor-project'],
295
+ claudeCodeScope: flags['claude-code-scope'] || flags.scope,
296
+ serverName: flags['server-name'],
297
+ mcpCommand: flags['mcp-command'],
298
+ mcpArgs: flags['mcp-args'],
299
+ agentName: flags['agent-name'],
300
+ developerName: flags['developer-name'],
301
+ shieldId: flags['shield-id'],
302
+ shieldKey: flags['shield-key'],
303
+ apiUrl: flags['api-url'],
304
+ environment: flags.environment,
305
+ userObjective: flags['user-objective'],
306
+ authority: flags.authority,
307
+ approvalMode: flags['approval-mode'],
308
+ approvalTimeoutMs: flags['approval-timeout-ms'],
309
+ approvalPollMs: flags['approval-poll-ms'],
310
+ scanResponse: flags['scan-response'],
311
+ failClosed: flags['fail-closed'],
312
+ upload: flags.upload,
313
+ apiKey: flags['api-key'],
314
+ });
315
+ const buildGatewayArgs = () => ({
316
+ mcpCommand: flags['mcp-command'],
317
+ mcpArgs: flags['mcp-args'],
318
+ agentName: flags['agent-name'],
319
+ agentClient: flags['agent-client'],
320
+ developerName: flags['developer-name'],
321
+ shieldId: flags['shield-id'],
322
+ shieldKey: flags['shield-key'],
323
+ apiUrl: flags['api-url'],
324
+ environment: flags.environment,
325
+ userObjective: flags['user-objective'],
326
+ authority: flags.authority,
327
+ approvalMode: flags['approval-mode'],
328
+ approvalTimeoutMs: flags['approval-timeout-ms'],
329
+ approvalPollMs: flags['approval-poll-ms'],
330
+ scanResponse: flags['scan-response'],
331
+ failClosed: flags['fail-closed'],
332
+ });
229
333
  if (flags.version || flags.v) {
230
334
  console.log(VERSION);
231
335
  return;
@@ -296,11 +400,15 @@ async function main() {
296
400
  await (0, doctor_1.doctorCommand)(args, config);
297
401
  break;
298
402
  }
299
- case 'configure': {
403
+ case 'configure':
404
+ case 'setup': {
300
405
  const args = {
406
+ apiKey: flags['api-key'],
407
+ organizationId: flags['organization-id'] || flags['org-id'],
301
408
  shieldId: flags['shield-id'],
302
409
  shieldKey: flags['shield-key'],
303
410
  apiUrl: flags['api-url'],
411
+ skipValidate: flags['skip-validate'] === 'true',
304
412
  };
305
413
  await (0, configure_1.configureCommand)(args, config);
306
414
  break;
@@ -316,6 +424,7 @@ async function main() {
316
424
  case 'discover': {
317
425
  const args = {
318
426
  type: flags.type,
427
+ surface: flags.surface,
319
428
  apiKey: flags['api-key'],
320
429
  apiUrl: flags['api-url'],
321
430
  json: flags.json,
@@ -364,123 +473,85 @@ async function main() {
364
473
  break;
365
474
  }
366
475
  case 'mcp-gateway': {
476
+ await (0, mcpGateway_1.mcpGatewayCommand)(buildGatewayArgs(), config);
477
+ break;
478
+ }
479
+ case 'install-all':
480
+ case 'install': {
367
481
  const args = {
368
- mcpCommand: flags['mcp-command'],
369
- mcpArgs: flags['mcp-args'],
370
- agentName: flags['agent-name'],
371
- agentClient: flags['agent-client'],
372
- developerName: flags['developer-name'],
373
- shieldId: flags['shield-id'],
374
- shieldKey: flags['shield-key'],
375
- apiUrl: flags['api-url'],
376
- environment: flags.environment,
377
- userObjective: flags['user-objective'],
378
- authority: flags.authority,
379
- approvalMode: flags['approval-mode'],
380
- approvalTimeoutMs: flags['approval-timeout-ms'],
381
- approvalPollMs: flags['approval-poll-ms'],
382
- scanResponse: flags['scan-response'],
383
- failClosed: flags['fail-closed'],
482
+ ...buildInstallArgs(),
483
+ hooks: flags.hooks,
484
+ discover: flags.discover,
384
485
  };
385
- await (0, mcpGateway_1.mcpGatewayCommand)(args, config);
486
+ await (0, installAll_1.installAllCommand)(args, config);
386
487
  break;
387
488
  }
388
489
  case 'install-mcp-gateway': {
389
- const args = {
390
- clients: flags.clients,
391
- cursorProject: flags['cursor-project'],
392
- claudeCodeScope: flags['claude-code-scope'] || flags.scope,
393
- serverName: flags['server-name'],
394
- mcpCommand: flags['mcp-command'],
395
- mcpArgs: flags['mcp-args'],
396
- agentName: flags['agent-name'],
397
- developerName: flags['developer-name'],
398
- shieldId: flags['shield-id'],
399
- shieldKey: flags['shield-key'],
400
- apiUrl: flags['api-url'],
401
- environment: flags.environment,
402
- userObjective: flags['user-objective'],
403
- authority: flags.authority,
404
- approvalMode: flags['approval-mode'],
405
- approvalTimeoutMs: flags['approval-timeout-ms'],
406
- approvalPollMs: flags['approval-poll-ms'],
407
- scanResponse: flags['scan-response'],
408
- failClosed: flags['fail-closed'],
409
- upload: flags.upload,
410
- apiKey: flags['api-key'],
411
- };
412
- await (0, mcpGateway_1.installMcpGatewayCommand)(args, config);
490
+ await (0, mcpGateway_1.installMcpGatewayCommand)(buildInstallArgs(), config);
413
491
  break;
414
492
  }
415
493
  case 'install-cursor-mcp-gateway': {
416
494
  const args = {
495
+ ...buildGatewayArgs(),
417
496
  project: flags.project,
418
497
  serverName: flags['server-name'],
419
- mcpCommand: flags['mcp-command'],
420
- mcpArgs: flags['mcp-args'],
421
- agentName: flags['agent-name'],
422
- developerName: flags['developer-name'],
423
- shieldId: flags['shield-id'],
424
- shieldKey: flags['shield-key'],
425
- apiUrl: flags['api-url'],
426
- environment: flags.environment,
427
- userObjective: flags['user-objective'],
428
- authority: flags.authority,
429
- approvalMode: flags['approval-mode'],
430
- approvalTimeoutMs: flags['approval-timeout-ms'],
431
- approvalPollMs: flags['approval-poll-ms'],
432
- scanResponse: flags['scan-response'],
433
- failClosed: flags['fail-closed'],
434
498
  };
435
499
  await (0, mcpGateway_1.installCursorMcpGatewayCommand)(args, config);
436
500
  break;
437
501
  }
438
502
  case 'install-claude-code-mcp-gateway': {
439
503
  const args = {
504
+ ...buildGatewayArgs(),
440
505
  scope: flags.scope,
441
506
  serverName: flags['server-name'],
442
- mcpCommand: flags['mcp-command'],
443
- mcpArgs: flags['mcp-args'],
444
- agentName: flags['agent-name'],
445
- developerName: flags['developer-name'],
446
- shieldId: flags['shield-id'],
447
- shieldKey: flags['shield-key'],
448
- apiUrl: flags['api-url'],
449
- environment: flags.environment,
450
- userObjective: flags['user-objective'],
451
- authority: flags.authority,
452
- approvalMode: flags['approval-mode'],
453
- approvalTimeoutMs: flags['approval-timeout-ms'],
454
- approvalPollMs: flags['approval-poll-ms'],
455
- scanResponse: flags['scan-response'],
456
- failClosed: flags['fail-closed'],
457
507
  };
458
508
  await (0, mcpGateway_1.installClaudeCodeMcpGatewayCommand)(args, config);
459
509
  break;
460
510
  }
461
511
  case 'install-claude-desktop-mcp-gateway': {
462
512
  const args = {
513
+ ...buildGatewayArgs(),
463
514
  configPath: flags['config-path'],
464
515
  serverName: flags['server-name'],
465
- mcpCommand: flags['mcp-command'],
466
- mcpArgs: flags['mcp-args'],
467
- agentName: flags['agent-name'],
468
- developerName: flags['developer-name'],
469
- shieldId: flags['shield-id'],
470
- shieldKey: flags['shield-key'],
471
- apiUrl: flags['api-url'],
472
- environment: flags.environment,
473
- userObjective: flags['user-objective'],
474
- authority: flags.authority,
475
- approvalMode: flags['approval-mode'],
476
- approvalTimeoutMs: flags['approval-timeout-ms'],
477
- approvalPollMs: flags['approval-poll-ms'],
478
- scanResponse: flags['scan-response'],
479
- failClosed: flags['fail-closed'],
480
516
  };
481
517
  await (0, mcpGateway_1.installClaudeDesktopMcpGatewayCommand)(args, config);
482
518
  break;
483
519
  }
520
+ case 'install-codex-mcp-gateway': {
521
+ const args = {
522
+ ...buildGatewayArgs(),
523
+ project: flags.project,
524
+ serverName: flags['server-name'],
525
+ };
526
+ await (0, mcpGateway_1.installCodexMcpGatewayCommand)(args, config);
527
+ break;
528
+ }
529
+ case 'install-gemini-mcp-gateway': {
530
+ const args = {
531
+ ...buildGatewayArgs(),
532
+ project: flags.project,
533
+ serverName: flags['server-name'],
534
+ };
535
+ await (0, mcpGateway_1.installGeminiMcpGatewayCommand)(args, config);
536
+ break;
537
+ }
538
+ case 'install-windsurf-mcp-gateway': {
539
+ const args = {
540
+ ...buildGatewayArgs(),
541
+ serverName: flags['server-name'],
542
+ };
543
+ await (0, mcpGateway_1.installWindsurfMcpGatewayCommand)(args, config);
544
+ break;
545
+ }
546
+ case 'install-vscode-mcp-gateway': {
547
+ const args = {
548
+ ...buildGatewayArgs(),
549
+ project: flags.project,
550
+ serverName: flags['server-name'],
551
+ };
552
+ await (0, mcpGateway_1.installVscodeMcpGatewayCommand)(args, config);
553
+ break;
554
+ }
484
555
  case 'init': {
485
556
  await (0, init_1.initCommand)();
486
557
  break;
@@ -0,0 +1,3 @@
1
+ {
2
+ "version": "1.3.3"
3
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fullcourtdefense-cli",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {