Building an efficient Content Pipeline with Claude Code: From PRs to Blog Drafts
I built a system that scans my GitHub PRs weekly, identifies content-worthy work, and generates blog drafts automatically. I call the pattern Quasi-Claw. I built a system to solve a problem most developers share: doing interesting work every week but never writing about it. The pattern β slash commands + LaunchAgents + CLI execution β turns Claude Code into a lightweight scheduled agent without any heavy framework or infrastructure. Here is how it works: π The Trigger: Every Friday at 5pm, a macOS LaunchAgent triggers Claude Code. π The Scan: It scans my GitHub repos and scores PRs/commits for "content potential." π¬ The Summary: It sends me a Slack digest of the week's best stories. π The Execution: I run a single command to pick an idea, generate a full blog draft from the actual source code, and push it to my siteβs API. The meta proof it works? This very post was identified and drafted by the system itself. #ClaudeCode #AI #BuildInPublic #Automation #SoftwareEngineering
I have a problem that I suspect a lot of developers share: I build interesting things every week but never write about them. The gap between "that was a cool technical decision" and "published blog post" is just too wide. So I built a system to close it.
The idea is simple: every Friday at 5pm, an automated process scans my GitHub PRs and commits from the past week, identifies anything that could become a blog post or portfolio project, and sends me a Slack summary. When I'm ready, I run a single command to review the ideas, generate a draft, and push it straight to my site's API as a draft post. This is actually the system that identified β and wrote β this very blog post.
The Two-Phase Pattern
I borrowed the architecture from a daily time-tracking system I'd already built with Claude Code. It follows a gather/confirm pattern:
PHASE 1 β AUTOMATED (FRIDAY 17:00) LAUNCHAGENT Cron Trigger CLAUDE CODE Scan Repos ANALYSE Score Ideas OUTPUT Ideas JSON SLACK Notify Nick Slack nudge PHASE 2 β MANUAL (WHEN READY) NICK /confirm REVIEW Pick Idea CLAUDE CODE Draft Post API POST Draft FILAMENT Publish The two-phase content pipeline β automated gathering, human-driven draftingPhase 1 (automated): A macOS LaunchAgent triggers Claude Code every Friday at 5pm. It runs a slash command (/weekly-content-gather) that scans my key active GitHub repos, analyses the PRs and commits, scores them for content potential, and writes the results to a JSON file. Then it sends me a Slack notification with the highlights.
Phase 2 (manual): When I'm ready to write, I run /weekly-content-confirm in Claude Code. It presents the ideas, I pick one, and it fetches the full PR details, reads the actual source code, and generates a complete blog draft. I can review, iterate, or skip. If I'm happy, it POSTs to my Laravel API as a draft.
The key insight is that not every week produces content-worthy work β and that's fine. The system handles zero-idea weeks gracefully instead of pressuring me to write about nothing.
The API Foundation
Before building the pipeline, I needed API endpoints that could accept content programmatically. I added two Sanctum-authenticated POST endpoints to my Laravel backend:
public function store(StoreBlogRequest $request): JsonResponse
{
$blog = Blog::create([
...$request->validated(),
'status' => PublishStatus::Draft,
]);
return response()->json([
'data' => (new BlogResource($blog))->resolve(),
'admin_url' => FilamentBlogResource::getUrl('edit', ['record' => $blog]),
], 201);
}
Two things worth noting here. First, the endpoint always forces PublishStatus::Draft regardless of what the client sends. Nothing publishes without me reviewing it in Filament first. Second, the response includes an admin_url β a direct link to the Filament admin edit page for that post. This means after the pipeline creates a draft, I get a clickable link to go add a featured image and hit publish.
Quasi-Claw: Commands + LaunchAgents
I've started calling this pattern "Quasi-Claw" β a play on "OpenClaw.β It's not as elegant as a fully autonomous agent, but it gets you 90% of the way there. Iβm quite keen to experiment with OpenClaw, but my current feeling is that Anthropic itself will be able to provide similar functionality sooner rather than later. As much as I love tinkering, Iβm more focused on outcomes.
The idea is simple: Claude Code slash commands are just markdown files in ~/.claude/commands/ that describe what you want done. LaunchAgents are macOS's built-in cron system. Combine the two and you get scheduled AI workflows that run unattended. I didn't find this pattern in any blog post or YouTube tutorial β it was just me identifying a problem (I never write about my work) and figuring out a solution that works with the tools I already had.
Here's the LaunchAgent plist that triggers the weekly scan:
<key>ProgramArguments</key>
<array>
<string>/Users/nickbell/.local/bin/claude</string>
<string>-p</string>
<string>run /weekly-content-gather</string>
<string>--allowedTools</string>
<string>Bash,Read,Write,Edit,Glob,Grep,Agent,...</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>5</integer>
<key>Hour</key>
<integer>17</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
The --allowedTools flag is crucial β it pre-authorises the tools Claude Code needs so the process can run unattended. Without it, the agent would block waiting for permission prompts that nobody's there to approve.
The Gathering Process
The gather command scans my active repos in parallel:
# GitHub PRs merged in the past 7 days
gh pr list --repo Nicholasbell03/personal-site \
--state merged --search "merged:>=2026-03-03" \
--json number,title,body,url,mergedAt,files --limit 50
# Git commits by me in the past 7 days
git -C /Users/nickbell/Dev\ Pvt/nickbell.dev/personal-site \
log --author="nickbell\|Nicholas Bell" \
--after="2026-03-03" --before="2026-03-10" \
--all --format="%H|%ai|%s|%D" --no-merges
Claude then evaluates each PR against criteria I defined in the command: interesting technical decisions, third-party integrations, architecture choices, problems others commonly face. Routine bug fixes, dependency updates, and config changes are explicitly filtered out. Each idea gets scored 1-5, and only ideas scoring 3+ make the cut.
The results are written to a structured JSON file:
{
"status": "PENDING_REVIEW",
"ideas": [
{
"id": "idea-1",
"type": "blog",
"title": "Fixing a Mermaid.js Race Condition in React",
"interest_score": 5,
"key_points": [
"Race between React rendering and mermaid initialization",
"Three iterations to solve: singleton, CSS, synchronous claiming"
]
}
]
}
The Confirmation Flow
When I run /weekly-content-confirm, it finds the most recent pending ideas file, presents them as a numbered list, and asks me to pick one. For the selected idea, it goes deep β fetching full PR diffs, reading 5-8 key source files from the actual codebase, and using all of that context to generate a technically accurate draft.
The draft gets POSTed to my API via curl with a Sanctum bearer token:
curl -s -X POST "https://api.nickbell.dev/api/v1/blogs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"title": "...", "content": "...", "excerpt": "..."}'
After posting, it updates the ideas JSON with the outcome and sends a Slack notification with the admin URL so I can go add a featured image and publish.
Lessons Learned
The gather/confirm split is essential. I initially considered making it fully automated β scan and draft in one step. But content creation needs human judgement. Some weeks the "interesting" PR is actually boring, and sometimes a small commit hides a great story. The two-phase approach costs almost nothing (one extra command) and prevents bad content from clogging up my drafts.
Pre-authorising tools for background agents is non-obvious. LaunchAgent processes run without a terminal, so any tool that requires interactive approval will silently hang. The --allowedTools flag was the key to making this work unattended.
Forcing draft status on the API was the right call. It would be tempting to let the automation publish directly, but blog posts need featured images, final proofreading, and sometimes timing. The draft-only API plus the admin_url in the response creates a smooth handoff between automation and human review.
What's Next
The system has been running for a week and already surfaced three content ideas from work I would have otherwise forgotten about. The meta twist β that this blog post was itself identified and drafted by the system β feels like a good validation that it works.
If you're using Claude Code, the Quasi-Claw pattern β slash commands plus LaunchAgents β is a surprisingly powerful way to create semi-automated workflows. The commands are just markdown files describing what you want done, Claude handles the execution, and LaunchAgents handle the scheduling. No framework, no infrastructure, no blog post that told me to do it this way. Just a problem and a solution.
You might also like
blog A Developer's AI Workflow: From Voice Dictation to Automated Reviews
The AI toolkit and workflow behind building three repositories, 347 commits, and a full-stack portfolio in under a month of part-time work β Claude Code, voice dictation, automated reviews, and more.
blog How I Built a Full-Stack AI Portfolio for Under $1/Month
Four hosting services, three repositories, an AI chatbot, semantic search, and cross-device content sharing β practically free.
blog Building an AI Portfolio Agent with Laravel, pgvector, and Gemini
A chatbot that knows everything I've written β built with the Laravel AI SDK, pgvector embeddings, hybrid search, and Gemini's free tier.