跳到主要内容

hermes-windows-ports

❖ Communityv0.1.0

Answer "who holds this port" on Windows. win_port_owners reads the TCP and UDP owner tables through iphlpapi (the same rows netstat -ano prints, with the owning PID attached) and resolves each PID to its image name and path, returning one structured record per endpoint. Filters cover one port, several ports, a process substring, the protocol (tcp, udp or both), the TCP state (listen, established, any state name, or all; UDP rows report bound) and IPv6 inclusion, with a record cap and a per-process summary of the rows returned. Built for the failure mode that stalls agents on Windows: a gateway, backend or bridge that cannot bind, where the error names a port but not the process holding it. netstat -ano prints columns, not fields, and its PID still needs a second command (tasklist, or a PowerShell round-trip) to become an image name; this tool is one in-process call instead of a shell parse plus a join, with no child process and no dependency on PowerShell being installed or allowed by execution policy. A protected process whose image cannot be queried keeps its PID and reports a null process name instead of failing the call.

Open in Hermes Desktop
hermes plugins install hermes-windows-ports

What it adds

Tools 1

win_port_owners

README

From the reviewed commit aa49f6a ↗; it updates when the author re-pins.

hermes-windows-ports

Answer "who holds this port" on Windows, from inside Hermes.

win_port_owners({"port": 3000})
win_port_owners({"state": "listen", "process": "hermes"})
win_port_owners({"protocol": "tcp", "state": "established", "limit": 20})

win_port_owners reads the same tables netstat -ano prints — GetExtendedTcpTable / GetExtendedUdpTable with the owning PID attached — and resolves each PID to its image name through QueryFullProcessImageName. The result is structured JSON, not localized console text, so it does not depend on the machine's display language.

{
  "ok": true,
  "matched": 8,
  "listeners": 8,
  "total_endpoints": 121,
  "entries": [
    {"protocol": "tcp", "address": "127.0.0.1", "port": 8086, "state": "listen",
     "pid": 496, "process": "fc-core.exe", "path": "C:\\...\\fc-core.exe",
     "remote_address": "0.0.0.0", "remote_port": 0}
  ],
  "by_process": {"fc-core.exe": 4, "System": 1},
  "notes": ["8 endpoint(s) matched out of 121 in the table"]
}

Why this exists

Port conflicts are one of the most common ways an agent stalls on Windows: a gateway, a backend or a bridge cannot bind, and the error text names a port but not the process holding it. The obvious workaround — running netstat -ano through the terminal tool — has two problems: its output is localized (so parsing column headers breaks on a non-English machine), and the PID it prints has to be resolved to a name by a second command whose output is localized in the same way.

This plugin does the lookup once, in-process, and returns fields instead of columns. It is the read-only half of the same question whether you are debugging EADDRINUSE, hunting a stale process that survived a crash, or checking that only 127.0.0.1 is listening.

Requirements

  • Windows 10 or 11.
  • Hermes 0.21.4 or newer.
  • Nothing else: stdlib only (ctypes), no Python dependencies, no child processes, no network.

Install

git clone https://github.com/Yicheng-Mark/hermes-windows-ports \
  ~/.hermes/plugins/hermes-windows-ports
hermes plugins enable hermes-windows-ports

Filters

Argument Meaning
port / ports One port or several, matched on the local endpoint
process Case-insensitive substring of the image name or path
protocol tcp, udp or both (default)
state listen, established, any TCP state name, or all (default); UDP rows report bound
include_ipv6 Read the IPv6 tables too (default true)
limit Maximum endpoints returned (default 100, max 500)

Behaviour and limits

  • Read-only. No socket is opened or bound, no connection is made.
  • Some system processes (pid 4 = System, pid 0 = System Idle) are labelled; a protected process whose image cannot be queried keeps its PID and reports process: null instead of failing the whole call.
  • by_process summarises the returned rows so a caller can see at a glance that, say, four listeners belong to one binary.
  • Windows only. Other platforms get a structured error.

Disclosure

  • Reads the local TCP/UDP tables and resolves PIDs to image paths. Output includes local and remote addresses, ports, PIDs and process image paths — the same information netstat -ano plus Task Manager shows. Treat it like any other local diagnostic output.
  • No network activity. The plugin does not open, bind or connect a socket; it only reads the kernel's tables.
  • Read-only process access. QueryFullProcessImageName with PROCESS_QUERY_LIMITED_INFORMATION — the minimum right needed to read an image name. No memory reads, no handles inherited, no injection.
  • No child processes, no files written, no self-update. Stdlib only (ctypes).

