Skip to main content

hermes-windows-process

❖ Communityv0.1.0★ 0

Answer "what is still running, and who started it" on Windows: win_process_table reads the process table (PID, parent PID, image name) and adds each process's image path and creation time, then marks every row with whether its recorded parent is still the process that spawned it. Windows stores a parent PID rather than a handle, so a child that outlived its parent points at a PID that is either unused or reused by a newer process; a parent that started after its child cannot have spawned it, so both cases are reported as gone or reused instead of a plausible but wrong parent name. Filters cover one PID, several PIDs, a name or path substring, a parent PID, and an orphans-only view of what outlived its parent, with a result cap and an option to leave out Windows session processes. Use it for leftover gateway/backend/server children after a quit, for telling thirty python.exe rows apart by start time, and for checking whether a process started before or after the thing being debugged. Read-only: processes are opened with PROCESS_QUERY_LIMITED_INFORMATION for QueryFullProcessImageName and GetProcessTimes only - no memory reads (command lines are deliberately out of scope), no handle duplication, no writes, no child processes. Stdlib-only (ctypes): no Python dependencies, no network calls, no file writes, no self-update. Windows only.

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

What it adds

Tools 1

win_process_table

README

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

hermes-windows-process

Answer "what is still running, and who started it" on Windows, from inside Hermes.

win_process_table({"process": "hermes"})
win_process_table({"orphans_only": True, "include_system": False})
win_process_table({"pid": 21432, "with_ancestry": True})

The tool reads the same process rows Task Manager does — CreateToolhelp32Snapshot gives PID, parent PID, image name and thread count — then opens each process read-only for its image path and start time. That last field is what makes the parent column mean something: Windows stores a parent PID, not a handle, so once the parent exits its PID is free for reuse, and a child that outlived it points at an unrelated newer process. A parent that started after its child cannot have spawned it.

parent_state Meaning
alive The parent PID belongs to a process that started before this one — the real parent.
gone No process holds that PID any more: the parent exited and this one kept running.
reused The PID is in use, but by a process that started later, so the original parent is gone.
unknown The parent row exists but one of the two start times could not be read.
root Parent PID 0 — the top of the table.

Output

{
  "ok": true,
  "matched": 2,
  "total_processes": 308,
  "orphans": 9,
  "orphans_gone": 9,
  "orphans_reused": 0,
  "entries": [
    {"pid": 10004, "parent_pid": 8640, "process": "cc-switch.exe",
     "path": "C:\\Users\\warri\\AppData\\Local\\Programs\\CC Switch\\cc-switch.exe",
     "started": "2026-10-24T14:19:31Z", "age_seconds": 41040, "threads": 12,
     "parent_process": null, "parent_state": "gone", "system": false}
  ],
  "ancestry": [],
  "notes": ["2 of 308 process(es) matched"]
}

Ordering puts the oldest process first, which is how you find the survivor rather than the thing you just started. ancestry carries the chain up to the top of the table for each matched PID when with_ancestry is set, marked context: true.

Filters

Argument Effect
pid / pids Match specific process IDs.
process Case-insensitive substring of the image name or path.
parent Only processes whose parent PID is this value.
orphans_only Only gone and reused — what outlived its parent.
with_ancestry Add the ancestor chain of each match.
include_system Default true. false drops images under the Windows directory and processes this account cannot open.
limit Default 100, max 500.

Session and bootstrap processes (csrss, wininit, winlogon, services, explorer) are started by a parent that exits by design, so they always read gone without being a leak. They are flagged system: true, and the notes say how many of the flagged rows are theirs.

What it does not do

  • No command lines. Reading another process's command line on Windows means reading its memory (the PEB) through ReadProcessMemory. This plugin does not read process memory, so it reports the image path and start time instead. wmic process get commandline or PowerShell's Get-CimInstance Win32_Process still answer that, at a second or more per call and with a child process spawned each time.
  • No killing. Terminating a PID that may have been reused is a good way to kill the wrong thing; the tool is read-only on purpose.
  • No job-object membership. IsProcessInJob(handle, NULL) answers true for every process on Windows 8 and later (the system root job), so it cannot be used to tell whether a child would die with its parent.

Install

git clone https://github.com/Yicheng-Mark/hermes-windows-plugins /tmp/hermes-windows-plugins
cp -r /tmp/hermes-windows-plugins/windows-process ~/.hermes/plugins/hermes-windows-process
hermes plugins enable hermes-windows-process

Or install the catalog entry by name once it is listed: hermes plugins install hermes-windows-process.

Disclosures

The tool reads the process table and each process's image path and creation time, and hands them to the model: image names and paths routinely carry the user name (C:\Users\<name>\...), and the ancestry chain shows which editor, shell or agent started which process. Treat the output like the Task Manager screenshot it replaces.

Everything is read-only: PROCESS_QUERY_LIMITED_INFORMATION only, no memory reads, no handle duplication, no inheritance, no writes, no child processes, no network calls, no file writes, no self-update. Stdlib-only (ctypes against kernel32).

Tests

python -m pytest tests/     # 14 unit + 4 live; the live ones skip off Windows

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★ 0

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-windows-ports❖ Community★ 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.

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

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