{"record":{"id":"079707ca3ca10ac3","repo":"Hmbown/CodeWhale","slug":"message-shell","errorCode":null,"errorMessage":"{message}","messagePattern":"\\{message\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/shell.rs","lineNumber":2233,"sourceCode":"    pub fn execute_interactive_with_policy_env(\n        &mut self,\n        command: &str,\n        working_dir: Option<&str>,\n        timeout_ms: u64,\n        policy_override: Option<ExecutionSandboxPolicy>,\n        extra_env: HashMap<String, String>,\n    ) -> Result<ShellResult> {\n        crate::shell_dispatcher::ShellDispatcher::log_exec(command);\n\n        // A new Unix process group that inherits the terminal is not its\n        // foreground owner. Letting it read stdin triggers SIGTTIN; sharing\n        // Codewhale's group instead would make cooked-mode Ctrl+C terminate\n        // both parent and child. Until this path owns a complete POSIX job-\n        // control lease, fail closed before spawning. Persistent PTY tools\n        // already provide a safe interactive lane without taking over the\n        // operator's live terminal.\n        if let Some(message) = inherited_interactive_terminal_refusal() {\n            return Err(anyhow!(message));\n        }\n\n        let work_dir = working_dir.map_or_else(|| self.default_workspace.clone(), PathBuf::from);\n        validate_shell_working_dir(&work_dir, working_dir.is_none())?;\n\n        let timeout_ms = timeout_ms.clamp(1000, 600_000);\n        let policy = policy_override.unwrap_or_else(|| self.sandbox_policy.clone());\n\n        let spec = CommandSpec::shell(command, work_dir.clone(), Duration::from_millis(timeout_ms))\n            .with_policy(policy)\n            .with_env(extra_env);\n        let exec_env = self.sandbox_manager.prepare(&spec);\n\n        Self::execute_interactive_sandboxed(command, &work_dir, timeout_ms, &exec_env)\n    }\n\n    /// Execute command synchronously with timeout (sandboxed).\n    fn execute_sync_sandboxed(","sourceCodeStart":2215,"sourceCodeEnd":2251,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/shell.rs#L2215-L2251","documentation":"This refusal is raised before spawning any process when the tool detects that the command would inherit the agent's own interactive terminal and take over its foreground TTY. On Unix, foreground process-group ownership cannot be transferred safely from the running TUI (cooked-mode Ctrl+C would terminate both parent and child), so the tool fails closed rather than spawning. The concrete message is produced by `inherited_interactive_terminal_refusal()` and explains the supported alternatives.","triggerScenarios":"Calling the shell tool with `interactive: true` on Unix, so the child would inherit the operator's live terminal; the guard `inherited_interactive_terminal_refusal()` returns Some(message) for all Unix targets (with a variant text on ohos) and None only on non-Unix platforms.","commonSituations":"Agents attempt to run interactive/foreground terminal programs (vim, top, ssh with prompts) attached to the live terminal; porting or testing on Linux/macOS where interactive inheritance is never allowed; behavior differs across platforms since non-Unix builds skip this check.","solutions":["Run the command with `background: true, tty: true`, then continue it with `action: \"interact\"` and the returned `task_id`","Use `terminal/run` and `terminal/send` for a persistent interactive PTY lane","Launch the command in a new terminal window instead of the agent's terminal","For non-interactive work, omit `interactive: true` entirely"],"exampleFix":"// before\n{ \"command\": \"htop\", \"interactive\": true }\n// after\n{ \"command\": \"htop\", \"tty\": true, \"background\": true }","handlingStrategy":"validation","validationCode":"// Unix: interactive inheritance is never allowed, check the flag first\nif request.interactive {\n    // route through background tty or terminal/run instead\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use interactive: true on Unix with the one-shot shell tool","Remember the platform difference: the refusal exists on all Unix targets and is absent on non-Unix","Use terminal/run + terminal/send or background tty for anything interactive"],"tags":["shell","tty","job-control","unix"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}