Skip to main content

AI code safety scanner + prompt version control, with a global git pre-commit hook

Project description

Vibeguard

The safety layer for AI-generated code.

Stop committing bugs you didn't write.

You paste AI code. You commit. Three weeks later an API key is scraped, or your app breaks silently in production with no logs, no trace, nothing to debug. Vibeguard sits at the one moment between "AI wrote it" and "it's in git forever" — your commit — and stops the ones that matter.

$ git commit -m "add auth"

╔═══════════════════════════════════════════════════════╗
║  vibeguard blocked this commit                        ║
║  HIGH severity issues must be fixed before committing ║
║                                                       ║
║  [HIGH] auth.py:14  → Hardcoded secret               ║
║  [HIGH] api.py:31   → SQL string injection            ║
║  [MED]  config.py:5 → Hardcoded localhost             ║
╚═══════════════════════════════════════════════════════╝

Install once. Guards every repo on your machine automatically. Zero config. Works offline.

🔗 github.com/Jen-chad/vibe-tools · Python 3.10+ · macOS · Linux · Windows · MIT


30-second install

pip install jenchad-guard
vibeguard hook install

Done. Every future git commit on your machine is now guarded. No per-repo setup. No config files to write. Just works.

Want to scan right now?

cd your-project
vibeguard check .

Built for how you actually code today

If any of these sound familiar, this tool is for you:

  • You paste code from ChatGPT, Claude, or Cursor and commit it without reading every line
  • You've rotated an API key because it ended up in a public repo
  • Your app broke in production with no error log because the AI wrapped everything in except: pass
  • You've shipped DEBUG=True or http://localhost:3000 into a live environment
  • You're building with AI agents across multiple sessions and the codebase is drifting

Every other scanner was built for a world where humans write every line. Vibeguard was built for the world you're in now.


What it catches

15 patterns tuned specifically for what AI assistants write carelessly:

ID Severity What it catches Why it matters
P1 HIGH Hardcoded secrets (API keys, tokens, passwords) Scraped by bots within hours of a push
P1b HIGH High-entropy strings (raw JWTs, webhook keys) Catches secrets with no keyword prefix
P_SQL HIGH SQL injection via f-strings or .format() Classic AI habit — f"SELECT * WHERE id={uid}"
P_SHELL HIGH subprocess with shell=True Allows arbitrary command execution
P_DESER HIGH pickle.loads() / yaml.load() without SafeLoader Remote code execution if input is untrusted
P_EVAL HIGH eval()/exec() on user input Remote code execution
P_ADMIN HIGH Hardcoded admin / root credentials Trivial to exploit
P2 HIGH except: pass — silent error catch App fails with no trace, no log
P3 HIGH Empty JS/TS catch blocks .catch(() => {}) Same as P2 but JavaScript
P4 HIGH Credentials printed to logs Visible in every monitoring tool
P7 MED except Exception: pass — broad swallow Bugs vanish completely in production
P5 MED TODO/FIXME left in production paths AI placeholder running in live code
P6 MED Hardcoded localhost / 127.0.0.1 Works locally, breaks every real deploy
P8 LOW DEBUG=True / NODE_ENV=development Exposes stack traces in production
P_DUP MED Same function defined in multiple files AI re-implements helpers across sessions

Scans: .py .js .ts .jsx .tsx .json .yaml .yml .sh .bash .env

Auto-skips: node_modules, dist, build, .next, __pycache__, minified files, binaries, lock files, files over 500 KB.


How it works

Offline-first. The scanner runs entirely on your machine. No internet required. No API key needed for the core scan.

Git-aware. Runs git diff and scans only the files that changed in your last commit — fast, targeted, no noise from the rest of the codebase. Falls back to a full scan on brand-new repos.

Entropy scanning. Beyond keyword matching, high-entropy strings (raw JWTs, webhook secrets, base64 keys) are caught by Shannon entropy analysis — no keyword prefix needed.

Pre-commit hook. Optionally installs itself as a global git hook so every git commit on your machine runs the scanner automatically and blocks if serious issues are found.

Paper trail. Every scan is appended to VIBELOG.md in your project root — an append-only history of what was found and when. Auto-added to .gitignore so it never pollutes git status.

AI features (optional, needs a free Groq key):

  • --narrate — 3-bullet plain-English explanation of what the diff changed and why it's risky
  • --explain — numbered fix guidance for each issue, with AI elaboration on your specific code

Complete setup guide

Step 1 — Install

pip install jenchad-guard

Verify:

vibeguard --version
# vibeguard 1.0.0

This installs three commands:

