Two Weeks of Building: 5 Projects, 1 Pattern

I've been on a building tear lately. Over the past two weeks, I shipped 5 projects that span meeting intelligence, outbound automation, developer tools, a game, and a personal website. Looking back, there's a common thread: Claude as orchestrator, humans as approvers.

Here's what I built and what I learned.


1. granola-tools: Meeting Intelligence with Approval Workflows

The problem: I take a lot of meetings. Granola records them, but the action items sit in transcripts that I rarely revisit. Things slip through the cracks.

The solution: An agent that watches my Granola meetings, extracts action items using Claude, and posts them to Slack with interactive buttons. One click creates a Linear ticket. Another generates a follow-up email draft.

How it works

Granola → Claude (extract actions) → Slack (approve/dismiss) → Linear/Gmail

The key insight was the three-phase workflow:

  1. Sync: Fetch new meetings from Granola, categorize them by context (which client? which project?), generate embeddings, store in Supabase
  2. Propose: Claude analyzes the transcript with context-specific rules and proposes actions (create ticket, update existing ticket, draft email, schedule follow-up)
  3. Execute: After I click "Approve" in Slack, it actually creates the ticket or drafts the email

I also added a Slack assistant mode. In a private channel, I can ask questions like "What did Sarah say about the timeline in our last Acme call?" and it searches the vector embeddings to find relevant context.

The approval pattern

This is the pattern I keep coming back to: AI proposes, human approves, then execute. It's not fully autonomous - I still have to click a button. But that click takes 2 seconds instead of the 5 minutes it would take to manually create a well-formatted Linear ticket with the right labels and assignee.

The Slack message looks like:

šŸ“… Weekly Team Sync
December 29, 2025

Summary: Discussed Q1 roadmap and resource allocation...

āœ… Action Items (3)
šŸ”“ Finalize budget proposal (Owner: Chris)
🟔 Schedule design review
🟢 Update documentation

[Create Ticket] [Create All] [Generate Email] [Dismiss]

2. slack-linear-sync: Turn Conversations into Tracked Work

The problem: Important decisions and action items get buried in Slack threads. By the time someone remembers to create a ticket, context is lost.

The solution: An agent that monitors specific Slack channels, uses Claude to identify actionable items, and proposes Linear tickets for approval.

How it works

Each channel has rules defined in a markdown file:

## #product-feedback
Team: Product
Default labels: feedback, triage
Look for: feature requests, bug reports, user complaints
Ignore: general discussion, thank-you messages

The agent polls channels on a schedule, runs messages through Claude with these rules, and posts proposals to an approval channel. Approve with a button click, or dismiss if it's noise.

The dedup service prevents the same message from generating multiple tickets. Once processed, it's tracked.

Why this matters

Async communication is great until things fall through the cracks. This bridges the gap between "we talked about it in Slack" and "it's tracked in Linear." No manual triage required.


3. cheerful-gtm: Multi-Agent Outbound Pipeline

The problem: Outbound is tedious. Finding leads, researching them, writing personalized emails, pushing to campaign tools - it's hours of work that doesn't scale.

The solution: A multi-agent pipeline that automates the entire flow from lead discovery to personalized email sequences.

The architecture

Lead Finder Agent → Enrichment Agent → Copywriter Agent → Instantly → Slack Digest

Lead Finder Agent: Uses Claude with tool access to Apollo. Searches for companies matching our ICP, finds contacts, dedupes against our CRM (Clarify) and existing campaigns (Instantly). Returns a list of net-new leads.

Enrichment Agent: Takes each lead, scrapes their LinkedIn profile and recent posts, scores them based on activity:

  • HIGH: Recent posts relevant to what we do
  • MEDIUM: Any recent activity
  • LOW: No recent posts or minimal presence

The score determines personalization depth.

Copywriter Agent: Generates a 3-email sequence (day 0, 4, 8). High-score leads get deep personalization referencing specific posts. Low-score leads get lighter personalization based on company and role.

The agentic loop pattern

Each agent follows the same pattern:

while True:
    response = claude.messages.create(
        model="claude-opus-4-5-20251101",
        tools=self._get_tool_definitions(),
        messages=messages
    )

    if response.stop_reason != "tool_use":
        break

    # Handle tool calls, append results, continue

The agent decides when it's done. It might call Apollo 3 times to refine a search, or it might get lucky on the first try. Claude manages the loop.

Results

