Skip to content

feat: smart Postgres detection and context-aware installer menu#127

Open
AntTheLimey wants to merge 24 commits into
mainfrom
feat/smart-postgres-detection
Open

feat: smart Postgres detection and context-aware installer menu#127
AntTheLimey wants to merge 24 commits into
mainfrom
feat/smart-postgres-detection

Conversation

@AntTheLimey
Copy link
Copy Markdown
Member

@AntTheLimey AntTheLimey commented Apr 18, 2026

Summary

  • Adds Postgres instance discovery on startup (ports 5432-5436)
    using pg_isready with platform-native fallbacks (lsof,
    ss, Get-NetTCPConnection).

  • Replaces the static two-option menu with a context-aware menu
    that adapts based on detected instances: connect to existing,
    start demo on a non-conflicting port, or enter details manually.

  • Adds a connect-to-existing flow with passwordless auth attempt,
    credential prompting, and automatic database listing.

  • Adds --detect (bash) / -Detect (PowerShell) flag for
    non-interactive auto-connection to detected instances.

  • Detects previous installations and offers to update the binary
    or reconfigure the database connection instead of re-running
    the full install flow.

  • Fixes Windows port detection (TcpListener ->
    Get-NetTCPConnection) to reliably detect Postgres on all
    network addresses.

  • Graceful four-tier degradation when pg_isready or psql
    are not available.

  • Adds a README for the try-it-now installer scripts documenting
    flags, detection behavior, and install location.

Hardening (review rounds)

  • Gate config writes on DB_CONFIGURED/DbConfigured so placeholder
    values are never written to Claude Code or Claude Desktop configs.
  • Exit/return when user declines an update instead of falling
    through to the reconfigure block.
  • Suppress update summary when explicit reconfigure follows to
    avoid contradictory double summaries.
  • Use preloaded DB_HOST/DB_PORT as manual entry defaults so
    detected values survive the prompt flow.
  • Null-safe .version file reading (PS1) to avoid crash on empty
    file.
  • Exact process name matching in stop_stale_processes (pgrep -x /
    Get-Process -Name) to avoid false positives.
  • Back up invalid Claude Desktop JSON in PS1 instead of silently
    skipping the config write (matches bash behavior).
  • Add empty-instance guard in PS1 Connect-ExistingInstance matching
    bash's early return when no instances match.
  • Align update prompt default to "y" in bash (PS1 already
    defaulted to "y").
  • Add confirmed/unconfirmed label on port display in PS1 to match
    bash's "(PostgreSQL)" vs "(service)" output.
  • Rename Detect-PostgresInstances to Find-PostgresInstance
    (PSScriptAnalyzer approved verb).

Files changed

  • examples/claude-try-it/install.sh -- instance detection,
    context-aware menu, connect-to-existing flow, existing-install
    detection, --detect flag, hardening fixes
  • examples/claude-try-it/install.ps1 -- same changes plus
    Find-FreePort fix and PS1-specific hardening
  • examples/claude-try-it/README.md -- new; documents flags,
    detection behavior, and install location
  • docs/changelog.md -- Added/Fixed entries for installer changes

Test plan

  • Run install.sh on macOS with Postgres on 5432 -- verify
    detection, context-aware menu, database listing
  • Run install.sh on macOS with no Postgres -- verify fallback
    to original 2-option menu
  • Run install.sh --detect -- verify auto-connection
  • Run install.sh --detect --db-name=nonexistent -- verify
    error message about database not found
  • Run install.ps1 on Windows with Postgres on 5432 -- verify
    detection and Find-FreePort picks a non-conflicting port
  • Run install.ps1 -Detect on Windows -- verify auto-connection
  • Run install.sh without pg_isready installed -- verify
    Tier 3 fallback (port check only, no confirmation)
  • Run install.sh without pg_isready or psql -- verify
    Tier 4 fallback (original menu)
  • Verify demo container starts on free port when 5432 is taken
  • Run installer over existing install (same version) -- verify
    "already up to date" flow with reconfigure prompt
  • Run installer over existing install (older version) -- verify
    update prompt, then reconfigure if flags provided
  • Decline update prompt (press Enter or "n") -- verify clean
    exit with no database prompts
  • Run install.sh --demo over existing install -- verify
    update + reconfigure to demo in one pass

Summary by CodeRabbit

  • New Features

    • Auto-detect running PostgreSQL instances and prompt for database connection
    • Introduced non-interactive --detect mode for automatic connection to existing instances
    • Detect previous installations and offer upgrade or reconfiguration options
    • Configurable schema metadata cache TTL (metadata_ttl, default 5 minutes) affecting schema info freshness
  • Bug Fixes

    • Improved Windows port detection reliability across all network addresses
  • Documentation

    • Added comprehensive installer guide with usage instructions and feature overview

…etection

TcpListener binding to 127.0.0.1 missed Postgres instances
listening on 0.0.0.0 or ::1. Get-NetTCPConnection reads the
kernel TCP table directly and catches all listeners.
Scans ports 5432-5436 for running Postgres using pg_isready
with fallbacks to lsof and ss. Populates DETECTED_PORTS and
DETECTED_CONFIRMED arrays for the context-aware menu.
Scans ports 5432-5436 for running Postgres using pg_isready
with fallback to Get-NetTCPConnection. Returns array of
objects with Port and Confirmed properties.
Adds try_passwordless_auth, list_databases,
connect_existing_instance, and prompt_credentials_and_list
functions. Implements the four-tier dependency fallback chain:
full psql, pg_isready only, port check only, and no tools.
Rewrites choose_database to detect running Postgres instances
before presenting the menu. Shows detected instances with
option to connect. Adds --detect flag for non-interactive
auto-connection via passwordless auth.
Adds Test-PasswordlessAuth, Get-UserDatabases,
Connect-ExistingInstance, and Invoke-CredentialPrompt
functions. Mirrors the bash implementation with PowerShell
idioms and secure password handling.
Rewrites Select-Database to detect running Postgres instances
before presenting the menu. Adds -Detect parameter for
non-interactive auto-connection. Mirrors the bash
implementation.
Updates changelog with port detection fix, smart instance
detection, --detect flag, and context-aware database menu.
Use the label variable in port display output. Remove unused
demo_num variable assignment.
Fix Find-FreePort to filter by -State Listen so TIME_WAIT connections
don't falsely mark ports as in use. Restructure Test-PasswordlessAuth
with a single try/finally for reliable ErrorActionPreference restore.
Clear $env:PGPASSWORD after use in all PowerShell functions. Validate
--db-name database exists before accepting it in --detect mode.
Restructure changelog to use Keep a Changelog categories.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

