Metadata-Version: 2.4
Name: portm
Version: 0.1.0
Summary: A developer-friendly port manager for Linux and macOS — inspect and free ports safely.
Project-URL: Homepage, https://github.com/ayushkcs/portman
Project-URL: Repository, https://github.com/ayushkcs/portman
Project-URL: Issues, https://github.com/ayushkcs/portman/issues
Author-email: Ayush Kumar <kayush2k02@gmail.com>
License: MIT
Keywords: cli,developer-tools,kill,lsof,port,process
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: System :: Networking
Requires-Python: >=3.10
Requires-Dist: fastapi>=0.110
Requires-Dist: psutil>=5.9
Requires-Dist: pydantic>=2.6
Requires-Dist: rich>=13.0
Requires-Dist: sse-starlette>=2.1
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn>=0.29
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# 🛜 Portman

**A developer-friendly port manager for Linux and macOS.** Inspect active ports,
see what's running on them, and free them with a single safe command — from the
terminal or a live web dashboard.

No more `lsof -i :3000` → squint at the PID → `kill -9`. Just:

```bash
portman kill 3000
```

## Why

During local development, ports get stuck behind orphaned or forgotten
processes. The usual fix is multi-step and easy to get wrong — including killing
the wrong thing. Portman collapses it into intuitive commands with a safety net:
it **refuses to casually kill critical daemons** (`systemd`, `sshd`, `dockerd`,
databases, PID 1 …) and escalates gracefully (SIGTERM → wait → SIGKILL) instead
of going straight to `kill -9`.

## Install

```bash
pipx install portm
```

(The PyPI package is `portm`; the command it installs is `portman`.)

From source (with the dashboard):

```bash
cd web && npm install && npm run build && cd ..
pip install .
```

## CLI

```bash
portman list [--range 3000-9999] [--all] [--json]   # what's listening
portman check <port>                                 # free? or what's on it
portman info <port>                                  # full detail
portman kill <port> [--force] [--yes] [--force-protected]
portman watch [--range 3000-9999]                    # live auto-refresh table
portman serve [--port 8765] [--expose]               # launch the web dashboard
```

Exit codes: `0` success · `1` port occupied (`check`) · `2` failed · `3` blocked
by the safety guard. Read commands accept `--json` for scripting.

### The hero command

`portman kill <port>` discovers every PID on the port, refuses protected
processes (unless `--force-protected`), previews exactly what will die, sends
`SIGTERM`, waits, then `SIGKILL`s any stragglers, and finally verifies the port
is actually free.

## Web dashboard

```bash
portman serve
```

Opens a polished dark dashboard (live table via SSE, filters, per-row "Free"
with a confirmation modal and graceful/force toggle). The server binds to
`127.0.0.1` only and gates the destructive `DELETE` endpoint behind a per-launch
token (passed in the launch URL), so a malicious page in your browser can't free
your ports behind your back. Use `--expose` to bind on `0.0.0.0` (with a loud
warning).

API docs are auto-generated at `/docs`.

## Architecture

A shared **core library** holds all logic; the CLI and the web API are thin
layers over it, so behaviour is identical everywhere and the risky part
(killing) lives in one well-tested place.

```
portman/core/   scanner · killer · safety · models · exceptions
portman/cli/    Typer + Rich
portman/api/    FastAPI + uvicorn (serves the bundled UI)
web/            Vite + React + Tailwind dashboard → builds into portman/api/static
```

## Develop

```bash
pip install -e ".[dev]"
pytest                      # core + API + CLI tests (psutil mocked)
ruff check portman tests

cd web
npm install
npm run dev                 # Vite dev server, proxies to `portman serve --no-token`
```
