10. Work That Keeps Running After You Close the Laptop

Summary

What happens when the laptop closes

Three setups behave differently. With remote control, the session keeps running on your laptop and the phone or browser only connects to it, so it stops when the laptop sleeps or goes offline. A Claude Code on the web session runs on a machine Anthropic starts with a copy of your GitHub repository, so it continues. A headless run (claude -p) lasts as long as the machine it was started on. Plan eligibility and the exact remote-control command name change between releases, so check Anthropic's documentation and your installed version.

Preparing a hosted run

The job is the shared-list app's issue thirteen, the item count in the list header. Last chapter's fix, regression test and commit were only described, so this run does them. A cloud session needs these in place:

  • GitHub access through the Claude GitHub app, limited to the one repository. The session works on a new branch cloned from main.
  • An environment whose setup script installs packages, installs and starts PostgreSQL, creates a test database and runs migrations. Without a database, a run can report success with nothing tested. A SessionStart hook in the repository is an alternative.
  • Committed files such as CLAUDE.md, the settings, the hook, the skill and the reviewer subagent load as usual. The GitHub token does not, so the issue text goes into the request. Production secrets stay out.
  • Small commits at each step, since only the branch and the conversation log outlast the session.
  • A final report with test output, reviewer verdicts and open items.

The run and its checks

The request asks for a failing regression test first, then the fix, then a review against the criteria. In the illustrative result the header uses the displayed list's length. The reviewer only read code, so you still run the suite and try the app by hand. Common problems are a failed database setup and a session waiting on an approval; repeated routine approvals can become allow rules.

Headless runs and permission mode

The same job can run from a script or CI with a stated permission mode, a turn limit, an optional budget cap and JSON output. The chapter recalls an earlier news item: headless and Agent SDK runs may start in default mode under some conditions, where nobody is there to approve actions. Save the JSON, especially the session id.

When a run stops partway

After a timeout or usage limit, resume by session id on the same machine, or start a fresh session from the committed branch. Both work because of the commit after each step. Automatic retries should check for an existing branch first.

Choosing, and checking from your phone

Use remote control to watch a job, a cloud session for self-contained repository work, and headless for scripted or CI jobs. On the phone, read the last message: the named test and its result, the reviewer verdicts, then the diff for unexpected files. Add a report-format line to CLAUDE.md's definition of done.


Where the work lives when the lid comes down

Close your laptop while Claude Code is working, and what happens next depends on where that work is running. There are three common setups, and each one gives a different answer.

The first is remote control. You start a Claude Code session in your terminal as usual, then connect to it from the Claude app on your phone or from Claude Code in a browser. You can read its progress, send messages and answer its approval prompts from somewhere else. The session itself never moves. It runs on your laptop, in your checkout, with your files and your environment variables. Your phone is only a window into it. Close the lid, let the laptop sleep or drop off the network, and the work stops, because the machine doing it has stopped.

The second is a hosted cloud session. The main one is Claude Code on the web, which you open from the Code section of the Claude website or the Claude mobile app. Here Anthropic starts a machine for the task, copies your GitHub repository onto it, and runs Claude Code there. Your laptop only sent the request. Close it and the session carries on, because nothing it needs is on your laptop.

The third is a headless run. You type claude, then dash p, then a request in quotes, and Claude Code works through that request with no interactive screen, prints a result and exits. Where it runs is up to you. On your laptop it stops when the laptop stops. On a server, a cloud machine or a continuous integration runner, it keeps going as long as that machine does. Headless mode is the Claude Code program running without a conversation window. It is different from the Claude API, which is the raw model service, and from the Agent SDK, which is a library for building your own agent program in code.

So the short answer is this. Remote control stops when the laptop does. A cloud session does not. A headless run lasts as long as the machine you started it on.

All three are still changing quickly, so two things are worth checking on Anthropic's Claude Code documentation before you rely on them. First, which plans can use Claude Code on the web and remote control. Both have been available to paid individual and team plans, with conditions that change between releases. Second, the exact name of the command that turns on remote control in your installed version. Run claude dash dash version and compare it with the documentation page for that feature.

