Add clickable mail preview in tmux status bar

- New `gt mail peek` command shows compact preview of first unread message
- Left-click on status-right (mail icon area) opens popup with mail preview
- Popup shows subject, sender, body preview (truncated to 500 chars)
- Shows count of additional unread messages if any
- Silent exit (code 1) when no unread mail

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-21 23:14:08 -08:00
parent 19fd7e05b2
commit b254b4b3f8
2 changed files with 86 additions and 0 deletions

View File

@@ -110,6 +110,16 @@ The message ID can be found from 'gt mail inbox'.`,
RunE: runMailRead,
}
var mailPeekCmd = &cobra.Command{
Use: "peek",
Short: "Show preview of first unread message",
Long: `Display a compact preview of the first unread message.
Useful for status bar popups - shows subject, sender, and body preview.
Exits silently with code 1 if no unread messages.`,
RunE: runMailPeek,
}
var mailDeleteCmd = &cobra.Command{
Use: "delete <message-id>",
Short: "Delete a message",
@@ -221,6 +231,7 @@ func init() {
mailCmd.AddCommand(mailSendCmd)
mailCmd.AddCommand(mailInboxCmd)
mailCmd.AddCommand(mailReadCmd)
mailCmd.AddCommand(mailPeekCmd)
mailCmd.AddCommand(mailDeleteCmd)
mailCmd.AddCommand(mailArchiveCmd)
mailCmd.AddCommand(mailCheckCmd)
@@ -448,6 +459,68 @@ func runMailRead(cmd *cobra.Command, args []string) error {
return nil
}
func runMailPeek(cmd *cobra.Command, args []string) error {
// Determine which inbox
address := detectSender()
// All mail uses town beads (two-level architecture)
workDir, err := findMailWorkDir()
if err != nil {
os.Exit(1) // Silent exit - no workspace
return nil
}
// Get mailbox
router := mail.NewRouter(workDir)
mailbox, err := router.GetMailbox(address)
if err != nil {
os.Exit(1) // Silent exit - can't access mailbox
return nil
}
// Get unread messages
messages, err := mailbox.ListUnread()
if err != nil || len(messages) == 0 {
os.Exit(1) // Silent exit - no unread
return nil
}
// Show first unread message
msg := messages[0]
// Header with priority indicator
priorityStr := ""
if msg.Priority == mail.PriorityUrgent {
priorityStr = " [URGENT]"
} else if msg.Priority == mail.PriorityHigh {
priorityStr = " [!]"
}
fmt.Printf("📬 %s%s\n", msg.Subject, priorityStr)
fmt.Printf("From: %s\n", msg.From)
fmt.Printf("ID: %s\n\n", msg.ID)
// Body preview (truncate long bodies)
if msg.Body != "" {
body := msg.Body
// Truncate to ~500 chars for popup display
if len(body) > 500 {
body = body[:500] + "\n..."
}
fmt.Print(body)
if !strings.HasSuffix(body, "\n") {
fmt.Println()
}
}
// Show count if more messages
if len(messages) > 1 {
fmt.Printf("\n%s\n", style.Dim.Render(fmt.Sprintf("(+%d more unread)", len(messages)-1)))
}
return nil
}
func runMailDelete(cmd *cobra.Command, args []string) error {
msgID := args[0]

View File

@@ -498,5 +498,18 @@ func (t *Tmux) ConfigureGasTownSession(session string, theme Theme, rig, worker,
if err := t.SetDynamicStatus(session); err != nil {
return fmt.Errorf("setting dynamic status: %w", err)
}
if err := t.SetMailClickBinding(session); err != nil {
return fmt.Errorf("setting mail click binding: %w", err)
}
return nil
}
// SetMailClickBinding configures left-click on status-right to show mail preview.
// This creates a popup showing the first unread message when clicking the mail icon area.
func (t *Tmux) SetMailClickBinding(session string) error {
// Bind left-click on status-right to show mail popup
// The popup runs gt mail peek and closes on any key
_, err := t.run("bind-key", "-T", "root", "MouseDown1StatusRight",
"display-popup", "-E", "-w", "60", "-h", "15", "gt mail peek || echo 'No unread mail'")
return err
}