1#![warn(clippy::all, clippy::pedantic)]
2#![allow(
3 clippy::assigning_clones,
4 clippy::bool_to_int_with_if,
5 clippy::case_sensitive_file_extension_comparisons,
6 clippy::cast_possible_wrap,
7 clippy::doc_markdown,
8 clippy::field_reassign_with_default,
9 clippy::float_cmp,
10 clippy::implicit_clone,
11 clippy::items_after_statements,
12 clippy::map_unwrap_or,
13 clippy::manual_let_else,
14 clippy::missing_errors_doc,
15 clippy::missing_panics_doc,
16 clippy::module_name_repetitions,
17 clippy::must_use_candidate,
18 clippy::new_without_default,
19 clippy::needless_pass_by_value,
20 clippy::needless_raw_string_hashes,
21 clippy::redundant_closure_for_method_calls,
22 clippy::return_self_not_must_use,
23 clippy::similar_names,
24 clippy::single_match_else,
25 clippy::struct_field_names,
26 clippy::too_many_lines,
27 clippy::uninlined_format_args,
28 clippy::unnecessary_cast,
29 clippy::unnecessary_lazy_evaluations,
30 clippy::unnecessary_literal_bound,
31 clippy::unnecessary_map_or,
32 clippy::unused_self,
33 clippy::cast_precision_loss,
34 clippy::unnecessary_wraps,
35 dead_code
36)]
37
38use clap::Subcommand;
39use serde::{Deserialize, Serialize};
40
41pub mod agent;
42pub(crate) mod approval;
43pub(crate) mod auth;
44pub mod channels;
45pub mod config;
46pub(crate) mod cost;
47pub(crate) mod cron;
48pub(crate) mod daemon;
49pub(crate) mod doctor;
50pub mod gateway;
51pub(crate) mod hardware;
52pub(crate) mod health;
53pub(crate) mod heartbeat;
54pub mod hooks;
55pub(crate) mod identity;
56pub(crate) mod integrations;
57pub mod memory;
58pub(crate) mod migration;
59pub(crate) mod multimodal;
60pub mod observability;
61pub(crate) mod onboard;
62pub mod peripherals;
63pub mod providers;
64pub mod rag;
65pub mod runtime;
66pub(crate) mod security;
67pub(crate) mod service;
68pub(crate) mod skills;
69pub mod tools;
70pub(crate) mod tunnel;
71pub(crate) mod util;
72
73pub use config::Config;
74
75#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
77pub enum ServiceCommands {
78 Install,
80 Start,
82 Stop,
84 Restart,
86 Status,
88 Uninstall,
90}
91
92#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
94pub enum ChannelCommands {
95 List,
97 Start,
99 Doctor,
101 #[command(long_about = "\
103Add a new channel configuration.
104
105Provide the channel type and a JSON object with the required \
106configuration keys for that channel type.
107
108Supported types: telegram, discord, slack, whatsapp, matrix, imessage, email.
109
110Examples:
111 zeroclaw channel add telegram '{\"bot_token\":\"...\",\"name\":\"my-bot\"}'
112 zeroclaw channel add discord '{\"bot_token\":\"...\",\"name\":\"my-discord\"}'")]
113 Add {
114 channel_type: String,
116 config: String,
118 },
119 Remove {
121 name: String,
123 },
124 #[command(long_about = "\
126Bind a Telegram identity into the allowlist.
127
128Adds a Telegram username (without the '@' prefix) or numeric user \
129ID to the channel allowlist so the agent will respond to messages \
130from that identity.
131
132Examples:
133 zeroclaw channel bind-telegram zeroclaw_user
134 zeroclaw channel bind-telegram 123456789")]
135 BindTelegram {
136 identity: String,
138 },
139}
140
141#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
143pub enum SkillCommands {
144 List,
146 Audit {
148 source: String,
150 },
151 Install {
153 source: String,
155 },
156 Remove {
158 name: String,
160 },
161}
162
163#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
165pub enum MigrateCommands {
166 Openclaw {
168 #[arg(long)]
170 source: Option<std::path::PathBuf>,
171
172 #[arg(long)]
174 dry_run: bool,
175 },
176}
177
178#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
180pub enum CronCommands {
181 List,
183 #[command(long_about = "\
185Add a new recurring scheduled task.
186
187Uses standard 5-field cron syntax: 'min hour day month weekday'. \
188Times are evaluated in UTC by default; use --tz with an IANA \
189timezone name to override.
190
191Examples:
192 zeroclaw cron add '0 9 * * 1-5' 'Good morning' --tz America/New_York
193 zeroclaw cron add '*/30 * * * *' 'Check system health'")]
194 Add {
195 expression: String,
197 #[arg(long)]
199 tz: Option<String>,
200 command: String,
202 },
203 #[command(long_about = "\
205Add a one-shot task that fires at a specific UTC timestamp.
206
207The timestamp must be in RFC 3339 format (e.g. 2025-01-15T14:00:00Z).
208
209Examples:
210 zeroclaw cron add-at 2025-01-15T14:00:00Z 'Send reminder'
211 zeroclaw cron add-at 2025-12-31T23:59:00Z 'Happy New Year!'")]
212 AddAt {
213 at: String,
215 command: String,
217 },
218 #[command(long_about = "\
220Add a task that repeats at a fixed interval.
221
222Interval is specified in milliseconds. For example, 60000 = 1 minute.
223
224Examples:
225 zeroclaw cron add-every 60000 'Ping heartbeat' # every minute
226 zeroclaw cron add-every 3600000 'Hourly report' # every hour")]
227 AddEvery {
228 every_ms: u64,
230 command: String,
232 },
233 #[command(long_about = "\
235Add a one-shot task that fires after a delay from now.
236
237Accepts human-readable durations: s (seconds), m (minutes), \
238h (hours), d (days).
239
240Examples:
241 zeroclaw cron once 30m 'Run backup in 30 minutes'
242 zeroclaw cron once 2h 'Follow up on deployment'
243 zeroclaw cron once 1d 'Daily check'")]
244 Once {
245 delay: String,
247 command: String,
249 },
250 Remove {
252 id: String,
254 },
255 #[command(long_about = "\
257Update one or more fields of an existing scheduled task.
258
259Only the fields you specify are changed; others remain unchanged.
260
261Examples:
262 zeroclaw cron update <task-id> --expression '0 8 * * *'
263 zeroclaw cron update <task-id> --tz Europe/London --name 'Morning check'
264 zeroclaw cron update <task-id> --command 'Updated message'")]
265 Update {
266 id: String,
268 #[arg(long)]
270 expression: Option<String>,
271 #[arg(long)]
273 tz: Option<String>,
274 #[arg(long)]
276 command: Option<String>,
277 #[arg(long)]
279 name: Option<String>,
280 },
281 Pause {
283 id: String,
285 },
286 Resume {
288 id: String,
290 },
291}
292
293#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
295pub enum MemoryCommands {
296 List {
298 #[arg(long)]
300 category: Option<String>,
301 #[arg(long)]
303 session: Option<String>,
304 #[arg(long, default_value = "50")]
306 limit: usize,
307 #[arg(long, default_value = "0")]
309 offset: usize,
310 },
311 Get {
313 key: String,
315 },
316 Stats,
318 Clear {
320 #[arg(long)]
322 key: Option<String>,
323 #[arg(long)]
325 category: Option<String>,
326 #[arg(long)]
328 yes: bool,
329 },
330}
331
332#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
334pub enum IntegrationCommands {
335 Info {
337 name: String,
339 },
340}
341
342#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
344pub enum HardwareCommands {
345 #[command(long_about = "\
347Enumerate USB devices and show known boards.
348
349Scans connected USB devices by VID/PID and matches them against \
350known development boards (STM32 Nucleo, Arduino, ESP32).
351
352Examples:
353 zeroclaw hardware discover")]
354 Discover,
355 #[command(long_about = "\
357Introspect a device by its serial or device path.
358
359Opens the specified device path and queries for board information, \
360firmware version, and supported capabilities.
361
362Examples:
363 zeroclaw hardware introspect /dev/ttyACM0
364 zeroclaw hardware introspect COM3")]
365 Introspect {
366 path: String,
368 },
369 #[command(long_about = "\
371Get chip info via USB using probe-rs over ST-Link.
372
373Queries the target MCU directly through the debug probe without \
374requiring any firmware on the target board.
375
376Examples:
377 zeroclaw hardware info
378 zeroclaw hardware info --chip STM32F401RETx")]
379 Info {
380 #[arg(long, default_value = "STM32F401RETx")]
382 chip: String,
383 },
384}
385
386#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
388pub enum PeripheralCommands {
389 List,
391 #[command(long_about = "\
393Add a peripheral by board type and transport path.
394
395Registers a hardware board so the agent can use its tools (GPIO, \
396sensors, actuators). Use 'native' as path for local GPIO on \
397single-board computers like Raspberry Pi.
398
399Supported boards: nucleo-f401re, rpi-gpio, esp32, arduino-uno.
400
401Examples:
402 zeroclaw peripheral add nucleo-f401re /dev/ttyACM0
403 zeroclaw peripheral add rpi-gpio native
404 zeroclaw peripheral add esp32 /dev/ttyUSB0")]
405 Add {
406 board: String,
408 path: String,
410 },
411 #[command(long_about = "\
413Flash ZeroClaw firmware to an Arduino board.
414
415Generates the .ino sketch, installs arduino-cli if it is not \
416already available, compiles, and uploads the firmware.
417
418Examples:
419 zeroclaw peripheral flash
420 zeroclaw peripheral flash --port /dev/cu.usbmodem12345
421 zeroclaw peripheral flash -p COM3")]
422 Flash {
423 #[arg(short, long)]
425 port: Option<String>,
426 },
427 SetupUnoQ {
429 #[arg(long)]
431 host: Option<String>,
432 },
433 FlashNucleo,
435}