Vibe coding is real and it's genuinely good. You describe what you want, the AI writes the code, runs tests, fixes errors, deploys. The feedback loop collapses from minutes to seconds. Entire features appear while you're still holding your coffee.
The problem isn't the AI's ability to write code. The problem is that writing code and executing commands on your infrastructure are very different risk profiles — and most vibe coding setups treat them identically.
When Codex, Claude, or Cursor runs npm test, that's fine. When it runs psql production -c "DROP TABLE sessions" to "clean up test data" — that's a different story. And unlike a human, the AI doesn't pause before destructive commands. It just runs them, because you told it to "clean up."
The actual failure modes
These aren't hypothetical. They're patterns that emerge naturally from how AI coding agents work:
1. Context collapse
You're working in dev. You tell the agent to "run the migration to add the new column." The agent runs it — on production, because the DATABASE_URL env var pointed there and the agent didn't know to check. The migration runs. It works. You now have a new column in production before you tested it anywhere else.
The agent did exactly what you asked. You just didn't specify which database.
2. Cleanup that isn't
You ask the agent to "clean up the temporary files from that last run." The agent interprets this broadly, deletes some build artifacts, then also removes a cache directory that turned out to be the persistent session store. Your users' sessions are gone. The agent was thorough.
3. The helpful rollback
Something is broken. You ask the agent to fix it. The agent decides the cleanest fix is to roll back to the previous deployment. It does. What the agent didn't know: the previous deployment had a security patch removed. You're now running vulnerable code and you don't know why.
4. Scope creep in shell commands
You ask the agent to "restart the backend so the config change takes effect." The agent runs pkill -f expacti-backend, which kills the process. Then it notices the process isn't coming back up and, trying to be helpful, runs additional commands to investigate — reading config files, checking logs, eventually trying to restart other services it thinks might be related.
What started as a one-command restart became a five-command debugging session, with each command potentially affecting production state.
In all four cases, the AI did what it was told — or what it reasonably inferred you wanted. The problem isn't intelligence failure. It's that there was no checkpoint between "AI decides to run a command" and "command runs on production."
Why "just sandbox it" isn't enough
The standard advice is to give AI agents sandboxed environments with no production access. This is good advice. It's also incomplete.
At some point the code has to ship. The deployment, the migration, the config change — all of that eventually hits production. You can sandbox the development loop all you want, but deployment is an inherently production-touching activity.
More importantly, many useful vibe coding workflows require production access. Debugging a production issue. Backfilling data. Running a one-off query. Applying a hotfix. If you sandbox everything, you've removed the AI agent from exactly the situations where it's most valuable — and most risky.
What you actually need isn't a wall between AI and production. You need a gate. Let the AI do the work; intercept before execution; give a human 30 seconds to say yes or no.
What command-level interception looks like in practice
Here's a vibe coding session with expacti in the loop. The developer is using Claude to debug a slow query in production:
# Developer prompt to Claude:
# "The /api/sessions endpoint is slow. Find the slow query and fix it."
# Claude decides to run EXPLAIN ANALYZE on the query
EXPACTI: Command pending approval
Command: psql $DATABASE_URL -c "EXPLAIN ANALYZE SELECT * FROM sessions WHERE org_id = $1 ORDER BY started_at DESC LIMIT 50"
Risk: LOW — 12 (read-only EXPLAIN, no data modification)
Context: debugging /api/sessions performance
# Reviewer approves — 8 seconds later
✓ Approved by [email protected]
# Claude sees the query plan, identifies missing index
# Claude proposes: CREATE INDEX CONCURRENTLY on sessions(org_id, started_at)
EXPACTI: Command pending approval
Command: psql $DATABASE_URL -c "CREATE INDEX CONCURRENTLY idx_sessions_org_started ON sessions(org_id, started_at DESC)"
Risk: MEDIUM — 41 (DDL on production table, CONCURRENTLY is safe but irreversible)
Context: fixing slow query identified in prior step
# Reviewer approves — 22 seconds later (read the migration, decided it was safe)
✓ Approved by [email protected]
The entire debug-and-fix loop ran in under 5 minutes, fully AI-driven. Two commands touched production. Both had a human in the loop. The EXPLAIN ran without friction (low risk, fast approval). The DDL got a second of scrutiny (medium risk, reviewer actually read it).
That's the point: not every command needs the same amount of friction. The risk score determines how much attention is warranted.
Risk scoring for shell commands
Expacti scores every command on a 0–100 risk scale before presenting it for approval. The scoring engine covers 14 command categories with 25 modifiers:
| Command | Risk | Why |
|---|---|---|
git status |
LOW — 5 | Read-only, no side effects |
npm test |
LOW — 10 | Local execution, deterministic |
git push origin main |
MEDIUM — 45 | Permanent state change to main branch |
psql prod -c "UPDATE users SET..." |
HIGH — 72 | Direct production DB write |
DROP TABLE sessions |
CRITICAL — 95 | Destructive DDL, unrecoverable |
kubectl delete deployment/api |
CRITICAL — 98 | Production service termination |
The whitelist handles the repetitive safe commands. Once you've approved npm test a few times, it runs automatically. Once you've approved the specific migration pattern your CI uses, that passes without interruption. The AI agent's routine work flows freely; novel or higher-risk actions get flagged.
Setting up expacti for AI coding sessions
The typical setup for a vibe coding workflow:
Option A: Wrap the agent's shell access
If your AI agent calls shell commands through a specific binary or script, wrap it with expacti-sh:
# Instead of the agent running commands directly:
EXPACTI_BACKEND_URL=wss://api.expacti.com/shell/ws \
EXPACTI_SHELL_TOKEN=<your-token> \
expacti-sh
Every command the agent types into this shell is intercepted. The agent's development loop continues at full speed; only commands that exceed your risk threshold pause for approval.
Option B: MCP tool integration
If your AI agent uses MCP tools, the expacti MCP server provides an exec tool that routes through the approval queue. The agent calls exec(command="..."), expacti intercepts, you approve, the result comes back to the agent.
# In your MCP config:
{
"mcpServers": {
"expacti": {
"command": "expacti-mcp",
"env": {
"EXPACTI_URL": "wss://api.expacti.com/shell/ws",
"EXPACTI_TOKEN": "<your-token>"
}
}
}
}
Option C: SSH proxy
If your AI agent SSHs into production machines, expacti-sshd acts as a transparent SSH proxy. The agent connects through it; every command in the session is intercepted before reaching the real server.
# Agent SSH config:
Host production
HostName expacti-sshd.your-infra.com
Port 2222
User agent-user
# All SSH session commands go through expacti's approval queue
This approach requires zero changes to the AI agent. It SSH's to "production" as normal; expacti is invisible until something needs approval.
Tuning the friction level
The most common complaint about human-in-the-loop systems is that they slow everything down. That's a tuning problem, not an inherent tradeoff.
Three levers:
- Whitelist aggressively. Any command pattern you trust unconditionally should be on the whitelist. The AI suggestion engine proposes patterns based on your approval history — accept the ones that make sense. Your vibe coding session shouldn't be interrupted by
cargo test -p backendfor the 50th time. - Set the risk threshold. By default, everything requires approval. You can configure auto-approve below a risk score threshold — say, anything under 20 runs without review. Adjust based on your risk tolerance.
- Use anomaly detection selectively. Expacti's anomaly engine flags commands that are unusual for the time of day, the session, or the command history. If you're doing a late-night vibe coding session, you might want tighter scrutiny than your usual approval flow provides.
In practice, after the first week of a vibe coding setup, 80–90% of commands auto-approve via whitelist. The remaining 10–20% are things you actually want to review: first-time deployments, DDL changes, anything touching production data. The total overhead is a few seconds per hour of coding.
The audit trail benefit
Vibe coding sessions with AI agents are notoriously hard to audit. Did the AI modify the database directly? Which commands ran in that debug session yesterday? What exactly did it deploy?
With expacti in the loop, every command is logged: timestamp, exact command text, risk score, whether it was approved or denied, who approved it, how long the review took. Commands run automatically via whitelist are logged as whitelist-approved with the matching rule.
When something goes wrong — and something always eventually goes wrong — you have a complete record of every command that ran in every AI agent session. Not just the code that was written, but the commands that were executed.
For teams using AI agents in CI/CD
If you're running AI coding agents in CI pipelines that touch production (deployments, migrations, data backfills), the GitHub Actions integration applies the same approval gate to your CI workflow:
- name: AI-proposed migration
uses: kwha/expacti-action@v1
with:
command: ${{ steps.ai-agent.outputs.migration-command }}
expacti-url: ${{ secrets.EXPACTI_URL }}
shell-token: ${{ secrets.EXPACTI_SHELL_TOKEN }}
The AI generates the command; expacti intercepts it; a human reviews the actual SQL before it runs against production. The AI agent's output is used but not blindly trusted.
The meta-point
The whole appeal of vibe coding is that you can move fast. Human-in-the-loop sounds like the opposite of that. The insight is that read operations and safe local commands should be fast — and they are, because they hit the whitelist. What should be slow is the irreversible stuff: the DDL migrations, the production deployments, the data deletions.
Those were slow before AI agents too. You'd check the command three times before running it. You'd ask a colleague to review the migration. You'd create a change request ticket.
The expacti model is just that same careful human judgment, but made explicit, logged, and integrated into the tool the AI agent is already using. The vibe stays. The blast radius shrinks.
Let the AI code. You keep the gate.
Add expacti to your vibe coding setup in under 10 minutes. Command-level approval, risk scoring, audit trail — without slowing down the loop for things that don't need review.