From 8cdbf1e6bdb7a183f45d49eaff899e5c7742ef78 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Fri, 26 Dec 2025 14:58:07 -0800 Subject: [PATCH] feat: Add --args flag for natural language executor instructions (gt-1py3y) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Args field to SlungWork struct in wisp/types.go - Add --args/-a flag to gt sling command - Display args in gt prime autonomous mode - Display args in gt mol status output The --args string is stored in the hook and shown to the LLM executor, which interprets the instructions naturally without schema maintenance. Example: gt sling beads-release --args "patch release" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/cmd/molecule_status.go | 3 +++ internal/cmd/prime.go | 5 +++++ internal/cmd/sling.go | 34 +++++++++++++++++++++++++++++---- internal/wisp/types.go | 5 +++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/internal/cmd/molecule_status.go b/internal/cmd/molecule_status.go index 7402c91f..0ff2ef10 100644 --- a/internal/cmd/molecule_status.go +++ b/internal/cmd/molecule_status.go @@ -462,6 +462,9 @@ func outputMoleculeStatus(status MoleculeStatusInfo) error { if status.SlungWork.Context != "" { fmt.Printf(" Context: %s\n", status.SlungWork.Context) } + if status.SlungWork.Args != "" { + fmt.Printf(" Args: %s\n", style.Bold.Render(status.SlungWork.Args)) + } fmt.Printf(" Slung by: %s at %s\n", status.SlungWork.CreatedBy, status.SlungWork.CreatedAt.Format("2006-01-02 15:04:05")) diff --git a/internal/cmd/prime.go b/internal/cmd/prime.go index f9cd1f5f..4154c492 100644 --- a/internal/cmd/prime.go +++ b/internal/cmd/prime.go @@ -1360,6 +1360,11 @@ func checkSlungWork(ctx RoleContext) bool { if sw.Context != "" { fmt.Printf(" Context: %s\n", sw.Context) } + if sw.Args != "" { + fmt.Printf(" Args: %s\n", style.Bold.Render(sw.Args)) + fmt.Println() + fmt.Printf(" %s Use these args to guide your execution.\n", style.Bold.Render("→")) + } fmt.Printf(" Slung by: %s at %s\n", sw.CreatedBy, sw.CreatedAt.Format("2006-01-02 15:04:05")) fmt.Println() diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index e72cfffa..3fb0c6c3 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -41,6 +41,13 @@ Standalone formula slinging: gt sling mol-town-shutdown mayor/ # Cook + wisp + attach + nudge gt sling towers-of-hanoi --var disks=3 # With formula variables +Natural language args (for LLM executor): + gt sling beads-release --args "patch release" + gt sling code-review gt-abc --args "focus on security issues" + +The --args string is stored in the hook and shown to the executor. +Since the executor is an LLM, it interprets these instructions naturally. + When the first argument is a formula (not a bead), sling will: 1. Cook the formula (bd cook) 2. Create a wisp instance (bd wisp) @@ -69,6 +76,7 @@ var ( slingDryRun bool slingOnTarget string // --on flag: target bead when slinging a formula slingVars []string // --var flag: formula variables (key=value) + slingArgs string // --args flag: natural language instructions for executor ) func init() { @@ -77,6 +85,7 @@ func init() { slingCmd.Flags().BoolVarP(&slingDryRun, "dry-run", "n", false, "Show what would be done") slingCmd.Flags().StringVar(&slingOnTarget, "on", "", "Apply formula to existing bead (implies wisp scaffolding)") slingCmd.Flags().StringArrayVar(&slingVars, "var", nil, "Formula variable (key=value), can be repeated") + slingCmd.Flags().StringVarP(&slingArgs, "args", "a", "", "Natural language instructions for the executor (e.g., 'patch release')") rootCmd.AddCommand(slingCmd) } @@ -150,6 +159,7 @@ func runSling(cmd *cobra.Command, args []string) error { sw.Subject = slingSubject sw.Context = slingMessage sw.Formula = formulaName + sw.Args = slingArgs // Display what we're doing if formulaName != "" { @@ -172,6 +182,9 @@ func runSling(cmd *cobra.Command, args []string) error { if slingMessage != "" { fmt.Printf(" context: %s\n", slingMessage) } + if slingArgs != "" { + fmt.Printf(" args: %s\n", slingArgs) + } fmt.Printf("Would inject start prompt to pane: %s\n", targetPane) return nil } @@ -184,7 +197,7 @@ func runSling(cmd *cobra.Command, args []string) error { fmt.Printf("%s Work attached to hook\n", style.Bold.Render("✓")) // Inject the "start now" prompt - if err := injectStartPrompt(targetPane, beadID, slingSubject); err != nil { + if err := injectStartPrompt(targetPane, beadID, slingSubject, slingArgs); err != nil { return fmt.Errorf("injecting start prompt: %w", err) } @@ -194,14 +207,21 @@ func runSling(cmd *cobra.Command, args []string) error { // injectStartPrompt sends a prompt to the target pane to start working. // Uses the reliable nudge pattern: literal mode + 500ms debounce + separate Enter. -func injectStartPrompt(pane, beadID, subject string) error { +func injectStartPrompt(pane, beadID, subject, args string) error { if pane == "" { return fmt.Errorf("no target pane") } // Build the prompt to inject var prompt string - if subject != "" { + if args != "" { + // Args provided - include them prominently in the prompt + if subject != "" { + prompt = fmt.Sprintf("Work slung: %s (%s). Args: %s. Start working now - use these args to guide your execution.", beadID, subject, args) + } else { + prompt = fmt.Sprintf("Work slung: %s. Args: %s. Start working now - use these args to guide your execution.", beadID, args) + } + } else if subject != "" { prompt = fmt.Sprintf("Work slung: %s (%s). Start working on it now - no questions, just begin.", beadID, subject) } else { prompt = fmt.Sprintf("Work slung: %s. Start working on it now - run `gt mol status` to see the hook, then begin.", beadID) @@ -429,6 +449,7 @@ func runSlingFormula(args []string) error { } sw.Context = slingMessage sw.Formula = formulaName + sw.Args = slingArgs if err := wisp.WriteSlungWork(hookRoot, targetAgent, sw); err != nil { return fmt.Errorf("writing to hook: %w", err) @@ -441,7 +462,12 @@ func runSlingFormula(args []string) error { return nil } - prompt := fmt.Sprintf("Formula %s slung. Run `gt mol status` to see your hook, then execute the steps.", formulaName) + var prompt string + if slingArgs != "" { + prompt = fmt.Sprintf("Formula %s slung. Args: %s. Run `gt mol status` to see your hook, then execute using these args.", formulaName, slingArgs) + } else { + prompt = fmt.Sprintf("Formula %s slung. Run `gt mol status` to see your hook, then execute the steps.", formulaName) + } t := tmux.NewTmux() if err := t.NudgePane(targetPane, prompt); err != nil { return fmt.Errorf("nudging: %w", err) diff --git a/internal/wisp/types.go b/internal/wisp/types.go index 138abf05..e9409230 100644 --- a/internal/wisp/types.go +++ b/internal/wisp/types.go @@ -63,6 +63,11 @@ type SlungWork struct { // Subject is optional subject line (used in handoff mail). Subject string `json:"subject,omitempty"` + + // Args is optional natural language instructions for the formula executor. + // Example: "patch release" or "focus on security issues" + // The LLM executor interprets these instructions - no schema needed. + Args string `json:"args,omitempty"` } // NewSlungWork creates a new slung work hook file.