MySQL connection manager with SSH tunnel support.
- Interactive connection setup with encrypted password storage (AES-256-GCM + Argon2id)
- SSH tunnel management (ad-hoc and background persistent tunnels)
- Automatic output masking for AI/non-TTY execution (protects personal data in production)
- Multiple connections across different terminals without conflicts
- mycli preferred, falls back to standard mysql client
- Native Go driver with MySQL 4.x old_password authentication support
- Output format conversion (plain, markdown, CSV, JSON, PDF) with file export
- MySQL 4.x+ compatible (native driver) / MySQL 5.1+ compatible (CLI driver)
brew tap atani/tap
brew install myshOr with Go:
go install github.com/atani/mysh@latest# Add a connection interactively
mysh add
# Test connection (name optional if only one connection)
mysh ping
# Connect
mysh connectmysh <command> [arguments]
# Add a new connection (interactive)
mysh add
# List all connections
mysh list
# Edit an existing connection
mysh edit production
# Remove a connection
mysh remove productionConnection name can be omitted when only one connection exists.
# Test connection
mysh ping production
# Open an interactive MySQL session
mysh connect production
# Execute a SQL file
mysh run production query.sql
# Execute inline SQL
mysh run production -e "SELECT COUNT(*) FROM users"
# Show tables
mysh tables productionBy default, connect and run open an ad-hoc SSH tunnel that closes when the command finishes.
For repeated access, start a persistent background tunnel:
# Start a background tunnel
mysh tunnel production
# List active tunnels
mysh tunnel
# connect/run will automatically reuse the background tunnel
mysh run production -e "SHOW PROCESSLIST"
# Stop a tunnel
mysh tunnel stop productionMultiple tunnels can run simultaneously for different connections.
mysh can automatically mask sensitive columns (email, phone, etc.) in query output. This is designed to prevent personal data from leaking into AI tool contexts.
Masking is controlled by two factors:
- Connection environment (
envin config) - TTY detection (is output going to a terminal or being captured?)
| env | Terminal (human) | Piped/captured (AI) |
|---|---|---|
| production | Auto-masked | Auto-masked |
| staging | Raw | Auto-masked |
| development | Raw | Raw |
connections:
- name: production
env: production
mask:
columns: ["email", "phone", "password_hash"]
patterns: ["*address*", "*secret*"]
ssh: ...
db: ...# Force masking (even in terminal)
mysh run production --mask -e "SELECT * FROM users LIMIT 5"
# Force raw output (requires interactive confirmation for production)
mysh run production --raw -e "SELECT * FROM users LIMIT 5"For production connections, --raw requires interactive confirmation at the terminal. Non-TTY processes (AI tools, scripts) cannot bypass masking.
| Type | Original | Masked |
|---|---|---|
| alice@example.com | a***@example.com | |
| Phone | 090-1234-5678 | 0*** |
| Name | Alice | A*** |
| Short value | ab | *** |
| NULL | NULL | NULL |
Extract specific records from a database as INSERT statements. Useful for creating reproducible test data or migrating individual records.
# Extract records matching a condition
mysh slice production products --where "category='electronics'"
# Save to file
mysh slice production products --where "id IN (7,8)" -o subset.sql
# Disable masking (requires interactive confirmation)
mysh slice production customers --where "id=3" --rawOutput example:
-- mysh slice: products WHERE category='electronics'
-- Generated at: 2026-03-15T12:00:00+09:00
INSERT INTO `products` (`id`, `name`, `price`) VALUES (7, 'Widget Pro', 2980);
INSERT INTO `products` (`id`, `name`, `price`) VALUES (8, 'Gadget Mini', NULL);Masking rules from the connection config are always applied by default, regardless of environment. Use --raw to disable (requires interactive confirmation).
Export query results as markdown, CSV, JSON, or PDF.
# Markdown table
mysh run production -e "SELECT * FROM users LIMIT 5" --format markdown
# CSV file
mysh run production -e "SELECT * FROM users" --format csv -o users.csv
# JSON output
mysh run production -e "SELECT * FROM users LIMIT 5" --format json
# JSON file
mysh run production -e "SELECT * FROM users" --format json -o users.json
# PDF report
mysh run production -e "SELECT * FROM users" --format pdf -o report.pdf
# tables command also supports format/output
mysh tables production --format csv -o tables.csvSupported formats: plain (default), markdown (md), csv, json, pdf
Save .sql files in ~/.config/mysh/queries/ and list them with:
mysh queriesConnections are stored in ~/.config/mysh/connections.yaml.
connections:
- name: production
env: production
ssh:
host: bastion.example.com
port: 22
user: deploy
key: ~/.ssh/id_ed25519
mask:
columns: [email, phone]
patterns: ["*address*"]
db:
host: 127.0.0.1
port: 3306
user: app
database: myapp_production
password: <encrypted>
- name: legacy-db
env: production
db:
host: 10.0.0.5
port: 3306
user: app
database: legacy_production
password: <encrypted>
driver: native # MySQL 4.x old_password support
- name: local
env: development
db:
host: localhost
port: 3306
user: root
database: myapp_devThe driver field selects how mysh connects to MySQL.
| driver | Description | Supported versions |
|---|---|---|
cli (default) |
Delegates to mysql/mycli CLI | MySQL 5.1+ |
native |
Direct connection via Go's database/sql | MySQL 4.x+ |
The native driver uses go-sql-driver/mysql with allowOldPasswords=true to support MySQL 4.x old_password (mysql323) authentication. The connect command provides a simple REPL instead of mycli/mysql.
- Database passwords are encrypted with AES-256-GCM
- Key derivation uses Argon2id (memory-hard, resistant to GPU attacks)
- Master password is stored in macOS Keychain (falls back to prompt on other platforms)
- Config files are created with
0600permissions - Production query output is always masked when mask rules are configured
--rawon production requires interactive TTY confirmation (AI tools cannot bypass)
- old_password is cryptographically weak: MySQL 4.x old_password (mysql323 hash) is a 16-byte XOR-based hash that does not meet modern security standards. Use the native driver only for legacy system connectivity.
- Native driver
connectlimitations: Unlike mycli/mysql CLI, the built-in REPL has no tab completion, syntax highlighting, or pager. For complex interactive work, preferrun -e. - go-sql-driver/mysql
allowOldPasswords: This depends on the driver's support, which may be removed in future driver updates.
golang.org/x/crypto- Argon2id key derivationgolang.org/x/term- Secure password input and TTY detectiongopkg.in/yaml.v3- Configuration file parsinggithub.com/go-sql-driver/mysql- Native MySQL driver (old_password support)github.com/go-pdf/fpdf- PDF output
