ドキュメント

TeamOnly ドキュメント

CLI、アプリが使う SDK、そして AI に何を書くべきかを教えるスキルファイル。技術的な内容を、短くまとめています。コーディングエージェントは、このページを /docs.md で Markdown として読めます。

クイックスタート

Node.js 20 以降が必要です。まだプランがない場合は、初めてログインするときに、カード不要の14日間無料トライアルを始めるか、お申し込みができます。こちらからお申し込みいただくこともできます。新しいフォルダか、既存のプロジェクトで:

  1. npx teamonly init で、ひな形のアプリと、AI ツールが従う指示書を追加します。
  2. npx teamonly login をパソコンごとに1回。会社のメールアドレスと、メールで届く6桁のコードを入力します。会社にまだプランがなければ、14日間の無料トライアルか、支払いページから申し込むプランを案内します。トライアルはすぐに始まります。メールアドレスの代わりに Enter を押すと、ブラウザでログインします。
  3. npx teamonly deploy で、アプリが https://<app>.<company>.teamonly.app で公開されます。

たとえばこうなります:

Terminal~/expenses
npx teamonly initAdded the TeamOnly skill, Cursor rules and SDK経費承認ツールを作って(AI がアプリを作成)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 にログインします。パソコンごとに1回。会社のメールアドレスと、メールで届く6桁のコードを入力するか、Enter を押してブラウザでログインします。--email と --code を使うと質問なしで同じことができます。AI ツールやスクリプト向けです。
npx teamonly trial --company "Acme"
カード不要で、御社の14日間無料トライアルを始めます。会社にまだプランがないときに、login のあとで使います。無料トライアルは会社のメールドメインごとに1回です。
npx teamonly subscribe --plan builder
申し込むか、トライアル終了後にアプリを再開します。builder、team、business から選びます。支払いページが開き、支払いが終わるとここでログインします。
npx teamonly init
このフォルダを準備します。ひな形のアプリを作るか、既存のプロジェクトに AI ツール向けの TeamOnly の指示書(Claude Code のスキル、Cursor のルール、AGENTS.md)と SDK を追加します。
npx teamonly deploy
アプリをビルドしてオンラインに置きます。最初のデプロイでデータベースとファイル保存を作成し、アプリのアドレスを表示します。
npx teamonly access
アプリを開ける人を表示します。only、add、remove にメールアドレスを付けるとリストを使い、everyone で全社に開きます。
npx teamonly roles
アプリ内の役割(承認者や経理など)を人に割り当てます。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 のアプリです。SDK のミドルウェアが、各リクエストに c.var.ctx としてコンテキストを渡します。内容は次のとおりです:

ctx.user
ログイン中の人: email、name、最初にアプリをデプロイした人なら isOwner、そしてこのアプリでのその人の役割 roles。コードが動く前に TeamOnly が検証済みです。身元情報をヘッダーから自分で読まないでください。
ctx.db
このアプリ専用の SQL データベース(Cloudflare D1 上の SQLite)。最初のデプロイで作成されます。
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。定期実行ジョブを参照。

ブラウザでは、teamonly/react の useUser() が { 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 を設定した場合はそちらに届きます(これも会社のアドレス)。
  • どのメールにも、どのアプリが送ったかを示す一文が入ります。
  • アプリごとの上限: 1時間に宛先100件、1日に500件、1通あたり宛先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分刻みで動くので、分は5の倍数にしてください。
  • timezone は省略でき、既定は UTC です。
  • ルートは teamonly/server の scheduled(...) で包みます。URL を開いた人には 404 が返ります。
  • ダッシュボードのアプリのページに、各ジョブの最後の実行と、成功したかどうかが表示されます。
  • 無料トライアルが終了すると、ジョブは一時停止します。

役割

承認者、経理、管理者などの役割は、コードではなく 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 向けにしたルールファイルを追加します。AI ツールはコードを書く前にこれを読みます。教える内容は次のとおりです:

  • 対応している唯一のアプリの形(下記)と、その範囲に収まること。
  • 身元情報には ctx.user を使い、独自のログイン、新規登録、パスワードの画面を書かないこと。
  • データベースサービス、Express、Supabase、Firebase を追加する代わりに ctx.db と ctx.files を使うこと。
  • APIキーは ctx.secrets に置き、決してコードに書かないこと。
  • メールは ctx.email で送り、決まった時刻の処理は定期実行ジョブにし、ctx.user.roles はサーバーで確認すること。
  • deploy の実行方法と、表示された問題の直し方。

目的は、最初のデプロイで動くことです。私たちが扱わないものに AI が何度も手を出すようなら、教えてください。それはスキルファイルのバグです。

MCP サーバー

パッケージ teamonly は MCP サーバーとしても動きます。Claude Desktop やターミナルのない Cursor のエージェントのように、ターミナルのコマンドよりツールを使うほうが得意な AI ツール向けです。デプロイではプロジェクトのファイルを読むので、あなたのパソコンで動きます。Claude Code には次のコマンドで追加します:

Terminal~/expenses
claude mcp add teamonly -- npx -y teamonly mcp
  • Cursor、Claude Desktop、Windsurf: それぞれの MCP 設定に { "mcpServers": { "teamonly": { "command": "npx", "args": ["-y", "teamonly", "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 として載っています。

AI がこの構成を覚える主な方法は今もスキルファイルとルールで、CLI もこれまでどおり使えます。ツールごとの設定方法と Cursor のワンクリック追加ボタン: TeamOnly の MCP サーバー。

対応しているアプリの形

  • 画面: Vite でビルドした React を、静的ファイルとして配信。
  • API: TypeScript か JavaScript の Hono アプリを、同じアドレスの /api 以下に。
  • 実行環境: Cloudflare Workers。標準の Web API が使え、Node の組み込みモジュールの多くは互換機能で動きますが、ネイティブモジュールや長時間動くプロセスは使えません。
  • 非対応: Python、Ruby、PHP、Docker コンテナ、WebSocket とリアルタイム更新、バックグラウンドワーカー、社外の人へのメール、社内ネットワーク上のサーバーへの接続、独自ドメイン、一般公開のアプリ。

制限

現在の制限:

  • Builder: 作成者1人、アプリ3つ。Team: 作成者もアプリも無制限。
  • 各アプリのデータベースとファイル保存は、Cloudflare D1 と R2 の制限に従います。
  • リクエストは、CPU 時間とメモリについて Cloudflare Workers の制限のもとで動きます。

全体のしくみについては 使い方とセキュリティをご覧ください。

アーリーアクセス

最初のツールを、今週公開しましょう。

TeamOnly はアーリーアクセス中で、すべてのプランを今すぐお申し込みいただけます。カード不要で14日間無料でお試しいただくか、お申し込みください。どちらの場合も御社の準備はすぐに整い、コマンド3つで最初のアプリが公開されます。

14日間無料で試すまたは今すぐ申し込む

トライアルはカード不要。その後は月額 $19 から、いつでも解約できます。

まだ検討中なら、最新情報を

会社のメールアドレスをお使いください。お知らせする価値のあるニュースがあるときだけ、たまにお送りします。

ご質問は hello@teamonly.dev へ。人が返信します。