package inbox import ( "fmt" "ai-workflow-skill/packages/coord-core/protocol" "ai-workflow-skill/packages/coord-core/store" "github.com/spf13/cobra" ) type listOptions struct { agent string statuses string createdBy string assignedTo string limit int } func newListCmd(root *rootOptions) *cobra.Command { opts := &listOptions{} cmd := &cobra.Command{ Use: "list", Short: "List threads with filters", Long: helpLong( "Use list for broad inbox inspection across many threads.", "Compared with fetch: fetch is the worker discovery step before claim, while list is the general inspection surface for leaders, operators, and debugging.", "Use list when you want to scan by assigned worker, creator, or status without implying that the current agent plans to claim the work.", ), Example: ` inbox --db .agents/coord.db list --status blocked,in_progress inbox --db .agents/coord.db list --assigned-to worker-a --status pending --limit 10 inbox --db .agents/coord.db list --created-by orch --status done,failed`, RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() agent := opts.agent if agent == "" { agent = root.agent } sqlDB, err := openInboxDB(ctx, root.dbPath) if err != nil { return err } defer sqlDB.Close() s := store.NewInboxStore(sqlDB) threads, err := s.ListThreads(ctx, store.ListInput{ Agent: agent, Statuses: parseCSV(opts.statuses), CreatedBy: opts.createdBy, AssignedTo: opts.assignedTo, Limit: opts.limit, }) if err != nil { return err } if len(threads) == 0 { return protocol.NoMatchingWork("no matching work") } resp := protocol.Success{ OK: true, Command: "list", Data: map[string]any{ "threads": threads, }, } if root.json { return protocol.WriteJSON(cmd.OutOrStdout(), resp) } for _, thread := range threads { if _, err := fmt.Fprintf(cmd.OutOrStdout(), "%s\t%s\t%s\t%s\n", thread.ThreadID, thread.Status, thread.AssignedTo, thread.Subject); err != nil { return err } } return nil }, } cmd.Flags().StringVar(&opts.agent, "agent", "", "Shortcut for filtering threads assigned to one agent") cmd.Flags().StringVar(&opts.statuses, "status", "", "Comma-separated status filter such as pending,blocked,done") cmd.Flags().StringVar(&opts.createdBy, "created-by", "", "Only include threads created by this agent") cmd.Flags().StringVar(&opts.assignedTo, "assigned-to", "", "Only include threads currently assigned to this agent") cmd.Flags().IntVar(&opts.limit, "limit", 20, "Maximum number of threads to return") return cmd }