Skip to content

Latest commit

 

History

History
356 lines (274 loc) · 14.5 KB

File metadata and controls

356 lines (274 loc) · 14.5 KB

PortReeve

Warning

Alpha Preview — PortReeve is evolving quickly. Breaking changes remain possible, and the currently published macOS previews through 0.1.0-preview.4 are immutable unsigned history. New public previews require Apple Developer ID signing and notarization. Review the installation and removal guide, including the narrowly scoped historical-preview guidance, before installing.

PortReeve, Local Port Authority

Install the alpha preview

The current public alpha preview is available on GitHub Releases. On macOS, install the graphical application with Homebrew after reviewing and narrowly trusting its cask:

brew tap TrentBrown/portreeve
brew trust --cask trentbrown/portreeve/portreeve-app
brew install --cask trentbrown/portreeve/portreeve-app

For terminal and MCP use, install the standalone CLI independently:

brew trust --formula trentbrown/portreeve/portreeve
brew install trentbrown/portreeve/portreeve

Homebrew does not silently install or start the supervised service. Direct macOS DMGs, Linux executables, checksum verification, historical unsigned-preview guidance, and removal procedures are covered in the installation guide.

Localhost port conflicts, solved

PortReeve gives every development service a stable TCP address and verifies which process or container actually owns it.

On one development machine, every service shares localhost's TCP port space. The familiar defaults—3000, 5432, 8080, and their neighbors—work until several projects need them at once. Concurrent agentic development multiplies that pressure: multiple agents can run independent copies of the same stack from different Git worktrees, and every copy naturally reaches for the same ports.

PortReeve replaces duplicated startup-time probing and remapping with one shared, inspectable source of truth.

Want to try it? Install the alpha preview and open PortReeve from Applications. Desktop is the primary visual experience; CLI, MCP, and JavaScript clients remain independent first-class ways to use the same authority.

PortReeve Desktop open to Overview, showing the product header and “What is PortReeve?” introduction

Why “PortReeve”?

A reeve was a person entrusted with local administration. The office took different names—shire reeve, borough reeve, and portreeve—according to the place or responsibility. Shire reeve survives in contracted form as the modern word sheriff.

A portreeve governed a port or market borough, where port could mean a market town rather than only a seaport. PortReeve is the modern local official for your machine's network ports.

One authority, several peer clients

One PortReeve server runs at a time for the current operating-system user—normally as a supervised service, or explicitly in the foreground for a temporary session. It owns the durable registry and coordinates every client through the same private HTTP/JSON Unix socket.

flowchart LR
  Desktop["PortReeve Desktop"] --> Server[("One PortReeve server")]
  MCP["MCP bridge"] --> Server
  CLI["portreeve CLI"] --> Server
  JS["JavaScript client"] --> Server
  Server --> Registry[("SQLite claims")]
  Server --> Evidence["lsof and Docker evidence"]
Loading

Desktop, MCP, CLI, and the official JavaScript library are peer clients of that authority. PortReeve assigns addresses and verifies bindings. Your project tooling remains responsible for starting, supervising, health-checking, and stopping services.

Choose a client

Client Choose it when Important boundary
Desktop A developer wants visual inspection, stack editing, or the lowest-friction built-in launcher macOS only; explicit UI confirmation protects consequential actions
MCP An agent should inspect and coordinate PortReeve through strict typed tools No daemon lifecycle, arbitrary shell, raw credentials, or unsafe eviction
CLI A terminal or trusted automation needs complete local administration Launcher commands may execute project-authored shell commands
JavaScript client Project tooling should own allocation, startup, and binding confirmation in one control flow The project owns provider lifecycle and confirms only after a successful bind

The clients share one authority; choosing one does not create a separate installation or registry. Native project integration through the JavaScript client provides the tightest coupling between lease acquisition and real service startup.

Choose an integration path

Every integration leaves service lifecycle with project-owned commands. The paths differ in what invokes those commands, what must be present at runtime, and how assigned ports reach the services.

Good: built-in Desktop driver

Configure shell commands such as npm run dev in Desktop. PortReeve resolves the stack, injects endpoint environment variables, invokes those commands, and confirms the resulting bindings. Desktop remains in the runtime path.

sequenceDiagram
  actor Initiator as You or agent
  participant Desktop as PortReeve Desktop
  participant Server as PortReeve Server
  participant Command as Shell command
  participant Services as Your services
  Initiator->>Desktop: Start
  Desktop->>Server: Plan and lease
  Server-->>Desktop: Resolved endpoints
  Desktop->>Command: Inject environment + invoke
  Command->>Services: Start services
  Desktop->>Server: Confirm bindings
Loading

Best for: exploring and proving the integration with the least initial friction.

Better: generated launcher

A generated launcher follows the same coordination protocol but runs without Desktop. It injects resolved endpoints into your existing lifecycle commands and can be checked into or distributed with the project.

sequenceDiagram
  actor Initiator as You or agent
  participant Launcher as Generated launcher
  participant Server as PortReeve Server
  participant Services as Your services
  Initiator->>Launcher: Start
  Launcher->>Server: Plan and lease
  Server-->>Launcher: Resolved endpoints
  Launcher->>Services: Inject environment + start
  Launcher->>Server: Confirm bindings
Loading

Payoff: reusable project automation without Desktop at runtime. The generated-launcher interface is an upgrade path and is not yet shipped; Desktop currently exposes it as Coming soon.

Best: project-owned integration

