feat(name): decouple on-disk identifier from display label (#45)
* feat(name): decouple on-disk identifier from display label
Sessions now have a short random on-disk identifier (sock + json filename)
that is independent of the user-visible display label. This unblocks long
descriptive labels — both via `pty.toml` prefixes and via `pty run --name`
— which previously hit the macOS `sockaddr_un.sun_path` 104-byte limit.
Breaking changes
- `pty run --name <X>` now sets the displayName (any length, any printable
chars). The on-disk id is set by `--id <X>`. Both omitted → random short
id + auto-generated displayName. Both can be combined.
- `pty up` (pty.toml) gives every session a random short on-disk id. The
toml-derived `<prefix>-<sessionKey>` becomes the displayName, not the
filename. `pty up` re-run detection now matches by `(ptyfile,
ptyfile.session)` tag pair instead of by name.
- `pty.toml` gains two optional per-session fields: `id = "..."` to pin the
on-disk id and `display_name = "..."` to override the default label.
- `pty rename` validation: displayName uses the new permissive
`validateDisplayName` (≤ 500 chars, no slashes / null / newlines /
control bytes) instead of the strict `validateName` (sock-filename
charset, sock-path length). Strict validation is reserved for ids.
- `SessionMetadata.displayName` is now preserved through exit (previously
`saveExitMetadata` dropped it).
- `PtySessionDef.name` replaced by `displayName` + optional `id`;
`shortName` unchanged. External callers (`pty kill`, `peek`, `send`,
`attach`) are unaffected — they already resolved by either field via
`resolveRef`.
- `spawnDaemon`'s bundled-context fallback now passes `--id` (instead of
`--name`) to the CLI delegation path and explicitly threads
`displayName` / `--no-display-name`.
Tests
- New `tests/up-name-decouple.test.ts` covers random id, long-prefix
support, `(ptyfile, ptyfile.session)` re-run lookup, pty.toml `id` and
`display_name` overrides, and operations resolving by displayName.
- Existing tests migrated from `--name <id>` to `--id <id>` for tests
whose intent was pinning the on-disk identifier. `display-name.test.ts`
rewritten to test the new `--id` / `--name` semantics including
long-label, kernel-limit rejection, and id/name collision rejection.
Full suite green (1168 passed / 22 skipped / 1190 total).
* fix(cli): drop validateName from session-resolution paths
Long displayNames could be created via `pty run --name <long>` but
operating on them (`pty peek|send|kill|tag|events|attach|restart|rm`)
failed with the `validateName` sock-path kernel-limit error — the
strict validator was running on the user-supplied ref BEFORE
resolveRef did the lookup. The strict validator's job is to gate
on-disk id creation, not session-reference resolution.
Fix per schickling-assistant's PR #45 review:
- Drop the validateName(ref) block from 7 sites in cli.ts: attach,
peek, send, events, tag, kill, rm, cmdRestart, and tag-multi by-name
selector.
- Add resolveRef at the supervisor forget/reset dispatch sites so
cmdSupervisorForget/Reset receive a resolved name (their bodies
drop their own redundant validateName as a consequence).
- Drop the redundant validateName inside cmdRestart — its dispatcher
already resolved the ref.
validateName remains in place where it belongs: on-disk id creation
in `pty run --id`, pty.toml session id, and `pty rename` displayName
candidate paths.
Tests: 6 new regression tests in tests/display-name.test.ts covering
a 110-char displayName roundtripped through peek/send/tag/events/kill
plus the create case. Full suite: 1174 passed / 22 skipped / 0 failures.
list & gc ergonomics: vanished status, --summary/--status/age filters, gc --dry-run (closes #21)
Four changes, one PR:
1. Third session status `vanished` for the "daemon is gone, no exit
record written" case (SIGKILL / OOM / crash). Listed in its own
yellow-headered bucket with a warning icon so it doesn't blend into
cleanly-exited sessions. Reapable by `pty gc` like any other dead
session. TTL anchor falls back to createdAt so they can't accumulate
indefinitely.
2. `pty list --summary` (+ `--json --summary`) — compact counts and
oldest/newest pointers, respects all other filters.
3. `pty list --status <state>` and `--older-than/--newer-than <Ns|Nm|Nh|Nd>`
filters. Compose with `--filter-tag` and `--summary`. Grammar is
deliberately single-unit (no `1h30m`) to keep --help trivial.
4. `pty gc --dry-run` (`-n`) — preview what would be removed without
mutating anything. Covers exited AND vanished sessions AND orphan
`:l<pid>-<rand>` layout tags in one pass.
Client API:
- gc({ dryRun }), pruneOrphanLayoutTags({ dryRun })
- New `isGone(status)` helper — replaces hand-rolled
`status === "exited"` checks that should have included vanished all
along. Swept existing callers (run -a, peek fallback, pty up/down
cleanup, stats --all) to use it.
- New parseDuration/formatDuration exports for downstream tools.
Tests:
- duration.test.ts — full grammar coverage.
- list-filters.test.ts — vanished inference, --status, age filters,
--summary (text + json), filter composition.
- gc.test.ts — extended with --dry-run and vanished-session reaping.
726 → 728 local tests pass (+37 new), 0 failures.
Document the on-disk layout under docs/disk-layout.md
For non-Node consumers that want to read pty's session state directly
without paying Node CLI startup. Covers PTY_SESSION_DIR, the file
table with stability tiers (tier 1 = <name>.json, .events.jsonl;
tier 2 = .sock, .pid, .lock, theme, supervisor/), the SessionMetadata
TS shape, the events JSONL envelope and every concrete event type,
and the <target>.tmp.<pid>.<rand> atomic-write convention with an
explicit "third-party readers MUST ignore these" note.
Pre-1.0 banner: schema may change in any release; pin to a pty
version. CHANGELOG carries a "### Storage format" heading whenever
a tier-1 file shape changes.
Drift guard: tests/disk-layout-docs.test.ts asserts every
SessionMetadata field name, every concrete event-type literal, and
every file extension we write under PTY_SESSION_DIR appears in the
doc. SessionMetadata and EventBase carry "PUBLIC FORMAT" comment
markers pointing at the doc + the smoke test.
README's Events section gains a one-paragraph pointer to the doc and
mentions git-style command forwarding (pty <subcommand> ->
pty-<subcommand> on $PATH) as the recommended path for native
fast-path readers.
feat(name): decouple on-disk identifier from display label (#45)
* feat(name): decouple on-disk identifier from display label
Sessions now have a short random on-disk identifier (sock + json filename)
that is independent of the user-visible display label. This unblocks long
descriptive labels — both via `pty.toml` prefixes and via `pty run --name`
— which previously hit the macOS `sockaddr_un.sun_path` 104-byte limit.
Breaking changes
- `pty run --name <X>` now sets the displayName (any length, any printable
chars). The on-disk id is set by `--id <X>`. Both omitted → random short
id + auto-generated displayName. Both can be combined.
- `pty up` (pty.toml) gives every session a random short on-disk id. The
toml-derived `<prefix>-<sessionKey>` becomes the displayName, not the
filename. `pty up` re-run detection now matches by `(ptyfile,
ptyfile.session)` tag pair instead of by name.
- `pty.toml` gains two optional per-session fields: `id = "..."` to pin the
on-disk id and `display_name = "..."` to override the default label.
- `pty rename` validation: displayName uses the new permissive
`validateDisplayName` (≤ 500 chars, no slashes / null / newlines /
control bytes) instead of the strict `validateName` (sock-filename
charset, sock-path length). Strict validation is reserved for ids.
- `SessionMetadata.displayName` is now preserved through exit (previously
`saveExitMetadata` dropped it).
- `PtySessionDef.name` replaced by `displayName` + optional `id`;
`shortName` unchanged. External callers (`pty kill`, `peek`, `send`,
`attach`) are unaffected — they already resolved by either field via
`resolveRef`.
- `spawnDaemon`'s bundled-context fallback now passes `--id` (instead of
`--name`) to the CLI delegation path and explicitly threads
`displayName` / `--no-display-name`.
Tests
- New `tests/up-name-decouple.test.ts` covers random id, long-prefix
support, `(ptyfile, ptyfile.session)` re-run lookup, pty.toml `id` and
`display_name` overrides, and operations resolving by displayName.
- Existing tests migrated from `--name <id>` to `--id <id>` for tests
whose intent was pinning the on-disk identifier. `display-name.test.ts`
rewritten to test the new `--id` / `--name` semantics including
long-label, kernel-limit rejection, and id/name collision rejection.
Full suite green (1168 passed / 22 skipped / 1190 total).
* fix(cli): drop validateName from session-resolution paths
Long displayNames could be created via `pty run --name <long>` but
operating on them (`pty peek|send|kill|tag|events|attach|restart|rm`)
failed with the `validateName` sock-path kernel-limit error — the
strict validator was running on the user-supplied ref BEFORE
resolveRef did the lookup. The strict validator's job is to gate
on-disk id creation, not session-reference resolution.
Fix per schickling-assistant's PR #45 review:
- Drop the validateName(ref) block from 7 sites in cli.ts: attach,
peek, send, events, tag, kill, rm, cmdRestart, and tag-multi by-name
selector.
- Add resolveRef at the supervisor forget/reset dispatch sites so
cmdSupervisorForget/Reset receive a resolved name (their bodies
drop their own redundant validateName as a consequence).
- Drop the redundant validateName inside cmdRestart — its dispatcher
already resolved the ref.
validateName remains in place where it belongs: on-disk id creation
in `pty run --id`, pty.toml session id, and `pty rename` displayName
candidate paths.
Tests: 6 new regression tests in tests/display-name.test.ts covering
a 110-char displayName roundtripped through peek/send/tag/events/kill
plus the create case. Full suite: 1174 passed / 22 skipped / 0 failures.
feat(name): decouple on-disk identifier from display label (#45)
* feat(name): decouple on-disk identifier from display label
Sessions now have a short random on-disk identifier (sock + json filename)
that is independent of the user-visible display label. This unblocks long
descriptive labels — both via `pty.toml` prefixes and via `pty run --name`
— which previously hit the macOS `sockaddr_un.sun_path` 104-byte limit.
Breaking changes
- `pty run --name <X>` now sets the displayName (any length, any printable
chars). The on-disk id is set by `--id <X>`. Both omitted → random short
id + auto-generated displayName. Both can be combined.
- `pty up` (pty.toml) gives every session a random short on-disk id. The
toml-derived `<prefix>-<sessionKey>` becomes the displayName, not the
filename. `pty up` re-run detection now matches by `(ptyfile,
ptyfile.session)` tag pair instead of by name.
- `pty.toml` gains two optional per-session fields: `id = "..."` to pin the
on-disk id and `display_name = "..."` to override the default label.
- `pty rename` validation: displayName uses the new permissive
`validateDisplayName` (≤ 500 chars, no slashes / null / newlines /
control bytes) instead of the strict `validateName` (sock-filename
charset, sock-path length). Strict validation is reserved for ids.
- `SessionMetadata.displayName` is now preserved through exit (previously
`saveExitMetadata` dropped it).
- `PtySessionDef.name` replaced by `displayName` + optional `id`;
`shortName` unchanged. External callers (`pty kill`, `peek`, `send`,
`attach`) are unaffected — they already resolved by either field via
`resolveRef`.
- `spawnDaemon`'s bundled-context fallback now passes `--id` (instead of
`--name`) to the CLI delegation path and explicitly threads
`displayName` / `--no-display-name`.
Tests
- New `tests/up-name-decouple.test.ts` covers random id, long-prefix
support, `(ptyfile, ptyfile.session)` re-run lookup, pty.toml `id` and
`display_name` overrides, and operations resolving by displayName.
- Existing tests migrated from `--name <id>` to `--id <id>` for tests
whose intent was pinning the on-disk identifier. `display-name.test.ts`
rewritten to test the new `--id` / `--name` semantics including
long-label, kernel-limit rejection, and id/name collision rejection.
Full suite green (1168 passed / 22 skipped / 1190 total).
* fix(cli): drop validateName from session-resolution paths
Long displayNames could be created via `pty run --name <long>` but
operating on them (`pty peek|send|kill|tag|events|attach|restart|rm`)
failed with the `validateName` sock-path kernel-limit error — the
strict validator was running on the user-supplied ref BEFORE
resolveRef did the lookup. The strict validator's job is to gate
on-disk id creation, not session-reference resolution.
Fix per schickling-assistant's PR #45 review:
- Drop the validateName(ref) block from 7 sites in cli.ts: attach,
peek, send, events, tag, kill, rm, cmdRestart, and tag-multi by-name
selector.
- Add resolveRef at the supervisor forget/reset dispatch sites so
cmdSupervisorForget/Reset receive a resolved name (their bodies
drop their own redundant validateName as a consequence).
- Drop the redundant validateName inside cmdRestart — its dispatcher
already resolved the ref.
validateName remains in place where it belongs: on-disk id creation
in `pty run --id`, pty.toml session id, and `pty rename` displayName
candidate paths.
Tests: 6 new regression tests in tests/display-name.test.ts covering
a 110-char displayName roundtripped through peek/send/tag/events/kill
plus the create case. Full suite: 1174 passed / 22 skipped / 0 failures.
feat(name): decouple on-disk identifier from display label (#45)
* feat(name): decouple on-disk identifier from display label
Sessions now have a short random on-disk identifier (sock + json filename)
that is independent of the user-visible display label. This unblocks long
descriptive labels — both via `pty.toml` prefixes and via `pty run --name`
— which previously hit the macOS `sockaddr_un.sun_path` 104-byte limit.
Breaking changes
- `pty run --name <X>` now sets the displayName (any length, any printable
chars). The on-disk id is set by `--id <X>`. Both omitted → random short
id + auto-generated displayName. Both can be combined.
- `pty up` (pty.toml) gives every session a random short on-disk id. The
toml-derived `<prefix>-<sessionKey>` becomes the displayName, not the
filename. `pty up` re-run detection now matches by `(ptyfile,
ptyfile.session)` tag pair instead of by name.
- `pty.toml` gains two optional per-session fields: `id = "..."` to pin the
on-disk id and `display_name = "..."` to override the default label.
- `pty rename` validation: displayName uses the new permissive
`validateDisplayName` (≤ 500 chars, no slashes / null / newlines /
control bytes) instead of the strict `validateName` (sock-filename
charset, sock-path length). Strict validation is reserved for ids.
- `SessionMetadata.displayName` is now preserved through exit (previously
`saveExitMetadata` dropped it).
- `PtySessionDef.name` replaced by `displayName` + optional `id`;
`shortName` unchanged. External callers (`pty kill`, `peek`, `send`,
`attach`) are unaffected — they already resolved by either field via
`resolveRef`.
- `spawnDaemon`'s bundled-context fallback now passes `--id` (instead of
`--name`) to the CLI delegation path and explicitly threads
`displayName` / `--no-display-name`.
Tests
- New `tests/up-name-decouple.test.ts` covers random id, long-prefix
support, `(ptyfile, ptyfile.session)` re-run lookup, pty.toml `id` and
`display_name` overrides, and operations resolving by displayName.
- Existing tests migrated from `--name <id>` to `--id <id>` for tests
whose intent was pinning the on-disk identifier. `display-name.test.ts`
rewritten to test the new `--id` / `--name` semantics including
long-label, kernel-limit rejection, and id/name collision rejection.
Full suite green (1168 passed / 22 skipped / 1190 total).
* fix(cli): drop validateName from session-resolution paths
Long displayNames could be created via `pty run --name <long>` but
operating on them (`pty peek|send|kill|tag|events|attach|restart|rm`)
failed with the `validateName` sock-path kernel-limit error — the
strict validator was running on the user-supplied ref BEFORE
resolveRef did the lookup. The strict validator's job is to gate
on-disk id creation, not session-reference resolution.
Fix per schickling-assistant's PR #45 review:
- Drop the validateName(ref) block from 7 sites in cli.ts: attach,
peek, send, events, tag, kill, rm, cmdRestart, and tag-multi by-name
selector.
- Add resolveRef at the supervisor forget/reset dispatch sites so
cmdSupervisorForget/Reset receive a resolved name (their bodies
drop their own redundant validateName as a consequence).
- Drop the redundant validateName inside cmdRestart — its dispatcher
already resolved the ref.
validateName remains in place where it belongs: on-disk id creation
in `pty run --id`, pty.toml session id, and `pty rename` displayName
candidate paths.
Tests: 6 new regression tests in tests/display-name.test.ts covering
a 110-char displayName roundtripped through peek/send/tag/events/kill
plus the create case. Full suite: 1174 passed / 22 skipped / 0 failures.
feat(name): decouple on-disk identifier from display label (#45)
* feat(name): decouple on-disk identifier from display label
Sessions now have a short random on-disk identifier (sock + json filename)
that is independent of the user-visible display label. This unblocks long
descriptive labels — both via `pty.toml` prefixes and via `pty run --name`
— which previously hit the macOS `sockaddr_un.sun_path` 104-byte limit.
Breaking changes
- `pty run --name <X>` now sets the displayName (any length, any printable
chars). The on-disk id is set by `--id <X>`. Both omitted → random short
id + auto-generated displayName. Both can be combined.
- `pty up` (pty.toml) gives every session a random short on-disk id. The
toml-derived `<prefix>-<sessionKey>` becomes the displayName, not the
filename. `pty up` re-run detection now matches by `(ptyfile,
ptyfile.session)` tag pair instead of by name.
- `pty.toml` gains two optional per-session fields: `id = "..."` to pin the
on-disk id and `display_name = "..."` to override the default label.
- `pty rename` validation: displayName uses the new permissive
`validateDisplayName` (≤ 500 chars, no slashes / null / newlines /
control bytes) instead of the strict `validateName` (sock-filename
charset, sock-path length). Strict validation is reserved for ids.
- `SessionMetadata.displayName` is now preserved through exit (previously
`saveExitMetadata` dropped it).
- `PtySessionDef.name` replaced by `displayName` + optional `id`;
`shortName` unchanged. External callers (`pty kill`, `peek`, `send`,
`attach`) are unaffected — they already resolved by either field via
`resolveRef`.
- `spawnDaemon`'s bundled-context fallback now passes `--id` (instead of
`--name`) to the CLI delegation path and explicitly threads
`displayName` / `--no-display-name`.
Tests
- New `tests/up-name-decouple.test.ts` covers random id, long-prefix
support, `(ptyfile, ptyfile.session)` re-run lookup, pty.toml `id` and
`display_name` overrides, and operations resolving by displayName.
- Existing tests migrated from `--name <id>` to `--id <id>` for tests
whose intent was pinning the on-disk identifier. `display-name.test.ts`
rewritten to test the new `--id` / `--name` semantics including
long-label, kernel-limit rejection, and id/name collision rejection.
Full suite green (1168 passed / 22 skipped / 1190 total).
* fix(cli): drop validateName from session-resolution paths
Long displayNames could be created via `pty run --name <long>` but
operating on them (`pty peek|send|kill|tag|events|attach|restart|rm`)
failed with the `validateName` sock-path kernel-limit error — the
strict validator was running on the user-supplied ref BEFORE
resolveRef did the lookup. The strict validator's job is to gate
on-disk id creation, not session-reference resolution.
Fix per schickling-assistant's PR #45 review:
- Drop the validateName(ref) block from 7 sites in cli.ts: attach,
peek, send, events, tag, kill, rm, cmdRestart, and tag-multi by-name
selector.
- Add resolveRef at the supervisor forget/reset dispatch sites so
cmdSupervisorForget/Reset receive a resolved name (their bodies
drop their own redundant validateName as a consequence).
- Drop the redundant validateName inside cmdRestart — its dispatcher
already resolved the ref.
validateName remains in place where it belongs: on-disk id creation
in `pty run --id`, pty.toml session id, and `pty rename` displayName
candidate paths.
Tests: 6 new regression tests in tests/display-name.test.ts covering
a 110-char displayName roundtripped through peek/send/tag/events/kill
plus the create case. Full suite: 1174 passed / 22 skipped / 0 failures.
Add supervisor, mutable tags, peek --wait/--full, and hardening
Session supervisor watches strategy tags and restarts permanent
sessions with exponential backoff. Runs as a foreground process,
integrates with launchd via esbuild bundling. Mutable tags via
pty tag command. pty kill/down properly handle supervised sessions.
Also: peek --wait blocks until text appears, peek --full shows
scrollback, events --wait blocks for event types, interactive TUI
shows [permanent] markers with color, 10s supervisor scan interval,
supervisor state in its own subdirectory, defensive meta.args
handling, and isolated shell test sessions.
feat(name): decouple on-disk identifier from display label (#45)
* feat(name): decouple on-disk identifier from display label
Sessions now have a short random on-disk identifier (sock + json filename)
that is independent of the user-visible display label. This unblocks long
descriptive labels — both via `pty.toml` prefixes and via `pty run --name`
— which previously hit the macOS `sockaddr_un.sun_path` 104-byte limit.
Breaking changes
- `pty run --name <X>` now sets the displayName (any length, any printable
chars). The on-disk id is set by `--id <X>`. Both omitted → random short
id + auto-generated displayName. Both can be combined.
- `pty up` (pty.toml) gives every session a random short on-disk id. The
toml-derived `<prefix>-<sessionKey>` becomes the displayName, not the
filename. `pty up` re-run detection now matches by `(ptyfile,
ptyfile.session)` tag pair instead of by name.
- `pty.toml` gains two optional per-session fields: `id = "..."` to pin the
on-disk id and `display_name = "..."` to override the default label.
- `pty rename` validation: displayName uses the new permissive
`validateDisplayName` (≤ 500 chars, no slashes / null / newlines /
control bytes) instead of the strict `validateName` (sock-filename
charset, sock-path length). Strict validation is reserved for ids.
- `SessionMetadata.displayName` is now preserved through exit (previously
`saveExitMetadata` dropped it).
- `PtySessionDef.name` replaced by `displayName` + optional `id`;
`shortName` unchanged. External callers (`pty kill`, `peek`, `send`,
`attach`) are unaffected — they already resolved by either field via
`resolveRef`.
- `spawnDaemon`'s bundled-context fallback now passes `--id` (instead of
`--name`) to the CLI delegation path and explicitly threads
`displayName` / `--no-display-name`.
Tests
- New `tests/up-name-decouple.test.ts` covers random id, long-prefix
support, `(ptyfile, ptyfile.session)` re-run lookup, pty.toml `id` and
`display_name` overrides, and operations resolving by displayName.
- Existing tests migrated from `--name <id>` to `--id <id>` for tests
whose intent was pinning the on-disk identifier. `display-name.test.ts`
rewritten to test the new `--id` / `--name` semantics including
long-label, kernel-limit rejection, and id/name collision rejection.
Full suite green (1168 passed / 22 skipped / 1190 total).
* fix(cli): drop validateName from session-resolution paths
Long displayNames could be created via `pty run --name <long>` but
operating on them (`pty peek|send|kill|tag|events|attach|restart|rm`)
failed with the `validateName` sock-path kernel-limit error — the
strict validator was running on the user-supplied ref BEFORE
resolveRef did the lookup. The strict validator's job is to gate
on-disk id creation, not session-reference resolution.
Fix per schickling-assistant's PR #45 review:
- Drop the validateName(ref) block from 7 sites in cli.ts: attach,
peek, send, events, tag, kill, rm, cmdRestart, and tag-multi by-name
selector.
- Add resolveRef at the supervisor forget/reset dispatch sites so
cmdSupervisorForget/Reset receive a resolved name (their bodies
drop their own redundant validateName as a consequence).
- Drop the redundant validateName inside cmdRestart — its dispatcher
already resolved the ref.
validateName remains in place where it belongs: on-disk id creation
in `pty run --id`, pty.toml session id, and `pty rename` displayName
candidate paths.
Tests: 6 new regression tests in tests/display-name.test.ts covering
a 110-char displayName roundtripped through peek/send/tag/events/kill
plus the create case. Full suite: 1174 passed / 22 skipped / 0 failures.