Run by Claude

What Claude Built While I Was at Lunch

Full build log: cross-platform social automation, CDP commenting when APIs fail, a 12-template image pipeline, and what I learned about running an AI-operated agency.

MurphApril 21, 20265 min read

I left Claude running while I went to lunch.

Came back to find it had built a complete cross-platform social media automation system. Posting, commenting, replying, threading — across X, Facebook, and LinkedIn. With branded images on every post.

Here's the full build log. The wins, the failures, the workarounds, and what I learned.

The Problem

We run an AI-powered agency. Claude Code is the operator — it handles client work, content creation, email marketing, website updates, everything. But social media was half-automated. We could post to X and Facebook, but couldn't comment, reply, or engage programmatically. Three platforms, three different auth systems, three different API quirks.

The goal: post to every channel, reply to comments, build threads, engage with mentions — all autonomously. No manual Canva. No copy-pasting between tabs. No "I'll do it later."

X/Twitter: OAuth 1.0a from Scratch

X's API uses OAuth 1.0a, which means HMAC-SHA1 signatures on every request. If you've never implemented this, here's what it involves:

  1. Collect all OAuth parameters (consumer key, nonce, timestamp, token, signature method, version)
  2. Collect all request parameters (query params + body params)
  3. Sort ALL of them alphabetically by key
  4. Percent-encode every key and value
  5. Join them with &
  6. Build the signature base string: METHOD&encoded_url&encoded_params
  7. HMAC-SHA1 that with consumer_secret&token_secret
  8. Base64 encode the result
  9. Add it to the Authorization header

One wrong encoding anywhere = 401 Unauthorized. No error message telling you what's wrong.

We built this from scratch in a Next.js API route. The v2 API handles tweets and replies. The v1.1 API handles media upload (images). The two APIs use different auth patterns but the same signature method.

What works now: Posting with images, replying to tweets, building threads on our own posts, searching for conversations, monitoring @mentions. All via production API endpoints.

Facebook: The Six-Hour War

This was the hard one.

Facebook's Graph API needs a Page Access Token with pages_manage_engagement scope to comment on posts. Sounds simple. It wasn't.

The Trap

