package cli import ( "flag" "fmt" "io" ) type cmdHelp struct { name string synopsis string summary string } // agentCmds emit machine-readable JSON; adminCmds are human-readable. var agentCmds = []cmdHelp{ {"list", "list --account [--folder F] [--new] [--limit N] [--before U] [--since U]", "List message headers, newest first."}, {"get", "get --account [--folder F] --uid ", "Fetch one full message (body + attachments)."}, {"search", "search --account [--folder F] [--from A] [--subject-contains S] [--text S] [--since-date D] [--before-date D] [--limit N]", "Server-side IMAP search."}, {"ack", "ack --account [--folder F] --uid-list U1,U2,…", "Mark message(s) processed."}, {"send", "send --account --to A… [--cc A…] [--bcc A…] --subject S --body B [--attach P]… [--reply-to U [--folder F]]", "Send or reply (RW accounts only)."}, } var adminCmds = []cmdHelp{ {"init", "init", "Create the database and add the first account (interactive)."}, {"account", "account [flags]", "Manage accounts (add/edit accept flags, or run with none for an interactive form)."}, {"whitelist", "whitelist --account [--address A]", "Manage inbound/outbound whitelists."}, {"config", "config [value]", "Get or set global settings (e.g. audit_retention_days)."}, {"audit", "audit list [--account ] [--limit N]", "Show recent audit-log entries."}, {"doctor", "doctor [--account ]", "Check each account's IMAP/SMTP connectivity and auth."}, {"version", "version", "Print the emcli version."}, {"help", "help [command]", "Show this help, or detailed usage for one command."}, } func helpIndex() map[string]cmdHelp { m := make(map[string]cmdHelp, len(agentCmds)+len(adminCmds)) for _, c := range append(append([]cmdHelp{}, agentCmds...), adminCmds...) { m[c.name] = c } return m } // helpRequested reports whether an argument is a help flag/word. func helpRequested(s string) bool { return s == "help" || s == "-h" || s == "--help" } // printMainHelp writes the top-level command catalogue. func printMainHelp(w io.Writer) { fmt.Fprint(w, "emcli — guard-railed email gateway for agents\n\n") fmt.Fprint(w, "Usage:\n emcli [flags]\n\n") fmt.Fprint(w, "Agent commands (machine-readable JSON on stdout):\n") for _, c := range agentCmds { fmt.Fprintf(w, " %-10s %s\n", c.name, c.summary) } fmt.Fprint(w, "\nAdmin commands (human-readable):\n") for _, c := range adminCmds { fmt.Fprintf(w, " %-10s %s\n", c.name, c.summary) } fmt.Fprint(w, "\nRun \"emcli --help\" for a command's flags.\n") fmt.Fprint(w, "\nEnvironment:\n") fmt.Fprint(w, " EMCLI_KEY base64-encoded 32-byte AES key; required for any command that uses the database\n") fmt.Fprint(w, " EMCLI_DB database path (default ~/.config/emcli/emcli.db; %AppData%\\emcli\\emcli.db on Windows)\n") } // printCmdUsage writes "Usage: emcli " and the summary for one command. func printCmdUsage(w io.Writer, name string) { if h, ok := helpIndex()[name]; ok { fmt.Fprintf(w, "Usage: emcli %s\n\n%s\n", h.synopsis, h.summary) return } fmt.Fprintf(w, "Usage: emcli %s\n", name) } // usageFlags makes a flag set print the command's synopsis/summary followed by // its flags whenever flag prints usage (on -h/--help or a flag error). func usageFlags(fs *flag.FlagSet, name string, w io.Writer) { fs.Usage = func() { printCmdUsage(w, name) fmt.Fprintln(w, "\nFlags:") fs.PrintDefaults() } }