Caution

Review failed

Failed to post review comments

Walkthrough

Adds interactive and non-interactive PostgreSQL detection to the claude-try-it installers (Bash + PowerShell): port scan (5432–5436), passwordless auth probing, per-instance database enumeration, auto-connect (--detect), existing-install/version detection, process cleanup, and updated README/changelog entries.

Changes

Installer + Docs

Layer / File(s) Summary
CLI / Usage
examples/claude-try-it/install.sh, examples/claude-try-it/install.ps1, examples/claude-try-it/README.md
Adds --detect / -Detect flag and CLI usage text; documents flags and non-interactive behavior in README.
Port Detection / Availability
examples/claude-try-it/install.sh, examples/claude-try-it/install.ps1
Add port scanning over preferred ports (5432–5436). Improve port-in-use checks to consult OS listener state (Get-NetTCPConnection / lsof/ss) and fallback probes.
Auth Probing & DB Enumeration
examples/claude-try-it/install.sh, examples/claude-try-it/install.ps1
Introduce passwordless auth attempts and per-instance database listing functions (try_passwordless_auth/Test-PasswordlessAuth, list_databases/Get-UserDatabases).
Connect Flows (interactive & auto)
examples/claude-try-it/install.sh, examples/claude-try-it/install.ps1
Add connect_existing_instance/Connect-ExistingInstance for interactive selection and connect_existing_auto/Connect-ExistingAuto for non-interactive auto-connect with DETECT_* status codes.
Existing-install / Update Handling
examples/claude-try-it/install.sh, examples/claude-try-it/install.ps1
Add check_existing_install/Test-ExistingInstall, write installed version manifest (.version/VERSION), stop_stale_processes/Stop-StaleProcesses, and print/write update summary. Main() now runs pre-install check and may skip or reconfigure instead of full reinstall.
UX / Prompts & Config Handling
examples/claude-try-it/install.sh, examples/claude-try-it/install.ps1
Enhance database selection menu to include detected instances and numeric port selectors; Set-OwnDatabase/setup_own_database prompts show Host/Port defaults; Claude Desktop config write backs up invalid JSON before overwriting.
Changelog / Docs
docs/changelog.md, examples/claude-try-it/README.md
Add changelog entries for installer detection, --detect flag, upgrade/reconfigure behavior, metadata_ttl doc move, and Windows port-detection fix; add README describing installer flow, flags, detection steps, and install paths.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Installer as Installer Script
    participant Scanner as Port Scanner
    participant PG as PostgreSQL
    participant Auth as Auth Probe
    participant DB as DB Enumerator
    participant Menu as Selection UI

    User->>Installer: Run installer (--detect or interactive)
    Installer->>Scanner: Scan ports 5432-5436
    Scanner->>PG: Check listener (pg_isready / OS listener)
    PG-->>Scanner: reachable / not reachable
    Scanner-->>Installer: Detected instances

    Installer->>Auth: Attempt passwordless auth per instance
    Auth->>PG: psql connection attempt
    PG-->>Auth: auth success / fail
    Auth-->>Installer: auth result

    alt Auth success
        Installer->>DB: Enumerate databases for instance
        DB->>PG: query database list
        PG-->>DB: databases
        DB-->>Installer: db list
    else Auth fail
        Installer->>Menu: Prompt for credentials
        Menu-->>User: request password
        User-->>Menu: provide credentials
        Menu-->>Installer: credentials
        Installer->>PG: authenticate with provided creds
    end

    Installer->>Menu: Present selection or auto-select
    Menu-->>User: selection (or auto-connect)
    User-->>Installer: chosen target
    Installer->>Installer: configure DB connection / continue install or reconfigure
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • pgEdge/pgedge-postgres-mcp#91: Directly extends the same installer scripts (install.ps1 and install.sh) by adding detect mode, passwordless auth probing, DB selection UX, and existing-install handling.

Suggested reviewers

  • dpage
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding smart PostgreSQL detection and making the installer menu context-aware based on detected instances.
Docstring Coverage ✅ Passed Docstring coverage is 88.24% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/smart-postgres-detection

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Apr 18, 2026

Up to standards ✅

🟢 Issues 3 medium

Results:
3 new issues

