ag2space-voice
AG2 Space voice surface — binds the room the AG2 Space client announces to the voice session's origin, so work delegated by voice…
Report, and with --reap stop, orphaned processes that interrupted agent test runs left behind in per-session scratchpads (PPID 1, this user, older than 2 h by default, cwd inside <tmp>/claude-<uid>/<project>/<session>/scratchpad, and that session has ended). --spotlight keeps
$ npx -y skills add sonichi/sutando --skill process-hygiene --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/process-hygieneContext preview
The summary Claude sees to decide when to auto-load this skill.
Report, and with --reap stop, orphaned processes that interrupted agent test runs left behind in per-session scratchpads (PPID 1, this user, older than 2 h by default, cwd inside <tmp>/claude-<uid>/<project>/<session>/scratchpad, and that session has ended). --spotlight keeps
name: process-hygiene description: "Report, and with --reap stop, orphaned processes that interrupted agent test runs left behind in per-session scratchpads (PPID 1, this user, older than 2 h by default, cwd inside <tmp>/claude-<uid>/<project>/<session>/scratchpad, and that session has ended). --spotlight keeps Spotlight from indexing scratchpad churn. For Sutando developers only; not scheduled. Use when the Mac is noisy or loaded with leftover test processes." user-invocable: true
Agent sessions run tests from their per-session scratchpads. When a run is interrupted or times out, background children it started are re-parented to init and keep running: spin loops waiting on a file that will never appear, fixture servers, hung interpreters. They accumulate across sessions for days. This skill finds them by provenance, not by name, and stops them one target at a time.
**Usage**
python3 skills/process-hygiene/scripts/reap_orphans.py # report only python3 skills/process-hygiene/scripts/reap_orphans.py --reap # stop candidates python3 skills/process-hygiene/scripts/reap_orphans.py --spotlight # Spotlight markers only
Every run appends one line per action and a summary to `<workspace>/logs/process-hygiene.log` and prints the summary. The exit status is 0 for every run that parsed its arguments, so a scheduled caller never retries in a loop; 2 on a usage error.
ALL of:
1. owned by the user running the script; 2. PPID 1 — whatever started it is gone; 3. elapsed time over `PROCESS_HYGIENE_MIN_AGE_S` (default 7200); 4. its working directory (`lsof -a -p PID -d cwd -Fn` on macOS, `/proc/PID/cwd` on Linux), as a realpath, is inside a scratchpad root matching `/private/tmp/claude-<uid>/*/*/scratchpad` or `/tmp/claude-<uid>/*/*/scratchpad`. A root is used only when `claude-<uid>` is a real directory owned by this user, nothing between it and `scratchpad` is a symlink, and the resolved root sits under the resolved `claude-<uid>`; a symlinked scratchpad would otherwise make its target (a repo, the workspace) a root, for reaping and for `--spotlight` alike; 5. the Claude Code session that owns that scratchpad has **ended** (below); 6. **no process in its process group holds a server socket** — a listening TCP socket or any UDP socket (`lsof -w -a -p PID -iTCP -sTCP:LISTEN -iUDP` on macOS; the pid's socket inodes against `/proc/PID/net/{tcp,tcp6,udp,udp6}` on Linux). A dev server, database or tunnel an agent started on purpose is spared even after its session ended. If the sockets cannot be read for any member, the whole group is spared.
**The owning session.** A scratchpad is `<tmp>/claude-<uid>/<project-slug>/<session-id>/scratchpad`. A live session may have started a server there on purpose, so its orphans are never candidates. For each Claude config dir (`CLAUDE_CONFIG_DIR`, the home `.claude`, and every `claude` entry of `core_config_dirs`; `--claude-config-dir` replaces the list):
(`sessionId`) and its `pid` is running with the marker's `procStart` (compared with `ps -o lstart=` under `TZ=UTC` and the C locale, so a reused pid is not mistaken for the session), or the session transcript `<config>/projects/<slug>/<session-id>.jsonl` changed within the minimum age;
a marker, neither alive condition holds, and no live Claude process of the same project could still own the scratchpad after a `/clear` (below);
`sessions/` directory that cannot be read, a marker without `pid`/`procStart`. Unknown is treated as alive: never reaped.
**`/clear`.** Measured with a throwaway interactive `claude`: `/clear` rewrites the running process's marker with a **new** `sessionId` (same `pid`, same `procStart`), starts a new session directory and transcript, and leaves the old session's scratchpad in place. Nothing on disk links the new id back to the old one (the new transcript does not name it; the process holds nothing open under the old session directory). So the old scratchpad, still the cwd of anything the session started, would read gone while its owner is alive. The rule that covers it: if any **live** marker (pid running with its `procStart`) belongs to the same project (its `cwd` mapped to a project name the way Claude Code does, every non-alphanumeric character to `-`) and that process started no later than `CLEAR_SLACK_S` (120 s) after the session directory was created, the owner is **unknown** and the scratchpad is spared. A process started after the directory existed cannot have owned it. A live marker with no `cwd` or no `procStart` counts as the same project. The consequence: on a host with a long-running session in a project, no ended session of that project created during its lifetime is reaped.
Claude Code writes the marker while a session runs and it is the only per-session liveness record on disk; a session's main process does not hold its transcript open, and its task-output files are open only while a background command runs, so neither of those can tell an idle live session from an ended one.
**Never touched, whatever else holds.** These are matched on the command line (`PROTECTED_SUBSTRINGS` and `PROTECTED_EXECUTABLES` in the script). They are normally safe anyway, because their cwd is not a scratchpad; the list is what keeps them safe when a Sutando checkout is run from a scratchpad worktree.
| Matched | Why | |---|---| | executable `tmux`, `claude` (also `-claude`), `launchd` | terminal multiplexers and agent sessions own other work | | `claude-code` | the Claude Code node CLI | | `sutando-core`, `sutando-worker`, `sutando-tmux`, `sutando-relay`, `sutando-station` | the core, workers, their tmux sockets, relays
My AI Stand — Realtime by Day, Rewriting Itself by Night. Summon my AI superpower. Voice, vision, screen, meetings, calls when I'm engaged. Learns my patterns, ships its own code when I'm not. Runs across my Macs, interacts with people & their Stands.
AG2 Space voice surface — binds the room the AG2 Space client announces to the voice session's origin, so work delegated by voice…
Streams what the agent is doing into the room, as rows the desktop client renders in an **events drawer** above the composer…
Local Agent Registry — a standalone, dependency-free service that tracks running Claude Code (and other) agent instances. Agents…
For an all-room analysis sweep, use the tested window collector and coverage contract in…
Deterministic final-answer normalizer — a last-step pass for any task that ends in a *precise* answer (a number, a short string,…
Transcribes audio files and voice notes to text via Gemini 2.5-flash. Integrates with Slack, Discord, and Telegram bridges so…