lenovobenben

tmux-mysql

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.

lenovobenben 1 Updated 1mo ago

Resources

7
GitHub

Install

npx skillscat add lenovobenben/tmux-mysql

Install via the SkillsCat registry.

SKILL.md

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, or delete statement.
  • Cancel accidental multiline input with \c.
  • Exit the MySQL REPL with exit.

Not supported:

  • Starting mysql from 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=production

Production 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.0

Prompt 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 --json

Run 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.sh

Exit MySQL and return to the surrounding shell:

REMOTE_TMUX_ENV=non-production ~/.codex/skills/tmux-mysql/scripts/mysql_exit.sh

Query 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.sh or tmux-remote-linux/send.sh inside 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 through mysql_send_sql.sh or mysql_write_sql.sh so 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-linux before starting the client and after exiting it.
  • Always run mysql_status.sh --json when the pane state is uncertain.
  • If status is continuation, do not send SQL. Use mysql_cancel.sh, then run mysql_status.sh --json again 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 limit to every result-producing select / with query that reads from tables. The helper refuses unbounded table reads by default; aggregate-only queries such as select count(1) from t; and no-table queries such as select database(); are exempt.
  • Avoid querying or printing sensitive fields such as password, token, secret, credential, private_key, access_key, or secret_key.
  • Use single quotes for MySQL string literals. Do not generate double-quoted strings; ANSI_QUOTES can 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, and delete go through the bundled pure-Python SQLGlot parser before being sent to the MySQL client. show / desc / describe / explain / use are still handled by conservative scanner rules because MySQL-compatible backends differ here.
  • insert, update, and delete must use mysql_write_sql.sh; they require explicit user approval in both production and non-production.
  • update and delete must have a where clause. where 1=1 is refused.
  • insert ... select is refused in this first write version.
  • Report the query result summary to the user; do not dump large result sets unless requested.
  • Prefer --json when 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_boundary begin/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.sh and mysql_write_sql.sh write 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, or unknown.
  • category: success, syntax_error, schema_or_data_error, lock_error, mysql_error, timeout, or unknown.
  • error_code, sql_state, and message for MySQL ERROR output.
  • rows_in_set for result sets.
  • affected_rows, rows_matched, rows_changed, warnings, has_warnings, and write_effect for 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 the where clause, 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=0

MySQL 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.