goodvibesonly-cc 0.1.0 → 0.2.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 +17 -17
- package/bin/install.js +28 -28
- package/bin/scan.js +2 -2
- package/commands/{vibecheck.md → goodvibesonly.md} +2 -2
- package/hooks/hooks.json +1 -1
- package/package.json +2 -2
- package/skills/{vibecheck → goodvibesonly}/SKILL.md +6 -6
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# GoodVibesOnly
|
|
2
2
|
|
|
3
3
|
**Security scanner for vibe-coded projects.** A Claude Code extension that automatically scans for vulnerabilities before you commit.
|
|
4
4
|
|
|
5
5
|
## How It Works
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
GoodVibesOnly uses Claude Code's hooks system to intercept git commands:
|
|
8
8
|
|
|
9
9
|
1. **Hooks into git commit/push** - Automatically runs before any `git commit` or `git push`
|
|
10
10
|
2. **Scans changed files** - Checks for hardcoded secrets, injection vulnerabilities, XSS, and more
|
|
@@ -14,7 +14,7 @@ VibeCheck uses Claude Code's hooks system to intercept git commands:
|
|
|
14
14
|
```
|
|
15
15
|
You: git commit -m "add user api"
|
|
16
16
|
|
|
17
|
-
🛡️
|
|
17
|
+
🛡️ GoodVibesOnly Security Scan
|
|
18
18
|
|
|
19
19
|
🔴 CRITICAL - Must fix before commit:
|
|
20
20
|
|
|
@@ -47,8 +47,8 @@ npm install -g goodvibesonly-cc
|
|
|
47
47
|
### Option 3: Manual
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
git clone https://github.com/YOURNAME/
|
|
51
|
-
cd
|
|
50
|
+
git clone https://github.com/YOURNAME/goodvibesonly.git
|
|
51
|
+
cd goodvibesonly
|
|
52
52
|
node bin/install.js --global
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -58,14 +58,14 @@ node bin/install.js --global
|
|
|
58
58
|
node bin/install.js --global # Install to ~/.claude/ (all projects)
|
|
59
59
|
node bin/install.js --local # Install to ./.claude/ (this project)
|
|
60
60
|
node bin/install.js --no-hooks # Skip hook installation (command/skill only)
|
|
61
|
-
node bin/install.js --uninstall # Remove
|
|
61
|
+
node bin/install.js --uninstall # Remove GoodVibesOnly
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
## Usage
|
|
65
65
|
|
|
66
66
|
### Automatic (via hooks)
|
|
67
67
|
|
|
68
|
-
Just use git normally.
|
|
68
|
+
Just use git normally. GoodVibesOnly runs automatically:
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
71
|
git commit -m "message" # Scans before commit
|
|
@@ -75,13 +75,13 @@ git push # Scans before push
|
|
|
75
75
|
### Manual Scan
|
|
76
76
|
|
|
77
77
|
```
|
|
78
|
-
/
|
|
78
|
+
/goodvibesonly
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
Or ask Claude:
|
|
82
82
|
```
|
|
83
83
|
is this code safe?
|
|
84
|
-
|
|
84
|
+
goodvibesonly this
|
|
85
85
|
check for security issues
|
|
86
86
|
```
|
|
87
87
|
|
|
@@ -116,14 +116,14 @@ check for security issues
|
|
|
116
116
|
## Project Structure
|
|
117
117
|
|
|
118
118
|
```
|
|
119
|
-
|
|
119
|
+
goodvibesonly/
|
|
120
120
|
├── bin/
|
|
121
121
|
│ ├── install.js # Installer (copies files + sets up hooks)
|
|
122
122
|
│ └── scan.js # Scanner script (runs via hooks)
|
|
123
123
|
├── commands/
|
|
124
|
-
│ └──
|
|
124
|
+
│ └── goodvibesonly.md # /goodvibesonly slash command
|
|
125
125
|
├── skills/
|
|
126
|
-
│ └──
|
|
126
|
+
│ └── goodvibesonly/
|
|
127
127
|
│ └── SKILL.md # Skill for Claude assistance
|
|
128
128
|
├── hooks/
|
|
129
129
|
│ └── hooks.json # Hook configuration template
|
|
@@ -140,7 +140,7 @@ vibecheck/
|
|
|
140
140
|
|
|
141
141
|
## Technical Details
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
GoodVibesOnly installs a `PreToolUse` hook that intercepts Bash commands. When it detects `git commit` or `git push`:
|
|
144
144
|
|
|
145
145
|
1. Reads staged files via `git diff --cached --name-only`
|
|
146
146
|
2. Scans each file against vulnerability patterns
|
|
@@ -156,7 +156,7 @@ The hook is configured in `~/.claude/settings.json`:
|
|
|
156
156
|
"matcher": "Bash",
|
|
157
157
|
"hooks": [{
|
|
158
158
|
"type": "command",
|
|
159
|
-
"command": "node \"~/.claude/
|
|
159
|
+
"command": "node \"~/.claude/goodvibesonly/scan.js\""
|
|
160
160
|
}]
|
|
161
161
|
}]
|
|
162
162
|
}
|
|
@@ -174,9 +174,9 @@ node bin/install.js --uninstall --local
|
|
|
174
174
|
Or manually:
|
|
175
175
|
|
|
176
176
|
```bash
|
|
177
|
-
rm -rf ~/.claude/commands/
|
|
178
|
-
rm -rf ~/.claude/skills/
|
|
179
|
-
rm -rf ~/.claude/
|
|
177
|
+
rm -rf ~/.claude/commands/goodvibesonly.md
|
|
178
|
+
rm -rf ~/.claude/skills/goodvibesonly/
|
|
179
|
+
rm -rf ~/.claude/goodvibesonly/
|
|
180
180
|
# Then remove the hook from ~/.claude/settings.json
|
|
181
181
|
```
|
|
182
182
|
|
package/bin/install.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* GoodVibesOnly Installer
|
|
5
5
|
*
|
|
6
|
-
* Installs
|
|
7
|
-
* - Slash command: /
|
|
6
|
+
* Installs GoodVibesOnly as a Claude Code extension with:
|
|
7
|
+
* - Slash command: /goodvibesonly
|
|
8
8
|
* - Auto-invoke skill for commit/push detection
|
|
9
9
|
* - PreToolUse hook for automatic scanning before git commit/push
|
|
10
10
|
*/
|
|
@@ -69,12 +69,12 @@ function installHooks(targetDir, scanScriptPath) {
|
|
|
69
69
|
settings.hooks.PreToolUse = [];
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
// Check if
|
|
72
|
+
// Check if goodvibesonly hook already exists
|
|
73
73
|
const existingHookIndex = settings.hooks.PreToolUse.findIndex(h =>
|
|
74
|
-
h.hooks?.some(inner => inner.command?.includes('
|
|
74
|
+
h.hooks?.some(inner => inner.command?.includes('goodvibesonly') || inner.command?.includes('scan.js'))
|
|
75
75
|
);
|
|
76
76
|
|
|
77
|
-
const
|
|
77
|
+
const goodvibesonlyHook = {
|
|
78
78
|
matcher: 'Bash',
|
|
79
79
|
hooks: [
|
|
80
80
|
{
|
|
@@ -87,12 +87,12 @@ function installHooks(targetDir, scanScriptPath) {
|
|
|
87
87
|
|
|
88
88
|
if (existingHookIndex >= 0) {
|
|
89
89
|
// Update existing hook
|
|
90
|
-
settings.hooks.PreToolUse[existingHookIndex] =
|
|
91
|
-
console.log('Updated existing
|
|
90
|
+
settings.hooks.PreToolUse[existingHookIndex] = goodvibesonlyHook;
|
|
91
|
+
console.log('Updated existing GoodVibesOnly hook');
|
|
92
92
|
} else {
|
|
93
93
|
// Add new hook
|
|
94
|
-
settings.hooks.PreToolUse.push(
|
|
95
|
-
console.log('Installed
|
|
94
|
+
settings.hooks.PreToolUse.push(goodvibesonlyHook);
|
|
95
|
+
console.log('Installed GoodVibesOnly hook');
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
saveJson(settingsPath, settings);
|
|
@@ -106,8 +106,8 @@ function install(targetDir, skipHooks = false) {
|
|
|
106
106
|
|
|
107
107
|
const commandsDest = path.join(targetDir, 'commands');
|
|
108
108
|
const skillsDest = path.join(targetDir, 'skills');
|
|
109
|
-
const
|
|
110
|
-
const scanScriptDest = path.join(
|
|
109
|
+
const goodvibesonlyDir = path.join(targetDir, 'goodvibesonly');
|
|
110
|
+
const scanScriptDest = path.join(goodvibesonlyDir, 'scan.js');
|
|
111
111
|
|
|
112
112
|
// Copy commands
|
|
113
113
|
if (fs.existsSync(commandsSrc)) {
|
|
@@ -123,7 +123,7 @@ function install(targetDir, skipHooks = false) {
|
|
|
123
123
|
|
|
124
124
|
// Copy scan script
|
|
125
125
|
if (fs.existsSync(scanScriptSrc)) {
|
|
126
|
-
console.log(`Installing scanner to ${
|
|
126
|
+
console.log(`Installing scanner to ${goodvibesonlyDir}`);
|
|
127
127
|
copyFile(scanScriptSrc, scanScriptDest);
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -132,23 +132,23 @@ function install(targetDir, skipHooks = false) {
|
|
|
132
132
|
installHooks(targetDir, scanScriptDest);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
console.log('\n✓
|
|
135
|
+
console.log('\n✓ GoodVibesOnly installed successfully!\n');
|
|
136
136
|
console.log('Features:');
|
|
137
|
-
console.log(' • /
|
|
137
|
+
console.log(' • /goodvibesonly command for manual scans');
|
|
138
138
|
console.log(' • Auto-scan before git commit/push (via hooks)');
|
|
139
139
|
console.log(' • Blocks commits with critical vulnerabilities');
|
|
140
140
|
console.log('');
|
|
141
141
|
console.log('Usage:');
|
|
142
|
-
console.log(' /
|
|
142
|
+
console.log(' /goodvibesonly Manual security scan');
|
|
143
143
|
console.log(' git commit -m "msg" Auto-scans before commit');
|
|
144
144
|
console.log(' git push Auto-scans before push');
|
|
145
145
|
console.log('');
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
function uninstall(targetDir) {
|
|
149
|
-
const commandPath = path.join(targetDir, 'commands', '
|
|
150
|
-
const skillPath = path.join(targetDir, 'skills', '
|
|
151
|
-
const
|
|
149
|
+
const commandPath = path.join(targetDir, 'commands', 'goodvibesonly.md');
|
|
150
|
+
const skillPath = path.join(targetDir, 'skills', 'goodvibesonly');
|
|
151
|
+
const goodvibesonlyDir = path.join(targetDir, 'goodvibesonly');
|
|
152
152
|
const settingsPath = path.join(targetDir, 'settings.json');
|
|
153
153
|
|
|
154
154
|
let removed = false;
|
|
@@ -156,20 +156,20 @@ function uninstall(targetDir) {
|
|
|
156
156
|
// Remove command
|
|
157
157
|
if (fs.existsSync(commandPath)) {
|
|
158
158
|
fs.unlinkSync(commandPath);
|
|
159
|
-
console.log('Removed /
|
|
159
|
+
console.log('Removed /goodvibesonly command');
|
|
160
160
|
removed = true;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
// Remove skill
|
|
164
164
|
if (fs.existsSync(skillPath)) {
|
|
165
165
|
fs.rmSync(skillPath, { recursive: true });
|
|
166
|
-
console.log('Removed
|
|
166
|
+
console.log('Removed goodvibesonly skill');
|
|
167
167
|
removed = true;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
// Remove scanner
|
|
171
|
-
if (fs.existsSync(
|
|
172
|
-
fs.rmSync(
|
|
171
|
+
if (fs.existsSync(goodvibesonlyDir)) {
|
|
172
|
+
fs.rmSync(goodvibesonlyDir, { recursive: true });
|
|
173
173
|
console.log('Removed scanner');
|
|
174
174
|
removed = true;
|
|
175
175
|
}
|
|
@@ -180,7 +180,7 @@ function uninstall(targetDir) {
|
|
|
180
180
|
if (settings.hooks?.PreToolUse) {
|
|
181
181
|
const originalLength = settings.hooks.PreToolUse.length;
|
|
182
182
|
settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(h =>
|
|
183
|
-
!h.hooks?.some(inner => inner.command?.includes('
|
|
183
|
+
!h.hooks?.some(inner => inner.command?.includes('goodvibesonly') || inner.command?.includes('scan.js'))
|
|
184
184
|
);
|
|
185
185
|
if (settings.hooks.PreToolUse.length < originalLength) {
|
|
186
186
|
saveJson(settingsPath, settings);
|
|
@@ -191,9 +191,9 @@ function uninstall(targetDir) {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
if (removed) {
|
|
194
|
-
console.log('\n✓
|
|
194
|
+
console.log('\n✓ GoodVibesOnly uninstalled successfully!\n');
|
|
195
195
|
} else {
|
|
196
|
-
console.log('
|
|
196
|
+
console.log('GoodVibesOnly was not installed in this location.\n');
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
|
|
@@ -215,7 +215,7 @@ async function main() {
|
|
|
215
215
|
const args = process.argv.slice(2);
|
|
216
216
|
|
|
217
217
|
console.log('');
|
|
218
|
-
console.log('🛡️
|
|
218
|
+
console.log('🛡️ GoodVibesOnly Installer');
|
|
219
219
|
console.log(' Security scanner for vibe-coded projects');
|
|
220
220
|
console.log('');
|
|
221
221
|
|
|
@@ -239,7 +239,7 @@ async function main() {
|
|
|
239
239
|
targetDir = LOCAL_CLAUDE_DIR;
|
|
240
240
|
} else {
|
|
241
241
|
// Interactive mode
|
|
242
|
-
console.log('Where would you like to install
|
|
242
|
+
console.log('Where would you like to install GoodVibesOnly?');
|
|
243
243
|
console.log('');
|
|
244
244
|
console.log(' [g] Global (~/.claude/) - Available in all projects');
|
|
245
245
|
console.log(' [l] Local (./.claude/) - This project only');
|
package/bin/scan.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* GoodVibesOnly Scanner
|
|
5
5
|
*
|
|
6
6
|
* Scans files for security vulnerabilities.
|
|
7
7
|
* Used by Claude Code hooks to block commits with critical issues.
|
|
@@ -172,7 +172,7 @@ function formatFindings(findings) {
|
|
|
172
172
|
bySeverity[f.severity].push(f);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
let output = '\n🛡️
|
|
175
|
+
let output = '\n🛡️ GoodVibesOnly Security Scan\n\n';
|
|
176
176
|
|
|
177
177
|
const total = findings.length;
|
|
178
178
|
if (total === 0) {
|
|
@@ -60,7 +60,7 @@ Run a security scan on the current changes before committing.
|
|
|
60
60
|
|
|
61
61
|
If issues found:
|
|
62
62
|
```
|
|
63
|
-
|
|
63
|
+
GoodVibesOnly found [N] issues:
|
|
64
64
|
|
|
65
65
|
🔴 CRITICAL (must fix):
|
|
66
66
|
1. [Type]: [file]:[line]
|
|
@@ -78,7 +78,7 @@ Want me to fix the critical issues before you commit?
|
|
|
78
78
|
|
|
79
79
|
If clean:
|
|
80
80
|
```
|
|
81
|
-
✓
|
|
81
|
+
✓ GoodVibesOnly passed - no security issues found in [N] files
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
## After Scanning
|
package/hooks/hooks.json
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goodvibesonly-cc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Security scanner for vibe-coded projects - Claude Code extension",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"
|
|
7
|
+
"goodvibesonly": "./bin/install.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"postinstall": "node bin/install.js --global"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Security scanner for vibe-coded projects. AUTO-INVOKE this skill before any git commit, git push, or when user says "commit", "push", "ship it", "deploy", "is this safe?", "check for security issues", or "
|
|
2
|
+
name: goodvibesonly
|
|
3
|
+
description: Security scanner for vibe-coded projects. AUTO-INVOKE this skill before any git commit, git push, or when user says "commit", "push", "ship it", "deploy", "is this safe?", "check for security issues", or "goodvibesonly". Also invoke after generating code that handles user input, authentication, database queries, or file operations.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# GoodVibesOnly - Security Scanner
|
|
7
7
|
|
|
8
8
|
Automatically scan for security vulnerabilities before code leaves the developer's machine.
|
|
9
9
|
|
|
@@ -20,7 +20,7 @@ Run this skill WHEN user says:
|
|
|
20
20
|
- "ship it"
|
|
21
21
|
- "is this safe?"
|
|
22
22
|
- "check security"
|
|
23
|
-
- "
|
|
23
|
+
- "goodvibesonly"
|
|
24
24
|
- "ready to deploy"
|
|
25
25
|
|
|
26
26
|
## Quick Scan Checklist
|
|
@@ -94,7 +94,7 @@ http://(?!localhost) # Non-HTTPS
|
|
|
94
94
|
## Example Output
|
|
95
95
|
|
|
96
96
|
```
|
|
97
|
-
🛡️
|
|
97
|
+
🛡️ GoodVibesOnly Security Scan
|
|
98
98
|
|
|
99
99
|
Scanned 8 files with changes.
|
|
100
100
|
|
|
@@ -105,7 +105,7 @@ Scanned 8 files with changes.
|
|
|
105
105
|
const API_KEY = "sk-abc123..."
|
|
106
106
|
→ Move to environment variable
|
|
107
107
|
|
|
108
|
-
2. SQL Injection
|
|
108
|
+
2. SQL Injection
|
|
109
109
|
src/db/users.js:42
|
|
110
110
|
db.query("SELECT * FROM users WHERE id = " + id)
|
|
111
111
|
→ Use parameterized query: db.query("SELECT * FROM users WHERE id = ?", [id])
|