{"id":47183118,"url":"https://github.com/erikdarlingdata/performancestudio","last_synced_at":"2026-04-24T22:01:12.615Z","repository":{"id":342145609,"uuid":"1173009661","full_name":"erikdarlingdata/PerformanceStudio","owner":"erikdarlingdata","description":"Free, open-source SQL Server execution plan analyzer — cross-platform GUI + CLI with 30 analysis rules, missing index detection, SSMS extension. Built-in MCP server for AI-assisted plan review.","archived":false,"fork":false,"pushed_at":"2026-04-23T15:27:42.000Z","size":2159,"stargazers_count":173,"open_issues_count":2,"forks_count":28,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-04-23T17:22:21.798Z","etag":null,"topics":["avalonia","cli","cross-platform","database-performance","dba-tools","dotnet","execution-plan","mcp-server","model-context-protocol","query-optimization","query-performance","query-plan","query-store","query-tuning","sql-plan-analyzer","sql-server","sql-server-management","sqlplan","ssms-extension"],"latest_commit_sha":null,"homepage":"https://erikdarling.com","language":"C#","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/erikdarlingdata.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","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},"funding":{"github":"erikdarlingdata"}},"created_at":"2026-03-04T23:17:28.000Z","updated_at":"2026-04-23T15:27:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/erikdarlingdata/PerformanceStudio","commit_stats":null,"previous_names":["erikdarlingdata/performancestudio"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/erikdarlingdata/PerformanceStudio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikdarlingdata%2FPerformanceStudio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikdarlingdata%2FPerformanceStudio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikdarlingdata%2FPerformanceStudio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikdarlingdata%2FPerformanceStudio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erikdarlingdata","download_url":"https://codeload.github.com/erikdarlingdata/PerformanceStudio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erikdarlingdata%2FPerformanceStudio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32242315,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T13:21:15.438Z","status":"ssl_error","status_checked_at":"2026-04-24T13:21:15.005Z","response_time":64,"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":["avalonia","cli","cross-platform","database-performance","dba-tools","dotnet","execution-plan","mcp-server","model-context-protocol","query-optimization","query-performance","query-plan","query-store","query-tuning","sql-plan-analyzer","sql-server","sql-server-management","sqlplan","ssms-extension"],"created_at":"2026-03-13T08:05:35.781Z","updated_at":"2026-04-24T22:01:12.602Z","avatar_url":"https://github.com/erikdarlingdata.png","language":"C#","readme":"# Performance Studio\r\n\r\n\u003cp align=\"center\"\u003e\r\n  \u003ca href=\"https://github.com/erikdarlingdata/PerformanceStudio/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/erikdarlingdata/PerformanceStudio?style=for-the-badge\u0026logo=github\u0026color=gold\u0026logoColor=black\" alt=\"GitHub Stars\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://github.com/erikdarlingdata/PerformanceStudio/network/members\"\u003e\u003cimg src=\"https://img.shields.io/github/forks/erikdarlingdata/PerformanceStudio?style=for-the-badge\u0026logo=github\" alt=\"GitHub Forks\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://github.com/erikdarlingdata/PerformanceStudio/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/erikdarlingdata/PerformanceStudio?style=for-the-badge\" alt=\"License: MIT\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://github.com/erikdarlingdata/PerformanceStudio/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/erikdarlingdata/PerformanceStudio?style=for-the-badge\" alt=\"Latest Release\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://github.com/erikdarlingdata/PerformanceStudio/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/erikdarlingdata/PerformanceStudio?style=for-the-badge\" alt=\"Open Issues\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://github.com/erikdarlingdata/PerformanceStudio/commits/main\"\u003e\u003cimg src=\"https://img.shields.io/github/last-commit/erikdarlingdata/PerformanceStudio?style=for-the-badge\" alt=\"Last Commit\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://github.com/erikdarlingdata/PerformanceStudio/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/erikdarlingdata/PerformanceStudio/ci.yml?style=for-the-badge\u0026label=CI\" alt=\"CI\"\u003e\u003c/a\u003e\r\n\u003c/p\u003e\r\n\u003cp align=\"center\"\u003e\r\n  \u003ca href=\"https://x.com/erikdarlingdata\"\u003e\u003cimg src=\"https://img.shields.io/badge/Follow_%40ErikDarlingData-black?style=for-the-badge\u0026logo=x\u0026logoColor=white\" alt=\"Follow @ErikDarlingData on X\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://www.youtube.com/@ErikDarlingData\"\u003e\u003cimg src=\"https://img.shields.io/badge/YouTube-Subscribe-red?style=for-the-badge\u0026logo=youtube\u0026logoColor=white\" alt=\"YouTube Subscribe\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://www.linkedin.com/in/erik-darling-data/\"\u003e\u003cimg src=\"https://img.shields.io/badge/LinkedIn-Connect-0077B5?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white\" alt=\"LinkedIn Connect\"\u003e\u003c/a\u003e\r\n  \u003ca href=\"https://erikdarling.com\"\u003e\u003cimg src=\"https://img.shields.io/badge/Blog-erikdarling.com-FF6B35?style=for-the-badge\u0026logo=wordpress\u0026logoColor=white\" alt=\"Blog\"\u003e\u003c/a\u003e\r\n\u003c/p\u003e\r\n\r\nA cross-platform SQL Server execution plan analyzer with built-in MCP server for AI-assisted analysis. Parses `.sqlplan` XML, identifies performance problems, suggests missing indexes, and provides actionable warnings — from the command line or a desktop GUI.\r\n\r\nBuilt for developers and DBAs who want fast, automated plan analysis without clicking through SSMS.\r\n\r\n## Screenshots\r\n\r\n### Query Editor\r\nWrite queries with syntax highlighting and SQL keyword completion, connect to any SQL Server, and capture plans with one click.\r\n\r\n![Query Editor](screenshots/Query%20Editor.png)\r\n\r\n### Actual Execution Plan with Plan Insights\r\nGraphical plan tree with SSMS-style operator icons, cost percentages, row counts, and warning badges. The Plan Insights panel shows runtime summary, missing indexes, parameters, and wait stats at a glance.\r\n\r\n![Actual Execution Plan](screenshots/Actual%20Execution%20Plan.png)\r\n\r\n### Multi-Statement Navigation\r\nNavigate stored procedures and batches with multiple statements. Click any statement in the grid to jump to its plan. Plan Insights shows parameters with compiled vs runtime values.\r\n\r\n![Navigate Stored Procedure Statements and Plans](screenshots/Navigate%20Stored%20Procedure%20Statements%20and%20Plans.png)\r\n\r\n### Operator Tooltip and Properties\r\nHover over any operator for a detailed tooltip with costs, rows, I/O, timing, parallelism, and warnings. Click to open the full properties panel with per-thread timing, predicates, and more.\r\n\r\n![Operator Tooltip](screenshots/Actual%20Execution%20Plan%20With%20Warning%20Tool%20Tip.png)\r\n\r\n![Operator Properties](screenshots/Operator%20Properties.png)\r\n\r\n### Advice for Humans\r\nOne-click text report with server context, warnings, wait stats, and expensive operators — ready to read or share.\r\n\r\n![Advice for Humans](screenshots/Advice%20For%20Humans.png)\r\n\r\n### Plan Comparison\r\nSide-by-side comparison of two plans showing cost, runtime, I/O, memory, and wait stat differences.\r\n\r\n![Plan Comparison](screenshots/Plan%20Comparison.png)\r\n\r\n### Query Store Integration\r\nFetch top queries by CPU, duration, logical reads, physical reads, writes, memory, or executions from Query Store and load their plans directly into the analyzer.\r\n\r\n![Query Store Integration](screenshots/Query%20Store%20Integration.png)\r\n\r\n### MCP Integration\r\nAsk Claude Code to analyze loaded plans, identify warnings, suggest indexes, and compare plans — all through the built-in MCP server.\r\n\r\n![MCP Integration](screenshots/MCP%20Integration.png)\r\n\r\n## What It Does\r\n\r\nFeed it a query plan and it tells you what's wrong:\r\n\r\n- **Large memory grants** — flags queries hoarding memory they don't use\r\n- **Row estimate mismatches** — finds operators where estimates are 10x+ off from actuals\r\n- **Missing indexes** — extracts SQL Server's index suggestions with ready-to-run CREATE statements\r\n- **Hash, sort, and exchange spills** — identifies operators spilling to TempDB with severity based on volume\r\n- **Parallel skew** — detects threads doing all the work while others sit idle\r\n- **Scan predicates** — warns when scans filter rows with residual predicates\r\n- **Key and RID lookups** — flags lookups back to the base table, distinguishes heaps from clustered indexes\r\n- **Late filters** — finds Filter operators discarding rows deep in the plan\r\n- **Nested loop concerns** — flags high-execution nested loops that might be better as hash joins\r\n- **Parameter sniffing** — compares compiled vs runtime parameter values\r\n- **Scalar UDFs** — warns about T-SQL and CLR scalar functions in execution paths\r\n- **Implicit conversions** — detects type mismatches, upgrades severity when a seek plan is prevented\r\n- **Anti-patterns** — OPTIMIZE FOR UNKNOWN, NOT IN with nullable columns, leading wildcards, function-wrapped predicates, and more\r\n\r\nEach warning includes severity (Info, Warning, or Critical), the operator node ID, and enough context to act on immediately.\r\n\r\n## Prerequisites\r\n\r\n- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) (required to build and run)\r\n- SQL Server instance (optional — only needed for live plan capture; file analysis works without one)\r\n- Docker (optional — macOS/Linux users can run SQL Server locally via Docker)\r\n\r\n## Download\r\n\r\nPre-built binaries are available on the [Releases](https://github.com/erikdarlingdata/PerformanceStudio/releases/latest) page:\r\n\r\n| Platform | Download |\r\n|----------|----------|\r\n| Windows (x64) | [PerformanceStudio-win-x64.zip](https://github.com/erikdarlingdata/PerformanceStudio/releases/latest/download/PerformanceStudio-win-x64.zip) |\r\n| macOS (Apple Silicon) | [PerformanceStudio-osx-arm64.zip](https://github.com/erikdarlingdata/PerformanceStudio/releases/latest/download/PerformanceStudio-osx-arm64.zip) |\r\n| macOS (Intel) | [PerformanceStudio-osx-x64.zip](https://github.com/erikdarlingdata/PerformanceStudio/releases/latest/download/PerformanceStudio-osx-x64.zip) |\r\n| Linux (x64) | [PerformanceStudio-linux-x64.zip](https://github.com/erikdarlingdata/PerformanceStudio/releases/latest/download/PerformanceStudio-linux-x64.zip) |\r\n\r\nThese are self-contained — no .NET SDK required. Extract the zip and run.\r\n\r\n**macOS note:** macOS may block the app because it isn't signed with an Apple Developer certificate. If you see a warning that the app \"can't be opened,\" run this after extracting:\r\n\r\n```bash\r\nxattr -cr PerformanceStudio.app\r\n```\r\n\r\nThen open the app normally.\r\n\r\n## Build from Source\r\n\r\nClone and build:\r\n\r\n```bash\r\ngit clone https://github.com/erikdarlingdata/PerformanceStudio.git\r\ncd PerformanceStudio\r\ndotnet build\r\n```\r\n\r\nTo verify the build:\r\n\r\n```bash\r\ndotnet test tests/PlanViewer.Core.Tests    # 37 tests should pass\r\ndotnet run --project src/PlanViewer.Cli -- analyze --help\r\n```\r\n\r\n## Quick Start\r\n\r\n### Analyze an existing .sqlplan file\r\n\r\nIf you already have a `.sqlplan` file (saved from SSMS, Azure Data Studio, or another tool):\r\n\r\n```bash\r\n# JSON output (default) — full operator tree, suitable for automation\r\nplanview analyze my_query.sqlplan\r\n\r\n# Human-readable text output\r\nplanview analyze my_query.sqlplan --output text\r\n\r\n# Text output, warnings and missing indexes only (skip operator tree)\r\nplanview analyze my_query.sqlplan --output text --warnings-only\r\n```\r\n\r\n### Capture and analyze plans from a live server\r\n\r\nConnect to a SQL Server instance, run queries, and capture their execution plans automatically.\r\n\r\n**Quickest way** — pass credentials directly:\r\n\r\n```bash\r\n# Capture an actual execution plan (the query WILL run)\r\nplanview analyze --server sql2022 --database AdventureWorks \\\r\n    --login sa --password YourPassword \\\r\n    --query \"SELECT * FROM Sales.SalesOrderHeader WHERE OrderDate \u003e '2024-01-01'\" \\\r\n    --trust-cert --output-dir ./results/\r\n\r\n# Capture an estimated plan (safe for production — query is NOT executed)\r\nplanview analyze --server sql2022 --database AdventureWorks \\\r\n    --login sa --password YourPassword \\\r\n    --query \"SELECT * FROM Sales.SalesOrderHeader\" \\\r\n    --estimated --trust-cert --output-dir ./results/\r\n```\r\n\r\n**Using a .env file** — drop a `.env` in your working directory to avoid repeating connection details:\r\n\r\n```bash\r\n# .env\r\nPLANVIEW_SERVER=sql2022\r\nPLANVIEW_DATABASE=AdventureWorks\r\nPLANVIEW_LOGIN=sa\r\nPLANVIEW_PASSWORD=YourPassword\r\nPLANVIEW_TRUST_CERT=true\r\n```\r\n\r\nThen just run:\r\n\r\n```bash\r\nplanview analyze --query \"SELECT * FROM Sales.SalesOrderHeader\"\r\nplanview analyze ./queries/ --output-dir ./results/\r\n```\r\n\r\nCLI arguments override `.env` values when both are provided.\r\n\r\n**Using the credential store** — for longer-term use, store credentials in your OS keychain:\r\n\r\n```bash\r\n# Store credentials (once per server)\r\nplanview credential add sql2022 --user sa\r\n# You'll be prompted for the password — it's stored in your OS credential store\r\n\r\n# Now connect without --login/--password\r\nplanview analyze --server sql2022 --database AdventureWorks \\\r\n    --query \"SELECT * FROM Sales.SalesOrderHeader\" \\\r\n    --trust-cert --output-dir ./results/\r\n```\r\n\r\n**Batch processing** a folder of .sql files:\r\n\r\n```bash\r\nplanview analyze ./queries/ --server sql2022 --database StackOverflow2013 \\\r\n    --login sa --password YourPassword \\\r\n    --trust-cert --output-dir ./results/\r\n```\r\n\r\nBatch mode produces three files per query:\r\n- `query_name.sqlplan` — the raw execution plan XML (openable in SSMS or the Performance Studio GUI)\r\n- `query_name.analysis.json` — structured analysis with warnings, missing indexes, and operator tree\r\n- `query_name.analysis.txt` — human-readable text report\r\n\r\n### Manage credentials\r\n\r\n```bash\r\nplanview credential add my-server --user sa        # prompts for password\r\nplanview credential add my-server --user sa -p pwd  # non-interactive\r\nplanview credential list                            # show stored credentials\r\nplanview credential remove my-server                # delete credential\r\n```\r\n\r\nCredentials are stored in the OS credential store — Windows Credential Manager on Windows, Apple Keychain on macOS. Nothing is written to disk in plaintext.\r\n\r\n## Example Output\r\n\r\nThese examples were generated against StackOverflow2013 on SQL Server 2022. Source queries are in [`examples/queries/`](examples/queries/), plans and analysis in [`examples/output/`](examples/output/).\r\n\r\n### Text output (`--output text`)\r\n\r\n```\r\nPlan: 04_comment_heavy_posts.sqlplan\r\nSQL Server: 1.564 (build 16.0.4222.2)\r\nStatements: 1\r\n\r\n--- Statement 1: SELECT ---\r\n  Query: SELECT p.Id, p.Title, p.Score, COUNT(c.Id) AS CommentCount\r\n         FROM dbo.Posts AS p JOIN dbo.Comments AS c ON c.PostId = p.Id\r\n         WHERE p.PostTypeId = 1 GROUP BY p.Id, p.Title, p.Score\r\n         HAVING COUNT(c.Id) \u003e 20 ORDER BY CommentCount DESC\r\n  Estimated cost: 4069.8700\r\n  DOP: 8\r\n  Runtime: 4551ms elapsed, 15049ms CPU\r\n  Memory grant: 8,022,664 KB granted, 2,514,944 KB used\r\n\r\n  Warnings:\r\n    [Critical] Large Memory Grant: Query granted 7835 MB of memory.\r\n\r\n  Operator warnings:\r\n    [Critical] Parallelism (Node 0): Estimated 1 rows, actual 2,889 (2889x underestimated).\r\n    [Critical] Sort (Node 1): Estimated 1 rows, actual 2,889 (2889x underestimated).\r\n    [Warning] Sort (Node 1): Thread 1 processed 100% of rows. Work is heavily skewed.\r\n    [Warning] Filter (Node 2): Filter discards rows late in the plan.\r\n\r\n  Missing indexes:\r\n    StackOverflow2013.dbo.Posts (impact: 74%)\r\n      CREATE NONCLUSTERED INDEX [IX_Posts_PostTypeId]\r\n      ON dbo.Posts (PostTypeId) INCLUDE (Score, Title)\r\n    StackOverflow2013.dbo.Comments (impact: 19%)\r\n      CREATE NONCLUSTERED INDEX [IX_Comments_PostId]\r\n      ON dbo.Comments (PostId)\r\n\r\n=== Summary ===\r\n  Warnings: 8 (4 critical)\r\n  Missing indexes: 2\r\n  Actual stats: yes\r\n  Warning types: Filter Operator, Large Memory Grant, Parallel Skew,\r\n                 Row Estimate Mismatch, Scan With Predicate\r\n```\r\n\r\n### JSON output (default)\r\n\r\nThe default JSON output includes the full operator tree, making it suitable for CI pipelines, LLM consumption, or further processing. See [`examples/output/`](examples/output/) for complete examples.\r\n\r\n### Batch processing\r\n\r\n```\r\n$ planview analyze ./examples/queries/ --server sql2022 \\\r\n    --database StackOverflow2013 --trust-cert --output-dir ./results/\r\n\r\nCapturing actual plans from sql2022/StackOverflow2013\r\n\r\n[1/5] 01_top_users_by_posts ... OK (1.8s)\r\n[2/5] 02_recent_questions ... OK (0.8s)\r\n[3/5] 03_unanswered_high_score ... OK (0.7s)\r\n[4/5] 04_comment_heavy_posts ... OK (4.7s)\r\n[5/5] 05_user_vote_summary ... OK (4.3s)\r\n\r\nProcessed 5 files: 5 succeeded, 0 failed\r\nOutput: ./results/\r\n```\r\n\r\n## Desktop GUI\r\n\r\nThe Avalonia-based GUI renders execution plans visually with the same operator icons as SSMS. Open `.sqlplan` files via File \u003e Open or drag-and-drop.\r\n\r\nFeatures:\r\n- Graphical plan tree with cost percentages and row counts\r\n- Warning badge on root node showing total warning count\r\n- Plan Insights panel — three-column view with runtime summary, missing indexes, and wait stats visualization\r\n- Zoom and pan (mouse wheel + middle-click drag)\r\n- Click any operator to see full properties (30 sections)\r\n- Statement grid with sortable columns (cost, rows, DOP, warnings)\r\n- Tooltips on hover with key operator metrics\r\n- **Advice for Humans** — one-click text analysis report you can read or share\r\n- **Advice for Robots** — one-click JSON export designed for LLMs and automation\r\n- **Plan Comparison** — compare two plans side-by-side (cost, runtime, I/O, memory, wait stats)\r\n- **Copy Repro Script** — extracts parameters, SET options, and query text into a runnable `sp_executesql` script\r\n- **Get Actual Plan** — connect to a server and re-execute the query to capture runtime stats\r\n- **Query Store Analysis** — connect to a server and analyze top queries by CPU, duration, or reads\r\n- **MCP Server** — built-in Model Context Protocol server for AI-assisted plan analysis (opt-in)\r\n- Dark theme\r\n\r\n```bash\r\ndotnet run --project src/PlanViewer.App\r\n```\r\n\r\n## SSMS Extension\r\n\r\nA VSIX extension that adds **\"Open in Performance Studio\"** to the execution plan right-click context menu in SSMS 18-22.\r\n\r\n### How it works\r\n\r\n1. Right-click on any execution plan in SSMS\r\n2. Click \"Open in Performance Studio\"\r\n3. The extension extracts the plan XML via reflection and saves it to a temp file\r\n4. Performance Studio opens with the plan loaded\r\n\r\n### Installation\r\n\r\n1. Download `PlanViewer.Ssms.vsix` and `InstallSsmsExtension.exe` from the [v0.7.0 release](https://github.com/erikdarlingdata/PerformanceStudio/releases/tag/v0.7.0) (SSMS extension is not yet included in automated builds)\r\n2. Place them in the same folder\r\n3. Double-click `InstallSsmsExtension.exe` and approve the UAC prompt\r\n4. The installer auto-detects SSMS 21 and/or SSMS 22 and installs into both\r\n5. Restart SSMS to activate the extension\r\n\r\n### First run\r\n\r\nOn first use, if Performance Studio isn't found automatically, the extension will prompt you to locate `PlanViewer.App.exe`. The path is saved to the registry (`HKCU\\SOFTWARE\\DarlingData\\SQLPerformanceStudio\\InstallPath`) so you only need to do this once.\r\n\r\nThe extension searches for the app in this order:\r\n1. Registry key (set automatically after first browse)\r\n2. System PATH\r\n3. Common install locations (`%LOCALAPPDATA%\\Programs\\SQLPerformanceStudio\\`, `Program Files`, etc.)\r\n\r\n## MCP Server (LLM Integration)\r\n\r\nThe desktop GUI includes an embedded [Model Context Protocol](https://modelcontextprotocol.io) server that exposes loaded execution plans and Query Store data to LLM clients like Claude Code and Cursor.\r\n\r\n### Setup\r\n\r\n1. Enable the MCP server in `~/.planview/settings.json`:\r\n\r\n```json\r\n{\r\n  \"mcp_enabled\": true,\r\n  \"mcp_port\": 5152\r\n}\r\n```\r\n\r\n2. Register with Claude Code:\r\n\r\n```\r\nclaude mcp add --transport http --scope user performance-studio http://localhost:5152/\r\n```\r\n\r\n3. Open a new Claude Code session and ask questions like:\r\n   - \"What plans are loaded in the application?\"\r\n   - \"Analyze the execution plan and tell me what's wrong\"\r\n   - \"Are there any missing index suggestions?\"\r\n   - \"Compare these two plans — which is better?\"\r\n   - \"Fetch the top 10 queries by CPU from Query Store\"\r\n\r\n### Available Tools\r\n\r\n13 tools for plan analysis and Query Store data:\r\n\r\n| Category | Tools |\r\n|---|---|\r\n| Discovery | `list_plans`, `get_connections` |\r\n| Plan Analysis | `analyze_plan`, `get_plan_summary`, `get_plan_warnings`, `get_missing_indexes`, `get_plan_parameters`, `get_expensive_operators`, `get_plan_xml`, `compare_plans`, `get_repro_script` |\r\n| Query Store | `check_query_store`, `get_query_store_top` |\r\n\r\nPlan analysis tools work on plans loaded in the app (via file open, paste, query execution, or Query Store fetch). Query Store tools use a built-in read-only DMV query — no arbitrary SQL can be executed.\r\n\r\nThe MCP server binds to `localhost` only and does not accept remote connections. Disabled by default.\r\n\r\n## Project Structure\r\n\r\n```\r\nPerformanceStudio/\r\n├── src/\r\n│   ├── PlanViewer.Core/       # Analysis engine (parser, 30 rules, layout)\r\n│   ├── PlanViewer.App/        # Avalonia desktop GUI\r\n│   ├── PlanViewer.Cli/        # CLI tool (planview command)\r\n│   ├── PlanViewer.Ssms/       # SSMS extension (.vsix, .NET Framework 4.7.2)\r\n│   └── PlanViewer.Ssms.Installer/ # SSMS extension installer (auto-detects SSMS 21/22)\r\n├── tests/\r\n│   └── PlanViewer.Core.Tests/ # 37 xUnit tests with real .sqlplan fixtures\r\n├── examples/\r\n│   ├── plans/                 # Sample .sqlplan files for testing\r\n│   ├── queries/               # Sample .sql files\r\n│   └── output/                # Generated .sqlplan, .analysis.json, .txt\r\n└── PlanViewer.sln\r\n```\r\n\r\n## CLI Reference\r\n\r\n### `planview analyze`\r\n\r\n```\r\nUsage: planview analyze [\u003cfile\u003e] [options]\r\n\r\nArguments:\r\n  \u003cfile\u003e    .sqlplan file, .sql file, or directory of .sql files\r\n\r\nOptions:\r\n  --stdin                    Read plan XML from stdin\r\n  -o, --output \u003cformat\u003e      json (default) or text\r\n  --compact                  Compact JSON (no indentation)\r\n  --warnings-only            Skip operator tree, only output warnings and indexes\r\n  -s, --server \u003cname\u003e        SQL Server name (matches credential store key)\r\n  -d, --database \u003cname\u003e      Database context for execution\r\n  -q, --query \u003csql\u003e          Inline SQL text to execute\r\n  --output-dir \u003cpath\u003e        Directory for output files\r\n  --estimated                Estimated plan only (query is NOT executed)\r\n  --auth \u003ctype\u003e              windows, sql, or entra (default: auto-detect)\r\n  --trust-cert               Trust server certificate\r\n  --timeout \u003cseconds\u003e        Query timeout (default: 60)\r\n  --login \u003cname\u003e             SQL Server login (bypasses credential store)\r\n  --password \u003cpassword\u003e      SQL Server password (bypasses credential store)\r\n```\r\n\r\n### `planview credential`\r\n\r\n```\r\nplanview credential add \u003cserver\u003e --user \u003cuser\u003e [-p \u003cpassword\u003e]\r\nplanview credential list\r\nplanview credential remove \u003cserver\u003e\r\n```\r\n\r\n## Authentication\r\n\r\nThere are three ways to authenticate, in order of precedence:\r\n\r\n1. **`--login` / `--password`** — passed directly on the command line (or via `.env` file). Simplest for dev/test.\r\n2. **Credential store** — stored in Windows Credential Manager or Apple Keychain via `planview credential add`. Best for repeated use.\r\n3. **Windows Authentication** — used automatically when no SQL credentials are found. Requires a valid Kerberos ticket.\r\n\r\nOverride the auto-detection with `--auth windows`, `--auth sql`, or `--auth entra`.\r\n\r\n**macOS note:** Windows Authentication does not work on macOS (no Kerberos ticket by default). Use `--login`/`--password`, the credential store, or `--auth entra` instead.\r\n\r\n## Platform Support\r\n\r\n| Platform | GUI | CLI | Credential Store |\r\n|----------|-----|-----|-----------------|\r\n| Windows  | Yes | Yes | Windows Credential Manager |\r\n| macOS    | Yes | Yes | Apple Keychain |\r\n| Linux    | Yes | Yes | Not yet (file analysis works) |\r\n\r\n### macOS: SQL Server via Docker\r\n\r\nmacOS users need a SQL Server instance to use the live capture features. The easiest path is Docker:\r\n\r\n```bash\r\ndocker run -e \"ACCEPT_EULA=Y\" -e \"MSSQL_SA_PASSWORD=YourPassword123\" \\\r\n    -p 1433:1433 --name sql_server \\\r\n    -d mcr.microsoft.com/mssql/server:2022-latest\r\n\r\n# Store the credential\r\nplanview credential add localhost --user sa -p YourPassword123\r\n\r\n# Test connectivity\r\nplanview analyze --server localhost --database master --trust-cert \\\r\n    --query \"SELECT @@VERSION\" -o text\r\n```\r\n\r\nAlways use `--trust-cert` with local Docker instances.\r\n\r\n## Analysis Rules\r\n\r\nThe analyzer runs 30 rules against each plan, covering:\r\n\r\n| Category | Rules |\r\n|----------|-------|\r\n| Memory | Large grants, grant vs used ratio, spills to TempDB (including exchange spills) |\r\n| Estimates | Row estimate mismatches (10x+), zero-row actuals, row goals |\r\n| Indexes | Missing index suggestions, key lookups, RID lookups, scan with residual predicates |\r\n| Parallelism | Serial plan reasons, thread skew, ineffective parallelism, DOP reporting |\r\n| Joins | Nested loop high executions, many-to-many merge join worktables |\r\n| Filters | Late filter operators with impact quantification, function-wrapped predicates |\r\n| Functions | Scalar UDF detection (T-SQL and CLR), UDF timing |\r\n| Parameters | Compiled vs runtime values, sniffing issue detection |\r\n| Patterns | Leading wildcards, implicit conversions (with seek plan severity upgrade), OPTIMIZE FOR UNKNOWN, NOT IN with nullable columns, OR expansion, CASE in predicates |\r\n| Compilation | High compile CPU, compile memory exceeded, early abort |\r\n| Objects | Table variables, table-valued functions, CTE multiple references, eager index spools, lazy spools, row count spools |\r\n| Operators | Operator self-time calculation with per-thread awareness for parallel plans |\r\n\r\nRules can be disabled or have their severity overridden via a `.planview.json` config file. See the `--config` option.\r\n\r\n## Sponsors\r\n\r\n\u003ctable\u003e\r\n  \u003ctr\u003e\r\n    \u003ctd\u003e\u003ca href=\"https://signpath.io\"\u003e\u003cimg src=\"docs/signpath_logo.svg\" alt=\"SignPath\" width=\"40\"\u003e\u003c/a\u003e\u003c/td\u003e\r\n    \u003ctd\u003eFree code signing on Windows provided by \u003ca href=\"https://signpath.io\"\u003eSignPath.io\u003c/a\u003e, certificate by \u003ca href=\"https://signpath.org\"\u003eSignPath Foundation\u003c/a\u003e\u003c/td\u003e\r\n  \u003c/tr\u003e\r\n\u003c/table\u003e\r\n\r\n## License\r\n\r\nMIT — see [LICENSE](LICENSE).\r\n\r\nExecution plan operator icons are from Microsoft's [vscode-mssql](https://github.com/microsoft/vscode-mssql) extension (MIT). See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) for details.\r\n","funding_links":["https://github.com/sponsors/erikdarlingdata"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferikdarlingdata%2Fperformancestudio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferikdarlingdata%2Fperformancestudio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferikdarlingdata%2Fperformancestudio/lists"}