The Coline App SDK: apps, tools, file types and surfaces that run inside Coline workspaces, and public websites with Coline Sites. TypeScript, with an in-memory test workspace. MIT.
The Coline App SDK — define apps that live inside Coline workspaces: Kairo tools, file types with rich previews, home surfaces, app storage, scheduled triggers, and external API access. Coline hosts your logic; there are no servers to deploy unless you want them.
npx create-coline-app my-app
import { z } from "zod/v4";
import { defineApp, defineTool, ui } from "@colineapp/sdk/v2";
const createTodo = defineTool({
name: "todos.create_todo",
description: "Create a todo with a title.",
input: z.object({ title: z.string().min(1) }),
effect: "write", // enforced by the runtime as a hard capability ceiling
execute: async (input, ctx) => {
const file = await ctx.coline.files.create({
typeKey: "todos.todo",
name: input.title,
document: { title: input.title, status: "open" },
});
return {
output: { fileId: file.fileId },
card: ui.reference({ kind: "file", id: file.fileId }),
};
},
});
export default defineApp({
key: "todos",
name: "Todos",
permissions: ["files.read", "files.write", "ai.tools"],
hosting: { default: "coline" },
surfaces: { home: { tier: "tree" } },
tools: [createTodo],
handlers: {
renderHome: async (ctx) => {
const { files } = await ctx.coline.files.list({ typeKey: "todos.todo" });
return ui.stack([
ui.heading("Todos"),
...files.map((f) => ui.fileCard({ title: f.name, fileId: f.fileId })),
]);
},
},
});
One definition produces two artifacts: a serializable manifest (what the app may do — reviewed and consented to) and a runtime bundle (what it does). Every capability call is checked against the workspace's grants, the acting user's access, and the declared tool effect.
The same coline.* object everywhere your code runs — tools, render
handlers, schedules, hosted or external:
coline.files — create/read/update/trash workspace filescoline.storage.kv / coline.storage.collection(name) — app-private
key-value state and queryable recordscoline.members, coline.notifications, coline.searchcoline.net.fetch — external HTTP through Coline's allowlist, with
{{secret:KEY}} server-side credential injectionimport { createTestWorkspace } from "@colineapp/sdk/testing";
import app from "./app.config";
const ws = createTestWorkspace(app);
await ws.invokeTool("todos.create_todo", { title: "Ship it" });
expect(ws.files.byType("todos.todo")).toHaveLength(1);
@colineapp/sdk/testing runs your app against an in-memory workspace with
the same capability contract as production.
| Entry | Contents |
|---|---|
@colineapp/sdk/v2 | defineApp, defineTool, defineFileType, ui, actions, manifest schemas, capability types, createColineAppHandler for external hosting |
@colineapp/sdk/testing | createTestWorkspace — the in-memory test harness |
@colineapp/sdk | The legacy v1 surface (frozen; do not use for new apps) |
Full guides at coline.app/developers/docs.
MIT © Coline
Run coline-app check before pushing: it checks types, the manifest, hosted logic,
and the React bundle without uploading. dev --internal updates one development
version; install it in the workspace and reload after changes. The CLI bundles
from the app's installed dependencies and preserves imported CSS and inline assets.
Compile app-specific Tailwind utilities to CSS before importing them.
The starter includes a React home and editor, tree mobile fallback, and a tool.
Use coline.tools.invoke or actions.invokeTool to run the same declared tool
from UI that Kairo runs. Save with expectedVersion to detect concurrent edits.
Homes/editors can write within grants; previews and server render handlers cannot.
createTestWorkspace(app).client() tests the interactive contract and
grantedPermissions simulates revoked consent.
New tasks, calendar, messages, and references capabilities require their
explicit manifest permissions and retain the invoking user's workspace access.
Use files.list({ scope: "workspace" }) for shared files; document writes stay
with the owning app. Collections are install-private. Code integration and a
native mobile React runtime are separate work.