Documentation
Ship your coding agent to every customer. Each customer gets an isolated cell with their repo cloned, indexed, and ready. Your agent codes inside their cell. Their source code never leaves it.
Quickstart
Get from zero to a deployed coding agent in under 5 minutes. Your customers will each get their own isolated cell with their repo, index, and agent runtime.
1. Install the CLI
npm install -g oncell
oncell login2. Write your agent
import { Agent, Context } from "oncell";
export class CodingAgent extends Agent {
cell = { compute: "4cpu-8gb", storage: "50gb" };
async setup(ctx: Context) {
await ctx.shell("color:#5cdb7f">`git clone ${ctx.config.repoUrl} /work`);
await ctx.index("/work");
}
async task(ctx: Context, instruction: string) {
const files = await ctx.search(instruction);
const plan = await ctx.llm(instruction, { context: files });
for (const step of plan.steps) {
await ctx.shell(step.command);
const result = await ctx.shell("npm test");
if (result.failed) {
const fix = await ctx.llm("color:#5cdb7f">`Fix: ${result.error}`);
await ctx.shell(fix.command);
}
}
await ctx.shell("git add -A && git commit -m '" + instruction + "'");
await ctx.shell("git push");
return { status: "done" };
}
}3. Deploy
oncell deployThat's it. Your coding agent is live. Each customer who connects gets their own cell — repo cloned, codebase indexed, agent ready to code.
Core Concepts
OnCell has three primitives: Agents, Cells, and Customers.
CodingAgent (your code)
└── deployed to oncell
└── Customer connects
└── Cell created
├── Repo cloned to local NVMe
├── Codebase indexed for search
└── Agent starts coding inside the cellCells
A cell is the atomic unit of oncell. For coding agents, each cell contains the customer's cloned repo on NVMe, a vector index of their codebase, a durable agent runtime, and an isolated test environment. One cell per customer.
Cell configuration
export class MyAgent extends Agent {
cell = {
compute: "4cpu-8gb", // CPU and RAM allocation
storage: "50gb", // NVMe storage per cell
gpu: "L4", // Optional GPU(L4, A10G)
packages: ["nodejs", "python3", "git"], // System packages
idleTimeout: "30m", // Auto-pause after inactivity
network: {
egress: "blocked", // Default: no outbound
allow: [ // Allowlisted domains
"api.openai.com",
"github.com",
"registry.npmjs.org"
]
}
};
}Available sizes
Cell lifecycle
Cell states:
CREATING → ACTIVE → PAUSING → PAUSED
↑ │
└──── WAKING ←─────────┘
ACTIVE: Agent running. Full compute allocated. $0.05/hr
PAUSED: Agent idle. Only storage persists. $0.001/hr
WAKING: Resuming from pause. ~200ms
Automatic transitions:
Active → Paused: after idle_timeout (default: 30 min)
Paused → Active: on next API call (automatic, ~200ms)Agents
An agent is a class that extends Agent. It defines what the cell looks like (cell), and what the agent does (setup and your custom methods).
Agent lifecycle
import { Agent, Context } from "oncell";
export class MyAgent extends Agent {
cell = { compute: "2cpu-4gb", storage: "10gb" };
async setup(ctx: Context) {
// Called ONCE when a new customer is created.
// State persists across all future calls.
await ctx.shell("npm install pandas");
await ctx.upload("data/", { fromUrl: ctx.config.dataUrl });
await ctx.index("data/");
}
async analyze(ctx: Context, question: string) {
// Called every time the customer sends a request.
const relevant = await ctx.search(question);
const code = await ctx.llm("color:#5cdb7f">`Write code to answer: ${question}`, { context: relevant });
const result = await ctx.shell("color:#5cdb7f">`node -e '${code}'`);
return { answer: result.stdout };
}
}Every public method (except setup) becomes an API endpoint that customers can call.
Context API
The ctx object is passed to every agent method. It's your interface to the cell's capabilities.
ctx.shell()
Execute shell commands inside the cell.
const result = await ctx.shell("npm test");
result.stdout; // Standard output
result.stderr; // Standard error
result.exitCode; // Exit code(0 = success)
result.failed; // true if exitCode !== 0ctx.llm()
Call any LLM. Routes to OpenAI, Anthropic, or a local model on the cell's GPU. Response is automatically checkpointed.
// Simple call
const response = await ctx.llm("Explain this code", { context: files });
// With model selection
const response = await ctx.llm("Explain this code", {
model: "claude-sonnet-4-20250514",
context: files,
temperature: 0.2
});
// With tool calls
const response = await ctx.llm("Fix the failing test", {
tools: [ctx.shell, ctx.search] // Agent can call these
});ctx.memory
Persistent key-value store scoped to each customer. Survives cell pause/resume and crashes.
// Store
ctx.memory.set("lastTask", instruction);
ctx.memory.set("preferences", { language: "typescript" });
// Retrieve
const last = ctx.memory.get("lastTask");
const prefs = ctx.memory.get("preferences", { default: {} });
// List keys
const keys = ctx.memory.keys();
// Delete
ctx.memory.delete("oldKey");Storage
Each cell has NVMe-backed local storage. Files persist across agent calls, pause/resume, and crash recovery. Read speed: 7 GB/s.
# Write files
await ctx.shell("echo 'hello' > /work/output.txt")
# Read files
result = await ctx.shell("cat /work/output.txt")
# Upload from URL
await ctx.upload("/work/data/", from_url="">https://example.com/dataset.csv")
# Storage is scoped to the cell — Customer A's files
# are physically separate from Customer B's files.Vector Search
Built-in vector search, stored locally on NVMe. No external vector database needed.
// Index a directory
await ctx.index("/work/src/", { glob: "**/*.{ts,py,go,md}" });
// Search
const results = await ctx.search("authentication middleware", { topK: 10 });
for (const result of results) {
console.log(result.path); // /work/src/auth/middleware.ts
console.log(result.content); // File content(or relevant chunk)
console.log(result.score); // Similarity score(0-1)
}
// Re-index after changes (incremental)
await ctx.index("/work/src/");Durability
Every await in your coding agent is a durable checkpoint. If the cell crashes mid-test-run, the agent resumes from the last passing step — not from git clone.
Coding agent executes "Add dark mode":
Step 1: ctx.search("dark mode") ✓ done (result saved)
Step 2: ctx.llm("plan changes") ✓ done (tokens spent, result saved)
Step 3: ctx.shell("edit theme.ts") ✓ done (file written)
Step 4: ctx.shell("edit settings") ✓ done (file written)
Step 5: ctx.shell("npm test") ✓ done (tests passed)
Step 6: ctx.shell("edit toggle") ✓ done (file written)
Step 7: ctx.shell("npm test") ⟳ running...
──── HOST REBOOTS ────
Cell restarts on new host.
Replays journal:
Steps 1-6: return cached results (not re-executed)
Step 2: LLM tokens NOT re-spent
Step 7: re-execute from here ← resumes npm test
Customer never noticed. PR still gets created.Side effects (PRs created, commits pushed) are not re-executed on replay. Only the interrupted step is retried.
Isolation
Each customer's source code runs in a gVisor sandbox. Customer A's repo physically cannot be accessed by Customer B's cell — different processes, different filesystems, different network namespaces.
Isolation for coding agents:
✓ Separate filesystem Customer A's repo invisible to Customer B
✓ Scoped git credentials Each cell has its own git token
✓ Separate process space npm test runs in complete isolation
✓ Network egress blocked Default: no outbound except allowlisted
✓ Allowlisted domains github.com, registry.npmjs.org, LLM APIs
✓ gVisor syscall filter Only ~68 host syscalls (vs ~350 in Docker)
✓ Resource limits CPU, RAM, storage capped per cellCustomer source code never leaves the cell. Not separated by IAM policies — physically isolated at the kernel level. SOC2 and HIPAA compliant by architecture.
Deployment
oncell deploy
$ oncell deploy
Building agent image...
✓ Image built (8s)
✓ Cell template created (compute: 4cpu-8gb, storage: 50gb)
✓ Endpoint live: https://your-agent.oncell.run
Dashboard: "color:#7dd3fc">https://console.oncell.ai/your-agentEnvironments
oncell deploy --env staging
oncell deploy --env production
oncell promote staging productionLogs
oncell logs --customer acme-corp --follow
oncell cells list
oncell cells inspect acme-corpCustomer API
Manage customers from your existing backend.
import { OnCell } from "oncell";
const oncell = new OnCell();
// Create a customer (provisions a cell, runs setup())
const customer = await oncell.customers.create({
id: "acme-corp",
config: {
repoUrl: "https://github.com/acme/webapp",
language: "typescript"
}
});
// Run a task
const result = await oncell.agents.run({
customer: "acme-corp",
method: "task",
input: { instruction: "Add dark mode to settings page" }
});
// Stream results
for await (const event of oncell.agents.stream({
customer: "acme-corp",
method: "task",
input: { instruction: "Fix the auth bug" }
})) {
console.log(event);
}
// Pause / Resume / Delete
await oncell.customers.pause("acme-corp");
await oncell.customers.resume("acme-corp"); // ~200ms
await oncell.customers.delete("acme-corp");REST API
POST /v1/customers Create customer
GET /v1/customers/:id Get customer
DELETE /v1/customers/:id Delete customer
POST /v1/customers/:id/pause Pause cell
POST /v1/customers/:id/resume Resume cell
POST /v1/agents/:method Run agent method
POST /v1/agents/:method/stream Stream agent methodConfiguration
LLM configuration
llm:
default: openai
providers:
openai:
api_key: $OPENAI_API_KEY
model: gpt-4o
anthropic:
api_key: $ANTHROPIC_API_KEY
model: claude-sonnet-4-20250514
local:
model: meta-llama/Llama-3-8B
gpu: requiredNetwork
network:
egress: blocked
allow:
- api.openai.com
- api.anthropic.com
- github.com
- "*.amazonaws.com"Secrets
oncell secrets set OPENAI_API_KEY=sk-...
oncell secrets set GITHUB_TOKEN=ghp_...Pricing
Free tier: 3 cells, 100 compute hours/month, 5 GB storage per cell.
Examples
Real-world coding agent patterns. Each example is production-ready — deploy with oncell deploy.
Full-Stack Coding Agent
Clones the customer's repo, indexes their codebase, plans and implements changes, runs tests, and pushes a PR.
import { Agent, Context } from "oncell";
export class CodingAgent extends Agent {
cell = { compute: "4cpu-8gb", storage: "50gb", packages: ["nodejs", "git"] };
async setup(ctx: Context) {
await ctx.shell("color:#5cdb7f">`git clone ${ctx.config.repoUrl} /work`);
await ctx.index("/work");
}
async task(ctx: Context, instruction: string) {
const files = await ctx.search(instruction);
const plan = await ctx.llm(instruction, { context: files });
for (const step of plan.steps) {
await ctx.shell(step.command);
await ctx.shell("npm test");
}
await ctx.shell("git add -A && git commit -m '" + instruction + "' && git push");
return { status: "done" };
}
}Code Review Agent
Reviews PRs automatically — checks for bugs, security issues, and style violations in the customer's codebase.
import { Agent, Context } from "oncell";
export class ReviewAgent extends Agent {
cell = { compute: "4cpu-8gb", storage: "50gb", packages: ["git"] };
async setup(ctx: Context) {
await ctx.shell("color:#5cdb7f">`git clone ${ctx.config.repoUrl} /work`);
await ctx.index("/work");
}
async reviewPR(ctx: Context, prNumber: number) {
await ctx.shell("color:#5cdb7f">`cd /work && git fetch origin pull/${prNumber}/head:pr`);
const diff = await ctx.shell("cd /work && git diff main...pr");
const context = await ctx.search(diff.stdout);
const review = await ctx.llm("Review this PR for bugs and security issues", {
context: [...context, { content: diff.stdout }]
});
return { review, approved: !review.includes("CRITICAL") };
}
}Migration Agent
Upgrades dependencies, migrates APIs, and refactors code across the entire codebase with test verification.
import { Agent, Context } from "oncell";
export class MigrationAgent extends Agent {
cell = { compute: "8cpu-16gb", storage: "50gb", packages: ["nodejs", "git"] };
async setup(ctx: Context) {
await ctx.shell("color:#5cdb7f">`git clone ${ctx.config.repoUrl} /work`);
await ctx.index("/work");
}
async migrate(ctx: Context, from: string, to: string) {
const files = await ctx.search("color:#5cdb7f">`import.*${from}`);
const plan = await ctx.llm(
"color:#5cdb7f">`Migrate all usages of ${from} to ${to}`,
{ context: files }
);
for (const step of plan.steps) {
await ctx.shell(step.command);
const tests = await ctx.shell("npm test");
if (tests.failed) {
const fix = await ctx.llm("color:#5cdb7f">`Tests failed after migration step. Fix:`, {
context: [{ content: tests.stderr }]
});
await ctx.shell(fix.command);
}
}
await ctx.shell("color:#5cdb7f">`git add -A && git commit -m 'Migrate ${from} to ${to}'`);
await ctx.shell("git push");
return { status: "done", filesChanged: plan.steps.length };
}
}Security Scanner (Air-Gapped)
Scans customer codebases for vulnerabilities with zero internet access. Source code never leaves the cell.
import { Agent, Context } from "oncell";
export class SecurityAgent extends Agent {
cell = {
compute: "4cpu-8gb",
storage: "20gb",
network: { egress: "blocked" } // No internet access
};
async setup(ctx: Context) {
await ctx.shell("color:#5cdb7f">`git clone ${ctx.config.repoUrl} /work`);
await ctx.index("/work");
}
async scan(ctx: Context) {
const files = await ctx.search("password secret key token auth credential");
// LLM runs locally on GPU — no data leaves the cell
const findings = await ctx.llm("Find security vulnerabilities", {
context: files, model: "local"
});
return { findings };
}
}