Docs menuLifecycle

pty experimental

Lifecycle

A session's lifecycle is a policy you set with flags and tags. No supervisor daemon watches over your sessions. Instead, a periodic gc pass reads the tags and makes them true.

When the program exits

By default, a finished session reaps itself: it removes its own entry, so it doesn't linger in pty list. You can change that.

  • Set PTY_REAP_ON_EXIT=false to preserve finished sessions. Their final screen stays readable with pty peek until gc sweeps them.
  • Tag a session keep=true to keep it even past a sweep, until you remove it yourself.
  • Start it with --ephemeral to reap it on any shutdown and leave no trace.

pty kill stops a session and keeps its record. pty rm removes the record.

gc: stateless reconciliation

pty gc is a single pass that you run on a short timer. Each pass:

  • Respawns sessions tagged strategy=permanent whenever their program exits or vanishes.
  • Stops flapping. A permanent session that keeps dying right after a respawn is marked flapping, and gc stops respawning it until you step in.
  • Kills orphans. A session tagged parent=<name> is stopped once its parent is gone, so sidecars never outlive the thing they serve.
  • Sweeps finished sessions that nobody asked to keep.

There's no restart counter in memory and no long-running supervisor to crash. Every pass works out what you want from the files on disk. If something can't start yet, because a disk isn't mounted at boot for example, the next pass tries again.

pty gc --dry-run     # show what gc would do, and change nothing

Declaring a project's sessions

A project can declare its sessions in a pty.toml and bring them up together:

[sessions.serve]
command = "bin/serve"
tags = { strategy = "permanent" }

[sessions.dev]
command = "npm run dev"
pty up      # start every session in ./pty.toml
pty down    # stop them

A permanent session from a pty.toml re-reads the file when gc respawns it, so your edits take effect on the next restart.