1. Define success before giving a task unattended time

A useful unattended task is more specific than “fix the repository.” State the input revision, permitted directories, available tools, expected artifact, maximum runtime and conditions requiring a human decision. For example, a documentation job might read a supplied diff and produce a report under an output directory, with no network tools and no source edits. That is a contract a separate checker can assess.

Separate three outcomes: the runner started, Claude returned a result, and the requested work passed acceptance. A process can start correctly and then refuse a tool. It can return fluent JSON while leaving the file unchanged. It can finish useful work while a child process continues running. Combining these into a single green status makes failures difficult to diagnose.

The plan below concerns your own controlled runner and disposable data. It does not establish that your installed version, credentials or company policy behave as described. Record the version and effective configuration before testing. Choose a harmless, reversible first workload and preserve the previous launcher configuration so recovery is concrete.

2. What changed on October 30 and 31

Official releaseRelevant changeAcceptance implication
v2.1.314, October 30A write guard for three file tools; corrected print-mode startup failure status.Test a refused outside write and a failed startup independently.
v2.1.314CI trust correction for ultrareview and remote-control.Do not extend that promise to every headless invocation.
v2.1.316, October 31Cleanup of shell commands after self-exit; a restricted-mode outside-upload correction.Retest lifecycle and file boundaries on the intended host.

Official GitHub metadata places v2.1.314 at October 30, 01:06:26 UTC and v2.1.316 at October 31, 01:01:35 UTC, respectively 09:06:26 and 09:01:35 in Singapore. The official latest-release endpoint still identified v2.1.316 during this research. These are release timestamps, not proof that every installation has updated.

The engineering opportunity is a clearer contract between runner and agent. A documented correction gives you a regression case to add, rather than evidence that all related failures are impossible. Keep older context clearly dated: the MCP retry and safety-event changes discussed later originate in the October 21 UTC release, not a new November announcement.

3. Map file tools, commands and external services separately

There are at least four execution surfaces: built-in file tools, shell commands and their children, locally launched integration processes, and remote services. A working-directory rule can govern the first without constraining a Python test process or a database action on an MCP server. A repository worktree separates Git work; it does not establish an operating-system boundary around everything launched from it.

The sandbox documentation explicitly separates shell isolation from file tools, web tools, local MCP servers, hooks and helper processes. A remote tool may perform work on another machine altogether. Draw a small inventory before configuring permissions: which process performs the write, which credential it uses, and which component can stop it.

For a report-only job, eliminating a needless execution surface is often easier to verify than allowing it and writing many exceptions. That is an architectural choice, not a promise that fewer tools make all input trustworthy. Keep tool inventory, permissions and runtime confinement as separate fields in the job configuration.

4. Use the new write boundary without inventing its missing reference

The release note names permissions.blockWritesOutsideWorkingDirectories and says that Write, Edit and NotebookEdit refuse paths outside working directories in every permission mode. This is a meaningful statement about those named tools. It is not a documented guarantee about arbitrary commands, remote services or every way to move information out of a session.

The official settings reference we reviewed did not supply a dedicated entry for the new key. We therefore do not present a guessed complete configuration, default, remote-forwarding rule or additional-directory edge case. On the version you deploy, validate the setting and test its actual refusal before depending on it. A silently ignored key would otherwise create false assurance.

Also distinguish tool names from path-rule syntax. The permission reference says path-scoped editing rules use Edit(path); a scoped Write(path) or NotebookEdit(path) is not matched by the file checks. Inspect the resolved rule and its source. Test an inside path, a sibling path and a deliberately added fixture directory, without using real home-directory files.

5. Verify shell isolation, availability and fallback

A shell test must exercise a child process, not merely an Edit call. An approved build can run scripts that open files indirectly. The file-rule documentation describes these limits; an operating-system boundary is what constrains the running subprocess. The built-in sandbox supports macOS, Linux and WSL2. Native Windows does not gain the same boundary just because the JSON setting exists.

