sql-review
Skill1 starsChanged 3 months agoMITView on GitHub
Pre-commit review of uncommitted SQL against a catalog of antipatterns that cause real production incidents, reporting BLOCKER / WARN / INFO with file-and-line citations and a fix per finding. Never edits SQL. Use this skill whenever the user says "/sql-review", "review my SQL", "review the SQL diff", "lint the SQL", "check my SQL changes", "SQL pre-commit check", "audit my stored proc", or "any SQL antipatterns in this diff" - even if they do not name the skill. Distinct from code-review (general review) - this carries the SQL-specific incident patterns.
- Deletes or force-pushes
10 other projects use a version of this.
Adopted by
Most recently taken up by
- Smaui94/ClaudeSkillCollectiontheir own version, first seen Nov 8, 2026
- polardb/polardbx-skillstheir own version, first seen Nov 8, 2026
- Lanqiao-Luca/ai-java-workflowtheir own version, first seen Nov 8, 2026
- z-Zihan/Evirtheir own version, first seen Oct 13, 2026
- analyticsengineering/ae-toolkittheir own version, first seen Oct 12, 2026
- GabrielHenriqueCA/cortex-aitheir own version, first seen Oct 11, 2026
Other versions10 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 10
- Lanqiao-Luca/ai-java-workflow★ 220same name
- kyle-chalmers/streamsnow★ 17same name
- z-Zihan/Evir★ 11same name
- polardb/polardbx-skills★ 8same name
- analyticsengineering/ae-toolkit★ 3same name
- gmanch94/claude-code-aidlc-template★ 2same name
- Jiplet/transformation-os★ 2same name
- GabrielHenriqueCA/cortex-ai★ 1same name
- bt2go/claude-skills★ 0same name
- Smaui94/ClaudeSkillCollection★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository38 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- api-contract-reviewSkill
- autopilotSkill
- backlog-plannerSkill
- codebase-explainerSkill
- code-reviewSkill
- context-dietSkill
- conventional-commitsSkill
- create-prSkill
- design-briefSkill
- diagnoseSkill
- dotnet-conventionsSkill
- dotnet-onion-apiSkill
- draw-optionsSkill
- e2e-verifySkill
- githubSkill
- goal-runnerSkill
- grill-with-docsSkill
- handoffSkill
- humanizerSkill
- improve-codebase-architectureSkill
- maestro-mobile-testSkill
- migration-safetySkill
- model-inventorySkill
- nextjs-app-routerSkill
- plan-and-buildSkill
- record-browser-testSkill
- regression-huntSkill
- safe-refactorSkill
- security-reviewSkill
- ship-itSkill
- task-executorSkill
- tauri-2-appSkill
- think-like-fableSkill
- upgrade-depsSkill
- worktree-sandboxSkill
- write-a-skillSkill
- write-testsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
14 rules. 0 are common, 5 are distinctive, and 9 are very specific to this project.
0
Common
Most of the 8 edited versions we read keep these.
5
Distinctive
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 15
Before committing a .sql change touching a stored procedure, function, or table
- Very specific: line 17
Do not auto-trigger when the user is asking for a *general* code review on a mixed diff — defer to code-review for that.
- Distinctive: line 29
Snapshot the SQL diff: Run in parallel:
- Very specific: line 33
If user passed an explicit range (e.g.
- Distinctive: line 60
Every reported finding must:
- Distinctive: line 68
Use ripgrep for detection.
- Very specific: line 78
Fix: Add the missing WHILE @retry > 0 BEGIN ...
- Very specific: line 96
Fix: Add PRIMARY KEY CLUSTERED on the natural ID column.
- Very specific: line 126
Fix: Add the WHERE clause. If "every row" really is intended (TRUNCATE-style), use TRUNCATE TABLE and add a comment explaining why.
- Very specific: line 130
Fix: Remove the hint on tables being modified.
- Very specific: line 141
Fix: Add SET NOCOUNT ON; as the first statement after AS BEGIN.
- Very specific: line 205
Every finding quotes the offending SQL verbatim with file:line — no paraphrases survived.
- Distinctive: line 206
Every BLOCKER/WARN carries its one-sentence incident — anything that couldn't name one got demoted.
- Distinctive: line 271
If the user wants the broader cleanup (refactor every legacy SP in the repo with one of these issues), recommend opening a tracked task …
“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SQL Review
Review uncommitted SQL changes against a catalog of patterns that cause real production incidents — masked errors, unindexed new tables, silent truncation, SQL injection, deadlock-prone CATCH blocks — and surface findings as recommendations the user can act on, without editing SQL unprompted.
When to use this skill
- "/sql-review" / "review my SQL" / "review the SQL diff"
- "lint the SQL" / "SQL pre-commit check" / "check my SQL changes"
- "audit my stored proc" / "any SQL antipatterns in this diff"
- Before committing a
.sqlchange touching a stored procedure, function, or table
Do not auto-trigger when the user is asking for a general code review on a mixed diff — defer to code-review for that. This skill is specifically for SQL-heavy diffs where the antipattern catalog applies.
Hard rule: surface, don't refactor
If you find issues, do not start editing the SQL. Produce the findings report first. After delivering it, ask the user per finding: "Want me to fix #N?" — and wait for an explicit yes. Pre-authorization ("fix them all") proceeds through the list; absent that, default to ask-per-fix.
Same rule, harder: never execute any SQL from the diff against any database — not to reproduce, not to verify. This is a static read-only review; verification here means quoting the offending lines, not running them. (Doctrine's run-against-a-schema-copy row is deploy-time verification, out of scope for this pre-commit pass.)
SQL changes are particularly sensitive because they often run against production data in a single non-reversible deployment. A drive-by refactor mid-review is more dangerous here than in application code.
Workflow
- Snapshot the SQL diff. Run in parallel:
git status --short— see what's modified, staged, untracked.git diff -- '*.sql'— unstaged SQL changes.git diff --staged -- '*.sql'— staged SQL changes.- If user passed an explicit range (e.g.
main..HEAD), use that instead:git diff <range> -- '*.sql'.
- Triage files into two buckets:
- New files (status
Aor??) — review the entire file. The whole file is new code; pre-existing antipatterns elsewhere don't apply. - Modified files (status
M) — review only the changed hunks. The rest of the file may have legacy antipatterns the user isn't introducing (e.g. existing repos commonly have dozens of SPs with thesp_send_dbmail-in-CATCH pattern; flagging all of them on an unrelated edit creates noise). - Exit gate: you have a list of changed
.sqlfiles, each tagged new or modified. If the list is empty, STOP — report "No uncommitted SQL changes found (checked staged, unstaged, untracked)" and ask whether the user meant a committed range (git diff <range> -- '*.sql'). Never widen scope to non-SQL files or committed history on your own.
- New files (status
- For each check in What to check, look for the pattern in the relevant scope (whole file for new files, diff hunks for modified files). Use ripgrep — don't try to fully parse SQL.
- Categorize each finding as
BLOCKER/WARN/INFO(see Categories). - Cite
file:linefor every finding. Line numbers come from the diff or the current file content. - Produce the report in the Output format.
- Offer to fix the suggested findings. Wait for the user's selection before editing.
Categories
BLOCKER— would cause a production incident: silent data loss, masked errors, SQL injection, unindexed table that will grow, broken transaction handling. Fix before commit.WARN— likely a bug or maintenance hazard: NOLOCK in write paths, hardcoded environment values, missingSET NOCOUNT ON, cross-DB references. Should fix but won't necessarily incident.INFO— style / convention / hygiene: vestigial comments, cursor defaults, missingGRANT EXECUTEwhere the project's pattern exists.
Lead each finding with the why. "This swallows the original error and surfaces a misleading permission denial" beats "add ;THROW;".
Pattern hit ≠ finding
The 17 checks are pattern matches. A ripgrep hit is a candidate — before reporting it, Read the whole procedure/batch it sits in; severity depends on context the pattern can't see. Concrete demotions:
WITH (NOLOCK)hit, but the proc is a read-only reporting proc with noINSERT/UPDATE/DELETE→ WARN at most, not BLOCKER (check #13 blocks only when the same proc writes the tables it dirty-reads).DECLARE @retrywith noWHILE @retryin sight → check for aGOTO-label retry loop consuming it before flagging; only report when nothing reads the variable.- New
CREATE TABLEwith no index, but it's a static lookup/config table seeded with a handful of rows in the same diff → WARN with a one-line reason, not BLOCKER (the deadlock incident needs growth under concurrent writes).
Every reported finding must:
- Quote the offending SQL verbatim — the exact line(s) from the file, not a paraphrase. Severity turns on exact tokens.
- For
BLOCKER/WARN: state the concrete production incident in one sentence (this state → this outcome, e.g. "first deadlock under load → SP silently gives up, rows never written"). If you can't write that sentence after reading the full proc, demote one level.
Zero findings is a valid outcome — a clean diff gets a clean report. Never stretch INFO items into WARNs to fill sections; thoroughness is the 17 checks you ran, which the report shows.
What to check
Use ripgrep for detection. The patterns below are starting points — adapt to the actual diff text.
Error-handling antipatterns (BLOCKER class)
sp_send_dbmailinsideCATCH— masks the real exception with a permission/configuration error when the executing login lacksEXECUTEonmsdb.dbo.sp_send_dbmail. The real underlying error is silently lost.- Pattern:
rg -n -B 20 'sp_send_dbmail' <file>→ check whether the surrounding context is aBEGIN CATCH. - Fix: Replace with
;THROW;to re-raise, or write the error info to a local log table. Neversp_send_dbmailfrom inside operational SPs.
- Pattern:
- Broken retry pattern —
DECLARE @retry INT = N;exists, but noWHILE @retryloop wraps theTRY/CATCH. The retry variable is decremented in the CATCH but never read, so the SP gives up on the first deadlock instead of retrying.- Pattern:
rg -n '@retry' <file>→ confirm there's a matchingWHILE.*@retrysomewhere in the same SP body. - Fix: Add the missing
WHILE @retry > 0 BEGIN ... ENDaround the TRY/CATCH, or remove the vestigial variable entirely.
- Pattern:
- Empty / swallowing
CATCHblocks —BEGIN CATCH ... END CATCHwith noTHROW, noRAISERROR, and noINSERT INTO <error_log_table>. Silent failure → silent data loss.- Pattern:
rg -n -A 30 'BEGIN CATCH' <file>→ check each match for at least one ofTHROW,RAISERROR, orINSERT INTO. - Fix: End the CATCH with
;THROW;unless there's a deliberate reason to suppress (and document that reason).
- Pattern:
BEGIN TRANSACTIONwithoutTRY/CATCH+XACT_STATEhandling — an error mid-transaction leaves an open transaction on the connection.- Pattern:
rg -n 'BEGIN TRAN' <file>→ confirm the same SP hasBEGIN TRYandXACT_STATE()checks in CATCH. - Fix: Wrap in
BEGIN TRY / BEGIN TRANSACTION ... COMMIT TRANSACTION / END TRY / BEGIN CATCH / IF XACT_STATE() = -1 ROLLBACK; IF XACT_STATE() = 1 COMMIT; ;THROW; / END CATCH.
- Pattern:
- Vestigial control-flow comments —
-- end while loopwith noWHILEkeyword,-- retry on deadlockwith no retry loop, etc. Strong signal that a refactor left dead code behind.- Pattern:
rg -n -- '-- end (while|for|repeat)' <file>→ check for matching opening keyword. - Fix: Either restore the missing loop or delete the misleading comment.
- Pattern:
Schema / performance antipatterns (BLOCKER for new tables, WARN otherwise)
- New
CREATE TABLEwithout a primary key, clustered index, or any index — heap tables will deadlock-and-table-scan once they grow. This is the exact pattern that caused real production deadlocks.- Pattern:
rg -n -A 50 'CREATE TABLE' <file>→ confirm at least one ofPRIMARY KEY,CLUSTERED INDEX, orCREATE INDEXexists on that table within the diff or in a sibling file. - Fix: Add
PRIMARY KEY CLUSTEREDon the natural ID column. If the table is append-mostly with no natural ID, add a clustered index on the column the populating SPs filter by inWHERE.
- Pattern:
- Parameter-to-column type-width mismatches — passing
@x VARCHAR(50)into a column declaredVARCHAR(3)causes silent truncation (or runtime error 8152 depending onANSI_WARNINGS).- Pattern: cross-reference the SP's
@param VARCHAR(N)declarations against the target table's column widths. Flag any narrowing. - Find the widths:
rg -n 'CREATE TABLE' --glob '*.sql'filtered to the table name — DDL repos keep one file per table — and quote the column definition line as evidence. If the table's DDL is not in the repo, do NOT guess: record #7 asnot run — table DDL not availablein the report's checks line (see Summary) and say so in one line. - Fix: Match widths between parameter and column, or add explicit
LEFT(@x, 3)truncation at the boundary so it's intentional and visible.
- Pattern: cross-reference the SP's
- Implicit type conversions in
JOIN/WHERE—WHERE intCol = @varcharParamdefeats indexes and produces table scans.- Pattern:
rg -n -i 'WHERE\s+\w+\s*=\s*@\w+' <file>→ cross-check using the same DDL lookup as #7; samenot runrule if the DDL is absent. - Fix: Match the parameter type to the column type. If they're authoritatively different, cast the parameter, not the column (casting the column kills the index).
- Pattern:
Security antipatterns (BLOCKER)
- Dynamic SQL via string concatenation passed to
EXEC()withoutsp_executesql @stmt, @paramsparameterization — SQL injection.- Pattern:
rg -n 'EXEC\s*\(' <file>→ confirm any string-concat dynamic SQL nearby usessp_executesqlwith parameters, notEXEC(@strSQL)with values inlined. - Fix: Switch to
EXEC sp_executesql @stmt = @strSQL, @params = N'@p1 INT, @p2 VARCHAR(50)', @p1 = @value1, @p2 = @value2;.
- Pattern:
- Hardcoded environment-specific values — email addresses, server names, file paths, IP addresses, connection strings.
- Pattern:
rg -nE "'[\w.-]+@[\w.-]+\.\w+'|@server_name\s*=\s*'\w+'|\\\\\\\\[\\w.-]+\\\\" <file>(emails, linked servers, UNC paths). - Fix: Move env-specific values into a configuration table or pass them as parameters from the application layer.
- Pattern:
- Cross-database references —
msdb.dbo.*,master.dbo.*, linked server[srv].db.dbo.*. These require permissions that may not exist in all environments (the canonical example: a SP callingmsdb.dbo.sp_send_dbmailfrom a login that lacks EXECUTE on it).- Pattern:
rg -n 'msdb\.|master\.dbo\.|\[\w+\]\.\w+\.\w+\.' <file>. - Fix: Move the cross-DB call out of operational SPs into infrastructure-owned code. If it must stay, document the required permission in a comment so deployments to new environments include the GRANT.
- Pattern:
Correctness / data-safety antipatterns (BLOCKER)
UPDATEorDELETEwithout aWHEREclause — almost always a bug; will affect every row.- Pattern:
rg -n -B 0 -A 20 'UPDATE\s+\w+' <file>→ confirm aWHEREclause is present and not commented out. - Pattern:
rg -n -B 0 -A 10 'DELETE\s+FROM' <file>→ same. - Fix: Add the
WHEREclause. If "every row" really is intended (TRUNCATE-style), useTRUNCATE TABLEand add a comment explaining why.
- Pattern:
NOLOCK/READ UNCOMMITTEDinside transactional write paths —WITH (NOLOCK)is fine for ad-hoc reporting reads, but in anUPDATE/INSERT/DELETESP it can read uncommitted data and corrupt the write.- Pattern:
rg -n -i 'NOLOCK|READ UNCOMMITTED' <file>→ check whether the same SP hasINSERT,UPDATE, orDELETEagainst the same tables. - Fix: Remove the hint on tables being modified. Consider
SNAPSHOTisolation if the goal is to avoid blocking.
- Pattern:
TRUNCATE TABLEorDROPwithoutIF EXISTSin deploy scripts that are supposed to be idempotent (re-runnable). Many repos use flat idempotentDeploy_*.sqlfiles where re-runs must not fail on missing objects.- Pattern:
rg -n -i 'DROP (TABLE|PROC|FUNCTION|VIEW)' <file>→ confirmIF EXISTSorOBJECT_ID(...) IS NOT NULLguard. - Repo style: glob for
**/Deploy_*.sql(or a re-run/idempotency note in the changed file's header comment). Present → idempotent-deploy repo, flag as BLOCKER. Absent → forward-only migrations, flag as WARN. Can't tell → ask the user which style the repo uses; don't pick silently. - Fix:
IF OBJECT_ID('dbo.X', 'U') IS NOT NULL DROP TABLE dbo.X;orDROP TABLE IF EXISTS dbo.X;(SQL 2016+).
- Pattern:
Style / convention (WARN/INFO)
- Missing
SET NOCOUNT ONat the top of a newCREATE PROC— causes extra round-trips to the client and breaks some ORM drivers that don't handle row-count messages.- Pattern:
rg -n -A 5 'CREATE PROC' <file>→ confirmSET NOCOUNT ONappears within the first ~10 lines of the procedure body. - Fix: Add
SET NOCOUNT ON;as the first statement afterAS BEGIN.
- Pattern:
- Cursors without
READ_ONLY FORWARD_ONLY LOCAL— default cursors are slow and persist beyond the current batch.- Pattern:
rg -n 'DECLARE\s+\w+\s+CURSOR\b' <file>→ confirmREAD_ONLY FORWARD_ONLY LOCAL(orFAST_FORWARD) is specified. - Fix:
DECLARE c CURSOR READ_ONLY FORWARD_ONLY LOCAL FOR SELECT ....
- Pattern:
- Missing
GRANT EXECUTEat end ofCREATE PROC— only flag when the rest of the repo has a consistentGRANT EXECUTE ON ... TO <role>pattern at the end of every SP file. Detect the pattern by sampling the 5 most recently modified.sqlfiles in the same directory (all of them if fewer than 5); the convention exists only if at least 4 grant EXECUTE to the same role — otherwise there is no convention and #17 is not flagged.- Pattern:
rg -n 'GRANT\s+EXECUTE' <file>→ confirm present if the repo convention requires it. - Fix: Append
GRANT EXECUTE ON [dbo].[<proc>] TO [<app_role>] GOmatching the role the rest of the repo grants to.
- Pattern:
Output format
# SQL review — uncommitted changes
**SQL files changed:** <N> (<S new>, <M modified>)
---
## Verdict
**Ship / Fix blockers first**
<one-paragraph summary of the change and overall state>
---
## Blockers (<N>)
### B1. <short title> — `path/to/file.sql:<line>`
**Evidence:** `<offending SQL fragment, quoted verbatim>`
**Why:** <root cause / production consequence — one line>
**Fix:** <concrete recommendation — one line>
### B2. ...
## Warnings (<N>)
### W1. <short title> — `path/to/file.sql:<line>`
**Evidence:** `<offending SQL fragment, quoted verbatim>`
**Why:** ...
**Fix:** ...
## Info (<N>)
- `path:line` — <one-liner>
---
## Summary
- BLOCKER: <count>
- WARN: <count>
- INFO: <count>
- Checks: <n>/17 run — <'all' | list each check not run with a one-line reason>
## Fixes I can apply
If you want, I can apply any of: B1, B2, W1. Which? (or "all", or "none")End with the offer. Wait for the user's choice.
A check you could not perform is listed as not run, never silently omitted — a result you did not observe is "not run", never "passed".
Before delivering the report
- Every finding quotes the offending SQL verbatim with
file:line— no paraphrases survived. - Every BLOCKER/WARN carries its one-sentence incident — anything that couldn't name one got demoted.
- Modified files: every finding sits inside a changed hunk — legacy hits went to the footer note, not the findings.
- The Checks line accounts for all 17 — anything you couldn't run says
not runwith the reason. - The report ends with the fix offer and you have not touched a file.
Any "no" → fix the report, don't ship it.
Examples
Example 1: New stored proc with mixed issues
User: "/sql-review"
Claude:
- Runs
git diff --staged -- '*.sql'andgit diff -- '*.sql'in parallel. - Finds one new file
Stored Procedures/dbo.usp_NewSave.sql. - Spots:
B1—BEGIN CATCHwithout;THROW;(line 88) — swallowing.B2— callsEXEC msdb.dbo.sp_send_dbmailinside that CATCH (line 92) — masking risk.W1— missingSET NOCOUNT ONat line 6.W2—WITH (NOLOCK)on the table being UPDATEd (line 45).I1— missingGRANT EXECUTEat end of file (the repo's other SPs all end with it).
- Reports, then asks: "Want me to fix B1, B2, W1, W2, I1?"
Example 2: Adding a new table — the canonical incident pattern
User: "review the SQL diff before I push"
Claude:
- Spots
Tables/dbo.NewAuditLog.sql(new file) —CREATE TABLEdeclared but no PRIMARY KEY, no CLUSTERED INDEX, no CREATE INDEX. - Flags as
B1— "Heap table will table-scan on every read/UPDATE. Once the table grows past a few hundred thousand rows under concurrent writes, SQL Server's optimizer picks parallel plans and the workers deadlock on heap pages — a recurring production incident pattern." - Fix: "Add
PRIMARY KEY CLUSTERED (id)or a clustered index on the lookup column." - Also flags the SP that populates the new table (
B2— implicit type conversionWHERE recordID = @recordIDwhere the new table'srecordIDisINTbut the param is declaredVARCHAR).
Example 3: Modified existing SP — flag only new badness, not legacy
User: "lint the SQL — just the staged hunks"
Claude:
- The file
usp_UpdateBigOldSP.sqlis modified but huge. The user's diff added a 20-line block that doesUPDATE dbo.Customers SET ...without aWHEREclause. - Only flags the new block's
UPDATEwithoutWHEREasB1— does NOT flag the legacysp_send_dbmailcall elsewhere in the file (which was already there before the user's edit). - Notes in the report footer: "1 pre-existing antipattern observed in this file but outside the diff — flagging suppressed per scope. Full-file audit available on request."
Anti-patterns
- ❌ Trying to parse SQL with a full grammar — use ripgrep on the diff text. The skill is heuristic by design.
- ❌ Flagging every existing antipattern in a modified file. Stay scoped to the diff for modified files; full-file scan only for new files.
- ❌ Editing SQL during the review pass. Report first, always.
- ❌ Running SQL from the diff "to verify" a finding. Static review — evidence is the quoted line, never an execution.
- ❌ Suggesting autofixes for
BLOCKERitems without asking. SQL deploys to production; user confirmation gates the change. - ❌ Listing a
nitwhen there's aBLOCKERnext to it. Lead with severity. - ❌ Hand-wavy findings without
file:line. - ❌ Reporting a raw ripgrep hit without reading the surrounding procedure. A pattern match is a candidate; the proc's full context sets the severity (see Pattern hit ≠ finding).
- ❌ Paraphrasing the offending SQL instead of quoting it verbatim.
WITH (NOLOCK)vsREADPAST,@retryvs@retryCount— the exact token is the finding. - ❌ A
BLOCKERwith no one-sentence production-incident scenario. Can't name the incident? It's aWARN. - ❌ Padding a clean diff with stretched findings. Zero findings is a valid report.
- ❌ Inventing antipatterns not in What to check. This is a fixed catalog — extending it is a
write-a-skillchange, not a per-run improvisation. - ❌ Running on non-SQL files. The skill is
.sql-scoped; mixed diffs route tocode-reviewfor the non-SQL parts. - ✅ Diff-scoped scan for modified files, full scan for new files, findings categorized + cited + offered as fixes.
Notes
- The check catalog is intentionally finite — 17 checks chosen because each one maps to a real production incident class. Don't try to be a full SQL linter (e.g. SQLFluff or sqlcheck) — those exist and run from CI; this skill is the pre-commit human-pass complement focused on bug classes that linters miss.
- For repos that use flat idempotent
Deploy_*.sqlfiles (every deploy is a full re-run), check #14 (DROP/TRUNCATEwithoutIF EXISTS) is critical — the deploy will fail on second run otherwise. For repos that use forward-only migrations, this check is lower priority. - The "broken retry" pattern (check #2) is sneakier than it sounds: a
DECLARE @retry INT = 5;followed bySET @retry = @retry - 1;in CATCH but noWHILEloop looks like deadlock handling. It isn't. Multiple SPs in real codebases have this bug from removed-loop refactors. - If the user wants the broader cleanup (refactor every legacy SP in the repo with one of these issues), recommend opening a tracked task rather than doing it in the current review — these fixes ripple through deploy pipelines and need coordinated review.
- This skill composes downstream with
code-review— on a mixed diff (.cs+.sql), runcode-reviewfor the application code andsql-reviewfor the database changes.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

