Building a SaaS from Scratch with Claude Cowork

This guide is for a senior engineer who knows what they’re doing and just needs the Cowork-specific mental model to get out of the way. No padding. No fluff. Let’s build.

Table of Contents

The Big Picture

Cowork is Anthropic’s visual, browser-based agentic coding environment. Unlike Claude Code (the terminal CLI), Cowork runs inside a sandboxed VM with a visual interface — trading some of the control and configurability of the terminal for a more accessible experience. It can read and write files, run code, and execute multi-step tasks, but it operates within a sandboxed environment (no direct internet access from the VM, fewer configuration options than Claude Code). For a full overview, see the Cowork Help Center.

When you’re building a SaaS, the way to think about it is this: Cowork is your engineering team. You’re the tech lead.

You write the specs. Cowork executes. You review, steer, and unblock.

The primitives you need to understand before building anything:

PrimitiveWhat It IsAnalogy
FolderThe workspace Cowork can accessYour monorepo
MD Task FilesInstructions for a specific taskA Jira ticket with real detail
SKILL.mdReusable capability Claude loads on demandA trained engineer for a specific domain
AGENTS.md / CLAUDE.mdPersistent project context loaded every sessionYour team’s onboarding doc
SubagentsSpecialists Claude spawns to work in parallelDedicated engineers per workstream

Get these five things right and you can delegate an absurd amount of the build to Cowork.


Part 1: Project Setup

Folder Structure

Before you write a single line of code or a single MD file, set up your workspace. Cowork can only access what you explicitly give it.

📁 my-saas/
  📁 .claude/              ← agent memory and rules (auto-managed)
  📁 skills/               ← your custom SKILL.md files
  📁 tasks/                ← reusable task MD files
  📁 agents/               ← subagent definitions
  📁 src/                  ← actual application code
    📁 app/                ← frontend (Next.js, Astro, etc.)
    📁 api/                ← backend / AI routes
    📁 lib/                ← shared utilities
  📁 docs/                 ← specs, PRDs, architecture notes
  📁 outputs/              ← generated files, reports, exports
  AGENTS.md                ← root-level project brief (read by all agents)
  CLAUDE.md                ← Claude-specific instructions and memory

Point Cowork at the my-saas/ root. Everything inside is accessible. Everything outside is off-limits.


Part 2: AGENTS.md - Your Project’s Permanent Brain

This is the most important file you’ll write. AGENTS.md is loaded at the start of every session, by every agent. It’s the one file that gives Claude persistent context across the entire project.

Think of it as onboarding a new engineer - except every session, Claude forgets everything except what’s in this file. Write it accordingly.

What Belongs in AGENTS.md

# AGENTS.md - my-saas Project Context

## What We're Building
[Product name] is a [one-liner].
Target user: [who]. Core problem: [what].

## Tech Stack
- Frontend: Next.js 14 (App Router), TypeScript, Tailwind
- Backend: Node.js, Express, Prisma ORM
- Database: PostgreSQL (Supabase)
- AI Layer: Anthropic Claude API (claude-sonnet-4-6)
- Auth: Clerk
- Payments: Stripe
- Hosting: Vercel (frontend), Railway (backend)

## Architecture Decisions
- All API routes live in /src/api
- Database models defined in /src/lib/db/schema.prisma
- Environment variables documented in .env.example (NEVER commit .env)
- AI calls are centralized in /src/lib/ai/client.ts
- Use async/await everywhere. No .then() chains.

## Coding Conventions
- TypeScript strict mode. No `any` types.
- Functional components only. No class components.
- All database queries go through the Prisma client, never raw SQL
- API responses follow this shape: { data, error, meta }
- Error handling: always use try/catch, log to console.error, return structured error

## What NOT to Do
- Do not install new packages without checking package.json first
- Do not modify .env files directly - update .env.example and note what's needed
- Do not delete files - comment out or archive instead
- Do not make git commits without listing what changed and why

## Current Status
[Update this as the project evolves]
- Auth: ✅ Complete
- Onboarding: 🔄 In progress
- Billing: ❌ Not started
- AI Feature: ❌ Not started

AGENTS.md vs CLAUDE.md - When to Use Each

FileUse For
AGENTS.mdShared context for ALL agents (Claude, Cursor, Copilot, etc.)
CLAUDE.mdClaude-specific features, @imports, /init workflow, personal preferences

If you’re only using Claude (which you are), either works. AGENTS.md is the open standard - use it so the file is portable if you ever add Cursor or another tool to the workflow.


Part 3: Skills - Teaching Cowork How to Work

