cmdAutoExec is the hidden `flow __auto-exec ` supervisor. It runs inside the detached process the launcher started: build the autonomous prompt, run claude headlessly to completion, then finalize the run status. Not listed in usage — it's an internal re-entry point.
(args []string)
| 217 | } |
| 218 | t.AutoRunPID = sql.NullInt64{} |
| 219 | } |
| 220 | |
| 221 | // cmdAutoExec is the hidden `flow __auto-exec <slug>` supervisor. It runs |
| 222 | // inside the detached process the launcher started: build the autonomous |
| 223 | // prompt, run claude headlessly to completion, then finalize the run |
| 224 | // status. Not listed in usage — it's an internal re-entry point. |
| 225 | func cmdAutoExec(args []string) int { |
| 226 | if len(args) == 0 { |
| 227 | fmt.Fprintln(os.Stderr, "error: __auto-exec requires a task slug") |
| 228 | return 2 |
| 229 | } |
| 230 | slug := args[0] |
| 231 | fs := flagSet("__auto-exec") |
| 232 | withInstr := fs.String("with", "", "one-off instruction to append to the autonomous prompt") |
| 233 | if err := fs.Parse(args[1:]); err != nil { |
| 234 | return 2 |
| 235 | } |
| 236 | |
| 237 | dbPath, err := flowDBPath() |
| 238 | if err != nil { |
| 239 | fmt.Fprintf(os.Stderr, "error: %v\n", err) |
| 240 | return 1 |
| 241 | } |
| 242 | db, err := openConcurrentDB(dbPath) |
| 243 | if err != nil { |
| 244 | fmt.Fprintf(os.Stderr, "error: %v\n", err) |
| 245 | return 1 |
| 246 | } |
| 247 | defer db.Close() |
| 248 | |
| 249 | task, err := flowdb.GetTask(db, slug) |
| 250 | if err != nil { |
| 251 | fmt.Fprintf(os.Stderr, "error: load task %q: %v\n", slug, err) |
| 252 | return 1 |
| 253 | } |
| 254 | if !task.SessionID.Valid || task.SessionID.String == "" { |
| 255 | fmt.Fprintf(os.Stderr, "error: task %q has no session_id; cannot run headlessly\n", slug) |
| 256 | _ = finalizeAutoRun(db, slug, "dead") |
| 257 | return 1 |
| 258 | } |
| 259 | |
| 260 | playbookSlug := "" |
| 261 | if task.PlaybookSlug.Valid { |
| 262 | playbookSlug = task.PlaybookSlug.String |
| 263 | } |
| 264 | prompt := buildAutoBootstrapPrompt(slug, task.Kind, playbookSlug) |
| 265 | |
| 266 | // Resolve the task's harness (claude today; codex/gemini once their |
| 267 | // adapters implement AutoRunArgv). The --with instruction rides via |
| 268 | // opts.Inject so the harness wraps it behind InjectionMarker — same |
| 269 | // contract as the interactive --with path. |
| 270 | h, herr := harnessForSpawn(task) |
| 271 | if herr != nil { |
| 272 | fmt.Fprintf(os.Stderr, "error: resolve harness for %q: %v\n", slug, herr) |
| 273 | _ = finalizeAutoRun(db, slug, "dead") |
| 274 | return 1 |
| 275 | } |
| 276 | opts := harness.LaunchOpts{SkipPermissions: true, Inject: *withInstr} |