My work spans multiple companies and software projects, often with several Claude and Codex sessions running at the same time. Each project has a different user, business definition, technical constraint, maintenance owner, and finish line. Take an unnamed example where a team asks for an internal status dashboard so managers can stop chasing project updates in chat, while a session in another repository modifies a webhook retry worker and a third updates role permissions in an admin tool. All three sessions can return clean diffs, passing local tests, and confident summaries before you have finished reading the first one.

In Critical thinking when agents do the work, Addy Osmani names the constraint that governs parallel agent workflows: "Even if you are running many agents at a time, you still only have one pair of eyes on the outputs." Execution can run in parallel across terminals, while human judgment stays serial. When an agent produces a well-formatted patch and a plausible explanation, nothing in the interface forces you to slow down before moving to the next waiting terminal.

Switching between companies makes that speed harder to handle because your working memory of each system starts cold. Moving from one company's reporting tables to another company's queue worker means . A fluent summary from the session that just edited the files feels like warm context, so it is easy to adopt the agent's framing instead of checking the original source files and runtime behavior yourself. Accepting work that another team will rely on or maintain requires rebuilding enough of the problem, the design tradeoffs, and the supporting evidence to own the decision.

Diagram showing three parallel project tracks on the left and a single active project view on the right containing original intent, source files and logs, unverified live check, and next decision.
Three project sessions can run in parallel, while returning to any one project requires rebuilding its context from the saved intent, source files and raw logs, and remaining live checks before making the next decision.

How do I know that I'm working on the right problem?

A fast implementation of the wrong fix wastes more time than a slow start, especially when you are splitting attention across projects. Before sending a prompt or approving a plan, I want to answer one question directly: Both choices are useful when they are deliberate. When the problem and scope are already settled, such as renaming an environment variable across twenty files, formatting test fixtures, or generating a typed client from an existing schema, offloading the work and scanning the diff is the right call. Adding ceremony to every small edit would defeat the purpose of running agents.

Offloading turns into a trap when the problem itself is still a guess. In the status dashboard example, someone asks for a page showing project health so leadership can stop asking for updates in chat. If you pass that request straight to Claude or Codex as a build ticket, the agent can resolve ambiguities on its own, create a read-only dashboard view over the projects table, and hand back a working page. Yet if project leads keep their updates in chat threads because nobody is assigned to update the tracker or the form takes ten fields to save, the new dashboard will display empty or stale rows. The code works, while the underlying workflow problem remains untouched.

When the root cause is uncertain, use the agent for problem discovery before allowing code changes. Start by stating a short hypothesis about what is failing, which source table or workflow rule defines the expected behavior, and what evidence would prove your guess wrong. You can then ask the agent to inspect the current data (for instance, counting how many active projects have recorded a status update in the last fourteen days), interview you about missing constraints, challenge your hypothesis, and lay out alternative causes. Independent thinking includes changing your mind when the evidence points somewhere else: .

How do I know that I'm solving it the right way?

Once discovery shows what actually needs to change, the implementation has to fit the constraints of that specific company and the people who will maintain the code after you move on. In the status workflow example, if updates are missing because no single person owns them and the form is too heavy, assigning one status owner per project and sending a short weekly prompt that writes their reply into the existing project record gives you a concrete design to test before building a standalone dashboard. That option leaves the maintaining team with less surface area to support, though the team's actual workflow and constraints still determine whether it fits.

Even on a well-scoped backend task, an agent session makes dozens of quiet design choices across a long run. It picks default values, chooses how errors propagate, copies patterns from older directories, and resolves conflicting constraints by relaxing one of them. Take the webhook retry worker from the opening example, and assume the production worker runs inside a queue consumer with a 60-second visibility timeout while downstream endpoints occasionally return temporary 503 errors. An agent asked to stop dropping events can wrap the HTTP call in an in-memory backoff loop that waits up to 90 seconds, and a unit test with mocked timers may pass.