Category Results
BestPractice 3 medium (3 false positives)

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/claude-try-it/install.ps1`:
- Around line 508-534: The code overwrites $env:PGPASSWORD and always restores
it to $null, which clears any pre-existing session value; update the affected
helpers (the shown block plus Get-UserDatabases and Invoke-CredentialPrompt) to
save the original $env:PGPASSWORD into a local variable (e.g. $prevPGPASSWORD)
before setting it for the check, then in the finally block restore
$env:PGPASSWORD = $prevPGPASSWORD (not $null); ensure you still preserve and
restore $ErrorActionPreference as currently done and apply this save/restore
pattern in all three functions.
- Around line 513-550: The psql calls (e.g., in the auth-check function that
sets $script:AuthUser and in Get-UserDatabases) rely on default DB resolution
and also always exclude the 'postgres' DB; update those invocations to pass an
explicit database via -d using the configured DbName (or default to 'postgres'
when DbName is empty) so psql won't fail when a same-named DB doesn't exist, and
change the query in Get-UserDatabases to only exclude 'postgres' when the
requested DbName is not 'postgres' (i.e., make the filter conditional based on
the provided DbName parameter) so validation works for clusters containing only
the default database.
- Around line 579-580: Get-UserDatabases may return a scalar when there's only
one DB, causing $dbs[0] to grab a character; wrap each call to Get-UserDatabases
in array subexpression syntax @(...) to force array context. Specifically,
update the assignments to $dbs (used where you check .Count and foreach, where
you use index-based access $dbs[$i], where you use -contains, and where you
directly index $dbs[0] to set $script:DbName) so each is set as $dbs =
@(...Get-UserDatabases...), ensuring subsequent .Count, foreach, -contains and
indexing operate on an array rather than a scalar string.

In `@examples/claude-try-it/install.sh`:
- Around line 499-533: The psql authentication checks use the default database
(username) which can fail if a same-named DB doesn't exist, and list_databases
explicitly excludes 'postgres' which prevents detecting fresh clusters; update
the three psql calls in the detection/auth block to include -d postgres so they
always connect to the postgres database, and modify the list_databases function
to stop excluding 'postgres' (remove the "AND datname NOT IN ('postgres')"
filter) or make that exclusion conditional so --db-name=postgres is honored;
reference the psql invocations in the detection/auth block and the
list_databases function when making these changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0d3df874-8ef1-4305-8813-7a9096e94a32

📥 Commits

Reviewing files that changed from the base of the PR and between bb590b7 and b1429fa.

📒 Files selected for processing (3)
  • docs/changelog.md
  • examples/claude-try-it/install.ps1
  • examples/claude-try-it/install.sh

Comment thread examples/claude-try-it/install.ps1
Comment thread examples/claude-try-it/install.ps1 Outdated
Comment thread examples/claude-try-it/install.ps1 Outdated
Comment thread examples/claude-try-it/install.sh
The installer now checks for a previous installation before
downloading. If the binary is current, it offers to reconfigure
the database connection. If a newer version is available, it
offers to update and kills stale MCP server processes first.
Add -d postgres to all psql calls so auth checks don't fail when
a same-named database doesn't exist. Preserve existing PGPASSWORD
in PowerShell instead of clearing to null. Wrap Get-UserDatabases
calls in @() to prevent scalar unwrapping when only one database
is returned.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/claude-try-it/install.ps1`:
- Around line 598-610: The code builds an "auth" option even when $hasPsql is
false, causing Invoke-CredentialPrompt to fail; fix by not adding a Type="auth"
PSCustomObject when $hasPsql is $false and instead add a different option (e.g.,
Type="manual" or Type="no-psql") that preserves the detected Port (InstIndex
null) so the UI routes to manual credential entry for that specific port; update
the prompt flow consumer (Invoke-CredentialPrompt call) to only be invoked for
options with Type="auth" and ensure Set-OwnDatabase reads and uses any prefilled
$script:DbHost and $script:DbPort values as the default values in its prompts so
manual entry uses the detected host/port.
- Around line 1245-1293: When an existing install is detected (installedVersion
-eq $script:Version) honor explicit DB flags and avoid overwriting configs:
before the early return in that branch, check for the explicit database flags
(e.g. -Detect, -Demo, -OwnDb) and call Select-Database non-interactively so
those flags can configure $script:DbConfigured; only call Set-ClaudeCodeConfig,
Set-ClaudeDesktopConfig and Write-Summary if $script:DbConfigured is $true. For
the interactive reconfigure path (Test-Interactive + Read-Prompt reconfigure),
after Select-Database also gate calls to
Set-ClaudeCodeConfig/Set-ClaudeDesktopConfig on $script:DbConfigured to avoid
writing placeholder configs when Select-Database leaves $script:DbConfigured
$false.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a11d7079-34da-4c30-82af-a1749833aacb

📥 Commits

Reviewing files that changed from the base of the PR and between b1429fa and 32b37f2.

📒 Files selected for processing (3)
  • docs/changelog.md
  • examples/claude-try-it/install.ps1
  • examples/claude-try-it/install.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/claude-try-it/install.sh

Comment thread examples/claude-try-it/install.ps1 Outdated
Comment thread examples/claude-try-it/install.ps1
Route no-psql detected ports to manual entry instead of auth prompt.
Honor explicit flags (-Detect, -Demo, -OwnDb / --detect, --demo,
--own-db) in the existing-install flow instead of short-circuiting.
Gate config writes on DbConfigured to avoid overwriting working
configs with placeholders.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
examples/claude-try-it/install.ps1 (1)

1353-1356: ⚠️ Potential issue | 🟠 Major

Guard config writes on DbConfigured in fresh-install path.

Line 1354 and Line 1355 still run even when Select-Database leaves $script:DbConfigured = $false, which can overwrite an existing working Claude config with placeholders.

🐛 Proposed fix
     Write-Host ""
     Select-Database

