# portman — Port Manager User Guide

**Version 1.0** | Engineered by **Codermasky**

A global port registry for all your containerized projects on **macOS, Linux, and Windows (WSL2)**

---

## Overview

`portman` solves the port conflict problem for developers running multiple Docker Compose projects. Instead of manually tracking ports across 15+ projects in `~/Sandbox`, portman maintains a **global, conflict-free registry** that auto-assigns ports and prevents collisions.

**The problem it solves:**
- Manually editing `docker-compose.yml` and guessing ports → constant conflicts
- Different projects using the same port (3000, 8000, 5432, etc.)
- Forgot which ports are taken → Docker startup fails
- No way to know what's actually listening on your Mac

**The solution:**
- One command to set up a new project: `portman new myapp`
- Never think about port ranges again — portman enforces them
- Check for conflicts instantly: `portman check`
- See what's listening: `portman scan`
- Copy-paste docker-compose snippets: `portman export myapp`

---

## Getting Started (5 Minutes)

### 1. Install portman

```bash
cd ~/Sandbox/portman
bash install.sh
source ~/.zshrc    # or ~/.bashrc, ~/.bash_profile, etc.
```

### 2. Auto-assign ports to all projects in your workspace

```bash
portman workspace init ~/Sandbox
```

This scans your entire workspace, finds all Docker projects, and assigns them unique conflict-free ports.

### 3. Done! Start using portman

```bash
portman list                          # View all assignments
portman workspace report              # See detailed report
portman export agentstack | pbcopy    # Copy ports to clipboard for a project
```

---

## Installation Details

### Requirements

- **Python 3.7+** (usually pre-installed on macOS/Linux, available via Windows Store on Windows 11)
- **bash/zsh/fish** shell (automatic on macOS/Linux, native on Windows 11, or use WSL2)

### One-time Setup

```bash
cd ~/Sandbox/portman
bash install.sh
source ~/.zshrc    # or ~/.bashrc, ~/.bash_profile, or ~/.config/fish/config.fish
```

This:
1. Copies `portman.py` to `~/.portman/`
2. Creates `~/.portman/registry.json` (the global registry)
3. Adds a shell alias: `portman = python3 ~/.portman/portman.py`

After running the install script, you can use `portman` from any terminal, any directory.

### Platform-Specific Notes

**macOS:** Works out of the box. Uses `lsof` for port scanning.

**Linux (Ubuntu/Debian/etc.):** Works out of the box. Uses `lsof` for port scanning. Install if missing:
```bash
sudo apt install lsof
```

**Windows (WSL2 / Git Bash):** Use Windows Subsystem for Linux 2 (WSL2) or Git Bash with Python 3 installed. Windows `netstat` is supported but less detailed. Recommended: use WSL2 for full compatibility.

---

## Quick Start

### Create a New Project

```bash
portman new agentstack
```

Output:
```
  ┌─ portman  new app: agentstack
  └────────────────────────────────────────────────────────
  ✓ frontend           → 3000  (frontend)
  ✓ backend            → 8000  (backend)
  ✓ postgres           → 5432  (postgres)
  ✓ redis              → 6379  (redis)
  ✓ langfuse           → 3200  (langfuse)
  ──────────────────────────────────────────────────────────
  Saved to ~/.portman/registry.json
  Run `portman export agentstack` for a docker-compose snippet.
```

portman automatically assigns the next available port in each service's range. No conflicts.

### View All Ports

```bash
portman list
```

Shows all projects and their ports in a table with live status (● active, ○ free).

### Export Docker Compose Snippet

```bash
portman export agentstack
```

Output:
```yaml
  # docker-compose.yml — ports for 'agentstack'
  # Generated by portman on 2026-03-14

  frontend:
    ports:
      - "3000:3000"

  backend:
    ports:
      - "8000:8000"

  postgres:
    ports:
      - "5432:5432"

  redis:
    ports:
      - "6379:6379"

  langfuse:
    ports:
      - "3200:3000"
```