In production, however, holding the job past the assumed 60-second visibility window lets the queue lease expire so the message can become visible to another worker while the first attempt is still waiting. That makes duplicate webhook deliveries possible even when the downstream receiver is idempotent; idempotency on the receiver only prevents those duplicate deliveries from causing repeated effects. Moving retries back to the queue with explicit attempt counts and backoff metadata removes the 90-second in-memory wait between attempts, yet an individual request can still exceed the 60-second lease; in this illustrative design, request execution and timeouts must be bounded below the lease window with processing margin, or the worker must extend visibility before the lease expires.

Is there evidence that supports my conclusion?

A green check at the end of an agent run supports only the behavior that the check actually exercises. Existing tests can provide useful evidence when they cover real database constraints, serialization rules, or API contracts, and new tests written for a change can add coverage for the new path as well. The risk of a shared mistaken expectation appears when the same agent session writes both the feature code and the new verification tests from a single prompt without an independent anchor.

Before reading the agent's prose summary, inspect the exact commands it ran and their raw output. Ask what a passing check proved and what it left untested. In the status workflow example, a test that writes a fixture project row and reads it back verifies the read and write path on that chosen fixture. A query against staging or production records checks field completeness on existing rows, such as whether owner and timestamp columns are populated, which is still distinct from the business result of whether teams keep updates current without chat follow-ups. The same discipline applies when an agent synthesizes customer notes, logs, or financial tables across companies: open two or three original source records yourself and trace the numbers by hand to confirm the summary matches the underlying files.

How do I know that I'm finished?

Every project has its own finish line, depending on who uses the work and who owns it next. A quick exploratory query for an internal discussion, a pull request handed to a client's engineering team, and a live workflow change each require a different standard of proof. Stopping when the terminal stops streaming or when local unit tests pass confuses code generation with completion. Passing local checks proves local behavior; it does not establish that a live integration works in the target environment.

In the status workflow example, the change is not finished when the handler passes a mocked test on a laptop. A live completion check means verifying that the scheduled prompt reaches a real test channel, that a reply updates the target record with the status owner and timestamp, and that the team maintaining the service can see failed writes in their existing alerts. Where a live production check cannot run until a later deployment window, the handoff should state what remains unverified and who owns running that check when the deployment finishes.

Working across multiple companies adds a second requirement to finishing well: being able to return to the project days later without losing the thread. When you switch away to two other codebases and come back on Thursday when a maintainer asks why a query changed, you should not have to reread a long chat transcript to reconstruct your reasoning. Leaving a short note alongside the work (recording the task intent, key assumptions, paths to authoritative source files, raw check outputs, and the next decision) gives you a fast way back into the problem. When finished diffs start piling up faster than you can inspect their evidence, pause new sessions until you have reviewed the work already on your desk.

Diagram pairing four review questions with their corresponding actions: inspect usage and owner, compare tradeoffs and limits, read raw logs and records, and verify live and record next step.
Each of the four review questions maps to a concrete inspection step before accepting an agent's output.

Fresh-context review at session checkpoints

When a task is substantial enough that you want a second pass before your own final review, running that pass inside the same long session has a structural weakness. As a Claude or Codex session runs across dozens of turns, compacts its history, or adapts to a changed premise, its context accumulates earlier failed attempts and the step-by-step rationale for every compromise it made. Asking that same session whether its work is ready invites it to evaluate the diff through the narrative it already built. Delegating a read-only review to a fresh context strips away that conversation history so the reviewer judges the work against the requirements and the files.

Running a separate review on every turn would add cost and latency during routine exploration, so it works best at clear checkpoints: after context compaction, after a long stretch of transcript growth, when the premise of the task changes, or at a substantive milestone before handoff. In the Claude Code example below, a lightweight Python command hook runs on PreCompact and Stop. PreCompact marks a review pending in a local session cache, while Stop checks whether a review is pending or the session transcript has grown by 160,000 new bytes since the last review request (exiting immediately when stop_hook_active is true or background tasks are still running). The 160,000-byte figure is an adjustable heuristic for accumulated session activity rather than a model quality threshold. Because the shell check is cheap, it can run on every Stop and only inject instructions to spawn the read-only checkpoint-reviewer subagent when a checkpoint trips. In Codex, you can apply the same checkpoint rule in AGENTS.md and run the review in a fresh subagent or a new chat session.