Command What it does
vibeguard Main CLI — entry point for everything
vibecheck Direct alias for the code scanner
promptgit Direct alias for prompt version control

Step 2 — Install the global pre-commit hook

vibeguard hook install

This writes a hook to ~/.config/git/hooks/pre-commit and sets git config --global core.hooksPath so every repo on your machine uses it automatically — existing and future projects alike.

Verify:

vibeguard hook status

From this point forward, any git commit that introduces a HIGH-severity issue is blocked until you fix it.


Step 3 — (Optional) Add AI features with a free Groq key

The scanner works fully offline without this. But if you want plain-English diff explanations and AI-powered fix guidance, get a free Groq key at console.groq.com — takes about two minutes.

Run the guided setup wizard:

vibeguard setup

Or set the key manually:

# macOS / Linux — add to ~/.bashrc or ~/.zshrc
export GROQ_API_KEY="your-key-here"

# Windows (Command Prompt)
set GROQ_API_KEY=your-key-here

# Windows (PowerShell)
$env:GROQ_API_KEY="your-key-here"

Step 4 — (Optional) Create a .vibecheck config file

Drop a .vibecheck file in your project root (or ~/) to set defaults without passing flags every time:

# .vibecheck
mode    = dev        # eli5 | beginner | dev  (AI explanation style)
strict  = false      # true = also fail on MED issues
compact = false      # true = one line per issue output

CLI flags always override the config file.


Scanning your code

Basic scan

cd your-project
vibeguard check .

Scans the files changed in your last git commit. Output:

╭──────────────────────────────────────────────╮
│         vibecheck  v1.0.0                    │
│         Scanned 4 file(s)                    │
╰──────────────────────────────────────────────╯

╭─── Scan results ─────────────────────────────────────────────────────╮
│ Severity │ File      │ Line │ Issue              │ Why it matters     │
│ HIGH     │ auth.py   │ 14   │ Hardcoded secret   │ Scraped within...  │
│ HIGH     │ api.py    │ 31   │ SQL string inject  │ Dynamic SQL via... │
│ MED      │ config.py │ 5    │ Hardcoded localhost│ Works locally...   │
╰──────────────────────────────────────────────────────────────────────╯

Summary:  2 HIGH  1 MED  0 LOW

Suppress a false positive: add  # vibecheck-ignore  or  # vibecheck-ignore: P1  to the flagged line.
Run with  --explain  for step-by-step fix guidance on each issue.

Exit codes: 1 if HIGH issues are found (blocks the hook). 0 if clean.


All scan flags

--explain — numbered fix guidance (offline + optional AI)

After the scan, shows a numbered list of every issue. Type a number for instant fix guidance — before/after code examples for that specific pattern, no format to memorise, no transcription:

vibeguard check . --explain
Fix guidance  (enter number, or q to quit)

   1  auth.py:14   Hardcoded secret
   2  api.py:31    SQL string injection
   3  config.py:5  Hardcoded localhost

> 1

╭─── [P1] Fix guidance ──────────────────────────────────────────────╮
│ Issue:  Hardcoded secret                                            │
│ File:   auth.py  line 14                                            │
│ Why:    Ships to GitHub and gets scraped by bots within hours.      │
│                                                                     │
│ Code:                                                               │
│   api_key = "sk-abc123verylongsecret"                               │
│                                                                     │
│ How to fix:                                                         │
│   Replace the hardcoded value with an environment variable.         │
│   Before: api_key = "sk-abc123"                                     │
│   After:  api_key = os.getenv("API_KEY")                            │
╰─────────────────────────────────────────────────────────────────────╯

Works 100% offline. If GROQ_API_KEY is set, an AI elaboration panel appears below with 2-3 sentences targeted to your specific code.


--narrate — 3-bullet AI diff summary (needs Groq key)

Sends your git diff to Groq and returns a plain-English explanation of what changed and what could break:

vibeguard check . --narrate
vibeguard check . --narrate --mode eli5    # plain words, no jargon
vibeguard check . --narrate --mode dev     # technical, senior-engineer voice

Three explanation modes:

Mode Who it's for Labels
dev (default) Engineers who want the technical summary Change · Impact · Risk
beginner Junior devs or non-technical reviewers What changed · Why · Risk
eli5 Anyone, plainest possible English What changed · Why · Risk

--autofix — generate fix prompts

For every issue found, generates a targeted prompt you can paste into Claude, ChatGPT, or Cursor to fix only that specific issue:

vibeguard check . --autofix           # one prompt per issue
vibeguard check . --autofix --one-prompt   # combine all into one prompt
vibeguard check . --autofix --copy         # copy prompt(s) to clipboard

