sift_queue/cli/commands/
prime.rs1use anyhow::Result;
2
3pub fn execute() -> Result<i32> {
5 println!("{}", generate());
6 Ok(0)
7}
8
9pub fn generate() -> String {
11 let mut parts = Vec::new();
12
13 parts.push(
14 r#"# sq — Lightweight task-list CLI with structured sources
15
16`sq` manages tasks in a JSONL file for agent workflows.
17
18By default, `sq` stores tasks in `.sift/issues.jsonl`. Override with `-q, --queue <PATH>` or `SQ_QUEUE_PATH=<PATH>`.
19
20## Examples
21
22```bash
23sq add --title "Investigate checkout exception" \
24 --description "Review the pasted error report and identify the failing code path" \
25 --text "Sentry alert: NoMethodError in Checkout::ApplyDiscount at app/services/checkout/apply_discount.rb:42"
26
27rg --json -n -C2 'OldApi.call' | sq collect --by-file \
28 --title-template "migrate: {{filepath}}" \
29 --description "Migrate OldApi.call to NewApi.call"
30
31sq list --ready
32```
33
34## `sq` Commands"#
35 .to_string(),
36 );
37
38 parts.push(generate_command_reference());
39
40 parts.join("\n\n")
41}
42
43fn generate_command_reference() -> String {
44 let cmd = crate::build_cli();
45 let mut lines = Vec::new();
46
47 for sub in cmd.get_subcommands() {
48 let name = sub.get_name();
49 if name == "prime" || name == "help" {
50 continue;
51 }
52
53 let about = sub.get_about().map(|a| a.to_string()).unwrap_or_default();
54 lines.push(format!("### `sq {}` — {}\n", name, about));
55 lines.push("```".to_string());
56
57 for arg in sub.get_arguments() {
58 if arg.is_hide_set() {
59 continue;
60 }
61 let id = arg.get_id().as_str();
62 if id == "help" || id == "version" {
63 continue;
64 }
65
66 let is_positional = arg.get_long().is_none() && arg.get_short().is_none();
68 if is_positional {
69 continue;
70 }
71
72 let long = arg.get_long().map(|l| format!("--{}", l));
73 let short = arg.get_short().map(|s| format!("-{}", s));
74 let names: Vec<String> = [short, long].into_iter().flatten().collect();
75 let names_str = names.join(", ");
76
77 let is_bool = arg.get_action().takes_values();
79 let value = if is_bool {
80 arg.get_value_names()
81 .map(|v| {
82 v.iter()
83 .map(|s| s.to_string())
84 .collect::<Vec<_>>()
85 .join(" ")
86 })
87 .unwrap_or_default()
88 } else {
89 String::new()
90 };
91
92 let usage = if value.is_empty() {
93 names_str
94 } else {
95 format!("{} {}", names_str, value)
96 };
97
98 let help = arg.get_help().map(|h| h.to_string()).unwrap_or_default();
99
100 lines.push(format!(" {} {}", usage, help));
101 }
102
103 lines.push("```".to_string());
104 lines.push(String::new());
105 lines.push(format!("For more information, use `sq {} --help`.", name));
106 lines.push(String::new());
107 }
108
109 lines.join("\n")
110}