Busy ports are one of those tiny problems that interrupt real work far more often than they should.
You start a dev server, a local database, a preview app, or a test runner, and something fails because a port is already in use. Then the usual dance begins:
- check what is using the port
- figure out whether it is safe to stop
- kill the process
- retry your actual work
That friction is exactly why I built ferman.
ferman is a small cross-platform CLI for inspecting busy ports, identifying the process behind them, and freeing them safely.
It is built for developers, but also for AI agents, scripts, and local automation workflows that need deterministic output and low ambiguity.
Why I built it
The core problem is simple:
- a port is occupied
- you need to know what is using it
- you may want to free it
There are already OS-level commands for this, but they are not consistent across platforms, and they are not especially friendly for automation.
On macOS and Linux you might use lsof.
On Windows you might use netstat, tasklist, and taskkill.
If you are scripting around those commands, you also end up dealing with parsing, platform branching, and error handling.
I wanted one clean command that:
- works across platforms
- stays small
- is readable for humans
- is structured for machines
What ferman does
At the simplest level:
npx ferman 3000
It validates the port, checks whether it is busy, identifies the matching process when possible, and asks before termination.
There are a few core modes:
ferman 3000
ferman 3000 --force
ferman 3000 --dry
ferman 3000 --json
ferman 3000 --toon
It also supports more AI-oriented flows:
ferman 3000 5173 5432 --json
ferman --common --json
ferman --plan --json
ferman --doctor --json
ferman --json-schema
ferman 3000 --watch --json
Built for humans and agents
One thing I cared about from the start was making the tool work well in two very different contexts:
- a developer using a terminal manually
- a script, CI job, or AI agent using structured output
For humans, the CLI stays minimal and readable.
For machines, the output is deterministic and stable.
Example JSON output:
{
"ok": true,
"code": "PORT_RELEASED",
"port": 3000,
"busy": true,
"processes": [
{
"pid": 1234,
"name": "node"
}
],
"action": "killed",
"message": "Port released."
}
Example error output:
{
"ok": false,
"code": "INVALID_PORT",
"message": "Port must be a whole number."
}
That matters because once the output contract is stable, the CLI becomes much easier to compose into larger workflows.
AI-facing features
Over time, I pushed the project beyond the original “free a port” use case.
The current AI-facing surface includes:
- strong JSON contract
- stable machine error codes
- TOON output for compact LLM-oriented structured data
- multi-port support
-
--commonfor common local development ports -
--planfor recommendation output -
--doctorfor local environment diagnosis -
--json-schemafor machine contract discovery -
--watchfor repeated snapshot events
This makes ferman more useful for:
- local AI coding agents
- shell automation
- CI helpers
- internal dev tooling
- MCP-style wrappers and structured integrations
A few examples
Inspect without changing anything:
ferman 3000 --dry
Release immediately:
ferman 3000 --force
Check several ports at once:
ferman 3000 5173 5432 --json
Scan common dev ports:
ferman --common --json
Ask for the recommended next step:
ferman 3000 --plan --json
Get the output schema for integrations:
ferman --json-schema
Watch a port over time:
ferman 3000 --watch --json
Under the hood
The project is built in TypeScript and keeps dependencies intentionally small.
Platform-specific behavior is abstracted behind separate adapters:
- macOS
- Linux
- Windows
The docs are built with VitePress, tests run with Vitest, and the package is published through GitHub Actions with trusted publishing.
I also added:
- ESLint
- Prettier
- Husky
- smoke checks
- release checks
So even though the tool is small, the release workflow is treated seriously.
What I like about the result
I like that ferman stays narrow.
It does not try to be a general system monitor or a giant process manager.
It focuses on one annoying workflow and makes it much easier:
- find what is using a port
- understand whether action is needed
- free the port when appropriate
That is enough to be useful every day.
Try it
If you want to try it:
npx ferman 3000
Project links:
- GitHub: https://github.com/borakilicoglu/ferman
- npm: https://www.npmjs.com/package/ferman
- Docs: https://borakilicoglu.github.io/ferman/
If you build internal tooling, local automation, or AI-assisted developer workflows, I think this kind of CLI surface is worth investing in.
Small tools with predictable interfaces compound well.
Top comments (0)