You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(gc): expire keep-tagged exited sessions after a max age
`keep=true` exempted a dead session from `pty gc`'s sweep forever. Agents set
it on the session they are debugging right now and never come back to untag it,
so the registry becomes append-only: 740 of 911 sessions on one host were
exited-and-kept, and `pty gc --dry-run` could only offer to sweep 113.
The exemption is now bounded. `pty gc` skips a `keep`-tagged exited/vanished
session only while it has been dead for less than `--keep-max-age` (default
7d), then sweeps it and reports it under a separate `keepExpired` bucket so the
reason stays visible. `0` sweeps the whole dead-keep backlog on that pass.
Exit-time retention is untouched and still unconditional, and running sessions
are never sweep candidates whatever their age.
Age is anchored on `exitedAt`, falling back to `createdAt` for a `vanished`
session that never wrote one — the same anchor precedence `pty list
--older-than` uses. A record with neither timestamp never expires except under
an explicit `0`.
Refs schickling/dotfiles#2412, schickling/dotfiles#2408.
pty run --tag keep=true -- npm test# keep it even past a gc sweep, until you rm it
62
+
pty run --tag keep=true -- npm test# keep it past a gc sweep for 7d after it dies
63
63
pty run --cwd /path -- node server.js # run in a specific directory
64
64
65
65
pty rename my-label # inside a session: add/change its displayName
@@ -195,7 +195,7 @@ Two per-session flags override the configured default either way:
195
195
196
196
| Flag | Effect |
197
197
|---|---|
198
-
| tag `keep=true`| Force **preserve**, and survive even a `pty gc` sweep — metadata/`lastLines`/events last until you `pty rm` it. Wins over everything, including `--ephemeral`. |
198
+
| tag `keep=true`| Force **preserve**, including past a `pty gc` sweep — metadata/`lastLines`/events last until `pty gc --keep-max-age` (default 7d) after the session died, or until you `pty rm` it. Wins over everything, including `--ephemeral`. |
199
199
|`pty run -e` (`--ephemeral`) | Force **reap**, on *any* shutdown incl. `pty kill` and `strategy=permanent`. `keep` still wins over it. |
200
200
201
201
`strategy=permanent` sessions are always preserved (their supervisor reconciles
@@ -220,15 +220,28 @@ the supporting daemon.
220
220
```sh
221
221
pty run -d -- npm test# shipped default: reaped when it finishes
222
222
PTY_REAP_ON_EXIT=false pty run -d -- npm test# preserved: peekable until gc sweeps it
223
-
pty run -d --tag keep=true -- npm test# force-keep, even past a gc sweep, until you rm it
223
+
pty run -d --tag keep=true -- npm test# force-keep, past a gc sweep, for 7d after it dies
224
224
pty run -d -e -- npm test# ephemeral: reaps on any shutdown, leaves no trace
`pty gc` is a one-shot reconciliation pass. The intended deployment is to run it on a short interval so permanent sessions come back quickly and orphans get cleaned promptly. The CLI ships an install helper for macOS:
389
402
390
-
Whether finished sessions need the sweep depends on [`PTY_REAP_ON_EXIT`](#session-lifecycle-and-cleanup): under the shipped `reap` default they self-clean at exit, so the sweep's finished-session duty is mostly `vanished` sessions (daemon killed outright, so it never ran its own cleanup) plus anything left listed by `preserve` mode. `pty list` only observes this state; it never cleans it up. So the interval primarily buys you respawn latency for permanents and orphan-kill promptness — and, in `preserve` mode, `pty ls` hygiene. `keep=true` and `strategy=permanent` sessions are exempt.
403
+
Whether finished sessions need the sweep depends on [`PTY_REAP_ON_EXIT`](#session-lifecycle-and-cleanup): under the shipped `reap` default they self-clean at exit, so the sweep's finished-session duty is mostly `vanished` sessions (daemon killed outright, so it never ran its own cleanup) plus anything left listed by `preserve` mode. `pty list` only observes this state; it never cleans it up. So the interval primarily buys you respawn latency for permanents and orphan-kill promptness — and, in `preserve` mode, `pty ls` hygiene. `strategy=permanent` sessions are exempt; `keep=true` sessions are exempt until they have been dead longer than `--keep-max-age` (default 7d), which an interval-driven gc then reclaims on its own.
Copy file name to clipboardExpand all lines: docs/disk-layout.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -110,8 +110,8 @@ the historical ambient-inheritance behavior.
110
110
-`strategy.abandon-if-cwd-gone=false` — opts a permanent session OUT of the on-by-default cwd-gone reap in `pty gc` step 1.5. Only meaningful with `strategy=permanent`.
111
111
-`strategy.idle-days=<N>` — opts a permanent session INTO idle-reap: `pty gc` reaps it when `lastAttachAt` is older than N days. Takes precedence over the global `--idle-days` flag.
112
112
-`parent=<name>` — `pty gc` orphan-kills this session (SIGTERM + cleanup) when the referenced session's daemon is no longer alive. Combinator with `strategy=permanent` is well-defined: orphan-kill wins.
113
-
-`keep=true` — exempts the session from reaping, both the daemon's exit-time self-cleanup and `pty gc`'s sweep. Its metadata, `lastLines`, and events file survive its death until an explicit `pty rm`. Any value other than `false`/`0`/`no`/`off` counts as set, so a mis-spelled value errs toward retaining. Without this tag, a non-permanent session's files are gone the moment its command finishes.
114
-
- Lifetime: a non-permanent session's files are removed by its own daemon during shutdown once the child process terminates. Files therefore outlive the process only for `keep`, `strategy=permanent`, external `pty kill`, and `vanished` sessions (SIGKILLed daemon — no cleanup code ran). Readers that poll these files after a session finishes must set `keep=true` or accept the race.
113
+
-`keep=true` — exempts the session from reaping: unconditionally from the daemon's exit-time self-cleanup, and from `pty gc`'s sweep until the session has been dead longer than `pty gc --keep-max-age <dur>` (default 7d; `0` sweeps every dead keep session on that pass). Age is anchored on `exitedAt`, or `createdAt` for a `vanished` session that never wrote one. Its metadata, `lastLines`, and events file therefore survive its death until that window elapses or an explicit `pty rm`, whichever comes first; a running session is never swept regardless of age. Any value other than `false`/`0`/`no`/`off` counts as set, so a mis-spelled value errs toward retaining. Without this tag, a non-permanent session's files are gone the moment its command finishes.
114
+
- Lifetime: a non-permanent session's files are removed by its own daemon during shutdown once the child process terminates. Files therefore outlive the process only for `keep` (bounded by `--keep-max-age`), `strategy=permanent`, external `pty kill`, and `vanished` sessions (SIGKILLed daemon — no cleanup code ran). Readers that poll these files after a session finishes must set `keep=true` or accept the race.
115
115
- Concurrent writers: last-write-wins; readers never see torn files. Cross-process writers can lose updates to the read-modify-write window.
0 commit comments