This chapter moves the course's main routine off the laptop for the first time. So far, every lesson's work happened in a terminal with you sitting in front of it. The goal now is a modest job that finishes somewhere else, tells you it is done, and can be picked up again if it stops halfway.

The job: finishing issue thirteen

The show's example is still the shared-list app: a small TypeScript and React web app with a PostgreSQL database, hosted on GitHub. Last chapter we used item-count issue thirteen. It asks the list header to show how many items the list has, with two acceptance criteria. The header shows the number of items. The number stays correct after adding, after deleting, and after a reload. We reviewed a good version and a deliberately broken version, where deleting left the count unchanged, and the reviewer subagent caught the delete handler. But the fix, the regression test for deletion and the commit were only described. They were never shown done. For this run, say the broken version is the one on main, so the job is to fix it.

That makes a good first job to run away from the laptop. It is small. Its acceptance criteria are already written. You know which test should fail before the fix. A wrong result is easy to spot by hand. A job you would struggle to judge at your desk is a poor choice for your first unattended run.

What a hosted run needs before it starts

A cloud session begins with a fresh machine and none of your laptop's setup. Before giving it the task, walk through what it will have and what it will be missing. Six things matter.

First, the checkout. When you first open Claude Code on the web, it asks you to connect GitHub by installing the Claude GitHub app on your account or organization and choosing which repositories it may see. Give it the shared-list repository only. For each session you pick the repository and the branch to start from. Here that is main. The session clones the repository onto its machine and does its work on a new branch, which it can push back to GitHub. It does not edit your main branch directly, and it never touches your laptop's copy.

Second, the working directory. The session works inside the root of that fresh clone. Every command your instructions mention, such as installing, running the tests or type checking, runs from there, just as it does in your terminal. If your CLAUDE.md said "cd into the app folder first," it would still work. Paths that point outside the repository, like a file in your home folder, will not exist there.

Third, dependencies. A fresh machine has a recent toolchain but not your project's packages, and it does not start with your database. Claude Code on the web lets you define an environment, a saved setting you pick when starting a session. An environment has three parts that matter here: a setup script that runs when the machine starts, environment variables, and a network access level. For the shared-list app, the setup script installs the project's packages, installs PostgreSQL, starts it, creates a test database and runs the migrations against it. That is five steps, the same ones a new teammate would follow. They are already written in CLAUDE.md as the install, migration and test commands.

There is a reason this matters. Without a database, the agent can still edit code and the type check still passes, but the suite fails or gets skipped, and the run may report success when nothing was tested. The network access level also matters. The default level allows common package registries but not everything. If installing a package or PostgreSQL fails, look at the setup log for a blocked address before you widen access. The documentation lists what each level allows.

You can also run setup from the repository instead of the environment. A SessionStart hook in the committed settings file runs when a session begins, so a script there can install packages and start the database for every session, in the cloud or on a new laptop. The trade-off is upkeep. A setup script in the environment lives on the website and is easy to forget. A hook lives in the repository and gets reviewed with everything else. For a team, the hook is usually easier to keep correct. For a first try, the environment's setup script is quicker to change.

Fourth, credentials. This is where a hosted run differs most from your terminal. Everything committed to the repository comes along with it: CLAUDE.md with its definition of done, the settings file with its deny list, the model and effort defaults, the PostToolUse hook that runs the type check after every edit, the reproduce-bug skill, and the criteria-reviewer subagent in the agents folder. They load in the cloud session just as they do locally. That is the payoff of committing them instead of keeping them in your head.

Your GitHub personal access token does not come along. The committed MCP configuration holds only a placeholder that reads a variable called GITHUB_PAT from the environment. On the cloud machine that variable is empty unless you set it. You have two choices. You could add a token to the environment's variables. Or the run can work without the GitHub MCP connection by including the issue's text in the request itself. For this job, choose the second. The issue is short, the criteria are what the run needs, and you don't create a new long-lived secret on a machine you don't manage. The session can still push its branch and open a pull request through the GitHub app connection you approved. That connection is limited to the repository you chose.

The same rule covers other secrets. A cloud session for a code change needs test data and a test database. It does not need production database passwords, deployment keys or payment keys. Leave them out. If a task seems to need one, that is a sign it belongs in a later, more carefully planned stage of the course.