Each prompt contains the file name, line number, the problematic code, and strict rules to fix only that issue — nothing else.


--strict — also block on MED issues

By default only HIGH issues block commits. Strict mode also blocks on MED:

vibeguard check . --strict

Recommended for production services or security-sensitive code.


--compact — one line per issue (CI-friendly)

vibeguard check . --compact
[HIGH] auth.py:14      → Hardcoded secret
[HIGH] api.py:31       → SQL string injection
[MED ] config.py:5     → Hardcoded localhost

No ANSI colour codes when piped — automatically clean for CI logs.


--commits N — scan more history

vibeguard check . --commits 3    # scan files changed in last 3 commits
vibeguard check . --commits 10   # useful after merging a large branch

--mode — set AI explanation style

vibeguard check . --mode eli5
vibeguard check . --mode beginner
vibeguard check . --mode dev

Can also be set permanently in .vibecheck.


Suppressing false positives

Add a comment to any line to suppress that issue:

# Suppress everything on this line
BASE_URL = "http://localhost:3000"   # vibecheck-ignore

# Suppress a specific pattern only (P6 = hardcoded localhost)
BASE_URL = "http://localhost:3000"   # vibecheck-ignore: P6

# Suppress multiple patterns
key = get_test_key()                 # vibecheck-ignore: P1, P1b

The suppress hint appears at the bottom of every scan that finds issues — you never need to memorise the syntax.


The global git hook

The most useful Vibeguard feature. Install once, guard everything.

vibeguard hook install          # normal mode — blocks HIGH
vibeguard hook install --strict  # strict mode — blocks HIGH + MED

Hook controls

vibeguard hook status           # show current status
vibeguard hook uninstall        # remove the hook entirely

vibeguard hook disable          # skip this repo only (hook stays on everywhere else)
vibeguard hook enable           # re-enable for this repo

vibeguard hook enable-strict    # block MED + HIGH globally
vibeguard hook disable-strict   # block HIGH only globally

Per-repo overrides

# Turn strict ON for this repo (even if global strict is off)
git config vibe-tools.strict true

# Turn strict OFF for this repo (even if global strict is on)
git config vibe-tools.strict false

# Disable scanning entirely for this repo
git config vibe-tools.disable true

Bypass in an emergency

git commit --no-verify -m "your message"

Use sparingly. The hook exists to protect you.


VIBELOG — your scan history

Every scan automatically appends a timestamped entry to VIBELOG.md in your project root:

# vibecheck scan log

Append-only record of every vibecheck scan on this project.

---

## 2026-03-21 14:32 UTC — 4 file(s) scanned
**Issues:** 2 HIGH  1 MED  0 LOW

| Severity | File | Line | Issue |
|----------|------|------|-------|
| HIGH | auth.py | 14 | Hardcoded secret |
| HIGH | api.py | 31 | SQL string injection |
| MED | config.py | 5 | Hardcoded localhost |

VIBELOG.md is automatically added to your .gitignore on first scan — it never pollutes git status.


Prompt version control

Vibeguard includes promptgit — lightweight version control for the system prompts, AGENTS.md files, and instruction files that drive your AI workflow. Think of it as git specifically for .md and .txt prompt files.

Why this exists

When you're iterating on a system prompt, you end up with prompt_v1.md, prompt_v2_final.md, prompt_ACTUALLY_FINAL.md. Promptgit replaces that chaos with a clean commit history and one-command rollback.

Setup

cd your-project

# Initialise promptgit in this directory
vibeguard prompt init

# Tell it which files to track
vibeguard prompt add AGENTS.md
vibeguard prompt add system-prompt.txt

Saving versions

vibeguard prompt commit -m "initial prompt"

# After editing your prompt:
vibeguard prompt commit -m "added JSON output rule"
vibeguard prompt commit -m "tightened response to 150 words"

Viewing history

vibeguard prompt log
 Ref  │ Hash     │ Timestamp            │ Message                   │ Words
 v3   │ c4d5e6f7 │ 2026-03-21 11:30 UTC │ tightened response length │ 162
 v2   │ a1b2c3d4 │ 2026-03-21 10:00 UTC │ added JSON output rule    │ 148
 v1   │ 9f8e7d6c │ 2026-03-20 09:00 UTC │ initial prompt            │ 98

Rolling back

vibeguard prompt rollback v1          # restore version 1
vibeguard prompt rollback 9f8e7d6c    # restore by hash
vibeguard prompt rollback HEAD        # restore most recent

Rollback shows you exactly what it will overwrite and asks for confirmation before doing anything.


How Vibeguard compares

Most security tools were built for CI — they run after code is already pushed. Vibeguard runs at commit time, on your machine, before anything leaves.

