Commit 6c80ae694b
6c80ae694b0e32803e461450f1f17a51a956b393
parent: 85bcef154b
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-04 14:43 UTC
Give signald and terminal-garden --help and --version
signald had no --help. Because any unrecognised argument became a repository
path, `signald --help` started the daemon watching a directory named --help
rather than printing anything. An unknown option now prints usage and exits 2.
terminal-garden gains the same two flags.
Found while writing the Homebrew formula: `brew test` runs the test block, and
a test invoking `signald --help` would have started a daemon and hung.
Ref #5
crates/signald/src/main.rs
+34
| @@ -25,6 +25,7 @@ |
| 25 | 25 | //! signald [--socket <path>] [--db <path>] [--spool <path>] |
| 26 | 26 | //! [--collector <path>] [--interval-ms <n>] [--retention-days <n>] |
| 27 | 27 | //! [<repo-path> ...] |
| 28 | //! signald --help | --version |
| 28 | 29 | //! ``` |
| 29 | 30 | //! With no repo paths, `$XDG_CONFIG_HOME/signald/repos` (else |
| 30 | 31 | //! `~/.config/signald/repos`) is read — one path per line, `#` comments |
| @@ -116,6 +117,24 @@ fn main() { |
| 116 | 117 | } |
| 117 | 118 | } |
| 118 | 119 | |
| 120 | const USAGE: &str = "\ |
| 121 | Usage: signald [options] [<repo-path> ...] |
| 122 | |
| 123 | --socket <path> listen here (default $XDG_RUNTIME_DIR/signald.sock, |
| 124 | else ~/.local/state/signald/sock) |
| 125 | --db <path> sqlite history (default: beside the socket) |
| 126 | --spool <path> terminal spool (default: beside the socket) |
| 127 | --collector <path> macos-collector binary (default: found on PATH) |
| 128 | --interval-ms <n> collector tick (default 2000) |
| 129 | --retention-days <n> history retention (default 7) |
| 130 | -h, --help print this and exit |
| 131 | -V, --version print the version and exit |
| 132 | |
| 133 | With no <repo-path>, $XDG_CONFIG_HOME/signald/repos (else |
| 134 | ~/.config/signald/repos) is read, one path per line, # comments ignored. |
| 135 | Failing that, the working directory is watched. |
| 136 | "; |
| 137 | |
| 119 | 138 | fn parse_args() -> Config { |
| 120 | 139 | let mut socket: Option<PathBuf> = None; |
| 121 | 140 | let mut db: Option<PathBuf> = None; |
| @@ -138,6 +157,21 @@ fn parse_args() -> Config { |
| 138 | 157 | "--retention-days" => { |
| 139 | 158 | retention_days = args.next().and_then(|s| s.parse().ok()).unwrap_or(retention_days) |
| 140 | 159 | } |
| 160 | "--help" | "-h" => { |
| 161 | print!("{USAGE}"); |
| 162 | std::process::exit(0); |
| 163 | } |
| 164 | "--version" | "-V" => { |
| 165 | println!("signald {}", env!("CARGO_PKG_VERSION")); |
| 166 | std::process::exit(0); |
| 167 | } |
| 168 | // Without this an unknown flag becomes a repository path and the |
| 169 | // daemon starts anyway, watching a directory that does not exist. |
| 170 | _ if arg.starts_with('-') => { |
| 171 | eprintln!("signald: unknown option {arg}\n"); |
| 172 | eprint!("{USAGE}"); |
| 173 | std::process::exit(2); |
| 174 | } |
| 141 | 175 | _ => repos.push(PathBuf::from(arg)), |
| 142 | 176 | } |
| 143 | 177 | } |
crates/terminal-garden/src/main.rs
+21
| @@ -13,6 +13,7 @@ |
| 13 | 13 | //! Usage: |
| 14 | 14 | //! ```text |
| 15 | 15 | //! terminal-garden [--socket <path>] |
| 16 | //! terminal-garden --help | --version |
| 16 | 17 | //! ``` |
| 17 | 18 | //! Socket defaults to `$XDG_RUNTIME_DIR/signald.sock`, falling back to |
| 18 | 19 | //! `~/.local/state/signald/sock`. |
| @@ -76,9 +77,29 @@ fn run(socket: &PathBuf) -> std::io::Result<()> { |
| 76 | 77 | Ok(()) |
| 77 | 78 | } |
| 78 | 79 | |
| 80 | const USAGE: &str = "\ |
| 81 | Usage: terminal-garden [--socket <path>] |
| 82 | |
| 83 | --socket <path> signald's socket (default $XDG_RUNTIME_DIR/signald.sock, |
| 84 | else ~/.local/state/signald/sock) |
| 85 | -h, --help print this and exit |
| 86 | -V, --version print the version and exit |
| 87 | "; |
| 88 | |
| 79 | 89 | fn parse_socket() -> PathBuf { |
| 80 | 90 | let mut args = std::env::args().skip(1); |
| 81 | 91 | while let Some(arg) = args.next() { |
| 92 | match arg.as_str() { |
| 93 | "--help" | "-h" => { |
| 94 | print!("{USAGE}"); |
| 95 | std::process::exit(0); |
| 96 | } |
| 97 | "--version" | "-V" => { |
| 98 | println!("terminal-garden {}", env!("CARGO_PKG_VERSION")); |
| 99 | std::process::exit(0); |
| 100 | } |
| 101 | _ => {} |
| 102 | } |
| 82 | 103 | if arg == "--socket" { |
| 83 | 104 | if let Some(path) = args.next() { |
| 84 | 105 | return PathBuf::from(path); |