The pipeline runs Mon-Thu at 9am ET. I get a Slack digest with stats: leads found, leads enriched, sequences generated, campaigns updated. If something looks off, I can review before emails go out.


4. home-run-derby: Building with My Son

The problem: My son wanted to make a game. We had an afternoon.

The solution: Night Home Run Derby - a timing-based baseball game built with nothing but HTML, CSS, and vanilla JavaScript.

The game

You're the batter. The pitcher throws. Click (or tap) when the ball is in the strike zone. Perfect timing = 400+ foot home run. Miss = strike. Three outs and the game ends.

It tracks your longest hit and total distance across the session.

Why no framework?

We built it in about 2 hours. Here's the entire tech stack:

  • index.html (1 file, ~550 lines)
  • Canvas API for rendering
  • No build step
  • No dependencies
  • Runs anywhere

Sometimes the best tool is the simplest one. My son could see every line of code. When he wanted the stadium lights to glow, we added it. When he wanted a night theme, we changed the background color. No bundler configuration, no npm install, no waiting.

The lesson

Not every project needs to be production-grade. Some of the most rewarding things I've built have been with my kids, on a weekend, with zero infrastructure.


5. chrisbrownridge.com: A Terminal You Can Talk To

The problem: Personal websites are boring. Static pages with a headshot and a list of jobs.

The solution: A terminal interface powered by Claude. Type questions, get answers. Use slash commands for quick info.

The experience

When you land on the site, you see a terminal window with ASCII art:

ā–ˆā–€ā–€ ā–ˆ ā–ˆ ā–ˆā–€ā–ˆ ā–ˆ ā–ˆā–€ā–€
ā–ˆā–„ā–„ ā–ˆā–€ā–ˆ ā–ˆā–€ā–„ ā–ˆ ā–„ā–„ā–ˆ

ā–ˆā–€ā–„ ā–ˆā–€ā–ˆ ā–ˆā–€ā–ˆ ā–ˆ   ā–ˆ ā–ˆā–„ ā–ˆ ā–ˆā–€ā–ˆ ā–ˆ ā–ˆā–€ā–„ ā–ˆā–€ā–€ ā–ˆā–€ā–€
ā–ˆā–„ā–ˆ ā–ˆā–€ā–„ ā–ˆā–„ā–ˆ ▀▄▀▄▀ ā–ˆ ā–€ā–ˆ ā–ˆā–€ā–„ ā–ˆ ā–ˆā–„ā–€ ā–ˆā–„ā–ˆ ā–ˆā–„ā–„

Below that, you can type anything. Ask about my background, my companies, my interests. Claude knows the context and responds conversationally.

Or use the built-in commands:

  • /contact - Get my email
  • /about - Quick bullet points
  • /thoughts - Claude summarizes my recent LinkedIn posts

The stack

  • Next.js 16, React 19, Tailwind 4
  • Anthropic SDK for Claude integration
  • Gray-matter for markdown parsing (blog posts)

The terminal aesthetic isn't just a gimmick - it reflects how I actually work. I spend most of my day in terminals and chat interfaces. Why should my personal site be any different?


The Pattern: AI Proposes, Human Approves

Looking across these projects, the same pattern keeps emerging:

  1. Claude does the heavy lifting - analyzing transcripts, researching leads, generating content
  2. The output is a proposal - not an immediate action
  3. Human reviews with one click - approve, modify, or dismiss
  4. Then it executes - creates tickets, sends emails, updates systems

This is the sweet spot for AI automation right now. Fully autonomous agents are scary and error-prone. Fully manual work doesn't scale. The middle ground - AI as a highly capable assistant that queues up work for your approval - feels right.

The approval step adds maybe 10 seconds to each action. But it gives me confidence that nothing crazy is happening. And over time, as I see the proposals match my intent, I might move toward more autonomy. But I can always dial it back.


What's Next

I'm continuing to iterate on these tools. A few things I'm exploring:

  • Cross-tool context: What if granola-tools and slack-linear-sync shared understanding of what's already been discussed?
  • Smarter dedup: Right now dedup is hash-based. Semantic dedup ("this is the same request phrased differently") would be more powerful.
  • More approval surfaces: Slack works, but what about email digests? A dedicated dashboard?

If you're building similar tools, I'd love to hear what patterns you've found. Reach out at chris@brownridges.com or find me on LinkedIn.


Built in 2 weeks, January 2025. All projects use Claude (Opus 4.5) as the core AI engine.