feat(handoff): add -s/-m flags for ergonomic handoff mail

Agents naturally expect `gt handoff -s "Subject" -m "Message"` to work
like `gt mail send`. Now it does:

- Added --subject/-s and --message/-m flags to gt handoff
- Added --self flag to gt mail send for sending to self
- Handoff auto-sends mail to self before respawning pane

This makes agent-initiated handoff more ergonomic - they can include
context in a single command instead of two separate steps.

🤖 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-23 01:51:33 -08:00
parent 5459e8e6b1
commit 18fb0e05fe
2 changed files with 64 additions and 5 deletions

View File

@@ -33,13 +33,17 @@ Any molecule on the hook will be auto-continued by the new session.`,
}
var (
handoffWatch bool
handoffDryRun bool
handoffWatch bool
handoffDryRun bool
handoffSubject string
handoffMessage string
)
func init() {
handoffCmd.Flags().BoolVarP(&handoffWatch, "watch", "w", true, "Switch to new session (for remote handoff)")
handoffCmd.Flags().BoolVarP(&handoffDryRun, "dry-run", "n", false, "Show what would be done without executing")
handoffCmd.Flags().StringVarP(&handoffSubject, "subject", "s", "", "Subject for handoff mail (optional)")
handoffCmd.Flags().StringVarP(&handoffMessage, "message", "m", "", "Message body for handoff mail (optional)")
rootCmd.AddCommand(handoffCmd)
}
@@ -83,6 +87,16 @@ func runHandoff(cmd *cobra.Command, args []string) error {
return handoffRemoteSession(t, targetSession, restartCmd)
}
// If subject/message provided, send handoff mail to self first
if handoffSubject != "" || handoffMessage != "" {
if err := sendHandoffMail(handoffSubject, handoffMessage); err != nil {
fmt.Printf("%s Warning: could not send handoff mail: %v\n", style.Dim.Render("⚠"), err)
// Continue anyway - the respawn is more important
} else {
fmt.Printf("%s Sent handoff mail\n", style.Bold.Render("📬"))
}
}
// Handing off ourselves - print feedback then respawn
fmt.Printf("%s Handing off %s...\n", style.Bold.Render("🤝"), currentSession)
@@ -239,3 +253,24 @@ func getSessionPane(sessionName string) (string, error) {
}
return lines[0], nil
}
// sendHandoffMail sends a handoff mail to self using gt mail send.
func sendHandoffMail(subject, message string) error {
// Build subject with handoff prefix if not already present
if subject == "" {
subject = "🤝 HANDOFF: Session cycling"
} else if !strings.Contains(subject, "HANDOFF") {
subject = "🤝 HANDOFF: " + subject
}
// Default message if not provided
if message == "" {
message = "Context cycling. Check bd ready for pending work."
}
// Use gt mail send to self (--self flag sends to current agent identity)
cmd := exec.Command("gt", "mail", "send", "--self", "-s", subject, "-m", message)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}