use crate::error::{Error, Result};
#[derive(Debug, Clone)]
pub struct SpawnOpts {
pub session_id: String,
pub permission_mode: Option<String>,
pub dangerous: bool,
}
pub trait Backend {
fn name(&self) -> &'static str;
fn spawn_command(&self, opts: &SpawnOpts) -> String;
fn plan_markers(&self) -> &'static [&'static str];
fn permission_markers(&self) -> &'static [&'static str];
fn trust_markers(&self) -> &'static [&'static str];
}
pub const CLAUDE_PERMISSION_MODES: &[&str] =
&["plan", "acceptEdits", "auto", "bypassPermissions", "default", "dontAsk"];
pub struct Claude;
impl Backend for Claude {
fn name(&self) -> &'static str {
"claude"
}
fn spawn_command(&self, opts: &SpawnOpts) -> String {
let mut cmd = format!(
"env -u CLAUDECODE -u CLAUDE_CODE_ENTRYPOINT claude --session-id {}",
opts.session_id
);
if let Some(mode) = &opts.permission_mode {
cmd.push_str(" --permission-mode ");
cmd.push_str(mode);
}
if opts.dangerous {
cmd.push_str(" --dangerously-skip-permissions");
}
cmd
}
fn plan_markers(&self) -> &'static [&'static str] {
&["Here is Claude's plan", "Would you like to proceed?"]
}
fn permission_markers(&self) -> &'static [&'static str] {
&["Do you want to proceed?", "Do you want to make this edit?"]
}
fn trust_markers(&self) -> &'static [&'static str] {
&[
"Is this a project you created or one you trust?",
"Yes, I trust this folder",
]
}
}
pub fn resolve(name: &str) -> Result<Box<dyn Backend>> {
match name {
"claude" => Ok(Box::new(Claude)),
other => Err(Error::UnknownBackend(other.to_string())),
}
}