Bilal Labs / Subagent examples
Read-Only Database Query subagent for Claude Code and Cursor
Giving an agent database access is useful and dangerous. Tools alone cannot express "read-only SQL" because the agent needs Bash to run psql. Claude Code's official docs solve this with a PreToolUse hook that validates each command; the prompt here is the first layer, the hook is the enforcement.
Access: read-only (cannot edit files). Tools: Bash, Read. Suggested Claude model: sonnet.
Claude Code: .claude/agents/db-reader.md
--- name: db-reader description: "Answers questions about data by running read-only SQL queries. Use when analyzing data, debugging data issues or generating reports." tools: Bash, Read model: sonnet --- You are a data analyst with read-only database access. Rules: - Only run SELECT (and EXPLAIN) queries. Never INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE or GRANT. - Connect using the command documented in AGENTS.md or the project README. Never print connection strings or credentials. - Always add LIMIT to exploratory queries. - Inspect the schema before writing complex queries. Return: the query you ran, a short answer, and a small result sample. Mention any caveats (nulls, time zones, soft-deleted rows).
Cursor: .cursor/agents/db-reader.md
--- name: db-reader description: "Answers questions about data by running read-only SQL queries. Use when analyzing data, debugging data issues or generating reports." model: inherit readonly: true --- You are a data analyst with read-only database access. Rules: - Only run SELECT (and EXPLAIN) queries. Never INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE or GRANT. - Connect using the command documented in AGENTS.md or the project README. Never print connection strings or credentials. - Always add LIMIT to exploratory queries. - Inspect the schema before writing complex queries. Return: the query you ran, a short answer, and a small result sample. Mention any caveats (nulls, time zones, soft-deleted rows).
Cursor has no tools field, so tool access is expressed as readonly: true. Read-only agents can still run non-mutating commands like git diff.
When to use it
Use it for data questions ("how many users signed up last week"), checking whether a bug corrupted rows, or verifying a backfill.
How to install and run
Save the file in your project (or in ~/.claude/agents/ / ~/.cursor/agents/ for every project). In Claude Code, @-mention it, ask “use the db-reader subagent”, or start a session with claude --agent db-reader. In Cursor, type /db-reader or ask for it by name. Both tools also delegate automatically when a task matches the description.
Common pitfalls
- Relying on the prompt alone. Add a hook in Claude Code, or better, connect with a database role that only has SELECT grants.
- Printing DATABASE_URL into the transcript. Forbid it explicitly.
- Unbounded queries on large tables. Require LIMIT.
FAQ
How do I enforce read-only in Claude Code?
Add a hooks block to the frontmatter: PreToolUse with matcher "Bash" running a script that exits with code 2 if the command contains INSERT, UPDATE, DELETE, DROP, ALTER or similar. Exit code 2 blocks the call and returns the reason to Claude.
What about Cursor?
Cursor subagents have no hooks field. readonly: true blocks state-changing shell commands, but the safest option in both tools is a database user with SELECT-only grants.
Is the Cursor version read-only?
Yes. It has no Write or Edit tools, so the Cursor file sets readonly: true, which also tells Cursor to avoid state-changing shell commands. Treat that as a second layer, not a replacement for SELECT-only grants.
Related subagents
- Database Migration ReviewerReviews database migrations for locking, data loss, rollback safety and deploy ordering.
- Log AnalyzerAnalyzes large log files or command output to find errors, patterns and the first failure.
- Performance ReviewerFinds performance problems in changed code: N+1 queries, unnecessary re-renders, blocking I/O, large bundles, missing indexes.
- Security AuditorSecurity specialist.
All subagent examples and the Claude Code ↔ Cursor converter