Copy-paste directly into your `docker-compose.yml`.

### Check for Conflicts

```bash
portman check
```

Scans the entire registry for duplicate ports (should never happen, but useful for audits).

---

## Workspace Mode

New in portman: **workspace management** allows you to auto-discover all projects in `~/Sandbox` (or any workspace) and bulk-assign ports to all of them at once.

### `portman workspace init [WORKSPACE]`

Auto-discover all Docker projects in a workspace and assign them ports.

**What it does:**
1. Scans the workspace directory for folders with `docker-compose.yml`
2. Assigns standard services to each discovered project:
   - `frontend` (port 3000–3099)
   - `backend` (port 8000–8099)
   - `postgres` (port 5432+)
   - `redis` (port 6379+)
   - `langfuse` (port 3200–3299)
3. Saves all assignments to `~/.portman/registry.json`

**Example:**
```bash
portman workspace init                      # Use ~/Sandbox as default workspace
portman workspace init ~/my-projects        # Use custom workspace path
```

**Output:**
```
  ┌─ portman by Codermasky  workspace init: /Users/sujitm/Sandbox
  └────────────────────────────────────────────────────────
  Discovered 13 project(s):

  ✓ AgentStack                     (5 services)
  ✓ QuestFlow                      (5 services)
  ✓ credo                          (5 services)
  ...

  ──────────────────────────────────────────────────────────
  ✓  Assigned ports for 13 project(s)
  Run `portman list` to view all assignments.
```

---

### `portman workspace list [WORKSPACE]`

List all projects in a workspace and their registration status.

**Options:**
- `WORKSPACE` — Path to workspace (default: `~/Sandbox`)

**Example:**
```bash
portman workspace list
portman workspace list ~/my-projects
```

**Output:**
```
  PROJECT                        SERVICES     STATUS
  ──────────────────────────────────────────────────────────
  AgentStack                     5            ✓ ready
  QuestFlow                      5            ✓ ready
  credo                          0            not registered
  ...
  ──────────────────────────────────────────────────────────
  13 total projects  ·  3 unregistered
```

---

### `portman workspace report [WORKSPACE]`

Generate a detailed port assignment report for all projects in a workspace.

Shows each project, its services, assigned ports, and live status (● active / ○ free).

**Example:**
```bash
portman workspace report
portman workspace report ~/my-projects
```

**Output:**
```
  PROJECT                   SERVICE         PORT     STATUS
  ──────────────────────────────────────────────────────────
  AgentStack                frontend        3000     ○ free
                            backend         8000     ○ free
                            postgres        5432     ○ free
                            redis           6380     ○ free
                            langfuse        3200     ○ free
  QuestFlow                 frontend        3001     ○ free
                            backend         8001     ○ free
                            postgres        5433     ○ free
                            redis           6381     ○ free
                            langfuse        3201     ○ free
  ...
```

---

## Core Commands

### `portman list [--app APP]`

List all registered ports across all projects.

**Options:**
- `--app APP` — Show only one app's ports

**Example:**
```bash
portman list                   # All apps
portman list --app agentstack  # Just agentstack
```

---

### `portman new APP`

Auto-assign standard services for a new project. Creates entries for:
- `frontend` (port 3000–3099)
- `backend` (port 8000–8099)
- `postgres` (port 5432+)
- `redis` (port 6379+)
- `langfuse` (port 3200–3299)

**Example:**
```bash
portman new myproject
```

---

### `portman assign SERVICE --app APP [--port PORT]`

Register a single service for a project.

**Options:**
- `--app APP` — **Required.** Project name
- `--port PORT` — Optional. Specific port number. If omitted, portman auto-picks the next free port

**Examples:**
```bash
portman assign clickhouse --app agentstack       # Auto-assign next free clickhouse port
portman assign nginx --app myapp --port 8090     # Use specific port
```

