bilt-toolkit 1.0.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/LICENSE +0 -0
- package/README.md +168 -0
- package/bin/bilt.js +2 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +161 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/doctor.d.ts +13 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +194 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/fix.d.ts +12 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +273 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +101 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/scan.d.ts +17 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +267 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/undo.d.ts +12 -0
- package/dist/commands/undo.d.ts.map +1 -0
- package/dist/commands/undo.js +90 -0
- package/dist/commands/undo.js.map +1 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +68 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/config.d.ts +8 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +75 -0
- package/dist/config/config.js.map +1 -0
- package/dist/core/fix/confirm.d.ts +21 -0
- package/dist/core/fix/confirm.d.ts.map +1 -0
- package/dist/core/fix/confirm.js +60 -0
- package/dist/core/fix/confirm.js.map +1 -0
- package/dist/core/fix/env-fix.d.ts +40 -0
- package/dist/core/fix/env-fix.d.ts.map +1 -0
- package/dist/core/fix/env-fix.js +186 -0
- package/dist/core/fix/env-fix.js.map +1 -0
- package/dist/core/fix/snapshot.d.ts +30 -0
- package/dist/core/fix/snapshot.d.ts.map +1 -0
- package/dist/core/fix/snapshot.js +186 -0
- package/dist/core/fix/snapshot.js.map +1 -0
- package/dist/core/rules/entropy.d.ts +29 -0
- package/dist/core/rules/entropy.d.ts.map +1 -0
- package/dist/core/rules/entropy.js +117 -0
- package/dist/core/rules/entropy.js.map +1 -0
- package/dist/core/rules/providers.d.ts +12 -0
- package/dist/core/rules/providers.d.ts.map +1 -0
- package/dist/core/rules/providers.js +184 -0
- package/dist/core/rules/providers.js.map +1 -0
- package/dist/core/rules/secret-rules.d.ts +3 -0
- package/dist/core/rules/secret-rules.d.ts.map +1 -0
- package/dist/core/rules/secret-rules.js +205 -0
- package/dist/core/rules/secret-rules.js.map +1 -0
- package/dist/core/scan/env.d.ts +47 -0
- package/dist/core/scan/env.d.ts.map +1 -0
- package/dist/core/scan/env.js +301 -0
- package/dist/core/scan/env.js.map +1 -0
- package/dist/core/scan/framework.d.ts +26 -0
- package/dist/core/scan/framework.d.ts.map +1 -0
- package/dist/core/scan/framework.js +254 -0
- package/dist/core/scan/framework.js.map +1 -0
- package/dist/core/scan/gitignore.d.ts +20 -0
- package/dist/core/scan/gitignore.d.ts.map +1 -0
- package/dist/core/scan/gitignore.js +217 -0
- package/dist/core/scan/gitignore.js.map +1 -0
- package/dist/core/scan/secrets.d.ts +27 -0
- package/dist/core/scan/secrets.d.ts.map +1 -0
- package/dist/core/scan/secrets.js +247 -0
- package/dist/core/scan/secrets.js.map +1 -0
- package/dist/core/score/health.d.ts +29 -0
- package/dist/core/score/health.d.ts.map +1 -0
- package/dist/core/score/health.js +73 -0
- package/dist/core/score/health.js.map +1 -0
- package/dist/core/watch/watcher.d.ts +29 -0
- package/dist/core/watch/watcher.d.ts.map +1 -0
- package/dist/core/watch/watcher.js +176 -0
- package/dist/core/watch/watcher.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/interface.d.ts +12 -0
- package/dist/plugins/interface.d.ts.map +1 -0
- package/dist/plugins/interface.js +91 -0
- package/dist/plugins/interface.js.map +1 -0
- package/dist/plugins/loader.d.ts +10 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +104 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/official/docker.d.ts +4 -0
- package/dist/plugins/official/docker.d.ts.map +1 -0
- package/dist/plugins/official/docker.js +111 -0
- package/dist/plugins/official/docker.js.map +1 -0
- package/dist/plugins/official/terraform.d.ts +4 -0
- package/dist/plugins/official/terraform.d.ts.map +1 -0
- package/dist/plugins/official/terraform.js +131 -0
- package/dist/plugins/official/terraform.js.map +1 -0
- package/dist/types/index.d.ts +158 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/format.d.ts +43 -0
- package/dist/ui/format.d.ts.map +1 -0
- package/dist/ui/format.js +207 -0
- package/dist/ui/format.js.map +1 -0
- package/dist/ui/reporter.d.ts +39 -0
- package/dist/ui/reporter.d.ts.map +1 -0
- package/dist/ui/reporter.js +254 -0
- package/dist/ui/reporter.js.map +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
File without changes
|
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# 🏗️ BILT
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](<>)
|
|
6
|
+
[](<>)
|
|
7
|
+
|
|
8
|
+
> **Zero-configuration project health toolkit.** Catch secrets, fix environment variable issues, and keep your local repository clean before it ever reaches Git — with a safety net.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
____ _ _ _____
|
|
14
|
+
| _ \ | | | | |_ _|
|
|
15
|
+
| |_) | | | | | | |
|
|
16
|
+
| _ < | | | |___ | |
|
|
17
|
+
| |_) | |_| |_____| |_|
|
|
18
|
+
|____/
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Bilt is a developer-focused utility designed to keep environment configurations healthy and prevent credentials leaks. It runs offline, requires zero configuration, and provides interactive, safe auto-fixing.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🚀 Quick Start
|
|
26
|
+
|
|
27
|
+
Initialize Bilt on your current project in one command:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx bilt init
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This runs a full scan, hooks up a `.gitignore` guardrail, drafts template environment files, and prints a summary of your repository health.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 📦 Terminal Health Report Example
|
|
38
|
+
|
|
39
|
+
When you scan your project, Bilt prints a beautiful health report card:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
╭──────────────────────────────────────────────────╮
|
|
43
|
+
│ │
|
|
44
|
+
│ 🏗️ BILT HEALTH REPORT │
|
|
45
|
+
│ │
|
|
46
|
+
│ Score: 92/100 Grade: A │
|
|
47
|
+
│ ██████████████████████░░░ 92% │
|
|
48
|
+
│ │
|
|
49
|
+
│ ✓ Secrets: Clean │
|
|
50
|
+
│ ⚠ Env vars: 2 missing in .env │
|
|
51
|
+
│ ✓ .gitignore: OK │
|
|
52
|
+
│ ✓ Framework: Next.js detected │
|
|
53
|
+
│ │
|
|
54
|
+
╰──────────────────────────────────────────────────╯
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 🛠️ CLI Commands & Options
|
|
60
|
+
|
|
61
|
+
| Command | Description | Core Options |
|
|
62
|
+
| :---------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------ |
|
|
63
|
+
| **`bilt init`** | Zero-friction onboarding. Scans the project, creates a local backup snapshot, auto-fixes safe issues (like missing `.gitignore` files or environment templates), and prints a health card. | None |
|
|
64
|
+
| **`bilt scan`** | Scans the working tree and git history for credential leaks, framework issues, and environment mismatches. | `--full-history` (scan all commits), `--json` (machine output), `--severity <level>` (filter), `--verbose`, `--fun` |
|
|
65
|
+
| **`bilt fix`** | Safely applies automated fixes. Can be run in interactive mode (prompts on every non-safe fix) or auto-pilot. | `--safe` (apply safe fixes only), `--dry-run` (preview changes), `--verbose`, `--quiet` |
|
|
66
|
+
| **`bilt undo`** | Reverts the last set of changes made by `bilt fix`. Shows a colored line-by-line diff and requires confirmation before restoring. | None |
|
|
67
|
+
| **`bilt watch`** | Runs a file-watching background daemon. Monitors your files as you edit and save them, instantly flagging secrets or env issues in real-time. | `--quiet`, `--debounce <ms>` (default: 300ms) |
|
|
68
|
+
| **`bilt doctor`** | Displays a detailed, comprehensive health breakdown categorized by severity with explicit recommendations. | `--card` (outputs markdown summary), `--fun` |
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ✨ Key Features & Differentiators
|
|
73
|
+
|
|
74
|
+
### 1. Real-time Protection (File Watcher Daemon)
|
|
75
|
+
|
|
76
|
+
Unlike traditional scanner hooks that only run during commits, Bilt has a file watcher daemon (`bilt watch`) that detects leaks **the moment you type or save a file**. If you accidentally paste a Stripe secret key into `config.js`, Bilt immediately triggers a terminal notification:
|
|
77
|
+
|
|
78
|
+
> 🔴 Stripe API Key detected in `config.js` line 12 — want me to move it to `.env`?
|
|
79
|
+
|
|
80
|
+
### 2. The Safety Undo Net
|
|
81
|
+
|
|
82
|
+
Bilt is the only tool that cannot accidentally corrupt your codebase.
|
|
83
|
+
|
|
84
|
+
- Before applying any change that edits files, modifies git history, or removes items, Bilt automatically takes a local file snapshot stored under `.bilt/snapshots/`.
|
|
85
|
+
- Every irreversible fix requires typing `confirm` to proceed.
|
|
86
|
+
- If something breaks, simply run **`bilt undo`** to view the diff and restore your files to their exact pre-fix state.
|
|
87
|
+
|
|
88
|
+
### 3. Framework-Aware Intelligence
|
|
89
|
+
|
|
90
|
+
Bilt automatically inspects your dependencies and configuration files to detect the framework you are using (Next.js, Vite, Create React App, Django, Rails, etc.).
|
|
91
|
+
It understands which prefixes expose variables to the browser bundle (e.g. `NEXT_PUBLIC_`, `VITE_`, `REACT_APP_`). If a secret is placed inside a variable with one of these prefixes, it flags it as a **critical vulnerability** since it will be leaked to web browsers.
|
|
92
|
+
|
|
93
|
+
### 4. Interactive Secret Rotation Assistance
|
|
94
|
+
|
|
95
|
+
When a secret is found, Bilt maps the credential to its specific SaaS provider (Stripe, AWS, OpenAI, GitHub, Supabase, Twilio, SendGrid, etc.) and provides a direct, clickable deep-link to the exact rotation settings console so you can revoke the token immediately.
|
|
96
|
+
|
|
97
|
+
### 5. False Positive Management
|
|
98
|
+
|
|
99
|
+
If a credential check is a false positive (such as a public key meant for client-side use), you can tell Bilt to ignore the line.
|
|
100
|
+
Add a comment containing `# gitleaks:allow` or `# bilt:allow` on the line itself, or on the line directly above it:
|
|
101
|
+
|
|
102
|
+
```env
|
|
103
|
+
# gitleaks:allow
|
|
104
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## ⚙️ Configuration (`.biltrc.json`)
|
|
110
|
+
|
|
111
|
+
Bilt is zero-config by default, but you can customize it by placing a `.biltrc.json` file in your project root:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"ignore": ["tests/fixtures/**", "legacy-code/**"],
|
|
116
|
+
"entropyThreshold": 4.5,
|
|
117
|
+
"historyDepth": 15,
|
|
118
|
+
"severityOverrides": {
|
|
119
|
+
"env-mismatch": "warning",
|
|
120
|
+
"dockerfile-leak": "critical"
|
|
121
|
+
},
|
|
122
|
+
"customRules": [
|
|
123
|
+
{
|
|
124
|
+
"id": "my-custom-token",
|
|
125
|
+
"name": "Custom Organization Token",
|
|
126
|
+
"pattern": "org-token-[a-f0-9]{16}",
|
|
127
|
+
"severity": "critical"
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"funMode": true
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🔌 Extensible Plugin System
|
|
137
|
+
|
|
138
|
+
Bilt allows developers to write custom plugins to scan specialized files (e.g. Terraform configs, Dockerfiles).
|
|
139
|
+
|
|
140
|
+
### Example Plugin Interface
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import type { PluginManifest, PluginContext } from "bilt";
|
|
144
|
+
|
|
145
|
+
export const myPlugin: PluginManifest = {
|
|
146
|
+
name: "bilt-plugin-custom",
|
|
147
|
+
check: async (context: PluginContext) => {
|
|
148
|
+
// Scan files in context.projectDir
|
|
149
|
+
return {
|
|
150
|
+
findings: [
|
|
151
|
+
{
|
|
152
|
+
id: "custom-leak",
|
|
153
|
+
severity: "warning",
|
|
154
|
+
category: "plugin-finding",
|
|
155
|
+
message: "Custom pattern match found",
|
|
156
|
+
file: "config.json",
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 📄 License
|
|
167
|
+
|
|
168
|
+
MIT © [Samuel Yeshambel](https://github.com/Samuel-0228)
|
package/bin/bilt.js
ADDED
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ─── Bilt CLI Entry Point ────────────────────────────────────────────────────
|
|
3
|
+
// Zero-configuration project health toolkit.
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import { executeScan } from "./commands/scan.js";
|
|
8
|
+
import { executeInit } from "./commands/init.js";
|
|
9
|
+
import { executeFix } from "./commands/fix.js";
|
|
10
|
+
import { executeUndo } from "./commands/undo.js";
|
|
11
|
+
import { executeDoctor } from "./commands/doctor.js";
|
|
12
|
+
import { executeWatch } from "./commands/watch.js";
|
|
13
|
+
// ─── Version ─────────────────────────────────────────────────────────────────
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const pkg = require("../package.json");
|
|
16
|
+
// ─── Program Setup ───────────────────────────────────────────────────────────
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name("bilt")
|
|
20
|
+
.description("Zero-configuration project health toolkit. Catch secrets, fix env issues, and keep your repo clean.")
|
|
21
|
+
.version(pkg.version, "-v, --version")
|
|
22
|
+
.option("--no-color", "Disable colored output");
|
|
23
|
+
// ─── bilt scan ───────────────────────────────────────────────────────────────
|
|
24
|
+
program
|
|
25
|
+
.command("scan")
|
|
26
|
+
.description("Scan the project for secrets, env issues, and misconfigurations")
|
|
27
|
+
.argument("[dir]", "Project directory", ".")
|
|
28
|
+
.option("--full-history", "Scan all git history (not just recent commits)")
|
|
29
|
+
.option("--json", "Output results as JSON")
|
|
30
|
+
.option("--severity <level>", "Minimum severity to report (critical, warning, info)")
|
|
31
|
+
.option("--verbose", "Show detailed output with suggestions")
|
|
32
|
+
.option("--quiet", "Suppress all output except errors")
|
|
33
|
+
.option("--dry-run", "Show what would be scanned without scanning")
|
|
34
|
+
.option("--fun", "Enable fun mode with celebrations")
|
|
35
|
+
.action(async (dir, opts) => {
|
|
36
|
+
try {
|
|
37
|
+
const result = await executeScan(dir, {
|
|
38
|
+
fullHistory: opts.fullHistory,
|
|
39
|
+
json: opts.json,
|
|
40
|
+
severity: opts.severity,
|
|
41
|
+
verbose: opts.verbose,
|
|
42
|
+
quiet: opts.quiet,
|
|
43
|
+
dryRun: opts.dryRun,
|
|
44
|
+
fun: opts.fun,
|
|
45
|
+
});
|
|
46
|
+
// Exit code based on findings
|
|
47
|
+
const criticals = result.findings.filter((f) => f.severity === "critical").length;
|
|
48
|
+
if (criticals > 0) {
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
printError(error);
|
|
54
|
+
process.exitCode = 2;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
// ─── bilt init ───────────────────────────────────────────────────────────────
|
|
58
|
+
program
|
|
59
|
+
.command("init")
|
|
60
|
+
.description("Initialize Bilt — scan, auto-fix safe issues, and show health report")
|
|
61
|
+
.argument("[dir]", "Project directory", ".")
|
|
62
|
+
.action(async (dir) => {
|
|
63
|
+
try {
|
|
64
|
+
await executeInit(dir);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
printError(error);
|
|
68
|
+
process.exitCode = 2;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// ─── bilt fix ────────────────────────────────────────────────────────────────
|
|
72
|
+
program
|
|
73
|
+
.command("fix")
|
|
74
|
+
.description("Fix issues found by scan — interactively or automatically")
|
|
75
|
+
.argument("[dir]", "Project directory", ".")
|
|
76
|
+
.option("--safe", "Auto-apply safe fixes only (no prompts)")
|
|
77
|
+
.option("--dry-run", "Preview fixes without applying")
|
|
78
|
+
.option("--verbose", "Show detailed output")
|
|
79
|
+
.option("--quiet", "Suppress non-essential output")
|
|
80
|
+
.action(async (dir, opts) => {
|
|
81
|
+
try {
|
|
82
|
+
await executeFix(dir, {
|
|
83
|
+
safe: opts.safe,
|
|
84
|
+
dryRun: opts.dryRun,
|
|
85
|
+
verbose: opts.verbose,
|
|
86
|
+
quiet: opts.quiet,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
printError(error);
|
|
91
|
+
process.exitCode = 2;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// ─── bilt undo ───────────────────────────────────────────────────────────────
|
|
95
|
+
program
|
|
96
|
+
.command("undo")
|
|
97
|
+
.description("Undo the last set of changes made by bilt fix")
|
|
98
|
+
.argument("[dir]", "Project directory", ".")
|
|
99
|
+
.action(async (dir) => {
|
|
100
|
+
try {
|
|
101
|
+
await executeUndo(dir);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
printError(error);
|
|
105
|
+
process.exitCode = 2;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
// ─── bilt watch ──────────────────────────────────────────────────────────────
|
|
109
|
+
program
|
|
110
|
+
.command("watch")
|
|
111
|
+
.description("Watch the project for changes and scan in real-time")
|
|
112
|
+
.argument("[dir]", "Project directory", ".")
|
|
113
|
+
.option("--quiet", "Only show findings, no status messages")
|
|
114
|
+
.option("--debounce <ms>", "Debounce interval in milliseconds", "300")
|
|
115
|
+
.action(async (dir, opts) => {
|
|
116
|
+
try {
|
|
117
|
+
await executeWatch(dir, {
|
|
118
|
+
quiet: opts.quiet,
|
|
119
|
+
debounce: opts.debounce ? parseInt(opts.debounce, 10) : undefined,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
printError(error);
|
|
124
|
+
process.exitCode = 2;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// ─── bilt doctor ─────────────────────────────────────────────────────────────
|
|
128
|
+
program
|
|
129
|
+
.command("doctor")
|
|
130
|
+
.description("Comprehensive health report with detailed breakdown")
|
|
131
|
+
.argument("[dir]", "Project directory", ".")
|
|
132
|
+
.option("--card", "Output a markdown health card to stdout")
|
|
133
|
+
.option("--fun", "Enable celebrations and streak counter")
|
|
134
|
+
.action(async (dir, opts) => {
|
|
135
|
+
try {
|
|
136
|
+
await executeDoctor(dir, {
|
|
137
|
+
card: opts.card,
|
|
138
|
+
fun: opts.fun,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
printError(error);
|
|
143
|
+
process.exitCode = 2;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// ─── Error Handler ───────────────────────────────────────────────────────────
|
|
147
|
+
function printError(error) {
|
|
148
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
149
|
+
console.error("");
|
|
150
|
+
console.error(chalk.red.bold(` ✗ Error: ${message}`));
|
|
151
|
+
if (error instanceof Error && error.stack) {
|
|
152
|
+
const stackLines = error.stack.split("\n").slice(1, 4);
|
|
153
|
+
for (const line of stackLines) {
|
|
154
|
+
console.error(chalk.dim(` ${line.trim()}`));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
console.error("");
|
|
158
|
+
}
|
|
159
|
+
// ─── Parse & Run ─────────────────────────────────────────────────────────────
|
|
160
|
+
program.parse();
|
|
161
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execute the `bilt doctor` command.
|
|
3
|
+
*
|
|
4
|
+
* 1. Run full scan
|
|
5
|
+
* 2. Display comprehensive health report
|
|
6
|
+
* 3. If --card: output markdown summary
|
|
7
|
+
* 4. Show recommendations per category
|
|
8
|
+
*/
|
|
9
|
+
export declare function executeDoctor(projectDir: string, options?: {
|
|
10
|
+
card?: boolean;
|
|
11
|
+
fun?: boolean;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9C,OAAO,CAAC,IAAI,CAAC,CAqKf"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// ─── Doctor Command ──────────────────────────────────────────────────────────
|
|
2
|
+
// Comprehensive health report with detailed breakdown and recommendations.
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import boxen from "boxen";
|
|
6
|
+
import { executeScan } from "./scan.js";
|
|
7
|
+
import { formatHealthScore, severityIcon } from "../ui/format.js";
|
|
8
|
+
/**
|
|
9
|
+
* Execute the `bilt doctor` command.
|
|
10
|
+
*
|
|
11
|
+
* 1. Run full scan
|
|
12
|
+
* 2. Display comprehensive health report
|
|
13
|
+
* 3. If --card: output markdown summary
|
|
14
|
+
* 4. Show recommendations per category
|
|
15
|
+
*/
|
|
16
|
+
export async function executeDoctor(projectDir, options = {}) {
|
|
17
|
+
const rootDir = path.resolve(projectDir);
|
|
18
|
+
// ── Run full scan ───────────────────────────────────────────────────
|
|
19
|
+
const result = await executeScan(rootDir, {
|
|
20
|
+
quiet: true,
|
|
21
|
+
fullHistory: true,
|
|
22
|
+
});
|
|
23
|
+
const { findings, healthScore, grade, scannedFiles, duration, framework } = result;
|
|
24
|
+
// ── Markdown card mode ──────────────────────────────────────────────
|
|
25
|
+
if (options.card) {
|
|
26
|
+
const md = generateMarkdownCard(result.healthScore, result.grade, findings, framework?.displayName);
|
|
27
|
+
console.log(md);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// ── Header ──────────────────────────────────────────────────────────
|
|
31
|
+
console.log("");
|
|
32
|
+
const header = boxen(`\n${chalk.bold.cyan(" 🏗️ BILT DOCTOR — Comprehensive Health Report")}\n`, {
|
|
33
|
+
padding: 0,
|
|
34
|
+
margin: { top: 0, bottom: 0, left: 1, right: 1 },
|
|
35
|
+
borderStyle: "round",
|
|
36
|
+
borderColor: "cyan",
|
|
37
|
+
});
|
|
38
|
+
console.log(header);
|
|
39
|
+
console.log("");
|
|
40
|
+
// ── Overall score ───────────────────────────────────────────────────
|
|
41
|
+
console.log(chalk.bold(" 📊 Overall Health"));
|
|
42
|
+
console.log("");
|
|
43
|
+
console.log(` ${formatHealthScore(healthScore, grade)}`);
|
|
44
|
+
console.log("");
|
|
45
|
+
console.log(chalk.dim(` Scanned ${scannedFiles} files in ${duration}ms${framework ? ` • Framework: ${framework.displayName}` : ""}`));
|
|
46
|
+
console.log("");
|
|
47
|
+
// ── Fun mode ────────────────────────────────────────────────────────
|
|
48
|
+
if (options.fun) {
|
|
49
|
+
if (healthScore === 100) {
|
|
50
|
+
console.log(chalk.bold.green(" 🎉🏆🎉 PERFECT SCORE! You absolute legend! 🎉🏆🎉"));
|
|
51
|
+
console.log("");
|
|
52
|
+
}
|
|
53
|
+
else if (healthScore >= 90) {
|
|
54
|
+
console.log(chalk.green(" 🔥 So close to perfection — you got this!"));
|
|
55
|
+
console.log("");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ── Category breakdown ──────────────────────────────────────────────
|
|
59
|
+
console.log(chalk.bold(" 📋 Category Breakdown"));
|
|
60
|
+
console.log("");
|
|
61
|
+
const categories = [
|
|
62
|
+
{ key: "secret-detected", label: "Secret Detection", icon: "🔐" },
|
|
63
|
+
{ key: "env-missing", label: "Missing Env Vars", icon: "📦" },
|
|
64
|
+
{ key: "env-unused", label: "Unused Env Vars", icon: "🗑️" },
|
|
65
|
+
{ key: "env-mismatch", label: "Env Mismatches", icon: "🔀" },
|
|
66
|
+
{ key: "env-exposed", label: "Client-Exposed Secrets", icon: "🌐" },
|
|
67
|
+
{ key: "gitignore-missing", label: ".gitignore Coverage", icon: "📄" },
|
|
68
|
+
{ key: "framework-warning", label: "Framework Warnings", icon: "⚙️" },
|
|
69
|
+
{ key: "plugin-finding", label: "Plugin Findings", icon: "🔌" },
|
|
70
|
+
];
|
|
71
|
+
for (const cat of categories) {
|
|
72
|
+
const catFindings = findings.filter((f) => f.category === cat.key);
|
|
73
|
+
if (catFindings.length === 0) {
|
|
74
|
+
console.log(chalk.green(` ${cat.icon} ${cat.label}: ${chalk.bold("Clean")} ✓`));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const critCount = catFindings.filter((f) => f.severity === "critical").length;
|
|
78
|
+
const warnCount = catFindings.filter((f) => f.severity === "warning").length;
|
|
79
|
+
const infoCount = catFindings.filter((f) => f.severity === "info").length;
|
|
80
|
+
const parts = [];
|
|
81
|
+
if (critCount > 0)
|
|
82
|
+
parts.push(chalk.red(`${critCount} critical`));
|
|
83
|
+
if (warnCount > 0)
|
|
84
|
+
parts.push(chalk.yellow(`${warnCount} warning`));
|
|
85
|
+
if (infoCount > 0)
|
|
86
|
+
parts.push(chalk.cyan(`${infoCount} info`));
|
|
87
|
+
console.log(` ${cat.icon} ${cat.label}: ${parts.join(", ")} ${chalk.dim(`(${catFindings.length} total)`)}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
console.log("");
|
|
91
|
+
// ── Detailed findings ───────────────────────────────────────────────
|
|
92
|
+
if (findings.length > 0) {
|
|
93
|
+
console.log(chalk.bold(" 🔍 Detailed Findings"));
|
|
94
|
+
console.log("");
|
|
95
|
+
const order = ["critical", "warning", "info"];
|
|
96
|
+
for (const sev of order) {
|
|
97
|
+
const sevFindings = findings.filter((f) => f.severity === sev);
|
|
98
|
+
if (sevFindings.length === 0)
|
|
99
|
+
continue;
|
|
100
|
+
const icon = severityIcon(sev);
|
|
101
|
+
console.log(` ${icon} ${chalk.bold(sev.charAt(0).toUpperCase() + sev.slice(1))}`);
|
|
102
|
+
for (const f of sevFindings) {
|
|
103
|
+
const loc = f.line ? `${f.file}:${f.line}` : f.file;
|
|
104
|
+
console.log(` ${chalk.dim("›")} ${f.message} ${chalk.dim(loc)}`);
|
|
105
|
+
if (f.suggestion) {
|
|
106
|
+
console.log(chalk.dim(` 💡 ${f.suggestion}`));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
console.log("");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// ── Recommendations ─────────────────────────────────────────────────
|
|
113
|
+
console.log(chalk.bold(" 💡 Recommendations"));
|
|
114
|
+
console.log("");
|
|
115
|
+
const recommendations = generateRecommendations(findings);
|
|
116
|
+
if (recommendations.length === 0) {
|
|
117
|
+
console.log(chalk.green(" Everything looks great! No recommendations needed."));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
for (let i = 0; i < recommendations.length; i++) {
|
|
121
|
+
console.log(` ${chalk.cyan(`${i + 1}.`)} ${recommendations[i]}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
console.log("");
|
|
125
|
+
// ── Footer ──────────────────────────────────────────────────────────
|
|
126
|
+
const footer = boxen(chalk.dim(`\n Run ${chalk.white("bilt fix --safe")} to auto-fix safe issues\n` +
|
|
127
|
+
` Run ${chalk.white("bilt fix")} for interactive fix mode\n` +
|
|
128
|
+
` Run ${chalk.white("bilt watch")} for real-time monitoring\n`), {
|
|
129
|
+
padding: 0,
|
|
130
|
+
margin: { top: 0, bottom: 0, left: 1, right: 1 },
|
|
131
|
+
borderStyle: "round",
|
|
132
|
+
borderColor: "gray",
|
|
133
|
+
});
|
|
134
|
+
console.log(footer);
|
|
135
|
+
console.log("");
|
|
136
|
+
}
|
|
137
|
+
// ─── Recommendation Generator ────────────────────────────────────────────────
|
|
138
|
+
function generateRecommendations(findings) {
|
|
139
|
+
const recs = [];
|
|
140
|
+
const categories = new Set(findings.map((f) => f.category));
|
|
141
|
+
if (categories.has("secret-detected")) {
|
|
142
|
+
recs.push("Move hardcoded secrets to .env files and rotate compromised keys immediately.");
|
|
143
|
+
}
|
|
144
|
+
if (categories.has("gitignore-missing")) {
|
|
145
|
+
recs.push("Add .env file patterns to .gitignore to prevent accidental commits.");
|
|
146
|
+
}
|
|
147
|
+
if (categories.has("env-missing")) {
|
|
148
|
+
recs.push("Add missing environment variables or generate a .env.example for onboarding.");
|
|
149
|
+
}
|
|
150
|
+
if (categories.has("env-unused")) {
|
|
151
|
+
recs.push("Remove unused environment variables to keep your config clean.");
|
|
152
|
+
}
|
|
153
|
+
if (categories.has("env-mismatch")) {
|
|
154
|
+
recs.push("Sync environment files — ensure all environments have the same variables.");
|
|
155
|
+
}
|
|
156
|
+
if (categories.has("env-exposed")) {
|
|
157
|
+
recs.push("Review client-exposed env vars — only public keys should use framework-specific prefixes.");
|
|
158
|
+
}
|
|
159
|
+
if (categories.has("framework-warning")) {
|
|
160
|
+
recs.push("Review framework-specific configuration for potential security issues.");
|
|
161
|
+
}
|
|
162
|
+
if (categories.has("plugin-finding")) {
|
|
163
|
+
recs.push("Address plugin-specific findings — check Docker, Terraform, or other tool configurations.");
|
|
164
|
+
}
|
|
165
|
+
return recs;
|
|
166
|
+
}
|
|
167
|
+
// ─── Markdown Card Generator ─────────────────────────────────────────────────
|
|
168
|
+
function generateMarkdownCard(score, grade, findings, frameworkName) {
|
|
169
|
+
const criticals = findings.filter((f) => f.severity === "critical").length;
|
|
170
|
+
const warnings = findings.filter((f) => f.severity === "warning").length;
|
|
171
|
+
const infos = findings.filter((f) => f.severity === "info").length;
|
|
172
|
+
const barWidth = 20;
|
|
173
|
+
const filled = Math.round((score / 100) * barWidth);
|
|
174
|
+
const empty = barWidth - filled;
|
|
175
|
+
const bar = "█".repeat(filled) + "░".repeat(empty);
|
|
176
|
+
let md = "# 🏗️ Bilt Health Report\n\n";
|
|
177
|
+
md += `**Score:** ${score}/100 — **${grade}**\n\n`;
|
|
178
|
+
md += "```\n";
|
|
179
|
+
md += `${bar} ${score}%\n`;
|
|
180
|
+
md += "```\n\n";
|
|
181
|
+
md += "## Summary\n\n";
|
|
182
|
+
md += `| Metric | Count |\n`;
|
|
183
|
+
md += `|--------|-------|\n`;
|
|
184
|
+
md += `| 🔴 Critical | ${criticals} |\n`;
|
|
185
|
+
md += `| 🟡 Warning | ${warnings} |\n`;
|
|
186
|
+
md += `| 🔵 Info | ${infos} |\n`;
|
|
187
|
+
if (frameworkName) {
|
|
188
|
+
md += `\n**Framework:** ${frameworkName}\n`;
|
|
189
|
+
}
|
|
190
|
+
md += "\n---\n";
|
|
191
|
+
md += "*Generated by [Bilt](https://github.com/bilt-cli/bilt)*\n";
|
|
192
|
+
return md;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FixOptions } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Execute the `bilt fix` command.
|
|
4
|
+
*
|
|
5
|
+
* 1. Run scan to find issues
|
|
6
|
+
* 2. Generate fix actions
|
|
7
|
+
* 3. Apply fixes (auto for --safe, preview for --dry-run, interactive otherwise)
|
|
8
|
+
* 4. Create snapshot before applying
|
|
9
|
+
* 5. Report results
|
|
10
|
+
*/
|
|
11
|
+
export declare function executeFix(projectDir: string, options?: FixOptions): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=fix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix.d.ts","sourceRoot":"","sources":["../../src/commands/fix.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAA0B,MAAM,mBAAmB,CAAC;AAiB5E;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAoJf"}
|