I built a CLI that scaffolds the boring parts of an AI SaaS — here's what it actually generates A developer built @chimerai/cli, a command-line tool that scaffolds the boilerplate for AI SaaS projects, generating Next.js app routes, a Prisma schema with feature-gated models, AES-256 encrypted provider API key storage, and resource:action RBAC checks. The CLI resolves feature dependencies automatically (admin-dashboard requires RBAC, rag requires model-providers) and splits the stack between TypeScript for user-facing code and a Python LLM orchestration service reached via AI_SERVICE_URL. It supports SQLite or PostgreSQL 16 plus Redis 7 via Docker Compose, and requires Next.js 15+ for its async route handler params. Every AI SaaS project starts with the same two days of nothing-interesting: auth, a users table, an encrypted place to store provider API keys, a Prisma schema. Then you finally get to the part you actually wanted to build. I've been working on a CLI @chimerai/cli that scaffolds exactly that prefix. This post is about what it actually writes to disk — not what a landing page would claim — because that's the only thing that matters when you decide whether to adopt a generator. npx @chimerai/cli create my-ai-app Interactive feature selector. Defaults are auth + RBAC + admin dashboard + analytics; AI features are opt-in. Flags worth knowing: chimerai create my-ai-app --yes no prompts, defaults chimerai create my-ai-app --sqlite no Docker needed, DATABASE URL=file:./dev.db chimerai create my-ai-app --yes --install + npm install --sqlite is the one I'd start with if you just want to look at the code. Without it you get a docker-compose.yml for PostgreSQL 16 + Redis 7. my-ai-app/ ├── app/ │ ├── layout.tsx │ ├── page.tsx │ ├── api/auth/ NextAuth routes if auth selected │ └── admin/ admin pages if selected ├── components/ui/ shadcn/ui components ├── lib/ │ ├── prisma.ts PrismaClient singleton │ ├── auth.ts auth config │ └── encryption.ts API key encryption ├── prisma/schema.prisma only models for selected features ├── .env ├── docker-compose.yml └── package.json The generated Prisma schema is additive per feature, which is the part I check first in any scaffolding tool — if it gives me six models when I asked for two, I stop trusting it: | Selected | Models added | |---|---| | Auth | User , Account , Session , VerificationToken | | RBAC | Role , Permission | | Providers | ModelProvider | | Prompts | PromptTemplate | | Analytics | ApiUsage | Feature dependencies are resolved by the CLI rather than left to you: admin-dashboard requires RBAC, model-providers requires auth the encryption key lives in the auth config , chat-ui requires model-providers , rag requires model-providers . The split is deliberate: the LLM orchestration layer is Python because that's where the ecosystem lives LangChain, FAISS, spaCy , and everything type-safe and user-facing stays TypeScript. The Next.js side proxies to AI SERVICE URL default http://localhost:8002 . Provider management with encrypted keys, which is the thing everyone re-implements badly: js const response = await fetch '/api/providers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify { name: 'OpenAI GPT-4', provider: 'openai', // | 'anthropic' | 'ollama' | 'custom' apiKey: 'sk-...', isActive: true, } , } ; Keys are stored AES-256 encrypted at rest using ENCRYPTION KEY from .env , never in the database in plaintext. provider: 'custom' takes any OpenAI-compatible baseURL , which is how you wire up a self-hosted vLLM or an OpenRouter-style gateway without the core knowing about it. You can also add providers through the admin UI and test the connection before using it — small thing, saves an annoying debugging loop. RBAC uses resource:action permission strings, checked in API routes: js import { requirePermission } from '@/lib/auth/require-permission'; export async function GET req: NextRequest { const permissionError = await requirePermission 'posts:read' ; if permissionError return permissionError; // ... } admin: is a wildcard. Roles carry permission lists; there's a seeded admin admin@example.com / admin123 — remove it, obviously . @chimerai/model-providers , @chimerai/admin-ui etc. exist in the monorepo. chimerai create therefore generates chimerai add requires Next.js 15+ generated route handlers use the async params API . The CLI detects the version and warns below 15. Standalone create output runs on port 3001 by default to avoid colliding with another dev server. create-next-app plus a library like LangChain is a perfectly reasonable starting point — pick the generator that matches the problem. You don't have to start from a generated project: cd my-nextjs-app npx chimerai add auth npx chimerai add model-providers npx chimerai add chat-ui pnpm install npx prisma db push && npx prisma db seed pnpm dev The CLI finds the project root by walking up for a .chimerai marker, then falls back to a registry in ~/.chimerai/projects.json , then --dir . In a monorepo, point --dir at the Next.js app apps/frontend , not the workspace root — the root has no app/ and no prisma/ . chimerai doctor runs health checks on env vars, DB connectivity, and installed components, which is mostly there because I forgot to set ENCRYPTION KEY often enough to be embarrassing. chimerai add rag — FAISS index, chunking, and the /api/rag/query round trip Repo: github.com/armbur19-collab/chimerai-kickstart · site: chimerai.dev