{"id":48282971,"url":"https://github.com/atani/mysh","last_synced_at":"2026-06-03T03:03:54.981Z","repository":{"id":343980364,"uuid":"1179954668","full_name":"atani/mysh","owner":"atani","description":"MySQL connection manager with SSH tunnel support. Auto-masks sensitive data for AI/non-TTY environments. Supports MySQL 4.x+.","archived":false,"fork":false,"pushed_at":"2026-03-31T01:17:38.000Z","size":5415,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-31T04:28:28.967Z","etag":null,"topics":["ai-safety","cli","connection-manager","data-masking","database","golang","mysql","mysql-client","security","ssh-tunnel"],"latest_commit_sha":null,"homepage":"https://dev.to/atani/built-mysh-a-mysql-connection-manager-that-auto-masks-query-output-emails-phones-etc-befor-2jid","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atani.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-12T14:52:11.000Z","updated_at":"2026-03-31T01:17:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/atani/mysh","commit_stats":null,"previous_names":["atani/mysh"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/atani/mysh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atani%2Fmysh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atani%2Fmysh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atani%2Fmysh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atani%2Fmysh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atani","download_url":"https://codeload.github.com/atani/mysh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atani%2Fmysh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31418270,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T20:09:54.854Z","status":"ssl_error","status_checked_at":"2026-04-04T20:09:44.350Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-safety","cli","connection-manager","data-masking","database","golang","mysql","mysql-client","security","ssh-tunnel"],"created_at":"2026-04-04T22:52:32.972Z","updated_at":"2026-06-03T03:03:54.973Z","avatar_url":"https://github.com/atani.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" alt=\"mysh logo\" width=\"180\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003emysh\u003c/h1\u003e\n\n[![CI](https://github.com/atani/mysh/actions/workflows/ci.yml/badge.svg)](https://github.com/atani/mysh/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/atani/mysh/branch/main/graph/badge.svg)](https://codecov.io/gh/atani/mysh)\n[![Go Report Card](https://goreportcard.com/badge/github.com/atani/mysh)](https://goreportcard.com/report/github.com/atani/mysh)\n[![Go Reference](https://pkg.go.dev/badge/github.com/atani/mysh.svg)](https://pkg.go.dev/github.com/atani/mysh)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n**A safer MySQL CLI for the AI coding era.**\n\nmysh manages MySQL connections, SSH tunnels, and query output so teams can use production-like databases from Claude Code, Cursor, shell scripts, and other AI-assisted workflows without accidentally leaking sensitive data.\n\n*Pronounced \"my-sh\" (/maɪʃ/), like \"my shell\".*\n\n![demo](demo.gif)\n\n\u003e **New to mysh?** See the [Getting Started guide for non-engineers](docs/getting-started.md) — set up in 5 minutes and start querying with Claude Code.\n\n## Why mysh?\n\nTraditional MySQL clients are great for humans, but risky in AI-assisted workflows: query results can be copied into prompts, captured by scripts, or returned to agents without a final privacy check.\n\nmysh is built for that gap:\n\n- **AI-safe by default**: automatically masks configured sensitive fields in production and non-TTY contexts\n- **One command for secure access**: handles MySQL connection profiles and SSH tunnels together\n- **Team-friendly onboarding**: export shared connection configs without passwords, then let each teammate enter their own credentials\n- **Works with existing tools**: import connections from DBeaver, Sequel Ace, and MySQL Workbench\n- **Cross-platform**: install via Homebrew, winget/MSI, standalone binaries, or `go install`\n\n## AI-safe output masking\n\nWhen mysh detects production data or output captured by an AI agent/script, it masks sensitive values before they leave the CLI.\n\n```bash\nmysh run production -e \"SELECT id, name, email, phone FROM users LIMIT 2\" --format markdown\n```\n\nExample masked output:\n\n| id | name | email | phone |\n|----|------|-------|-------|\n| 1 | A*** | a***@example.com | 0*** |\n| 2 | B*** | b***@example.com | 0*** |\n\nProduction `--raw` output requires an interactive TTY confirmation, so AI tools and non-interactive scripts cannot silently bypass masking.\n\nSee [Using mysh safely with AI coding agents](docs/ai-agent-safety.md) for recommended configuration and team workflow guidance.\n\n## MCP server (native AI-agent integration)\n\nmysh ships a built-in [Model Context Protocol](https://modelcontextprotocol.io) server, so AI coding agents can query your databases as a first-class tool instead of shelling out to the CLI. The same masking rules apply, and **raw output cannot be requested over MCP** — sensitive values are masked before they ever reach the agent.\n\n**1. Configure a connection first.** The MCP server reads the same connections you set up for the CLI (`~/.config/mysh/connections.yaml`); it does not define its own. Set one up with `mysh add`, `mysh import`, or the Redash flags, and verify with `mysh list` / `mysh ping`. There are no `add`/`edit`/`remove` tools over MCP by design.\n\n**2. Register the server with Claude Code:**\n\n```bash\nclaude mcp add mysh -- mysh mcp\n```\n\nOr add it to any MCP client config (e.g. Cursor, `claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"mysh\": { \"command\": \"mysh\", \"args\": [\"mcp\"] }\n  }\n}\n```\n\n**3. Make the master password available.** Connections with encrypted credentials need the master password to decrypt them. Since the MCP transport is non-interactive, the server never prompts: run any `mysh` command interactively once (it is saved to the macOS Keychain / Windows Credential Manager), or set `MYSH_MASTER_PASSWORD` in the server's environment. If it is missing, `mysh_query`/`mysh_ping` return a clear error instead of hanging.\n\nExposed tools: `mysh_list_connections`, `mysh_query`, `mysh_tables`, `mysh_ping`. No hosting, API key, or extra service is required — the server runs locally over stdio. See the [MCP Server Guide](docs/mcp-guide.md) for details.\n\n## Common use cases\n\n- Query production-like MySQL databases from Claude Code or Cursor without returning raw PII to the agent\n- Give non-engineer teammates a safer, preconfigured way to query through Redash or shared connection profiles\n- Replace ad-hoc SSH tunnel commands with reusable database profiles\n- Export query results as Markdown for AI/code-review contexts or CSV/JSON/PDF for reporting\n- Import existing database client profiles instead of rebuilding them by hand\n\n## Feature comparison\n\n| Feature | `mysql` CLI | `mycli` | DBeaver | mysh |\n|---|:---:|:---:|:---:|:---:|\n| CLI-first workflow | ✅ | ✅ | ❌ | ✅ |\n| Connection profile management | ❌ | ⚠️ | ✅ | ✅ |\n| SSH tunnel management | ❌ | ❌ | ✅ | ✅ |\n| Automatic masking for AI/non-TTY output | ❌ | ❌ | ❌ | ✅ |\n| Production `--raw` safety confirmation | ❌ | ❌ | ❌ | ✅ |\n| Import from GUI database clients | ❌ | ❌ | — | ✅ |\n| Team-safe config export without passwords | ❌ | ❌ | ⚠️ | ✅ |\n| Markdown/CSV/JSON/PDF export | ❌ | ❌ | ✅ | ✅ |\n| MySQL 4.x old_password support | ⚠️ | ⚠️ | ⚠️ | ✅ |\n\n## Features\n\n- Interactive connection setup with encrypted password storage (AES-256-GCM + Argon2id)\n- SSH tunnel management (ad-hoc and background persistent tunnels)\n- Automatic output masking for AI/non-TTY execution (protects personal data in production)\n- Built-in MCP server (`mysh mcp`) so AI agents can query databases natively, with masking enforced\n- Multiple connections across different terminals without conflicts\n- mycli preferred, falls back to standard mysql client\n- Native Go driver with MySQL 4.x old_password authentication support\n- Output format conversion (plain, markdown, CSV, JSON, PDF) with file export\n- Import connections from DBeaver, Sequel Ace, and MySQL Workbench\n- MySQL 4.x+ compatible (native driver) / MySQL 5.1+ compatible (CLI driver)\n\n## Install\n\n### macOS / Linux\n\n```bash\nbrew tap atani/tap\nbrew install mysh\n```\n\n### Windows\n\n#### MSI installer\n\nDownload `mysh-windows-x64.msi` (or `-arm64`) from the\n[latest release](https://github.com/atani/mysh/releases/latest) and run it.\nThe installer places `mysh.exe` under `C:\\Program Files\\mysh` by default (or a\nfolder you choose) and adds it to the system PATH.\n\n#### winget\n\n```powershell\nwinget install atani.mysh\n```\n\nwinget downloads and runs the MSI for you. If you need an offline installer or\nwant to choose the install location manually, use the MSI installer above.\n\n#### Standalone binary\n\nDownload `mysh-windows-amd64.exe` from the\n[latest release](https://github.com/atani/mysh/releases/latest), rename it to\n`mysh.exe`, and place it in a directory on your PATH.\n\n\u003e [!NOTE]\n\u003e The MSI and winget package are not code-signed yet, so Windows SmartScreen may\n\u003e show an \"unknown publisher\" prompt, and some endpoint-protection or ASR\n\u003e (Attack Surface Reduction) policies may block the installer. In managed\n\u003e environments an administrator may need to allow `mysh.exe`. A consistent\n\u003e install path (`C:\\Program Files\\mysh`) makes a path-based ASR exclusion\n\u003e straightforward, which is why the MSI keeps this path uniform across machines.\n\n### Go\n\n```bash\ngo install github.com/atani/mysh@latest\n```\n\n## Quick Start\n\n```bash\n# Add a connection interactively\nmysh add\n\n# Test connection (name optional if only one connection)\nmysh ping\n\n# Connect\nmysh connect\n```\n\n## Usage\n\n```\nmysh \u003ccommand\u003e [arguments]\n```\n\n### Connection Management\n\n```bash\n# Add a new connection (interactive)\nmysh add\n\n# List all connections\nmysh list\n\n# Edit an existing connection\nmysh edit production\n\n# Remove a connection\nmysh remove production\n```\n\nConnection name can be omitted when only one connection exists.\n\n### Import from Other Tools\n\nImport connections from other database tools:\n\n- [Migrating from DBeaver](docs/import-guide.md#migrating-from-dbeaver)\n- [Migrating from Sequel Ace](docs/import-guide.md#migrating-from-sequel-ace)\n- [Migrating from MySQL Workbench](docs/import-guide.md#migrating-from-mysql-workbench)\n\n```bash\nmysh import --from dbeaver        # Import from DBeaver\nmysh import --from sequel-ace     # Import from Sequel Ace\nmysh import --from workbench      # Import from MySQL Workbench\nmysh import --from dbeaver --all  # Import all without selection prompt\n```\n\n### Share Connections\n\nExport connections for team members (passwords are always excluded):\n\n```bash\n# Export all connections\nmysh export \u003e connections.yaml\n\n# Export a specific connection\nmysh export production \u003e prod.yaml\n```\n\nRecipients import the shared file and enter their own password:\n\n```bash\nmysh import --from yaml --file prod.yaml\n```\n\nFor direct DB connections where each team member has their own DB username, use `--ask-user` or pass one username with `--db-user`. If several DB connections share the same password, `--reuse-password` asks for it once:\n\n```bash\nmysh import --from yaml --file team-db.yaml --all --ask-user\nmysh import --from yaml --file team-db.yaml --all --db-user alice --reuse-password\n```\n\nExported files include environment, SSH, and mask settings, so non-engineer users get a fully configured connection — they only need to enter their own database credentials or Redash API key.\n\n### Redash Integration\n\nQuery production databases through Redash instead of direct DB connections. No database credentials or SSH tunnels needed — just a Redash API key.\n\n```bash\n# Add a Redash connection\nmysh add --name prod --redash-url https://redash.example.com --redash-key YOUR_API_KEY --redash-datasource 1\n\n# Query through Redash (masking is applied automatically)\nmysh run prod -e \"SELECT * FROM users LIMIT 10\"\n\n# Test connectivity\nmysh ping prod\n```\n\nThis is ideal for non-engineer users (CS, marketing, PM) who need safe access to production data via AI assistants like Claude Code. The query flows through Redash, and mysh applies masking rules to the results before returning them.\n\n### Connecting \u0026 Querying\n\n```bash\n# Test connection\nmysh ping production\n\n# Open an interactive MySQL session\nmysh connect production\n\n# Execute a SQL file\nmysh run production query.sql\n\n# Execute inline SQL\nmysh run production -e \"SELECT COUNT(*) FROM users\"\n\n# Show tables\nmysh tables production\n```\n\n### SSH Tunnels\n\nBy default, `connect` and `run` open an ad-hoc SSH tunnel that closes when the command finishes.\n\nFor repeated access, start a persistent background tunnel:\n\n```bash\n# Start a background tunnel\nmysh tunnel production\n\n# List active tunnels\nmysh tunnel\n\n# connect/run will automatically reuse the background tunnel\nmysh run production -e \"SHOW PROCESSLIST\"\n\n# Stop a tunnel\nmysh tunnel stop production\n```\n\nMultiple tunnels can run simultaneously for different connections.\n\n### Output Masking\n\nmysh can automatically mask sensitive columns (email, phone, etc.) in query output. This is designed to prevent personal data from leaking into AI tool contexts.\n\n#### How it works\n\nMasking is controlled by two factors:\n\n1. **Connection environment** (`env` in config)\n2. **TTY detection** (is output going to a terminal or being captured?)\n\n| env | Terminal (human) | Piped/captured (AI) |\n|-----|-----------------|---------------------|\n| production | **Auto-masked** | **Auto-masked** |\n| staging | Raw | **Auto-masked** |\n| development | Raw | Raw |\n\n#### Configuration\n\n```yaml\nconnections:\n  - name: production\n    env: production\n    mask:\n      columns: [\"email\", \"phone\", \"password_hash\"]\n      patterns: [\"*address*\", \"*secret*\"]\n    ssh: ...\n    db: ...\n```\n\n#### Manual override\n\n```bash\n# Force masking (even in terminal)\nmysh run production --mask -e \"SELECT * FROM users LIMIT 5\"\n\n# Force raw output (requires interactive confirmation for production)\nmysh run production --raw -e \"SELECT * FROM users LIMIT 5\"\n```\n\nFor production connections, `--raw` requires interactive confirmation at the terminal. Non-TTY processes (AI tools, scripts) cannot bypass masking.\n\n#### Masking examples\n\n| Type | Original | Masked |\n|------|----------|--------|\n| Email | alice@example.com | a\\*\\*\\*@example.com |\n| Phone | 090-1234-5678 | 0\\*\\*\\* |\n| Name | Alice | A\\*\\*\\* |\n| Short value | ab | \\*\\*\\* |\n| NULL | NULL | NULL |\n\n### Record Slicing\n\nExtract specific records from a database as INSERT statements. Useful for creating reproducible test data or migrating individual records.\n\n```bash\n# Extract records matching a condition\nmysh slice production products --where \"category='electronics'\"\n\n# Save to file\nmysh slice production products --where \"id IN (7,8)\" -o subset.sql\n\n# Disable masking (requires interactive confirmation)\nmysh slice production customers --where \"id=3\" --raw\n```\n\nOutput example:\n\n```sql\n-- mysh slice: products WHERE category='electronics'\n-- Generated at: 2026-03-15T12:00:00+09:00\n\nINSERT INTO `products` (`id`, `name`, `price`) VALUES (7, 'Widget Pro', 2980);\nINSERT INTO `products` (`id`, `name`, `price`) VALUES (8, 'Gadget Mini', NULL);\n```\n\nMasking rules from the connection config are always applied by default, regardless of environment. Use `--raw` to disable (requires interactive confirmation).\n\n### Output Formats\n\nExport query results as markdown, CSV, JSON, or PDF.\n\n```bash\n# Markdown table\nmysh run production -e \"SELECT * FROM users LIMIT 5\" --format markdown\n\n# CSV file\nmysh run production -e \"SELECT * FROM users\" --format csv -o users.csv\n\n# JSON output\nmysh run production -e \"SELECT * FROM users LIMIT 5\" --format json\n\n# JSON file\nmysh run production -e \"SELECT * FROM users\" --format json -o users.json\n\n# PDF report\nmysh run production -e \"SELECT * FROM users\" --format pdf -o report.pdf\n\n# tables command also supports format/output\nmysh tables production --format csv -o tables.csv\n```\n\nSupported formats: `plain` (default), `markdown` (`md`), `csv`, `json`, `pdf`\n\n### Saved Queries\n\nSave `.sql` files in `~/.config/mysh/queries/` and list them with:\n\n```bash\nmysh queries\n```\n\n## Configuration\n\nConnections are stored in `~/.config/mysh/connections.yaml`.\n\n```yaml\nconnections:\n  - name: production\n    env: production\n    ssh:\n      host: bastion.example.com\n      port: 22\n      user: deploy\n      key: ~/.ssh/id_ed25519\n    mask:\n      columns: [email, phone]\n      patterns: [\"*address*\"]\n    db:\n      host: 127.0.0.1\n      port: 3306\n      user: app\n      database: myapp_production\n      password: \u003cencrypted\u003e\n\n  - name: legacy-db\n    env: production\n    db:\n      host: 10.0.0.5\n      port: 3306\n      user: app\n      database: legacy_production\n      password: \u003cencrypted\u003e\n      driver: native  # MySQL 4.x old_password support\n\n  - name: local\n    env: development\n    db:\n      host: localhost\n      port: 3306\n      user: root\n      database: myapp_dev\n```\n\n### Connection Driver\n\nThe `driver` field selects how mysh connects to MySQL.\n\n| driver | Description | Supported versions |\n|--------|-------------|-------------------|\n| `cli` (default) | Delegates to mysql/mycli CLI | MySQL 5.1+ |\n| `native` | Direct connection via Go's database/sql | MySQL 4.x+ |\n\nThe `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.\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `MYSH_MASTER_PASSWORD` | Master password for credential decryption. Useful for non-interactive contexts (AI assistants, scripts). |\n\nThe master password lookup order is: **OS credential store (macOS Keychain / Windows Credential Manager) → `MYSH_MASTER_PASSWORD` → interactive prompt**.\n\nOn macOS and Windows, the master password is saved to the OS credential store on first use, so you don't need to set `MYSH_MASTER_PASSWORD` for unattended runs (e.g. from AI assistants). On platforms without a supported store, use the environment variable or the interactive prompt.\n\n## Security\n\n- Database passwords are encrypted with AES-256-GCM\n- Key derivation uses Argon2id (memory-hard, resistant to GPU attacks)\n- Master password is stored in the OS credential store — macOS Keychain or Windows Credential Manager (falls back to `MYSH_MASTER_PASSWORD` env var, then prompt)\n- Config files are created with `0600` permissions\n- Production query output is always masked when mask rules are configured\n- `--raw` on production requires interactive TTY confirmation (AI tools cannot bypass)\n\n## Caveats\n\n- **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.\n- **Native driver `connect` limitations**: Unlike mycli/mysql CLI, the built-in REPL has no tab completion, syntax highlighting, or pager. For complex interactive work, prefer `run -e`.\n- **go-sql-driver/mysql `allowOldPasswords`**: This depends on the driver's support, which may be removed in future driver updates.\n\n## Documentation\n\n- [Getting Started (non-engineers)](docs/getting-started.md) — set up mysh and start querying with Claude Code\n- [Using mysh safely with AI coding agents](docs/ai-agent-safety.md) — recommended masking and workflow guidance for Claude Code, Cursor, scripts, and other agents\n- [MCP Server Guide](docs/mcp-guide.md) — expose mysh to AI agents over the Model Context Protocol\n- [Redash Integration Guide](docs/redash-guide.md) — query databases through Redash\n- [Sharing Connections](docs/sharing-connections.md) — export/import configurations for team onboarding\n- [Import Guide](docs/import-guide.md) — migrate from DBeaver, Sequel Ace, MySQL Workbench\n- [Launch Kit](docs/launch-kit.md) — copy-ready English posts for Show HN, Reddit, X/Bluesky, and other communities\n- [Global Launch Checklist](docs/global-launch-checklist.md) — repository metadata, launch order, and follow-up checklist\n\nJapanese translations are available under [`docs/ja/`](docs/ja/)（日本語ドキュメントは [`docs/ja/`](docs/ja/) を参照）.\n\n## Dependencies\n\n- `golang.org/x/crypto` - Argon2id key derivation\n- `golang.org/x/term` - Secure password input and TTY detection\n- `gopkg.in/yaml.v3` - Configuration file parsing\n- `github.com/go-sql-driver/mysql` - Native MySQL driver (old_password support)\n- `github.com/go-pdf/fpdf` - PDF output\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatani%2Fmysh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatani%2Fmysh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatani%2Fmysh/lists"}