-    Write-Host ""
-    Set-ClaudeCodeConfig
-    Set-ClaudeDesktopConfig
+    Write-Host ""
+    if ($script:DbConfigured) {
+        Set-ClaudeCodeConfig
+        Set-ClaudeDesktopConfig
+    } else {
+        Write-Warn "Skipping Claude config update because database is not configured."
+    }

     Write-Summary
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/claude-try-it/install.ps1` around lines 1353 - 1356, The installer
currently calls Set-ClaudeCodeConfig and Set-ClaudeDesktopConfig unconditionally
after Select-Database, which can overwrite a working config when Select-Database
sets $script:DbConfigured = $false; update the fresh-install path to check the
$script:DbConfigured flag returned/modified by Select-Database and only invoke
Set-ClaudeCodeConfig and Set-ClaudeDesktopConfig when $script:DbConfigured -eq
$true (i.e., guard the config write operations based on the Select-Database
outcome).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/claude-try-it/install.ps1`:
- Around line 815-820: The DETECT_AUTH_FAILED output is too generic for
non-interactive runs; modify the detection branch that writes DETECT_AUTH_FAILED
(the block that sets $script:DbConfigured = $false and emits
"DETECT_AUTH_FAILED") to include a machine-readable, explicit failure reason
(e.g., a short token or the underlying error message) so automation can
distinguish cases like missing psql vs no matching port; populate and emit a new
variable/token such as $script:DetectFailureReason (or include
$Error[0].Exception.Message) alongside the existing message and ensure the
non-interactive path prints that token/message so callers can parse it.

---

Outside diff comments:
In `@examples/claude-try-it/install.ps1`:
- Around line 1353-1356: The installer currently calls Set-ClaudeCodeConfig and
Set-ClaudeDesktopConfig unconditionally after Select-Database, which can
overwrite a working config when Select-Database sets $script:DbConfigured =
$false; update the fresh-install path to check the $script:DbConfigured flag
returned/modified by Select-Database and only invoke Set-ClaudeCodeConfig and
Set-ClaudeDesktopConfig when $script:DbConfigured -eq $true (i.e., guard the
config write operations based on the Select-Database outcome).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a49402a7-f39f-4500-9857-8d279267cb0d

📥 Commits

Reviewing files that changed from the base of the PR and between 32b37f2 and 80e3f86.

📒 Files selected for processing (2)
  • examples/claude-try-it/install.ps1
  • examples/claude-try-it/install.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/claude-try-it/install.sh

Comment thread examples/claude-try-it/install.ps1
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
examples/claude-try-it/install.sh (1)

1374-1378: ⚠️ Potential issue | 🟠 Major

Don’t write Claude configs when DB selection failed.

When choose_database returns with DB_CONFIGURED=false, main still writes configs using placeholder database values. This affects no-choice non-interactive runs and failed --detect / Docker flows.

Proposed fix
   echo ""
   choose_database
 
-  echo ""
-  configure_claude_code
-  configure_claude_desktop
+  if [ "$DB_CONFIGURED" = true ]; then
+    echo ""
+    configure_claude_code
+    configure_claude_desktop
+  fi
 
   print_summary
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/claude-try-it/install.sh` around lines 1374 - 1378, After calling
choose_database in main, check the DB_CONFIGURED flag and do not proceed to
write Claude configs if it is false; specifically, guard the calls to
configure_claude_code and configure_claude_desktop (and any placeholder DB
writes performed in main) behind a conditional that only runs when
DB_CONFIGURED=true so non-interactive no-choice and failed --detect/Docker flows
do not create configs with placeholder database values.
examples/claude-try-it/install.ps1 (1)

1385-1390: ⚠️ Potential issue | 🟠 Major

Gate config writes after database selection.

If Select-Database leaves $script:DbConfigured = $false—for example -Detect finds nothing, Docker is unavailable, or non-interactive mode asks for a choice—Main still writes Claude configs with placeholder DB values.

Proposed fix
     Select-Database
 
-    Write-Host ""
-    Set-ClaudeCodeConfig
-    Set-ClaudeDesktopConfig
+    if ($script:DbConfigured) {
+        Write-Host ""
+        Set-ClaudeCodeConfig
+        Set-ClaudeDesktopConfig
+    }
 
     Write-Summary
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/claude-try-it/install.ps1` around lines 1385 - 1390, Main currently
calls Set-ClaudeCodeConfig and Set-ClaudeDesktopConfig unconditionally after
Select-Database, which can leave placeholder DB values when Select-Database sets
$script:DbConfigured = $false; change the flow so that after calling
Select-Database you check $script:DbConfigured and only invoke
Set-ClaudeCodeConfig and Set-ClaudeDesktopConfig when $script:DbConfigured -eq
$true (or otherwise handle the non-configured path, e.g., abort or prompt),
ensuring Select-Database, Set-ClaudeCodeConfig, and Set-ClaudeDesktopConfig are
referenced when adding the conditional guard.
♻️ Duplicate comments (2)
examples/claude-try-it/install.sh (1)

1041-1045: ⚠️ Potential issue | 🟠 Major

Keep detected host/port as manual-entry defaults.

manualPort preloads DB_HOST=localhost and DB_PORT=<detected port>, but these prompts still default to localhost:5432, so users can accidentally lose the selected port by pressing Enter.

Proposed fix
-  ask "  Host [localhost]: " DB_HOST
-  DB_HOST="${DB_HOST:-localhost}"
+  local default_host="${DB_HOST:-localhost}"
+  ask "  Host [$default_host]: " DB_HOST
+  DB_HOST="${DB_HOST:-$default_host}"
 
-  ask "  Port [5432]: " DB_PORT
-  DB_PORT="${DB_PORT:-5432}"
+  local default_port="${DB_PORT:-5432}"
+  ask "  Port [$default_port]: " DB_PORT
+  DB_PORT="${DB_PORT:-$default_port}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/claude-try-it/install.sh` around lines 1041 - 1045, The prompts
always fall back to hardcoded defaults ("localhost" and "5432") which can
overwrite values preloaded by manualPort; update the prompt logic so the ask
calls use the current DB_HOST and DB_PORT variables as their displayed/default
values (i.e., pass DB_HOST and DB_PORT into the prompts instead of literal
"localhost" and "5432") so existing detected values are preserved when the user
presses Enter; locate the ask invocations around the DB_HOST/DB_PORT variables
and ensure you only set DB_HOST="${DB_HOST:-localhost}" and
DB_PORT="${DB_PORT:-5432}" before prompting or use the variables directly in the
prompt text to avoid losing preloaded values.
examples/claude-try-it/install.ps1 (1)

