Use when the current prepared tmux pane is already inside an interactive mysql-compatible client REPL (`mysql>`, `mariadb>`, `MySQL [db]>`, `MariaDB [db]>`, or a configured mysql prompt), including MySQL, MariaDB, TiDB, Percona Server for MySQL, StarRocks, OceanBase MySQL mode, ShardingSphere-Proxy, or similar backends operated through the mysql client. Safely send read-only SQL and explicitly user-approved insert/update/delete SQL without using Linux shell wrappers, inspect prompt state, cancel broken multiline input, and exit the client REPL.
Resources
7Install
npx skillscat add lenovobenben/tmux-mysql Install via the SkillsCat registry.
tmux MySQL
Use this skill only when the user's prepared tmux pane is already inside the interactive mysql client REPL. The backend can be MySQL, MariaDB, TiDB, Percona Server for MySQL, StarRocks, OceanBase in MySQL mode, ShardingSphere-Proxy through its MySQL protocol entry, or another mysql-compatible database as long as the interactive client behaves like the standard mysql client. This skill builds on the tmux transport model from tmux-remote-linux, but it does not use Linux-shell run.sh or shell marker wrapping while the pane is inside a recognized mysql prompt.
Scope
Good fits for the current implementation:
- Check whether the pane appears to be at a recognized mysql-client ready prompt such as
mysql>,mariadb>,MySQL [db]>,MariaDB [db]>, official custom prompt example(user@host) [database]>, or a continuation prompt. - Run one conservative read-only SQL statement.
- Run one user-approved
insert,update, ordeletestatement. - Cancel accidental multiline input with
\c. - Exit the MySQL REPL with
exit.
Not supported:
- Starting
mysqlfrom a Linux shell. - Logging into remote hosts.
- Multi-step database automation.
- Multi-statement SQL.
- DDL, grants, kills, imports, flushes, transactions, or maintenance operations.
- Dumping large or sensitive query results.
Required Environment
The user must have a tmux pane prepared. Set:
export REMOTE_TMUX_ENV=non-production
# or
export REMOTE_TMUX_ENV=productionProduction and non-production modes are both supported. mysql_send_sql.sh remains read-only. mysql_write_sql.sh still requires a fresh one-digit approval for every insert, update, or delete in both production and non-production.
The scripts default to tmux target remote:0.0. Override it when needed:
export REMOTE_TMUX_TARGET=remote:0.0Prompt detection recognizes conservative mysql-client defaults and official examples. These prompts are controlled by the client, not by the database server. That means compatible backends such as TiDB, StarRocks, OceanBase MySQL mode, and ShardingSphere-Proxy can be supported when accessed through a standard mysql-compatible client prompt. Prompts are user-configurable through MYSQL_PS1, --prompt, option files, or the interactive prompt command, so they cannot be exhaustively enumerated without risking false positives. For a known custom prompt, set:
export TMUX_MYSQL_READY_PROMPT_REGEX='<extended-awk-regex>'Preferred Commands
Check state first:
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_status.sh --jsonRun one read-only SQL statement:
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_send_sql.sh 'select 1;'
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_send_sql.sh 'show databases;'
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_send_sql.sh 'show tables;'
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_send_sql.sh 'select id, name from users limit 20;'Run one write SQL statement only after explicit user approval:
REMOTE_TMUX_ENV=non-production \
TMUX_MYSQL_WRITE_APPROVAL_EXPECTED_DIGIT=<digit-shown-to-user> \
TMUX_MYSQL_WRITE_APPROVAL_DIGIT=<digit-replied-by-user> \
TMUX_MYSQL_WRITE_EXPLANATION='<Chinese explanation shown to the user>' \
~/.codex/skills/tmux-mysql/scripts/mysql_write_sql.sh "update users set name = 'new' where id = 1;"Cancel a broken continuation prompt:
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_cancel.shExit MySQL and return to the surrounding shell:
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_exit.shQuery local JSONL audit logs:
~/.codex/skills/tmux-mysql/scripts/mysql_logs.sh last 10
~/.codex/skills/tmux-mysql/scripts/mysql_logs.sh failures
~/.codex/skills/tmux-mysql/scripts/mysql_logs.sh show <request_id>
~/.codex/skills/tmux-mysql/scripts/mysql_logs.sh output <request_id>mysql_logs.sh requires local jq.
Rules
- Do not use
tmux-remote-linux/run.shortmux-remote-linux/send.shinside a recognized mysql-compatible client prompt. - Never send SQL directly to a mysql-compatible client prompt with
tmux send-keys,tmux paste-buffer, raw pane input, or another wrapper. All SQL must go throughmysql_send_sql.shormysql_write_sql.shso guardrails, approval checks, response parsing, and audit logs cannot be bypassed. - Use this skill only after the pane is already inside the mysql-compatible client. Use
tmux-remote-linuxbefore starting the client and after exiting it. - Always run
mysql_status.sh --jsonwhen the pane state is uncertain. - If status is
continuation, do not send SQL. Usemysql_cancel.sh, then runmysql_status.sh --jsonagain before sending any SQL. - Never send concurrent commands or input to the same tmux target. A tmux pane is a serial interactive channel.
- Never send multiple SQL statements concurrently to the same tmux MySQL target. The MySQL REPL is serial; wait for one script call to finish before starting the next.
- Default SQL must be read-only and bounded. Read-only SQL may end with
;,\G, or\g; write SQL must end with;. - Avoid
select *. Name columns explicitly. - Add
limitto every result-producingselect/withquery that reads from tables. The helper refuses unbounded table reads by default; aggregate-only queries such asselect count(1) from t;and no-table queries such asselect database();are exempt. - Avoid querying or printing sensitive fields such as
password,token,secret,credential,private_key,access_key, orsecret_key. - Use single quotes for MySQL string literals. Do not generate double-quoted strings;
ANSI_QUOTEScan make double quotes mean identifiers. - Use backticks only when an identifier must be quoted. Do not confuse backticks with strings.
- Escape a single quote inside a string with doubled single quotes, for example
'it''s'; do not rely on backslash escapes. - Do not generate comments in user SQL. MySQL version comments such as
/*! ... */can execute code and are refused. - Treat SQL keywords, semicolons, and quote characters inside string literals as data, not SQL structure.
- The helper rejects obvious writes and sensitive-field queries by default.
select,with,insert,update, anddeletego through the bundled pure-Python SQLGlot parser before being sent to the MySQL client.show/desc/describe/explain/useare still handled by conservative scanner rules because MySQL-compatible backends differ here.insert,update, anddeletemust usemysql_write_sql.sh; they require explicit user approval in both production and non-production.updateanddeletemust have awhereclause.where 1=1is refused.insert ... selectis refused in this first write version.- Report the query result summary to the user; do not dump large result sets unless requested.
- Prefer
--jsonwhen the task needs robust handling of success, MySQL errors, timeouts, or unknown output. - The scripts internally wrap each accepted single user SQL with short
select ... as tmux_mysql_boundarybegin/end markers. Agents must not generate wrapper SQL themselves. This avoids relying on long echoed input lines, which the mysql client may horizontally scroll while tmux can capture only the visible terminal cells. mysql_send_sql.shandmysql_write_sql.shwrite local JSONL audit logs by default under~/.codex/tmux-mysql/logs. Logs include SQL text, target, timing, exit code, structured result summary, and truncated output.
Response Handling
Both mysql_send_sql.sh and mysql_write_sql.sh support --json.
REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_send_sql.sh --json 'select id, name from users limit 20;'JSON responses include:
status:success,error,timeout, orunknown.category:success,syntax_error,schema_or_data_error,lock_error,mysql_error,timeout, orunknown.error_code,sql_state, andmessagefor MySQLERRORoutput.rows_in_setfor result sets.affected_rows,rows_matched,rows_changed,warnings,has_warnings, andwrite_effectfor DML.
For DML success, report the effect precisely. Do not say only "executed successfully":
write_effect=changed: data changed.write_effect=matched_but_unchanged: rows matched thewhereclause, but values were already the requested values.write_effect=no_match: no row matched or no row was inserted/deleted.write_effect=unknown: the output was successful but effect details were not available.
If has_warnings=true, explicitly report it and consider running show warnings; before treating the operation as complete.
Timeout defaults to TMUX_MYSQL_WAIT_SECONDS=120. Override it per call when a query is expected to be especially quick or slow.
Exit codes:
0: classified success.2: timeout waiting for a recognized mysql-compatible prompt after sending SQL.3: MySQL returned an error or the output could not be classified as success.
On timeout, do not assume the SQL stopped. The query may still finish later in the MySQL REPL. Read the pane or check status before sending another SQL.
Audit Logs
Useful environment variables:
TMUX_MYSQL_LOG_ENABLED=1
TMUX_MYSQL_LOG_DIR="$HOME/.codex/tmux-mysql/logs"
TMUX_MYSQL_LOG_MAX_OUTPUT_LINES=10
TMUX_MYSQL_LOG_RETENTION_DAYS=7
TMUX_MYSQL_REQUEST_ID=<optional-stable-id>Disable audit logs only for deliberate local testing:
TMUX_MYSQL_LOG_ENABLED=0MySQL Write Approval Policy
Every insert, update, and delete requires a fresh one-digit user approval, regardless of REMOTE_TMUX_ENV.
Before every mysql_write_sql.sh call, generate a fresh random digit from 0 to 9. Show the user the target, exact SQL, and a concise Chinese explanation of what the SQL will do. Keep the approval prompt compact, using this exact no-blank-line format:
**MySQL写操作确认**
**目标**:`remote:0.0`
**说明**:`<one concise Chinese sentence>`
**SQL**:`<insert/update/delete SQL>`
**同意执行请只回复数字**:`<digit>`If the SQL is too long for one line, keep the SQL in one fenced sql code block and put the approval sentence immediately after the code block without extra blank lines.
Ask the user to reply with only that digit if they approve this exact SQL. If the reply is not exactly the digit, do not execute the SQL. Start over with a new digit if the write is still needed.
After a matching reply, pass the one-time approval through:
TMUX_MYSQL_WRITE_APPROVAL_EXPECTED_DIGIT=<digit-shown-to-user>
TMUX_MYSQL_WRITE_APPROVAL_DIGIT=<digit-replied-by-user>
TMUX_MYSQL_WRITE_EXPLANATION='<Chinese explanation shown to the user>'The approval is per SQL statement. Do not reuse a digit. Do not batch multiple SQL statements under one approval.
Anti-bypass rule: You MUST NOT set TMUX_MYSQL_WRITE_APPROVAL_EXPECTED_DIGIT, TMUX_MYSQL_WRITE_APPROVAL_DIGIT, or TMUX_MYSQL_WRITE_EXPLANATION yourself unless the user has explicitly replied with the approval digit in the current conversation. These variables are a relay of the user's informed consent, not a way to skip approval.
Handoff
- If the pane is at a Linux shell, use
tmux-remote-linux. - If the pane is at a recognized mysql-compatible client prompt, use this skill.
- If the pane is in another REPL such as Redis, psql, Spark shell, Python, or Oasis, do not use this skill.