[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7D36VE5AEREF874PDV2SJSG":3,"skill-same:01M7D36VE5AEREF874PDV2SJSG":61},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":21,"frontMatter":22,"refName":23,"commitSha":24,"skillDirectory":25,"forksCount":13,"repositoryHtmlUrl":26,"repositoryHomepageUrl":6,"ownerHtmlUrl":27,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":28,"install":29,"resources":42},"01M7D36VE5AEREF874PDV2SJSG","prod-db-mysql-bastion",null,"rabihkodeih\u002Fagentic-workflow","rabihkodeih","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1883033?v=4","01M7D357MHZJG4N8PQV8R5TZ82","Rabih Kodeih","01M7D357NM3WD86XTZ93FV7DNK",0,"MIT","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fprod-db-mysql-bastion\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: prod-db-mysql-bastion\ndescription: Run read-only SQL against a production MySQL\u002FAurora database that has no public endpoint (RDS Proxy inside a VPC), by piping a small runner to an EC2 instance in that VPC over SSH-via-SSM and executing it there. Use when the user asks to query, inspect, count or check data in \"the production database\" and the DB is only reachable from inside the VPC. Read-only: SELECT\u002FSHOW\u002FDESCRIBE\u002FEXPLAIN only, enforced server-side.\n---\n\n# Production MySQL behind a VPC, read-only queries\n\nRuns one read-only statement against prod and returns the rows.\n\n```bash\nscripts\u002Fquery.sh 'SELECT COUNT(*) AS dealers FROM company'\nscripts\u002Fquery.sh --format json 'SELECT id, name FROM company LIMIT 20'\nscripts\u002Fquery.sh --timeout 60 'SELECT ... a slower analytical query ...'\n```\n\nFlags: `--format table|json` (default `table`) · `--limit N` (default 200) ·\n`--timeout SECONDS` (default 30) · `--start` (boot the instance if it is stopped).\n\n## Configuration\n\nEnv or `scripts\u002Fconfig.env` (sourced if present, gitignored). Copy `config.example.env`.\n\n| Variable | What |\n|---|---|\n| `BASTION_INSTANCE_ID` | EC2 inside the VPC whose instance role may read the DB secret |\n| `BASTION_SSH_ALIAS` | `~\u002F.ssh\u002Fconfig` host using `ProxyCommand aws ssm start-session ... AWS-StartSSHSession` |\n| `BASTION_AWS_PROFILE` \u002F `BASTION_AWS_REGION` | SSO profile and region |\n| `BASTION_REMOTE_PYTHON` | a python on the instance with `pymysql` and `boto3` |\n| `DB_SECRET_ID`, `DB_HOST`, `DB_PORT`, `DB_NAME` | Secrets Manager id and the proxy endpoint, sent to the runner |\n\nHardcode `DB_HOST` in `config.env` for one environment on purpose: a skill that can be\npointed at any host by an env var an operator last set is not prod-only by construction.\n\n## Schema: look, do not guess\n\n`SHOW TABLES` and `DESCRIBE \u003Ctable>` cost a few milliseconds. Start there instead of\nassuming a name, and keep a dated cheat sheet in the project's `domain-knowledge.md`.\n\n## Ask the user before the first query of a session\n\nThis hits a live production database. Confirm with the user before the first query,\nand again for anything that is not a cheap indexed lookup: a wide scan on prod\ncompetes with the real pipeline for proxy connections. Cheap `COUNT(*)` follow-ups in\nan already-authorised session do not each need a fresh confirmation.\n\n## Why it cannot just connect\n\nThe RDS Proxy has no public endpoint, so the laptop cannot reach it. `query.sh` pipes\n`runner.py` to the instance over SSH-via-SSM and it executes there. DB credentials are\nread from Secrets Manager by the instance role, so no password ever reaches the\ncaller's machine or the transcript.\n\n## How read-only is enforced\n\nThe DB user may well have full privileges (many shops have no read-only role), so\nread-only is enforced by the skill, in three layers:\n\n1. Statement allow-list: `SELECT` \u002F `WITH` \u002F `SHOW` \u002F `DESCRIBE` \u002F `EXPLAIN`, one\n   statement per call. String literals and comments are blanked before the check, so a\n   `;` inside `'...'` is not misread as a stacked statement.\n2. No-file-write check: rejects `INTO OUTFILE` \u002F `INTO DUMPFILE` (a `SELECT` that writes).\n3. `START TRANSACTION READ ONLY`: the server rejects any write with error 1792. This is\n   the layer that holds; 1 and 2 exist to fail fast with a clear message.\n\nPlus `max_execution_time` (default 30s) and a row cap, which is the guard that matters\nday to day: on a live cluster the real hazard is an unbounded join pinning a proxy\nconnection, not a rogue `DELETE`.\n\n`scripts\u002Ftest_guard.py` covers the guard offline (no DB, no AWS): `python3 scripts\u002Ftest_guard.py`.\n\n## Failure modes\n\n| Symptom | Meaning |\n| --- | --- |\n| `SSO token expired. Run: aws sso login --profile X` | The user must log in; you cannot do it for them |\n| `instance is 'stopped'` | Ask the user, then re-run with `--start` (a small instance costs a few dollars a month running, nothing stopped) |\n| `SSM agent is ConnectionLost` | Box is running but saturated; the agent got starved off the network. Common right after `--start` following a long stop when missed cron timers fire at boot. Wait for CPU to drop, or reboot |\n| `REFUSED: ...` (exit 3) | The statement is not read-only. Do not try to reword around the guard |\n| `TIMEOUT: ...` (exit 4) | Query exceeded `--timeout` and was killed server-side. Narrow it before raising the limit |\n| `No such file or directory: \u003Cremote python>` | Point `BASTION_REMOTE_PYTHON` at a venv on the instance with `pymysql` and `boto3` |\n\npymysql TLS quirk: `ssl={\"ca\": None}`, not `{}`, is the shape that triggers the TLS\npath; an RDS Proxy rejects a plaintext connection (error 3159).\n","# Production MySQL behind a VPC, read-only queries\n\nRuns one read-only statement against prod and returns the rows.\n\n```bash\nscripts\u002Fquery.sh 'SELECT COUNT(*) AS dealers FROM company'\nscripts\u002Fquery.sh --format json 'SELECT id, name FROM company LIMIT 20'\nscripts\u002Fquery.sh --timeout 60 'SELECT ... a slower analytical query ...'\n```\n\nFlags: `--format table|json` (default `table`) · `--limit N` (default 200) ·\n`--timeout SECONDS` (default 30) · `--start` (boot the instance if it is stopped).\n\n## Configuration\n\nEnv or `scripts\u002Fconfig.env` (sourced if present, gitignored). Copy `config.example.env`.\n\n| Variable | What |\n|---|---|\n| `BASTION_INSTANCE_ID` | EC2 inside the VPC whose instance role may read the DB secret |\n| `BASTION_SSH_ALIAS` | `~\u002F.ssh\u002Fconfig` host using `ProxyCommand aws ssm start-session ... AWS-StartSSHSession` |\n| `BASTION_AWS_PROFILE` \u002F `BASTION_AWS_REGION` | SSO profile and region |\n| `BASTION_REMOTE_PYTHON` | a python on the instance with `pymysql` and `boto3` |\n| `DB_SECRET_ID`, `DB_HOST`, `DB_PORT`, `DB_NAME` | Secrets Manager id and the proxy endpoint, sent to the runner |\n\nHardcode `DB_HOST` in `config.env` for one environment on purpose: a skill that can be\npointed at any host by an env var an operator last set is not prod-only by construction.\n\n## Schema: look, do not guess\n\n`SHOW TABLES` and `DESCRIBE \u003Ctable>` cost a few milliseconds. Start there instead of\nassuming a name, and keep a dated cheat sheet in the project's `domain-knowledge.md`.\n\n## Ask the user before the first query of a session\n\nThis hits a live production database. Confirm with the user before the first query,\nand again for anything that is not a cheap indexed lookup: a wide scan on prod\ncompetes with the real pipeline for proxy connections. Cheap `COUNT(*)` follow-ups in\nan already-authorised session do not each need a fresh confirmation.\n\n## Why it cannot just connect\n\nThe RDS Proxy has no public endpoint, so the laptop cannot reach it. `query.sh` pipes\n`runner.py` to the instance over SSH-via-SSM and it executes there. DB credentials are\nread from Secrets Manager by the instance role, so no password ever reaches the\ncaller's machine or the transcript.\n\n## How read-only is enforced\n\nThe DB user may well have full privileges (many shops have no read-only role), so\nread-only is enforced by the skill, in three layers:\n\n1. Statement allow-list: `SELECT` \u002F `WITH` \u002F `SHOW` \u002F `DESCRIBE` \u002F `EXPLAIN`, one\n   statement per call. String literals and comments are blanked before the check, so a\n   `;` inside `'...'` is not misread as a stacked statement.\n2. No-file-write check: rejects `INTO OUTFILE` \u002F `INTO DUMPFILE` (a `SELECT` that writes).\n3. `START TRANSACTION READ ONLY`: the server rejects any write with error 1792. This is\n   the layer that holds; 1 and 2 exist to fail fast with a clear message.\n\nPlus `max_execution_time` (default 30s) and a row cap, which is the guard that matters\nday to day: on a live cluster the real hazard is an unbounded join pinning a proxy\nconnection, not a rogue `DELETE`.\n\n`scripts\u002Ftest_guard.py` covers the guard offline (no DB, no AWS): `python3 scripts\u002Ftest_guard.py`.\n\n## Failure modes\n\n| Symptom | Meaning |\n| --- | --- |\n| `SSO token expired. Run: aws sso login --profile X` | The user must log in; you cannot do it for them |\n| `instance is 'stopped'` | Ask the user, then re-run with `--start` (a small instance costs a few dollars a month running, nothing stopped) |\n| `SSM agent is ConnectionLost` | Box is running but saturated; the agent got starved off the network. Common right after `--start` following a long stop when missed cron timers fire at boot. Wait for CPU to drop, or reboot |\n| `REFUSED: ...` (exit 3) | The statement is not read-only. Do not try to reword around the guard |\n| `TIMEOUT: ...` (exit 4) | Query exceeded `--timeout` and was killed server-side. Narrow it before raising the limit |\n| `No such file or directory: \u003Cremote python>` | Point `BASTION_REMOTE_PYTHON` at a venv on the instance with `pymysql` and `boto3` |\n\npymysql TLS quirk: `ssl={\"ca\": None}`, not `{}`, is the shape that triggers the TLS\npath; an RDS Proxy rejects a plaintext connection (error 3159).\n",{},"main","7b05d4ac96431d4dca2179b70d4f124979d4c3a8","skills\u002Fprod-db-mysql-bastion","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow","https:\u002F\u002Fgithub.com\u002Frabihkodeih","2026-09-20 04:17:12",{"source":7,"skillName":5,"commands":30,"prompt":40,"zipAvailable":41},[31,34,37],{"tool":32,"command":33},"npx","npx skills add rabihkodeih\u002Fagentic-workflow --skill prod-db-mysql-bastion",{"tool":35,"command":36},"bunx","bunx skills add rabihkodeih\u002Fagentic-workflow --skill prod-db-mysql-bastion",{"tool":38,"command":39},"pnpm","pnpm dlx skills add rabihkodeih\u002Fagentic-workflow --skill prod-db-mysql-bastion","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fprod-db-mysql-bastion\u002FSKILL.md",true,[43,49,53,57],{"path":44,"resourceType":45,"resourceTypeDesc":46,"sizeBytes":47,"sourceHtmlUrl":48},"scripts\u002Fconfig.example.env","SCRIPT","脚本",362,"https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fprod-db-mysql-bastion\u002Fscripts\u002Fconfig.example.env",{"path":50,"resourceType":45,"resourceTypeDesc":46,"sizeBytes":51,"sourceHtmlUrl":52},"scripts\u002Fquery.sh",4040,"https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fprod-db-mysql-bastion\u002Fscripts\u002Fquery.sh",{"path":54,"resourceType":45,"resourceTypeDesc":46,"sizeBytes":55,"sourceHtmlUrl":56},"scripts\u002Frunner.py",7305,"https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fprod-db-mysql-bastion\u002Fscripts\u002Frunner.py",{"path":58,"resourceType":45,"resourceTypeDesc":46,"sizeBytes":59,"sourceHtmlUrl":60},"scripts\u002Ftest_guard.py",2076,"https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fprod-db-mysql-bastion\u002Fscripts\u002Ftest_guard.py",[62,69,76,83,90,96],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":68,"publishedAt":18},"01M7D37HNRY0RGK352YT1SYQVH","yes-no","Answer the user's question with a yes or no, optionally followed by a short explanation when the model sees fit. Use when the user types \"\u002Fyes-no\", asks a yes\u002Fno question and wants a decisive answer, or says \"just yes or no\".","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fyes-no\u002FSKILL.md",[],[],{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":18},"01M7D37CDX8K153CYY4FVCGAT5","sonar-workflow","Fix SonarQube code quality issues for a pull request. Auto-fixes trivial issues (formatting, unused imports) and requests approval for complex issues (security, bugs). Integrates with commit-workflow and pr-workflow skills.","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fsonar-workflow\u002FSKILL.md",[],[],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":82,"publishedAt":18},"01M7D377REEE0MBH7SJ37JWR41","short-answer","Answer the user's question as concisely as possible, a direct, to-the-point response with no preamble, filler, or unnecessary elaboration. Use when the user types \"\u002Fshort-answer\", asks for a brief\u002Fshort\u002Fconcise\u002FTL;DR answer, or says \"just the answer\".","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fshort-answer\u002FSKILL.md",[],[],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":18},"01M7D371KTYERB0DFG67XE9PTC","redash","Query a Redash instance over its REST API , list data sources and saved queries, read a saved query's SQL, run it, or run ad-hoc read-only SQL and get the rows back. Use when the user asks about Redash, a Redash query\u002Fdashboard\u002Flink, \"run that query\", \"what does query 1234 return\", or wants numbers out of an analytics data source rather than the application DB.","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fredash\u002FSKILL.md",[],[],{"skillNo":91,"name":92,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":95,"publishedAt":18},"01M7D36Y5BF600Z6B470W1AFNZ","prod-db-postgres","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fprod-db-postgres\u002FSKILL.md",[],[],{"skillNo":97,"name":98,"nameZh":6,"description":99,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":102,"publishedAt":18},"01M7D36NSNPJVP3BS20DRMZ953","pr-workflow","Use this skill when asked to create or update a pull request (PR). It ensures all PRs follow the repository's established templates and standards. Handles both new PR creation and updating existing PRs with new commits, title changes, or description updates.","https:\u002F\u002Fgithub.com\u002Frabihkodeih\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fpr-workflow\u002FSKILL.md",[],[]]