A Skill is a directory containing a SKILL.md file that gives Claude a reusable, domain-specific capability. Skills load on demand - Claude reads its description and decides when to apply it. This keeps context lean.

SKILL.md Structure

📁 skills/
  📁 api-endpoint/
    SKILL.md
  📁 react-component/
    SKILL.md
  📁 database-migration/
    SKILL.md
  📁 stripe-integration/
    SKILL.md
  📁 ai-feature/
    SKILL.md

How to Write a SKILL.md

Every SKILL.md needs a YAML metadata block and then plain markdown instructions.

---
name: api-endpoint
description: >
  Use this skill when creating new Express API routes, REST endpoints,
  or API handlers. Applies to any file in /src/api/.
version: 1.0.0
author: your-name
---

# API Endpoint Skill

## Purpose
Creates consistent, type-safe Express API endpoints following project conventions.

## Always Do
- Import from `express` and type the Request/Response with our custom types in `/src/lib/types`
- Wrap all logic in try/catch
- Validate request body using Zod schemas (defined in `/src/lib/validators`)
- Return responses in the shape: `{ data: T | null, error: string | null, meta?: object }`
- Log errors with `console.error('[route-name]:', error)`

## File Structure
New endpoints go in: `/src/api/routes/[feature-name].ts`
Register them in: `/src/api/index.ts`

## Example Pattern
```typescript
import { Router, Request, Response } from 'express';
import { z } from 'zod';

const router = Router();

const CreateItemSchema = z.object({
  name: z.string().min(1),
  userId: z.string().uuid(),
});

router.post('/', async (req: Request, res: Response) => {
  try {
    const body = CreateItemSchema.parse(req.body);
    const item = await db.item.create({ data: body });
    return res.json({ data: item, error: null });
  } catch (error) {
    console.error('[items/create]:', error);
    return res.status(500).json({ data: null, error: 'Failed to create item' });
  }
});

export default router;

Do Not

  • Never use raw SQL - use Prisma
  • Never skip input validation
  • Never return passwords or sensitive fields in the response

Create these eight skills and you’ll cover 90% of the implementation surface area:

Skill NameTriggers When…
api-endpointCreating backend routes or handlers
react-componentBuilding UI components or pages
database-migrationAdding/modifying Prisma schema or running migrations
stripe-integrationAnything touching payments, webhooks, subscriptions
ai-featureBuilding features that call the Claude API
auth-middlewareImplementing Clerk auth checks or protected routes
error-handlingDebugging, writing error boundaries, logging patterns
env-configAdding environment variables or configuration

Installing Skills into Cowork

  1. Go to Settings → Capabilities → Skills
  2. Click Add → Upload a skill
  3. Upload the folder (zip it first if needed)
  4. Or drop the skills folder directly into your Claude Code/Cowork project directory

Part 4: Setting Up an AI Backend

Your SaaS needs to call Claude. Here’s the architecture that works.

Project Structure for AI Features

📁 src/
📁 lib/
📁 ai/
client.ts          ← Anthropic client singleton
prompts.ts         ← prompt templates
types.ts           ← shared types for AI responses
📁 api/
📁 routes/
ai.ts              ← AI-specific route handlers

The AI Client Singleton

For full API reference and SDK docs, see the Anthropic SDK documentation.

// src/lib/ai/client.ts
import Anthropic from '@anthropic-ai/sdk';

if (!process.env.ANTHROPIC_API_KEY) {
  throw new Error('ANTHROPIC_API_KEY is not set');
}

export const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

export const DEFAULT_MODEL = 'claude-sonnet-4-6';
export const DEFAULT_MAX_TOKENS = 2048;

A Typed API Route for AI Features

// src/api/routes/ai.ts
import { Router } from 'express';
import { anthropic, DEFAULT_MODEL, DEFAULT_MAX_TOKENS } from '../../lib/ai/client';
import { requireAuth } from '../../middleware/auth';
import { z } from 'zod';

const router = Router();

const AnalyzeSchema = z.object({
  content: z.string().min(1).max(10000),
  userId: z.string().uuid(),
});

router.post('/analyze', requireAuth, async (req, res) => {
  try {
    const { content, userId } = AnalyzeSchema.parse(req.body);

    const message = await anthropic.messages.create({
      model: DEFAULT_MODEL,
      max_tokens: DEFAULT_MAX_TOKENS,
      system: `You are an expert analyst. Be concise, structured, and specific.`,
      messages: [
        {
          role: 'user',
          content: `Analyze the following and return your findings as JSON:\n\n${content}`,
        },
      ],
    });

    const textContent = message.content.find(block => block.type === 'text');
    if (!textContent || textContent.type !== 'text') {
      throw new Error('Unexpected response format from Claude');
    }

    return res.json({ data: textContent.text, error: null });
  } catch (error) {
    console.error('[ai/analyze]:', error);
    return res.status(500).json({ data: null, error: 'Analysis failed' });
  }
});

export default router;

Task File to Get Cowork to Build This

Create tasks/build-ai-route.md:

# Task: Build AI Backend Route

## Context
We are building an AI-powered analysis feature. Read AGENTS.md for full project context.
Use the `api-endpoint` and `ai-feature` skills.

## What to Build
Create a new Express route at `/src/api/routes/ai.ts` that:
1. Accepts POST requests to `/api/ai/analyze`
2. Validates input with Zod (content: string, userId: uuid)
3. Calls the Claude API using the client at `/src/lib/ai/client.ts`
4. Returns structured JSON response
5. Handles errors cleanly

## Input
```json
{
  "content": "string (max 10,000 chars)",
  "userId": "uuid string"
}

