English | 简体中文
Cell
The TypeScript framework that builds once and runs anywhere, designed for humans and coding agents alike.
Quick Start · Deploy Anywhere · Coding Agents · AI · Examples · CLI Reference
Cell is a serverless-first, component-based, platform-independent application framework for TypeScript. You write plain classes with dependency injection; Cell turns them into a full-stack application, bundles the backend into a single file, and ships the same code to a Node.js server, a container, a single executable, Cloudflare Workers, AWS Lambda, Alibaba Cloud Function Compute, Tencent Cloud SCF or Vercel.
Cell 4 rebuilds the toolchain on Vite 8 and treats coding agents as first-class users: every command speaks JSON, every error carries a code and a fix, and every project ships with an AGENTS.md and an MCP server.
Why Cell
| One codebase, every runtime | Pick a preset at build time: node, cli, cloudflare, fc, scf, lambda, vercel. No platform SDK in your code, no rewrite when you move. |
| Single-file output | The backend is one dependency-inlined index.mjs. Add --single to embed the frontend as well, or --compile for a standalone executable (Bun, Deno or Node.js SEA). |
| Agent-first toolchain | --json on every command, structured CellError codes with hints, cell check for types and DI wiring, version-matched docs, and MCP tools for both the project and the running dev server. |
| Enterprise-grade architecture | Dependency injection and AOP (@Component, @Autowired, @Value, @Aspect), MVC, RPC, declarative transactions, security, JWT and OAuth2. |
| Full stack in one process | Backend MVC plus React, served on one port in development with frontend HMR and backend hot reload. |
| AI native | Provider-neutral chat models, prompts and streaming; agents and pi coding agent sessions whose tools are your own services. |
| Zero configuration | Sensible defaults everywhere. Override only what you need in cell.yml, cell.config.ts or CELL_BACKEND__* environment variables. |
| Minimal footprint | The toolchain depends on little more than Vite; cloud deployers sign their own requests instead of pulling in vendor SDKs. |
Quick Start
Requires Node.js ^20.19.0 || >=22.12.0.
npx @celljs/cli init backend my-app # or: fullstack (React + backend over RPC)
cd my-app
npm install
npx cell dev # http://127.0.0.1:3000, hot reload on saveA complete backend is a configuration file and a class:
# cell.yml
backend:
cell:
greeting: Hello from my-app// src/node/home-controller.ts
import { Value } from '@celljs/core';
import { Controller, Get, Text } from '@celljs/mvc/lib/node';
@Controller()
export class HomeController {
@Value('cell.greeting')
protected readonly greeting: string;
@Get()
@Text()
home(): string {
return this.greeting;
}
}Test it in-process, without opening a port:
import { createTestApp } from '@celljs/cli';
const app = await createTestApp({ root: process.cwd() });
const res = await app.fetch('/'); // 200 "Hello from my-app"
await app.close();The everyday commands:
| Command | What it does |
|---|---|
cell dev | One port for frontend and backend; HMR for the UI, hot reload for the server, automatic restart on config changes |
cell build | Production build into .cell/output (--single, --compile, --preset <name>) |
cell preview | Run the build output exactly as the target platform would |
cell deploy | Build and publish with the preset's deployer; --dry-run prints the plan |
cell check | Configuration, TypeScript types, decorator settings and DI bindings in one pass |
cell info | Everything Cell resolved: preset, modes, components, DI modules, hooks, output state |
cell config get <key> --why | The merged value of a setting and every file or variable that set it |
Deploy Anywhere
Your code stays the same; the preset decides the shape of the output and how it is deployed.
| Preset | Output | Deploy |
|---|---|---|
node (default) | Node.js HTTP server, one index.mjs | Anywhere Node.js runs: VM, container, PaaS |
cli | Command-line program on Cell DI | Distribute as a file or an executable |
cloudflare | Worker + static assets + wrangler.json | cell deploy --preset cloudflare |
fc | Alibaba Cloud Function Compute (custom runtime) | cell deploy --preset fc |
scf | Tencent Cloud SCF web function | cell deploy --preset scf |
lambda | AWS Lambda (Function URL / API Gateway) | cell deploy --preset lambda |
vercel | Vercel Build Output API (.vercel/output) | cell deploy --preset vercel |
cell build --single # the whole full-stack app in one file: node index.mjs
cell build --compile # a standalone executable, no Node.js required on the host
cell deploy --preset cloudflare --dry-runBuilt for Coding Agents
Cell assumes the next developer on your project may be an AI agent, and makes the framework something an agent can use correctly on the first try (design principles).
- Machine-readable everything:
--jsonon every command returns exactly one JSON result; errors areCellErrors with a stablecode, a location and ahint. - Context, not guesswork:
cell initwritesAGENTS.md, a Cell skill and.mcp.json;cell agent synckeeps them matched to the installed versions;cell docs <query>searches the docs shipped with your exact dependencies. - MCP built in:
cell mcpexposesinfo,check,config_get,docs_search,buildanddeploy_plan;cell devserves/_cell/mcpwith routes, DI bindings, resolved config, recent requests, logs and errors of the running app. - Fast feedback:
cell checkcatches type errors, missing decorator settings and broken DI bindings before anything runs;createTestApp()gives in-process integration tests.
// .mcp.json (Claude Code, Cursor, CodeBuddy, ...)
{ "mcpServers": { "cell": { "command": "npx", "args": ["cell", "mcp"] } } }AI Native
import { Component, Autowired } from '@celljs/core';
import { ChatModel, ProxyChatModel, PromptTemplate } from '@celljs/ai-core';
@Component()
export class Assistant {
@Autowired(ProxyChatModel)
protected chatModel: ChatModel;
@Autowired(PromptTemplate)
protected promptTemplate: PromptTemplate;
async ask(question: string): Promise<string> {
const prompt = await this.promptTemplate.create('Answer briefly: {question}', {
variables: { question },
// pi:<provider>/<model id>, routed by ProxyChatModel to @celljs/ai-pi
chatOptions: { model: 'pi:anthropic/claude-sonnet-4-5' }
});
const response = await this.chatModel.call(prompt);
return response.result.output.content;
}
}- Models:
@celljs/ai-piconnects 20+ providers (Anthropic, OpenAI, Google, DeepSeek, Ollama and other OpenAI-compatible endpoints) behind the@celljs/ai-coreChatModelAPI (pi:<provider>/<model>). - Agents:
@celljs/ai-agentbuilds tool-using agents whose tools are ordinary Cell components; events stream over SSE. - Coding agents:
@celljs/ai-coding-agenthosts pi coding agent sessions inside your application, managed by DI. - Terminal UIs:
@celljs/tuiturns an agent into an interactive command-line chat (seeexamples/tui-app).
More Examples
Dependency injection
import { Component, Autowired, Value } from '@celljs/core';
@Component()
export class A {}
@Component()
export class B {
@Autowired()
protected a: A; // class injection
}
@Component()
export class C {
@Value('foo') // configuration injection: 'obj.xxx', 'arr[1]', ...
protected foo: string;
}Database access with declarative transactions
import { Controller, Get, Param, Delete, Put, Post, Body } from '@celljs/mvc/lib/node';
import { Transactional, OrmContext } from '@celljs/typeorm/lib/node';
import { User } from './entity';
@Controller('users')
export class UserController {
@Get()
@Transactional({ readOnly: true })
list(): Promise<User[]> {
return OrmContext.getRepository(User).find();
}
@Get(':id')
@Transactional({ readOnly: true })
get(@Param('id') id: number): Promise<User | null> {
return OrmContext.getRepository(User).findOneBy({ id });
}
@Post()
@Transactional()
create(@Body() user: User): Promise<User> {
return OrmContext.getRepository(User).save(user);
}
@Put()
@Transactional()
async modify(@Body() user: User): Promise<void> {
await OrmContext.getRepository(User).update(user.id, user);
}
@Delete(':id')
@Transactional()
async remove(@Param('id') id: number): Promise<void> {
await OrmContext.getRepository(User).delete(id);
}
}RPC between frontend, backend and services
// Shared contract
export const UserService = 'UserService';
export interface UserService {
hello(name: string): Promise<string>;
}
// Provider
import { Rpc } from '@celljs/rpc';
@Rpc(UserService)
export class UserServiceImpl implements UserService {
async hello(name: string): Promise<string> {
return `Hello, ${name}`;
}
}
// Consumer: a typed remote proxy is injected
import { Component } from '@celljs/core';
import { Autorpc } from '@celljs/rpc';
@Component()
export class Greeter {
@Autorpc(UserService)
protected userService: UserService;
}Runnable applications live in examples/: backend-app, sample-app (React), security-app, jwt-app, schedule, prisma-app, docker-app, standalone-app, mycli, tui-app and coding-agent-app.
Ecosystem
All packages are published under the @celljs scope as dual CommonJS / ES module builds.
| Area | Packages |
|---|---|
Core (packages/) | core, logger, web, mvc, http, express-adapter, serve-static, rpc, typeorm, cache, retry, schedule, security, jwt, oauth2-core, oauth2-client, oauth2-jose |
Cloud (cloud-packages/) | cloud, faas-adapter, lambda-adapter, fc-adapter, scf-adapter, vercel-adapter, oss, cos |
AI (ai-packages/) | ai-core, ai-pi, ai-agent, ai-coding-agent |
UI (ui-packages/) | react, widget, tui |
Toolchain (dev-packages/) | cli, vite, kit |
Documentation
cellCLI reference: commands, presets, deployers,cell.config.ts- Migrating from Cell 3.x (Cell 3.x remains available at tag
v3.9.0) - Design: architecture, modules, agent-first principles
- API reference, generated with TypeDoc
- Changelog
Contributing
Issues and pull requests are welcome. The repository is a Bun workspace monorepo built with Turborepo and TypeScript 7.
Prerequisites: Bun (version pinned in package.json → packageManager) and Node.js ^20.19.0 || >=22.12.0.
bun install # install dependencies and sync tsconfig references
bun run build # build all packages
bun run test # run all tests
bunx turbo run test --filter=@celljs/core # test one package
bun run lint # Biome (bun run format to fix)
bun changeset # describe your change for the next release