Skip to main content
A template is a directory that knows how to be cloned. It contains the app’s code (backend, optional frontend, MCP server) plus a clone.manifest.json that tells the CLI everything it needs to spin, migrate, health-check, and seed it. Templates live under the templates directory (the monorepo apps/ by default; override with ASYM_TEMPLATES_DIR). The published CLI bundles each manifest with its compose file, so it resolves templates from its own bundle with no monorepo present. The CLI discovers a template by reading each manifest’s name — so apps/slack-clone/ declares the name slack, which is what you type in asymmetric spin slack.

The manifest

Here’s the Slack template’s clone.manifest.json, annotated:
{
  "name": "slack",                         // canonical id used on the CLI
  "displayName": "Slack",
  "realProduct": "slack",                  // what `verify` scores fidelity against
  "services": {
    "backend": {
      "image": "ghcr.io/asymmetric-ai/asymmetric-slack-backend:latest", // pulled, not built
      "port": 3001,                        // container port
      "health": "/api/health"              // polled until healthy on spin
    },
    "frontend": {
      "build": "./frontend",               // the one service still built from source
      "port": 5173,
      "optional": true
    }
  },
  "modes": {                               // named service sets
    "api": ["backend"],
    "full": ["backend", "frontend"]
  },
  "database": {
    "migrations": "./supabase/migrations", // .sql files, run in sorted order
    "nameTemplate": "clone_{id}"           // per-clone database name
  },
  "redis": {
    "prefixTemplate": "{id}:"              // per-clone key prefix
  },
  "seed": {
    "fixtures": "./seeds/*.sql",           // deterministic fixture packs
    "ai": {
      "entities": ["users", "channels", "messages"]
    }
  }
}
Backends declare an image (pulled and digest-pinned at spin). A service can instead declare build for a local build context — today only Slack’s optional frontend does.

Fields that matter

FieldDrives
nameThe identifier you type (spin <name>, verify <name>).
services[].imageThe published image the CLI pulls and runs (digest-pinned).
services[].healthThe endpoint spin and reset poll before declaring the clone healthy.
modesWhat --mode accepts; the first key is the default.
database.migrationsThe .sql files run on create and replayed on reset.
database.nameTemplateHow the per-clone database is named ({id} is substituted).
redis.prefixTemplateThe per-clone Redis key namespace.
seed.fixturesThe glob of named fixture packs seed --fixture can load.
seed.ai.entitiesWhat AI seeding generates for this template.

Ready-made templates

Six templates ship today. Each backend is a published image; verify scores it against the real product’s live API documentation.

Slack

RPC Web API, MCP server, and a frontend. The {ok} envelope, Slack-format ids, byte-identical events. Modes: api, full.

Stripe

REST API: customers, payments, invoices, subscriptions, refunds, and signed webhooks. API-only.

Notion

REST API: databases, data sources, pages, blocks, views, comments, file uploads, search — with Notion’s rate limits. API-only.

HubSpot

CRM REST API: generic objects, v4 associations, properties, pipelines, owners, OAuth tokens, and HubSpot-accurate rate limiting. API-only.

GitHub

REST API: repos, issues, pull requests, comments, labels, tokens, and rate limiting. API-only.

Linear

GraphQL API: issues, projects, teams, cycles, and webhooks. API-only.
Default container ports are slack 3001, linear 3002, stripe 3003, notion 3004, hubspot 3005, github 3006; the host port for each clone is allocated at spin time from your range (default 3000–3999). Templates are built and maintained by asymmetric — you spin and use them, you don’t author your own.