Vibeguard Bandit Semgrep detect-secrets Ruff
AI-generated bug patterns ✅ 15 built-in ⚠️ Python only ⚠️ Needs custom rules
SQL / shell injection ✅ Python only ⚠️ Paid
Entropy-based secret detection ✅ Built-in ⚠️ Paid
Duplicate function detection ✅ Cross-file
Global git hook (one command) ⚠️ Per-repo ⚠️ Per-repo ⚠️ Per-repo ⚠️ Per-repo
Scans only changed files ✅ Auto via git diff ❌ Full scan ⚠️ CI mode only ❌ Full scan ❌ Full scan
Offline (no internet needed) ✅ Core scan
AI narration of diff ✅ Free (Groq)
Fix guidance per issue ✅ Offline
Scan history (VIBELOG) ✅ Auto
Prompt version control ✅ Built-in
Zero config to start ⚠️
JS / TS / YAML / shell
Free & open source ✅ MIT ✅ Community

The right stack: Vibeguard is not a replacement for Bandit or Ruff — it fills a different gap.

Project type Recommended
Python only Vibeguard (safety + hook) + Ruff (style) + Bandit (deep Python security in CI)
Python + JS/TS Vibeguard (safety + hook) + Ruff (Python style)
Security-critical Vibeguard + Bandit + detect-secrets (all in CI)
Any AI-assisted project Vibeguard as the first line — catches what AI gets wrong, regardless of language

Naming

Three names, one tool:

Name What it is
Vibeguard The brand. What you call it, search for it, star on GitHub.
jenchad-guard The PyPI package name (pip install jenchad-guard). PyPI requires globally unique names.
vibeguard / vibecheck / promptgit The CLI commands installed on your machine.

Same pattern as Beautiful Soup (installed as beautifulsoup4) and Pillow (the PIL fork).


Troubleshooting

vibeguard: command not found

The pip scripts directory isn't in your PATH:

pip install --force-reinstall jenchad-guard

# If still not found, add scripts to PATH:
python -m site --user-base
# → /home/yourname/.local
# Add /home/yourname/.local/bin to your PATH

--narrate or --explain AI features not working

# Check the key is set
echo $GROQ_API_KEY        # macOS/Linux
echo %GROQ_API_KEY%       # Windows

# Run guided setup
vibeguard setup

# Or set manually
export GROQ_API_KEY="your-key-here"

The scanner and git hook work without a key — only AI features need it.

groq package not installed

pip install groq

Hook not blocking commits

vibeguard hook status

# If disabled for this repo:
git config --local vibe-tools.disable
# If prints "true":
vibeguard hook enable

Need to commit urgently despite issues

git commit --no-verify -m "your message"

Blocked commit but issue is a false positive

Add a suppression comment to the flagged line:

url = "http://localhost:3000"   # vibecheck-ignore: P6

Uninstalling

vibeguard hook uninstall
pip uninstall jenchad-guard

hook uninstall clears core.hooksPath from your global git config — git returns to default behaviour immediately.


License

MIT — github.com/Jen-chad/vibe-tools

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

jenchad_guard-1.0.10.tar.gz (33.8 kB view details)

Uploaded Source

Built Distribution

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

jenchad_guard-1.0.10-py3-none-any.whl (32.3 kB view details)

Uploaded Python 3

File details

Details for the file jenchad_guard-1.0.10.tar.gz.

File metadata

  • Download URL: jenchad_guard-1.0.10.tar.gz
  • Upload date:
  • Size: 33.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for jenchad_guard-1.0.10.tar.gz
Algorithm Hash digest
SHA256 bba45271cf31d6f8af67095e5a3c5deba6185747563c85fe022b9dc37b0728d7
MD5 4fb4dd88d7be7d6d1ee0c22f012c488f
BLAKE2b-256 babb637365a7337be9d648c6a678407846fae073aa186a97cd3cfeaaabb9377e

See more details on using hashes here.

File details

Details for the file jenchad_guard-1.0.10-py3-none-any.whl.

File metadata

  • Download URL: jenchad_guard-1.0.10-py3-none-any.whl
  • Upload date:
  • Size: 32.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for jenchad_guard-1.0.10-py3-none-any.whl
Algorithm Hash digest
SHA256 b9df7bcf0b50be0c11f5c1a42a02611e08c40edb73740de88fc7d249fdffd2e6
MD5 e9fba49001e17bb8efef86f04cd021c4
BLAKE2b-256 848257f7b3b7fa2f17f4ebfe4d3efbed195c6fbc9173f6c1ce76a81d94dd0f48

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