Skip to main content

sift_queue/cli/commands/
prime.rs

1use anyhow::Result;
2use clap::CommandFactory;
3
4/// Execute the `sq prime` command.
5pub fn execute() -> Result<i32> {
6    println!("{}", generate());
7    Ok(0)
8}
9
10/// Generate the prime context string.
11pub fn generate() -> String {
12    let mut parts = Vec::new();
13
14    parts.push(
15        r#"# Sift — Queue-Driven Review System
16
17Sift is a queue-driven review system where **humans make decisions** and **agents do the work**.
18
19## Core Workflow
20
211. Items enter the queue via `sq add` (with sources: text, diff, file, directory)
222. A human launches `sift` to review pending items in the TUI
233. For each item, the human can view the sources and spawn agents to act on them
244. When an agent finishes, its transcript is appended as a source on the item
25
26## `sq` Commands"#
27            .to_string(),
28    );
29
30    parts.push(generate_command_reference());
31
32    parts.join("\n\n")
33}
34
35fn generate_command_reference() -> String {
36    let cmd = crate::Cli::command();
37    let mut lines = Vec::new();
38
39    for sub in cmd.get_subcommands() {
40        let name = sub.get_name();
41        if name == "prime" || name == "help" {
42            continue;
43        }
44
45        let about = sub
46            .get_about()
47            .map(|a| a.to_string())
48            .unwrap_or_default();
49        lines.push(format!("### `sq {}` — {}\n", name, about));
50        lines.push("```".to_string());
51
52        for arg in sub.get_arguments() {
53            if arg.is_hide_set() {
54                continue;
55            }
56            let id = arg.get_id().as_str();
57            if id == "help" || id == "version" {
58                continue;
59            }
60
61            // Skip positional arguments in the flags listing
62            let is_positional = arg.get_long().is_none() && arg.get_short().is_none();
63            if is_positional {
64                continue;
65            }
66
67            let long = arg.get_long().map(|l| format!("--{}", l));
68            let short = arg.get_short().map(|s| format!("-{}", s));
69            let names: Vec<String> = [short, long].into_iter().flatten().collect();
70            let names_str = names.join(", ");
71
72            // For boolean flags (num_vals == 0), don't show value name
73            let is_bool = arg.get_action().takes_values();
74            let value = if is_bool {
75                arg.get_value_names()
76                    .map(|v| {
77                        v.iter()
78                            .map(|s| s.to_string())
79                            .collect::<Vec<_>>()
80                            .join(" ")
81                    })
82                    .unwrap_or_default()
83            } else {
84                String::new()
85            };
86
87            let usage = if value.is_empty() {
88                names_str
89            } else {
90                format!("{} {}", names_str, value)
91            };
92
93            let help = arg
94                .get_help()
95                .map(|h| h.to_string())
96                .unwrap_or_default();
97
98            lines.push(format!("  {}  {}", usage, help));
99        }
100
101        lines.push("```".to_string());
102        lines.push(String::new());
103        lines.push(format!("For more information, use `sq {} --help`.", name));
104        lines.push(String::new());
105    }
106
107    lines.join("\n")
108}