{"id":45621303,"url":"https://github.com/JacobArthurs/pgplan","last_synced_at":"2026-03-08T23:01:29.474Z","repository":{"id":335936215,"uuid":"1147458609","full_name":"JacobArthurs/pgplan","owner":"JacobArthurs","description":"Compare and analyze PostgreSQL EXPLAIN plans from the CLI","archived":false,"fork":false,"pushed_at":"2026-03-04T00:00:59.000Z","size":94,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-04T03:56:37.822Z","etag":null,"topics":["cli","cobra","database","developer-tools","golang","postgresql","query-optimization"],"latest_commit_sha":null,"homepage":"","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/JacobArthurs.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-02-01T19:21:05.000Z","updated_at":"2026-03-04T00:01:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JacobArthurs/pgplan","commit_stats":null,"previous_names":["jacobarthurs/pgplan"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/JacobArthurs/pgplan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobArthurs%2Fpgplan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobArthurs%2Fpgplan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobArthurs%2Fpgplan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobArthurs%2Fpgplan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JacobArthurs","download_url":"https://codeload.github.com/JacobArthurs/pgplan/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobArthurs%2Fpgplan/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30276606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T20:45:49.896Z","status":"ssl_error","status_checked_at":"2026-03-08T20:45:49.525Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["cli","cobra","database","developer-tools","golang","postgresql","query-optimization"],"created_at":"2026-02-23T19:00:18.723Z","updated_at":"2026-03-08T23:01:29.458Z","avatar_url":"https://github.com/JacobArthurs.png","language":"Go","readme":"# pgplan\n\n[![GitHub Release](https://img.shields.io/github/v/release/JacobArthurs/pgplan)](https://github.com/JacobArthurs/pgplan/releases/latest)\n[![npm](https://img.shields.io/npm/v/pgplan)](https://www.npmjs.com/package/pgplan)\n[![PyPI](https://img.shields.io/pypi/v/pgplan)](https://pypi.org/project/pgplan/)\n[![Go Reference](https://pkg.go.dev/badge/github.com/jacobarthurs/pgplan.svg)](https://pkg.go.dev/github.com/jacobarthurs/pgplan)\n[![Go Report Card](https://goreportcard.com/badge/github.com/jacobarthurs/pgplan)](https://goreportcard.com/report/github.com/jacobarthurs/pgplan)\n[![ci](https://img.shields.io/github/actions/workflow/status/JacobArthurs/pgplan/ci.yml?branch=main)](https://github.com/JacobArthurs/pgplan/actions/workflows/ci.yml)\n[![go version](https://img.shields.io/github/go-mod/go-version/JacobArthurs/pgplan)](./go.mod)\n[![License](https://img.shields.io/github/license/JacobArthurs/pgplan)](LICENSE)\n\nA command-line tool for analyzing and comparing PostgreSQL query execution plans. Get optimization insights and track performance regressions without leaving your terminal.\n\n## Features\n\n- **Plan Analysis** - Run 15+ intelligent rules against a query plan to surface performance issues with actionable fix suggestions\n- **Plan Comparison** - Semantically diff two plans side-by-side to understand what changed and whether it got better or worse\n- **Flexible Input** - Accept JSON EXPLAIN output, raw SQL files, stdin, or paste plans interactively\n- **Connection Profiles** - Save and manage named PostgreSQL connection strings for quick reuse\n- **Multiple Output Formats** - Human-readable colored terminal output or structured JSON for tooling integration\n\n## Installation\n\n### [PyPI](https://pypi.org/project/pgplan/)\n\n```bash\npip install pgplan\n```\n\n### [npm](https://www.npmjs.com/package/pgplan)\n\n```bash\nnpm i -g pgplan\n```\n\n### [Go](https://pkg.go.dev/github.com/jacobarthurs/pgplan)\n\n```bash\ngo install github.com/jacobarthurs/pgplan@latest\n```\n\n### Binary\n\nDownload the latest release for your platform from the [releases page](https://github.com/JacobArthurs/pgplan/releases/latest).\n\n## Quick Start\n\n```bash\n# Analyze a query plan from a JSON EXPLAIN output\npgplan analyze plan.json\n\n# Analyze by running a SQL file against a database\npgplan analyze query.sql --db postgres://localhost:5432/mydb\n\n# Compare two plans\npgplan compare before.json after.json\n\n# Interactive mode - paste plans or queries directly into the terminal\npgplan analyze\npgplan compare\n```\n\n## Commands\n\n### `pgplan analyze [file]`\n\nAnalyzes a single query plan and returns optimization findings sorted by severity.\n\n**Arguments:**\n\n| Argument | Description |\n| -------- | ----------- |\n| `file` | Path to a `.json` (EXPLAIN output) or `.sql` file. Use `-` for stdin. Omit for interactive mode. |\n\n**Flags:**\n\n| Flag | Description |\n| ---- | ----------- |\n| `-d, --db` | PostgreSQL connection string (required for SQL input) |\n| `-p, --profile` | Named connection profile to use |\n| `-f, --format` | Output format: `text` (default) or `json` |\n\n**Example:**\n\n```bash\npgplan analyze slow-query.sql --profile prod\n```\n\n### `pgplan compare [file1] [file2]`\n\nCompares two query plans and reports on cost, time, row estimate, and buffer differences across every node in the plan tree.\n\n**Arguments:**\n\n| Argument | Description |\n| -------- | ----------- |\n| `file1` | The \"before\" plan. `.json`, `.sql`, `-` for stdin, or omit for interactive. |\n| `file2` | The \"after\" plan. Same input options as `file1`. |\n\n**Flags:**\n\n| Flag | Description |\n| ---- | ----------- |\n| `-d, --db` | PostgreSQL connection string (required for SQL input) |\n| `-p, --profile` | Named connection profile to use |\n| `-f, --format` | Output format: `text` (default) or `json` |\n| `-t, --threshold` | Percent change threshold for significance (default: `5`) |\n\n**Example:**\n\n```bash\npgplan compare before.json after.json --threshold 10\n```\n\n### `pgplan profile \u003csubcommand\u003e`\n\nManages saved PostgreSQL connection profiles stored in `~/.config/pgplan/profiles.yaml`.\n\n| Subcommand | Description |\n| ---------- | ----------- |\n| `list [--show]` | List saved profiles. Pass `--show` to display connection strings. |\n| `add \u003cname\u003e \u003cconn_str\u003e` | Add or update a named profile. |\n| `remove \u003cname\u003e` | Remove a profile. |\n| `default \u003cname\u003e` | Set a profile as the default. |\n| `clear-default` | Clear the default profile. |\n\n**Example:**\n\n```bash\npgplan profile add prod postgres://user:pass@host:5432/mydb\npgplan profile default prod\n\n# Now use it with analyze or compare\npgplan analyze query.sql --profile prod\n```\n\n## Analysis Rules\n\nThe `analyze` command applies the following rules to identify performance issues. Each finding includes a severity level and an actionable suggestion.\n\n| Severity | Rule | Description |\n| -------- | ---- | ----------- |\n| Critical | Sort Spill to Disk | Sort operation exceeded `work_mem` and spilled to disk |\n| Warning | Hash Spill to Disk | Hash table exceeded `work_mem` |\n| Warning | Temp Block I/O | Plan is reading/writing temporary blocks |\n| Warning | Seq Scan in Join | Sequential scan used inside a join against a smaller set |\n| Warning | Seq Scan with Filter | Standalone sequential scan filtering a large number of rows |\n| Warning | Index Scan Filter Inefficiency | Index scan is fetching many rows then discarding most via filter |\n| Warning | Bitmap Heap Recheck | Lossy bitmap scan rechecking conditions (bitmap exceeded `work_mem`) |\n| Warning | Nested Loop High Loops | Nested loop executing 1,000+ iterations |\n| Warning | Correlated Subplan | Subplan re-executing on every outer row |\n| Warning | Worker Launch Mismatch | Fewer parallel workers launched than planned |\n| Warning | Parallel Overhead | Parallel execution is slower than the serial estimate |\n| Warning | Large Join Filter Removal | Join filter is discarding a large percentage of rows |\n| Warning | Excessive Materialization | Materialize node looping many times |\n| Info | Low Selectivity Index Scan | Index scan is returning most of the table |\n| Info | Wide Row Output | Query is selecting more columns than necessary |\n\n## Comparison Output\n\nThe `compare` command produces a structured diff of two plans including:\n\n- **Summary** - Overall cost, execution time, and buffer changes with directional indicators\n- **Node Details** - Per-node breakdown of metric changes (cost, rows, loops, buffers, filters, indexes)\n- **Verdict** - A final assessment such as \"faster and cheaper\" or \"slower but cheaper\"\n\nChanges below the significance threshold (default 5%) are filtered out to reduce noise.\n\n## Output Formats\n\n### Text (default)\n\nColored terminal output with severity-coded findings and directional change indicators. Designed for quick human review.\n\n### JSON\n\nStructured output suitable for piping into other tools, CI systems, or dashboards. Includes all metrics, findings, and comparison deltas.\n\n```bash\npgplan analyze plan.json --format json | jq '.findings[] | select(.severity == \"critical\")'\n```\n\n## Configuration\n\n### Connection Profiles\n\nProfiles are stored in a YAML configuration file at the platform-appropriate config directory:\n\n- **Linux/macOS:** `~/.config/pgplan/profiles.yaml`\n- **Windows:** `%APPDATA%\\pgplan\\profiles.yaml`\n\n```yaml\ndefault: prod\nprofiles:\n  - name: prod\n    conn_str: postgres://user:pass@host:5432/production\n  - name: dev\n    conn_str: postgres://localhost:5432/development\n```\n\nUse `--profile \u003cname\u003e` with any command, or set a default to skip the flag entirely. The `--db` and `--profile` flags are mutually exclusive.\n\n## Contributing\n\nContributions are welcome! To get started:\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b my-new-feature`)\n3. Open a pull request\n\nCI will automatically run tests and linting on your PR.\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE).\n","funding_links":[],"categories":["CLI"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJacobArthurs%2Fpgplan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJacobArthurs%2Fpgplan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJacobArthurs%2Fpgplan/lists"}