Keep Claude Code on One Task per Session
Give the session one observable finish line
My most productive Claude Code sessions end with a small diff, not an architectural surprise. The trick is defining the finish line before opening the agent. Here is a reproducible example: make a slug helper return untitled for whitespace-only input, without changing its existing behavior for ordinary titles.
We will create a tiny repository, write the acceptance tests ourselves, and let Claude change exactly one implementation file. Use a disposable directory so the commands do not touch your current project.
Connect Claude Code through Fluxo
Install Claude Code with npm, then configure your relay credentials in the same terminal. These commands assume Bash and an installed Node.js runtime.
npm install -g @anthropic-ai/claude-code — read -rsp 'Fluxo API key: ' ANTHROPIC_API_KEY; printf '\n'; export ANTHROPIC_API_KEY
export ANTHROPIC_BASE_URL=https://api.fluxorelay.com — Copy the exact model identifier from Fluxo rather than guessing it from a display name. Claude Sonnet 5.5 is one concrete choice for this walkthrough.
read -rp 'Fluxo model identifier: ' CLAUDE_MODEL; export CLAUDE_MODEL
Fluxo gives me one key and one base URL for Claude, GPT, Gemini, DeepSeek, Kimi, GLM, Qwen, Grok, and more. It works with Claude Code, Codex, Gemini CLI, and any OpenAI SDK. Billing follows real tokens, including cache reads and writes, with no monthly fee. Users also earn a referral share when people they invite pay.
If you want to follow along through the same relay, create a Fluxo account and copy your key.
Build a two-test boundary around the slug fix
Create the repository and its deliberately incomplete implementation. The .mjs extension keeps this example independent of package configuration.
mkdir fluxo-focused-session && cd fluxo-focused-session — git init && git switch -c fix/empty-slug
mkdir -p src test — printf '%s\n' 'export function slugify(input) {' ' return input.trim().toLowerCase().replace(/\s+/g, "-");' '}' > src/slug.mjs
Now add one regression test and one acceptance test. The second test should fail before Claude touches anything.
printf '%s\n' 'import test from "node:test";' 'import assert from "node:assert/strict";' 'import { slugify } from "../src/slug.mjs";' 'test("ordinary titles keep their slug", () => {' ' assert.equal(slugify(" Hello World "), "hello-world");' '});' 'test("whitespace becomes untitled", () => {' ' assert.equal(slugify(" "), "untitled");' '});' > test/slug.test.mjs
node --test test/slug.test.mjs — That failure is useful: it makes success measurable instead of leaving Claude to invent a broader interpretation of “improve slugs.”
Put the scope into CLAUDE.md before launching
Repository instructions make the boundary visible when the session starts. They are guidance, not a security sandbox, so review the resulting diff anyway.
printf '%s\n' '# Session scope' 'Task: return untitled when slugify receives whitespace-only input.' 'Edit only src/slug.mjs.' 'Preserve ordinary-title behavior.' 'Do not modify tests, add dependencies, reformat unrelated code, or commit.' 'Run node --test test/slug.test.mjs before finishing.' 'Stop after reporting the change and test result.' > CLAUDE.md
Save a baseline so every subsequent change is easy to inspect. The temporary identity below applies only to this commit.
git add src/slug.mjs test/slug.test.mjs CLAUDE.md
git -c user.name='Session Demo' -c user.email='[email protected]' commit -m 'Add focused slug fixture'
Launch once, implement once, then inspect
Start a fresh session with a prompt that repeats the acceptance condition. Do not append your backlog.
claude --model "$CLAUDE_MODEL" 'Read CLAUDE.md. Fix only the whitespace-only slug case in src/slug.mjs. Run the specified test command, report the result, and stop. Ask before expanding scope.'
Review proposed commands and edits rather than bypassing permission checks. After Claude finishes, exit the interactive session and verify independently:
node --test test/slug.test.mjs — git status --short
git diff --check — git diff -- src/slug.mjs
Start the next fix without carrying this session forward
If Claude suggests punctuation handling or Unicode normalization, capture that separately. Neither belongs in this patch. Check that only the implementation changed and both tests pass.
For the next task, update CLAUDE.md and launch a new claude process without --continue or --resume. A compacted conversation is still the same conversation; a new session gives the next task a cleaner boundary. Small scope, explicit tests, reviewed diff, stop: that is the whole loop.