1052-1053: ⚠️ Potential issue | 🟠 Major

Preserve prefilled manual connection defaults.

The manualPort flow sets $script:DbPort to the selected detected port, but Set-OwnDatabase still prompts with and defaults to 5432, so pressing Enter silently discards the selected port.

Proposed fix
-    $script:DbHost = Read-Prompt "  Host [localhost]" "localhost"
-    $script:DbPort = Read-Prompt "  Port [5432]" "5432"
+    $defaultHost = if ($script:DbHost) { $script:DbHost } else { "localhost" }
+    $defaultPort = if ($script:DbPort) { $script:DbPort } else { "5432" }
+    $script:DbHost = Read-Prompt "  Host [$defaultHost]" $defaultHost
+    $script:DbPort = Read-Prompt "  Port [$defaultPort]" $defaultPort
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/claude-try-it/install.ps1` around lines 1052 - 1053, Set-OwnDatabase
is prompting with a hardcoded default "5432" which overrides the
previously-detected manual port stored in $script:DbPort; change the Read-Prompt
call in Set-OwnDatabase to use $script:DbPort as the default (i.e., pass
$script:DbPort as the second argument to Read-Prompt for the Port prompt) so
that pressing Enter preserves the detected/selected manual port value from the
manualPort flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/claude-try-it/install.ps1`:
- Around line 1273-1274: The Test-ExistingInstall function sets
$explicitReconfigure without considering $InstallDocker, so calling the script
with -InstallDocker on an existing install is ignored; update the assignment of
$explicitReconfigure in Test-ExistingInstall (where $explicitReconfigure is
currently set) to include $InstallDocker (or otherwise OR in the $InstallDocker
flag) so that Select-Database and downstream logic will respect -InstallDocker
for existing installations; ensure this change is applied where
$explicitReconfigure is defined and any code paths that branch on it (e.g., the
path that calls Select-Database / Docker setup) will now execute when
-InstallDocker is provided.

In `@examples/claude-try-it/install.sh`:
- Around line 1284-1317: Replace the interactive TTY checks that use the test "[
-t 0 ]" in the existing-install flow with the project helper function "has_tty"
so prompts behave correctly when stdin is redirected; specifically, update the
conditional branches that guard the reconfigure prompt and the later info block
(the "elif [ -t 0 ]" and the later "if [ -t 0 ]" surrounding the choose_database
/ configure_claude_code / configure_claude_desktop / print_summary logic) to
call has_tty instead and keep the existing branches and behavior intact when
has_tty returns false.
- Around line 794-797: The grep call that checks for the requested database name
treats DB_NAME as a regex which breaks names containing regex metacharacters;
update the literal match to use fixed-string mode by changing the grep
invocation that tests dbs for DB_NAME (the line with echo "$dbs" | grep -qx
"$DB_NAME") so it uses the -F flag (i.e., grep -Fqx) to ensure list_databases
results are matched literally; keep the surrounding logic with DB_NAME and the
dbs variable intact.
- Around line 1248-1254: In stop_stale_processes replace full-command matching
flags by removing -f from pgrep and pkill so they match the command name only
(or use pgrep -xc for exact-count matching); update the pgrep invocation
(currently using pgrep -fc pgedge-postgres-mcp) to use name-only matching (e.g.,
pgrep -c or pgrep -xc) and remove -f from pkill -f pgedge-postgres-mcp so pkill
targets the command basename instead of the entire command line.

---

Outside diff comments:
In `@examples/claude-try-it/install.ps1`:
- Around line 1385-1390: Main currently calls Set-ClaudeCodeConfig and
Set-ClaudeDesktopConfig unconditionally after Select-Database, which can leave
placeholder DB values when Select-Database sets $script:DbConfigured = $false;
change the flow so that after calling Select-Database you check
$script:DbConfigured and only invoke Set-ClaudeCodeConfig and
Set-ClaudeDesktopConfig when $script:DbConfigured -eq $true (or otherwise handle
the non-configured path, e.g., abort or prompt), ensuring Select-Database,
Set-ClaudeCodeConfig, and Set-ClaudeDesktopConfig are referenced when adding the
conditional guard.

In `@examples/claude-try-it/install.sh`:
- Around line 1374-1378: After calling choose_database in main, check the
DB_CONFIGURED flag and do not proceed to write Claude configs if it is false;
specifically, guard the calls to configure_claude_code and
configure_claude_desktop (and any placeholder DB writes performed in main)
behind a conditional that only runs when DB_CONFIGURED=true so non-interactive
no-choice and failed --detect/Docker flows do not create configs with
placeholder database values.

---

Duplicate comments:
In `@examples/claude-try-it/install.ps1`:
- Around line 1052-1053: Set-OwnDatabase is prompting with a hardcoded default
"5432" which overrides the previously-detected manual port stored in
$script:DbPort; change the Read-Prompt call in Set-OwnDatabase to use
$script:DbPort as the default (i.e., pass $script:DbPort as the second argument
to Read-Prompt for the Port prompt) so that pressing Enter preserves the
detected/selected manual port value from the manualPort flow.

In `@examples/claude-try-it/install.sh`:
- Around line 1041-1045: The prompts always fall back to hardcoded defaults
("localhost" and "5432") which can overwrite values preloaded by manualPort;
update the prompt logic so the ask calls use the current DB_HOST and DB_PORT
variables as their displayed/default values (i.e., pass DB_HOST and DB_PORT into
the prompts instead of literal "localhost" and "5432") so existing detected
values are preserved when the user presses Enter; locate the ask invocations
around the DB_HOST/DB_PORT variables and ensure you only set
DB_HOST="${DB_HOST:-localhost}" and DB_PORT="${DB_PORT:-5432}" before prompting
or use the variables directly in the prompt text to avoid losing preloaded
values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b75097d7-4419-4f36-a997-160c5053438d

