Документация

Документация TeamOnly

CLI, SDK, которым пользуется ваше приложение, и файл навыка, который объясняет вашему ИИ, что писать. Технично и коротко. ИИ-агенты могут прочитать эту страницу в Markdown по адресу /docs.md.

Быстрый старт

Нужен Node.js 20 или новее. Тарифа ещё нет? При первом входе можно начать бесплатный пробный период на 14 дней без карты или оформить подписку. Также можно оформить подписку здесь. В новой папке или в уже существующем проекте:

  1. npx teamonly init добавляет стартовое приложение и инструкции, которым следует ваш ИИ-инструмент.
  2. npx teamonly login один раз на каждом компьютере. Введите рабочую почту и 6-значный код, который мы пришлём письмом. Если у компании ещё нет тарифа, команда предложит бесплатный пробный период на 14 дней, который начнётся сразу, или тариф со страницей оплаты. Нажмите Enter вместо адреса, чтобы войти через браузер.
  3. npx teamonly deploy публикует приложение по адресу https://<app>.<company>.teamonly.app.

Выглядит это так:

Terminal~/expenses
npx teamonly initAdded the TeamOnly skill, Cursor rules and SDKСделай инструмент для согласования расходов(ваш ИИ делает приложение)npx teamonly loginSigned in as dana@acme.comnpx teamonly deployLive at https://expenses.acme.teamonly.appOnly @acme.com accounts can sign in

Первая публикация создаёт приложение, его базу данных и хранилище файлов. Следующие публикации обновляют то же приложение по тому же адресу.

Команды CLI

npx teamonly login
Войти в TeamOnly с этого компьютера, один раз на каждом компьютере. Введите рабочую почту и 6-значный код из нашего письма или нажмите Enter, чтобы войти через браузер. --email и --code делают то же самое без вопросов, для ИИ-инструментов и скриптов.
npx teamonly trial --company "Acme"
Начать бесплатный пробный период на 14 дней для вашей компании, без карты. Используйте после login, если у компании ещё нет тарифа. Один пробный период на почтовый домен компании.
npx teamonly subscribe --plan builder
Оформить подписку или снова включить приложения после пробного периода. Выберите builder, team или business. Откроется страница оплаты, а после оплаты вы войдёте здесь.
npx teamonly init
Подготовить папку: стартовое приложение или инструкции TeamOnly для вашего ИИ-инструмента (навык Claude Code, правила Cursor, AGENTS.md) и SDK в существующем проекте.
npx teamonly deploy
Собрать приложение и опубликовать его. При первой публикации создаёт базу данных и хранилище файлов. Выводит адрес приложения.
npx teamonly access
Показать, кто может открыть приложение. Добавьте only, add или remove с адресами почты, чтобы задать список, или everyone для всей компании.
npx teamonly roles
Выдать людям роли внутри приложения, например approver или finance. roles add approver dana@acme.com выдаёт роль, roles remove забирает её, а roles без аргументов показывает, у кого какая роль. Только адреса компании.
npx teamonly secrets set NAME
Сохранить секрет для этого приложения. Значение запрашивается отдельно, поэтому оно не попадает в историю командной строки.
npx teamonly logs
Смотреть запросы работающего приложения, вывод console.log и ошибки в реальном времени. Остановить: Ctrl+C.
npx teamonly whoami
Показать, под кем вы вошли, ваш тариф и ваши приложения.
npx teamonly delete
Удалить работающее приложение вместе с базой данных и файлами. Сначала попросит ввести название приложения.
npx teamonly logout
Выйти из TeamOnly на этом компьютере.

SDK

Ваш API это приложение на Hono. Middleware из SDK даёт каждому запросу контекст в c.var.ctx:

ctx.user
Вошедший пользователь: email, name, isOwner для того, кто первым опубликовал приложение, и roles, роли этого человека в приложении. TeamOnly проверяет его до запуска вашего кода. Никогда не читайте личность из заголовков сами.
ctx.db
Собственная SQL-база данных этого приложения (SQLite на Cloudflare D1). Создаётся при первой публикации.
ctx.files
Хранилище файлов этого приложения: put, get, list, delete.
ctx.secrets
Значения, заданные через npx teamonly secrets set. Читаются через ctx.secrets.get(name).
ctx.email
Отправляет письма коллегам: send({ to, subject, text, html?, replyTo? }). См. раздел Почта.
ctx.schedule
Название задачи, когда TeamOnly запускает задачу по расписанию, иначе undefined. См. раздел Задачи по расписанию.