Tests

python -m pytest tests -q

14 tests: filters, protocol/state handling, limits and error paths against a fake table on every platform, plus live tests on Windows that bind a socket and find it again through the tool, and cross-check the table size. See VALIDATION.md.

License

MIT.

Disclosure

hermes-dpapi-secrets❖ Community★ 0

Resolve Hermes environment variables at startup from a single secret file encrypted with the Windows Data Protection API, instead of keeping provider keys in plaintext in .env or auth.json. Config is secrets.dpapi.map, an ENV_VAR -> store-name mapping (bare names or dpapi:// names) plus an optional file path (default <HERMES_HOME>/secrets.dpapi). The file is one DPAPI blob keyed by the current Windows user profile, so it is unreadable by another Windows account and worthless off the machine; it is written by the bundled CLI (python -m hermes_dpapi_secrets set NAME, value read from a prompt or stdin, never from argv) and only read at runtime. Mapped names that are missing or empty are skipped with a warning; a file that is not ours, a blob this user cannot decrypt, or a payload that is not a flat string map is reported as an error with nothing injected.

Tools
hermes-wincred❖ Community★ 0

Resolve Hermes environment variables from the current user's Windows Credential Manager at startup, instead of keeping provider keys in plaintext in .env or auth.json. Config is secrets.wincred.map, an ENV_VAR -> generic-credential-target mapping (bare names or wincred:// names); each value is read with CredReadW in the current user's vault and handed to the secret-source orchestrator, which applies it with the usual precedence, provenance and conflict rules. Values may be UTF-8 or UTF-16LE (cmdkey and the Credential UI write UTF-16); anything that does not decode to text, or that contains interior NULs, is skipped with a warning instead of being injected as a mangled key.

Tools
hermes-windows-eventlog❖ Community

Answer "why did this process die" on Windows: three read-only tools over the Windows Event Log. win_crash_events reads Application Error / Application Hang / Windows Error Reporting / .NET Runtime records for a time window, decodes the exception code (0xC0000005 -> ACCESS_VIOLATION and the other codes a debugger would name), reports the faulting module, its path and the fault offset, and groups repeated crashes by app and signature. Records are classified by provider as well as by event id, so unrelated providers that reuse ids 1000 and 1001 for informational events are not reported as crashes. win_shutdown_events reads the System log for Kernel-Power 41 unexpected restarts, bugchecks decoded to names (0x9F -> DRIVER_POWER_STATE_FAILURE, accepting the decimal form some providers emit), EventLog 6008 dirty shutdowns, 1074 operator-initiated restarts with the process and comment, and the 6005/6006/12/13 start and stop markers. win_eventlog_query is the general case: any channel, filtered by event ids, levels, an exact provider name or a payload substring, returning structured records instead of raw XML. Queries read newest-first and stop at the window start or at a 5000-record scan cap; a call returns at most 200 records and marks truncated payload text. Channel names, provider names and numeric filters are validated before anything is interpolated into the query.

Tools
hermes-windows-ops❖ Community★ 0

Windows and WSL triage skills for Hermes: processes that survive a quit (orphaned stdio MCP trees, lingering python/uv/node children), WSL-to-Windows interop where an argument reaches cmd.exe as shell syntax, config and encoding traps (UTF-8 BOM, legacy console code pages), and long-path or reserved-name errors. One skill plus a copy-paste command reference; the process, argv and job-object failure modes are pinned to reports #131561, #132069 and #61059 and re-verified against current main.

Tools
hermes-wsl-terminal❖ Community★ 0

Run Hermes' terminal tools inside an existing WSL distro on Windows: one bash -c per command as the distro's default user, over the same files Windows sees at /mnt/<drive>, with no Docker Desktop, no image and no container to start or tear down. A host cwd is translated (C:\Users\me\proj becomes /mnt/c/Users/me/proj, \\wsl.localhost paths become the distro's own paths) and the mount root is asked once with wslpath, so a distro that moved its automount point still gets correct paths. cwd persists across commands, stdin and exit codes ride through wsl.exe, and hermes doctor / setup and the dashboard picker get real rows (wsl.exe path, WSL version, distros present, selected distro). HERMES_WSL_DISTRO and HERMES_WSL_USER select the distro and the user.

Tools
hermes-wslc-sandbox❖ Community★ 0

Run Hermes' terminal, file and execute_code tools in a Linux container on Microsoft's WSL Containers (wslc) runtime, so Windows users who run WSL Containers get a sandbox without Docker Desktop.

Tools

← Back to the catalog · catalog built Oct 23, 2026