NAME2PORT — Deterministic Name → Free Port Resolver
===============================================

A small CLI utility that converts a service name (string) into a deterministic TCP port,
checks if that port is already in use, shows what is listening on it, and keeps deriving
new ports until it finds a free one.

Designed for local dev environments, microservices, scripts, containers, and tooling
where you want stable-but-safe port assignment without manual tracking.

Features
--------

• Deterministic name → port mapping
• Automatic collision detection
• Shows what process is using a conflicting port
• Re-derives ports until a free one is found
• Uses psutil when available for best diagnostics
• Falls back to OS tools if psutil is missing
• Works on Linux, macOS, and Windows
• CLI-friendly (prints only the final port to stdout)
• IPv4 and IPv6 host support

Installation (recommended: pip)
--------------------------------

**Fast path (recommended)**

- With PATH-managed shim: `pipx install "name2port[psutil]"`
- Minimal install: `pip install name2port`
- Enable richer listener info later: `pip install psutil`

**From source tree**

```bash
./install.sh                # macOS/Linux helper; supports --yes/--link flags
# or
pipx install .
# or
pip install ".[psutil]"
```

**One-liner (macOS/Linux)**

```bash
curl -fsSL https://raw.githubusercontent.com/ZeitounCorp/name2port/main/install.sh | bash
```

**Windows**

```powershell
pip install name2port
# add %USERPROFILE%\\.local\\bin to PATH if pip chooses that location
```

**Run it**

```bash
name2port bento-pdf
```

Installation (standalone script mode)
-------------------------------------

If you prefer a single file, download `name_to_free_port.py`, make it executable,
and place it on your PATH:

```bash
mkdir -p ~/bin
cp name_to_free_port.py ~/bin/name2port
chmod +x ~/bin/name2port
```

System-wide on macOS/Linux:

```bash
sudo cp name_to_free_port.py /usr/local/bin/name2port && sudo chmod +x /usr/local/bin/name2port
```

Windows: put `name_to_free_port.py` in a directory on PATH (e.g., `C:\tools\`) and run `py name_to_free_port.py <name>`.

Example
-------

```bash
$ name2port bento-pdf
24317
```

If a collision occurs:

```txt
[in use] name-to-port('bento-pdf', salt=0) -> 24317 is already in use.
Listener(s):
127.0.0.1:24317 pid=1234 name=node exe=/usr/bin/node

24389   ← next free port
```

Psutil (optional but recommended)
---------------------------------

Without psutil, the tool still works but has limited process detection.

Install:

pip:

```bash
python -m pip install psutil          # add psutil to existing install
python -m pip install "name2port[psutil]"  # fresh install with extra
```

Ubuntu/Debian:

```bash
sudo apt install python3-psutil
```

Fedora:

```bash
sudo dnf install python3-psutil
```

Arch:

```bash
sudo pacman -S python-psutil
```

Usage
-----

```bash
name2port <name> [options]
```

Options:

```txt
--host           Interface to test binding against (default 127.0.0.1)
--min-port       Minimum port in range (default 20000)
--max-port       Maximum port in range (default 45000)
--max-attempts   Maximum re-derivation tries (default 2000)
```

Example:

```bash
name2port api-service --min-port 30000 --max-port 40000
```

Tips for PATH/bin
-----------------

- `pipx` adds a shim in `~/.local/bin` (usually already on PATH after reloading your shell).
- For `pip install --user`, ensure `~/.local/bin` (Linux/macOS) or `%USERPROFILE%\.local\bin` (Windows) is on PATH.
- If you copied the standalone script manually, placing it at `~/bin/name2port` (user) or `/usr/local/bin/name2port` (system) makes it available everywhere.

Why This Exists
---------------

**Manually tracking service ports leads to:**

- conflicts
- environment drift
- "works on my machine" problems
- brittle config files

**This tool gives:**

- stable + collision-safe ports
- no config files
- works across teams and machines

Notes / Limitations
-------------------

- This tool does NOT reserve the port — it only checks availability.
  For race-safe reservation, bind your server to the returned port immediately,
  or implement a reservation mechanism in your runtime/tooling.