Output

{
  "data": "AI analysis result as string",
  "error": null
}

After Building

  • Register the new route in /src/api/index.ts
  • Add a note to AGENTS.md under Current Status: “AI Route: ✅ Complete”
  • Create a test file at /src/api/routes/ai.test.ts with at least 2 test cases

Run it with:


Read tasks/build-ai-route.md and execute. Use the api-endpoint and ai-feature skills.

Part 5: Agents - Parallel Workstreams at Scale

Once you’re past the MVP stage, single-threaded Cowork sessions become a bottleneck. That’s where subagents come in.

What Is a Subagent?

A subagent is a specialized Claude instance with its own context window, system prompt, and tool permissions. It handles a scoped task, reports back, and disappears.

Use them when:

  • The task produces verbose output you don’t need in your main session
  • You want parallel execution (frontend + backend at the same time)
  • The work is self-contained and can return a summary

Defining Subagents for SaaS Build

Create agents/ in your project root:

📁 agents/
frontend-builder.md
backend-builder.md
db-architect.md
qa-reviewer.md

Example: agents/frontend-builder.md

---
name: frontend-builder
description: >
  Specialist for building React/Next.js UI components, pages, and frontend
  logic. Only works in /src/app/. Does not touch backend files.
memory: project
---

You are a senior frontend engineer specializing in Next.js 14 App Router,
TypeScript, and Tailwind CSS.

Your scope: /src/app/ and /src/components/ only.

Rules:
- Functional components only
- TypeScript strict mode
- Tailwind for all styling - no CSS files unless absolutely necessary
- Use Next.js server components by default; add 'use client' only when needed
- All data fetching goes in server components
- Always handle loading and error states

When done with a task, output a summary:
- Files created or modified
- Any open questions or blockers
- Suggested next steps

Example: agents/qa-reviewer.md

---
name: qa-reviewer
description: >
  Reviews completed code for bugs, security issues, and convention violations.
  Run after any major feature is built.
memory: project
---

You are a senior code reviewer. Your job is to find problems, not build things.

Review checklist:
- Input validation present and correct?
- Auth checks in place for protected routes?
- No sensitive data exposed in API responses?
- Error handling catches all failure paths?
- TypeScript types accurate (no `any`)?
- Follows conventions in AGENTS.md?

Output a structured report:
- ✅ Looks good
- ⚠️ Minor issues (list them)
- 🚨 Blocking issues (list them with file:line references)

Spawning Agents in Cowork

Spawn two agents to work in parallel:
1. frontend-builder: Build the user dashboard page at /src/app/dashboard/page.tsx
   using the design spec in /docs/dashboard-spec.md
2. backend-builder: Build the /api/dashboard/stats endpoint per
   /docs/dashboard-spec.md

When both are done, spawn qa-reviewer to review both outputs.

Agent Teams (Claude Code Only)

If you switch to Claude Code (terminal), you can enable full Agent Teams for true parallel execution:

// settings.json
{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  }
}

Note: This is an experimental flag and may change or be removed in future releases. Check the official Claude Code docs for the latest on agent teams support.

Then spawn teammates conversationally:

Spawn 3 teammates:
- architect: design the database schema for multi-tenant billing
- frontend: scaffold the pricing page component
- backend: build the Stripe webhook handler

Each teammate is a full Claude Code instance. They coordinate via shared task files and report back to you.


Part 6: The Build Workflow

Here’s how a typical feature build looks end-to-end using everything above.

Step 1 - Write the Spec

Drop it in docs/feature-[name].md. Be specific. This is what Cowork will read.

Step 2 - Create the Task File

# Task: [Feature Name]

## Read First
- AGENTS.md (project context)
- docs/feature-[name].md (spec)

