Claude Code Background Tasks: Long-Running Shell Jobs 2026
Last updated: April 15, 2026
Background Tasks in Claude Code
TLDR verdict: use run_in_background: true on the Bash tool when a command will take longer than about thirty seconds. The session keeps going while the task runs, and you can tail its output with the Monitor tool or read its log file later.
Background tasks matter because Claude Code is otherwise single-threaded per session. A long build, a full test suite, or a database migration blocks the agent for minutes. Background execution frees the agent to do other work in parallel.
The run_in_background parameter
Every Bash tool call accepts an optional run_in_background flag. When set to true, Claude fires the command and returns immediately with a job handle. The stdout and stderr stream to a log file the agent can read.
Typical use:
Bash(command="pnpm build", run_in_background=true, description="Run production build")
The tool returns a background job ID. The agent continues the session, inspects other files, drafts code, and checks back on the job when ready.
Why not just use &
The shell & operator also backgrounds a process, but Claude loses the handle. Output goes to the void unless the command redirects it. Retrieving exit status means calling wait, which blocks. The run_in_background parameter wraps all of that; the agent gets a tracked handle and a log file without extra plumbing.
That said, & is still useful for fire-and-forget commands where the agent does not care about the result:
nohup redis-server --daemonize yes &
disown
Use the shell operator for server processes you want to outlive the session. Use the tool parameter for tasks whose output the agent will read.
Monitoring background output
Once a task runs in the background, the Monitor tool streams new stdout lines back into the session. The agent treats each new line as a signal and can act on it: stop the task if a test fails, continue if it passes, or wait for a specific log pattern.
A common pattern: kick off the build, move on, then wait for the build to finish before running the deploy.
Bash(command="pnpm build", run_in_background=true)
Monitor(jobId=<id>, until="Build complete")
Bash(command="pnpm deploy")
Monitor blocks the agent until the pattern matches or the task exits. That is the right semantics when the next step depends on the previous one.
Practical uses
- Database migration - kick off a long migration in the background while reviewing the migration file and checking for risky drops.
- Full test suite - start Jest or Pytest, move to drafting a docstring, then check results when the tail hits the summary line.
- Docker build - multi-stage builds can take several minutes. Background the build, use the time to write a Dockerfile comment or update README.
- Dev server - start Next.js dev on port 3000 in the background, then run a Playwright script against it in the foreground.
- Batch downloads - pull a large dataset with curl or wget, work on other files while it streams to disk.
- Log tailing -
tail -F /var/log/app.login the background, let Claude react to lines as they arrive.
Log files for durable output
Background tasks write to a log file the agent can read later. Redirecting to an explicit path makes the log survive the session:
pnpm test > /tmp/test-run.log 2>&1 &
echo $!
The echo $! captures the PID. Store it if the agent needs to kill or wait on that specific job later. For Claude-managed background tasks, the tool handles this plumbing automatically.
For repeatable jobs, commit a log directory to .gitignore and write to logs/. A quick retention script keeps the directory from growing forever:
find logs -type f -mtime +7 -delete
Cron scheduling inside a session
The CronCreate tool schedules recurring tasks from within an agentic session. The scheduled job fires even after the session ends, which is how Claude Code drives long-lived automation without a separate worker process.
Example: schedule a nightly dependency audit.
CronCreate(
schedule="0 3 * * *",
command="cd /srv/app && pnpm audit --prod > /var/log/audit.log",
description="Nightly production dependency audit"
)
List active schedules with CronList. Delete a schedule with CronDelete. The cron jobs run under the Claude Code daemon, not the system cron, so the schedule travels with the agent binary.
Remote triggers for event-driven tasks
For tasks triggered by external events like a GitHub webhook or a Slack command, the RemoteTrigger tool registers an HTTP endpoint that wakes the session. The tool returns a URL and a shared secret. Any external service that can POST JSON can invoke it.
See the remote triggers reference for the full lifecycle. The short version: register the trigger, share the URL with the external service, wait for the call. When it arrives, the agent handles the payload the same way it handles a user message.
Stopping background tasks
If a background task goes rogue, stop it with kill:
kill <PID>
Or by process name:
pkill -f "pnpm build"
For Claude-managed background jobs, the session tracks the PID internally. Asking the agent to stop the job by ID also works. Either way, confirm the process is gone with ps aux | grep .
For stuck tasks that ignore SIGTERM, escalate to SIGKILL:
kill -9 <PID>
Use -9 sparingly; it gives the process no chance to flush buffers or clean up temp files.
When background execution makes sense
Background tasks have real overhead: a log file, a tracked PID, a chance the task finishes before the agent checks back. For quick commands, foreground execution is faster and easier to reason about.
Rules of thumb:
- Command takes under 10 seconds: run in the foreground.
- Command takes 10 to 60 seconds and the agent has other work: consider background.
- Command takes over a minute: background it, especially if the agent has files to read or edits to queue up.
- Command is a server process (dev server, queue worker): always background; the agent does not want to block on it.
- Command is a one-shot query (curl, git log): foreground, since you want the output immediately.
Parallel work across several background jobs
One session can run several background tasks at once. A common pattern during a big refactor: type-check, lint, and test in parallel.
Bash(command="pnpm typecheck", run_in_background=true)
Bash(command="pnpm lint", run_in_background=true)
Bash(command="pnpm test", run_in_background=true)
The agent queues three jobs, keeps working on the refactor, and checks back on each. When any job reports a failure, the agent reads the log, fixes the issue, and reruns that specific check.
This beats waiting 90 seconds for each command in sequence. It is the closest Claude Code gets to the parallel execution you would do in a Makefile.
Gotchas to watch for
A short list of things that bite first-time users:
- Stale log readers - if the agent reads the log once and the task keeps writing, the second read starts from the beginning. Use tail-style tools or the Monitor stream instead.
- PID reuse - after a process exits, Linux may reuse its PID. Track jobs by tool-returned ID, not raw PID.
- Buffer flushing - Node, Python, and Ruby buffer stdout when output is not a TTY. Pass
--unbufferedor setPYTHONUNBUFFERED=1or the log will look empty until the task finishes. - Zombie processes - a background task whose parent shell exited but whose child is still running.
ps -ef | grep defunctspots them. Kill the parent or reboot to clean up. - Rate limits - running three background tasks against the same API key hits per-account rate limits fast. Sequence API-heavy tasks instead.
A worked example
Here is a realistic flow: add a feature to a Next.js app, run full checks in parallel, ship the PR.
- Agent reads the relevant components and drafts the change.
- Agent writes the new component file and updates imports.
- Agent kicks off
pnpm typecheck,pnpm lint, andpnpm testin background. - While checks run, agent writes a commit message and drafts a PR description.
- Monitor streams the first failing check. Agent reads the log, fixes the issue, reruns just that check.
- All checks green. Agent stages files, commits, pushes, opens the PR.
Total wall-clock time: about the duration of the longest check. Without background execution, the same flow takes the sum of every check in sequence.
Background tasks turn Claude Code from a serial assistant into something closer to a small CI pipeline that thinks.
Frequently asked questions
Do background tasks keep running if I close the session?
Tasks started with the shell `&` operator and `disown` survive. Tasks started with `run_in_background: true` on the Bash tool end with the session. For long-lived processes, use cron or a proper service manager.
How many background tasks can I run at once?
There is no hard cap, but four to six is a sensible practical limit. Beyond that the agent loses track, log files pile up, and OS resource limits kick in.
Why is my log empty while the task is running?
Stdout buffering. Pass `--unbuffered` to the command or set the language-specific env var: `PYTHONUNBUFFERED=1` for Python, `stdbuf -oL` for generic commands, `--no-buffer` for some test runners.
Can I use background tasks in headless mode?
Partially. The Bash tool still accepts `run_in_background`, but the agent exits at the end of the prompt, which kills most backgrounded jobs. For true fire-and-forget from headless, use `nohup` and `disown`.
Does Monitor block other agent work?
Yes. Monitor is a blocking wait on a log pattern. Use it only when the next step truly depends on the task finishing. For parallel-friendly checks, poll the log with short reads instead.
How is CronCreate different from system cron?
CronCreate schedules run inside the Claude Code daemon, so they inherit the session model memory, settings.json, and MCP servers. System cron runs raw shell with none of that context. Use Claude cron for agentic work, system cron for dumb shell jobs.