Skip to main content

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:

  1. Create a Stripe account and get your API keys
  2. Create subscription products/prices in Stripe Dashboard
  3. 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

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stablestack-0.3.23.tar.gz (184.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stablestack-0.3.23-py3-none-any.whl (167.4 kB view details)

Uploaded Python 3

File details

Details for the file stablestack-0.3.23.tar.gz.

File metadata

  • Download URL: stablestack-0.3.23.tar.gz
  • Upload date:
  • Size: 184.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for stablestack-0.3.23.tar.gz
Algorithm Hash digest
SHA256 c91bdc9616c3f1526db53fd474be2eeaafafbd0b07c71121d4fef2fef6006a6f
MD5 82d18eec561534046f05c6306660b7c0
BLAKE2b-256 4a086bffa8f7a4445c4fcd9a77752a621ad625eb144eaf91cbd446d3fa74b9c7

See more details on using hashes here.

File details

Details for the file stablestack-0.3.23-py3-none-any.whl.

File metadata

  • Download URL: stablestack-0.3.23-py3-none-any.whl
  • Upload date:
  • Size: 167.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for stablestack-0.3.23-py3-none-any.whl
Algorithm Hash digest
SHA256 d9afd0d74ef873b813db38e2a436a70b49276f504d046227e238776e866d5979
MD5 352cf51a3556b3eac82eb976b1a4cafa
BLAKE2b-256 438493274947add4b59e50ad395eef5ee0e8ab3eb56bd5887a229b7deb72c218

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page