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 <noreply@anthropic.com>
This commit is contained in:
argenis de la rosa 2026-02-15 06:52:33 -05:00
parent 9aaa5bfef1
commit 085b57aa30
7 changed files with 131 additions and 18 deletions

View file

@ -19,9 +19,9 @@ pub struct CronJob {
} }
#[allow(clippy::needless_pass_by_value)] #[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 { match command {
super::CronCommands::List => { crate::CronCommands::List => {
let jobs = list_jobs(config)?; let jobs = list_jobs(config)?;
if jobs.is_empty() { if jobs.is_empty() {
println!("No scheduled tasks yet."); println!("No scheduled tasks yet.");
@ -48,7 +48,7 @@ pub fn handle_command(command: super::CronCommands, config: &Config) -> Result<(
} }
Ok(()) Ok(())
} }
super::CronCommands::Add { crate::CronCommands::Add {
expression, expression,
command, command,
} => { } => {
@ -59,7 +59,7 @@ pub fn handle_command(command: super::CronCommands, config: &Config) -> Result<(
println!(" Cmd : {}", job.command); println!(" Cmd : {}", job.command);
Ok(()) Ok(())
} }
super::CronCommands::Remove { id } => remove_job(config, &id), crate::CronCommands::Remove { id } => remove_job(config, &id),
} }
} }

View file

@ -67,9 +67,9 @@ pub struct IntegrationEntry {
} }
/// Handle the `integrations` CLI command /// 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 { match command {
super::IntegrationCommands::Info { name } => show_integration_info(config, &name), crate::IntegrationCommands::Info { name } => show_integration_info(config, &name),
} }
} }

View file

@ -11,17 +11,129 @@
dead_code dead_code
)] )]
use clap::Subcommand;
use serde::{Deserialize, Serialize};
pub mod agent;
pub mod channels; pub mod channels;
pub mod config; pub mod config;
pub mod cron;
pub mod daemon;
pub mod doctor;
pub mod gateway; pub mod gateway;
pub mod health; pub mod health;
pub mod heartbeat; pub mod heartbeat;
pub mod integrations;
pub mod memory; pub mod memory;
pub mod migration;
pub mod observability; pub mod observability;
pub mod onboard;
pub mod providers; pub mod providers;
pub mod runtime; pub mod runtime;
pub mod security; pub mod security;
pub mod service;
pub mod skills; pub mod skills;
pub mod tools; pub mod tools;
pub mod tunnel; pub mod tunnel;
pub mod util; 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<std::path::PathBuf>,
/// 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,
},
}

View file

@ -34,6 +34,7 @@ mod service;
mod skills; mod skills;
mod tools; mod tools;
mod tunnel; mod tunnel;
mod util;
use config::Config; use config::Config;

View file

@ -23,9 +23,9 @@ struct MigrationStats {
renamed_conflicts: usize, 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 { match command {
super::MigrateCommands::Openclaw { source, dry_run } => { crate::MigrateCommands::Openclaw { source, dry_run } => {
migrate_openclaw_memory(config, source, dry_run).await migrate_openclaw_memory(config, source, dry_run).await
} }
} }

View file

@ -6,13 +6,13 @@ use std::process::Command;
const SERVICE_LABEL: &str = "com.zeroclaw.daemon"; 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 { match command {
super::ServiceCommands::Install => install(config), crate::ServiceCommands::Install => install(config),
super::ServiceCommands::Start => start(config), crate::ServiceCommands::Start => start(config),
super::ServiceCommands::Stop => stop(config), crate::ServiceCommands::Stop => stop(config),
super::ServiceCommands::Status => status(config), crate::ServiceCommands::Status => status(config),
super::ServiceCommands::Uninstall => uninstall(config), crate::ServiceCommands::Uninstall => uninstall(config),
} }
} }

View file

@ -453,9 +453,9 @@ fn copy_dir_recursive(src: &Path, dest: &Path) -> Result<()> {
/// Handle the `skills` CLI command /// Handle the `skills` CLI command
#[allow(clippy::too_many_lines)] #[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 { match command {
super::SkillCommands::List => { crate::SkillCommands::List => {
let skills = load_skills(workspace_dir); let skills = load_skills(workspace_dir);
if skills.is_empty() { if skills.is_empty() {
println!("No skills installed."); println!("No skills installed.");
@ -493,7 +493,7 @@ pub fn handle_command(command: super::SkillCommands, workspace_dir: &Path) -> Re
println!(); println!();
Ok(()) Ok(())
} }
super::SkillCommands::Install { source } => { crate::SkillCommands::Install { source } => {
println!("Installing skill from: {source}"); println!("Installing skill from: {source}");
let skills_path = skills_dir(workspace_dir); let skills_path = skills_dir(workspace_dir);
@ -584,7 +584,7 @@ pub fn handle_command(command: super::SkillCommands, workspace_dir: &Path) -> Re
Ok(()) Ok(())
} }
super::SkillCommands::Remove { name } => { crate::SkillCommands::Remove { name } => {
let skill_path = skills_dir(workspace_dir).join(&name); let skill_path = skills_dir(workspace_dir).join(&name);
if !skill_path.exists() { if !skill_path.exists() {
anyhow::bail!("Skill not found: {name}"); anyhow::bail!("Skill not found: {name}");