#include "flag_spec.h" namespace detz::cli { namespace { FlagSpec sw(std::string name, std::string dest, std::string help = "") { FlagSpec f; f.names = {std::move(name)}; f.dest = std::move(dest); f.nargs = Nargs::Flag; f.help = std::move(help); return f; } FlagSpec val(std::string name, std::string dest, std::string metavar = "", std::string help = "") { FlagSpec f; f.names = {std::move(name)}; f.dest = std::move(dest); f.nargs = Nargs::One; f.metavar = std::move(metavar); f.help = std::move(help); return f; } std::vector build() { std::vector t; FlagSpec h; h.names = {"-h", "--help"}; h.dest = "help"; h.nargs = Nargs::Help; h.help = "show this help message and exit"; t.push_back(h); t.push_back(val("--profile", "profile")); t.push_back(sw("--yes", "yes")); t.push_back(sw("--yolo", "yolo")); t.push_back(sw("--auto", "auto")); t.push_back(sw("--continue", "resume")); FlagSpec dbg = val("--debug", "debug", "SINK", "extensive debug logging to /debug.log (file), stdout, or stderr, plus the vault logs table (see logging.md)"); dbg.nargs = Nargs::Optional; dbg.constant = "file"; dbg.choices = {"file", "stdout", "stderr"}; t.push_back(dbg); FlagSpec df = val("--debug-format", "debug_format", "FORMAT", "debug log line format, sentence or json (default sentence, or TAI_DEBUG_FORMAT)"); df.choices = {"sentence", "json"}; t.push_back(df); t.push_back(val("--env", "env")); t.push_back(sw("--no-opencode", "no_opencode", "skip the opencode CLI backends for this run (same as TAI_OPENCODE=0)")); t.push_back(sw("--update-models", "update_models", "rediscover the free model lists of every provider, drop models that are gone, and exit")); t.push_back(sw("--eval-retrieval", "eval_retrieval", "score vault retrieval (Hit@K, MRR, nDCG, Context Precision) on generated goldens plus implicit pairs, print the report, and exit")); t.push_back(sw("--stats-rag", "stats_rag", "print RAG usage and effectiveness stats (vault totals, searches, reads, per-record context uses, retrieval eval) and exit")); t.push_back(sw("--version", "version")); t.push_back(sw("--cap-manifest", "cap_manifest", "print tai's CAP agent manifest (cap-agent.toml) and exit")); t.push_back(sw("--cap-speak", "cap_speak", "speak CAP stream-json on stdio as an agent (bulk session config via CAP_SESSION_CONFIG)")); t.push_back(val("--cap-cwd", "cap_cwd", "DIR", "speak session working directory (overrides CAP_SESSION_CONFIG cwd)")); t.push_back(val("--cap-model", "cap_model", "MODEL", "speak session model label (overrides CAP_SESSION_CONFIG model)")); FlagSpec pm = val("--cap-permission-mode", "cap_permission_mode", "", "speak session permission mode (overrides CAP_SESSION_CONFIG permission_mode)"); pm.choices = {"none", "confirm", "interactive"}; t.push_back(pm); FlagSpec mt = val("--cap-max-turns", "cap_max_turns", "N", "speak session turn cap (overrides CAP_SESSION_CONFIG max_turns)"); mt.integer = true; t.push_back(mt); FlagSpec cap = val("--cap", "cap", "COMMAND", "orchestrator: resolve, chat or run fleet commands (see cap.md)"); cap.nargs = Nargs::Remainder; t.push_back(cap); t.push_back(val("--serve-mcp", "serve_mcp", "KEY", "serve MCP over HTTP (Streamable HTTP): all native tools plus chat/completions, Bearer KEY required (see mcp.md)")); FlagSpec port = val("--mcp-port", "mcp_port", "PORT", "serve-mcp port (default TAI_MCP_PORT else 8765)"); port.integer = true; t.push_back(port); t.push_back(val("--mcp-bind", "mcp_bind", "HOST", "serve-mcp bind address (default TAI_MCP_BIND else 127.0.0.1)")); t.push_back(sw("--telegram", "telegram")); t.push_back(sw("--scheduler", "scheduler")); t.push_back(sw("--install", "install")); t.push_back(sw("--install-telegram", "install_telegram")); t.push_back(sw("--uninstall-telegram", "uninstall_telegram")); t.push_back(sw("--plexer-wrap", "plexer_wrap", "internal: invoked by the bashrc plexer hook, not meant to be run by hand")); FlagSpec mp = val("--mplex", "mplex", "COMMAND", "terminal multiplexer: any mplex command (new-session, attach-session, list-keys ...); bare --mplex starts a session. Config: ~/.tai/mplex.toml"); mp.nargs = Nargs::Remainder; t.push_back(mp); t.push_back(sw("--demo", "demo", "run the fullscreen TUI framework showcase")); t.push_back(sw("--demo-shot", "demo_shot", "print one composed demo frame as text and exit")); t.push_back(sw("--tui", "tui", "run the fullscreen grr client (bots, chats, automations, library, projects, settings) against the grr server; address in GRR_URL")); t.push_back(sw("--tui-local", "tui_local", "run the fullscreen Telegram-style chat UI on the local vault, no server needed")); t.push_back(val("--theme", "theme", "NAME", "TUI theme: dark, light, nord, gruvbox, ansi (or TAI_THEME)")); FlagSpec pr; pr.dest = "prompt"; pr.nargs = Nargs::Star; t.push_back(pr); return t; } } // namespace const std::vector& FlagTable::all() { static const std::vector table = build(); return table; } const FlagSpec* FlagTable::find(const std::string& dest) { for (const auto& f : all()) if (f.dest == dest) return &f; return nullptr; } } // namespace detz::cli