Background Bash
Setting run_in_background: true on a Bash call starts the command as a background task, so Claude keeps working while a dev server, watcher, or long build runs to completion.
What it is
The Bash tool runs each command in a separate process and waits for it. That is wrong for anything that does not exit: a dev server, a file watcher, a tail -f. For those, Claude sets run_in_background: true. Claude Code starts the process, returns a task ID and the path of the file its output streams to, and the conversation continues. Claude reads that file when it wants to know what the process has printed.
Backgrounding also happens without being asked. When a command reaches its timeout without finishing, Claude Code moves it to the background rather than killing it, and the result says so explicitly: Command did not complete within its 120s timeout and was moved to the background, followed by the task ID and output path. Two exceptions: a command starting with sleep is never auto-backgrounded, and CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 turns the whole feature off.
You manage running tasks with /tasks, which lists the session’s background work — including subagents that have finished — and lets you stop them. Everything is session-scoped: background tasks do not survive exiting the session.
What it does for you
- It stops a dev server from ending the turn. Without backgrounding,
npm run devblocks until its timeout and Claude has done nothing else in the meantime. - It lets Claude edit and check at the same time. A watcher running in the background means Claude edits a file, reads the watcher’s output, and sees the rebuild result without starting a new command.
- It keeps a long build off the critical path. Claude starts the build, does something useful, and reads the output file when it is ready.
How it works
01Claude starts the command detached
With
run_in_background: true, Claude Code spawns the process and immediately returns a task ID plus the path of the file the output is being written to.02Output streams to a working file
Claude Code streams the command’s output to a file as it runs; a command whose output passes 5 GB is killed. Claude reads or greps that file to check progress, which is cheaper than re-running the command and gives it the whole history rather than the tail.
03A timeout moves the command instead of killing it
BASH_DEFAULT_TIMEOUT_MSsets the default — two minutes out of the box — andBASH_MAX_TIMEOUT_MSthe ceiling, ten minutes out of the box. Hitting the limit backgrounds the command and says so in the result.04Directory changes in a backgrounded command do not carry over
A
cd,pushd,popd, orchdirinside a command that gets moved to the background is discarded, and the result statesSession cwd remains <dir>so Claude does not act on a change that did not happen.05You inspect and stop tasks with /tasks
/tasks— also available as/bashes— lists the session’s background work and lets you stop it. Claude can also stop one withTaskStop.06Non-interactive runs end them shortly after the result
Under
-p, a background shell is terminated about five seconds after Claude returns its final result and stdin closes. The grace period lets a task finishing right at the end still deliver its output.
How to implement it
01Say what should run in the background
Ask for it directly: "Start the dev server in the background, then fix the failing component." Claude sets the flag; you do not pass it yourself.
02Ask Claude to read the output rather than restart the command
The output file keeps accumulating. "Check the dev server output for errors" reads the file; starting the server again gives you two servers on one port.
03Raise the timeout for legitimately slow foreground work
Set
BASH_DEFAULT_TIMEOUT_MSandBASH_MAX_TIMEOUT_MSinenvfor a project whose test suite genuinely takes eight minutes, so it is not backgrounded halfway through.04Stop tasks you are done with
Run
/tasksand stop the ones still running. A dev server left holding port 3000 is the most common orphan.05Do not rely on background tasks under -p
They are killed about five seconds after the final result. If a CI step needs a server, start it in the pipeline and pass Claude the URL.
Examples
# What you type:
# "Start the dev server and the test watcher in the background, then fix
# the failing CartTotal test. Check the watcher output after each edit
# instead of running the suite again."
# What Claude runs — each returns a task ID and an output file path:
npm run dev # run_in_background: true
npm test -- --watch # run_in_background: true
# What Claude does between edits, instead of re-running anything:
# Read <output-file-path> # the watcher's latest run
# Grep 'FAIL|✕' <output-file-path> # just the failures
# What you do at the end:
/tasks # list background work and stop the ones still running{
"env": {
"BASH_DEFAULT_TIMEOUT_MS": "300000",
"BASH_MAX_TIMEOUT_MS": "900000",
"BASH_MAX_OUTPUT_LENGTH": "80000"
}
}Use it when
- Running a dev server while Claude edits the components it serves.
- Keeping a test watcher alive so each edit is checked without a new command.
- Starting a long build or Docker image job and doing something else until it finishes.
- Tailing a log while reproducing a bug, so the output arrives as it happens.
- Running a database or queue worker that the code under test needs.
Avoid it when
- You need the result before the next step. A background task returns a task ID, not an answer; Claude has to poll the file, which costs more than waiting.
- The command is quick. Backgrounding a two-second command adds a task, an output file, and a read for nothing.
- You are in a
-prun. Background shells are killed about five seconds after the final result, so anything that needed to keep running does not. - You want to react to each line as it appears. That is the
Monitortool, which feeds output lines back to Claude as events instead of writing them to a file Claude has to poll.
Common mistakes
SYMPTOMA long-running command times out and Claude seems to lose track of it.
FIXIt was not killed — it was moved to the background. The result names the task ID and the output file. Ask Claude to read that file, or open
/tasks.SYMPTOMTwo dev servers end up fighting over one port.
FIXClaude started a second one instead of reading the first one’s output. Ask it to check
/tasksand read the existing output file rather than re-running the command.SYMPTOMA
cdinside a command that got backgrounded does not affect later commands.FIXThat is intentional: directory changes in a backgrounded command are discarded, and the result says
Session cwd remains <dir>. Pass absolute paths instead.SYMPTOMBackground tasks are left running after the session ends.
FIXStop them from
/tasksbefore you exit. Under-pthey are terminated automatically about five seconds after the final result.SYMPTOMA
sleep-based wait is expected to background and does not.FIXClaude Code never auto-backgrounds a command starting with
sleep. Use theMonitortool to wait on an actual condition instead of a fixed delay.
Best practices
- Ask for backgrounding explicitly for anything that does not exit on its own.
- Have Claude grep the output file for the failure pattern rather than reading the whole log.
- Set
BASH_DEFAULT_TIMEOUT_MSto match your project’s slowest legitimate foreground command. - Check
/tasksbefore starting a server you may already be running. - Reach for
Monitorwhen you want Claude to react to output as it arrives, and background Bash when you only need the output later. - Treat
-pruns as if background tasks do not exist, because they are terminated shortly after the result.
Try it in five minutes
Start a background process, read its output, and watch a timeout move a command instead of killing it.
- 1.In a project with a dev server, ask: "Start the dev server in the background and tell me the task ID and output file."
- 2.Ask Claude to make a small visible change, then to read the output file and report what the server logged.
- 3.Run
/tasksand confirm the server is listed. - 4.Ask Claude to run
for i in $(seq 1 200); do echo $i; sleep 1; donein the foreground and watch the result report that it was moved to the background at the timeout. - 5.Stop both tasks from
/tasksand confirm the port is free.
Related concepts
Verified against code.claude.com/docs/en/tools-reference#bash-tool-behavior on 2026-08-09. See content/SOURCES.md for the full table.
← / → MOVE BETWEEN CONCEPTS