Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
When Cursor’s agent runs rg (ripgrep) via its shell tool without an explicit path argument, the process hangs indefinitely instead of completing in seconds.
Root cause: rg’s stdin heuristic. When no path argument is given, ripgrep checks whether stdin is a TTY. If it is, it searches the current working directory; if it isn’t, it reads from stdin instead. The agent’s shell wraps every command in cursorsandbox with stdin connected to a Unix domain socket, so the TTY check fails and rg silently waits forever for input on stdin that never arrives.
Symptoms:
- The
rg process sits at ~0.0% CPU in state S (sleeping), accumulating essentially no CPU time, while the agent’s shell tool reports it as “still running” and eventually backgrounds it.
lsof shows FD 0 as a Unix socket, not a TTY.
- The exact same command run in a regular interactive Terminal in the same directory finishes in ~1–2 seconds.
- Appending
. (or any explicit path) to the rg invocation fixes the hang.
This is a high-frequency footgun in real agent sessions because the agent often shells out to rg directly (which Cursor’s tool docs actively recommend over grep). The built-in Grep tool is unaffected because it implicitly passes the workspace root as the path.
Steps to Reproduce
-
Open Cursor in a moderately sized repo (I reproduced in a ~100k-file Node monorepo, but any non-trivial repo works).
-
In an Agent chat, ask the agent to run an rg command without a path argument, e.g.:
rg -c "assert\.ok\(" --type js -g "*.spec.js"
-
Observe that the command never returns. The shell tool reports it as still running and eventually moves it to background.
-
Open a regular macOS Terminal, cd to the same directory, and run the exact same command. It completes in ~1–2 seconds.
-
(Optional) While the agent’s rg is hung, inspect it:
ps -o pid,pcpu,time,stat -p <rg_pid> # ~0.0% CPU, state S, ~0:00.00 CPU time
lsof -p <rg_pid> | awk '$4 ~ /^0/' # FD 0 is "unix", not a TTY
-
Re-run the same command via the agent but with . appended:
rg -c "assert\.ok\(" --type js -g "*.spec.js" .
It completes immediately with correct results, confirming the hang is rg’s stdin fallback, not anything else about how the agent runs the command.
Expected Behavior
rg invoked by the agent should behave the same as rg invoked from a normal terminal: when no path argument is given, it should search the current working directory and return results in seconds, not block forever on a stdin that will never produce data.
Any of the following would resolve it:
- Wire stdin to
/dev/null (or close it) for commands run by the shell tool, so rg sees EOF immediately and falls through to searching cwd.
- Allocate a pty for the shell tool so
rg’s TTY check succeeds.
- Update the agent’s tool documentation/system prompt to instruct it to always pass an explicit path when invoking
rg directly. (The shell tool docs already steer the agent toward rg over grep; adding a sentence about always passing a path would be a small change.)
Operating System
MacOS
Version Information
Version: 3.3.30 (Universal)
VSCode Version: 1.105.1
Commit: 3dc559280adc5f931ade8e25c7b85393842acf30
Date: 2026-05-09T18:28:42.332Z
Layout: editor
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Darwin arm64 25.5.0
For AI issues: which model did you use?
Most recent issue seen on claude-opus-4-7-thinking-xhigh, but I’m almost 100% certain I’ve seen this across many different models
Additional Information
Environment
- ripgrep: 15.1.0
- Default shell: zsh
Evidence the process is blocked on stdin, not slow
A stuck rg invoked by the agent had been running for 19 minutes when inspected; it had accumulated essentially no CPU time:
PID ELAPSED %CPU TIME STAT
3096 19:23 0.0 0:00.01 S
lsof on the same PID confirms FD 0 is a Unix domain socket, not a TTY:
rg 3096 user 0u unix 0x7a1c8e2ecfa67e52 ->0x1be40e439438bbc
For comparison, the same rg invocation run by hand in an interactive Terminal in the same cwd completed in 1.81s and produced the expected results.
Process tree (from ps)
The agent’s command is wrapped roughly like this (truncated):
/Applications/Cursor.app/.../helpers/cursorsandbox --policy /var/folders/.../sandbox-policy-xxx -- /bin/zsh -c "<wrapper script> -- <user command>"
└─ /bin/zsh -c "..."
└─ rg -c "assert\.ok\(" --type js -g "*.spec.js" -g "integration-tests/**"
Stdin to the inner zsh (and therefore to rg) is a unix socket inherited from the cursorsandbox wrapper, which is what trips rg’s “stdin is not a TTY → read from stdin” heuristic.
Why this is more than a minor papercut
- The shell tool’s own description tells the agent to use
rg instead of grep, but doesn’t tell it to pass a path. So the agent reaches for rg constantly and falls into this trap.
- Each hang typically wastes ~minutes per occurrence (the agent waits, then backgrounds, then sometimes retries), and consumes a model turn slot in the meantime.
- The built-in
Grep tool is unaffected because it implicitly passes the workspace root as the path, which suggests the cleanest fix is either matching that behavior at the shell-tool layer (e.g. close/redirect stdin to /dev/null) or instructing the agent in the tool description.
Workaround currently used
A workspace rule telling the agent to always append . (or another explicit path) when shelling out to rg.
Does this stop you from using Cursor
No - Cursor works, but with this issue