Tool choice · Agent database operations

When should vibe coding
use dbcli?

At 4pm, the agent says it only needs to connect to the local database, inspect a column, and finish the screen. It often does. The question usually arrives later: which fixture did it change, and why does CI no longer match the laptop?

A developer at a local workstation reviews code and a database while a second screen shows a passing test.
Local development should be fast. Keeping the important operations visible is what keeps tomorrow fast, too.
This is a common local scene. The Docker database holds a small dataset that reproduces a payment-page bug: order #42 received a refund event, but the UI is still stuck on “processing.” The agent looks at orders, then proposes marking a few rows paid. You only wanted the screen to work, but e2e, a teammate, and tomorrow morning’s CI all use the same fixture.

If the database will genuinely live for five minutes in front of you, opening a client and letting the agent help with a line or two of SQL is perfectly reasonable. Once “confirm the bug” becomes “change data that everyone relies on,” however, the job has changed. You need more than a connection: the next person needs to understand it, and the next machine needs to reproduce it.

4:00pm

The screen is stuck

The browser shows an old status. The agent needs the real shape of the data, not a guessed column name.

4:06pm

One fix is about to touch a fixture

This is no longer a read. The wrong predicate can make the next test begin with already-contaminated data.

9:12am, tomorrow

CI cannot reproduce the result

The chat does not contain the whole predicate, and someone has to reconstruct what happened yesterday.

Which tool fits this moment?

Direct database client

Best for: throwaway experiments, synthetic data, and a trusted developer who will inspect every statement.

MCP database server

Best for: low-risk, interactive tool exploration in an agent host whose authorization and logging model already meets the need.

dbcli

Best for: realistic data, shared fixtures, migrations, CI, incident runbooks, or any result another person must rerun.

A direct client is fine when the database will be discarded and you are watching every statement. The fixture in this example has crossed that line.

At first

You only want to see the screen work
A direct client gets the agent an answer quickly.

Five minutes later

You are changing a shared fixture
Use dbcli and leave a command the next person can run.

Letting an agent operate a client

What is fast is this one moment

The agent can browse, compose SQL, and send writes from a GUI, driver, or shell. Its context lives in this conversation and this session; when you are beside it, that can be very efficient.

But when it says “I also fixed three rows,” the meaningful facts are spread across chat, tool output, and browsing history: which columns it inspected, what the WHERE predicate was, and whether anyone reviewed the write before it ran.

Using dbcli

What remains is a path for the next time

Schema, protection rules, a previewed write, the actual execution, and recovery after a failure use one CLI surface. The agent can still move quickly, but what it gives you is more than “done”: it is a command sequence that belongs in a PR, test script, or runbook.

This is not about turning every local experiment into a ceremony. It is about taking shared data, repeatable operations, and handoffs out of a one-off conversation.

Walk through that afternoon

These three steps do not make the agent do less. They put the judgement that was hidden inside a client session somewhere anyone can inspect. The first pass may take a few more seconds; the next morning can save half an hour of guessing.

4:02pm: the agent cannot find the field

It may have imagined paid_at when the table uses payment_at. First see what it must not read, then give it the columns that really exist. It is a mundane step, but it prevents a plausible-looking fix from being built on the wrong assumption.

dbcli blacklist list
dbcli schema orders --format json

4:06pm: it wants to change the fixture

Print the UPDATE first. In a few seconds, you can see whether the predicate selects only #42, and whether it touches a refund amount or test account. This is a good moment for a human to intervene: the SQL has not run, but the risk is finally concrete.

dbcli update orders --where "id=42" --set '{"status":"paid"}' --dry-run

4:08pm: write only after review, and leave a recovery trail

Put the reviewed command in the test script or PR description instead of reconstructing it from memory. When a supported command fails, --recovery leaves a machine-readable next step tied to its audit record. It is not magic rollback; it lets an investigation start from concrete evidence.

dbcli query "SELECT status FROM orders WHERE id=42" --format json --recovery

Where does MCP fit in this story?

MCP is not inherently unsafe, and it does not have to compete with dbcli. If an agent host has already put least-privilege access, data masking, approval, and useful audit logs around a particular database server, MCP can be excellent for interactive discovery: “show me the tables” or “let me inspect a small sample.”

The difference is where responsibility sits. MCP’s boundary and record depend on how that host, server, and tool are implemented; a direct client’s boundary is commonly the connection and the operator’s habits.

dbcli focuses on a command contract that the project can agree on, inspect, and run again in CI. Once exploration becomes a write, a shared fixture, or a handoff, that contract is usually more valuable than the fact that the agent is already connected.