ドキュメント
TeamOnly ドキュメント
CLI、アプリが使う SDK、そして AI に何を書くべきかを教えるスキルファイル。技術的な内容を、短くまとめています。コーディングエージェントは、このページを /docs.md で Markdown として読めます。
クイックスタート
Node.js 20 以降が必要です。まだプランがない場合は、初めてログインするときに、カード不要の14日間無料トライアルを始めるか、お申し込みができます。こちらからお申し込みいただくこともできます。新しいフォルダか、既存のプロジェクトで:
npx teamonly initで、ひな形のアプリと、AI ツールが従う指示書を追加します。npx teamonly loginをパソコンごとに1回。会社のメールアドレスと、メールで届く6桁のコードを入力します。会社にまだプランがなければ、14日間の無料トライアルか、支払いページから申し込むプランを案内します。トライアルはすぐに始まります。メールアドレスの代わりに Enter を押すと、ブラウザでログインします。npx teamonly deployで、アプリがhttps://<app>.<company>.teamonly.appで公開されます。
たとえばこうなります:
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.secretsnpx 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 } を返します。
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() で社内の人にメールを送れます。たとえば、承認待ちの経費があることを承認者に知らせるときです。
// 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 がその時刻に各ルートを呼び出します。
{
"name": "expenses",
"timezone": "America/New_York",
"schedules": [
{ "name": "daily-digest", "cron": "0 9 * * 1-5", "path": "/api/cron/daily-digest" }
]
}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 で割り当てます。会社のアドレスのみです。
npx teamonly roles add approver dana@acme.comGave dana@acme.com the role approverapprover: dana@acme.com// 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 には次のコマンドで追加します:
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つで最初のアプリが公開されます。
まだ検討中なら、最新情報を
ご質問は hello@teamonly.dev へ。人が返信します。