Repository navigation
Add who/free, launcher attribution, and --mine/--orphaned scopes - #15
Merged
Merged
Conversation
Port commands: - `marina who <port>` names whatever holds a port: a dev target (with project, tool, pid, uptime, branch, cwd, launcher) or, for anything outside curation, the process name + pid. Exits 1 when the port is free. - `marina free <port>` stops the dev target on a port and waits until the port is actually released. Idempotent (already free = exit 0) and refuses to touch holders that are not dev targets. Both accept ports only. Launcher attribution (new `launcher` module): - Each target records who started it: an agent session (claude, codex, opencode, cursor-agent, ...), an editor, a terminal, or detached. - Resolved from the live parent chain, falling back to an allowlist of agent env markers (CLAUDE_PID, CLAUDE_CODE_SESSION_ID, CLAUDECODE, AI_AGENT) that survive reparenting after `&`/`nohup`. A server whose agent session has ended is flagged orphaned. No other env vars are retained. - TUI: VIA column, launcher details in the status line and inspect panel (including `claude --resume <id>`), `/` filter matches launcher. - JSON: new `launcher` object on every target. - CLI: `--mine` (targets started by the agent session running marina) and `--orphaned` (targets whose agent session ended) on ls/kill/restart/url. Resolution and verbs: - Labels see through corepack's pnpm-native shim and node-hosted bin scripts (`pnpm exec vp dev` -> `vp dev`); `python -m X` -> `X`. - A server whose cwd is $HOME is named after its tool, not the username. - CLI kill returns as soon as processes exit instead of always sleeping the full grace period (free/kill: ~1.5s -> ~30ms in the common case).
Session view (`v` in the TUI): - Groups targets by launcher instead of project: one header per agent session (`claude·<dir>`, `claude·ended`), editor, terminal, `detached`, or `unattributed`, spanning projects. Distinct sessions that would share a label get a short id suffix. Every session gets a header, even with one member. `K`/`R` on a session header act on exactly that session's targets. - Session headers are colored by launcher; the status line and inspect panel describe the session (with `claude --resume <id>` where known). - Long group labels are truncated with `…` so the member count stays visible. Orphan notices: - The snapshot diff reports each agent session whose servers go from alive to orphaned, once per session: `claude session in ~/dev/app ended — left 2 servers running (480MB)`, as a 20s status notice and a desktop notification (osascript on macOS, notify-send on Linux; AppleScript string escaping prevents breaking out of the literal). - Orphans already present at startup get a status-line count only. - `[notify] desktop = false` in config disables the desktop notification. Fix: a server carrying agent env markers without CLAUDE_PID is no longer reported as orphaned — liveness can't be proven either way, so no alarm.
Launcher attribution previously traced backgrounded servers only for Claude Code. Agent marker parsing is now table-driven (`MARKERS` in launcher.rs), covering the variables each agent exports to the commands it runs: - Codex: CODEX_THREAD_ID (session), CODEX_SANDBOX - opencode: OPENCODE_SESSION_ID (session), OPENCODE - Copilot: COPILOT_AGENT_SESSION_ID, COPILOT_AGENT, COPILOT_CLI - Amp, Cline, Roo, Qwen, Pi: their thread/task/session ids - Cursor, Gemini, Goose, Augment, Crush, Kiro: presence flags - AI_AGENT / AGENT as a fallback when no specific marker is present Sources: Codex exec_env.rs, opencode's bash tool (from the shipped binary), cross-checked against the is-ai-agent table. Only pids and validated session ids are kept; flag values are never read. Session ids may now contain letters and underscores (opencode `ses_…`, Amp `T-…`). Attribution: - A live agent in the parent chain picks up its own session id from the markers, so `--mine` works for Codex/opencode sessions by thread id. - An editor whose server carries agent markers is attributed to the editor's agent (Cursor agent, Copilot agent mode). Terminals are not upgraded, to avoid markers leaked into tmux panes. - Agents without a pid marker are attributed and grouped but never reported as ended. - Inspect shows `codex resume <id>` / `opencode --session <id>`. - More agent process names recognized (qwen, auggie, kiro-cli, cline). Fix: the anchor climb now stops at any launcher. An agent running in the project directory that spawned a server without an intervening shell was absorbed as the target's anchor — mislabeling the row and including the agent process in the kill set.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Coding agents now start most local dev servers, often in the background and across several concurrent sessions, which makes a running server hard to identify. This change makes marina answer what is this, and who started it, and adds port-first commands for the
EADDRINUSEmoment.marina who/marina freewho <port>…names whatever holds a port: a dev target (project · tool · pid · uptime · branch · cwd · launcher) or, for anything outside curation, the process name + pid. Exit1when free.free <port>…stops the dev target on a port and waits until it is actually released. Idempotent (marina free 3000 && pnpm devre-runs safely); refuses to touch non-dev holders such as macOS ControlCenter on:5000. Ports only — no substring matching.Launcher attribution
claude,codex,opencode,cursor-agent, …), an editor, a terminal, or detached.&/nohup, falls back to an allowlist of agent env markers (CLAUDE_PID,CLAUDE_CODE_SESSION_ID,CLAUDECODE,AI_AGENT). A server whose agent session has ended is flagged orphaned (claude·ended).VIAcolumn (dropped after BRANCH/UP on narrow panes), launcher detail in the status line and inspect panel (withclaude --resume <id>),/filter matches launcher (/claude,/ended).launcherobject{kind, name, pid, alive, orphaned, session, cwd}.--mine/--orphanedscopes onls/kill/restart/url: an agent can runmarina kill --mineto stop exactly the servers it started, andmarina kill --orphanedcleans up after finished sessions.Resolution and verbs
pnpm-nativeshim and node-hosted bin scripts (pnpm exec vp dev→vp dev);python -m http.server→http.server.$HOMEis named after its tool rather than the username.free/kill~1.5s → ~30ms typical).Privacy
Only the four allowlisted env keys are extracted; no other variable is kept, displayed, or serialized, and session ids are validated as hex/dashes. Claude Code's
~/.claude/sessions/*files are intentionally not read because they contain auth tokens. README privacy section updated accordingly.Testing
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo test --all-targets: 101 tests pass (17 new), covering the env allowlist, launcher classification without over-matching (codesign≠code), chain vs. env precedence, orphan detection, detached vs. unknown supervisors,--minesession matching, port parsing,who/freeexit codes against real sockets, label resolution, and TUI rendering of the VIA column / inspect panel / filter.nohup-backgrounded server still attributes via env; a server with a deadCLAUDE_PIDshowsclaude·endedand is stopped bykill --orphaned;--mineexcludes servers from other sessions; the TUI renders correctly at 130 columns.Session view and orphan notices (second commit)
v): groups rows by the agent session / editor / terminal that started them, across projects —claude·fal-app,claude·ended,tmux,detached.Kon a session header stops everything that session started.⚠ claude session in ~/dev/app ended — left 2 servers running (480MB)— in the status line (20s) and as a desktop notification. Disable the latter with[notify] desktop = false. Orphans present at startup get a status-line count only.CLAUDE_PIDare no longer treated as an ended session (no false orphan alarms).Verified live on macOS: a stand-in agent process with two env-attributed servers grouped under
claude·agent-pr… (2); killing the agent moved them toclaude·ended (2)and raised the notice;/ended+Kon the session header stopped exactly those two servers while other sessions' servers were untouched. 109 tests (8 new: session grouping and disambiguation, session-view kill scope, once-per-session notices, startup orphans, pid-less markers, header truncation, AppleScript escaping, notify config).Multi-agent detection (third commit)
CODEX_THREAD_ID,CODEX_SANDBOX), opencode (OPENCODE_SESSION_ID,OPENCODE), Copilot, Cursor, Gemini, Amp, Goose, Cline, Roo, Qwen, Pi, Augment, Crush and Kiro, withAI_AGENT/AGENTas a fallback. Sources: Codexexec_env.rs, opencode's bash tool (read from the shipped binary), cross-checked against is-ai-agent.--mineand session grouping work for Codex and opencode via their thread/session ids; inspect showscodex resume <id>/opencode --session <id>.codex sandboxcommand: with no shell in between, the Codex process itself became the target's anchor (row labelledcodex, Codex in the kill set).Verified live: a listener started via
codex sandboxreadsnc · via codex (pid …); backgrounded servers carrying Codex / opencode markers readvia codex (session 0199a213)/via opencode (session ses_3b0f);ls --minerun with each agent's session marker returns only that session's server. 117 tests.