Fifth, the record. Once the session ends, the machine's working files are gone. What lasts is the branch and its commits on GitHub, plus the session's conversation log, which stays in your list of sessions on the web and in the app. So the request should ask for small commits as each step finishes. Uncommitted work exists only on a machine you cannot reach.

Sixth, how it reports completion. A cloud session shows its status in the session list. Finished sessions show the diff and a button to create a pull request, and the Claude app can notify you on your phone. The real report is whatever you asked it to leave behind. Ask for the test output, the reviewer's verdicts and a short summary as the session's last message.

Starting the run and walking away

Open Claude Code on the web, choose the shared-list repository, start from main, pick the environment with the database setup, and give a request like this. "Issue thirteen: the list header should show the number of items. Acceptance criteria, word for word: one, the header shows the number of items in the list; two, the number stays correct after adding an item, deleting an item and reloading the page. The count currently does not change on delete. Work on a new branch named fix item count delete. First add a regression test that deletes an item and checks the header, run it and confirm it fails on the current code, and commit it. Then make the fix, run the type check and the full suite, and commit. Then hand the criteria word for word and the git diff against main to the criteria-reviewer subagent and answer every finding. Finish with the test results, each reviewer verdict with its evidence, and anything you could not settle."

This request covers each thing the cloud machine lacks. It pastes the criteria in, since there is no issue connection. It asks for commits at each step, since the machine's files will not survive. It names the reviewer, since last chapter showed that naming the subagent is how you make sure it runs. And it asks for a final report you can read on a small screen.

Close the laptop.

When you check in, say from your phone an hour later, here is what a good result looks like in this illustrative run. The session is marked finished. The branch has two commits. The first adds a test that deletes one of three items and expects the header to say two, and the log shows it failing with the header still saying three. The second makes the header use the length of the list that is actually displayed, instead of a separate counter the delete handler never updated. The suite passes. The reviewer reports both criteria passing, and cites the header component and the delete handler with file and line.

Read that report as you would read one at your desk. The reviewer only read the code. The suite ran on a cloud machine against a test database the setup script made. Neither one has clicked the real app. So when you are back at the laptop, run the usual routine. Fetch the branch, run the suite yourself, start the app, add three items, delete one, check that the header says two, reload, and check again. If all of that holds, open the pull request from the session and merge it the way you would merge your own branch.

Two things commonly go wrong with a first cloud run. If the log shows the database setup failing, the tests may have been skipped or every test errored, and a summary that says "done" means nothing. Check that the test output names the delete test and shows it passing. And if the session stopped to wait for approval of a command its permissions do not allow, it just sits there until you answer. You can approve it from the phone. If the same approval keeps coming up for a routine command, such as running the tests, add an allow rule for it to the committed settings so future runs are not held up.

The same job as a headless run

Claude Code on the web suits a self-contained repository task you start by hand. Sometimes you want the job to start from your own script instead, on a schedule or as a step in continuous integration, which is the system that runs checks automatically when code changes. That is what headless mode is for.

A headless run of the same job is one command. You run claude dash p with the request in quotes. Add dash dash permission mode, followed by a mode name. Add dash dash max turns with a number, say forty. Add dash dash output format json. Here is what each part does.

The permission mode must be stated outright. As covered in an earlier news segment, unattended runs started with claude dash p, and those started through the Agent SDK, may begin in default mode under some conditions. Default mode asks for approval on many actions, and in a headless run there is nobody to approve them, so the run stalls or refuses. Choose the mode deliberately. For a job that edits files and runs tests in a throwaway checkout, a narrow choice is accept edits mode, which approves file edits without asking but still asks before running other commands, combined with allow rules for your test and type-check commands. Auto mode gives the agent more room. Either way, the committed deny list still applies.

The turn limit is your guard against a run that loops. Each turn is one round of the model acting and seeing the result. Forty is plenty for this fix. If a run uses them all, it stops and says why. Headless runs also accept a spending cap, dash dash max budget usd, which ends the run when its cost reaches the amount you set. Use it when the run is billed through an API key.

