aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-20 03:15:21 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-20 03:15:21 +0300
commitef0b4bc6e201c137b22da4604590d28ebae7c2bd (patch)
treede7f5d24e1025de72b8aa0284c485610015605c5 /src/platform
parent052f20214b1be904924df8d50d01e31198098922 (diff)
fix: support agent env hints
refs #679 related #699
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/linux.rs38
-rw-r--r--src/platform/mod.rs5
2 files changed, 43 insertions, 0 deletions
diff --git a/src/platform/linux.rs b/src/platform/linux.rs
index 9a44d02e..3cf643e5 100644
--- a/src/platform/linux.rs
+++ b/src/platform/linux.rs
@@ -124,6 +124,26 @@ pub fn process_cwd(pid: u32) -> Option<PathBuf> {
std::fs::read_link(format!("/proc/{pid}/cwd")).ok()
}
+/// Read a Herdr agent identity hint from a process environment.
+pub fn process_agent_hint(pid: u32) -> Option<crate::detect::Agent> {
+ if pid == 0 {
+ return None;
+ }
+ let environ = std::fs::read(format!("/proc/{pid}/environ")).ok()?;
+ parse_agent_env_hint(&environ)
+}
+
+fn parse_agent_env_hint(environ: &[u8]) -> Option<crate::detect::Agent> {
+ for record in environ.split(|&byte| byte == 0) {
+ let Some(value) = record.strip_prefix(b"HERDR_AGENT=") else {
+ continue;
+ };
+ let value = std::str::from_utf8(value).ok()?;
+ return crate::detect::parse_agent_label(value);
+ }
+ None
+}
+
pub fn session_processes(child_pid: u32) -> Vec<u32> {
let Some(session_id) = process_session_id(child_pid) else {
return Vec::new();
@@ -490,6 +510,24 @@ mod tests {
}
#[test]
+ fn parse_agent_env_hint_accepts_known_agents() {
+ assert_eq!(
+ parse_agent_env_hint(b"PATH=/bin\0HERDR_AGENT=claude\0TERM=xterm\0"),
+ Some(crate::detect::Agent::Claude)
+ );
+ assert_eq!(
+ parse_agent_env_hint(b"HERDR_AGENT=codex"),
+ Some(crate::detect::Agent::Codex)
+ );
+ }
+
+ #[test]
+ fn parse_agent_env_hint_ignores_missing_or_unknown_agents() {
+ assert_eq!(parse_agent_env_hint(b"PATH=/bin\0TERM=xterm\0"), None);
+ assert_eq!(parse_agent_env_hint(b"HERDR_AGENT=not-an-agent\0"), None);
+ }
+
+ #[test]
fn clipboard_commands_prefer_wayland_when_available() {
let _guard = env_lock().lock().unwrap();
unsafe {
diff --git a/src/platform/mod.rs b/src/platform/mod.rs
index ec9a497f..0b5f9ecb 100644
--- a/src/platform/mod.rs
+++ b/src/platform/mod.rs
@@ -121,6 +121,11 @@ mod fallback;
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
pub use fallback::*;
+#[cfg(not(target_os = "linux"))]
+pub fn process_agent_hint(_pid: u32) -> Option<crate::detect::Agent> {
+ None
+}
+
#[cfg(not(target_os = "macos"))]
#[derive(Debug)]
pub(crate) struct InputSourceRestore;