Our Facebook app (created through Meta's developer portal) had "use cases" attached to it — Marketing API, Meta Ads Manager, Threads API. These use cases auto-inject their required scopes into every OAuth flow. One of those scopes, pages_read_user_content, is invalid for our app type.

When you request OAuth authorization, Facebook checks ALL scopes from ALL use cases, finds the invalid one, and shows "Invalid Scopes" error. This blocks pages_manage_engagement from ever being granted.

What We Tried (All Failed)

  • Graph API Explorer: Same error. The Explorer's OAuth popup inherits the app's use cases.
  • Server-side OAuth flow: "Can't load URL" — redirect URI wasn't registered. Fixed that via API.
  • Remove use cases via API: No endpoint exists. Facebook doesn't expose use case management programmatically.
  • Remove use cases via UI: The portal UI marks them as "Required for use case" with no delete option. Meta locked them.
  • Enable API access to app settings: Found the toggle in Advanced Settings, enabled it, set valid_oauth_redirect_uris and app_domains. OAuth still failed.
  • Switch to a different app in the Explorer: Other apps don't have pages_manage_engagement configured.
  • Revoke all user permissions and re-auth: Clean slate, same error.
  • auth_type=rerequest: Same error.
  • Create a new app: Developer portal's create page renders blank in headless Chrome.

15+ approaches. Six hours. All failed at the same wall: pages_read_user_content.

The Solution: Chrome DevTools Protocol

If the API won't cooperate, use the browser.

Chrome's DevTools Protocol (CDP) lets you control Chrome programmatically via WebSocket. Navigate to pages, execute JavaScript, dispatch mouse and keyboard events.

Here's the flow:

  1. Copy the logged-in Chrome profile to a new data directory
  2. Launch headless Chrome with --remote-debugging-port=9444
  3. Navigate to the Facebook post
  4. Find the [contenteditable="true"] comment field via Runtime.evaluate
  5. Click it with Input.dispatchMouseEvent
  6. Type the comment with Input.insertText
  7. Press Enter with Input.dispatchKeyEvent
  8. Verify the comment appeared in the DOM

No OAuth token. No pages_manage_engagement. No Graph API. Just browser automation using the logged-in session's cookies.

This is the same pattern we use for LinkedIn commenting via LinkedIn's internal Voyager API.

LinkedIn: CDP + Voyager API

LinkedIn's official API for commenting requires their "Community Management API" product, which needs approval. We applied. Still waiting.

In the meantime, the Voyager API (LinkedIn's internal browser API) works perfectly from within a CDP session. The flow:

  1. Navigate to linkedin.com in the CDP browser (logged in via cookies)
  2. Extract the JSESSIONID CSRF token from cookies
  3. Call the Voyager comments endpoint with the CSRF token
  4. Parse the response for comment data
  5. Post replies with the comment mutation endpoint

It's not the official API, but it's the same API LinkedIn's own web app uses.

The Image Pipeline

Every post needs a branded image. Not the default OG card. Not a stock photo. A custom, scroll-stopping graphic generated specifically for that post's content.

We built 12 templates using Satori (the SVG-to-image library from Vercel):

  • quote_card — Bold text with optional headshot
  • stat_card — Big number with trend indicator
  • list_card — Numbered items with accent highlights
  • bar_chart — Horizontal bars with labels
  • insight_card — Centered text, clean and bold
  • comparison_card — Side-by-side before/after
  • step_card — Numbered how-to steps
  • data_table — Comparison table with headers
  • progress_card — Metric with segmented bar
  • workshop_promo — Event card with CTA
  • carousel_cover — Bold title card
  • testimonial_card — Quote with stars

Every template includes:

  • Dark background (#080A0F) with subtle gradient
  • Green accent (#00FFB2)
  • Space Grotesk headings, Inter body text
  • VT logo + "Powered by Claude" watermark
  • Corner accents and dot grid pattern

Generated in under 2 seconds via API. 1080x1080 for social, 1200x675 for X/LinkedIn landscape.

Observations

1. CDP is the universal automation fallback. When APIs fail — and they do, constantly — the browser is always there. Every platform has a web UI. Every web UI can be automated. The skill gap in automation isn't "knowing the API." It's knowing what to do when the API doesn't work.

2. Facebook's developer portal is hostile to automation. React apps that don't render in headless browsers. Settings pages that redirect to dashboards. Use cases that can't be removed. API access toggles that don't persist. It felt intentionally designed to require human interaction at every step.

3. Image generation is a first-class feature, not an afterthought. The difference between a post that gets scrolled past and one that stops the thumb is the image. Auto-generated, branded images on every post. No exceptions. No "I'll add one later."

4. LaunchD > Cron for macOS services. LaunchD agents with KeepAlive restart automatically if they crash. The Chrome CDP instance runs 24/7. If Chrome dies, launchd brings it back.

5. OAuth is the hardest part of any integration. Not the API calls. Not the data modeling. The auth flow. Every platform does it differently. Every platform has edge cases. Every platform has undocumented requirements. Building the OAuth 1.0a signature from scratch took longer than building the entire posting system.

What's Running Now

  • X: Post with images, thread, reply, search mentions — all via production API
  • Facebook: Post with images (Graph API), comment (CDP)
  • LinkedIn: Post via Zapier, comment (CDP)
  • Images: 12 templates, auto-generated, branded
  • Chrome CDP: Running 24/7 via LaunchD on port 9444
  • LinkedIn monitor: LaunchD agent checking comments every 3 hours

This is what an AI-run agency looks like in practice. Not a demo. Not a prototype. Production infrastructure, running autonomously, handling real engagement across real platforms.

The content creation is the easy part. The plumbing is where the engineering lives.

Chrome DevTools Protocol lets you control Chrome via WebSocket. You navigate to a page, find DOM elements, click them, type text, and submit forms — all programmatically. It uses the browser's existing login session, so no separate OAuth tokens are needed. The Graph API requires pages_manage_engagement scope, which our app can't obtain due to locked "use cases" that inject an invalid scope. CDP bypasses this entirely by using the browser session directly. Satori is a library from Vercel that converts React JSX elements to SVG, which can then be rendered as PNG images. It runs server-side and supports custom fonts, layouts, and styling — perfect for generating social media images programmatically.

Want to see how your business stacks up?

Get a free brand audit — we'll show you what's working, what's not, and what to fix first.

Free Brand Audit →
Jason Murphy

Written by

Murph

Jason Matthew Murphy. Twenty years building digital systems for businesses. Former CardinalCommerce (acquired by Visa). Now running VibeTokens — a brand agency for small businesses that builds websites, content, and growth systems with AI.

Live Workshop · April 27

Build your Claude OS in 4 hours. CLAUDE.md, MCP servers, 3 custom workflows. 8 seats, $247.

Reserve Seat →

Your brand is your first impression.

Find out if it's costing you customers.

Free brand audit. We analyze your online presence, competitors, and messaging — then tell you exactly what to fix.

Get Your Free Brand Audit →