---

### `portman release SERVICE --app APP`

Remove a port registration (free it up).

**Example:**
```bash
portman release redis --app agentstack
```

---

### `portman rm APP`

Delete an entire project from the registry.

**Example:**
```bash
portman rm old-prototype
```

---

### `portman check [--app APP]`

Detect port conflicts in the registry. Shows status of every port (● active vs ○ free).

**Options:**
- `--app APP` — Check only one app

**Example:**
```bash
portman check              # Full audit
portman check --app credo  # Just one app
```

---

### `portman scan`

Live scan of what's actually listening on your Mac (uses `lsof`). Cross-references with the registry to show unregistered ports.

**Example:**
```bash
portman scan
```

Output:
```
  PORT     PROCESS          PID      REGISTRY
  ──────────────────────────────────────────
  3000     node             12345    ✓ agentstack/frontend
  8000     python           12346    ✓ agentstack/backend
  5432     postgres         12347    ✓ agentstack/postgres
  9200     java             12348      unregistered
```

This helps you spot processes you forgot to register or old services still running.

---

### `portman export APP`

Print a ready-to-paste `docker-compose.yml` ports section for a project.

**Example:**
```bash
portman export trading-platform | pbcopy
```

(Copy to clipboard on macOS)

---

### `portman dashboard`

Generate and open an interactive HTML dashboard showing:
- Visual port map for all projects
- Conflict detection with color coding
- Port range usage bars
- One-click copy buttons for each port
- CLI quick-reference

**Example:**
```bash
portman dashboard
```

Opens `~/.portman/dashboard.html` in your default browser.

---

## Port Ranges

portman enforces these ranges automatically. Each service type has its own zone to prevent overlap:

| Service Type | Host Port Range | Purpose |
|---|---|---|
| `frontend` | 3000–3099 | React, Vue, Next.js, Vite frontends |
| `backend` | 8000–8099 | FastAPI, Node.js, Flask, Django servers |
| `postgres` | 5432–5532 | PostgreSQL databases |
| `redis` | 6379–6479 | Redis cache |
| `langfuse` | 3200–3299 | Langfuse observability UI |
| `clickhouse` | 8123–8222 | ClickHouse analytics |
| `minio` | 9000–9099 | MinIO object storage |
| `grafana` | 3300–3399 | Grafana dashboards |
| `nginx` | 80–89 | Nginx reverse proxy |
| `elasticsearch` | 9200–9299 | Elasticsearch search |

**Why ranges?** They let you run multiple instances of each type (e.g., 3 databases: 5432, 5433, 5434) without worrying about conflicts with other service types.

---

## Next Steps After Installation

### Option 1: Auto-Setup Your Entire Workspace (Recommended)

```bash
portman workspace init ~/Sandbox
```

This is the fastest way to set up all your projects at once. portman will:
1. Scan `~/Sandbox` for all folders with `docker-compose.yml`
2. Auto-discover all your projects
3. Assign unique ports to each project (frontend, backend, postgres, redis, langfuse)
4. Save everything to `~/.portman/registry.json`

Then, for each project:
```bash
portman export <project-name> | pbcopy
# Paste into that project's docker-compose.yml
docker-compose up -d
```

### Option 2: Manual Setup (One Project at a Time)

```bash
portman new my-first-project
portman export my-first-project | pbcopy
# Paste into docker-compose.yml
docker-compose up -d

# Then:
portman new my-second-project
portman export my-second-project | pbcopy
# ... repeat for each project
```

---

## Workflows

### Starting a New Project

```bash
# 1. Create portman entry
portman new my-new-app

# 2. Get docker-compose snippet
portman export my-new-app

# 3. Paste into your docker-compose.yml
# (In your project folder)
cat >> docker-compose.yml << 'EOF'
# Ports auto-assigned by portman
services:
  frontend:
    ports:
      - "3000:3000"
  backend:
    ports:
      - "8000:8000"
  # ... rest of services ...
EOF

# 4. Start containers
docker-compose up -d

# 5. Verify
portman scan
```

