agentaudit 3.9.17 → 3.9.19

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 (3) hide show
  1. package/README.md +32 -4
  2. package/cli.mjs +152 -32
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -208,6 +208,7 @@ Then ask your agent: *"Check which MCP servers I have installed and audit any un
208
208
  | `agentaudit audit <url>` | Deep LLM-powered 3-pass audit (~30s) | `agentaudit audit https://github.com/owner/repo` |
209
209
  | `agentaudit lookup <name>` | Look up package in trust registry | `agentaudit lookup fastmcp` |
210
210
  | `agentaudit check <name\|url>` | Lookup + auto-audit if not found | `agentaudit check https://github.com/owner/repo` |
211
+ | `agentaudit status` | Check API keys + active LLM provider | `agentaudit status` |
211
212
  | `agentaudit setup` | Register agent + configure API key | `agentaudit setup` |
212
213
 
213
214
  ### Global Flags
@@ -217,6 +218,7 @@ Then ask your agent: *"Check which MCP servers I have installed and audit any un
217
218
  | `--json` | Output machine-readable JSON to stdout |
218
219
  | `--quiet` / `-q` | Suppress banner and decorative output (show findings only) |
219
220
  | `--no-color` | Disable ANSI colors (also respects `NO_COLOR` env var) |
221
+ | `--provider <name>` | Force LLM provider (`anthropic`, `openai`, `openrouter`, `ollama`, `custom`) |
220
222
  | `--help` / `-h` | Show help text |
221
223
  | `-v` / `--version` | Show version |
222
224
 
@@ -433,12 +435,19 @@ export AGENTAUDIT_API_KEY=asf_your_key_here
433
435
  | Variable | Description |
434
436
  |----------|-------------|
435
437
  | `AGENTAUDIT_API_KEY` | API key for registry access |
436
- | `ANTHROPIC_API_KEY` | Anthropic API key for deep audits (Claude) |
438
+ | `ANTHROPIC_API_KEY` | Anthropic API key for deep audits (Claude) -- recommended |
437
439
  | `OPENAI_API_KEY` | OpenAI API key for deep audits (GPT-4o) |
438
440
  | `OPENROUTER_API_KEY` | OpenRouter API key (access 200+ models) |
439
441
  | `OPENROUTER_MODEL` | Model to use via OpenRouter (default: `anthropic/claude-sonnet-4`) |
