[BUG] Bash executions freeze Claude session.

Resolved 💬 5 comments Opened Sep 9, 2025 by mrdale1958 Closed Jan 8, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When Claude tries to run some nodejs code in bash it will hang the whole session. Esc doesn't interrupt, ctrl-r doesn't expand the output display. I kill the shell and restart Claude in a new one and things are fine until we try bash again. the code runs and exits fine in a shell of its own

What Should Happen?

Claude should run the code, display any output and return for the next task

Error Messages/Logs

there is none.  it stops interacting

Steps to Reproduce

✻ Welcome to Claude Code!

/help for help, /status for your current setup

cwd: /Users/dalemacdonald/LocalProjects/BOLOmetrics

node tools/automation/test-verify.js is failing

with\
/bin/sh: timeout: command not found
\nStderr: /bin/sh: timeout: command not found\
Also when you run it in your own bash the
process never ends

⏺ I'll examine the test-verify.js file to
understand the issue and fix it.

⏺ Read(tools/automation/test-verify.js)
⎿ Read 45 lines (ctrl+r to expand)

⏺ Let me examine the flash-and-log.js file to
see the verifyFirmware method and understand
why the timeout command is being used:

⏺ Search(pattern: "timeout", path:
"tools/automation", output_mode: "content")
⎿ Found 2 lines (ctrl+r to expand)

⏺ Now let me look at the specific verifyFirmware
method:

⏺ Search(pattern: "verifyFirmware", path:
"tools/automation/flash-and-log.js",
output_mode: "content")
⎿ Found 43 lines (ctrl+r to expand)

⏺ I can see the issue. The timeout command is a
Linux/GNU command that's not available on
macOS by default. Let me look at more of the
verifyFirmware method to understand the full
context:

⏺ Read(tools/automation/flash-and-log.js)
⎿ Read 40 lines (ctrl+r to expand)

⏺ I need to see how execCommand is implemented
and fix the timeout issue. The problem is that
macOS doesn't have the timeout command by
default. I'll need to replace it with a
Node.js-based timeout mechanism.

⏺ Let me examine the execCommand method to
understand how to implement the timeout
properly:

⏺ Search(pattern: "execCommand", path:
"tools/automation/flash-and-log.js",
output_mode: "content")
⎿ Found 67 lines (ctrl+r to expand)

⏺ Now I need to see the imports to understand
what modules are being used:

⏺ Read(tools/automation/flash-and-log.js)
⎿ Read 15 lines (ctrl+r to expand)

⏺ Perfect! Now I understand the issue. I need to
modify the execCommand method to support
timeouts natively using Node.js instead of
relying on the timeout command which doesn't
exist on macOS.

⏺ I'll create a new version of the execCommand
method that supports timeouts and then fix the
verifyFirmware method to use it:

⏺ Update(tools/automation/flash-and-log.js)
⎿ Error editing file

⏺ Let me read more of the execCommand method to
get the exact string:

⏺ Read(tools/automation/flash-and-log.js)
⎿ Read 15 lines (ctrl+r to expand)

⏺ I see the issue - there are escaped newlines.
Let me fix that:

⏺ Update(tools/automation/flash-and-log.js)
⎿ Updated tools/automation/flash-and-log.js
with 12 additions and 4 removals
207 }
208 }
209
210 - // Execute shell command with

  • promise wrapper

211 - execCommand(command, cwd =

  • process.cwd()) {

210 + // Execute shell command with

  • promise wrapper
  • and optional timeout

211 + execCommand(command, cwd =

  • process.cwd(), timeoutMs = null
  • ) {

212 return new
Promise((resolve, reject) => {
213 console.log(
Executing: ${command}
);
214
215 -

  • exec(command, { cwd }, (error,
  • stdout, stderr) => {

216 - if (error) {
215 + const child =

  • exec(command, { cwd }, (error,
  • stdout, stderr) => {

216 + if (error &&

  • error.signal !== 'SIGTERM') {

217 reject(new
Error(Command failed:
${error.message}\\nStderr:
${stderr}
));
218 } else {
219 resolve({ stdout,
stderr });
220 }
221 });
222 +
223 + // Add timeout if

  • specified

224 + if (timeoutMs) {
225 + setTimeout(() => {
226 +

  • child.kill('SIGTERM');

227 + reject(new

  • Error(`Command timed out after
  • ${timeoutMs}ms`));

228 + }, timeoutMs);
229 + }
230 });
231 }
232

⏺ Now I need to modify the verifyFirmware method
to remove the timeout command and use the new
timeout parameter instead:

⏺ Update(tools/automation/flash-and-log.js)
⎿ Updated tools/automation/flash-and-log.js
with 2 additions and 2 removals
301 'Beginning firmware
verification');
302
303 // Try to connect and
check for BOLOmetrics startup
message
304 - const command = `

  • timeout 10 python3 -c "

304 + const command = `

  • python3 -c "

305 import serial
306 import time
307 try:
...
320 print(f'ERROR: {e}')
321 "`;
322
323 - const result = await

  • this.execCommand(command);

323 + const result = await

  • this.execCommand(command
  • , process.cwd(), 10000);

324
325 if (result.stdout.include
s('FIRMWARE_OK')) {
326 console.log('✅
Firmware verification
successful');

⏺ Now let's test the fix to make sure it works
properly:

⏺ Bash(node tools/automation/test-verify.js)
⎿ 📊 Database initialized at: /Users/dalemacd
onald/LocalProjects/BOLOmetrics/data/hardwa
re-log.db
… +56 lines (ctrl+r to expand)

✢ Testing the fix to ensure process ends properly… (
esc to interrupt · ctrl+t to show todos)

╭──────────────────────────────────────────────────╮
│ > │
╰──────────────────────────────────────────────────╯
? for shortcuts ⧉ In flash-and-log.js

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

1.0.109

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