---

### Adding a New Service to an Existing Project

```bash
# Project already has frontend, backend, postgres, redis
# Now you want to add Elasticsearch

portman assign elasticsearch --app my-new-app

# Get the port
portman list --app my-new-app

# Add to docker-compose.yml manually or regenerate with portman export
```

---

### Debugging Port Conflicts

```bash
# Something is failing because of a port?

# 1. Check if there's a registry conflict
portman check

# 2. See what's actually listening
portman scan

# 3. If a port is in use by an unknown process:
# - Either stop that process: lsof -i :3000
# - Or reassign portman to a different port

# 4. If portman assigned it incorrectly, fix it:
portman release problematic-service --app myapp
portman assign problematic-service --app myapp --port 3050
```

---

### Cleaning Up Old Projects

```bash
# You're done with a project?
portman rm old-prototype

# This frees up all its ports for reuse
portman list  # Verify it's gone
```

---

## Registry File

portman stores everything in `~/.portman/registry.json`. You shouldn't edit this manually, but it's good to know:

```json
{
  "meta": {
    "created": "2026-03-14T...",
    "version": "1.0"
  },
  "apps": {
    "agentstack": {
      "frontend": {
        "port": 3000,
        "type": "frontend",
        "assigned": "2026-03-14T09:13:00Z"
      },
      "backend": {
        "port": 8000,
        "type": "backend",
        "assigned": "2026-03-14T09:13:00Z"
      }
      // ... more services ...
    }
    // ... more apps ...
  }
}
```

**Key points:**
- Global file: shared across ALL projects in `~/Sandbox`
- Persists across terminal sessions
- Auto-created on first run
- Back it up if you want (optional)

---

## Best Practices

### ✅ DO

- **Check portman before hardcoding ports** in docker-compose
  ```bash
  portman list
  ```

- **Use `portman new` for every new project**
  ```bash
  portman new my-project
  ```

- **Run `portman check` before big deployments**
  ```bash
  portman check
  ```

- **Use `portman scan` to debug startup failures**
  ```bash
  portman scan
  ```

- **Export and paste rather than guessing**
  ```bash
  portman export my-app | pbcopy
  ```

### ❌ DON'T

- **Don't hardcode ports in docker-compose.yml**
  - Always use portman
  - Hardcoded ports conflict with other projects

- **Don't reuse port numbers across projects**
  - portman prevents this, trust it

- **Don't delete projects without freeing ports**
  ```bash
  portman rm my-app  # Cleans up ports
  ```

- **Don't ignore conflict warnings**
  ```bash
  portman check  # Run regularly
  ```

---

## Troubleshooting

### "Port X is already assigned"

```bash
portman check
```

Shows which project/service has the port. Either:
1. Use a different port: `portman assign svc --app myapp --port 3050`
2. Release the old one: `portman release old-svc --app old-app`

---

### "Address already in use"

The port is registered in portman BUT something else is listening on it.

```bash
portman scan
```