Your existing project tooling calls PortReeve directly so acquisition, startup, binding confirmation, and cleanup share one control flow. It may still inject the resolved values into child processes as environment variables, but no PortReeve-owned launcher stands between the project and the authority.

sequenceDiagram
  actor Initiator as You or agent
  participant Tooling as Your project tooling
  participant Server as PortReeve Server
  participant Services as Your services
  Initiator->>Tooling: Start
  Tooling->>Server: Request ports
  Server-->>Tooling: Leased endpoints
  Tooling->>Services: Inject and start
  Tooling->>Server: Confirm after successful bind
Loading

Payoff: the strongest lifecycle fidelity. Project tooling confirms a binding only after it succeeds in using the assigned endpoint.

Coordinate a familiar local stack

A PortReeve stack is the local development stack you already recognize. Its definition names components, endpoints, and dependencies; it does not preserve current port numbers.

flowchart LR
  Client["Web client<br/>frontend.http"] --> API["API<br/>api.http"]
  API --> Database["Database<br/>database.postgres"]
Loading

PortReeve coordinates two related problems:

  • Within one stack: every dependent service resolves the same coherent endpoint plan before startup. The client learns the API address, and the API learns the database address.
  • Across stack copies: separate worktrees and concurrent agents receive conflict-free bindings while retaining stable endpoint identities.

One canonical stack root represents one independently runnable stack. portreeve.stack.json belongs to the project and describes relationships. PortReeve's database owns current assignments, generations, activations, and leases. Project tooling still owns execution.

From a durable claim to a proven binding

PortReeve separates persistent intent from one startup attempt:

Concept Meaning
Claim The durable identity and sticky port preference of one published endpoint
Generation One immutable, coherent endpoint plan prepared for the whole stack
Activation One attempt to run a selected generation
Lease Temporary authority for one activation to bind an assigned endpoint
sequenceDiagram
  actor Initiator as You or agent
  participant Tooling as Integration tool
  participant Server as PortReeve Server
  participant Service as Provider service
  participant OS as Listener evidence

  Initiator->>Tooling: Start
  opt Standalone endpoint
    Tooling->>Server: Allocate endpoint
    Server-->>Tooling: Assigned port + lease
  end
  Tooling->>Server: Apply stack definition
  Note over Server: Create or update durable claims
  Tooling->>Server: Prepare stack
  Server-->>Tooling: Immutable generation G17
  Tooling->>Server: Begin activation for G17
  Server-->>Tooling: Activation A42 + endpoint leases
  Tooling->>Server: Resolve A42
  Server-->>Tooling: Coherent service addresses
  Tooling->>Service: Start with assigned endpoints
  Service->>OS: Bind listener
  Tooling->>Server: Confirm lease after bind
  Server->>OS: Inspect fresh ownership evidence
  Server-->>Tooling: Binding confirmed
  Note over Tooling,Service: Project health remains project-owned
  Tooling->>Server: End activation and release leases
Loading

For a standalone service, allocation and withPort() hide much of this negotiation. For a stack, prepare creates the coherent generation, resolve supplies its addresses, and confirm proves that the expected provider owns each binding. Confirmation proves ownership, not application readiness.

Trust live ownership evidence

Fresh lsof listener evidence is live authority for host ports. A stored process identifier can help explain history, but it is not proof: PIDs can go stale and be reused.

Docker confirmation uses running-container state, exact PortReeve labels, and publication evidence. Normal reclaim remains both ownership-bound and evidence-bound. PortReeve refuses to kill an unrelated listener merely because a stale claim remembers the same number. Unsafe any-owner eviction exists only as a separate, explicit last resort.

Boundaries and next steps

PortReeve coordinates local TCP addresses. It is not a general project-process supervisor, Docker Compose replacement, startup-order engine, secret manager, application health system, reverse proxy, DNS server, or sandbox control plane. It can verify ordinary Docker-backed endpoints, but it does not currently provide Docker Sandbox orchestration or integration.

PortReeve sends no telemetry and does not load project .env files.

Open PortReeve Desktop

Install the current preview through Homebrew or download the architecture-specific DMG from the GitHub Releases page, then open PortReeve from Applications. In Desktop, open Service and choose Install and Start PortReeve to place the verified bundled CLI in its managed per-user location and configure launchd. Then use Quick Start to try one existing project or Integrations to connect a stack.

To build Desktop from source instead, use the public repository and pinned Bun 1.3.14 toolchain:

git clone https://github.com/TrentBrown/portreeve.git
cd portreeve
bun install --frozen-lockfile
bun run build

PORTREEVE_DESKTOP_CLI_PATH="$PWD/dist/portreeve" bun run desktop:start

Use PortReeve without Desktop

The Homebrew formula, direct macOS/Linux downloads, and source build all provide the same complete CLI. Run a temporary foreground server with:

portreeve serve

Or install the supervised per-user service directly:

portreeve install
portreeve start
portreeve status --json

For a source build, substitute ./dist/portreeve; for example, ./dist/portreeve status --json.

Installation does not require root. PortReeve uses launchd on macOS and systemd --user on Linux. The JavaScript client archive is retained in the release evidence, but npm publication remains deferred.

Documentation

Platform support

PortReeve Desktop supports macOS. Standalone CLI and MCP artifacts support macOS and Linux. The JavaScript client supports its documented Node.js and Bun runtimes when it can reach the local Unix socket. Windows is not supported.

License

MIT