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
- Part 1: Project Setup
- Part 2: AGENTS.md —- Your Project’s Permanent Brain
- Part 3: Skills — Teaching Cowork How to Work
- Part 4: Setting Up an AI Backend
- Part 5: Agents — Parallel Workstreams at Scale
- Part 6: The Build Workflow
- Part 7: Reference — MD Files You Need for a SaaS Build
- Tips & Common Gotchas
- Quick Start Checklist
- References & Further Reading
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:
| Primitive | What It Is | Analogy |
|---|---|---|
| Folder | The workspace Cowork can access | Your monorepo |
| MD Task Files | Instructions for a specific task | A Jira ticket with real detail |
| SKILL.md | Reusable capability Claude loads on demand | A trained engineer for a specific domain |
| AGENTS.md / CLAUDE.md | Persistent project context loaded every session | Your team’s onboarding doc |
| Subagents | Specialists Claude spawns to work in parallel | Dedicated 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
| File | Use For |
|---|---|
AGENTS.md | Shared context for ALL agents (Claude, Cursor, Copilot, etc.) |
CLAUDE.md | Claude-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
Skills for a SaaS Build - Recommended Set
Create these eight skills and you’ll cover 90% of the implementation surface area:
| Skill Name | Triggers When… |
|---|---|
api-endpoint | Creating backend routes or handlers |
react-component | Building UI components or pages |
database-migration | Adding/modifying Prisma schema or running migrations |
stripe-integration | Anything touching payments, webhooks, subscriptions |
ai-feature | Building features that call the Claude API |
auth-middleware | Implementing Clerk auth checks or protected routes |
error-handling | Debugging, writing error boundaries, logging patterns |
env-config | Adding environment variables or configuration |
Installing Skills into Cowork
- Go to Settings → Capabilities → Skills
- Click Add → Upload a skill
- Upload the folder (zip it first if needed)
- 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.tswith 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
| File | Purpose |
|---|---|
AGENTS.md | Project-wide persistent context |
CLAUDE.md | Claude-specific preferences and imports |
Skills
| Skill | File |
|---|---|
| API endpoint patterns | skills/api-endpoint/SKILL.md |
| React components | skills/react-component/SKILL.md |
| Database migrations | skills/database-migration/SKILL.md |
| Stripe integration | skills/stripe-integration/SKILL.md |
| AI feature building | skills/ai-feature/SKILL.md |
| Auth middleware | skills/auth-middleware/SKILL.md |
Task Files
| Task | File |
|---|---|
| Scaffold full feature | tasks/build-feature.md |
| Build AI route | tasks/build-ai-route.md |
| Create DB migration | tasks/create-migration.md |
| Add Stripe webhook | tasks/stripe-webhook.md |
| Weekly code review | tasks/weekly-review.md |
Agents
| Agent | File |
|---|---|
| Frontend specialist | agents/frontend-builder.md |
| Backend specialist | agents/backend-builder.md |
| Database architect | agents/db-architect.md |
| QA reviewer | agents/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
descriptionfield 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-endpointskill for this task.”
Debugging Agent Failures
When a subagent returns bad output or errors out:
- Check that the agent’s
.mdfile 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
curlexternal APIs ornpm installfrom 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.mdwritten 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.examplecreated 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
- Cowork Product Page - overview and access
- Cowork Help Center - getting started guide and FAQ
- Cowork Research Preview Blog Post - background on the design and vision
- Anthropic API Documentation - full API reference for building with Claude
- Anthropic SDK (TypeScript/Python) - official client libraries
- Claude Code Documentation - terminal-based agentic coding docs
- AGENTS.md Spec - the open standard for agent context files