coverme-scanner 1.1.0 → 1.3.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/README.md CHANGED
@@ -1,127 +1,456 @@
1
- # CoverMe Scanner
1
+ <div align="center">
2
2
 
3
- **Multi-Agent AI Code Scanner for Claude Code**
3
+ # CoverMe
4
4
 
5
- One command. 7 AI agents. Complete code analysis with cross-validation.
5
+ ### The Most Comprehensive AI Security Scanner for Your Codebase
6
+
7
+ **22 AI Agents | Auto-Detection | Runtime Verification | Zero Config**
8
+
9
+ [![npm version](https://img.shields.io/npm/v/coverme-scanner.svg?style=flat-square)](https://www.npmjs.com/package/coverme-scanner)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
11
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
12
+
13
+ <img src="https://raw.githubusercontent.com/vibecode/coverme-scanner/main/assets/demo.gif" alt="CoverMe Demo" width="600">
14
+
15
+ [Quick Start](#quick-start) | [Features](#features) | [Agents](#-21-specialized-agents) | [Reports](#-beautiful-reports) | [Custom Agents](#-custom-agents)
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ ## Why CoverMe?
22
+
23
+ Traditional security scanners are **noisy** (too many false positives) and **blind** (miss context-specific issues).
24
+
25
+ CoverMe is different:
26
+
27
+ | Traditional Scanners | CoverMe |
28
+ |---------------------|---------|
29
+ | Single-pass analysis | **21 specialized AI agents** working in parallel |
30
+ | Pattern matching | **Deep understanding** of your code's intent |
31
+ | Generic rules | **Auto-detects** your stack and adapts |
32
+ | 60%+ false positives | **Cross-validation** eliminates noise |
33
+ | Requires configuration | **Zero config** - just run it |
34
+
35
+ ---
6
36
 
7
37
  ## Quick Start
8
38
 
9
39
  ```bash
10
- # Install
40
+ # Install globally
11
41
  npm install -g coverme-scanner
12
42
 
13
- # Initialize in your project
43
+ # Initialize in your project (one-time)
14
44
  coverme init
15
45
 
16
- # In Claude Code, run:
46
+ # Run the scan (in Claude Code)
17
47
  /coverme
18
48
  ```
19
49
 
20
- That's it! The scan will analyze your codebase and generate an HTML report.
50
+ **That's it.** Watch 22 AI agents analyze your entire codebase and generate a beautiful HTML report.
51
+
52
+ ---
53
+
54
+ ## Features
55
+
56
+ ### Auto-Detection
57
+
58
+ CoverMe automatically detects your stack and adapts its scanning:
59
+
60
+ | Category | Auto-Detected |
61
+ |----------|---------------|
62
+ | **Auth** | OAuth, JWT, Session, Clerk, Auth0, NextAuth, Supabase Auth, Firebase, Passport.js, API Keys |
63
+ | **Database** | PostgreSQL, MySQL, MongoDB, Redis, DynamoDB, Supabase, Prisma, TypeORM, Drizzle, PlanetScale, Neon, Turso |
64
+ | **Framework** | React, Next.js, Express, Fastify, NestJS, Django, FastAPI, Flask |
65
+ | **AI/LLM** | OpenAI, Anthropic, LangChain, Ollama, HuggingFace, Bedrock, Vertex AI |
66
+ | **Infra** | Docker, Kubernetes, Terraform, GitHub Actions, GitLab CI |
67
+
68
+ ### Smart Skipping
69
+
70
+ Agents that aren't relevant to your project **automatically skip**:
71
+ - No AI code? AI Security Scanner skips.
72
+ - No Redis? Redis Scanner skips.
73
+ - No enclaves? Enclave Scanner skips.
74
+
75
+ **Zero noise. Maximum relevance.**
76
+
77
+ ---
78
+
79
+ ## 22 Specialized Agents
80
+
81
+ <details>
82
+ <summary><b>Security Agents (Click to expand)</b></summary>
83
+
84
+ | Agent | What It Finds |
85
+ |-------|---------------|
86
+ | **Security Core** | OWASP Top 10, SQL/NoSQL injection, XSS, Command injection, SSRF, Path traversal |
87
+ | **Auth & Session** | OAuth flaws, JWT vulnerabilities, session fixation, cookie security, MFA bypass |
88
+ | **API Security** | CORS misconfiguration, rate limiting, IDOR, mass assignment, webhook security |
89
+ | **Database** | SQL injection, ORM-specific issues, connection security, RLS bypass |
90
+ | **Redis & Cache** | KEYS command abuse, Lua injection, cache poisoning, session security |
91
+ | **AI/LLM** | Prompt injection, content filter bypass, PII in prompts, jailbreak vectors |
92
+
93
+ </details>
94
+
95
+ <details>
96
+ <summary><b>Quality & Architecture Agents (Click to expand)</b></summary>
97
+
98
+ | Agent | What It Finds |
99
+ |-------|---------------|
100
+ | **Infrastructure** | Docker security, K8s misconfig, CI/CD secrets, IaC issues |
101
+ | **Data & Privacy** | PII exposure, GDPR violations, encryption gaps, data retention |
102
+ | **Performance** | N+1 queries, memory leaks, ReDoS, blocking operations |
103
+ | **Business Logic** | Race conditions, TOCTOU, workflow bypass, pricing exploits |
104
+ | **Code Quality** | Complexity, dead code, error handling, anti-patterns |
105
+ | **Dead Code** | Unused dependencies, unreachable code, stale feature flags |
106
+
107
+ </details>
108
+
109
+ <details>
110
+ <summary><b>Validation Agents (Click to expand)</b></summary>
111
+
112
+ | Agent | What It Does |
113
+ |-------|--------------|
114
+ | **Design Decision Detector** | Identifies intentional patterns to prevent false positives |
115
+ | **Context-Aware Validator** | Understands deployment context (K8s, API gateway, WAF) |
116
+ | **Network & Architecture** | Service boundaries, trust zones, NetworkPolicy gaps |
117
+ | **Resilience & Fallback** | Circuit breakers, retry patterns, graceful degradation |
118
+ | **Testing & Reliability** | Test coverage gaps, missing health checks |
119
+ | **Duplicate Scanner** | Finds existing solutions in your codebase |
120
+ | **Executive Summary** | Generates high-level risk overview |
121
+ | **Runtime Verification** | SSH to compare actual runtime vs code config |
122
+
123
+ </details>
124
+
125
+ ---
126
+
127
+ ## Beautiful Reports
128
+
129
+ CoverMe generates **professional HTML reports** with:
130
+
131
+ <table>
132
+ <tr>
133
+ <td width="50%">
134
+
135
+ **Executive Summary**
136
+ - Risk level assessment
137
+ - Top risks bullet points
138
+ - Findings by owner (Dev/DevOps/Architect)
139
+
140
+ **Project Overview**
141
+ - Auto-detected stack
142
+ - Architecture type
143
+ - Key components
144
+
145
+ </td>
146
+ <td width="50%">
147
+
148
+ **Detailed Findings**
149
+ - Severity scoring (DREAD)
150
+ - Code snippets with line numbers
151
+ - Copy-paste fix recommendations
152
+ - Claude Code prompts ready to use
153
+
154
+ **Smart Filtering**
155
+ - By severity
156
+ - By file
157
+ - By category
158
+ - By owner
159
+
160
+ </td>
161
+ </tr>
162
+ </table>
163
+
164
+ ### Sample Report Sections
165
+
166
+ ```
167
+ Executive Summary
168
+ -----------------
169
+ Risk Level: HIGH
170
+
171
+ Top Risks:
172
+ - SQL injection in user search allows database access
173
+ - Missing rate limiting enables brute force attacks
174
+ - Admin API exposed without IP restriction
175
+
176
+ Findings by Owner:
177
+ Developer: 5
178
+ DevOps: 3
179
+ Architect: 1
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Runtime Verification (SSH)
185
+
186
+ **The killer feature**: CoverMe can SSH into your servers and compare the **actual runtime** against your **code configuration**.
187
+
188
+ ### Why?
189
+
190
+ Your Dockerfile says `USER appuser`, but the container runs as `root`. Why? Because docker-compose overrides it. **This is why vulnerabilities become exploitable.**
191
+
192
+ ### Setup
193
+
194
+ ```bash
195
+ # Add your server (one-time)
196
+ coverme verify setup --host deploy@production.example.com --name production
197
+
198
+ # That's it! Now /coverme will automatically:
199
+ # 1. Scan your code
200
+ # 2. SSH to production
201
+ # 3. Compare expected vs actual
202
+ # 4. Report any mismatches
203
+ ```
204
+
205
+ ### What It Catches
206
+
207
+ | Issue | Example |
208
+ |-------|---------|
209
+ | **User Mismatch** | Dockerfile: `USER appuser` → Runtime: `root` |
210
+ | **Security Context Ignored** | K8s: `runAsNonRoot: true` → Pod runs as root |
211
+ | **Ports Exposed** | Code expects 3000 → Runtime has 3000, 6379, 5432 |
212
+ | **Permissions Wrong** | Expected: 755 → Actual: 777 |
213
+
214
+ ### Manage Environments
215
+
216
+ ```bash
217
+ coverme verify list # List all configured servers
218
+ coverme verify remove production # Remove an environment
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Custom Agents
224
+
225
+ Add your own specialized agents in seconds:
226
+
227
+ ```bash
228
+ # Add a custom agent
229
+ coverme agent add "John" "Check all .env files for exposed secrets"
230
+ coverme agent add "Sarah" "Find regex patterns vulnerable to ReDoS"
231
+ coverme agent add "Compliance" "Check for GDPR and PCI-DSS violations"
232
+
233
+ # List your agents
234
+ coverme agent list
235
+
236
+ # Remove an agent
237
+ coverme agent remove "John"
238
+ ```
239
+
240
+ Your custom agents run **alongside the 21 built-in agents** and appear in the same report.
241
+
242
+ ---
21
243
 
22
244
  ## How It Works
23
245
 
24
246
  ```
25
- ┌─────────────────────────────────────────────────────────────────┐
26
- │ COVERME ORCHESTRATOR │
27
- ├─────────────────────────────────────────────────────────────────┤
28
- │ │
29
- Phase 1: DISCOVERY (5 agents in parallel) │
30
- │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐│
31
- │ │ Security │ │ Quality │ │ Arch │ │ Deps │ │ Perf ││
32
- │ │ Agent │ │ Agent │ │ Agent │ │ Agent │ Agent ││
33
- │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───┬────┘│
34
- │ │ │ │ │ │
35
- │ └────────────┴────────────┴────────────┴───────────┘ │
36
- │ │ │
37
- │ ▼ │
38
- Phase 2: CROSS-VALIDATION (2 agents in parallel) │
39
- │ ┌──────────────────────────────────────────────────────────┐
40
- │ │ Cross-Validator: Challenge findings, find false positives │
41
- │ │ Deep-Dive Expert: Analyze disputed/complex issues │
42
- │ └──────────────────────────────────────────────────────────┘
43
- │ │ │
44
- │ ▼ │
45
- Phase 3: CONSENSUS & REPORT │
46
- ┌──────────────────────────────────────────────────────────┐ │
47
- │ │ Merge findings, calculate confidence, generate report │
48
- │ └──────────────────────────────────────────────────────────┘
49
- │ │
50
- └─────────────────────────────────────────────────────────────────┘
51
- ```
52
-
53
- ## What It Finds
54
-
55
- ### Security Issues
56
- - SQL/NoSQL Injection
57
- - Cross-Site Scripting (XSS)
58
- - Command Injection
59
- - Authentication/Authorization flaws
60
- - Hardcoded secrets
61
- - SSRF, Path Traversal
62
-
63
- ### Code Quality
64
- - DRY violations
65
- - High complexity functions
66
- - Dead code
67
- - Anti-patterns
68
- - Error handling problems
69
-
70
- ### Architecture Issues
71
- - Layer violations
72
- - Circular dependencies
73
- - Missing abstractions
74
- - Coupling problems
75
-
76
- ### Dependency Issues
77
- - Known CVEs
78
- - Outdated packages
79
- - License compliance
80
-
81
- ### Performance Issues
82
- - N+1 queries
83
- - Memory leaks
84
- - Blocking operations
85
-
86
- ## Why Multi-Agent?
87
-
88
- Traditional scanners have high false positive rates. CoverMe uses a unique approach:
89
-
90
- 1. **Multiple perspectives**: 5 specialized agents scan independently
91
- 2. **Cross-validation**: 2 validators challenge the findings
92
- 3. **Consensus**: Only high-confidence findings make the report
93
-
94
- This results in:
95
- - **Lower false positive rate** - Validators catch mistakes
96
- - **Higher coverage** - Multiple agents find different issues
97
- - **Confidence scores** - Know how certain each finding is
98
-
99
- ## Report Output
100
-
101
- The scan produces an HTML report in `.coverme/` folder:
102
-
103
- - **Score** - A-F grade with severity breakdown
104
- - **Critical/High/Medium/Low Issues** - With code context and fixes
105
- - **Claude Code Prompts** - Copy-paste ready fix instructions
106
- - **Positive Observations** - Good patterns found in your code
107
-
108
- ## Requirements
109
-
110
- - Claude Code CLI installed and authenticated
111
- - Node.js 18+
247
+ COVERME ORCHESTRATOR
248
+ ________________________________________________________________
249
+ | |
250
+ | PHASE 0: PROJECT DISCOVERY |
251
+ | [Auto-detect stack, auth, databases, frameworks] |
252
+ |________________________________________________________________|
253
+ | |
254
+ | PHASE 1: PARALLEL DISCOVERY (21 agents) |
255
+ | |
256
+ | Security Auth API Infra Data AI/LLM |
257
+ | | | | | | | |
258
+ | Database Redis Quality Logic Perf Dead |
259
+ | | | | | | | |
260
+ | PII Resil Network Design CTX Custom... |
261
+ | | | | | | | |
262
+ | +----+----+--------+----+----+--------+----+---+ |
263
+ | | | | |
264
+ | v v v |
265
+ |________________________________________________________________|
266
+ | |
267
+ | PHASE 2: CROSS-VALIDATION |
268
+ | [Challenge findings, find mitigations, detect false positives]|
269
+ |________________________________________________________________|
270
+ | |
271
+ | PHASE 3: CONSENSUS |
272
+ | [Merge, dedupe, calculate confidence, generate report] |
273
+ |________________________________________________________________|
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Installation
279
+
280
+ ### Requirements
281
+
282
+ - **Node.js 18+**
283
+ - **Claude Code** CLI installed and authenticated
112
284
  - No external API keys needed (uses your Claude Code session)
113
285
 
114
- ## Commands
286
+ ### Install
287
+
288
+ ```bash
289
+ npm install -g coverme-scanner
290
+ ```
291
+
292
+ ### Initialize (once per project)
293
+
294
+ ```bash
295
+ cd your-project
296
+ coverme init
297
+ ```
298
+
299
+ This creates:
300
+ - `.coverme/` folder for reports
301
+ - `.claude/commands/coverme.md` slash command
302
+
303
+ ### Run
304
+
305
+ In Claude Code:
306
+ ```
307
+ /coverme
308
+ ```
309
+
310
+ Or with arguments:
311
+ ```
312
+ /coverme src/
313
+ ```
314
+
315
+ ---
316
+
317
+ ## CLI Commands
115
318
 
116
319
  ```bash
117
- # Initialize in current project
320
+ # Initialize CoverMe in a project
118
321
  coverme init
119
322
 
120
- # Generate report from JSON
323
+ # Generate HTML report from JSON
121
324
  coverme report scan.json -f html -o report.html
325
+
326
+ # Custom Agents
327
+ coverme agent add "Name" "Task description"
328
+ coverme agent list
329
+ coverme agent remove "Name"
330
+
331
+ # Help
332
+ coverme --help
333
+ ```
334
+
335
+ ---
336
+
337
+ ## Configuration
338
+
339
+ CoverMe works **zero-config** out of the box, but you can customize:
340
+
341
+ ### Custom Agents
342
+
343
+ Create `.coverme/agents.json`:
344
+
345
+ ```json
346
+ {
347
+ "agents": [
348
+ { "name": "Security Lead", "task": "Review all auth flows for OWASP compliance" },
349
+ { "name": "Performance", "task": "Find N+1 queries and memory leaks" }
350
+ ]
351
+ }
352
+ ```
353
+
354
+ ### Ignore Patterns
355
+
356
+ Add to `.coverme/config.json`:
357
+
358
+ ```json
359
+ {
360
+ "ignore": [
361
+ "node_modules",
362
+ "dist",
363
+ "*.test.ts",
364
+ "**/__mocks__/**"
365
+ ]
366
+ }
367
+ ```
368
+
369
+ ---
370
+
371
+ ## FAQ
372
+
373
+ <details>
374
+ <summary><b>How long does a scan take?</b></summary>
375
+
376
+ Typically 2-5 minutes depending on codebase size. All 22 agents run in parallel.
377
+
378
+ </details>
379
+
380
+ <details>
381
+ <summary><b>Does it send my code anywhere?</b></summary>
382
+
383
+ CoverMe runs entirely through your local Claude Code session. Your code is processed by the same Claude API you're already using.
384
+
385
+ </details>
386
+
387
+ <details>
388
+ <summary><b>Can I use it in CI/CD?</b></summary>
389
+
390
+ Not yet, but it's on the roadmap. Currently CoverMe requires an interactive Claude Code session.
391
+
392
+ </details>
393
+
394
+ <details>
395
+ <summary><b>What languages does it support?</b></summary>
396
+
397
+ Any language Claude understands: TypeScript, JavaScript, Python, Go, Rust, Java, C#, Ruby, PHP, and more.
398
+
399
+ </details>
400
+
401
+ <details>
402
+ <summary><b>How do I reduce false positives?</b></summary>
403
+
404
+ CoverMe already has multiple validation agents that eliminate most false positives. For remaining cases:
405
+ 1. Add comments like `// Intentional: ...` to document design decisions
406
+ 2. Create custom agents for your specific patterns
407
+ 3. The Design Decision Detector will learn from these
408
+
409
+ </details>
410
+
411
+ ---
412
+
413
+ ## Roadmap
414
+
415
+ - [ ] CI/CD integration (GitHub Action)
416
+ - [ ] VS Code extension
417
+ - [ ] Baseline comparison (diff between scans)
418
+ - [ ] Custom rule definitions
419
+ - [ ] Team dashboard
420
+ - [ ] Slack/Discord notifications
421
+
422
+ ---
423
+
424
+ ## Contributing
425
+
426
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.
427
+
428
+ ```bash
429
+ # Clone the repo
430
+ git clone https://github.com/vibecode/coverme-scanner.git
431
+
432
+ # Install dependencies
433
+ npm install
434
+
435
+ # Build
436
+ npm run build
437
+
438
+ # Test locally
439
+ npm link
122
440
  ```
123
441
 
442
+ ---
443
+
124
444
  ## License
125
445
 
126
- MIT
446
+ MIT - see [LICENSE](LICENSE)
447
+
448
+ ---
449
+
450
+ <div align="center">
451
+
452
+ **Built with Claude Code**
453
+
454
+ [Report Bug](https://github.com/vibecode/coverme-scanner/issues) | [Request Feature](https://github.com/vibecode/coverme-scanner/issues) | [Star on GitHub](https://github.com/vibecode/coverme-scanner)
127
455
 
456
+ </div>
package/dist/cli/index.js CHANGED
@@ -105,5 +105,115 @@ agentCmd
105
105
  (0, fs_1.writeFileSync)(agentsPath, JSON.stringify(agents, null, 2));
106
106
  console.log(`Removed agent "${removed.name}"`);
107
107
  });
108
+ // Runtime verification commands
109
+ const verifyCmd = program
110
+ .command('verify')
111
+ .description('Verify runtime environment matches code expectations');
112
+ verifyCmd
113
+ .command('setup')
114
+ .description('Configure SSH access for runtime verification')
115
+ .option('-h, --host <host>', 'SSH host (e.g., user@server.com)')
116
+ .option('-p, --port <port>', 'SSH port', '22')
117
+ .option('-k, --key <path>', 'Path to SSH private key')
118
+ .option('-n, --name <name>', 'Environment name (e.g., production, staging)')
119
+ .action((options) => {
120
+ const covermeDir = (0, path_1.join)(process.cwd(), '.coverme');
121
+ const configPath = (0, path_1.join)(covermeDir, 'runtime.json');
122
+ if (!(0, fs_1.existsSync)(covermeDir)) {
123
+ (0, fs_1.mkdirSync)(covermeDir, { recursive: true });
124
+ }
125
+ let config = { environments: [] };
126
+ if ((0, fs_1.existsSync)(configPath)) {
127
+ config = JSON.parse((0, fs_1.readFileSync)(configPath, 'utf-8'));
128
+ if (!config.environments)
129
+ config.environments = [];
130
+ }
131
+ if (!options.host) {
132
+ console.log('\nRuntime Verification Setup');
133
+ console.log('==========================\n');
134
+ console.log('This feature allows CoverMe to SSH into your servers and compare');
135
+ console.log('the actual runtime environment against your code configuration.\n');
136
+ console.log('Usage:');
137
+ console.log(' coverme verify setup --host user@server.com --name production');
138
+ console.log(' coverme verify setup --host deploy@staging.example.com --key ~/.ssh/id_rsa --name staging\n');
139
+ console.log('Options:');
140
+ console.log(' -h, --host <host> SSH host (required)');
141
+ console.log(' -n, --name <name> Environment name (default: from host)');
142
+ console.log(' -p, --port <port> SSH port (default: 22)');
143
+ console.log(' -k, --key <path> Path to SSH private key\n');
144
+ if (config.environments.length > 0) {
145
+ console.log('Configured environments:');
146
+ config.environments.forEach((env, i) => {
147
+ console.log(` ${i + 1}. ${env.name}: ${env.host}:${env.port}`);
148
+ });
149
+ }
150
+ return;
151
+ }
152
+ const envName = options.name || options.host.split('@')[1]?.split('.')[0] || 'default';
153
+ // Remove existing with same name
154
+ config.environments = config.environments.filter((e) => e.name !== envName);
155
+ config.environments.push({
156
+ name: envName,
157
+ host: options.host,
158
+ port: parseInt(options.port || '22'),
159
+ keyPath: options.key || null,
160
+ addedAt: new Date().toISOString()
161
+ });
162
+ (0, fs_1.writeFileSync)(configPath, JSON.stringify(config, null, 2));
163
+ console.log(`\nAdded environment "${envName}"`);
164
+ console.log(` Host: ${options.host}`);
165
+ console.log(` Port: ${options.port || '22'}`);
166
+ if (options.key)
167
+ console.log(` Key: ${options.key}`);
168
+ console.log('\nRun verification with:');
169
+ console.log(` /coverme-verify ${envName}`);
170
+ console.log('\nOr in Claude Code:');
171
+ console.log(` /coverme --verify ${envName}`);
172
+ });
173
+ verifyCmd
174
+ .command('list')
175
+ .description('List configured environments')
176
+ .action(() => {
177
+ const configPath = (0, path_1.join)(process.cwd(), '.coverme', 'runtime.json');
178
+ if (!(0, fs_1.existsSync)(configPath)) {
179
+ console.log('No environments configured.');
180
+ console.log('Run: coverme verify setup --host user@server.com --name production');
181
+ return;
182
+ }
183
+ const config = JSON.parse((0, fs_1.readFileSync)(configPath, 'utf-8'));
184
+ if (!config.environments || config.environments.length === 0) {
185
+ console.log('No environments configured.');
186
+ return;
187
+ }
188
+ console.log('\nConfigured Environments:\n');
189
+ config.environments.forEach((env, i) => {
190
+ console.log(` ${i + 1}. ${env.name}`);
191
+ console.log(` Host: ${env.host}:${env.port}`);
192
+ if (env.keyPath)
193
+ console.log(` Key: ${env.keyPath}`);
194
+ console.log(` Added: ${new Date(env.addedAt).toLocaleDateString()}`);
195
+ console.log('');
196
+ });
197
+ });
198
+ verifyCmd
199
+ .command('remove')
200
+ .description('Remove an environment')
201
+ .argument('<name>', 'Environment name')
202
+ .action((name) => {
203
+ const configPath = (0, path_1.join)(process.cwd(), '.coverme', 'runtime.json');
204
+ if (!(0, fs_1.existsSync)(configPath)) {
205
+ console.error('No environments configured.');
206
+ return;
207
+ }
208
+ const config = JSON.parse((0, fs_1.readFileSync)(configPath, 'utf-8'));
209
+ const idx = config.environments.findIndex((e) => e.name.toLowerCase() === name.toLowerCase());
210
+ if (idx === -1) {
211
+ console.error(`Environment "${name}" not found`);
212
+ return;
213
+ }
214
+ const removed = config.environments.splice(idx, 1)[0];
215
+ (0, fs_1.writeFileSync)(configPath, JSON.stringify(config, null, 2));
216
+ console.log(`Removed environment "${removed.name}"`);
217
+ });
108
218
  program.parse();
109
219
  //# sourceMappingURL=index.js.map