Your AI-generated code, double-checked. Catches subtle bugs that AI assistants often introduce.
Project description
vibecheck
Your AI-generated code, double-checked.
A lightweight linter that catches subtle bugs AI assistants often introduce. 71 rules across 19 categories, focused on issues that existing linters miss.
Installation
pip install vibecheck
Or install from source:
git clone https://github.com/pfrank8/vibecheck
cd vibecheck
pip install -e .
Quick Start
# Check your source directory
vibecheck src/
# Check specific files
vibecheck app.py utils.py
# CI mode (exit code 1 if errors found)
vibecheck src/ --ci
# JSON output for CI/CD
vibecheck src/ --format json > results.json
Repository Structure
| Directory | Description |
|---|---|
/site |
Marketing website (Next.js) - the primary deployed application at stablestack.ai |
/stablestack |
Core product code - the vibecheck CLI and analysis engine |
/ |
Root contains shared configs, documentation, and Python package setup |
To run the marketing site locally:
cd site
npm install
npm run dev
Stripe Configuration (Optional)
The site includes Stripe Checkout for paid subscriptions. To enable payments:
- Create a Stripe account and get your API keys
- Create subscription products/prices in Stripe Dashboard
- Set the following environment variables:
# Required for checkout to work
STRIPE_SECRET_KEY=sk_live_... # or sk_test_... for testing
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_... # or pk_test_... for testing
# Price IDs from your Stripe Dashboard
NEXT_PUBLIC_STRIPE_PRICE_INDIE=price_...
NEXT_PUBLIC_STRIPE_PRICE_ENTERPRISE=price_...
If these variables are not set, the pricing page will display a notice and checkout buttons will show an error. The site builds and runs normally without Stripe configured.
What It Catches
71 rules across 19 categories. See CHECKERS.md for complete documentation.
Determinism Issues (DET001-DET008)
Non-deterministic code breaks LLM caching and causes flaky tests:
| Rule | Issue | Impact |
|---|---|---|
| DET001 | Unsorted dict iteration | Cache misses, flaky tests |
| DET002 | Unsorted set iteration | Random ordering |
| DET003 | Missing sort tiebreaker | Unstable ordering |
| DET004 | list(set()) deduplication | Order scrambling |
| DET005 | Random without seed | Non-reproducible results |
| DET006 | datetime.now() usage | Time-dependent bugs |
| DET007 | Unsorted directory listing | Platform-dependent order |
| DET008 | Hashing unsorted collections | Inconsistent cache keys |
Security Issues (SEC001-SEC011)
Catch vulnerabilities before they reach production:
| Rule | Issue | Risk |
|---|---|---|
| SEC001 | Hardcoded secrets | Credential leaks |
| SEC002 | SQL injection | Database compromise |
| SEC003 | eval() usage | Code execution |
| SEC004 | Insecure random | Predictable tokens |
| SEC005 | innerHTML XSS | Script injection |
| SEC006 | Webhook bypass | Forged webhooks |
| SEC007 | OAuth state missing | CSRF attacks |
| SEC008 | Plaintext tokens | Data breach exposure |
| SEC009 | Email header injection | Email spoofing |
| SEC010 | CSV formula injection | Code execution |
| SEC011 | Unsanitized HTML | XSS attacks |
Quality Issues (QUAL001-QUAL008)
Code quality problems that cause production bugs:
| Rule | Issue |
|---|---|
| QUAL001 | Swallowed exceptions (Python + JS/TS) |
| QUAL002 | Unnamed threads |
| QUAL003 | Complex tuple types |
| QUAL004 | Mutable default arguments |
| QUAL005 | Print statements |
| QUAL006 | TODO/FIXME comments |
| QUAL007 | Broad exception catching |
| QUAL008 | Magic numbers |
API Issues (API001-API004)
Frontend-backend integration problems:
| Rule | Issue |
|---|---|
| API001 | Unhandled API errors |
| API002 | Inconsistent naming (snake_case vs camelCase) |
| API003 | Missing Content-Type headers |
| API004 | Hardcoded API URLs |
Async Issues (ASYNC001-ASYNC004)
Common async/await mistakes:
| Rule | Issue |
|---|---|
| ASYNC001 | Missing await on async calls |
| ASYNC002 | Blocking calls in async functions |
| ASYNC003 | Fire-and-forget tasks |
| ASYNC004 | Silent .catch() handlers |
Concurrency Issues (CONC001)
Race conditions and thread safety:
| Rule | Issue |
|---|---|
| CONC001 | Check-then-act race conditions |
Type Safety Issues (TYPE001-TYPE010)
Type safety beyond basic linting:
| Rule | Issue |
|---|---|
| ASYNC001 | Missing await on async calls |
| ASYNC002 | Blocking calls in async functions |
| ASYNC003 | Fire-and-forget tasks without error handling |
Performance Issues (PERF001)
| Rule | Issue |
|---|---|
| PERF001 | N+1 queries in loops |
Project Issues (PROJ001-PROJ003)
Project setup and configuration checks:
| Rule | Issue |
|---|---|
| PROJ001 | Missing CLAUDE.md file for AI context |
| PROJ002 | Not using git version control |
| PROJ003 | Missing pyright configuration |
Structure Issues (STRUCT001-STRUCT010)
Code organization problems:
| Rule | Issue |
|---|---|
| STRUCT001 | Multiple classes in one file |
| STRUCT003 | Imports inside functions |
| STRUCT004 | sys.path manipulation |
| STRUCT005 | Relative imports |
| STRUCT006 | hasattr/getattr on typed fields |
| STRUCT009 | Class name doesn't match filename |
| STRUCT010 | Mixed frontend/backend code |
Type Safety Issues (TYPE001-TYPE009)
Type annotation problems:
| Rule | Issue |
|---|---|
| TYPE001 | Weak typing (Dict[str, Any]) |
| TYPE002 | Naked dict for structured data |
| TYPE004 | Missing type hints |
| TYPE006 | Inline type definitions |
| TYPE007 | Duplicate type definitions |
| TYPE008 | TypeScript 'any' usage |
| TYPE009 | Env var non-null assertions |
Testing Issues (TEST001-TEST004)
Test quality problems:
| Rule | Issue |
|---|---|
| TEST001 | Skipped tests |
| TEST003 | Async mock issues |
| TEST004 | Duplicate test helpers |
Session Issues (SESS001)
Database session problems:
| Rule | Issue |
|---|---|
| SESS001 | DB session passed to background tasks |
Datetime Issues (DATE002-DATE003)
Timezone problems:
| Rule | Issue |
|---|---|
| DATE002 | Naive datetime (no timezone) |
| DATE003 | DB datetime used without timezone check |
Kubernetes Issues (KUBE001)
Container compatibility:
| Rule | Issue |
|---|---|
| KUBE001 | Local filesystem for app data |
Import Issues (IMPORT001)
Import problems:
| Rule | Issue |
|---|---|
| IMPORT001 | Imports shadowing builtins |
Rate Limiting Issues (RATE001)
API protection:
| Rule | Issue |
|---|---|
| RATE001 | Missing rate limiting on endpoints |
Frontend Issues (FRONT002-FRONT003)
React/Next.js issues:
| Rule | Issue |
|---|---|
| FRONT002 | window/document without SSR check |
| FRONT003 | Inline arrow functions in JSX |
Example Output
src/cache.py
⚠ Line 42: Looping through 'config.items()' without sorting. This may produce different results on different runs.
Problem:
for key, value in config.items():
Fix:
for key, value in sorted(config.items()):
Why? Dictionary order isn't guaranteed to be the same every time your program runs.
This can cause tests to pass sometimes and fail other times, and can break caching
systems that depend on consistent output.
────────────────────────────────────────────────────────────
Found 1 warning in 1 file
Configuration
Configure vibecheck in your pyproject.toml:
[tool.vibecheck]
# Enable only specific rules
enable = ["DET001", "DET002", "SEC001", "SEC002"]
# Or disable specific rules
disable = ["QUAL005", "QUAL006"]
# Path patterns
include = ["src/**/*.py"]
exclude = ["**/migrations/**", "**/test_*.py"]
# Override severity for specific rules
[tool.vibecheck.rules.DET001]
severity = "info" # Downgrade from warning to info
CLI Options
Usage: vibecheck [OPTIONS] [PATHS]...
Options:
-f, --format [text|json] Output format (default: text)
-c, --config PATH Path to pyproject.toml config file
--enable TEXT Comma-separated list of rule IDs to enable
--disable TEXT Comma-separated list of rule IDs to disable
--ci CI mode: exit with code 1 if any errors found
--no-color Disable colored output
--no-why Don't show 'why this matters' explanations
-v, --version Show version and exit
--help Show this message and exit
Why vibecheck?
AI coding assistants are amazing, but they sometimes generate code with subtle issues:
- Non-deterministic patterns that work during development but break LLM caching and cause flaky tests
- Security vulnerabilities like hardcoded secrets and SQL injection
- Silent failures that hide bugs until production
- Async mistakes like missing await that cause hard-to-debug issues
- Type safety issues that bypass IDE checking
- Kubernetes-hostile patterns that break in containers
vibecheck catches these patterns that traditional linters miss.
Key benefits:
- Improve LLM cache hit rates from 30% to 95%+
- Eliminate flaky tests caused by non-determinism
- Catch security issues before they reach git history
- Beginner-friendly explanations for every issue
- Sensible pyright configuration recommendations
Language Support
- Python (.py) - All 71 rules
- TypeScript/JavaScript (.ts, .tsx, .js, .jsx) - 29 rules:
- DET: Random without seed, datetime.now() usage
- QUAL: Exception swallowing, file length
- API: Unhandled errors, naming, headers, URLs
- SEC: Secrets, SQL injection, eval, insecure random, XSS, webhooks
- ASYNC: Missing await, blocking calls (fs.readFileSync, execSync, etc.)
- TYPE: TypeScript any, env non-null assertions, unsafe JSON parsing
- FRONT: SSR safety, inline JSX handlers
- TEST: Skipped tests (Jest, Vitest, Playwright, Mocha)
- PERF: N+1 queries (Prisma, TypeORM, Sequelize, Mongoose, Drizzle)
- RATE: Missing rate limiting on endpoints
- KUBE: Local filesystem data storage
- Project-level - PROJ rules check any directory
Documentation
- CHECKERS.md - Complete reference for all 71 rules
- MARKETING.md - Value propositions and ROI analysis
Development Setup
Secrets Management
This project uses Doppler for secrets management:
# Install Doppler CLI
brew install dopplerhq/cli/doppler
# Login (creates scoped credentials for this directory)
doppler login --scope /path/to/vibecheck
# Setup the project (uses doppler.yaml config)
doppler setup
# Run commands with secrets injected
doppler run -- python -m pytest
doppler run -- vibecheck src/
Ask a team member to invite you to the CTS workspace in Doppler.
Contributing
Contributions welcome! Please see CONTRIBUTING.md for guidelines.
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stablestack-0.3.3.tar.gz.
File metadata
- Download URL: stablestack-0.3.3.tar.gz
- Upload date:
- Size: 24.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d2019527077ba676f0096f8ff0ac427a33753523ba74f37bbfa17ec83cefcce
|
|
| MD5 |
34fde1adcb7ea8477c0c12748d34b84d
|
|
| BLAKE2b-256 |
edf90272debe21c8b7f118c2d191f3a16884b1744875afea89c2b838752a2e96
|
File details
Details for the file stablestack-0.3.3-py3-none-any.whl.
File metadata
- Download URL: stablestack-0.3.3-py3-none-any.whl
- Upload date:
- Size: 1.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
809987339784f39e8fb0378ba90592db2e6b430878acc1cac043fcae073956e8
|
|
| MD5 |
750a4d293d9bb69380cb966fbacfa3bd
|
|
| BLAKE2b-256 |
5bd23b94bc5eab68dbcee352f5c1390c12451dd5f916ee89e35f7990432a7db0
|