For supported disposable runners, the official managed-sandbox example combines the following settings. This example is reproduced as a configuration shape to review, not a configuration we installed or executed:

{"sandbox":{"enabled":true,"failIfUnavailable":true,"allowUnsandboxedCommands":false}}

These options address unavailable isolation and unsandboxed retries. They do not cover every excluded command or process outside the shell sandbox. Default shell reads can still reach much of the computer, including credentials; inspect read access and inherited environment as well as writes. If the entire toolchain needs confinement, put the whole process in an appropriately configured isolated runner and review its mounts and network routes.

Use /sandbox to inspect configuration. Have the agent execute the harmless fixture probe through its tool: typing it at the usual ! prompt can test a different, unsandboxed path. A test run on macOS does not validate a WSL image with missing dependencies.

6. Decide what a headless run is allowed to discover

Print mode is an execution interface, not an automatic trust boundary. Ordinary claude -p has no workspace trust dialog and can discover project hooks and MCP configuration. The October 30 CI fix for ultrareview and remote-control must not be generalized to this different path. Review repository-supplied execution before invoking a third-party checkout.

--bare reduces automatic discovery of customizations. It does not provide OS isolation, and the documentation describes exceptions and setting-source interactions. Bare mode also uses an API credential rather than the subscription login for the Anthropic API. Authentication and billing route must therefore be an explicit deployment decision; the examples here made no model request.

The CLI reference distinguishes --allowedTools, which preapproves matching calls, from --tools, which limits built-in tool availability. The latter does not remove MCP tools. Review --setting-sources, explicit settings and MCP configuration together. For organization enforcement, check managed settings rather than assuming a local flag overrides policy. Keep the launcher and the reviewed configuration in the same versioned release bundle.

7. Treat MCP inventory, credentials and repeat safety independently

An MCP connection is a separate capability. List each server, transport, allowed tools and permitted business action. A local server can launch with host access; a remote server can possess credentials Claude never sees. Restrict the server's own access and task scope, rather than treating an agent-side file rule as a database or issue-tracker policy.

The MCP reference documents repeating an interrupted pending HTTP call once when a tool declares read-only or idempotent behavior. The earlier v2.1.307 release dates the retry correction to October 21 UTC. A declaration is not a proof that repeating a real payment, message or resource creation is safe. Implement and test the service's actual repeat behavior, with an operation identifier where appropriate.

Use a local mock journal for acceptance. Count received calls and final state after a deliberately interrupted response. A successful retry does not establish exactly-once delivery. Never use a real customer workflow as the test fixture. Avoid recording credentials in the journal; test authentication expiry with disposable test credentials, not by disrupting a production sign-in.

8. Make exit status, JSON and the artifact agree

The startup correction makes a previously misleading failure easier to detect. Your wrapper should still capture exit status, stdout, stderr, runtime and a task identifier separately. A zero exit status is evidence about the process outcome, not independent evidence that the requested repository change is correct.

Structured output supports JSON and a supplied schema. Check the presence of structured_output before consuming it; the documentation notes that a run can finish without that field. Schema validation checks shape. It does not establish that a referenced file exists, that a test actually ran or that an asserted business state was committed.

Give a separate checker the expected artifact path and deterministic conditions. A report task can require a UTF-8 file containing known fixture references; a code task needs its own appropriate acceptance checks. Compare changes against the allowed file set and reject unexpected modifications. Keep a refused action distinct from a transport failure, and preserve the agent's explanation without allowing it to substitute for the artifact check.

9. Bound runtime and verify cleanup after cancellation

Set a runner deadline outside the model loop. Decide how the launcher requests shutdown, how long it waits and how it identifies only the processes owned by that job. A timeout is a terminal job state, not permission to leave the same work running indefinitely. Do not terminate unrelated processes by broad name matching.