442
+ | `OLLAMA_MODEL` | Ollama model name for local audits (e.g. `llama3.1`, `qwen2.5-coder`) |
443
+ | `OLLAMA_HOST` | Ollama server URL (default: `http://localhost:11434`) |
444
+ | `LLM_API_URL` | Any OpenAI-compatible API endpoint (e.g. LM Studio, vLLM, Together, Groq) |
445
+ | `LLM_API_KEY` | API key for custom endpoint (optional if no auth needed) |
446
+ | `LLM_MODEL` | Model name for custom endpoint |
440
447
  | `NO_COLOR` | Disable ANSI colors ([no-color.org](https://no-color.org)) |
441
448
 
449
+ > **Provider priority:** Anthropic > OpenAI > OpenRouter > Custom > Ollama. Override with `--provider=ollama` etc.
450
+
442
451
  ---
443
452
 
444
453
  ## 📦 Requirements
@@ -468,7 +477,7 @@ Or use without installing: `npx agentaudit`
468
477
 
469
478
  ### Setting up your LLM key for deep audits
470
479
 
471
- The `audit` command supports **three LLM providers**. Set one of these environment variables:
480
+ The `audit` command supports **any LLM provider**. Set one of these environment variables:
472
481
 
473
482
  ```bash
474
483
  # Linux / macOS
@@ -487,13 +496,32 @@ set OPENAI_API_KEY=sk-...
487
496
  set OPENROUTER_API_KEY=sk-or-...
488
497
  ```
489
498
 
490
- **Provider priority:** Anthropic > OpenAI > OpenRouter. The active provider is shown during the audit.
499
+ **Provider priority:** Anthropic > OpenAI > OpenRouter > Custom > Ollama. Override with `--provider=<name>`.
491
500
 
492
- **OpenRouter model selection:** By default, OpenRouter uses `anthropic/claude-sonnet-4`. Override with:
501
+ **OpenRouter model selection:** By default uses `anthropic/claude-sonnet-4`. Override with:
493
502
  ```bash
494
503
  export OPENROUTER_MODEL=google/gemini-2.5-pro # or any model on openrouter.ai
495
504
  ```
496
505
 
506
+ **Local with Ollama (free, no API key):**
507
+ ```bash
508
+ export OLLAMA_MODEL=llama3.1 # or qwen2.5-coder, deepseek-r1, etc.
509
+ agentaudit audit https://github.com/owner/repo
510
+ ```
511
+ > Note: Local models produce lower quality audits than Claude/GPT-4o. Use for quick checks, not production security audits.
512
+
513
+ **Any OpenAI-compatible API:**
514
+ ```bash
515
+ export LLM_API_URL=http://localhost:1234/v1 # LM Studio, vLLM, etc.
516
+ export LLM_MODEL=my-model
517
+ agentaudit audit https://github.com/owner/repo
518
+ ```
519
+
520
+ **Check your setup:**
521
+ ```bash
522
+ agentaudit status # validates all configured API keys
523
+ ```
524
+
497
525
  **Troubleshooting:** If you see `API error: Incorrect API key`, double-check your key is valid and has credits. Use `--debug` to see the full API response.
498
526
 
499
527
  ### What data is sent externally?
package/cli.mjs CHANGED
@@ -9,6 +9,7 @@
9
9
  * agentaudit audit <repo-url> Deep LLM-powered security audit
10
10
  * agentaudit lookup <name> Look up package in registry
11
11
  * agentaudit check <name|url> Lookup + auto-audit if not found
12
+ * agentaudit status Check configured API keys + providers
12
13
  * agentaudit setup Register + configure API key
13
14
  *
14
15
  * Global flags: --json, --quiet, --no-color
@@ -25,6 +26,35 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
25
26
  const SKILL_DIR = path.resolve(__dirname);
26
27
  const REGISTRY_URL = 'https://agentaudit.dev';
27
28
 
29
+ // ── Provider resolution ────
30
+ function resolveProvider(preferred, keys) {
31
+ const orModel = process.env.OPENROUTER_MODEL || 'anthropic/claude-sonnet-4';
32
+ const ollamaModel = process.env.OLLAMA_MODEL || 'llama3.1';
33
+ const ollamaHost = process.env.OLLAMA_HOST || 'http://localhost:11434';
34
+ const customUrl = process.env.LLM_API_URL;
35
+ const customKey = process.env.LLM_API_KEY;
36
+ const customModel = process.env.LLM_MODEL || 'default';
37
+
38
+ const providers = {
39
+ anthropic: keys.anthropicKey ? { id: 'anthropic', label: 'Anthropic (Claude)', key: keys.anthropicKey } : null,
40
+ openai: keys.openaiKey ? { id: 'openai', label: 'OpenAI (GPT-4o)', key: keys.openaiKey } : null,
41
+ openrouter: keys.openrouterKey ? { id: 'openrouter', label: `OpenRouter (${orModel})`, key: keys.openrouterKey } : null,
42
+ ollama: process.env.OLLAMA_MODEL || process.env.OLLAMA_HOST ? { id: 'ollama', label: `Ollama (${ollamaModel})`, key: null, host: ollamaHost, model: ollamaModel } : null,
43
+ custom: customUrl ? { id: 'custom', label: `Custom (${customModel})`, key: customKey, url: customUrl, model: customModel } : null,
44
+ };
45
+ // Aliases
46
+ const aliases = { claude: 'anthropic', gpt: 'openai', 'gpt-4o': 'openai', 'gpt4': 'openai', or: 'openrouter', local: 'ollama' };
47
+
48
+ if (preferred) {
49
+ const resolved = aliases[preferred] || preferred;
50
+ const p = providers[resolved];
51
+ if (!p) return null;
52
+ return p;
53
+ }
54
+ // Auto-detect priority: Anthropic > OpenAI > OpenRouter > Custom > Ollama (local last — usually weaker)
55
+ return providers.anthropic || providers.openai || providers.openrouter || providers.custom || providers.ollama || null;
56
+ }
57
+
28
58
  // ── Global flags (set in main before command routing) ────
29
59
  let jsonMode = false;
30
60
  let quietMode = false;
@@ -1312,15 +1342,25 @@ async function auditRepo(url) {
1312
1342
  const openaiKey = process.env.OPENAI_API_KEY;
1313
1343
  const openrouterKey = process.env.OPENROUTER_API_KEY;
1314
1344
  const openrouterModel = process.env.OPENROUTER_MODEL || 'anthropic/claude-sonnet-4';
1315
- const activeProvider = anthropicKey ? 'Anthropic (Claude)' : openaiKey ? 'OpenAI (GPT-4o)' : openrouterKey ? `OpenRouter (${openrouterModel})` : null;
1345
+
1346
+ // --provider flag overrides auto-detection
1347
+ const providerFlag = process.argv.find(a => a.startsWith('--provider='))?.split('=')[1]?.toLowerCase()
1348
+ || (process.argv.includes('--provider') ? process.argv[process.argv.indexOf('--provider') + 1]?.toLowerCase() : null);
1349
+
1350
+ const resolvedProvider = resolveProvider(providerFlag, { anthropicKey, openaiKey, openrouterKey });
1351
+ const activeProvider = resolvedProvider?.label || null;
1316
1352
 
1317
- if (!anthropicKey && !openaiKey && !openrouterKey) {
1353
+ if (!resolvedProvider) {
1318
1354
  // No LLM API key — clear explanation
1319
1355
  console.log();
1320
- console.log(` ${c.yellow}No LLM API key found.${c.reset} The ${c.bold}audit${c.reset} command needs an LLM to analyze code.`);
1356
+ console.log(` ${c.yellow}No LLM provider configured.${c.reset} The ${c.bold}audit${c.reset} command needs an LLM to analyze code.`);
1321
1357
  console.log();
1322
- console.log(` ${c.bold}Option 1: Set an API key${c.reset}`);
1323
- console.log(` Supported keys: ${c.cyan}ANTHROPIC_API_KEY${c.reset}, ${c.cyan}OPENAI_API_KEY${c.reset}, or ${c.cyan}OPENROUTER_API_KEY${c.reset}`);
1358
+ console.log(` ${c.bold}Option 1: Set an API key${c.reset} ${c.dim}(any one of these)${c.reset}`);
1359
+ console.log(` ${c.cyan}ANTHROPIC_API_KEY${c.reset} Anthropic Claude ${c.dim}(recommended)${c.reset}`);
1360
+ console.log(` ${c.cyan}OPENAI_API_KEY${c.reset} OpenAI GPT-4o`);
1361
+ console.log(` ${c.cyan}OPENROUTER_API_KEY${c.reset} OpenRouter ${c.dim}(200+ models)${c.reset}`);
1362
+ console.log(` ${c.cyan}OLLAMA_MODEL${c.reset} Ollama ${c.dim}(local, free, set model name)${c.reset}`);
1363
+ console.log(` ${c.cyan}LLM_API_URL${c.reset} Any OpenAI-compatible API ${c.dim}(+ LLM_API_KEY, LLM_MODEL)${c.reset}`);
1324
1364
  console.log();
1325
1365
  console.log(` ${c.dim}# Linux / macOS:${c.reset}`);
1326
1366
  console.log(` ${c.dim}export ANTHROPIC_API_KEY=sk-ant-...${c.reset}`);
@@ -1397,11 +1437,11 @@ async function auditRepo(url) {
1397
1437
  let _lastLlmText = '';
1398
1438
 
1399
1439
  try {
1400
- if (anthropicKey) {
1440
+ if (resolvedProvider.id === 'anthropic') {
1401
1441
  const res = await fetch('https://api.anthropic.com/v1/messages', {
1402
1442
  method: 'POST',
1403
1443
  headers: {
1404
- 'x-api-key': anthropicKey,
1444
+ 'x-api-key': resolvedProvider.key,
1405
1445
  'anthropic-version': '2023-06-01',
1406
1446
  'content-type': 'application/json',
1407
1447
  },
@@ -1423,20 +1463,34 @@ async function auditRepo(url) {
1423
1463
  const text = data.content?.[0]?.text || '';
1424
1464
  _lastLlmText = text;
1425
1465
  report = extractJSON(text);
1426
- } else if (openaiKey || openrouterKey) {
1427
- const isOpenRouter = !openaiKey && !!openrouterKey;
1428
- const apiUrl = isOpenRouter ? 'https://openrouter.ai/api/v1/chat/completions' : 'https://api.openai.com/v1/chat/completions';
1429
- const apiToken = isOpenRouter ? openrouterKey : openaiKey;
1430
- const modelName = isOpenRouter ? (process.env.OPENROUTER_MODEL || 'anthropic/claude-sonnet-4') : 'gpt-4o';
1431
- const extraHeaders = isOpenRouter ? { 'HTTP-Referer': 'https://agentaudit.dev', 'X-Title': 'AgentAudit' } : {};
1466
+ } else {
1467
+ // OpenAI, OpenRouter, Ollama, or Custom (all use OpenAI-compatible chat completions API)
1468
+ let apiUrl, modelName, authHeaders;
1469
+ switch (resolvedProvider.id) {
1470
+ case 'openrouter':
1471
+ apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
1472
+ modelName = process.env.OPENROUTER_MODEL || 'anthropic/claude-sonnet-4';
1473
+ authHeaders = { 'Authorization': `Bearer ${resolvedProvider.key}`, 'HTTP-Referer': 'https://agentaudit.dev', 'X-Title': 'AgentAudit' };
1474
+ break;
1475
+ case 'ollama':
1476
+ apiUrl = `${resolvedProvider.host}/v1/chat/completions`;
1477
+ modelName = resolvedProvider.model;
1478
+ authHeaders = {};
1479
+ break;
1480
+ case 'custom':
1481
+ apiUrl = resolvedProvider.url.endsWith('/chat/completions') ? resolvedProvider.url : `${resolvedProvider.url.replace(/\/$/, '')}/chat/completions`;
1482
+ modelName = resolvedProvider.model;
1483
+ authHeaders = resolvedProvider.key ? { 'Authorization': `Bearer ${resolvedProvider.key}` } : {};
1484
+ break;
1485
+ default: // openai
1486
+ apiUrl = 'https://api.openai.com/v1/chat/completions';
1487
+ modelName = 'gpt-4o';
1488
+ authHeaders = { 'Authorization': `Bearer ${resolvedProvider.key}` };
1489
+ }
1432
1490
 
1433
1491
  const res = await fetch(apiUrl, {
1434
1492
  method: 'POST',
1435
- headers: {
1436
- 'Authorization': `Bearer ${apiToken}`,
1437
- 'Content-Type': 'application/json',
1438
- ...extraHeaders,
1439
- },
1493
+ headers: { 'Content-Type': 'application/json', ...authHeaders },
1440
1494
  body: JSON.stringify({
1441
1495
  model: modelName,
1442
1496
  max_tokens: 8192,
@@ -1445,7 +1499,7 @@ async function auditRepo(url) {
1445
1499
  { role: 'user', content: userMessage },
1446
1500
  ],
1447
1501
  }),
1448
- signal: AbortSignal.timeout(120_000),
1502
+ signal: AbortSignal.timeout(resolvedProvider.id === 'ollama' ? 300_000 : 120_000), // Ollama: 5min (local can be slow)
1449
1503
  });
1450
1504
  const data = await res.json();
1451
1505
  if (data.error) {
@@ -1656,12 +1710,14 @@ async function main() {
1656
1710
  console.log(` ${c.cyan}agentaudit audit${c.reset} <url> [url...] Deep LLM-powered security audit`);
1657
1711
  console.log(` ${c.cyan}agentaudit lookup${c.reset} <name> Look up package in registry`);
1658
1712
  console.log(` ${c.cyan}agentaudit check${c.reset} <name|url> Lookup + auto-audit if not found`);
1713
+ console.log(` ${c.cyan}agentaudit status${c.reset} Check API keys + active provider`);
1659
1714
  console.log(` ${c.cyan}agentaudit setup${c.reset} Register + configure API key`);
1660
1715
  console.log();
1661
1716
  console.log(` ${c.bold}Global flags:${c.reset}`);
1662
1717
  console.log(` ${c.dim}--json Output JSON to stdout (machine-readable)${c.reset}`);
1663
1718
  console.log(` ${c.dim}--quiet Suppress banner and tree visualization${c.reset}`);
1664
1719
  console.log(` ${c.dim}--no-color Disable ANSI colors (also: NO_COLOR env)${c.reset}`);
1720
+ console.log(` ${c.dim}--provider Force LLM provider (anthropic, openai, openrouter)${c.reset}`);
1665
1721
  console.log();
1666
1722
  console.log(` ${c.bold}Quick Scan${c.reset} vs ${c.bold}Deep Audit${c.reset}:`);
1667
1723
  console.log(` ${c.dim}scan = fast regex-based static analysis (~2s)${c.reset}`);
@@ -1677,19 +1733,14 @@ async function main() {
1677
1733
  console.log(` agentaudit audit https://github.com/owner/repo`);
1678
1734
  console.log(` agentaudit lookup fastmcp --json`);
1679
1735
  console.log();
1680
- console.log(` ${c.bold}For deep audits,${c.reset} set an LLM API key (any one):`);
1681
- if (process.platform === 'win32') {
1682
- console.log(` ${c.dim}PowerShell: $env:ANTHROPIC_API_KEY = "sk-ant-..."${c.reset}`);
1683
- console.log(` ${c.dim} $env:OPENAI_API_KEY = "sk-..."${c.reset}`);
1684
- console.log(` ${c.dim} $env:OPENROUTER_API_KEY = "sk-or-..."${c.reset}`);
1685
- console.log(` ${c.dim}CMD: set ANTHROPIC_API_KEY=sk-ant-...${c.reset}`);
1686
- console.log(` ${c.dim} set OPENAI_API_KEY=sk-...${c.reset}`);
1687
- console.log(` ${c.dim} set OPENROUTER_API_KEY=sk-or-...${c.reset}`);
1688
- } else {
1689
- console.log(` ${c.dim}export ANTHROPIC_API_KEY=sk-ant-...${c.reset}`);
1690
- console.log(` ${c.dim}export OPENAI_API_KEY=sk-...${c.reset}`);
1691
- console.log(` ${c.dim}export OPENROUTER_API_KEY=sk-or-...${c.reset} ${c.dim}(200+ models, set OPENROUTER_MODEL to pick)${c.reset}`);
1692
- }
1736
+ console.log(` ${c.bold}For deep audits,${c.reset} set an LLM provider (any one):`);
1737
+ console.log(` ${c.dim}ANTHROPIC_API_KEY Anthropic Claude (recommended)${c.reset}`);
1738
+ console.log(` ${c.dim}OPENAI_API_KEY OpenAI GPT-4o${c.reset}`);
1739
+ console.log(` ${c.dim}OPENROUTER_API_KEY 200+ models (+ OPENROUTER_MODEL)${c.reset}`);
1740
+ console.log(` ${c.dim}OLLAMA_MODEL Local Ollama (+ OLLAMA_HOST)${c.reset}`);
1741
+ console.log(` ${c.dim}LLM_API_URL Any OpenAI-compatible API (+ LLM_API_KEY, LLM_MODEL)${c.reset}`);
1742
+ console.log();
1743
+ console.log(` ${c.dim}Run ${c.cyan}agentaudit status${c.dim} to check your configured providers.${c.reset}`);
1693
1744
  console.log();
1694
1745
  console.log(` ${c.bold}Or use as MCP server${c.reset} in Cursor/Claude ${c.dim}(no extra API key needed):${c.reset}`);
1695
1746
  console.log(` ${c.dim}Add to your MCP config:${c.reset}`);
@@ -1709,6 +1760,75 @@ async function main() {
1709
1760
  return;
1710
1761
  }
1711
1762
 
1763
+ if (command === 'status') {
1764
+ console.log(` ${c.bold}LLM Providers:${c.reset}`);
1765
+ console.log();
1766
+ const keys = {
1767
+ anthropicKey: process.env.ANTHROPIC_API_KEY,
1768
+ openaiKey: process.env.OPENAI_API_KEY,
1769
+ openrouterKey: process.env.OPENROUTER_API_KEY,
1770
+ };
1771
+ const ollamaHost = process.env.OLLAMA_HOST || 'http://localhost:11434';
1772
+ const ollamaModel = process.env.OLLAMA_MODEL;
1773
+ const customUrl = process.env.LLM_API_URL;
1774
+
1775
+ const checks = [
1776
+ { name: 'Anthropic', env: 'ANTHROPIC_API_KEY', key: keys.anthropicKey, testUrl: 'https://api.anthropic.com/v1/messages', testHeaders: (k) => ({ 'x-api-key': k, 'anthropic-version': '2023-06-01', 'content-type': 'application/json' }), testBody: JSON.stringify({ model: 'claude-sonnet-4-20250514', max_tokens: 1, messages: [{ role: 'user', content: 'hi' }] }) },
1777
+ { name: 'OpenAI', env: 'OPENAI_API_KEY', key: keys.openaiKey, testUrl: 'https://api.openai.com/v1/models', testHeaders: (k) => ({ 'Authorization': `Bearer ${k}` }), testBody: null },
1778
+ { name: 'OpenRouter', env: 'OPENROUTER_API_KEY', key: keys.openrouterKey, testUrl: 'https://openrouter.ai/api/v1/models', testHeaders: (k) => ({ 'Authorization': `Bearer ${k}` }), testBody: null },
1779
+ { name: 'Ollama', env: 'OLLAMA_MODEL', key: ollamaModel, testUrl: `${ollamaHost}/api/tags`, testHeaders: () => ({}), testBody: null },
1780
+ { name: 'Custom', env: 'LLM_API_URL', key: customUrl, testUrl: customUrl ? `${customUrl.replace(/\/$/, '')}/models` : null, testHeaders: (k) => process.env.LLM_API_KEY ? ({ 'Authorization': `Bearer ${process.env.LLM_API_KEY}` }) : {}, testBody: null },
1781
+ ];
1782
+
1783
+ for (const p of checks) {
1784
+ if (!p.key) {
1785
+ console.log(` ${c.dim}○${c.reset} ${p.name.padEnd(12)} ${c.dim}not set${c.reset} ${c.dim}(${p.env})${c.reset}`);
1786
+ continue;
1787
+ }
1788
+ const masked = p.key.substring(0, 8) + '...' + p.key.substring(p.key.length - 4);
1789
+ process.stdout.write(` ${c.yellow}●${c.reset} ${p.name.padEnd(12)} ${c.dim}${masked}${c.reset} checking...`);
1790
+ try {
1791
+ const res = await fetch(p.testUrl, {
1792
+ method: p.testBody ? 'POST' : 'GET',
1793
+ headers: p.testHeaders(p.key),
1794
+ ...(p.testBody ? { body: p.testBody } : {}),
1795
+ signal: AbortSignal.timeout(10_000),
1796
+ });
1797
+ if (res.ok || res.status === 200 || res.status === 201) {
1798
+ process.stdout.write(`\r ${c.green}●${c.reset} ${p.name.padEnd(12)} ${c.dim}${masked}${c.reset} ${c.green}valid ✓${c.reset} \n`);
1799
+ } else {
1800
+ const body = await res.json().catch(() => ({}));
1801
+ const errMsg = body?.error?.message || `HTTP ${res.status}`;
1802
+ process.stdout.write(`\r ${c.red}●${c.reset} ${p.name.padEnd(12)} ${c.dim}${masked}${c.reset} ${c.red}invalid ✗${c.reset} ${c.dim}(${errMsg})${c.reset} \n`);
1803
+ }
1804
+ } catch (e) {
1805
+ process.stdout.write(`\r ${c.red}●${c.reset} ${p.name.padEnd(12)} ${c.dim}${masked}${c.reset} ${c.red}error ✗${c.reset} ${c.dim}(${e.message})${c.reset} \n`);
1806
+ }
1807
+ }
1808
+
1809
+ const resolved = resolveProvider(null, keys);
1810
+ console.log();
1811
+ if (resolved) {
1812
+ console.log(` ${c.bold}Active provider:${c.reset} ${resolved.label}`);
1813
+ console.log(` ${c.dim}Override with: --provider=openai | --provider=openrouter | --provider=anthropic${c.reset}`);
1814
+ } else {
1815
+ console.log(` ${c.yellow}No LLM provider configured.${c.reset} Set one of the API keys above for deep audits.`);
1816
+ }
1817
+
1818
+ // AgentAudit registry key
1819
+ console.log();
1820
+ console.log(` ${c.bold}Registry:${c.reset}`);
1821
+ const creds = loadCredentials();
1822
+ if (creds?.api_key) {
1823
+ const masked = creds.api_key.substring(0, 8) + '...' + creds.api_key.substring(creds.api_key.length - 4);
1824
+ console.log(` ${c.green}●${c.reset} AgentAudit ${c.dim}${masked}${c.reset} ${c.dim}(${creds.agent_name || 'unknown'})${c.reset}`);
1825
+ } else {
1826
+ console.log(` ${c.dim}○${c.reset} AgentAudit ${c.dim}not set${c.reset} ${c.dim}(run: agentaudit setup)${c.reset}`);
1827
+ }
1828
+ console.log();
1829
+ return;
1830
+ }
1831
+
1712
1832
  if (command === 'discover') {
1713
1833
  const scanFlag = targets.includes('--quick') || targets.includes('--scan') || targets.includes('-s');
1714
1834
  const auditFlag = targets.includes('--deep') || targets.includes('--audit') || targets.includes('-a');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentaudit",
3
- "version": "3.9.17",
3
+ "version": "3.9.19",
4
4
  "description": "Security scanner for AI packages — MCP server + CLI",
5
5
  "type": "module",
6
6
  "bin": {