npmguard-cli 1.1.0 → 1.1.2

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/README.md CHANGED
@@ -1,9 +1,175 @@
1
- # NpmGuard CLI
1
+ # npmguard-cli
2
2
 
3
- > **TODO** CLI will talk to the NpmGuard API server (not ENS/IPFS). Not yet implemented.
3
+ Security-gated npm install. Runs every package through NpmGuard's audit
4
+ engine before it touches your `node_modules`.
4
5
 
5
- Planned features:
6
+ ```bash
7
+ npx npmguard-cli install express
8
+ ```
6
9
 
7
- - `npmguard check <package>` — run a security audit via the API
8
- - `npmguard install <package>` audit-then-install workflow
9
- - Machine-readable JSON output for CI/CD integration
10
+ - **SAFE** installs immediately
11
+ - **DANGEROUS** warns, shows findings, asks before installing
12
+ - **No audit yet** → offers to pay for one (Stripe or crypto), then streams
13
+ the results in real time
14
+
15
+ ## Install
16
+
17
+ No install required — `npx` pulls the latest from npm:
18
+
19
+ ```bash
20
+ npx npmguard-cli@latest install <pkg>
21
+ ```
22
+
23
+ Or install globally:
24
+
25
+ ```bash
26
+ npm install -g npmguard-cli
27
+ npmguard install <pkg>
28
+ ```
29
+
30
+ ## Commands
31
+
32
+ ### `npmguard install <package>[@version]`
33
+
34
+ The main command. Runs the full gate-then-install flow.
35
+
36
+ ```bash
37
+ npmguard install express
38
+ npmguard install lodash@4.17.21
39
+ npmguard install @types/node@22
40
+
41
+ # Force install even if the package is flagged DANGEROUS
42
+ npmguard install left-pad --force
43
+ ```
44
+
45
+ The command auto-detects your package manager (`npm` / `pnpm` / `yarn`) from
46
+ lockfiles and runs the correct add command (`npm install`, `pnpm add`,
47
+ `yarn add`).
48
+
49
+ **Flow**:
50
+
51
+ 1. Resolves the version (`latest` if omitted)
52
+ 2. Asks the engine if the package has an existing audit
53
+ 3. **Found + SAFE** → runs `<pm> add <pkg>` directly
54
+ 4. **Found + DANGEROUS** → shows findings + capabilities, prompts `y/N`
55
+ (bypass with `--force`)
56
+ 5. **Not found** → asks how you want to pay for the audit:
57
+ - Stripe (credit card) — browser checkout via QR
58
+ - WalletConnect — mobile wallet signs a tx on Base Sepolia (~$0.30)
59
+ - Install without audit (yolo)
60
+ - Cancel
61
+ 6. Streams audit events live (phases, findings, verdict)
62
+ 7. Runs the install if the verdict is SAFE, or prompts otherwise
63
+
64
+ ### `npmguard audit <package>[@version]`
65
+
66
+ Run a standalone audit without installing. Returns the verdict and exits.
67
+
68
+ ```bash
69
+ npmguard audit is-number
70
+ npmguard audit express@5.2.1
71
+ ```
72
+
73
+ Same payment flow as `install` if the package hasn't been audited yet.
74
+
75
+ ### `npmguard check [--path <dir>]`
76
+
77
+ Walk `package.json` in the given directory and check every dependency
78
+ against NpmGuard's audit database. Useful for auditing an existing project.
79
+
80
+ ```bash
81
+ cd my-project
82
+ npmguard check
83
+ # or
84
+ npmguard check --path /path/to/other-project
85
+ ```
86
+
87
+ ## Payment options
88
+
89
+ When a package hasn't been audited yet, an audit run costs real compute
90
+ (LLM calls, sandbox execution). Two ways to pay:
91
+
92
+ ### Stripe (fiat)
93
+
94
+ Opens a Stripe checkout page in the browser. After payment, the engine
95
+ triggers the audit automatically. Works from any machine, no wallet
96
+ required.
97
+
98
+ ### WalletConnect (crypto)
99
+
100
+ The CLI generates a WalletConnect v2 QR code in the terminal. Scan it with
101
+ any mobile wallet (MetaMask, Rainbow, Coinbase Wallet, etc.) and confirm
102
+ the transaction.
103
+
104
+ - **Chain**: Base Sepolia (testnet — free ETH from
105
+ [Alchemy faucet](https://www.alchemy.com/faucets/base-sepolia))
106
+ - **Fee**: `0.0001 ETH` per audit
107
+ - **Contract**: [`0xBF562626e4Afb883423Ec719e0270DB232bcB9eD`](https://sepolia.basescan.org/address/0xbf562626e4afb883423ec719e0270db232bcb9ed)
108
+
109
+ Flow:
110
+
111
+ 1. CLI reads the fee from the contract
112
+ 2. You approve the tx in your wallet
113
+ 3. Engine verifies the receipt on Base Sepolia via Alchemy
114
+ 4. Audit starts, CLI streams events
115
+
116
+ The on-chain event `AuditRequested(packageName, version, requester, feePaid)`
117
+ acts as the payment proof. The engine decodes it and matches the args
118
+ against your request before launching the audit.
119
+
120
+ ## Configuration
121
+
122
+ The CLI talks to `https://npmguard.com` by default. You can override the
123
+ API URL for local development:
124
+
125
+ ```bash
126
+ # via flag
127
+ npmguard --api http://localhost:8000 install lodash
128
+
129
+ # via env
130
+ export NPMGUARD_API_URL=http://localhost:8000
131
+ npmguard install lodash
132
+ ```
133
+
134
+ No blockchain config is required from the user — the CLI reads the
135
+ contract address + chain from its own code. Your wallet's RPC handles the
136
+ broadcast.
137
+
138
+ ## Exit codes
139
+
140
+ | Code | Meaning |
141
+ |---|---|
142
+ | 0 | Audit passed, package installed |
143
+ | 1 | Audit failed / install aborted / network error |
144
+
145
+ ## Dependencies
146
+
147
+ Intentionally minimal:
148
+
149
+ - `commander` — CLI arg parsing
150
+ - `chalk`, `ora`, `qrcode-terminal` — terminal UI
151
+ - `eventsource` — SSE client for audit events
152
+ - `viem` — read contract, encode calldata, wait for receipt
153
+ - `@walletconnect/sign-client` — WalletConnect v2 session
154
+
155
+ No private key handling in the CLI. The wallet signs and broadcasts; the
156
+ CLI only observes.
157
+
158
+ ## Development
159
+
160
+ ```bash
161
+ cd cli
162
+ npm install
163
+ npm run build
164
+
165
+ # Test against local engine
166
+ node dist/index.js --api http://localhost:8000 install is-number
167
+ ```
168
+
169
+ ## Release
170
+
171
+ ```bash
172
+ npm version patch # or minor / major
173
+ npm run build
174
+ npm publish --access public
175
+ ```
@@ -175,6 +175,8 @@ async function runCryptoAuditAndInstall(fullSpec, name, version, apiUrl) {
175
175
  (err instanceof Error ? err.message : String(err)));
176
176
  process.exit(1);
177
177
  }
178
+ console.log(chalk.cyan(` Watch live: ${apiUrl}/audit/${auditId}`));
179
+ console.log();
178
180
  // 4. Stream the audit we just paid for (do NOT call auditCommand — that
179
181
  // would trigger a second, unpaid audit via /checkout).
180
182
  await streamAuditEvents(apiUrl, auditId);
package/dist/index.js CHANGED
@@ -1,13 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import { readFileSync } from "node:fs";
3
4
  import { auditCommand } from "./commands/audit.js";
4
5
  import { checkCommand } from "./commands/check.js";
5
6
  import { installCommand } from "./commands/install.js";
7
+ function readPackageVersion() {
8
+ try {
9
+ const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
10
+ return typeof pkg.version === "string" ? pkg.version : "0.0.0";
11
+ }
12
+ catch {
13
+ return "0.0.0";
14
+ }
15
+ }
6
16
  const program = new Command();
7
17
  program
8
18
  .name("npmguard")
9
19
  .description("NpmGuard CLI — audit npm packages for security issues")
10
- .version("1.0.0")
20
+ .version(readPackageVersion())
11
21
  .option("--api <url>", "NpmGuard engine API URL", process.env.NPMGUARD_API_URL ?? "https://npmguard.com");
12
22
  program
13
23
  .command("audit")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "npmguard-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "type": "module",
5
5
  "description": "NpmGuard CLI — check npm packages against NpmGuard security audits",
6
6
  "main": "dist/index.js",
@@ -8,7 +8,7 @@
8
8
  "dist"
9
9
  ],
10
10
  "bin": {
11
- "npmguard": "./dist/index.js"
11
+ "npmguard": "dist/index.js"
12
12
  },
13
13
  "scripts": {
14
14
  "build": "tsc"
@@ -27,7 +27,7 @@
27
27
  "eventsource": "^2.0.2",
28
28
  "ora": "^8.1.0",
29
29
  "qrcode-terminal": "^0.12.0",
30
- "viem": "^2.47.17"
30
+ "viem": "^2.52.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^22.0.0",