📥 Commits

Reviewing files that changed from the base of the PR and between 80e3f86 and 4867140.

📒 Files selected for processing (2)
  • examples/claude-try-it/install.ps1
  • examples/claude-try-it/install.sh

Comment thread examples/claude-try-it/install.ps1 Outdated
Comment thread examples/claude-try-it/install.sh Outdated
Comment thread examples/claude-try-it/install.sh
Comment thread examples/claude-try-it/install.sh Outdated
- Add -InstallDocker to $explicitReconfigure in install.ps1
- Use grep -Fqx for literal DB_NAME matching in install.sh
- Anchor pgrep/pkill patterns to avoid path false matches
- Replace [ -t 0 ] with has_tty in existing-install flow
@AntTheLimey AntTheLimey marked this pull request as ready for review April 24, 2026 13:03
@AntTheLimey AntTheLimey requested a review from dpage April 24, 2026 13:04
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
examples/claude-try-it/install.ps1 (1)

458-458: Nit: Detect-PostgresInstances uses an unapproved PowerShell verb.

PSScriptAnalyzer flags Detect- (PSUseApprovedVerbs). The idiomatic approved verbs for this kind of discovery are Find- or Get-. A rename (e.g., Find-PostgresInstance, singular per PSUseSingularNouns) silences the warning and reads as more canonical PowerShell — but this is purely cosmetic and purely internal to the script, so feel free to defer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/claude-try-it/install.ps1` at line 458, Rename the PowerShell
function Detect-PostgresInstances to use an approved verb and singular noun
(e.g., Find-PostgresInstance or Get-PostgresInstance) to satisfy
PSUseApprovedVerbs/PSUseSingularNouns; update the function declaration name and
all internal references/call sites that invoke Detect-PostgresInstances (search
for that symbol) so callers match the new name, and run PSScriptAnalyzer to
confirm the warning is resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/claude-try-it/install.ps1`:
- Line 1337: Write-UpdateSummary currently runs unconditionally and prints an
"existing database unchanged" message even when explicit reconfiguration is
requested; change the flow to avoid double/conflicting summaries by gating the
Write-UpdateSummary call on -not $explicitReconfigure (or otherwise
consolidating with the reconfigure path). Specifically, in the install.ps1 flow
where Write-UpdateSummary is invoked, wrap that call in a conditional such as if
(-not $explicitReconfigure) { Write-UpdateSummary } so that when Select-Database
and Write-Summary run (the explicit reconfigure branch) only the new
configuration summary is printed; update the analogous occurrence at the second
location (lines around 1347–1357) as well.
- Around line 1279-1283: The installer crashes when .version is empty because
(Get-Content -Raw) can return $null and calling .Trim() throws; change the logic
around the $versionFile read (the $versionFile / $installedVersion block) to
capture the raw content into a temp variable, check for $null (or coerce to
string) before calling .Trim(), and set $installedVersion to "" when the read
returns $null so the installer continues to Install-Binary; ensure you reference
the existing variables ($versionFile and $installedVersion) and the Get-Content
-Raw call when making the fix.
- Around line 1259-1269: Stop-StaleProcesses should avoid scanning all processes
and reading .Path (which can throw access errors) and must match the binary name
exactly; replace the Get-Process | Where-Object approach in Stop-StaleProcesses
with a direct Get-Process -Name 'pgedge-postgres-mcp' (use the process name
without .exe so the match is exact/not a substring) and supply -ErrorAction
SilentlyContinue (or wrap the call in try/catch) so failures are swallowed; then
use the returned $procs (no .Path access) to compute the count and call
Stop-Process -Force -ErrorAction SilentlyContinue on those PIDs.

In `@examples/claude-try-it/install.sh`:
- Around line 1322-1348: When an update is followed by an explicit reconfigure
the script currently calls download_binary then print_update_summary, then
choose_database/configure_claude_* and print_summary, producing contradictory
back-to-back summaries; change the flow so print_update_summary is suppressed
when $explicit_reconfigure is true (i.e. only call print_update_summary in the
branches where no reconfigure will occur), and make the same change in the
PowerShell logic by suppressing Write-UpdateSummary in Test-ExistingInstall when
a reconfiguration path will call Write-Summary (use the flags/variables
explicit_reconfigure and the equivalent detection in Test-ExistingInstall to
decide whether to emit the update summary).

---

Nitpick comments:
In `@examples/claude-try-it/install.ps1`:
- Line 458: Rename the PowerShell function Detect-PostgresInstances to use an
approved verb and singular noun (e.g., Find-PostgresInstance or
Get-PostgresInstance) to satisfy PSUseApprovedVerbs/PSUseSingularNouns; update
the function declaration name and all internal references/call sites that invoke
Detect-PostgresInstances (search for that symbol) so callers match the new name,
and run PSScriptAnalyzer to confirm the warning is resolved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 188d11eb-2fbb-449a-a441-37bfca8a0f2d

📥 Commits

Reviewing files that changed from the base of the PR and between 4867140 and 71ae2d7.

📒 Files selected for processing (2)
  • examples/claude-try-it/install.ps1
  • examples/claude-try-it/install.sh

Comment thread examples/claude-try-it/install.ps1
Comment thread examples/claude-try-it/install.ps1
Comment thread examples/claude-try-it/install.ps1 Outdated
Comment thread examples/claude-try-it/install.sh
@AntTheLimey AntTheLimey marked this pull request as draft April 24, 2026 14:19
- Gate config writes on DB_CONFIGURED/DbConfigured in main
- Suppress update summary when explicit reconfigure follows
- Use preloaded DB_HOST/DB_PORT as manual entry defaults
- Use exact process name matching in stop_stale_processes
- Null-safe .version file reading in Test-ExistingInstall
- Rename Detect-PostgresInstances to Find-PostgresInstance
- Exit/return when user declines update instead of falling
  through to explicit_reconfigure block