The October 31 cleanup correction concerns shell commands left behind when Claude Code exits itself on macOS and Linux. It does not prove cleanup of every detached descendant or cancellation of work already submitted to a remote MCP service. Both require separate observations.

In a disposable fixture, a child can write a heartbeat only inside the fixture. After cancellation, observe that the heartbeat stops and the job-owned process ends. Use a mock for remote asynchronous tasks and verify their final state too. If cancellation is unsupported, record that limitation and choose a workload whose side effects remain acceptable. Preserve incomplete artifacts with an unmistakable failed status so downstream jobs never publish them as completed work.

10. Collect evidence that explains a refusal without collecting everything

Record task, version, configuration revision, resolved workspace, permitted tools, outcome and verifier result. These let an operator distinguish “the boundary worked” from “the model did not try” and “the collector lost the event.” A log of a refusal is valuable only when it can be tied to the attempted operation and independent resulting state.

Claude Code's monitoring reference documents claude_code.safety_event from v2.1.307 onward, but also lists calls without that event. Its own fields avoid raw command and path details; standard attributes can still contain workspace information, and optional tool-detail logging adds content. Do not label the entire stream anonymous or assume every rejection is represented.

Start with minimal metadata and a small set of synthetic fixture events. Protect the collector destination and retention policy. Check that logs arrive before using their absence as evidence. This CLI tool-decision evidence is different from API cost analytics; it helps explain execution boundaries, not reconcile an invoice or prove all external side effects.

11. Run a disposable acceptance matrix

Create a fresh temporary parent containing workspace/, sibling/ and results/. Put harmless sentinel text in the sibling and record its hash. Keep all test targets inside this parent; never substitute real credentials, home files or customer systems. The following is our proposed plan and has not been executed for this article.

CaseHarmless exerciseRequired observation
File-tool boundaryWrite inside workspace and attempt a sibling sentinel change.Permitted artifact appears; refused target hash remains unchanged.
Shell childA tiny fixture script attempts the same sibling write.The intended shell boundary blocks it; file-tool results are not reused as proof.
Added directoryExplicitly add a disposable directory and exercise its paths.Resolved access matches reviewed intent; unknown behavior stops rollout.
Unavailable sandboxUse a disposable runner missing its required dependency.Required isolation fails startup instead of silently falling back.
Startup and outputUse a synthetic local startup failure, then a known valid fixture task.Failure status is nonzero; success also passes JSON and artifact checks.
MCP interruptionA local mock records read-only, idempotent and other operations.Invocation counts and final state explain any repeat; no real side effects.
TimeoutCancel a short fixture-owned heartbeat process.No continuing heartbeat or owned process after the shutdown window.
Evidence pathTrigger one known refusal and one accepted fixture operation.Runner records, available telemetry and verifier state can be correlated.

Run the negative cases as seriously as the happy path. Preserve before-and-after hashes, the exact launcher flags and the policy source. Use a new fixture for each variant. Testing in an already broadened workspace can hide an overly generous additional-directory rule and produce a misleading pass.

12. Release a configuration bundle, then expand the workload

Bundle the CLI version, launcher, model selection, setting sources, managed policy expectations, MCP inventory, timeout policy and verifier. Give the bundle a revision and a rollback target. A dependency upgrade without its matching configuration can reintroduce discovery or change how a wrapper interprets failure.

Start with report-only or similarly reversible jobs. Promote the bundle after the required fixture cases pass on each intended operating environment, then observe a limited real workload. Define stop conditions in advance: an outside artifact changes, an unexplained process survives, a non-idempotent operation repeats, or a required configuration cannot be verified.

The remaining unknowns are practical release gates: the new write key's missing reference details, host-specific behavior, remote-job cancellation and telemetry completeness. An official release note establishes a change; your recorded tests establish only the exercised configuration and workload. Keep that scope visible when sharing results, and repeat the relevant cases after a CLI, wrapper, policy or integration update.