В браузере useUser() из teamonly/react возвращает { email, name, roles }.

api/index.tsпример
import { Hono } from 'hono'
import { teamonly, type TeamOnly } from 'teamonly/server'

const app = new Hono<TeamOnly>()
app.use('*', teamonly())

// Who is signed in. Verified before your code runs.
app.get('/api/me', (c) => {
  return c.json(c.var.ctx.user) // { email: 'dana@acme.com', name: 'Dana Okafor', isOwner: false, roles: ['approver'] }
})

// Save to this app's own database.
app.post('/api/expenses', async (c) => {
  const { db, user } = c.var.ctx
  const { amount, reason } = await c.req.json()
  await db
    .prepare('INSERT INTO expenses (amount, reason, submitted_by) VALUES (?, ?, ?)')
    .bind(amount, reason, user.email)
    .run()
  return c.json({ ok: true })
})

// Store an uploaded receipt in this app's file storage.
app.put('/api/receipts/:id', async (c) => {
  await c.var.ctx.files.put(`receipts/${c.req.param('id')}`, c.req.raw.body)
  return c.json({ ok: true })
})

// Read a secret set with: npx teamonly secrets set QUICKBOOKS_KEY
app.get('/api/sync', async (c) => {
  const key = c.var.ctx.secrets.get('QUICKBOOKS_KEY')
  // ...
})

export default app

Почта

Приложение может отправлять письма людям из вашей компании через ctx.email.send(), например чтобы сообщить согласующему, что расход ждёт решения.

api/index.tsпример
// Tell the approver an expense is waiting.
await c.var.ctx.email.send({
  to: 'priya@acme.com',   // one address or a list, up to 50
  subject: 'An expense is waiting for you',
  text: 'Dana sent a $42 expense. Review it: https://expenses.acme.teamonly.app',
})
  • Только на адреса в собственных почтовых доменах вашей компании, то есть тем же людям, которые могут войти. Любой другой адрес отклоняется, и ничего не отправляется.
  • Письма уходят с notify@teamonly.app от имени приложения в вашей компании, например «Expenses at Acme». Ответы приходят владельцу приложения, если вы не задали replyTo (тоже адрес компании).
  • В каждом письме есть строка о том, какое приложение его отправило.
  • Ограничения на приложение: 100 получателей в час и 500 в день, до 50 получателей в одном письме.
  • Страница приложения в панели управления показывает, сколько писем оно отправило за последние 30 дней.
  • Локально, в npm run dev, письма выводятся в терминал, а не отправляются.
  • Письма людям за пределами компании не поддерживаются.

Задачи по расписанию

Для ежедневных сводок, напоминаний и отчётов в конце месяца перечислите задачи в teamonly.json. TeamOnly вызывает каждый маршрут в эти моменты.

teamonly.jsonпример
{
  "name": "expenses",
  "timezone": "America/New_York",
  "schedules": [
    { "name": "daily-digest", "cron": "0 9 * * 1-5", "path": "/api/cron/daily-digest" }
  ]
}
api/index.tsпример
import { scheduled } from 'teamonly/server'

// Runs at 9am New York time, Monday to Friday.
app.post('/api/cron/daily-digest', scheduled(async (c) => {
  const { db, email } = c.var.ctx
  // ...find what is waiting, then email each approver
  return c.json({ ok: true })
}))
  • У cron пять полей: минута, час, день месяца, месяц, день недели. Задачи запускаются с шагом в 5 минут, поэтому минуты должны быть кратны 5.
  • timezone необязателен, по умолчанию UTC.
  • Оберните маршрут в scheduled(...) из teamonly/server. Тот, кто откроет этот адрес, получит 404.
  • Страница приложения в панели управления показывает последний запуск каждой задачи и то, успешно ли он прошёл.
  • Задачи приостанавливаются, когда бесплатный пробный период закончился.

Роли

Роли вроде approver, finance или admin хранятся в TeamOnly, а не в вашем коде. Владелец приложения или администратор выдаёт их на странице приложения в панели управления или через npx teamonly roles. Только адреса компании.