- Move Write-Summary inside DbConfigured guard in PS1 Main
- Return 0 from connect_existing_instance on empty list to
  avoid set -eo pipefail terminating the script
- Add empty-instance guard in PS1 Connect-ExistingInstance
  matching bash's early return when no instances match
- Align update prompt default to "y" in bash (was silently
  declining on Enter; PS1 already defaulted to "y")
- Make reconfigure prompt default explicit ("n") in bash
- Back up invalid Claude Desktop JSON in PS1 instead of
  silently skipping config write (matches bash and PS1's
  own Claude Code behavior)
- Add confirmed/unconfirmed label on port display in PS1
  to match bash's "(PostgreSQL)" vs "(service)" labels
- Remove double blank line in PS1 Write-UpdateSummary
@AntTheLimey AntTheLimey marked this pull request as ready for review April 24, 2026 14:50
@AntTheLimey
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
examples/claude-try-it/install.sh (1)

1251-1259: ⚠️ Potential issue | 🟠 Major

Fix pgrep -x / pkill -x to actually match the MCP process on Linux.

Without -f, pgrep/pkill match against the process name from /proc/PID/stat, which the Linux kernel truncates to 15 characters (TASK_COMM_LEN). The binary name pgedge-postgres-mcp is 19 characters—its stored comm is pgedge-postgres. Combined with -x (exact match), the pattern pgedge-postgres-mcp will never match any running process on Linux, so stop_stale_processes becomes a silent no-op during upgrades and old server processes aren't stopped before the binary is replaced.

Use -f to match against the full command line instead, which is not truncated:

