Files
llmx/codex-cli/tests/fixed-requires-shell.test.ts
Brayden Moon 8dd1125681 fix: command pipe execution by improving shell detection (#437)
## Description
This PR fixes Issue #421 where commands with pipes (e.g., `grep -R ...
-n | head -n 20`) were failing to execute properly after PR #391 was
merged.

## Changes
- Modified the `requiresShell` function to only enable shell mode when
the command is a single string containing shell operators
- Added logic to handle the case where shell operators are passed as
separate arguments
- Added comprehensive tests to verify the fix

## Root Cause
The issue was that the `requiresShell` function was detecting shell
operators like `|` even when they were passed as separate arguments,
which caused the command to be executed with `shell: true`
unnecessarily. This was causing syntax errors when running commands with
pipes.

## Testing
- Added unit tests to verify the fix
- Manually tested with real commands using pipes
- Ensured all existing tests pass

Fixes #421
2025-04-20 21:11:19 -07:00

39 lines
1.3 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { parse } from "shell-quote";
// The fixed requiresShell function
function requiresShell(cmd: Array<string>): boolean {
// If the command is a single string that contains shell operators,
// it needs to be run with shell: true
if (cmd.length === 1 && cmd[0] !== undefined) {
const tokens = parse(cmd[0]) as Array<any>;
return tokens.some((token) => typeof token === "object" && "op" in token);
}
// If the command is split into multiple arguments, we don't need shell: true
// even if one of the arguments is a shell operator like '|'
return false;
}
describe("fixed requiresShell function", () => {
it("should detect pipe in a single argument", () => {
const cmd = ['grep -n "finally:" some-file | head'];
expect(requiresShell(cmd)).toBe(true);
});
it("should not detect pipe in separate arguments", () => {
const cmd = ["grep", "-n", "finally:", "some-file", "|", "head"];
expect(requiresShell(cmd)).toBe(false);
});
it("should handle other shell operators in a single argument", () => {
const cmd = ["echo hello && echo world"];
expect(requiresShell(cmd)).toBe(true);
});
it("should not enable shell for normal commands", () => {
const cmd = ["ls", "-la"];
expect(requiresShell(cmd)).toBe(false);
});
});