Skip to content

Add pty completions <shell> generator (fish/bash/zsh, SSOT, dynamic sessions) - #106

Merged
schickling merged 1 commit into
compoundingtech:mainfrom
schickling:feat/completions-generator
Jul 20, 2026
Merged

Add pty completions <shell> generator (fish/bash/zsh, SSOT, dynamic sessions)#106
schickling merged 1 commit into
compoundingtech:mainfrom
schickling:feat/completions-generator

Conversation

@schickling

Copy link
Copy Markdown
Contributor

Why

pty ships static completions/pty.{fish,bash,zsh} files that are hand-maintained and drift from the actual command surface in src/cli.ts. There is no pty completions subcommand, so downstreams (Home Manager, distro packages) can't regenerate them from the binary.

What

Adds pty completions <shell> (fish/bash/zsh) that prints a completion script to stdout, generated from a single declarative command-tree spec in src/completions.ts. The existing completions/pty.{fish,bash,zsh} are now produced by this generator and carry a "generated by pty completions" header.

How

  • src/completions.ts owns one CommandSpec[] describing commands → flags, enum-valued flags, and positionals. It emits all three shell scripts, so they cannot drift.
  • src/cli.ts dispatches case "completions" to the generator (exit code 2 + usage on unknown/missing shell, 0 on --help).
  • Dynamic session completion is preserved: verbs taking a <ref> are marked dynamic: "sessions" and the generator emits the per-shell idiom that reads <root>/*.json at completion time (same behavior as the legacy static files). up/down get path completion; list/ls --status get the running|exited|vanished enum.
  • tests/completions.test.ts asserts every command documented in COMMAND_HELP has a matching spec entry, and that the generated scripts are syntactically valid (fish -n / bash -n via the built CLI).

Rationale

Mirrors st's st completions design (which pty was modeled on), extended with the two things pty specifically needs: live session-name completion and path completion. Keeping the static files as generated artifacts means there is now exactly one source of truth.

Verification

  • npm run build and npm run typecheck pass.
  • tests/completions.test.ts passes (including a real fish -n / bash -n syntax check and a dynamic-session completion smoke test).
  • package-lock.json is unchanged, so the existing flake.nix npmDepsHash stays valid and nix build .#pty is unaffected.

… sessions)

- src/completions.ts owns one declarative command-tree spec that emits
  fish, bash, and zsh completion scripts, so the three can't drift.
- Keeps pty's dynamic session-name completion (reads <root>/*.json at
  completion time) for every verb that takes a <ref>, plus path completion
  for up/down and enum completion for list/ls --status.
- src/cli.ts dispatches `case "completions"` to the generator.
- Regenerated completions/pty.{fish,bash,zsh} from the generator; the
  static files now carry a 'generated by pty completions' header.
- tests/completions.test.ts guards COMMAND_HELP<->spec parity and shell
  syntax (fish -n / bash -n via the built CLI).
@schickling
schickling marked this pull request as ready for review July 20, 2026 09:58
@schickling
schickling marked this pull request as draft July 20, 2026 10:10
@schickling
schickling marked this pull request as ready for review July 20, 2026 14:00
@schickling
schickling merged commit 0a9be8c into compoundingtech:main Jul 20, 2026
1 check passed
myobie added a commit that referenced this pull request Jul 21, 2026
…k parity + wire vitest CI (#114)

Un-breaks the post-exit parity contract that #111 (exit-reap) broke on main, per
Nathan's call: make reap-vs-preserve-on-exit CONFIGURABLE rather than a fixed
default.

- PTY_REAP_ON_EXIT env knob (network/global; the daemon inherits it via
  spawn.ts) sets the default: false/0/no/off -> preserve, unset/else -> reap
  (shipped default). Per-session keep=true (force preserve) / --ephemeral
  (force reap) override it. shouldReapAtExit gains an OPTIONAL defaultReap
  param (defaults to reapOnExitDefault()) so the re-exported 2-arg API
  (relay/layout/supervisors) stays backward-compatible.
- parity #1 now asserts BOTH modes (preserve keeps the final screen; reap
  reaps). exit-reap.test.ts keeps the reap-default suite + adds a preserve-mode
  block. isolate-env.ts scrubs PTY_REAP_ON_EXIT for a deterministic default.
- help.test.ts: completions -> NON_COMMAND_CASES (fixes pre-existing #106 help
  drift; completions ships its own lightweight usage, not the strict
  per-subcommand format).
- CI: add .github/workflows/test.yml gating the vitest suite (Node 22, matches
  flake.nix) on PR + push-to-main. Installs the test-only binaries
  ubuntu-latest lacks (zsh/fish for shells.test.ts; a no-op claude stub for
  restart-guardrail). The push CI was Nix-build-only, which is how both breaks
  reached main invisibly. Supersedes #113.
- Docs: README "Session lifecycle and cleanup" + CHANGELOG rewritten for the
  configurable setting.

Full suite green: 1408 passed, 21 pre-existing env-gated skips.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant