Skip to content

feat: stateless nREPL port auto-discovery via process scanning - #21

Merged
licht1stein merged 5 commits into
masterfrom
auto-discovery
Feb 17, 2026
Merged

licht1stein merged 5 commits into
masterfrom
auto-discovery

Conversation

@licht1stein

@licht1stein licht1stein commented Feb 17, 2026 •

Copy link
Copy Markdown
Owner

Closes #20

Summary

When no .nrepl-port file, -p flag, or BREPL_PORT env var is found, brepl now automatically discovers running nREPL servers by scanning OS processes. Zero configuration, fully stateless.

How it works

  1. Runs lsof to find TCP ports listened on by Java/Clojure/Babashka processes
  2. Checks all candidate ports in parallel (pmap)
  3. Each port is validated with a single TCP connection — sends describe to confirm nREPL, then eval to get the server's working directory
  4. Returns the first port whose CWD matches yours

Port resolution order (updated)

  1. -p <port> CLI argument
  2. .nrepl-port file (walks up from file dir for -f)
  3. BREPL_PORT environment variable
  4. Process scanning ← new

Performance

  • Real nREPL servers respond in <5ms on localhost
  • Non-nREPL ports rejected within 100ms socket timeout
  • All ports scanned in parallel — discovery completes in ~100-200ms even with many Java processes

Changes

  • src/brepl/lib/discovery.clj — new module: get-listening-ports, parse-lsof-output, gather-port-info, discover-nrepl-port
  • src/brepl.clj — discover-nrepl-port added as final fallback in resolve-port's or chain
  • README.md — documents process auto-discovery in Port Configuration section

Design decisions

  • Stateless: no caching, no session files, scans fresh every time
  • CWD matching only: if the nREPL server's user.dir matches your CWD, it's a match
  • No new CLI flags: discovery is automatic and transparent
  • Graceful degradation: if lsof fails or no matching port found, falls through to error message

Inspired by clojure-mcp-light's discovery approach, with improvements: single-connection validation, parallel scanning via pmap, IPv6-aware lsof parsing, and Clojure-side command filtering (no shell grep).

…tion

Merge validate-nrepl-port and get-nrepl-cwd into a single gather-port-info
function that reuses one TCP connection per port. Replace sequential reduce
with pmap for parallel scanning. Lower socket timeout from 2000ms to 100ms
since real nREPL servers respond in <5ms on localhost.
@licht1stein
licht1stein merged commit 6ad9a0a into master Feb 17, 2026
1 of 2 checks passed
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.

Suggestion: Add nREPL port auto discovery à la clojure-mcp-light

1 participant