Shows what process is listening. Either:
1. Stop that process (it's a stray container from before portman)
2. Reassign portman to a free port

```bash
portman release svc --app myapp
portman assign svc --app myapp --port 3050
```

---

### "portman command not found"

The shell alias didn't install. Run:

```bash
bash ~/Sandbox/portman/install.sh
```

Then reload your shell config:
```bash
# macOS zsh
source ~/.zshrc

# macOS bash
source ~/.bash_profile

# Linux bash
source ~/.bashrc

# Fish shell
source ~/.config/fish/config.fish
```

Then verify:

```bash
portman list
```

If you're on Windows, use WSL2 or Git Bash for best results.

---

### Dashboard Won't Open

```bash
portman dashboard
```

If it doesn't open in your browser automatically, open manually:

```bash
open ~/.portman/dashboard.html
```

---

## Advanced Usage

### Scripting with portman

All portman output is designed to be parseable. Example: Extract all assigned ports for a project:

```bash
portman list --app myapp | grep myapp
```

Or extract JSON from the registry directly:

```bash
cat ~/.portman/registry.json | jq '.apps.myapp'
```

For reference, the source code is at: `~/Sandbox/portman/portman.py`

---

### Custom Port Ranges (not recommended)

If you need a port outside the standard ranges, use `portman assign` with `--port`:

```bash
portman assign custom-service --app myapp --port 7777
```

But this is manual and loses the auto-assign benefit. Better to use the standard ranges when possible.

---

### Sharing Registry Across Team

The registry file `~/.portman/registry.json` is per-user. For team coordination:

1. **Option A:** Share a spreadsheet or wiki with assigned ports
2. **Option B:** Commit `portman` states to a shared repo (advanced)
3. **Option C:** Each dev runs `portman new <project>` independently (simplest)

---

## Summary

### Single Project Commands

| Task | Command |
|---|---|
| Set up new project | `portman new myapp` |
| View all ports | `portman list` |
| View one project | `portman list --app myapp` |
| Add a service | `portman assign svc --app myapp` |
| Remove a service | `portman release svc --app myapp` |
| Get docker-compose snippet | `portman export myapp` |
| Check for conflicts | `portman check` |
| See what's listening | `portman scan` |
| Remove entire project | `portman rm myapp` |
| Open dashboard | `portman dashboard` |

### Workspace Commands (Bulk Operations)

| Task | Command |
|---|---|
| Auto-discover + assign all projects | `portman workspace init [WORKSPACE]` |
| List all projects in workspace | `portman workspace list [WORKSPACE]` |
| Generate workspace report | `portman workspace report [WORKSPACE]` |

**Note:** All workspace commands default to `~/Sandbox` if no workspace path is provided.

---

## Getting Help

- **See all commands:** `portman --help`
- **Command-specific help:** `portman COMMAND --help`
- **Check the source:** `cat ~/Sandbox/portman/portman.py`
- **View registry:** `cat ~/.portman/registry.json`
- **Read this guide:** `cat ~/Sandbox/portman/GUIDE.md`

---

## Quick Cheat Sheet

| Goal | Command |
|---|---|
| **Setup entire workspace at once** | `portman workspace init ~/Sandbox` |
| **See all projects & their status** | `portman workspace list ~/Sandbox` |
| **View detailed port assignments** | `portman workspace report ~/Sandbox` |
| **Setup one new project** | `portman new myapp` |
| **View all ports** | `portman list` |
| **Check for conflicts** | `portman check` |
| **See what's listening** | `portman scan` |
| **Get docker-compose snippet** | `portman export myapp` |
| **Add a service** | `portman assign elasticsearch --app myapp` |
| **Remove a service** | `portman release elasticsearch --app myapp` |
| **Delete entire project** | `portman rm myapp` |
| **Open visual dashboard** | `portman dashboard` |

---

---

## Platform Support

portman is **fully cross-platform**:

| Platform | Status | Notes |
|---|---|---|
| **macOS** | ✅ Full support | Uses `lsof` for port scanning |
| **Linux** | ✅ Full support | Uses `lsof` for port scanning (install: `apt install lsof`) |
| **Windows (WSL2)** | ✅ Full support | Run inside WSL2, all features work |
| **Windows (native)** | ⚠️ Partial | Basic functionality works; port scanning uses `netstat` |
| **Windows (Git Bash)** | ⚠️ Partial | Works but limited; WSL2 recommended |

**Recommendation:** On Windows, use **WSL2** (Windows Subsystem for Linux 2) for the best experience. portman was designed with Unix-like systems in mind, and WSL2 gives you that environment natively.

---

**Happy port managing!** 🎉

Engineered with ❤️ by **Codermasky**
