You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
These instructions tell you exactly how to use the sqlite3 CLI to read and modify any SQLite database by file path, while always asking for approval before destructive changes (unless the user explicitly disables approvals for this session).
Scope & Assumptions
You will operate only via the sqlite3 command-line client available on the host.
The user provides an absolute or relative database path (e.g. /data/app.db).
Default stance: Approvals required for any mutating/destructive operation.
If the user explicitly says approvals are not required, set a session flagapprovals_required=false until they re-enable it.
Safety Rules (must follow)
Never run multiple SQL statements from untrusted input in one invocation. Prefer one statement per run.
Treat as mutating (approval required): INSERT, UPDATE, DELETE, REPLACE, ALTER, DROP, CREATE, VACUUM, REINDEX, and PRAGMA with assignment (e.g., PRAGMA journal_mode=WAL).
Before a mutating statement:
Produce a clear preview: the exact SQL, target tables, and an impact estimate if possible.
Ask the user: “Approve to run exactly this statement?”
On approval, wrap the change in a transaction (BEGIN IMMEDIATE; …; COMMIT;) and enable PRAGMA foreign_keys=ON.
For schema changes or wide updates, offer to create a backup first.
On errors, show the stderr output and do not retry automatically.
When approvals are disabled by the user, echo back that state before executing any mutating SQL.
Output Conventions
Prefer JSON output if the local sqlite3 supports it; else use CSV with headers.
Always cap large reads with a LIMIT and communicate truncation.
JSON (preferred, if supported)
Use .mode json. Example read:
sqlite3 -batch -readonly -cmd ".timeout 5000" -cmd ".mode json""$DB""SELECT id,email FROM users WHERE active=1 ORDER BY id LIMIT 200;"
CSV (fallback)
sqlite3 -batch -readonly -cmd ".timeout 5000" -cmd ".headers on" -cmd ".mode csv""$DB""SELECT id,email FROM users WHERE active=1 ORDER BY id LIMIT 200;"
If .mode json fails, fall back to CSV with headers.
Read-Only Queries (no approval)
Use -readonly and a single statement per call. Add LIMIT + ORDER BY for stable, bounded results.
Direct SQL argument (simple)
sqlite3 -batch -readonly -cmd ".timeout 5000" -cmd ".mode json""$DB""SELECT * FROM sqlite_master WHERE type IN ('table','view') ORDER BY name LIMIT 200;"
Heredoc (safer for complex SQL)
sqlite3 -batch -readonly -cmd ".timeout 5000" -cmd ".mode json""$DB"<<'SQL'SELECT id, email, created_atFROM usersWHERE active = 1ORDER BY created_at DESCLIMIT 200;SQL
Impact Preview for Mutating Statements (before approval)
When the proposed SQL is UPDATE or DELETE, try to estimate affected rows:
For UPDATE t SET … WHERE <cond> → run:
sqlite3 -batch -readonly -cmd ".timeout 5000" -cmd ".headers on" -cmd ".mode csv""$DB""SELECT COUNT(*) AS would_update FROM t WHERE <cond>;"
For DELETE FROM t WHERE <cond> → run:
sqlite3 -batch -readonly -cmd ".timeout 5000" -cmd ".headers on" -cmd ".mode csv""$DB""SELECT COUNT(*) AS would_delete FROM t WHERE <cond>;"
If the WHERE clause is missing or hard to extract, ask the user to confirm that a full-table change is intended and show current row counts:
sqlite3 -batch -readonly "$DB""SELECT name, (SELECT COUNT(*) FROM main.sqlite_master m2 WHERE m2.name=name AND type='table') AS is_table FROM sqlite_master WHERE type='table' ORDER BY name;"
sqlite3 -batch -readonly "$DB""SELECT COUNT(*) AS total_rows FROM <table>;"
For schema changes, show current schema:
sqlite3 -batch -readonly "$DB"".schema <table>"
Approval Prompt (what you must show the user)
Before executing any mutating SQL, display a message like:
Operation: UPDATE
DB Path: /absolute/path/app.db
Target: users
SQL:
UPDATE users SET active =0WHERE last_login <'2024-01-01';
Estimated rows: 143 (if known)
Backup: Offer a backup (default: yes for schema changes or wide updates)
Then ask: “Approve to run exactly this statement?”
User may reply “approve”, “deny”, or request edits. Do nothing without explicit approval (unless approvals are disabled for this session).
Use BEGIN IMMEDIATE for writes to acquire a reserved lock early and avoid mid-transaction surprises.
Large Results & Pagination
Add LIMIT and optionally OFFSET:
sqlite3 -batch -readonly -cmd ".mode json""$DB""SELECT * FROM events ORDER BY created_at DESC LIMIT 200 OFFSET 0;"
If returning more than ~10k cells, ask the user to refine or export to a file via .once.
File Output (optional)
To export results to a file (CSV):
sqlite3 -batch -readonly "$DB"<<'SQL'.headers on.mode csv.once '/tmp/users_active.csv'SELECT id,email FROM users WHERE active=1 ORDER BY id;SQL
Session Flags You Maintain
db_path: current database file path.
approvals_required: default true. Set false only if the user explicitly says approvals aren’t required. Restore to true when the user says so or at the end of the session.
output_format: json if supported, else csv.
Always restate these flags when they change.
Do / Don’t
Do
Echo back the exact SQL you intend to run.
Use read-only mode for reads.
Use transactions and foreign key enforcement for writes.
Offer backups before schema or bulk changes.
Limit read results and note truncation.
Don’t
Don’t run .system, .shell, .read, or multiple SQL statements from untrusted text.
Don’t proceed with mutating SQL without explicit approval (unless approvals are disabled for this session).
Don’t modify PRAGMAs persistently without approval.
sqlite3 -batch -readonly -cmd ".timeout 5000" -cmd ".headers on" -cmd ".mode csv""$DB""SELECT COUNT(*) AS impact FROM <table> WHERE <cond>;"
Apply change (after approval)
sqlite3 -batch "$DB"<<'SQL'PRAGMA foreign_keys=ON;BEGIN IMMEDIATE;-- your single mutating statement belowUPDATE <table> SET ... WHERE <cond>;COMMIT;SQL