The JSON output format turns the final result into a small structured record instead of plain text. Among its fields are the session id, the final result text, the number of turns used, the cost, and a subtype that says whether the run succeeded or stopped on a limit. Save that record to a file. The session id is the most important piece for recovery.

Run it on a server or a cloud machine that has the repository checked out, the database running and Claude Code installed and signed in. In this illustrative case, the run finishes in a few minutes, the JSON says success, and the branch has the same two commits the cloud session produced. You check it the same way as before.

When a run stops partway

Now the case to practice on. Say you run the same job on a small cloud machine and wrap it in a thirty-minute timeout. Or suppose the account hits its usage limit. Either way, the run stops partway through. The process ends, the JSON record says it did not finish, or there may be no final record at all if it was killed.

Look at what survived. The branch on the machine has one commit, the failing regression test, because the request asked for a commit after each step. The fix itself was half written and never committed. The session id is in your saved output or in the run's log.

You now have two ways to continue. You can resume the session by running claude dash p dash dash resume, followed by the session id, with a short request such as "continue from where you stopped." Resuming brings back the whole conversation, so the agent remembers what it tried. Choose this when the stop was outside the agent's control, such as a timeout or a usage limit, and the session's reasoning was on track. Resume on the same machine, because the session's history is stored locally where it ran. If that machine is gone, so is the option.

Or you can retry from the branch with a fresh session. Start a new claude dash p run on a checkout of the branch, and tell it that the regression test is committed, and that its job is to make that test pass and finish the remaining steps. The new session reads CLAUDE.md, the git log and the committed test, and it has everything it needs. Choose this when the old session's context was large, when it had gone off course, or when the stop was a usage limit and a large resumed session would use a lot of your allowance.

Both options work only because the first step was committed. That is the course's rule from the multi-session chapter, holding up in a harder setting: work committed step by step survives the run that made it, and uncommitted work belongs to the run. When you design an unattended job, put a commit at every point where you would hate to start over.

One caution about retrying. If a script retries automatically, make it check first whether the branch already exists and what is on it. A retry that starts again from main makes a second branch, and now two branches claim the same issue. Retries, timeouts and duplicate starts get their own treatment later in the course. For now, one rule is enough: a retry continues from what was committed, not from scratch.

Choosing the mechanism

Here is how the three fit different tasks. Use remote control when you want to watch a job and answer its approvals as they come up, and you are fine with your laptop staying on and connected. It extends your desk to your phone. Use a cloud session for a self-contained repository task you want finished while you are away: the code is on GitHub, the setup can be written down, and the result can be checked as a branch. Use headless runs when the job should start from your own script, on your own server, or inside continuous integration, where nobody is there to talk to.

That last case leads to the next stage. GitHub's own runners can run Claude Code headlessly when an issue is labeled, which is how an issue becomes a pull request without anyone opening a terminal.

Checking a background run from your phone

That next stage will mean more work arriving while you are away, so it helps to have a set routine for checking on a background run from the Claude app. It takes about two minutes per run.

Open the session and go straight to its last message, not its running commentary. If the request asked for a final report, as this chapter's did, the last message gives you three things to check in order. First, did the tests actually run? Look for the specific test you care about, here the delete test, by name, with a count of passed and failed. A summary that says the tests pass without naming any is a reason to look closer. Second, the reviewer's verdicts. Each criterion should be marked pass, fail or unclear, with a file and line. An unclear verdict is not a failure. It is a note of what you need to click yourself later. Third, the diff. On a phone, scan it for files you did not expect, such as a changed migration or a lock file, before you look at the logic.

If something is waiting for approval, decide it on the spot only if you would approve it without thinking at your desk. Otherwise leave it. A paused session costs nothing, and a wrong approval from your phone is hard to take back.

To make this routine reliable, add one line to the CLAUDE.md definition of done: any run that is not interactive ends with a report naming the tests run and their results, the reviewer's verdicts, and anything left open. Commit it, start your next cloud session, and check that its last message follows the format. If it does, every future background run will report the same way, and checking one from your phone becomes the same two-minute task each time.

Want a Series of your own?

Gnothi wrote and narrated this chapter. Name a subject and it writes you a course, or a story that teaches it, one chapter at a time, delivered to your podcast app.

Get started free