feat: native SSH delegation via tea.ExecProcess + Gruvbox palette

Phase A — Tamagosh-inspired redesign:
- Replace goroutine-based SSH (crypto/ssh) with tea.ExecProcess + native ssh binary
- Zero-lag SSH: native binary pegang TTY langsung, ga ada Go buffering
- Password auth via sshpass -e (SSHPASS env)
- Key auth via ssh -i <tmpfile> + SSH_ASKPASS for passphrase
- ControlMaster sockets for fast reconnect
- Add askpass subcommand for SSH_ASKPASS support
- Gruvbox Material Dark Hard palette for comfortable viewing
- Clean up old session messages (openSessionMsg, sessionOutputMsg, sessionDoneMsg)
- Remove 354-line session.go, replace with 150-line ssh.go
This commit is contained in:
swanadiva
2026-06-23 15:36:40 +07:00
parent b319f44c3e
commit 7b06793002
8 changed files with 177 additions and 397 deletions
+28 -25
View File
@@ -2,37 +2,40 @@ package tui
import "github.com/charmbracelet/lipgloss"
// Orange theme palette
// Gruvbox Material Dark Hard palette — warm, soft, easy on eyes
var (
OrangePrimary = lipgloss.Color("#FF6B00")
OrangeSecondary = lipgloss.Color("#FF9F43")
OrangeLight = lipgloss.Color("#FFB800")
DarkBg = lipgloss.Color("#1A1A1A")
LightBg = lipgloss.Color("#2D2D2D")
TextPrimary = lipgloss.Color("#FFFFFF")
TextSecondary = lipgloss.Color("#AAAAAA")
GreenSuccess = lipgloss.Color("#00FF88")
RedError = lipgloss.Color("#FF4444")
BlueInfo = lipgloss.Color("#44AAFF")
gbFg = lipgloss.Color("#d4be98") // primary text
gbFgMute = lipgloss.Color("#7c6f64") // secondary/hints
gbBgSel = lipgloss.Color("#45403d") // cursor row bg
gbRed = lipgloss.Color("#ea6962") // error/destructive
gbOrange = lipgloss.Color("#e78a4e") // section headers
gbYellow = lipgloss.Color("#d8a657") // accent/titles
gbGreen = lipgloss.Color("#a9b665") // active pane/success
gbAqua = lipgloss.Color("#89b482") // interactive keys
gbBlue = lipgloss.Color("#7daea3")
gbPurple = lipgloss.Color("#d3869b")
gbBorder = lipgloss.Color("#504945") // subtle border
)
// Component styles
var (
TabActiveStyle = lipgloss.NewStyle().Background(OrangePrimary).Foreground(DarkBg).Bold(true).Padding(0, 2)
TabInactiveStyle = lipgloss.NewStyle().Background(LightBg).Foreground(TextSecondary).Padding(0, 2)
TabBarStyle = lipgloss.NewStyle().Background(DarkBg)
StatusBarStyle = lipgloss.NewStyle().Background(OrangePrimary).Foreground(DarkBg).Padding(0, 1)
AppTitleStyle = lipgloss.NewStyle().Foreground(OrangeSecondary).Bold(true)
HighlightStyle = lipgloss.NewStyle().Foreground(OrangePrimary).Bold(true)
SelectedStyle = lipgloss.NewStyle().Foreground(DarkBg).Background(OrangePrimary).Padding(0, 1)
ErrorStyle = lipgloss.NewStyle().Foreground(RedError).Bold(true)
SuccessStyle = lipgloss.NewStyle().Foreground(GreenSuccess).Bold(true)
InfoStyle = lipgloss.NewStyle().Foreground(BlueInfo)
SubtitleStyle = lipgloss.NewStyle().Foreground(TextSecondary)
HostNameStyle = lipgloss.NewStyle().Foreground(OrangeLight).Bold(true)
HostDetailStyle = lipgloss.NewStyle().Foreground(TextSecondary)
TagStyle = lipgloss.NewStyle().Foreground(GreenSuccess)
TabActiveStyle = lipgloss.NewStyle().Background(gbYellow).Foreground(lipgloss.Color("#1d2021")).Bold(true).Padding(0, 2)
TabInactiveStyle = lipgloss.NewStyle().Background(gbBorder).Foreground(gbFgMute).Padding(0, 2)
TabBarStyle = lipgloss.NewStyle().Background(lipgloss.Color("#1d2021"))
StatusBarStyle = lipgloss.NewStyle().Background(gbGreen).Foreground(lipgloss.Color("#1d2021")).Padding(0, 1)
AppTitleStyle = lipgloss.NewStyle().Foreground(gbYellow).Bold(true)
HighlightStyle = lipgloss.NewStyle().Foreground(gbOrange).Bold(true)
SelectedStyle = lipgloss.NewStyle().Foreground(gbFg).Background(gbBgSel).Bold(true).Padding(0, 1)
ErrorStyle = lipgloss.NewStyle().Foreground(gbRed).Bold(true)
SuccessStyle = lipgloss.NewStyle().Foreground(gbGreen).Bold(true)
InfoStyle = lipgloss.NewStyle().Foreground(gbAqua)
SubtitleStyle = lipgloss.NewStyle().Foreground(gbFgMute)
HostNameStyle = lipgloss.NewStyle().Foreground(gbYellow).Bold(true)
HostDetailStyle = lipgloss.NewStyle().Foreground(gbFgMute)
TagStyle = lipgloss.NewStyle().Foreground(gbGreen)
TitleStyle = AppTitleStyle
SectionStyle = lipgloss.NewStyle().Foreground(gbOrange).Bold(true)
BorderStyle = lipgloss.NewStyle().Border(lipgloss.RoundedBorder()).BorderForeground(gbBorder).Padding(1, 2)
)
// TabWidth returns the width of the tab bar content