Skip to main content

Port Manager for Development Environments

Project description

Portman

Port Manager for Development Environments

Portman automatically manages port allocations across multiple git worktrees and development contexts, preventing port conflicts when running Docker services.

The Problem

When working on multiple branches or worktrees of the same project, Docker services (PostgreSQL, Redis, etc.) conflict on ports. You end up manually managing port assignments, which is error-prone and time-consuming.

Example: Running PostgreSQL on port 5432 in worktree A crashes when you start the same service in worktree B.

The Solution

Portman provides:

  • Automatic port allocation - Each worktree gets unique ports
  • Machine-wide uniqueness - No conflicts across any projects
  • Context-aware - Automatically detects your project and branch
  • direnv integration - Ports are automatically available as environment variables
  • Docker Compose discovery - Auto-detects services from docker-compose.yml
  • Zero configuration - Works out of the box

Installation

Using uv (recommended)

uv tool install portman-cli

Using pip

pip install portman-cli

From source

git clone https://github.com/jpoutrin/portman-cli.git
cd portman-cli
uv pip install -e .

Quick Start

1. Basic Usage

Book a port for a service in your current worktree:

portman book postgres

Get the allocated port:

portman get postgres
# Output: 5432

2. Auto-discovery from docker-compose.yml

If you have a docker-compose.yml file, Portman can automatically discover and book ports for all services:

portman book --auto

This scans your docker-compose.yml and allocates ports for each service.

3. direnv Integration (Recommended)

Add to your .envrc:

eval "$(portman export --auto)"

Then allow direnv:

direnv allow

Now your environment variables are automatically set:

echo $POSTGRES_PORT
# Output: 5432

echo $REDIS_PORT
# Output: 6379

When you switch worktrees, the ports change automatically!

Common Workflows

Working with Multiple Worktrees

# In worktree main
cd ~/projects/myapp-main
portman book postgres
portman get postgres
# Output: 5432

# In worktree feature
cd ~/projects/myapp-feature
portman book postgres
portman get postgres
# Output: 5433  (different port, no conflict!)

Using with Docker Compose

Update your docker-compose.yml to use environment variables:

services:
  postgres:
    image: postgres:15
    ports:
      - "${POSTGRES_PORT:-5432}:5432"

  redis:
    image: redis:7
    ports:
      - "${REDIS_PORT:-6379}:6379"

Then in your .envrc:

eval "$(portman export --auto)"

Manual Port Allocation

Prefer a specific port:

portman book postgres --port 5555

Book multiple services:

portman book postgres
portman book redis
portman book mongodb

List All Allocations

See all port allocations across all contexts:

portman list

See allocations for the current context only:

portman list --current

Clean Up

Release a specific service in the current context:

portman release postgres

Release all ports for the current context:

portman release --all

Remove allocations for deleted worktrees:

portman prune

Remove stale allocations (not accessed in 30 days):

portman prune --stale 30

Commands Reference

portman book

Book a port for a service.

# Book with auto-assigned port
portman book <service>

# Book with preferred port
portman book <service> --port <port>

# Auto-discover from docker-compose.yml
portman book --auto

portman get

Get the allocated port for a service (for scripting).

portman get <service>

# With quiet output (just the port number)
portman get <service> --quiet

portman export

Export environment variables for direnv.

# Manual services
portman export postgres redis

# Auto-discover from docker-compose.yml
portman export --auto

# With custom format
portman export postgres --format "POSTGRES_URL=postgresql://localhost:{port}/db"

portman list

List all port allocations.

# All contexts
portman list

# Current context only
portman list --current

# Show system ports
portman list --system

portman release

Release port allocations.

# Release specific service
portman release <service>

# Release all in current context
portman release --all

portman prune

Clean up orphaned or stale allocations.

# Dry run (show what would be removed)
portman prune --dry-run

# Remove orphaned allocations
portman prune

# Remove allocations not accessed in N days
portman prune --stale 30

# Force without confirmation
portman prune --force

portman init

Initialize direnv integration.

# Add export to .envrc
portman init

# Just show the command
portman init --print

portman config

Manage port ranges.

# Show current configuration
portman config --show

# Set port range for a service
portman config --set-range postgres:5400-5500

portman status

Show system information and diagnostics.

portman status

How It Works

  1. Context Detection: Portman generates a unique hash based on your project path and git worktree
  2. Database: Port allocations are stored in a SQLite database at ~/.local/share/portman/allocations.db
  3. Port Allocation:
    • Checks if port is already allocated for this context
    • Scans system for ports in use
    • Allocates from service-specific ranges (e.g., 5432-5532 for PostgreSQL)
    • Guarantees machine-wide uniqueness
  4. direnv Integration: Exports environment variables that update automatically when you switch directories

Configuration

Port ranges are configurable per service. Default ranges:

  • PostgreSQL: 5432-5532
  • Redis: 6379-6479
  • MongoDB: 27017-27117
  • MySQL: 3306-3406

Set custom ranges:

portman config --set-range postgres:5400-5500

Requirements

  • Python 3.10 or higher
  • Git (for context detection)
  • direnv (optional, for automatic environment variable management)

License

MIT

Contributing

Contributions are welcome! Please open an issue or pull request on GitHub.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

portman_cli-1.0.0.tar.gz (63.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

portman_cli-1.0.0-py3-none-any.whl (19.9 kB view details)

Uploaded Python 3

File details

Details for the file portman_cli-1.0.0.tar.gz.

File metadata

  • Download URL: portman_cli-1.0.0.tar.gz
  • Upload date:
  • Size: 63.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for portman_cli-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3e5e04c8d7324ed3340ada84679a920c46cf14fc9cdfdb05a9dea9065dd37116
MD5 06224ce160732a8954a44ad928d23558
BLAKE2b-256 707807e4a5c1d77cab71c0d4d64f9977f3ce94876e324a6b8f1b186c243bd50c

See more details on using hashes here.

Provenance

The following attestation bundles were made for portman_cli-1.0.0.tar.gz:

Publisher: release.yml on jpoutrin/portman-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file portman_cli-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: portman_cli-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 19.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for portman_cli-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 528382765404388295f9d2edb8275471c8a63fa68870a61b1929572573dddabd
MD5 0d0a553fc65cbd0180763a534f1926cb
BLAKE2b-256 facd4a22856a31e0e6e3baf8bb48a46282c5b9bc246a7b5375b4e2a08fd3dc00

See more details on using hashes here.

Provenance

The following attestation bundles were made for portman_cli-1.0.0-py3-none-any.whl:

Publisher: release.yml on jpoutrin/portman-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page