feat: add headless mode support for SSH -N connections
All checks were successful
Docker Build and Push / build-and-push-branches (push) Has been skipped
Docker Build and Push / build-and-push-tags (push) Successful in 3m3s

- use s.lifecycle.GetConnection().Wait() to block until SSH connection closes
- Prevent premature session closure in headless mode

In headless mode (ssh -N), there's no channel interaction to block on,
so the session would immediately return and close. Now blocking on
conn.Wait() keeps the session alive until the client disconnects.
This commit is contained in:
2026-01-11 15:21:11 +07:00
parent 19fd6d59d2
commit e1f5d73e03
5 changed files with 65 additions and 14 deletions

View File

@@ -37,6 +37,9 @@ type Controller interface {
SetWH(w, h int)
Redraw()
SetSessionRegistry(registry SessionRegistry)
SetMode(m types.Mode)
GetMode() types.Mode
Send(message string) error
}
type Forwarder interface {
@@ -54,8 +57,24 @@ type Interaction struct {
program *tea.Program
ctx context.Context
cancel context.CancelFunc
mode types.Mode
}
func (i *Interaction) SetMode(m types.Mode) {
i.mode = m
}
func (i *Interaction) GetMode() types.Mode {
return i.mode
}
func (i *Interaction) Send(message string) error {
if i.channel != nil {
_, err := i.channel.Write([]byte(message))
return err
}
return nil
}
func (i *Interaction) SetWH(w, h int) {
if i.program != nil {
i.program.Send(tea.WindowSizeMsg{
@@ -749,6 +768,9 @@ func (m *model) View() string {
}
func (i *Interaction) Start() {
if i.mode == types.HEADLESS {
return
}
lipgloss.SetColorProfile(termenv.TrueColor)
domain := config.Getenv("DOMAIN", "localhost")