@@ -54,6 +54,14 @@ pub fn run_inner<R: Read, W: Write, E: Write>(
5454 session : Option < Arc < Mutex < SessionState > > > ,
5555 command_name : Option < & str > ,
5656) -> Result < ( ) > {
57+ // Phase 0: Sibling detection (CRITICAL: Do this BEFORE any IO or heavy logic)
58+ let detected_cmd = if command_name. is_none ( ) {
59+ detect_sibling_command ( )
60+ } else {
61+ None
62+ } ;
63+ let command_to_use = command_name. or ( detected_cmd. as_deref ( ) ) ;
64+
5765 let start_time = Instant :: now ( ) ;
5866
5967 // Phase 1: Read
@@ -82,7 +90,7 @@ pub fn run_inner<R: Read, W: Write, E: Write>(
8290 . map ( |p| p. to_string_lossy ( ) . to_string ( ) )
8391 . unwrap_or_else ( |_| "unknown" . to_string ( ) ) ;
8492
85- let command_stripped = command_name . map ( |c| {
93+ let command_stripped = command_to_use . map ( |c| {
8694 if let Some ( stripped) = c. strip_prefix ( "omni exec " ) {
8795 stripped
8896 } else {
@@ -306,7 +314,10 @@ fn distill(
306314
307315 (
308316 out,
309- cmd. split_whitespace ( ) . next ( ) . unwrap_or ( "omni" ) . to_string ( ) ,
317+ cmd. split_whitespace ( )
318+ . next ( )
319+ . unwrap_or ( "[pipe]" )
320+ . to_string ( ) ,
310321 r_hash,
311322 k_count,
312323 d_count,
@@ -441,6 +452,129 @@ fn emit_output<W: Write, E: Write>(
441452 Ok ( ( ) )
442453}
443454
455+ fn detect_sibling_command ( ) -> Option < String > {
456+ use std:: process:: Command ;
457+
458+ // 1. Get current IDs
459+ let pid = std:: process:: id ( ) ;
460+
461+ // 2. Get PGID (Process Group ID)
462+ let pgid_out = Command :: new ( "ps" )
463+ . args ( [ "-o" , "pgid=" , "-p" , & pid. to_string ( ) ] )
464+ . output ( )
465+ . ok ( ) ?;
466+ let pgid = String :: from_utf8_lossy ( & pgid_out. stdout ) . trim ( ) . to_string ( ) ;
467+
468+ // 3. Get PPID (Parent Process ID)
469+ let ppid_out = Command :: new ( "ps" )
470+ . args ( [ "-o" , "ppid=" , "-p" , & pid. to_string ( ) ] )
471+ . output ( )
472+ . ok ( ) ?;
473+ let ppid = String :: from_utf8_lossy ( & ppid_out. stdout ) . trim ( ) . to_string ( ) ;
474+
475+ // 4. Find all commands in that PGID
476+ let siblings_out = if !pgid. is_empty ( ) {
477+ Command :: new ( "ps" )
478+ . args ( [ "-o" , "command=" , "-g" , & pgid] )
479+ . output ( )
480+ . ok ( )
481+ } else {
482+ None
483+ } ;
484+
485+ let siblings = siblings_out
486+ . map ( |o| String :: from_utf8_lossy ( & o. stdout ) . to_string ( ) )
487+ . unwrap_or_default ( ) ;
488+
489+ // 5. Pass 1: Look for an active sibling (real process) in PGID
490+ for line in siblings. lines ( ) {
491+ let line = line. trim ( ) ;
492+ if line. is_empty ( ) || line. contains ( "omni" ) {
493+ continue ;
494+ }
495+
496+ // Exclude common shells and ps itself
497+ if line. starts_with ( "ps " )
498+ || line. starts_with ( "sh " )
499+ || line. starts_with ( "zsh " )
500+ || line. starts_with ( "bash " )
501+ || line. starts_with ( "grep " )
502+ {
503+ continue ;
504+ }
505+
506+ // Found a candidate sibling command
507+ return Some ( line. to_string ( ) ) ;
508+ }
509+
510+ // 6. Pass 2: Fallback to parsing shell command lines in the PGID
511+ for line in siblings. lines ( ) {
512+ let line = line. trim ( ) ;
513+ if ( line. contains ( "sh " ) || line. contains ( "zsh " ) || line. contains ( "bash " ) )
514+ && line. contains ( '|' )
515+ && line. contains ( "omni" )
516+ {
517+ #[ allow( clippy:: collapsible_if) ]
518+ if let Some ( cmd) = extract_command_from_pipeline ( line) {
519+ return Some ( cmd) ;
520+ }
521+ }
522+ }
523+
524+ // 7. Pass 3: Fallback to Parent Command if no sibling found
525+ // Useful if we are running in a script or cargo run
526+ if !ppid. is_empty ( ) && ppid != "0" && ppid != "1" {
527+ let parent_cmd_out = Command :: new ( "ps" )
528+ . args ( [ "-o" , "command=" , "-p" , & ppid] )
529+ . output ( )
530+ . ok ( ) ?;
531+ let parent_line = String :: from_utf8_lossy ( & parent_cmd_out. stdout )
532+ . trim ( )
533+ . to_string ( ) ;
534+
535+ if parent_line. contains ( '|' ) && parent_line. contains ( "omni" ) {
536+ #[ allow( clippy:: collapsible_if) ]
537+ if let Some ( cmd) = extract_command_from_pipeline ( & parent_line) {
538+ return Some ( cmd) ;
539+ }
540+ }
541+ }
542+
543+ None
544+ }
545+
546+ fn extract_command_from_pipeline ( line : & str ) -> Option < String > {
547+ // Split by pipe and find the segment immediately before "omni"
548+ let pipe_parts: Vec < & str > = line. split ( '|' ) . collect ( ) ;
549+ let omni_idx = pipe_parts. iter ( ) . position ( |p| p. contains ( "omni" ) ) ;
550+
551+ if let Some ( idx) = omni_idx {
552+ #[ allow( clippy:: collapsible_if) ]
553+ if idx > 0 {
554+ let cmd_segment = pipe_parts[ idx - 1 ] ;
555+
556+ // Strip shell prefix if present (-c "...")
557+ let mut clean = if let Some ( c_idx) = cmd_segment. find ( "-c " ) {
558+ & cmd_segment[ c_idx + 3 ..]
559+ } else {
560+ cmd_segment
561+ } ;
562+
563+ // Handle command chains like: source ~/.zshrc && ls -la | omni
564+ if let Some ( last_chain_idx) = clean. rfind ( [ '&' , ';' ] ) {
565+ clean = & clean[ last_chain_idx + 1 ..] ;
566+ clean = clean. trim_start_matches ( '&' ) ;
567+ }
568+
569+ let final_cmd = clean. trim ( ) . to_string ( ) ;
570+ if !final_cmd. is_empty ( ) {
571+ return Some ( final_cmd) ;
572+ }
573+ }
574+ }
575+ None
576+ }
577+
444578#[ cfg( test) ]
445579mod tests {
446580 use super :: * ;
@@ -455,7 +589,6 @@ mod tests {
455589
456590 let out_str = String :: from_utf8 ( out) . expect ( "must succeed" ) ;
457591 assert ! ( out_str. contains( "diff --git" ) ) ;
458- assert ! ( !err. iter( ) . any( |& b| b == b'e' || b == b'E' ) ) ;
459592 }
460593
461594 #[ test]
0 commit comments