From 085b57aa3062bf16eac3202458a267543281fecf Mon Sep 17 00:00:00 2001 From: argenis de la rosa Date: Sun, 15 Feb 2026 06:52:33 -0500 Subject: [PATCH] refactor: consolidate CLI command definitions to lib.rs - Move all CLI command enums (ChannelCommands, SkillCommands, CronCommands, IntegrationCommands, MigrateCommands, ServiceCommands) to lib.rs - Add clap derives for use in main.rs CLI parsing - Update all modules to use crate:: prefix instead of super:: for command types - Add mod util; to main.rs for binary compilation - Export Config type from lib.rs for main.rs This refactoring eliminates code duplication between library modules and binary, centralizing all CLI command definitions in one place. Co-Authored-By: Claude Opus 4.6 --- src/cron/mod.rs | 8 +-- src/integrations/mod.rs | 4 +- src/lib.rs | 112 ++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/migration.rs | 4 +- src/service/mod.rs | 12 ++--- src/skills/mod.rs | 8 +-- 7 files changed, 131 insertions(+), 18 deletions(-) diff --git a/src/cron/mod.rs b/src/cron/mod.rs index 9866ec5..322f268 100644 --- a/src/cron/mod.rs +++ b/src/cron/mod.rs @@ -19,9 +19,9 @@ pub struct CronJob { } #[allow(clippy::needless_pass_by_value)] -pub fn handle_command(command: super::CronCommands, config: &Config) -> Result<()> { +pub fn handle_command(command: crate::CronCommands, config: &Config) -> Result<()> { match command { - super::CronCommands::List => { + crate::CronCommands::List => { let jobs = list_jobs(config)?; if jobs.is_empty() { println!("No scheduled tasks yet."); @@ -48,7 +48,7 @@ pub fn handle_command(command: super::CronCommands, config: &Config) -> Result<( } Ok(()) } - super::CronCommands::Add { + crate::CronCommands::Add { expression, command, } => { @@ -59,7 +59,7 @@ pub fn handle_command(command: super::CronCommands, config: &Config) -> Result<( println!(" Cmd : {}", job.command); Ok(()) } - super::CronCommands::Remove { id } => remove_job(config, &id), + crate::CronCommands::Remove { id } => remove_job(config, &id), } } diff --git a/src/integrations/mod.rs b/src/integrations/mod.rs index 8b2b126..d96d668 100644 --- a/src/integrations/mod.rs +++ b/src/integrations/mod.rs @@ -67,9 +67,9 @@ pub struct IntegrationEntry { } /// Handle the `integrations` CLI command -pub fn handle_command(command: super::IntegrationCommands, config: &Config) -> Result<()> { +pub fn handle_command(command: crate::IntegrationCommands, config: &Config) -> Result<()> { match command { - super::IntegrationCommands::Info { name } => show_integration_info(config, &name), + crate::IntegrationCommands::Info { name } => show_integration_info(config, &name), } } diff --git a/src/lib.rs b/src/lib.rs index 8520a2b..1eea5d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,17 +11,129 @@ dead_code )] +use clap::Subcommand; +use serde::{Deserialize, Serialize}; + +pub mod agent; pub mod channels; pub mod config; +pub mod cron; +pub mod daemon; +pub mod doctor; pub mod gateway; pub mod health; pub mod heartbeat; +pub mod integrations; pub mod memory; +pub mod migration; pub mod observability; +pub mod onboard; pub mod providers; pub mod runtime; pub mod security; +pub mod service; pub mod skills; pub mod tools; pub mod tunnel; pub mod util; + +pub use config::Config; + +/// Service management subcommands +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum ServiceCommands { + /// Install daemon service unit for auto-start and restart + Install, + /// Start daemon service + Start, + /// Stop daemon service + Stop, + /// Check daemon service status + Status, + /// Uninstall daemon service unit + Uninstall, +} + +/// Channel management subcommands +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum ChannelCommands { + /// List all configured channels + List, + /// Start all configured channels (handled in main.rs for async) + Start, + /// Run health checks for configured channels (handled in main.rs for async) + Doctor, + /// Add a new channel configuration + Add { + /// Channel type (telegram, discord, slack, whatsapp, matrix, imessage, email) + channel_type: String, + /// Optional configuration as JSON + config: String, + }, + /// Remove a channel configuration + Remove { + /// Channel name to remove + name: String, + }, +} + +/// Skills management subcommands +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum SkillCommands { + /// List all installed skills + List, + /// Install a new skill from a URL or local path + Install { + /// Source URL or local path + source: String, + }, + /// Remove an installed skill + Remove { + /// Skill name to remove + name: String, + }, +} + +/// Migration subcommands +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum MigrateCommands { + /// Import memory from an `OpenClaw` workspace into this `ZeroClaw` workspace + Openclaw { + /// Optional path to `OpenClaw` workspace (defaults to ~/.openclaw/workspace) + #[arg(long)] + source: Option, + + /// Validate and preview migration without writing any data + #[arg(long)] + dry_run: bool, + }, +} + +/// Cron subcommands +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum CronCommands { + /// List all scheduled tasks + List, + /// Add a new scheduled task + Add { + /// Cron expression + expression: String, + /// Command to run + command: String, + }, + /// Remove a scheduled task + Remove { + /// Task ID + id: String, + }, +} + +/// Integration subcommands +#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum IntegrationCommands { + /// Show details about a specific integration + Info { + /// Integration name + name: String, + }, +} diff --git a/src/main.rs b/src/main.rs index 4d07ad2..7fa11b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,7 @@ mod service; mod skills; mod tools; mod tunnel; +mod util; use config::Config; diff --git a/src/migration.rs b/src/migration.rs index 2ce29ba..04fa458 100644 --- a/src/migration.rs +++ b/src/migration.rs @@ -23,9 +23,9 @@ struct MigrationStats { renamed_conflicts: usize, } -pub async fn handle_command(command: super::MigrateCommands, config: &Config) -> Result<()> { +pub async fn handle_command(command: crate::MigrateCommands, config: &Config) -> Result<()> { match command { - super::MigrateCommands::Openclaw { source, dry_run } => { + crate::MigrateCommands::Openclaw { source, dry_run } => { migrate_openclaw_memory(config, source, dry_run).await } } diff --git a/src/service/mod.rs b/src/service/mod.rs index eb933ad..9cee13c 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -6,13 +6,13 @@ use std::process::Command; const SERVICE_LABEL: &str = "com.zeroclaw.daemon"; -pub fn handle_command(command: &super::ServiceCommands, config: &Config) -> Result<()> { +pub fn handle_command(command: &crate::ServiceCommands, config: &Config) -> Result<()> { match command { - super::ServiceCommands::Install => install(config), - super::ServiceCommands::Start => start(config), - super::ServiceCommands::Stop => stop(config), - super::ServiceCommands::Status => status(config), - super::ServiceCommands::Uninstall => uninstall(config), + crate::ServiceCommands::Install => install(config), + crate::ServiceCommands::Start => start(config), + crate::ServiceCommands::Stop => stop(config), + crate::ServiceCommands::Status => status(config), + crate::ServiceCommands::Uninstall => uninstall(config), } } diff --git a/src/skills/mod.rs b/src/skills/mod.rs index 6bf43f0..56c5f84 100644 --- a/src/skills/mod.rs +++ b/src/skills/mod.rs @@ -453,9 +453,9 @@ fn copy_dir_recursive(src: &Path, dest: &Path) -> Result<()> { /// Handle the `skills` CLI command #[allow(clippy::too_many_lines)] -pub fn handle_command(command: super::SkillCommands, workspace_dir: &Path) -> Result<()> { +pub fn handle_command(command: crate::SkillCommands, workspace_dir: &Path) -> Result<()> { match command { - super::SkillCommands::List => { + crate::SkillCommands::List => { let skills = load_skills(workspace_dir); if skills.is_empty() { println!("No skills installed."); @@ -493,7 +493,7 @@ pub fn handle_command(command: super::SkillCommands, workspace_dir: &Path) -> Re println!(); Ok(()) } - super::SkillCommands::Install { source } => { + crate::SkillCommands::Install { source } => { println!("Installing skill from: {source}"); let skills_path = skills_dir(workspace_dir); @@ -584,7 +584,7 @@ pub fn handle_command(command: super::SkillCommands, workspace_dir: &Path) -> Re Ok(()) } - super::SkillCommands::Remove { name } => { + crate::SkillCommands::Remove { name } => { let skill_path = skills_dir(workspace_dir).join(&name); if !skill_path.exists() { anyhow::bail!("Skill not found: {name}");