## Skills to Use
- [list relevant skills]

## What to Build
[Specific, ordered list of what to create or modify]

## Definition of Done
- [ ] Feature works end-to-end
- [ ] Types are clean (no `any`)
- [ ] Error states handled
- [ ] AGENTS.md updated with new status

Step 3 - Run It

Read tasks/[feature].md and execute.
Use the [skill-1] and [skill-2] skills.
Check in with me before making any database schema changes.

Step 4 - Review and Steer

Watch the progress indicators. If something looks off, jump in and redirect mid-task. Cowork won’t get offended.

Step 5 - QA Pass

Read agents/qa-reviewer.md.
Review everything modified in the last task run.
Flag any issues.

Step 6 - Update AGENTS.md

Keep the “Current Status” section current. This is what future sessions (and future agents) will use to understand where things stand.


Part 7: Reference - MD Files You Need for a SaaS Build

Here’s the full set. Build these progressively as you need them.

Core Project Files

FilePurpose
AGENTS.mdProject-wide persistent context
CLAUDE.mdClaude-specific preferences and imports

Skills

SkillFile
API endpoint patternsskills/api-endpoint/SKILL.md
React componentsskills/react-component/SKILL.md
Database migrationsskills/database-migration/SKILL.md
Stripe integrationskills/stripe-integration/SKILL.md
AI feature buildingskills/ai-feature/SKILL.md
Auth middlewareskills/auth-middleware/SKILL.md

Task Files

TaskFile
Scaffold full featuretasks/build-feature.md
Build AI routetasks/build-ai-route.md
Create DB migrationtasks/create-migration.md
Add Stripe webhooktasks/stripe-webhook.md
Weekly code reviewtasks/weekly-review.md

Agents

AgentFile
Frontend specialistagents/frontend-builder.md
Backend specialistagents/backend-builder.md
Database architectagents/db-architect.md
QA revieweragents/qa-reviewer.md

Tips & Common Gotchas

Before you go full-speed, here are the pitfalls that catch most people:

Context Window Limits

Cowork (and Claude in general) has a finite context window. If your session gets too long or you paste too much code, Claude starts losing track of earlier instructions. Keep sessions lean:

  • Break large tasks into smaller, focused task files
  • Use subagents for verbose work so the output doesn’t flood your main session
  • Restart sessions for new features rather than chaining everything in one

When Skills Don’t Trigger

If a skill isn’t activating when you expect it to:

  • Description mismatch: The description field in your SKILL.md is what Claude uses to decide relevance. If it’s too vague or too narrow, Claude won’t match it to the task. Be explicit about when the skill applies.
  • Scope issues: Make sure the skill’s description covers the file paths or task types you’re working with. A skill scoped to /src/api/ won’t trigger for work in /src/lib/.
  • Explicit invocation: You can always tell Claude directly: “Use the api-endpoint skill for this task.”

Debugging Agent Failures

When a subagent returns bad output or errors out:

  • Check that the agent’s .md file has clear scope boundaries - agents that try to do too much produce worse results
  • Make sure AGENTS.md is up to date - stale context leads to stale output
  • Look at what the agent actually did (files modified, commands run) rather than just the summary
  • Try reducing the task scope - smaller, more specific tasks produce more reliable results

Cowork VM Limitations

Cowork runs in a sandboxed VM. This means:

  • No direct internet access from within the VM - you can’t curl external APIs or npm install from inside a Cowork session
  • File access is scoped to the folder you pointed Cowork at - nothing outside that folder exists to it
  • No persistent processes - background servers, watchers, or daemons won’t survive between sessions

Keep AGENTS.md Concise

It’s tempting to dump everything into AGENTS.md, but remember: this file is loaded at the start of every session and eats into your context window. Keep it under ~200 lines. Move detailed specs into docs/ and reference them from task files instead.


Quick Start Checklist

Before you write your first line of application code:

  • Folder structure created (src/, tasks/, skills/, agents/, docs/)
  • AGENTS.md written with tech stack, conventions, and current status
  • Core skills created (at minimum: api-endpoint, react-component, ai-feature)
  • AI client set up at src/lib/ai/client.ts
  • .env.example created with all required keys documented
  • Cowork pointed at project root folder
  • First task file written for initial scaffold

Once those are in place, you can move fast. Every task you hand off is informed by the skills and context you’ve already built. The compounding effect kicks in around week two.


The one thing to remember: Cowork is not magic. It’s a capable engineer who reads your docs, follows your conventions, and does what you spec. The quality of your AGENTS.md, skills, and task files determines the quality of what comes out. Invest thirty minutes upfront on those files and you’ll save ten hours on every feature after.


References & Further Reading