Terminal~/expenses
npx teamonly roles add approver dana@acme.comGave dana@acme.com the role approverapprover: dana@acme.com
api/index.tsпример
// Only approvers can approve.
app.post('/api/expenses/:id/approve', async (c) => {
  const { user } = c.var.ctx
  if (!user.roles.includes('approver')) return c.json({ error: 'Approvers only' }, 403)
  // ...
})

Приложение читает их как ctx.user.roles и само решает, что можно каждой роли. Код для входа писать по-прежнему не нужно.

Файл навыка

init добавляет файл навыка для Claude Code и то же содержимое в виде файла правил для Cursor. Ваш ИИ-инструмент читает его, прежде чем писать код. Он учит:

  • Одной поддерживаемой структуре приложения (ниже) и тому, чтобы не выходить за её рамки.
  • Брать личность из ctx.user и никогда не писать свои экраны входа, регистрации или паролей.
  • Использовать ctx.db и ctx.files вместо подключения сервиса баз данных, Express, Supabase или Firebase.
  • Хранить API-ключи в ctx.secrets и никогда в коде.
  • Отправлять письма через ctx.email, запускать работу по времени как задачи по расписанию и проверять ctx.user.roles на сервере.
  • Запускать deploy и исправлять то, о чём он сообщает.

Смысл в том, чтобы первая публикация сработала. Если ваш ИИ упорно тянется к тому, чего у нас нет, напишите нам: это ошибка в файле навыка.

MCP-сервер

Пакет teamonly также запускает MCP-сервер для ИИ-инструментов, которым удобнее вызывать инструменты, чем команды в терминале, например Claude Desktop или агента Cursor без терминала. Он работает на вашем компьютере, потому что для публикации нужно прочитать файлы проекта. Добавить его в Claude Code:

Terminal~/expenses
claude mcp add teamonly -- npx -y teamonly mcp
  • Cursor, Claude Desktop и Windsurf: добавьте { "mcpServers": { "teamonly": { "command": "npx", "args": ["-y", "teamonly", "mcp"] } } } в их настройки MCP.
  • VS Code: в .vscode/mcp.json ключ называется servers, с "type": "stdio".
  • Его 12 инструментов: get_app_rules, init, deploy, status, logs, access, roles, set_secret, sign_in, start_trial, subscribe, delete_app.
  • Есть в официальном MCP Registry под именем dev.teamonly/teamonly.

Файл навыка и правила остаются главным способом, которым ваш ИИ узнаёт стек, а CLI работает точно так же, как раньше. Настройка для каждого инструмента и кнопка установки в Cursor в один клик: MCP-сервер TeamOnly.

Поддерживаемая структура приложения

  • Фронтенд: React, собранный через Vite, отдаётся как статические файлы.
  • API: приложение на Hono на TypeScript или JavaScript, по пути /api, на том же адресе.
  • Среда выполнения: Cloudflare Workers. Стандартные веб-API; большинство встроенных модулей Node через режим совместимости, но без нативных модулей и долгих процессов.
  • Не поддерживается: Python, Ruby, PHP, Docker-контейнеры, WebSockets и обновления в реальном времени, фоновые процессы, письма людям за пределами компании, подключение к серверам во внутренней сети компании, свои домены, публичные приложения.

Ограничения

Ограничения на сегодня:

  • Builder: 1 автор, 3 приложения. Team: без ограничений на авторов и приложения.
  • База данных и хранилище файлов каждого приложения подчиняются ограничениям Cloudflare D1 и R2.
  • Запросы выполняются в рамках ограничений Cloudflare Workers по процессорному времени и памяти.

Подробнее о том, как всё устроено: Как это работает и Безопасность.

Ранний доступ

Запустите первый инструмент на этой неделе.

TeamOnly в раннем доступе, и все тарифы уже открыты. Попробуйте бесплатно 14 дней без карты или оформите подписку. В любом случае компания готова сразу, а три команды запускают первое приложение.

14 дней бесплатноИли оформите подписку сейчас

Для пробного периода карта не нужна. Дальше от $19 в месяц, отменить можно в любой момент.

Пока не готовы? Получайте новости

Укажите рабочую почту. Пишем редко и только когда есть что рассказать.

Вопросы пишите на hello@teamonly.dev, отвечает живой человек.