tyrekick について
Tyrekickは、プロトタイプにフィードバック用ウィジェットを追加し、レビュアーがページ要素にコメントを固定できるようにします。コーディングエージェントは、要素の表示テキストや見出し、ページエラーなどの情報とともにコメントを取得して対応し、解決済みにできます。
主な機能
- 01ページ要素へのコメント固定
- 02文脈情報付きフィードバック収集
- 03MCP経由のコメント取得と対応
- 04解決時のピン状態更新
- 05コメント一覧と下書き復元
- 06管理下のエンドポイントへの送信
活用シーン
- 01プロトタイプページのレビュー収集
- 02コーディングエージェントによる指摘修正
- 03フィードバックとページエラーの確認
- 04管理下の保存先へのコメント転送
MCP 対応
TyrekickのMCPサーバーは、フィードバックの一覧、取得、分類、解決、統計のツールを提供します。コーディングエージェントは設定済みWorkerからコメントを取得し、解決済みにできます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y tyrekick-mcpTYREKICK_URLBase URL of your deployed Tyrekick feedback worker (e.g. https://tyrekick-feedback.you.workers.dev)TYREKICK_TOKENシークレットBearer token for the worker's management routes (set via `wrangler secret put TYREKICK_TOKEN`)ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
6掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| limit | integer | いいえ | 返す項目の最大数(worker のデフォルトは 50、最大 200) |
| route | string | いいえ | この route に残されたフィードバックのみを返します |
| since | string | いいえ | この ISO-8601 タイムスタンプ以降に作成されたフィードバックのみを返します |
| status | enum | いいえ | この status のフィードバックのみを返します(open = 未トリアージ)open | approved | declined | resolved |
| project | string | いいえ | この project_name のフィードバックのみを返します(1 つの worker で複数のプロジェクトに対応できます) |
詳細
Tyrekick
リリース前に、しっかりチェックしましょう。 信頼できる人に AI で作成したプロトタイプをレビューしてもらい、コーディングエージェントにフィードバックを反映させましょう。
レビュアーはアカウントもトレーニングも不要で、公開中のページに直接コメントをピン留めできます。コーディングエージェントは、対象の要素、その表示テキスト、セクションの見出し、ページエラーを添えて MCP 経由でコメントを取得し、指摘された点を修正して解決済みとしてマークします。レビュアーのピンはメモ付きで緑色に変わります。フィードバックをプロンプトに打ち直す必要はもうありません。

▶ ライブデモを試す · クイックスタート · ドキュメント · 「アウターループ」— これが必要な理由
実際の映像です。ライブデモにコメントがピン留めされ、エージェントが修正すると、ピンが緑色に変わります。打ち直しも、トラッカーも、アカウントも必要ありません。
仕組み
reviewer's browser destination YOU own your coding agent
┌──────────────────┐ POST ┌────────────────────┐ MCP ┌─────────────────┐
│ pin a comment on │ ────────► │ Discord webhook or │ ◄───────► │ "fix the open │
│ the live page │ │ your CF Worker │ │ feedback" │
└──────────────────┘ └────────────────────┘ └─────────────────┘
ウィジェットは、依存関係のない約 14 KB(gzip 圧縮時)の単一スクリプトで、ページと干渉しないよう Shadow DOM にレンダリングされます。Tyrekick のバックエンドもアカウントもなく、外部への通信もありません。フィードバックはレビュアーのブラウザーから、あなたが所有する送信先へ直接 POST されます。これは、エージェントが構築したプロトタイプに複数の人の目が必要になったときのためのものです。スクリーンショットをグループチャットに貼り付けて返信を見失う代わりに、すべてのコメントが構造化され、バージョン管理され、該当箇所にピン留めされます。
コメントを残したあともピンはページ上に残ります(操作するまでは薄く表示されます)。ピンにカーソルを合わせるとテキストを確認でき、クリックするとその場で返信、再試行、破棄の操作を行えるスレッドが開きます。レビュアーはコメントドロワー(すべてのピンとそのテキストを一覧表示する右側のパネル。項目をクリックすると該当箇所に戻り、ピンをすべて非表示にすることもできます)、下書きの復元、キーボードとタッチの完全なサポート(Cmd/Ctrl+Enter で送信)も利用できます。persist: true(デフォルト)の場合、localStorage は再読み込み後に未送信の作業を復元するためだけに使用されます。送信できなかったコメントは再読み込み後に再表示され、再試行ボタンと破棄ボタンが付きます。ウィンドウサイズが変わっていても、コメントの対象だった要素に再びピン留めされます。
エージェント向け: プロジェクトに Tyrekick を導入しますか?
make-reviewableスキルを使ってください。1 文で、必要に応じてページをホストし、送信先を選び、ワーカーをデプロイし、ウィジェットをインストールし、MCP を接続して、レビュアーに送る依頼文の下書きを作成します。または、AGENTS.mdの手順に従ってください。
詳細なドキュメントはdocs/にあります:クイックスタート · はじめに · 設定 · レビュアーの利用体験 · 送信先 · エージェントのループ · ペイロードのリファレンス · トラブルシューティングと FAQ
プロトタイプを一般公開して共有しますか? まずはプロトタイプを一般公開するをご覧ください。続いて、機能別ガイドをご確認ください:レート制限 · 共同レビュー · AI 自動返信。
60秒クイックスタート(Discord)
最も手早く始めるには、自分で管理している Discord チャンネルを使います。フィードバックが自分の管理下にある場所へ届くことを確認するための、まずはお試しの方法です。永続化、ステータス管理、MCP 経由でエージェントが対応を完了する機能などを備えた完全版は、以下のワーカーの送信先にあります。
コマンド1つ(プロジェクトフォルダーから実行):
npx tyrekick init
Webhook URL を尋ね、スクリプトタグを挿入して、テストコメントを送信します。手動で設定する場合:
- Discord で サーバー設定 → 連携サービス → Webhook → 新しい Webhook を開き、チャンネルを選んで Webhook URL をコピーします。
- その URL を以下のコードに貼り付けて、プロトタイプの
</body>の直前に追加します。
<script
src="https://cdn.jsdelivr.net/npm/tyrekick@latest/dist/tyrekick.js"
data-webhook="https://discord.com/api/webhooks/XXXX/YYYY"
data-app-version="v0.1"
data-transport="discord"
data-project-name="My Prototype"
data-accent="#4f46e5"
data-position="bottom-right"
data-branding="true"
></script>
IIFE ビルドは、DOMContentLoaded 時に自身の <script> タグの data-* 属性から自動的に初期化されます。レビュー担当者には画面の隅に「フィードバックを送る」ボタンが表示され、各コメントは読みやすいメッセージとして Discord チャンネルに届きます。
必須なのは
data-webhookとdata-app-versionのみです。それ以外はすべて任意で、設定表にあるデフォルト値が使用されます。
セルフホスティング/所有するストレージ
Discord は手軽に使えるデフォルトの送信先ですが、自分で管理するストレージにデータを保存したい場合は、ペイロードを永続化するエンドポイントを指定して JSON トランスポート(transport: "json"、デフォルト)を使います。
- Cloudflare テンプレート(TypeScript): デプロイ可能な Worker の例は
destinations/cloudflareを参照してください。v2 ペイロードを受け取り、検証して、自分で管理するストレージに書き込みます。コードを自分で管理できるため、スパム検証を追加するのにも適しています。 - 同一オリジンの Pages Function: プロトタイプが Cloudflare Pages でホストされている場合は、同じオリジンに Pages Function(例:
/api/feedback)を配置し、webhookに相対 URL または同一オリジンの URL を設定します。同一オリジンなら、CORS の設定は不要です。
CORS が有効なエンドポイントやフォームバックエンドも使用できます。transport: "json" の場合、成功とみなされるのは HTTP 2xx で、レスポンス本文が返される場合は {"ok":false} 以外である必要があります。
エージェントのループ(MCP)
Tyrekick が存在する理由です。Cloudflare Worker の送信先を使えば、フィードバックを収集するだけでなく、コーディングエージェントが取得して対応し、解決できます。
- Worker をデプロイし、トークンを設定します(
destinations/cloudflareを参照):wrangler deploy && wrangler secret put TYREKICK_TOKEN - エージェントにパイプラインを渡します(一度設定すれば、今後のすべてのセッションで使えます):
claude mcp add tyrekick \ --env TYREKICK_URL=https://tyrekick-feedback.YOUR.workers.dev \ --env TYREKICK_TOKEN=your-token \ -- npx tyrekick-mcp - 次の一言で対応を完了します:
「未解決のフィードバックを一覧表示して、指摘された箇所を修正し、解決済みにしてください。」
エージェントは5つのツール — list_feedback、get_feedback、triage_feedback、resolve_feedback、feedback_stats — を利用できます。各項目には、要素に表示されているテキスト(ソースコード内で検索可能)、最も近い見出し、ルート、ビューポート、捕捉されなかったページエラーが含まれます。*「このボタンを押しても何も起きない」*といったコメントは、次のように届きます。
element: <button> "Search trips"
under: "Plan your escape" · landmark: main > section#planner
page_errors: 1
> This button does nothing when I click it
多くの人が書くバグ報告よりも、優れた内容です。詳しくは mcp/README.md を参照してください。
共有レビュー(レビュアー同士で閲覧)
デフォルトでは、レビューは複数の非公開の会話で構成されます。各レビュアーには自分のピンのみが表示され、コメントは指定した送信先に集まります。レビューキーを設定すると、ページ自体が共有の場になります。全員が互いのピンを、投稿者名付きで読み取り専用で閲覧できます。同じ指摘が4回も報告されることはなくなります。
npx wrangler secret put TYREKICK_REVIEW_KEY # on your worker; any long random string
<script
src="https://cdn.jsdelivr.net/npm/tyrekick@latest/dist/tyrekick.js"
data-webhook="https://your-worker.workers.dev/feedback"
data-app-version="v0.1"
data-project-name="my-prototype"
data-review-key="the-same-long-random-string"
></script>
有効にする前にお読みください。 キーはページ内に含まれるため、レビューリンクを持っている人なら誰でも閲覧できます。つまり、プロトタイプを開ける人なら誰でも、レビュアー名を含むすべてのコメントを読めます。これは、信頼できる5人に送った非公開リンクなら適切なトレードオフですが、公開URLでは適切ではありません。レビュアーはログインしないため、レビュアーごとに範囲を細かく設定することはできません。これがこの仕組みの要点でもあります。アクセスを取り消すには、シークレットをローテーションしてください。
できることとできないこと:
- 読み取り専用です。 他のレビュアーのコメントを閲覧して返信できます。返信は他のコメントと同様に指定した送信先へ届き、レビュアー間で直接やり取りされることはありません。リアルタイムのプレゼンス機能や、ページ上でのレビュアー間のスレッド機能はありません。
- 却下すると非表示になります。 コメントを(MCP または API 経由で)却下すると、全員のページから消えます。スパムやノイズを取り除くための仕組みです。投稿者には、自分のピンに結果が引き続き表示されます。
- プロジェクト単位です。 1つのワーカーで複数のプロトタイプを扱えますが、レビューキーで閲覧できるのは、指定された
projectNameのプロジェクトだけです。明示的で安定したprojectNameを設定してください。document.titleへのフォールバックを使うと、タイトルを初めて編集したときにフィードバックの流れが分かれてしまいます。 - ワーカーのみです。 Discord は設計上、書き込み専用であり、共有ビューはありません。
- 他のレビュアーに表示されない情報: ユーザーエージェント、画面またはデバイスのフィンガープリント、プロトタイプのページエラー、完全な URL(共有リンクにはクエリ文字列のシークレットが含まれることがあります)、セッション ID。
AI 自動返信(任意)
ワーカーに Anthropic API キーを設定すると、取り込まれた各コメントに対して、短く親しみやすい確認メッセージが1つ返されます。🤖 のラベルが付き、レビュアー本人のスレッドにのみ表示されます。ピンは開いたままです(コメントを受け取ったことを伝えるだけで、修正を行ったと主張したり、ピンを解決したりすることはありません)。モデルにはツールがないため、コメントの内容によって何らかの操作が実行されることはありません。デフォルトでは無効です。
npx wrangler secret put ANTHROPIC_API_KEY
プログラムからの利用/ESM の利用
レジストリからインストールし、明示的に初期化してください(ESM ビルドは自動初期化されません)。
npm install tyrekick
import { init, destroy } from "tyrekick";
init({
webhook: "https://discord.com/api/webhooks/XXXX/YYYY",
appVersion: "v0.1",
projectName: "My Prototype",
transport: "discord",
});
// later, to tear down all DOM, listeners, and in-memory state:
destroy();
グローバル(IIFE)版では、window.Tyrekick.init(config) / window.Tyrekick.destroy() が同等の機能です。destroy() を呼び出さずに init() を2回呼び出すと何もせず、警告が表示されます。webhook または appVersion がない場合は例外がスローされます。
フレームワーク/非同期読み込み(Next.js、React、バンドラー)
IIFE ビルドは document.currentScript を使って自身の <script> タグを読み取り、自動初期化されます。この値は、タグが非同期に挿入される場合(Next.js の next/script、React がレンダリングする <script>、または動的ローダーを使用する場合)には null になるため、通常の CDN タグでは起動に失敗しても気づかないことがあります。対応している方法は2つあります。
-
グローバル変数を設定する(どのローダーでも使用できます)。ウィジェットのスクリプトが実行される前に定義してください。
<script>window.tyrekickConfig = { webhook: "…", appVersion: "1.0" }</script>IIFE ビルドは、まず
window.tyrekickConfigを読み取り、次に自身のdata-*を読み取り、その後 DOM 内にある<script data-webhook>にフォールバックします。 -
クライアントコンポーネントから
init()を呼び出す(Next.js App Router/React ではこの方法を推奨します)。"use client"; import { useEffect } from "react"; export function TyrekickWidget() { useEffect(() => { let cleanup: (() => void) | undefined; import("tyrekick").then(({ init, destroy }) => { init({ webhook: "…", projectName: "…", appVersion: "…" }); cleanup = destroy; }); return () => cleanup?.(); }, []); return null; }
設定
TyrekickConfig の各フィールド(src/types.ts を参照):
| フィールド | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
webhook | string | はい | — | POST を受け取る送信先 URL です。 |
appVersion | string | はい | — | レビュー対象のプロトタイプのバージョン文字列です。 |
projectName | string | いいえ | document.title | プロジェクトの表示名です。 |
position | "bottom-right" | "bottom-left" | いいえ | "bottom-right" | トリガーボタンを配置する隅です。 |
accent | string | いいえ | "#FFC53D" | トリガー、ピン、送信ボタンのアクセントカラーです。アクセントカラー上のテキストは自動でコントラストが調整されます(明るいアクセントカラーには暗い文字色、暗いアクセントカラーには白)。 |
theme | "auto" | "light" | "dark" | いいえ | "auto" | ウィジェットの配色です。"auto" は初期化時に訪問者の prefers-color-scheme に従い、設定が変更されるとリアルタイムで更新されます。自動初期化ビルドでは、スクリプトタグに data-theme を指定してください。 |
branding | boolean | いいえ | true | 「Built by Frontier Operations」のフッターを表示します。 |
fields | { name?: boolean } | いいえ | { name: true } | 任意のレビュアー名入力欄を切り替えます。 |
transport | "json" | "discord" | いいえ | "json" | ペイロードの送信方法です(生の JSON または Discord メッセージ)。 |
persist | boolean | いいえ | true | 未送信データの復旧にのみ localStorage を使用します。対象は下書きテキストと、再読み込み後に再試行が必要な送信失敗コメントです。送信済みコメントは localStorage に保存されません。false の場合、ストレージキーの読み書きは行われません。 |
reviewKey | string | いいえ | — | 共有レビュー(オプトイン):すべてのレビュアーが、ほかのレビュアーのレビューをすべて読み取り専用で確認できます。Worker 上の TYREKICK_REVIEW_KEY と一致する必要があります。このキーはページに含まれるため、レビューリンクを知っている人は誰でもすべてのコメントを読めます。非公開リンクには適していますが、公開 URL には適していません。共有レビューを参照してください。 |
captureErrors | boolean | いいえ | true | ページで捕捉されなかったエラー/未処理の拒否を記録し(window の "error" および "unhandledrejection" リスナーを使用します。コンソールはパッチされません)、直近の最大 5 件を各ペイロードに page_errors として添付します。自動初期化ビルドでは、スクリプトタグに data-capture-errors="false" を指定してください。このフラグの値にかかわらず、入力欄の値が取得されることはありません。 |
ペイロードスキーマ(v2)
transport: "json" の場合、webhook に POST される生の本文は、正確に次の形式(FeedbackPayload)です。
{
"schema": 2,
"id": "b1c2...",
"created_at": "2026-07-02T10:15:30.000+12:00",
"project_name": "My Prototype",
"app_version": "v0.1",
"route": "/pricing?ref=x#plans",
"url": "https://example.com/pricing?ref=x#plans",
"body": "This button is hard to find.",
"reviewer_name": "Sam",
"session_id": "9f8e...",
"anchor": {
"x_pct": 42.3,
"y_pct": 71.8,
"selector": "main > section.pricing > button.cta",
"viewport": { "w": 1440, "h": 900 },
"element": {
"tag": "button",
"id": "buy-now",
"testid": "pricing-cta",
"role": null,
"text": "Start free trial",
"label": "Start your free trial",
"rect": { "x": 612, "y": 484, "w": 216, "h": 44 }
},
"context": {
"heading": "Pricing plans",
"landmark": "main > section#pricing"
}
},
"env": {
"user_agent": "Mozilla/5.0 ...",
"language": "en-US",
"screen": { "w": 1512, "h": 982 },
"dpr": 2,
"dark": false,
"touch": false
},
"page_errors": ["TypeError: prices is undefined"]
}
各フィールドの説明:
schemaは常に2です。idとsession_idは UUID です(idはコメントごと、session_idはページの読み込みごとに生成されます)。created_atはタイムゾーン付きの ISO-8601 形式です。routeはlocation.pathname + search + hash、urlはlocation.hrefです。bodyは前後の空白を取り除いたコメント本文です。reviewer_nameはstring | nullです。anchor.x_pct/anchor.y_pctはクリック時点のドキュメントの寸法に対するパーセンテージで、小数点以下1桁です。anchor.selectorは、その位置にあるホストページ上の最も深い要素を示す、可能な範囲で取得した CSS セレクター(最大5セグメント)か、nullです。ウィジェット自身のノードが含まれることはありません。anchor.elementは、コーディングエージェントがフィードバックをソースに対応付けられるよう、クリックされた要素を識別します。小文字のtag、id/data-testid(testid)/role属性(またはnull)、表示テキスト(前後の空白を削除し、連続する空白を1つにまとめて80文字以下。空の場合はnull)、label(aria-label→alt→placeholder→titleの順、80文字以下)、およびクリック時点のビューポート相対の境界rect(整数 px)が含まれます。要素を解決できなかった場合はnullです。プライバシー:input/textarea/selectの場合、textは常にnullです。フォームの値が取得されることはありません。anchor.contextは、クリック位置を構造的に示します。headingは最も近い見出し(h1~h6。祖先とその直前の兄弟要素をたどって取得。80文字以下)のテキストで、landmarkは最大3つのランドマーク祖先(main、nav、header、footer、aside、section、article、form)からなる大まかなパスです。最も内側の要素が最後になり、例は"main > section#pricing"です。どちらも見つからない場合はnullです。取得時に例外が発生することはありません。envには、物理的なscreenサイズ(CSS px)、dpr(devicePixelRatio、小数点以下2桁)、dark(prefers-color-scheme: dark)、touch(pointer: coarse)が追加されます。page_errorsは、このページの読み込み中に検出された、最後の最大5件の未捕捉エラー/未処理の Promise 拒否です(各200文字以下、古い順)。windowのリスナーで収集され、コンソールに変更を加えることはありません。該当するエラーがない場合、またはcaptureErrors: falseの場合は[]です。
transport: "discord" の場合、このペイロードは代わりに読みやすい Discord メッセージ({ content })に整形され、それが POST されます。
制限事項
これは意図的にバックエンドを持たないツールです。そのため、トレードオフがあります。
- 受領通知によってループが完結するのは、worker 経由の場合のみです。 Cloudflare の送信先では、コメントを解決すると、レビュー担当者のピンが解決メモ付きで緑色になります。書き込み専用の Discord では、読み戻しはできません。
- レビューはデフォルトでブラウザーごとに分かれます。 2人のレビュー担当者はそれぞれ自分のピンだけを確認でき、相手のピンは見えません。コメントはページ上ではなく、送信先に集約されます。共有レビューを有効にすると、worker 経由で別の動作になりますが、リンクを知っている人なら誰でもすべてのコメントを読めるようになります。
- スクリーンショットやセッションのリプレイはありません。 送信されるのは上記の JSON ペイロードのみです。画像、DOM の取得、録画はありません。構造化された要素/コンテキストの取得が、その代替として意図されています。
- スパム。 公開 webhook には迷惑な投稿が届く可能性があります。バックエンドもゲートキーパーも設けないことのトレードオフです。
transport: "json"の送信先を Cloudflare テンプレートにして、そこで検証とレート制限を追加するか、レビュー担当者だけがアクセスできる非公開 Discord チャンネルに送信することで軽減できます。ホスティング方法の判断表については、docs/destinations をご覧ください。
貢献
npm run build # build dist/tyrekick.js (IIFE) + dist/tyrekick.esm.js (ESM)
npm test # unit tests (vitest)
npm run e2e # end-to-end tests (playwright)
src/types.ts を唯一の信頼できる情報源として維持してください。スキーマのバージョンを上げずに、ペイロードのキーや設定フィールドの名前を変更しないでください。
README の先頭にある デモ GIF を再生成するには、node scripts/record-demo.mjs を実行します。使い捨てのローカル worker を使って一連の動作を撮影し、再エンコードします。scripts/README.md をご覧ください。撮影はスクリプト化されており、scripts/record-demo.mjs で調整できます。
Frontier Operations が開発
Tyrekick は、Frontier Operations のブランドとして存在しています。プロトタイプへのフィードバック収集を手軽にする、本当に役立つオープンなツールでありながら、私たちが大切にしている原則を実証します。レビュアーのコメントが私たちを経由することは決してありません。処理の流れに Frontier のバックエンドが介在することはなく、データが外部に送信されることもありません。フィードバックは、レビュアーのブラウザーから、あなたが所有する送信先へ直接届きます。私たちのものづくりに対する考え方をさりげなく示す、無料で提供する便利なソフトウェアです。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。