To keep the checkpoint review independent, the parent session passes only a restricted packet: the original request, the acceptance criteria, paths to the authoritative source files, the complete working-tree changes (including staged diffs and full untracked files), the raw outputs from tests and builds run on that exact state, and any open unknowns, omitting the chat transcript and the parent agent's verdict. In the hook cache, review_requested records only that the dispatch instruction was injected; a checkpoint is not complete until the fresh reviewer returns its report, any confirmed defects are fixed, and the verification checks pass on the updated files.

Use the fresh reviewer to catch missing checks and unstated assumptions early, then do your own check on the decisions that matter. Before starting or approving your next non-trivial session, write down in two sentences what problem needs solving and what raw output will prove the fix works in its target environment, and read that output before the agent's summary.

The source explorer below contains the complete Claude Code checkpoint hook (checkpoint.py), the settings.json hook configuration, the parent dispatch.txt prompt, the read-only checkpoint-reviewer.md subagent definition, and the equivalent Codex AGENTS.md checkpoint block.

View complete source files

To use this checkpoint pattern in a Claude Code repository, keep examples/review-checkpoint/checkpoint.py and examples/review-checkpoint/dispatch.txt in your project, save the subagent definition at .claude/agents/checkpoint-reviewer.md, and merge the PreCompact and Stop entries from examples/review-checkpoint/settings.json into .claude/settings.json. If .claude/settings.json already defines hooks or permissions, append these handler objects to the existing PreCompact and Stop arrays rather than overwriting the file. Claude Code resolves $CLAUDE_PROJECT_DIR to the project root and merges hook configurations across user, project, and local settings files (hooks configuration reference, subagents guide).

Because Claude Code invokes Stop handlers at the end of every turn, checkpoint.py keeps the shell check lightweight and only triggers a review when a checkpoint is due. It hashes session_id to store per-session state under ${XDG_CACHE_HOME:-~/.cache}/review-checkpoint/ via atomic file replacement. On PreCompact, the script sets pending: true so a review runs at the next stop after compaction completes. On Stop, it exits early if stop_hook_active is true or background_tasks is non-empty (Stop input schema), and otherwise checks whether pending is set or transcript_path has grown by at least GROWTH_BYTES = 160_000 new bytes since last_requested_bytes (measuring from zero if compaction shrank the transcript). Those 160,000 bytes are an adjustable heuristic for session growth rather than a token count or model-quality threshold. When the gate trips, the script records status: "review_requested" and prints dispatch.txt inside hookSpecificOutput.additionalContext (Stop decision control), instructing the parent session to assemble the scoped evidence packet and ask Claude to use checkpoint-reviewer in a fresh context (tools: Read, Grep, Glob, model: inherit, preserving CLAUDE.md instructions; frontmatter reference). At any project milestone before the byte threshold trips, you can also ask Claude directly to run checkpoint-reviewer.

These files are included under examples/review-checkpoint/ as a reference implementation and are not installed in .claude/settings.json in this repository. Local script verification covers piping synthetic PreCompact and Stop JSON payloads into python3 examples/review-checkpoint/checkpoint.py with a temporary XDG_CACHE_HOME and transcript file to check stop_hook_active exits, background_tasks deferral, byte-growth and post-compaction size reset math, and the emitted hookSpecificOutput JSON. A live end-to-end Claude Code session that compacts context or crosses 160,000 transcript bytes and automatically dispatches checkpoint-reviewer has not been run here.

settings.json
{  "hooks": {    "PreCompact": [{      "hooks": [{        "type": "command",        "command": "python3 \"$CLAUDE_PROJECT_DIR/examples/review-checkpoint/checkpoint.py\""      }]    }],    "Stop": [{      "hooks": [{        "type": "command",        "command": "python3 \"$CLAUDE_PROJECT_DIR/examples/review-checkpoint/checkpoint.py\""      }]    }]  }}