vibe-and-thrive 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/.claude/commands/add-tests.md +240 -0
- package/.claude/commands/e2e-scaffold.md +212 -0
- package/.claude/commands/explain.md +110 -0
- package/.claude/commands/fix-types.md +238 -0
- package/.claude/commands/refactor.md +184 -0
- package/.claude/commands/review.md +136 -0
- package/.claude/commands/security-check.md +223 -0
- package/.claude/commands/styleguide.md +446 -0
- package/.claude/commands/tdd-feature.md +227 -0
- package/.claude/commands/vibe-check.md +112 -0
- package/.pre-commit-hooks.yaml +77 -0
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/bin/vibe-check.js +19 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +206 -0
- package/dist/cli.js.map +1 -0
- package/dist/eslint-plugin/index.d.ts +66 -0
- package/dist/eslint-plugin/index.d.ts.map +1 -0
- package/dist/eslint-plugin/index.js +67 -0
- package/dist/eslint-plugin/index.js.map +1 -0
- package/dist/eslint-plugin/rules/max-function-length.d.ts +8 -0
- package/dist/eslint-plugin/rules/max-function-length.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/max-function-length.js +69 -0
- package/dist/eslint-plugin/rules/max-function-length.js.map +1 -0
- package/dist/eslint-plugin/rules/no-any-type.d.ts +8 -0
- package/dist/eslint-plugin/rules/no-any-type.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-any-type.js +29 -0
- package/dist/eslint-plugin/rules/no-any-type.js.map +1 -0
- package/dist/eslint-plugin/rules/no-debug-statements.d.ts +8 -0
- package/dist/eslint-plugin/rules/no-debug-statements.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-debug-statements.js +59 -0
- package/dist/eslint-plugin/rules/no-debug-statements.js.map +1 -0
- package/dist/eslint-plugin/rules/no-deep-nesting.d.ts +8 -0
- package/dist/eslint-plugin/rules/no-deep-nesting.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-deep-nesting.js +56 -0
- package/dist/eslint-plugin/rules/no-deep-nesting.js.map +1 -0
- package/dist/eslint-plugin/rules/no-empty-catch.d.ts +8 -0
- package/dist/eslint-plugin/rules/no-empty-catch.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-empty-catch.js +31 -0
- package/dist/eslint-plugin/rules/no-empty-catch.js.map +1 -0
- package/dist/eslint-plugin/rules/no-magic-numbers.d.ts +8 -0
- package/dist/eslint-plugin/rules/no-magic-numbers.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-magic-numbers.js +58 -0
- package/dist/eslint-plugin/rules/no-magic-numbers.js.map +1 -0
- package/dist/eslint-plugin/rules/no-snake-case-props.d.ts +8 -0
- package/dist/eslint-plugin/rules/no-snake-case-props.d.ts.map +1 -0
- package/dist/eslint-plugin/rules/no-snake-case-props.js +48 -0
- package/dist/eslint-plugin/rules/no-snake-case-props.js.map +1 -0
- package/dist/hooks/check-any-types.d.ts +6 -0
- package/dist/hooks/check-any-types.d.ts.map +1 -0
- package/dist/hooks/check-any-types.js +73 -0
- package/dist/hooks/check-any-types.js.map +1 -0
- package/dist/hooks/check-commented-code.d.ts +6 -0
- package/dist/hooks/check-commented-code.d.ts.map +1 -0
- package/dist/hooks/check-commented-code.js +81 -0
- package/dist/hooks/check-commented-code.js.map +1 -0
- package/dist/hooks/check-console-error.d.ts +6 -0
- package/dist/hooks/check-console-error.d.ts.map +1 -0
- package/dist/hooks/check-console-error.js +41 -0
- package/dist/hooks/check-console-error.js.map +1 -0
- package/dist/hooks/check-debug-statements.d.ts +6 -0
- package/dist/hooks/check-debug-statements.d.ts.map +1 -0
- package/dist/hooks/check-debug-statements.js +120 -0
- package/dist/hooks/check-debug-statements.js.map +1 -0
- package/dist/hooks/check-deep-nesting.d.ts +6 -0
- package/dist/hooks/check-deep-nesting.d.ts.map +1 -0
- package/dist/hooks/check-deep-nesting.js +116 -0
- package/dist/hooks/check-deep-nesting.js.map +1 -0
- package/dist/hooks/check-docker-platform.d.ts +6 -0
- package/dist/hooks/check-docker-platform.d.ts.map +1 -0
- package/dist/hooks/check-docker-platform.js +42 -0
- package/dist/hooks/check-docker-platform.js.map +1 -0
- package/dist/hooks/check-dry-violations.d.ts +6 -0
- package/dist/hooks/check-dry-violations.d.ts.map +1 -0
- package/dist/hooks/check-dry-violations.js +124 -0
- package/dist/hooks/check-dry-violations.js.map +1 -0
- package/dist/hooks/check-empty-catch.d.ts +6 -0
- package/dist/hooks/check-empty-catch.d.ts.map +1 -0
- package/dist/hooks/check-empty-catch.js +111 -0
- package/dist/hooks/check-empty-catch.js.map +1 -0
- package/dist/hooks/check-function-length.d.ts +6 -0
- package/dist/hooks/check-function-length.d.ts.map +1 -0
- package/dist/hooks/check-function-length.js +152 -0
- package/dist/hooks/check-function-length.js.map +1 -0
- package/dist/hooks/check-hardcoded-urls.d.ts +6 -0
- package/dist/hooks/check-hardcoded-urls.d.ts.map +1 -0
- package/dist/hooks/check-hardcoded-urls.js +124 -0
- package/dist/hooks/check-hardcoded-urls.js.map +1 -0
- package/dist/hooks/check-magic-numbers.d.ts +6 -0
- package/dist/hooks/check-magic-numbers.d.ts.map +1 -0
- package/dist/hooks/check-magic-numbers.js +116 -0
- package/dist/hooks/check-magic-numbers.js.map +1 -0
- package/dist/hooks/check-secrets.d.ts +6 -0
- package/dist/hooks/check-secrets.d.ts.map +1 -0
- package/dist/hooks/check-secrets.js +138 -0
- package/dist/hooks/check-secrets.js.map +1 -0
- package/dist/hooks/check-snake-case-ts.d.ts +6 -0
- package/dist/hooks/check-snake-case-ts.d.ts.map +1 -0
- package/dist/hooks/check-snake-case-ts.js +78 -0
- package/dist/hooks/check-snake-case-ts.js.map +1 -0
- package/dist/hooks/check-todo-fixme.d.ts +6 -0
- package/dist/hooks/check-todo-fixme.d.ts.map +1 -0
- package/dist/hooks/check-todo-fixme.js +41 -0
- package/dist/hooks/check-todo-fixme.js.map +1 -0
- package/dist/hooks/check-unsafe-html.d.ts +6 -0
- package/dist/hooks/check-unsafe-html.d.ts.map +1 -0
- package/dist/hooks/check-unsafe-html.js +101 -0
- package/dist/hooks/check-unsafe-html.js.map +1 -0
- package/dist/hooks/index.d.ts +29 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +54 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/lint-staged/config.d.ts +20 -0
- package/dist/lint-staged/config.d.ts.map +1 -0
- package/dist/lint-staged/config.js +27 -0
- package/dist/lint-staged/config.js.map +1 -0
- package/dist/utils/file-reader.d.ts +24 -0
- package/dist/utils/file-reader.d.ts.map +1 -0
- package/dist/utils/file-reader.js +140 -0
- package/dist/utils/file-reader.js.map +1 -0
- package/dist/utils/patterns.d.ts +27 -0
- package/dist/utils/patterns.d.ts.map +1 -0
- package/dist/utils/patterns.js +84 -0
- package/dist/utils/patterns.js.map +1 -0
- package/dist/utils/reporters.d.ts +21 -0
- package/dist/utils/reporters.d.ts.map +1 -0
- package/dist/utils/reporters.js +115 -0
- package/dist/utils/reporters.js.map +1 -0
- package/dist/utils/types.d.ts +71 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +5 -0
- package/dist/utils/types.js.map +1 -0
- package/integrations/cursorrules.template +147 -0
- package/integrations/eslint.config.js +34 -0
- package/integrations/lint-staged.config.js +34 -0
- package/integrations/ruff.toml +125 -0
- package/integrations/vibe-check.yml +116 -0
- package/integrations/vscode-settings.json +127 -0
- package/package.json +81 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# TDD Feature
|
|
2
|
+
|
|
3
|
+
Implement a feature using Test-Driven Development: write the failing E2E test first, then build the feature to make it pass.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
This skill follows the TDD workflow:
|
|
8
|
+
1. **Red**: Write a failing test that defines what success looks like
|
|
9
|
+
2. **Green**: Implement the minimum code to make the test pass
|
|
10
|
+
3. **Refactor**: Clean up while keeping tests green
|
|
11
|
+
|
|
12
|
+
### Phase 1: Discovery
|
|
13
|
+
|
|
14
|
+
Before writing any code, understand the project's testing setup:
|
|
15
|
+
|
|
16
|
+
**Check for Playwright configuration:**
|
|
17
|
+
- Look for `playwright.config.ts` or `playwright.config.js`
|
|
18
|
+
- Find the test directory (`e2e/`, `tests/`, etc.)
|
|
19
|
+
- Note the base URL configuration
|
|
20
|
+
|
|
21
|
+
**Check for existing test patterns:**
|
|
22
|
+
- Search for `*.spec.ts` or `*.test.ts` files in the test directory
|
|
23
|
+
- Look for helper functions and utilities
|
|
24
|
+
- Note how auth is handled in existing tests
|
|
25
|
+
|
|
26
|
+
**Check the tech stack:**
|
|
27
|
+
- Frontend framework (React, Vue, etc.)
|
|
28
|
+
- API pattern (REST, GraphQL, tRPC)
|
|
29
|
+
- Auth mechanism (session/cookie, JWT, OAuth)
|
|
30
|
+
|
|
31
|
+
### Phase 2: Gather Requirements
|
|
32
|
+
|
|
33
|
+
Ask the user:
|
|
34
|
+
1. **"What feature are you building?"** - Get a clear description
|
|
35
|
+
2. **"What should success look like?"** - Define acceptance criteria
|
|
36
|
+
3. **"Does this require authentication?"** - Understand auth needs
|
|
37
|
+
4. **"What API endpoints will this use?"** - Map the backend requirements
|
|
38
|
+
|
|
39
|
+
If the user provides a feature description upfront like "Users can reset their password via email", proceed to Phase 3.
|
|
40
|
+
|
|
41
|
+
### Phase 3: Write the Failing Test (RED)
|
|
42
|
+
|
|
43
|
+
Create the E2E test file with the SCENARIO/EXPECTED/FAILURE pattern:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { test, expect, Page } from '@playwright/test';
|
|
47
|
+
|
|
48
|
+
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
|
49
|
+
const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:8000';
|
|
50
|
+
|
|
51
|
+
test.describe('[Feature Name]', () => {
|
|
52
|
+
|
|
53
|
+
test('[primary user action]', async ({ page }) => {
|
|
54
|
+
/**
|
|
55
|
+
* SCENARIO: As a [user type], when I [perform action],
|
|
56
|
+
* I should [see expected outcome]
|
|
57
|
+
* EXPECTED: [Specific, measurable success criteria]
|
|
58
|
+
* FAILURE: [What would indicate the feature is broken]
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
// Navigate to the feature
|
|
62
|
+
await page.goto(`${BASE_URL}/feature-path`);
|
|
63
|
+
|
|
64
|
+
// Perform user actions
|
|
65
|
+
await page.getByRole('button', { name: /action/i }).click();
|
|
66
|
+
await page.fill('[data-testid="input-field"]', 'test value');
|
|
67
|
+
await page.getByRole('button', { name: /submit/i }).click();
|
|
68
|
+
|
|
69
|
+
// Wait for result
|
|
70
|
+
await page.waitForSelector('[data-testid="success-message"]', { timeout: 10000 });
|
|
71
|
+
|
|
72
|
+
// Critical assertion with debugging
|
|
73
|
+
const isSuccess = await page.locator('[data-testid="success-message"]').isVisible();
|
|
74
|
+
if (!isSuccess) {
|
|
75
|
+
console.error('FAIL: Success message not visible after form submission');
|
|
76
|
+
await page.screenshot({ path: 'e2e-feature-name-debug.png' });
|
|
77
|
+
}
|
|
78
|
+
expect(isSuccess).toBeTruthy();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Key testing patterns:**
|
|
85
|
+
|
|
86
|
+
1. **Flexible locators** - Handle UI variations:
|
|
87
|
+
```typescript
|
|
88
|
+
const submitButton = page.getByRole('button', { name: /submit|save|confirm/i })
|
|
89
|
+
.or(page.locator('[data-testid="submit-btn"]'))
|
|
90
|
+
.or(page.locator('button[type="submit"]'));
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
2. **Wait for network** - Don't race with API calls:
|
|
94
|
+
```typescript
|
|
95
|
+
await Promise.all([
|
|
96
|
+
page.waitForResponse(resp => resp.url().includes('/api/') && resp.status() === 200),
|
|
97
|
+
submitButton.click()
|
|
98
|
+
]);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
3. **Screenshot on failure** - Always capture debug info:
|
|
102
|
+
```typescript
|
|
103
|
+
if (!condition) {
|
|
104
|
+
console.error('FAIL: Description of what went wrong');
|
|
105
|
+
await page.screenshot({ path: 'e2e-descriptive-name.png' });
|
|
106
|
+
}
|
|
107
|
+
expect(condition).toBeTruthy();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Phase 4: Run the Test (Confirm RED)
|
|
111
|
+
|
|
112
|
+
Tell the user to run:
|
|
113
|
+
```bash
|
|
114
|
+
npx playwright test [test-file] --headed
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The test should fail because the feature doesn't exist yet. Verify:
|
|
118
|
+
- The test fails for the **right reason** (missing UI, 404 endpoint, etc.)
|
|
119
|
+
- Not because of test setup issues
|
|
120
|
+
|
|
121
|
+
If it fails for wrong reasons, fix the test first.
|
|
122
|
+
|
|
123
|
+
### Phase 5: Implement the Feature (GREEN)
|
|
124
|
+
|
|
125
|
+
Now implement the minimum code to make the test pass:
|
|
126
|
+
|
|
127
|
+
1. **Create the UI components** - Only what the test checks for
|
|
128
|
+
2. **Create the API endpoints** - Only what the test calls
|
|
129
|
+
3. **Wire them together** - Focus on the happy path first
|
|
130
|
+
|
|
131
|
+
Keep implementation minimal. Don't add:
|
|
132
|
+
- Features not covered by the test
|
|
133
|
+
- Error handling beyond what's tested
|
|
134
|
+
- Optimization or polish
|
|
135
|
+
|
|
136
|
+
### Phase 6: Run the Test (Confirm GREEN)
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npx playwright test [test-file] --headed
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The test should now pass. If it doesn't:
|
|
143
|
+
- Check the console for errors
|
|
144
|
+
- Look at the failure screenshot
|
|
145
|
+
- Adjust implementation, not the test (unless test was wrong)
|
|
146
|
+
|
|
147
|
+
### Phase 7: Refactor (Keep GREEN)
|
|
148
|
+
|
|
149
|
+
With a passing test as your safety net, now you can:
|
|
150
|
+
- Extract reusable components
|
|
151
|
+
- Add proper error handling
|
|
152
|
+
- Improve code organization
|
|
153
|
+
- Add TypeScript types
|
|
154
|
+
|
|
155
|
+
Run the test after each change to ensure nothing breaks.
|
|
156
|
+
|
|
157
|
+
### Phase 8: Expand Test Coverage
|
|
158
|
+
|
|
159
|
+
Add tests for:
|
|
160
|
+
- Edge cases (empty inputs, long strings, special characters)
|
|
161
|
+
- Error scenarios (network failure, invalid data)
|
|
162
|
+
- Auth variations (logged out, different roles)
|
|
163
|
+
|
|
164
|
+
Each new test follows the same cycle: write failing test → implement → verify.
|
|
165
|
+
|
|
166
|
+
## Example: Password Reset Feature
|
|
167
|
+
|
|
168
|
+
**User says:** "Users can reset their password via email"
|
|
169
|
+
|
|
170
|
+
**Phase 3 - Write failing test:**
|
|
171
|
+
```typescript
|
|
172
|
+
test.describe('Password Reset', () => {
|
|
173
|
+
|
|
174
|
+
test('user can request password reset email', async ({ page }) => {
|
|
175
|
+
/**
|
|
176
|
+
* SCENARIO: As a user who forgot my password, when I enter my email
|
|
177
|
+
* and click "Reset Password", I should see confirmation
|
|
178
|
+
* EXPECTED: Success message appears, email is sent (mock)
|
|
179
|
+
* FAILURE: Error shown, no confirmation, or page crashes
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
await page.goto(`${BASE_URL}/forgot-password`);
|
|
183
|
+
|
|
184
|
+
// Enter email
|
|
185
|
+
await page.fill('input[type="email"]', 'test@example.com');
|
|
186
|
+
|
|
187
|
+
// Submit request
|
|
188
|
+
await page.getByRole('button', { name: /reset|send/i }).click();
|
|
189
|
+
|
|
190
|
+
// Verify success
|
|
191
|
+
const successMessage = page.getByText(/check your email|reset link sent/i);
|
|
192
|
+
await expect(successMessage).toBeVisible({ timeout: 10000 });
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test('shows error for unregistered email', async ({ page }) => {
|
|
196
|
+
/**
|
|
197
|
+
* SCENARIO: As a visitor with an unregistered email, when I request
|
|
198
|
+
* a password reset, I should see an appropriate message
|
|
199
|
+
* EXPECTED: Message indicating email not found or generic success (for security)
|
|
200
|
+
* FAILURE: Crash, no feedback, or reveals registration status
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
await page.goto(`${BASE_URL}/forgot-password`);
|
|
204
|
+
await page.fill('input[type="email"]', 'notregistered@example.com');
|
|
205
|
+
await page.getByRole('button', { name: /reset|send/i }).click();
|
|
206
|
+
|
|
207
|
+
// Either error message OR same success message (for security)
|
|
208
|
+
const response = page.getByText(/check your email|not found|no account/i);
|
|
209
|
+
await expect(response).toBeVisible({ timeout: 10000 });
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Phase 5 - Implement:**
|
|
216
|
+
1. Create `/forgot-password` route
|
|
217
|
+
2. Create ForgotPasswordForm component
|
|
218
|
+
3. Create `POST /api/auth/reset-password` endpoint
|
|
219
|
+
4. Wire up form to API
|
|
220
|
+
|
|
221
|
+
## Notes
|
|
222
|
+
|
|
223
|
+
- **Test behavior, not implementation** - Tests should pass regardless of how feature is built
|
|
224
|
+
- **One feature per test file** - Keep tests focused and fast
|
|
225
|
+
- **Independent tests** - Each test sets up its own data, doesn't depend on others
|
|
226
|
+
- **Descriptive failures** - Make it easy to debug when tests fail
|
|
227
|
+
- **Run tests frequently** - Catch regressions immediately
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Vibe Check
|
|
2
|
+
|
|
3
|
+
Run a comprehensive code quality check on the current codebase, looking for common patterns that AI coding agents introduce.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
Analyze the codebase for the following issues. For each category, search the relevant file types and report what you find.
|
|
8
|
+
|
|
9
|
+
### 1. Debug Statements
|
|
10
|
+
Search for debug statements that shouldn't go to production:
|
|
11
|
+
- Python: `print()`, `breakpoint()`, `pdb.set_trace()`, `ipdb`
|
|
12
|
+
- JS/TS: `console.log()`, `console.debug()`, `console.info()`, `debugger`
|
|
13
|
+
|
|
14
|
+
Ignore: `console.error()`, `console.warn()`, `logger.*` calls, and lines with `// noqa: debug` or `# noqa: debug`
|
|
15
|
+
|
|
16
|
+
### 2. TODO/FIXME Comments
|
|
17
|
+
Search for unfinished work markers:
|
|
18
|
+
- `TODO`, `FIXME`, `XXX`, `HACK`, `BUG`
|
|
19
|
+
|
|
20
|
+
Skip markdown files and dedicated TODO files.
|
|
21
|
+
|
|
22
|
+
### 3. Empty Catch Blocks
|
|
23
|
+
Search for error handling that silently swallows errors:
|
|
24
|
+
- Python: `except: pass` or `except Exception: pass`
|
|
25
|
+
- JS/TS: `catch (e) {}` or `.catch(() => {})`
|
|
26
|
+
|
|
27
|
+
### 4. Hardcoded URLs
|
|
28
|
+
Search for localhost/development URLs:
|
|
29
|
+
- `http://localhost:`
|
|
30
|
+
- `http://127.0.0.1:`
|
|
31
|
+
|
|
32
|
+
Skip test files and config files.
|
|
33
|
+
|
|
34
|
+
### 5. snake_case in TypeScript
|
|
35
|
+
Search TypeScript interface/type definitions for snake_case property names that should be camelCase.
|
|
36
|
+
|
|
37
|
+
### 6. Magic Numbers
|
|
38
|
+
In Python files, look for hardcoded numbers > 10 that aren't in constants files.
|
|
39
|
+
|
|
40
|
+
### 7. Potential Secrets
|
|
41
|
+
Search for patterns that look like hardcoded secrets:
|
|
42
|
+
- `AKIA` (AWS keys)
|
|
43
|
+
- `sk-` followed by long strings (OpenAI/Stripe)
|
|
44
|
+
- `ghp_` (GitHub tokens)
|
|
45
|
+
- Connection strings with passwords
|
|
46
|
+
|
|
47
|
+
Skip `.env.example` files.
|
|
48
|
+
|
|
49
|
+
### 8. DRY Violations
|
|
50
|
+
Look for obvious code duplication:
|
|
51
|
+
- Very similar functions
|
|
52
|
+
- Repeated string literals (same long string 3+ times)
|
|
53
|
+
- Copy-pasted code blocks
|
|
54
|
+
|
|
55
|
+
## Output Format
|
|
56
|
+
|
|
57
|
+
Provide a summary report like this:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
## Vibe Check Report
|
|
61
|
+
|
|
62
|
+
### Summary
|
|
63
|
+
- X issues found across Y files
|
|
64
|
+
- Z high priority (secrets, hardcoded URLs)
|
|
65
|
+
- W low priority (TODOs, debug statements)
|
|
66
|
+
|
|
67
|
+
### High Priority (fix before committing)
|
|
68
|
+
|
|
69
|
+
#### Potential Secrets
|
|
70
|
+
- file.py:42 - Looks like an API key
|
|
71
|
+
|
|
72
|
+
#### Hardcoded URLs
|
|
73
|
+
- api.ts:15 - localhost URL should use env var
|
|
74
|
+
|
|
75
|
+
### Medium Priority (fix soon)
|
|
76
|
+
|
|
77
|
+
#### Empty Catch Blocks
|
|
78
|
+
- service.py:88 - except: pass (silently swallows errors)
|
|
79
|
+
|
|
80
|
+
#### snake_case in TypeScript
|
|
81
|
+
- types.ts:12 - `user_id` should be `userId`
|
|
82
|
+
|
|
83
|
+
### Low Priority (nice to fix)
|
|
84
|
+
|
|
85
|
+
#### Debug Statements
|
|
86
|
+
- utils.py:23 - print() statement
|
|
87
|
+
- component.tsx:45 - console.log()
|
|
88
|
+
|
|
89
|
+
#### TODO/FIXME
|
|
90
|
+
- auth.py:67 - TODO: implement refresh token
|
|
91
|
+
|
|
92
|
+
### Clean Areas
|
|
93
|
+
- No magic numbers found
|
|
94
|
+
- No DRY violations detected
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
If everything looks good:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
## Vibe Check Report
|
|
101
|
+
|
|
102
|
+
✨ Looking good! No issues found.
|
|
103
|
+
|
|
104
|
+
Your code is clean and ready to ship.
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Notes
|
|
108
|
+
|
|
109
|
+
- Focus on **actionable** findings, not nitpicks
|
|
110
|
+
- Group by severity to help prioritize
|
|
111
|
+
- If a file has many issues, summarize rather than listing every line
|
|
112
|
+
- Be encouraging - the goal is to help, not shame
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# vibe-and-thrive pre-commit hooks
|
|
2
|
+
# All hooks use language: node for consistency
|
|
3
|
+
|
|
4
|
+
# Security checks (blocking - these will fail the commit)
|
|
5
|
+
- id: check-secrets
|
|
6
|
+
name: Check for hardcoded secrets
|
|
7
|
+
entry: npx vibe-check --only secrets --fail-on error
|
|
8
|
+
language: node
|
|
9
|
+
types_or: [python, javascript, ts, json, yaml]
|
|
10
|
+
pass_filenames: true
|
|
11
|
+
|
|
12
|
+
- id: check-hardcoded-urls
|
|
13
|
+
name: Check for hardcoded URLs
|
|
14
|
+
entry: npx vibe-check --only urls --fail-on error
|
|
15
|
+
language: node
|
|
16
|
+
types_or: [python, javascript, ts]
|
|
17
|
+
pass_filenames: true
|
|
18
|
+
|
|
19
|
+
- id: check-unsafe-html
|
|
20
|
+
name: Check for unsafe HTML manipulation
|
|
21
|
+
entry: npx vibe-check --only unsafe-html --fail-on error
|
|
22
|
+
language: node
|
|
23
|
+
types_or: [javascript, ts]
|
|
24
|
+
pass_filenames: true
|
|
25
|
+
|
|
26
|
+
# Code quality checks (warnings - informational)
|
|
27
|
+
- id: check-debug
|
|
28
|
+
name: Check for debug statements
|
|
29
|
+
entry: npx vibe-check --only debug --fail-on error
|
|
30
|
+
language: node
|
|
31
|
+
types_or: [python, javascript, ts]
|
|
32
|
+
pass_filenames: true
|
|
33
|
+
|
|
34
|
+
- id: check-empty-catch
|
|
35
|
+
name: Check for empty catch blocks
|
|
36
|
+
entry: npx vibe-check --only empty-catch --fail-on warning
|
|
37
|
+
language: node
|
|
38
|
+
types_or: [python, javascript, ts]
|
|
39
|
+
pass_filenames: true
|
|
40
|
+
|
|
41
|
+
- id: check-any-types
|
|
42
|
+
name: Check for any types in TypeScript
|
|
43
|
+
entry: npx vibe-check --only any-types --fail-on warning
|
|
44
|
+
language: node
|
|
45
|
+
types: [ts]
|
|
46
|
+
pass_filenames: true
|
|
47
|
+
|
|
48
|
+
- id: check-snake-case
|
|
49
|
+
name: Check for snake_case in TypeScript
|
|
50
|
+
entry: npx vibe-check --only snake-case --fail-on warning
|
|
51
|
+
language: node
|
|
52
|
+
types: [ts]
|
|
53
|
+
pass_filenames: true
|
|
54
|
+
|
|
55
|
+
# Comprehensive check (all hooks)
|
|
56
|
+
- id: vibe-check
|
|
57
|
+
name: Vibe Check (all)
|
|
58
|
+
entry: npx vibe-check
|
|
59
|
+
language: node
|
|
60
|
+
types_or: [python, javascript, ts, json, yaml]
|
|
61
|
+
pass_filenames: true
|
|
62
|
+
|
|
63
|
+
# Quick security-only check
|
|
64
|
+
- id: vibe-check-security
|
|
65
|
+
name: Vibe Check (security only)
|
|
66
|
+
entry: npx vibe-check --only secrets,urls,unsafe-html --fail-on error
|
|
67
|
+
language: node
|
|
68
|
+
types_or: [python, javascript, ts, json, yaml]
|
|
69
|
+
pass_filenames: true
|
|
70
|
+
|
|
71
|
+
# Quality-only check (non-blocking)
|
|
72
|
+
- id: vibe-check-quality
|
|
73
|
+
name: Vibe Check (quality only)
|
|
74
|
+
entry: npx vibe-check --skip secrets,urls,unsafe-html --fail-on none
|
|
75
|
+
language: node
|
|
76
|
+
types_or: [python, javascript, ts]
|
|
77
|
+
pass_filenames: true
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 AllThrive AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Vibe and Thrive
|
|
2
|
+
|
|
3
|
+
**Catch common AI-generated code issues before they hit your codebase.**
|
|
4
|
+
|
|
5
|
+
Whether you're using AI coding agents or building your own—these tools catch patterns that lead to technical debt automatically.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install vibe-and-thrive
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### CLI
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Check all files in current directory
|
|
19
|
+
npx vibe-check .
|
|
20
|
+
|
|
21
|
+
# Check specific files
|
|
22
|
+
npx vibe-check src/app.ts src/utils.ts
|
|
23
|
+
|
|
24
|
+
# Check with specific hooks only
|
|
25
|
+
npx vibe-check . --only secrets,urls,debug
|
|
26
|
+
|
|
27
|
+
# Skip specific hooks
|
|
28
|
+
npx vibe-check . --skip any-types,snake-case
|
|
29
|
+
|
|
30
|
+
# Output formats
|
|
31
|
+
npx vibe-check . --format pretty # Default: colored terminal output
|
|
32
|
+
npx vibe-check . --format json # JSON for CI/scripts
|
|
33
|
+
npx vibe-check . --format compact # One line per issue
|
|
34
|
+
|
|
35
|
+
# Severity filtering
|
|
36
|
+
npx vibe-check . --fail-on error # Only fail on blocking issues (default)
|
|
37
|
+
npx vibe-check . --fail-on warning # Fail on warnings too
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### ESLint Plugin
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install -D vibe-and-thrive eslint
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// eslint.config.js
|
|
48
|
+
import vibe from 'vibe-and-thrive/eslint-plugin';
|
|
49
|
+
|
|
50
|
+
export default [
|
|
51
|
+
// Use recommended config
|
|
52
|
+
vibe.configs.recommended,
|
|
53
|
+
|
|
54
|
+
// Or configure individually
|
|
55
|
+
{
|
|
56
|
+
plugins: { vibe },
|
|
57
|
+
rules: {
|
|
58
|
+
'vibe/no-any-type': 'warn',
|
|
59
|
+
'vibe/no-snake-case-props': 'warn',
|
|
60
|
+
'vibe/no-debug-statements': 'error',
|
|
61
|
+
'vibe/no-empty-catch': 'warn',
|
|
62
|
+
'vibe/no-magic-numbers': 'off',
|
|
63
|
+
'vibe/no-deep-nesting': 'warn',
|
|
64
|
+
'vibe/max-function-length': ['warn', { max: 50 }],
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
];
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Pre-commit Hooks
|
|
71
|
+
|
|
72
|
+
Add to your `.pre-commit-config.yaml`:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
repos:
|
|
76
|
+
- repo: https://github.com/allthriveai/vibe-and-thrive
|
|
77
|
+
rev: v1.0.0
|
|
78
|
+
hooks:
|
|
79
|
+
- id: check-secrets # BLOCKS commits
|
|
80
|
+
- id: check-hardcoded-urls # BLOCKS commits
|
|
81
|
+
- id: check-debug # Warns
|
|
82
|
+
- id: check-empty-catch # Warns
|
|
83
|
+
- id: check-any-types # Warns (TypeScript only)
|
|
84
|
+
- id: check-snake-case # Warns (TypeScript only)
|
|
85
|
+
- id: vibe-check # All checks
|
|
86
|
+
- id: vibe-check-security # Security only (blocking)
|
|
87
|
+
- id: vibe-check-quality # Quality only (non-blocking)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then: `pre-commit install`
|
|
91
|
+
|
|
92
|
+
### lint-staged
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"lint-staged": {
|
|
97
|
+
"*.{js,ts,jsx,tsx}": "vibe-check --fail-on error"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Claude Code
|
|
103
|
+
|
|
104
|
+
Run `/vibe-check` in Claude Code for a full code quality audit.
|
|
105
|
+
|
|
106
|
+
## Available Checks
|
|
107
|
+
|
|
108
|
+
| Check | ID | Description | Severity |
|
|
109
|
+
|-------|-----|-------------|----------|
|
|
110
|
+
| Secrets | `secrets` | Hardcoded API keys, passwords, tokens | Error |
|
|
111
|
+
| URLs | `urls` | Hardcoded localhost/production URLs | Error |
|
|
112
|
+
| Unsafe HTML | `unsafe-html` | innerHTML, dangerouslySetInnerHTML, eval | Error |
|
|
113
|
+
| Debug | `debug` | console.log, print(), debugger statements | Warning |
|
|
114
|
+
| Empty Catch | `empty-catch` | Empty catch/except blocks | Warning |
|
|
115
|
+
| Any Types | `any-types` | TypeScript `any` type usage | Warning |
|
|
116
|
+
| Snake Case | `snake-case` | snake_case in TypeScript interfaces | Warning |
|
|
117
|
+
| Magic Numbers | `magic-numbers` | Hardcoded numbers without names | Warning |
|
|
118
|
+
| Function Length | `function-length` | Functions over 50 lines | Warning |
|
|
119
|
+
| Deep Nesting | `deep-nesting` | Code nested more than 4 levels | Warning |
|
|
120
|
+
| DRY | `dry` | Duplicated code blocks | Warning |
|
|
121
|
+
| TODO/FIXME | `todo` | Incomplete work markers | Info |
|
|
122
|
+
| Commented Code | `commented-code` | Commented-out code blocks | Info |
|
|
123
|
+
| Console Error | `console-error` | console.error in catch blocks | Info |
|
|
124
|
+
| Docker Platform | `docker-platform` | Missing --platform in Dockerfiles | Info |
|
|
125
|
+
|
|
126
|
+
## ESLint Rules
|
|
127
|
+
|
|
128
|
+
| Rule | Fixable | Description |
|
|
129
|
+
|------|---------|-------------|
|
|
130
|
+
| `vibe/no-any-type` | No | Disallow `any` type |
|
|
131
|
+
| `vibe/no-snake-case-props` | Yes | Disallow snake_case properties |
|
|
132
|
+
| `vibe/no-debug-statements` | No | Disallow console.log, debugger |
|
|
133
|
+
| `vibe/no-empty-catch` | No | Disallow empty catch blocks |
|
|
134
|
+
| `vibe/no-magic-numbers` | No | Disallow magic numbers |
|
|
135
|
+
| `vibe/no-deep-nesting` | No | Disallow deep nesting |
|
|
136
|
+
| `vibe/max-function-length` | No | Enforce max function length |
|
|
137
|
+
|
|
138
|
+
## Claude Code Skills
|
|
139
|
+
|
|
140
|
+
| Skill | Purpose |
|
|
141
|
+
|-------|---------|
|
|
142
|
+
| `/vibe-check` | Full code quality audit |
|
|
143
|
+
| `/styleguide` | Generate a styleguide from design preferences |
|
|
144
|
+
| `/tdd-feature` | Build features test-first with AI |
|
|
145
|
+
| `/e2e-scaffold` | Generate E2E test structure |
|
|
146
|
+
| `/review` | Code review for issues |
|
|
147
|
+
| `/explain` | Explain code line by line |
|
|
148
|
+
| `/refactor` | Guided refactoring |
|
|
149
|
+
| `/add-tests` | Add tests to existing code |
|
|
150
|
+
| `/fix-types` | Fix TypeScript without `any` |
|
|
151
|
+
| `/security-check` | Check for vulnerabilities |
|
|
152
|
+
|
|
153
|
+
## Philosophy
|
|
154
|
+
|
|
155
|
+
These are **guardrails, not gatekeepers**:
|
|
156
|
+
- Warn about most issues (awareness > blocking)
|
|
157
|
+
- Block only security-critical problems
|
|
158
|
+
- Support `# noqa:` and `// eslint-disable` suppression
|
|
159
|
+
- Little and often make much
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT - see [LICENSE](LICENSE)
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
Built by [AllThrive AI](https://allthrive.ai) for the vibe coding community.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* vibe-check CLI
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx vibe-check .
|
|
8
|
+
* npx vibe-check src/app.ts
|
|
9
|
+
* npx vibe-check . --only secrets,urls
|
|
10
|
+
* npx vibe-check . --skip any-types
|
|
11
|
+
* npx vibe-check . --format json
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { main } from '../dist/cli.js';
|
|
15
|
+
|
|
16
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
17
|
+
console.error('Fatal error:', error.message);
|
|
18
|
+
process.exit(2);
|
|
19
|
+
});
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entry point for vibe-check
|
|
3
|
+
*/
|
|
4
|
+
import type { CheckOptions, SummaryResult } from './utils/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Main vibe-check function
|
|
7
|
+
*/
|
|
8
|
+
export declare function vibeCheck(files: string[], options?: CheckOptions): SummaryResult;
|
|
9
|
+
/**
|
|
10
|
+
* CLI main function
|
|
11
|
+
*/
|
|
12
|
+
export declare function main(args: string[]): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EACV,YAAY,EAEZ,aAAa,EAId,MAAM,kBAAkB,CAAC;AAsI1B;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,YAAiB,GAAG,aAAa,CA0CpF;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BxD"}
|