Terminal session persistence. Run sessions that survive disconnects, reattach later.
Wanted to understand PTY internals without leaving the comfort of Go, so I prompted the shit out of Claude to help me. You're probably better off with tmux, zellij, shpool, or zmx.
A Go daemon manages sessions. Each session runs a shell in a PTY and tracks terminal state using libghostty/ghostty-vt compiled to WASM. When you reattach, it reconstructs the screen from that state.
If Ghostty is installed, hauntty injects its shell integration scripts.
The ht client talks to the daemon over a Unix socket.
attach, a Attach to a session, create if needed
new Create/start a session without attaching
restore Restore a dead session from saved state
list, ls List sessions
kill Kill a session
send Send input to a session without attaching
dump Dump session screen contents
kick Disconnect a specific attached client
wait Wait for output to match a pattern
status, st Show daemon and session status
prune Delete dead session state files
init Create default config file
config Print current configuration
daemon Start daemon in foreground
completion Print shell completion setup instructions
Run ht <command> --help for details.
ht attach work # attach to session, create it if needed
ht attach -r work # attach read-only
ht new work npm run dev # create/start without attaching
ht restore work # restore a dead session from saved state
ht status # show daemon/session status
ht kick work 1 # disconnect attached client 1
# detach from an attached client with ctrl+;, configured by detach_keybindDaemon starts on first attach, new, or restore. Sessions persist until killed or the shell exits.
When a session exits, its saved state can be restored with ht restore <name>
or removed with ht prune.
go install code.selman.me/hauntty/cmd/ht@latest
go build -o ht ./cmd/ht
Default path is $XDG_CONFIG_HOME/hauntty/config.toml when XDG_CONFIG_HOME is set; otherwise it is ~/.config/hauntty/config.toml. Run ht init to create it.
[daemon]
# Leave empty to use the default runtime socket path.
socket_path = ""
# Exit automatically when the last live session ends.
auto_exit = false
# Default scrollback size for new and attached sessions.
default_scrollback = 10000
# Persist dead session state to disk.
state_persistence = true
# Save session state every N seconds while the session is running. Must be > 0.
state_persistence_interval = 30
[client]
# Key used to detach from an attached client.
detach_keybind = "ctrl+;"
# Extra environment variables to forward from client to session.
forward_env = ["COLORTERM", "GHOSTTY_RESOURCES_DIR", "GHOSTTY_BIN_DIR"]
[session]
# Leave empty to use the user's shell as the default command.
default_command = ""
# Resize arbitration policy for multi-client sessions.
# Valid values are "smallest", "largest", "first", and "last".
resize_policy = "smallest"Forwarded from client to session:
TERM,SHELL; always forwardedCOLORTERM,GHOSTTY_RESOURCES_DIR,GHOSTTY_BIN_DIR; forwarded by default config
Configure forward_env in config to change the extra forwarded variables.
Set by hauntty:
HAUNTTY_SESSION- session name, set inside sessionsHAUNTTY_SOCKET- socket path override for client commands