Proposed fix
 stop_stale_processes() {
   local count
-  count=$(pgrep -xc pgedge-postgres-mcp 2>/dev/null || true)
+  count=$(pgrep -fc '(^|/)pgedge-postgres-mcp( |$)' 2>/dev/null || true)
   if [ "$count" -gt 0 ] 2>/dev/null; then
     info "Stopping $count running MCP server process(es)..."
-    pkill -x pgedge-postgres-mcp 2>/dev/null || true
+    pkill -f '(^|/)pgedge-postgres-mcp( |$)' 2>/dev/null || true
     sleep 1
   fi
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/claude-try-it/install.sh` around lines 1251 - 1259,
stop_stale_processes currently uses pgrep -x / pkill -x which match the
truncated comm on Linux and will never find "pgedge-postgres-mcp"; change those
calls to use the full-command-line matcher (-f) so the 19-char binary name is
matched: replace pgrep -xc pgedge-postgres-mcp with pgrep -c -f
pgedge-postgres-mcp (or pgrep -fc -f pgedge-postgres-mcp) to count matches and
replace pkill -x pgedge-postgres-mcp with pkill -f pgedge-postgres-mcp to
actually kill the running MCP processes in stop_stale_processes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@examples/claude-try-it/install.sh`:
- Around line 1251-1259: stop_stale_processes currently uses pgrep -x / pkill -x
which match the truncated comm on Linux and will never find
"pgedge-postgres-mcp"; change those calls to use the full-command-line matcher
(-f) so the 19-char binary name is matched: replace pgrep -xc
pgedge-postgres-mcp with pgrep -c -f pgedge-postgres-mcp (or pgrep -fc -f
pgedge-postgres-mcp) to count matches and replace pkill -x pgedge-postgres-mcp
with pkill -f pgedge-postgres-mcp to actually kill the running MCP processes in
stop_stale_processes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 16e1a916-489e-4324-ac78-5bbe179bd9d6

📥 Commits

Reviewing files that changed from the base of the PR and between 4867140 and 9b1c165.

📒 Files selected for processing (3)
  • examples/claude-try-it/README.md
  • examples/claude-try-it/install.ps1
  • examples/claude-try-it/install.sh
✅ Files skipped from review due to trivial changes (1)
  • examples/claude-try-it/README.md

Linux truncates process comm to 15 chars (TASK_COMM_LEN), so
pgrep -x never matches "pgedge-postgres-mcp" (19 chars). Switch
to pgrep -f with an anchored regex to match the full command line.
Copy link
Copy Markdown
Member

@dpage dpage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Substantial enhancement (1,447 additions): instance discovery, context-aware menu with passwordless-auth + database-listing, non-interactive --detect/-Detect flag, existing-install update/reconfigure flows, and a Windows port-detection fix. The PR has been through 4 rounds of CodeRabbit review with all 15 review threads resolved, all 12 CI checks passing, and Codacy reporting "Up to standards" — it's in good shape. My findings are all minor refinements plus one merge-process concern.

I read both scripts end-to-end and audited the new flows: detection, passwordless auth, credential prompt, --detect auto-connect, existing-install update path, and JSON config writers. The error handling is careful (sentinel tokens for non-interactive output, .bak backups on invalid JSON, env-var-based python3 invocation to avoid injection, 4-tier graceful degradation when pg_isready/psql/lsof are missing).

Findings

🟡 Should Fix — Branch is 57 commits behind main; changelog will conflict at merge

The PR branch is 57 commits behind main. The diff currently shows main's ### Fixed entry for #117 (Database switching via select_database_connection) being deleted, because the branch never had it. Main has also acquired entries for #126 and #142 since this branch was cut. A simple GitHub merge will not resolve this cleanly — the [Unreleased] section needs a manual reconcile. Recommend rebasing onto main (or merging main in) before merge. The conflict zone is small (just docs/changelog.md [Unreleased]); the install scripts themselves shouldn't conflict with anything on main.

🟡 Should Fix — Cross-platform parity: case-sensitive --db-name/-DbName match

examples/claude-try-it/install.ps1:797:

if ($dbs -contains $script:DbName) {

PowerShell's -contains operator is case-insensitive for strings by default. The bash counterpart at examples/claude-try-it/install.sh:798 uses echo "$dbs" | grep -Fqx -- "$DB_NAME", which is case-sensitive.

PostgreSQL identifiers are case-sensitive when not folded — a database created as "MyDB" is distinct from mydb. If a user runs install.ps1 -Detect -DbName MyDB and only mydb exists, this branch silently configures Claude with DbName=MyDB. The Postgres connection then fails at use time with a confusing database "MyDB" does not exist error from psql.

One-character fix: -ccontains (the case-sensitive variant).

🟢 Suggestion — find_free_port doesn't fall back when lsof is missing

examples/claude-try-it/install.sh:434-445:

find_free_port() {
  for port in 5432 5433 5434 5435 5436; do
    if ! lsof -i ":$port" >/dev/null 2>&1; then
      echo "$port"; return
    fi
  done
  ...
}

If lsof isn't installed (some minimal Linux containers, alpine without lsof), lsof -i ":$port" exits non-zero, the if ! triggers, and every port is treated as free. The demo container then tries to bind 5432 on top of an existing Postgres and fails with a port-bind error in the docker-compose log.

The detection function detect_postgres_instances (lines 459-486) already implements a 3-tier fallback: pg_isreadylsofss. find_free_port should mirror at least the ss step. Suggested:

port_in_use() {
  local p="$1"
  if command -v lsof &>/dev/null; then
    lsof -i ":$p" >/dev/null 2>&1
  elif command -v ss &>/dev/null; then
    ss -tlnH "sport = :$p" 2>/dev/null | grep -q .
  else
    (echo >/dev/tcp/localhost/"$p") 2>/dev/null
  fi
}

The PowerShell counterpart Find-FreePort uses Get-NetTCPConnection, which is always present on supported Windows versions, so it doesn't have this issue.

ℹ️ Note — README doesn't mention demo container cleanup wipes prior demos

cleanup_old_demos (install.sh:839-847) / Remove-OldDemos (install.ps1:843-854) removes every pgedge-demo-* container with docker rm -v (volumes too). Intentional and correct given the unique-timestamp naming for new containers, but a user who's been experimenting with multiple demo runs may not expect prior data to be wiped. Worth a one-liner in examples/claude-try-it/README.md, e.g.:

Each demo run replaces any previous demo container (pgedge-demo-*); previous demo data in those containers is removed.

ℹ️ Note — 120s readiness budget may be tight on first-run demos

start_demo_postgres waits up to 24×5s = 120s for pg_isready inside the container. On a fresh machine this has to cover docker image pull + Northwind SQL download + import. The script handles the timeout gracefully (DB_CONFIGURED=true with a warning) so the user gets a configured Claude — but the first query may hit a "database not ready" error on slow networks. Not a blocker, just noting.

Things I checked that are correct

  • PGPASSWORD is set per-process in bash; saved/restored via try/finally in PS. Never leaks to other processes.
  • ✅ JSON config writes use python3 with env-var-based value passing (no shell or python injection); manual fallback uses a robust json_escape. PS uses ConvertTo-Json.
  • ✅ Invalid pre-existing JSON configs are backed up to .bak instead of silently overwritten (matches PR hardening notes).
  • stop_stale_processes uses anchored regex (^|/)pgedge-postgres-mcp( |$); PS uses exact Get-Process -Name. Both avoid false positives like pgedge-postgres-mcp-foo.
  • ✅ Sentinel tokens (DETECT_NO_INSTANCES, DETECT_AUTH_FAILED, DOCKER_NOT_RUNNING, etc.) are consistent across both scripts — useful integration surface for Claude Code.
  • DB_CONFIGURED gating prevents placeholder values (your_database, your_user) from being written; traced every code path.
  • check_existing_install / Test-ExistingInstall short-circuit cleanly via exit 0 / early return — no double download.
  • bash -n syntax check passes.
  • ✅ All 12 CI checks green; CodeRabbit complete; Codacy "Up to standards".

Checklist

  • Correctness — flows trace cleanly
  • Security — credentials, JSON writes, and process-stop logic are safe
  • Cross-platform parity — see install.ps1:797 (case-sensitivity)
  • Robustness — see install.sh:434-445 (find_free_port fallback)
  • Tests — manual test plan in PR description is comprehensive
  • Documentation — README missing demo-cleanup note
  • Branch state — 57 commits behind main; rebase before merging

Review generated with Claude Code.

- Use case-sensitive -ccontains for database name matching in
  install.ps1 to match the case-sensitive grep -Fqx in install.sh
- Extract port_in_use() helper with lsof/ss/dev-tcp fallback so
  find_free_port works on systems without lsof
- Add README note that demo runs remove previous pgedge-demo-*
  containers and their data
Copy link
Copy Markdown
Member Author

@AntTheLimey AntTheLimey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the thorough review, Dave. All four actionable items addressed in f5bab72:

Case-sensitive -ccontains -- Fixed. Changed -contains to -ccontains at install.ps1:797 so database name matching is case-sensitive, consistent with the grep -Fqx in install.sh.

find_free_port lsof fallback -- Fixed. Extracted a port_in_use() helper with 3-tier fallback (lsof -> ss -> /dev/tcp), mirroring the degradation strategy already used in detect_postgres_instances.

README cleanup note -- Added a line in the Install Location section noting that each demo run removes previous pgedge-demo-* containers and their data.

57 commits behind main -- Merged origin/main into the branch. The changelog auto-merged cleanly with all three existing entries (#117, #126, #142) preserved.

Re the 120s readiness budget note -- agreed, the timeout is tight on cold pulls but the graceful degradation path handles it. Worth revisiting if we get reports.

@AntTheLimey AntTheLimey requested a review from dpage May 6, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants