LLMs with Bash access will occasionally run destructive database commands during verification or debugging —Documentation Index
Fetch the complete documentation index at: https://mintlify.com/swt-labs/vibe-better-with-claude-code-vbw/llms.txt
Use this file to discover all available pages before exploring further.
migrate:fresh, db:drop, TRUNCATE TABLE — wiping development data without warning. VBW prevents this with a PreToolUse hook that intercepts every Bash call before it reaches the shell.
How it works
bash-guard.sh fires on the Bash tool, not on a specific agent. Every Bash command from every agent passes through the same gate. The hook pattern-matches against a blocklist and blocks matches with exit code 2 (fail-closed). The command never executes.
Three defense layers
| Layer | Type | When it fires | Reliability |
|---|---|---|---|
bash-guard.sh | PreToolUse hook | Before every Bash call | Deterministic (regex match) |
| Agent prompt rules | Behavioral guidance | When agent reads its instructions | Probabilistic (model compliance) |
forbidden_commands contract | PostToolUse hard gate | After Bash execution | Deterministic but reactive |
Agents covered
All five agents with Bash access are filtered equally:- Dev — primary implementation agent
- QA — verification and testing
- Lead — orchestration and coordination
- Debugger — investigation and diagnosis
- Docs — documentation tasks
Patterns blocked
40+ patterns across every major ecosystem:| Category | Blocked patterns |
|---|---|
| PHP / Laravel | artisan migrate:fresh, artisan migrate:reset, artisan migrate:refresh, artisan db:wipe, artisan db:seed --force |
| Ruby / Rails | rails db:drop, rails db:reset, rake db:schema:load, bundle exec rake db:drop |
| Python / Django | manage.py flush, manage.py sqlflush, django-admin flush |
| Prisma | prisma migrate reset, prisma db push --force-reset, npx prisma migrate reset |
| Knex | knex migrate:rollback --all |
| Sequelize | sequelize db:drop, npx sequelize-cli db:drop |
| TypeORM | typeorm schema:drop |
| Drizzle | drizzle-kit push --force |
| Go | migrate ... drop (via golang-migrate) |
| Rust / Diesel | diesel database reset, diesel migration revert --all |
| Rust / SQLx | sqlx database drop |
| Elixir / Ecto | mix ecto.drop, mix ecto.reset, mix ecto.rollback --all |
| Raw SQL | DROP DATABASE, DROP TABLE, TRUNCATE via mysql, psql, sqlite3, mongosh |
| MongoDB | dropDatabase(), .drop() via mongosh |
| Redis | redis-cli FLUSHALL, redis-cli FLUSHDB |
| Docker volumes | docker-compose down -v, docker compose down -v, docker volume rm, docker volume prune, docker system prune --volumes |
| Filesystem | rm *.sqlite3, rm *.db, rm -rf /var/lib/mysql (and postgresql, mongodb) |
php artisan migrate (forward migration), rails db:migrate, prisma migrate dev, docker-compose down (without -v), and all read-only queries.
Override options
When you legitimately need to run a destructive command, you have three options: Environment variable — SetVBW_ALLOW_DESTRUCTIVE=1 before starting your session. The guard checks this first and exits immediately with zero overhead.
.vbw-planning/config.json directly:
Extending the blocklist
Add project-specific patterns to.vbw-planning/destructive-commands.local.txt:
config/destructive-commands.txt. Local patterns supplement the defaults — they don’t replace them.
Event logging
Every blocked command is logged to.vbw-planning/.event-log.jsonl with:
- Command preview (truncated to 40 characters)
- Matched pattern
- Agent name (
VBW_ACTIVE_AGENT) - Timestamp
Design notes
Fail-closed. Ifjq is missing, input is unparseable, or anything unexpected happens, the guard blocks the command (exit 2). It never fails open.
~50ms overhead. One jq parse + one grep per Bash call. The 5-second hook timeout in hooks.json provides a safety ceiling.