mod flags;
mod helpers;
mod install;
mod state;
mod uninstall;
use std::io::IsTerminal;
use std::process::ExitCode;
use flags::parse_flags;
use helpers::print_help;
use install::run_install;
use uninstall::run_uninstall;
pub(crate) use helpers::resolve_config_dir_for_agent;
pub(crate) use state::has_skim_hook_entry;
pub(crate) use state::MAX_SETTINGS_SIZE;
pub(crate) fn run(args: &[String]) -> anyhow::Result<ExitCode> {
if !cfg!(unix) {
anyhow::bail!(
"skim init is only supported on Unix systems (macOS, Linux)\n\
Windows support is planned for a future release."
);
}
if args.iter().any(|a| matches!(a.as_str(), "--help" | "-h")) {
print_help();
return Ok(ExitCode::SUCCESS);
}
let flags = parse_flags(args)?;
if !flags.yes && !std::io::stdin().is_terminal() {
eprintln!("error: skim init requires an interactive terminal");
eprintln!("hint: use --yes for non-interactive mode (e.g., CI)");
return Ok(ExitCode::FAILURE);
}
if flags.uninstall {
return run_uninstall(&flags);
}
run_install(&flags)
}
pub(super) fn command() -> clap::Command {
clap::Command::new("init")
.about("Install skim as an agent hook")
.arg(
clap::Arg::new("global")
.long("global")
.action(clap::ArgAction::SetTrue)
.help("Install to user-level config directory (default)"),
)
.arg(
clap::Arg::new("project")
.long("project")
.action(clap::ArgAction::SetTrue)
.help("Install to project-level config directory"),
)
.arg(
clap::Arg::new("agent")
.long("agent")
.value_name("NAME")
.help("Target agent (default: claude-code)"),
)
.arg(
clap::Arg::new("yes")
.long("yes")
.short('y')
.action(clap::ArgAction::SetTrue)
.help("Non-interactive mode (skip prompts)"),
)
.arg(
clap::Arg::new("dry-run")
.long("dry-run")
.action(clap::ArgAction::SetTrue)
.help("Print actions without writing"),
)
.arg(
clap::Arg::new("uninstall")
.long("uninstall")
.action(clap::ArgAction::SetTrue)
.help("Remove hook and clean up"),
)
.arg(
clap::Arg::new("no-guidance")
.long("no-guidance")
.action(clap::ArgAction::SetTrue)
.help("Skip injecting guidance into agent instruction file"),
)
.arg(
clap::Arg::new("force")
.long("force")
.action(clap::ArgAction::SetTrue)
.help("Force operation (e.g., uninstall tampered hook)"),
)
}