# Track terminal listening ports in activity events and thread state · PR \#43 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/43)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: closed

Source repository: pingdotgg/t3code

Source branch: codething/50e6e9da

Target branch: main

Head commit: b0bc101eb6d4cf43c9211e77c5b21ba44eec9044

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/43)

[Commits](https://git.cafe/pingdotgg/t3code/pull/43/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/43/diffs?format=markdown)

## Description

---

## Summary
- extend terminal activity payloads to include normalized `runningPorts` alongside `hasRunningSubprocess`
- replace simple subprocess checks with subprocess inspection that detects process families and listening ports on both POSIX (`lsof`/`ss`) and Windows (PowerShell CIM/NetTCP)
- persist per-terminal running port state in web thread store (`runningTerminalPorts`) and clear it on terminal restart/exit/error/close
- surface detected ports in the sidebar terminal status indicator, including compact port labels
- update shared contracts and tests across server, web, and contracts packages for port-aware activity behavior

## Testing
- `apps/server/src/terminalManager.test.ts`: verifies activity events emit on subprocess state and port changes, including port normalization and clearing when inactive
- `apps/web/src/store.test.ts`: verifies reducer tracks `runningTerminalPorts`, updates on activity changes, and removes port state when terminals stop/exist
- `packages/contracts/src/terminal.test.ts`: verifies `terminalActivityEventSchema` accepts `runningPorts`
- Additional fixture/schema updates covered in:
  - `apps/web/src/persistenceSchema.test.ts`
  - `apps/web/src/worktreeCleanup.test.ts`
- Lint: Not run
- Full test suite: Not run
<!-- devin-review-badge-begin -->

---

<a href="https://app.devin.ai/review/pingdotgg/codething-mvp/pull/43" target="_blank">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
    <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Sidebar shows detected listening ports with a clickable web icon to open the primary port; threads track per-terminal running ports.

* **Public Events**
  * Terminal activity events now include a runningPorts array alongside running-state info.

* **Behavior**
  * Web-port detection ignores root 404 responses, caches results, and deduplicates in-flight probes.

* **Persistence**
  * Thread state now persists per-terminal running ports.

* **Tests**
  * Tests added/updated for port detection, 404 handling, merging/clearing ports, and lifecycle propagation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds periodic OS-level process/port inspection (`ps`/`lsof`/`ss`/PowerShell) and HTTP probing to terminal polling, which can impact runtime behavior and introduces platform-specific edge cases despite bounded timeouts and error throttling.
> 
> **Overview**
> Terminal `activity` events now carry **normalized `runningPorts`** alongside `hasRunningSubprocess`, with contracts updated to validate port ranges.
> 
> On the server, a new `TerminalProcessInspectorLive` replaces the old boolean subprocess check by collecting process families and scanning listening ports on **POSIX (`ps` + `lsof`, fallback to `ss`)** and **Windows (PowerShell CIM + `Get-NetTCPConnection`)**; a new `WebPortInspectorLive` probes localhost over IPv4/IPv6 to decide which ports are likely web servers (404 ignored), with TTL caching and transient-failure tolerance. `TerminalManager` emits activity events when either the subprocess flag *or* the detected web-port set changes, and throttles repeated inspector error logs.
> 
> On the web side, thread terminal state now persists `runningTerminalPorts` per terminal, clears it on start/restart/exit/error/close, and the sidebar + terminal drawer show a clickable web indicator that opens `http://localhost:<port>` when a primary port is detected.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b0bc101eb6d4cf43c9211e77c5b21ba44eec9044. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Track listening ports in terminal activity events and display detected web ports in the UI
> - Adds cross-platform subprocess inspection (`TerminalProcessInspectorLive`) that discovers child PIDs and listening TCP ports via `lsof`/`ss` on POSIX and PowerShell on Windows, and a `WebPortInspectorLive` that probes `localhost` to confirm whether a port serves HTTP/HTML.
> - Extends `TerminalActivityEvent` in [terminal.ts](https://github.com/pingdotgg/t3code/pull/43/files#diff-68613534653e19cf33dc0ddf6c6bf01ac3c4848b8fbfdd29363100dd6a7c2a89) with a required `runningPorts` field; activity events are only emitted when `hasRunningSubprocess` or the port list changes. Web port detection uses a TTL cache so transient probe failures don't drop previously confirmed ports.
> - Updates `ThreadTerminalState` in [terminalStateStore.ts](https://github.com/pingdotgg/t3code/pull/43/files#diff-9e98e54d562825d3d06313f14e0c37ba761ec3457248dd98e1e388a6948fcd34) to store a `runningTerminalPorts` map per terminal, normalized and deduplicated on each update.
> - Renders detected web ports in the UI: the sidebar thread row shows a clickable terminal status icon that opens `http://localhost:<port>`, and the terminal drawer tab shows a Globe icon button for the same action.
> - Repeated identical inspector errors are throttled to one log per 30 seconds per session.
> - Risk: `runningPorts` is now a required field in `TerminalActivityEvent`; any existing persisted or in-flight events without this field will fail schema decoding.
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized b0bc101.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- macroscope-ui-refresh -->
<!-- Macroscope's pull request summary ends here -->
