用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/lukemcqueen/hermes-cortex --skill dev-port-conflict命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Cross-server agent health monitoring using binary status vectors — deploy health endpoints on each agent, poll from orchestrator, alert on state transitions.
Wire a self-hosted Langfuse instance to Hermes Agent — generate API keys, configure env vars, enable the bundled plugin, install SDK, and verify traces flow.
Use before enforcement code changes or shared-repo commits.
正在显示 SKILL.md
| name | dev-port-conflict |
| description | Diagnose and clear an orphaned server holding a dev port. |
| version | 1.0.0 |
| category | devops |
| license | MIT |
| platforms | ["linux","macos"] |
| metadata | {"hermes":{"tags":["debugging","ports","dev-server","orphan","eaddrinuse"],"related_skills":["web-ui-debugging","prevent-crash-looping"]}} |
A project's ./run dev (or next dev / uvicorn) fails with
Error: listen EADDRINUSE: address already in use :::<port> because a
previous run's server is still alive and squatting on the port. The classic
culprit is an orphaned dev server: the terminal that launched it exited,
so the process was reparented to init (macOS launchd / PPID 1) and now lives
forever holding 13201/13202 etc. It is leftover, not wanted. This skill walks
find-holder → prove-stale → free → verify.
./run dev, ./run dev:web, ./run dev:api (or any dev command) fails to
start with EADDRINUSE / "address already in use".lsof shows a node/python process you
did not start.Don't use for: page shows rows/empty despite the API returning data (that is
web-ui-debugging); systemd services crash-looping (that is
prevent-crash-looping).
Find the holder.
lsof -nP -iTCP:<port> -sTCP:LISTEN
-nP suppresses name/port resolution (fast, no DNS); -sTCP:LISTEN
confines to listeners. Note the PID and what the command actually is.
Completion: an output line with PID + command, or the port genuinely free.
Trace the ancestry to classify orphan vs managed. The command that
matters is often the grandparent, not the PID lsof returned (a
next-server child → next dev parent → pnpm exec next dev grandparent).
ps -o pid,ppid,etime,command -p <pid> # repeat for its PPID
Orphan signature: the top ancestor has PPID 1 (reparented to launchd after its terminal died) and an elapsed time of minutes-to-hours. An actively-managed server has a sitting terminal or a supervisor ancestor.
Completion: you can state the full lineage and whether the top ancestor is PPID 1.
Confirm no steward will respawn it. PPID 1 alone doesn't mean unsupervised — check for a keepalive:
launchctl list 2>/dev/null | grep -iE '<name>' # macOS
If a launchd/systemd label owns it, killing it makes the steward respawn
it — don't fight the supervisor. A plain pnpm/next/uvicorn orphan
reparented to launchd with NO matching launchd label is free to kill.
Completion: you know whether the process is supervised (do not kill) or a dead-fit orphan (safe to kill).
Clean SIBLING ports, not just the reported one. A dev command binds
several ports (e.g. a project's web 13201, api 13202). EADDRINUSE surfaces on the
first busy one and hides the rest. After the fix, check every port the
command binds so the next ./run dev doesn't fail one step later:
lsof -nP -iTCP:<port2> -sTCP:LISTEN # repeat for each sibling
Completion: every port the dev command binds has been checked.
Kill the orphaned tree (TERM first), then verify.
kill -TERM <top> <mid> <leaf> 2>/dev/null; sleep 2
lsof -nP -iTCP:<port> -sTCP:LISTEN || echo "port FREE"
ps -p <pids> 2>/dev/null || echo "orphan pids gone"
Completion: the port prints FREE and the orphan PIDs are gone.
port FREE and orphan pids gone../run dev. Don't start the server on their behalf
from an agent session, and don't claim done until the reproducible lsof
check shows the bind is available.next dev parent
alive and it may respawn or keep a lock. Pass the full PID chain.next dev v15.5.18, 1h10m) masked an API orphan on 13202
(uvicorn, 3h08m). Both cleared before ./run dev was clean.curl -s -o /dev/null -w '%{http_code}' --max-time 3 http://localhost:<port>/.
A 301/307/200 proves it is serving; combined with PPID-1 ancestry and no
steward, that is a stale leftover by definition — not a wanted server.Example (2026-08-20): ./run dev → EADDRINUSE :::13201, exit 48.
lsof → node PID 60768. Ancestry 60768→60762→60629
(node .../pnpm exec next dev -p 13201), top at PPID 1, 1h10m, no launchd
label → dead-fit orphan. Same sweep found uvicorn orphan PID 3317 on 13202
(3h08m, PPID 1). TERM'd the full trees; both ports verified free via lsof;
user re-ran ./run dev clean.