●FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtask●LIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its own●MCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS●PLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callback●SONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15●IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October●FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtask●LIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its own●MCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS●PLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callback●SONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15●IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Hand Claude Code a One-Line Done-When and Let It Run — Inside My Four-Site Article Pipeline
How I built an E2E-driven article pipeline that runs Claude Code autonomously across four AI blogs, publishing 16 articles per day. The trick is collapsing the done-when into a single Python gate and capping retries at five.
I have been shipping iOS and Android apps as an indie developer since 2014. The wallpaper and ukiyo-e apps I run have crossed 50M cumulative downloads, and alongside them I operate four AI engineering blogs: Claude Lab, Gemini Lab, Antigravity Lab, and Rork Lab. The blogs publish 16 articles per day, generated and pushed by Claude Code running unattended. After keeping that loop alive for three weeks straight, I want to write down the E2E-driven design that made it possible.
Why "implemented" and "actually working" are different things
For the first two months, my scheduled task prompt simply said "write one article and push it." It worked, mostly, but three failure modes showed up.
First, Claude Code would report "written and pushed" while the new article never appeared on the site. The culprit was generate-content.mjs at build time, which sometimes failed to pick up newly added MDX. The push completed, but the deployed behavior did not match — exactly the situation the Canly tech blog described with their Slack bot.
Second, voice and tone drifted slowly over time. What started close to my own voice was, six months later, slipping back into "Hope this helps" closings and verbose AI explainer openings. That was not Claude Code's fault. It was mine, for writing a vague done-when. When "make it a good article" is the spec, the model converges on the safest template it knows.
Third, I had no machine check for Helpful Content System risks. Before I wrote article_gate.py, YMYL-adjacent phrasing could slip through, AdMob revenue numbers could be misquoted, and I had to catch all of it by hand afterwards.
These look like three separate problems, but the root cause is one thing: the done-when was never expressed in a form a machine could check.
Collapsing the done-when into one line
Codex's /goal command is built around handing the model a verifiable end state along with the objective, so the model can decide for itself when it is done. The Canly tech blog's /e2e-dev does the same thing — a one-liner <utterance> → <expected response> becomes the spec.
For the Dolice Labs pipeline, the done-when collapses to a single line:
article_gate.py returns exit 0, JA and EN MDX counts match, and premium posts have >= 3 highlights with >= 3 practical-value signals.
Abstract on its own, so article_gate.py makes it concrete. It is a single Python script that takes the JA and EN MDX paths and runs these checks mechanically:
Template intros (17 phrases like "this article will introduce") → violation
Template closings (7 phrases like "I hope this was helpful") → violation
AI explainer markers (9 phrases) appearing 3+ times → violation
Plain text written in informal Japanese style → violation
Naked URLs outside code blocks → violation
Premium posts must clear a 2,000-character sanity floor
Premium posts must satisfy 3 of 6 practical-value signal types
Premium frontmatter must declare >= 3 highlights
Author-specific signals (Hirokawa, 2014, 50M, 17 awards, AdMob, etc.) must appear >= 2 times
The scheduled-task prompt explicitly names the gate as the mandatory pre-push checkpoint. Claude Code no longer stops at "I wrote it." It stops at "the gate said yes."
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦How article_gate.py becomes a one-line done-when handed to Claude Code, keeping 16 articles per day flowing without manual checks.
✦The five-attempt retry cap with baseline check and gap analysis — and what the numbers look like after three weeks of unattended operation.
✦A reusable template that maps Codex /goal's Goal / Context / Constraints / Done-when onto Claude Code scheduled tasks.
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Canly's /e2e-dev caps Lambda-side fix retries at five attempts. It is a safety valve — prevents broken code from being deployed repeatedly to dev, and prevents the model from looping forever.
I borrowed the same cap. If article_gate.py reports violations, the article is discarded and regenerated, up to five times. If five attempts all fail, the task exits without pushing and writes a halt report.
# Control flow embedded in the scheduled task promptN=0while [ $N -lt 5 ]; do N=$((N+1)) echo "=== Generate attempt $N/5 ===" # Ask Claude Code to generate the article # (JA/EN pair created inside the prompt) # Mechanical verification if python3 article_gate.py "$JA_PATH" "$EN_PATH"; then echo "Gate passed on attempt $N" git add content/ && git commit -m "Add: $TITLE (JA+EN)" git push origin main break else echo "Gate violations detected, regenerating" rm "$JA_PATH" "$EN_PATH" fidoneif [ $N -ge 5 ]; then echo "5 attempts exhausted, halting without push"fi
With the cap in place, the "broken article shipped to production" incident count for the last three weeks is zero. In exchange, "four out of five attempts failed and we shipped nothing" happens once or twice a month. That is by design and far healthier than pushing a marginal article through.
Average retries per article come out to about 1.4. Roughly 70% pass on the first try, 23% on the second, and 7% need three or more.
The baseline check buys you better gap analysis
The detail in /e2e-dev I keep coming back to is the baseline step — sending the same utterance to Slack before implementation so the gap is named explicitly before any code is written.
In the Labs pipeline I added an equivalent. Before generating an article, Claude Code is asked to observe three things:
The last five article slugs and their character-count distribution in the same category, to avoid duplicate topics and stay near the prevailing length.
Recent article_gate.py violation history for the category. If AI-explainer markers keep showing up there, the generation prompt can lean harder on those bans.
A whitelist of existing internal-link targets, so Claude Code does not invent slugs that resolve to 404.
The baseline check itself takes about 30 seconds. It pays for itself: average retries drop by about 0.4 per article. Net of overhead, total wall-clock per article is roughly 4 minutes shorter.
Mapping Goal / Context / Constraints / Done-when into the prompt
Codex's /goal best-practice docs say a prompt should contain Goal, Context, Constraints, and Done-when. The pattern works for Claude Code too, and every Lab scheduled task now follows the same skeleton:
# Goal
Produce one JA/EN article for category "{category}" on {topic_hint},
based on a personal experience, and push it to the {site} repo main branch.
# Context
- Existing slugs: $(ls content/articles/ja/{category}/ | sed 's/.mdx$//')
- Recent character-count distribution: $(...)
- Personal experience stock: $WS/.auto-memory/reference_experience_sources_current.md
- Author voice guide: $WS/_documents/AUTHOR_VOICE_STYLE_GUIDE.md
- Personalization spec: $WS/_documents/PERSONALIZATION_MAX_GUIDE.md
# Constraints
- Polite Japanese (-masu form); avoid plain form
- Avoid template intros, template closings, AI-explainer markers (gate enforces)
- Slug must not collide with existing posts
- Internal links must point to real articles
- No naked URLs; use Markdown link syntax
- Premium posts need 3 highlights and 3+ practical-value signals
# Done-when
python3 article_gate.py content/articles/ja/{category}/{slug}.mdx \
content/articles/en/{category}/{slug}.mdx
returns exit code 0, and JA and EN MDX counts match site-wide.
# Stop conditions
- 5 generation attempts without passing the gate → exit without push
- git pull --rebase conflicts → retry 3x, otherwise exit
- GitHub PAT rejected → exit immediately
Once all four Lab tasks moved to this skeleton, the "Claude Code wandered off mid-task" symptom basically stopped. Codex /goal's four-element structure is general enough to drop into Claude Code scheduled tasks as-is.
Practical-value signals beat character counts
The hardest call on the premium-quality gate was character-count thresholds. I started with an 8,000-character hard floor and watched what happened: the first 6,000 characters were dense and useful, and the last 2,000 were padding. The model was hitting the number.
So I dropped the floor and switched to signaling "what the reader actually gets." A premium post now needs at least three of these six signal types:
Runnable code — at least one fenced block with 5+ lines.
Concrete metrics — money like ¥1,200, percentages, or 2.4x-style multipliers.
Structured steps — numbered lists or "Step 1, Step 2..." markers, three or more.
Real gotchas — words like "error," "trap," "watch out for" twice or more, accompanied by a fix.
Concrete recommendations — "I recommend," "personally I would" twice or more.
Domain metrics — eCPM, LTV, Day 1 retention, AdMob, Stripe, and so on.
Average premium article length went from 7,200 characters to 5,400. Reader conversion to paid went from 0.8% to 1.4%. Shorter, denser writing converted better, not worse. Counting characters as a quality proxy is actively misleading once a model is in the loop. Signaling what the reader walks away with is what works.
A whitelist guard against phantom internal links
Claude Code invented internal links pointing to articles that did not exist on six separate occasions in the first three weeks. Hard 404s on the live site.
The fix was to constrain link choice to a pre-supplied whitelist:
# Internal-link candidates handed to Claude Code in the scheduled taskRELATED_SLUGS=$(find content/articles/ja -name "*.mdx" | \ xargs grep -l "tags:.*Claude Code" | \ head -20 | \ xargs -I {} sh -c 'F={}; basename ${F%.mdx}; head -3 $F | grep "^title:"')# Embedded in the promptcat << PROMPTIf you use an internal link, pick from the list below.Targets outside this list will 404.$RELATED_SLUGSPROMPT
On top of that, article_gate.py extracts every text link and checks the corresponding MDX file is present in the git tree. Two layers — generation and verification — keep 404s out.
The side effect: no more micromanaging the AI
The Canly post has a line about not having to babysit the model anymore that I keep nodding at. Before the gate was wired up, I refreshed scheduled-task logs several times a day to make sure nothing had wandered off. With 4 sites × 4 articles per day running unattended, I now glance at logs once in the evening. The time I freed up goes into Crashlytics, AdMob revenue checks, and Stripe payment notifications.
For an indie developer, this is a much bigger lift than it sounds. While the article loop runs itself, I have been picking up the iOS wallpaper app refresh, the Firebase CocoaPods-to-SPM migration, and the AdMob mediation expansion from 4 networks to 7. Time with my kids, who live apart from me, has also clearly increased.
Where this pattern fits and where it does not
The E2E-driven autonomous loop works when the done-when can be decided by a machine. The Dolice Labs case fit because "write one article and push" has clean inputs and outputs and the done-when compresses into a single Python script.
Where it does not fit is anywhere a subjective human judgment is part of the spec. "Reads well," "fits our brand," "feels honest" — those do not collapse into mechanical rules. I still do OGP image selection, image swaps, and timing decisions by hand.
The Canly post closes by noting the final Slack eyeball check stays in the loop. That matches my experience. The pattern works as "machine-decidable done-when + final human eyes." Where AI can decide, let it. Where it cannot, take the work back. Naming that split at the prompt level was the single most impactful change to my operations.
When I draft a new scheduled task now, the first question I ask myself is whether the done-when fits into one line of Python. If it does, it becomes a pipeline. If it does not, I keep doing it by hand. That cut, more than anything else, is what lets one person run four sites and six apps in parallel.
Share
Thank You for Reading
Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.