use std::path::PathBuf;
use thiserror::Error;
#[allow(dead_code)]
#[derive(Debug, Error)]
pub enum CliError {
#[error(".omne/ not found — not an omne volume")]
NotAVolume,
#[error(".omne/ already exists at {path}")]
VolumeAlreadyExists { path: PathBuf },
#[error("validation failed with {} issue(s)", issues.len())]
ValidationFailed { issues: Vec<String> },
#[error(transparent)]
Distro(#[from] crate::distro::Error),
#[error(transparent)]
Manifest(#[from] crate::manifest::Error),
#[error(transparent)]
Github(#[from] crate::github::Error),
#[error(transparent)]
Tarball(#[from] crate::tarball::Error),
#[error("tarball layout mismatch: expected '{expected}/' but found {found:?}")]
TarballLayoutMismatch {
expected: String,
found: Vec<String>,
},
#[error(transparent)]
Python(#[from] crate::python::Error),
#[error("unsafe target: {path} contains or is a symlink — refusing to remove")]
UnsafeTarget { path: PathBuf },
#[error(
"symlink privilege required on Windows\n\
\n\
Creating .claude/skills/ requires directory symlinks. Windows\n\
blocks this for non-elevated processes unless Developer Mode\n\
is enabled. Re-run `omne init` one of these ways:\n\
\n\
• Elevated PowerShell: right-click → Run as Administrator\n\
• Enable Developer Mode: Settings → Privacy & Security → For developers"
)]
SymlinkPrivilegeRequired,
#[error("{0}")]
Io(String),
}
impl From<std::io::Error> for CliError {
fn from(err: std::io::Error) -> Self {
CliError::Io(err.to_string())
}
}
impl CliError {
pub fn exit_code(&self) -> i32 {
match self {
CliError::NotAVolume
| CliError::VolumeAlreadyExists { .. }
| CliError::ValidationFailed { .. }
| CliError::Distro(_)
| CliError::Manifest(_)
| CliError::Github(_)
| CliError::Tarball(_)
| CliError::TarballLayoutMismatch { .. }
| CliError::Python(_)
| CliError::UnsafeTarget { .. }
| CliError::Io(_) => 1,
CliError::SymlinkPrivilegeRequired => 7,
}
}
}