イベントリファレンス
イベント型タクソノミー、全イベント共通の JSON エンベロープ、ブラウザ別の URL 捕捉対応。
Tadoru が記録するすべてのイベントは、ソースによらず OS 非依存の JSON エンベロープを共有します。この安定スキーマがプロジェクトのコア資産です — 捕捉バックエンドは OS ごとに変わっても、ツールが消費する形は変わりません。
イベントエンベロープ
生出力(query --format jsonl・record・export)では 1 行 1 イベント(NDJSON):
{
"v": 1,
"id": "evt_01J...",
"ts": "2026-08-16T12:34:56.789Z",
"mono_ns": 128374651234,
"source": "macos.ax",
"type": "window.focus",
"app": { "name": "Safari", "bundle_id": "com.apple.Safari", "pid": 501 },
"window": { "title": "Design doc", "id": 42 },
"element":{ "role": "AXButton", "title": "Send", "value": null },
"data": { },
"redaction": { "applied": true, "rules": ["email"] }
}
| フィールド | 説明 |
|---|---|
v |
エンベロープのスキーマバージョン(現在 1) |
id |
ULID ベースのイベント ID。一意かつ時刻順ソート可能 |
ts |
実時刻タイムスタンプ(RFC3339、ミリ秒精度) |
mono_ns |
単調時計(ナノ秒)— 実時刻が変わっても順序が保証される |
source |
捕捉バックエンド。例:macos.ax・macos.workspace・macos.eventtap・macos.applescript |
type |
イベント型(タクソノミー参照) |
app |
アプリ名・バンドル ID・PID |
window |
ウィンドウタイトルと ID(該当時) |
element |
UI 要素の role/title/value(該当時。secure field は決して現れない) |
data |
型固有ペイロード。例:browser.navigate の url / tab_title / mode |
redaction |
このイベントに適用された redaction ルール(email / credit_card / token)の有無と内訳。secure field は捕捉前に除外されるため redaction の痕跡は残りません |
このエンベロープは機械可読な JSON Schema としても公開されています:/schema/event.schema.json。全露出面が共有する単一契約であり、Rust コアの型はこのファイルとの一致をテストで担保されます。
イベント型タクソノミー
現在のイベント型です。権限列は、その型の捕捉に必要な macOS 権限を示します(権限ガイド参照)。
| 型 | ソース | 記録内容 | 権限 |
|---|---|---|---|
app.activate |
macos.workspace |
前面アプリの切替 | 不要 |
app.launch / app.terminate |
macos.workspace |
アプリの起動 / 終了 | 不要 |
window.focus |
macos.ax |
フォーカスウィンドウの変更 | アクセシビリティ |
window.title |
macos.ax |
タイトルの変化 | アクセシビリティ |
ui.focus |
macos.ax |
フォーカス UI 要素の変更 | アクセシビリティ |
ui.click |
macos.ax |
UI 要素へのクリック | アクセシビリティ(+ 入力監視) |
ui.value |
macos.ax |
要素値の変化(フィールド編集等)。内容は text_content 有効時のみ |
アクセシビリティ |
input.key |
macos.eventtap |
キー / ショートカット。既定は「入力の事実 + フィールド種別」。内容は opt-in | 入力監視 |
input.scroll |
macos.eventtap |
スクロール | 入力監視 |
browser.navigate |
macos.applescript |
URL / タブの変化。現在は Chrome のみ。incognito は常に除外 | オートメーション |
clipboard.copy / clipboard.paste |
macos.eventtap |
クリップボード操作。内容は opt-in | 入力監視 |
--types フィルタでは末尾ワイルドカードでファミリー全体を選べます:browser.*・ui.* など。
type は意図的に open set(closed enum ではない)です。将来のプラットフォームやバージョンはバージョン番号を上げずに型を追加でき、consumer は未知の型をエラーにせずスキップする必要があります。
型別ペイロード
各型が data に何を持つか、およびエンベロープの window / element の有無(✓ = あり、— = null)。規範的な定義は JSON Schema の型別条件にあります。
| 型 | window |
element |
data |
|---|---|---|---|
app.activate |
✓ | — | prev_bundle_id — 直前の前面アプリ。初回は null |
app.launch / app.terminate |
— | — | 空 |
window.focus |
✓ | — | 空(フォーカス先はエンベロープ側) |
window.title |
✓ | — | prev_title — 変化後のタイトルはエンベロープ側 |
ui.focus |
✓ | ✓ | field_kind |
ui.click |
✓ | ✓ | button(left/right/other)、click_count |
ui.value |
✓ | ✓ | field_kind、value_len — 内容そのものは element.value(opt-in) |
input.key |
✓ | — | kind、modifiers、count、combo、text、field_kind(詳細は下記) |
input.scroll |
✓ | — | direction、amount、count — coalesce 済み合計 |
browser.navigate |
✓ | — | url、tab_title、mode(常に "normal")、transition(navigate/tab_switch/null) |
clipboard.copy |
✓ | — | content_kind(text/image/file/other)、size_bytes、text |
clipboard.paste |
✓ | — | copy と同じ + ペースト先の field_kind |
field_kind はフォーカス中の入力フィールドの種別です:text / search / url / email / number / other、テキスト系要素にフォーカスがなければ null。password という値は存在しません — secure field はイベントが存在する前に除外されます。
input.key の詳細
「既定は入力の事実 + フィールド種別、内容は opt-in」の正確な形:
kind |
意味 | combo |
text |
coalesce |
|---|---|---|---|---|
text |
印字可能文字の打鍵 | null | 打鍵文字列(opt-in のみ) | する |
shortcut |
修飾キー付き(cmd+s 等) |
常に記録 | null | しない |
navigation |
矢印・PageUp/Down・Home/End・Tab | null | null | する |
delete |
Backspace / Delete | null | null | する |
other |
Esc・F キー・メディアキー | null | null | しない |
ショートカットは「内容」ではなく「操作」なので、combo は opt-in なしで記録されます。保存・コミット・タブ切替などタイムラインの主要な材料です。
coalesce の保証
イベントはストアに届く前に coalesce されるため、consumer がキー連打やスクロールの洪水を生で見ることはありません:
| 対象 | グループ化キー | 窓 | 結果 |
|---|---|---|---|
input.key(text/navigation/delete) |
app + window + field_kind + kind |
間隔 ≤ 2s | 1 イベントに集約。count 合算、text 連結(opt-in 時) |
input.scroll |
app + window + direction |
間隔 ≤ 1s | amount・count を合算 |
window.title |
window | 500ms debounce | 最後のタイトルのみ emit |
ui.value |
element | 1s debounce | 最後の値のみ emit |
ショートカットと ui.click は coalesce しません(1 操作 = 1 イベント)。coalesce バッファは pause・stop・batch flush 時に必ず吐き出されます — イベントは失われません。
text_content で変わるもの
opt-in なのは「内容」(打った・コピーした文字列)だけです。「操作の事実」(ショートカット・クリック・URL・タイトル)は既定で記録されます:
| フィールド | 既定(false) |
opt-in(true) |
|---|---|---|
element.value |
常に null | 記録(redaction 後) |
input.key.text |
常に null | 記録(redaction 後) |
input.key.combo(ショートカット) |
記録 | 記録 |
clipboard.*.text / size_bytes |
常に null | 記録(redaction 後) |
ui.value.value_len |
記録 | 記録 |
window.title / tab_title / url |
記録(redaction 後) | 記録 |
スキーマのバージョニング
- 追加的変更(フィールド追加・型追加・source 追加)では
vを上げません。consumer は未知フィールドを無視し、未知の型をスキップする必要があります。 - 破壊的変更(削除・改名・意味変更)では
vを上げ、ストアのマイグレーションを伴います。
ブラウザの URL 捕捉
browser.navigate(URL 捕捉)は現在 Chrome のみ対応します。理由はプライバシー保証です:Chromium は AppleScript でウィンドウのモード(normal / incognito)を決定的に返すため、「incognito ウィンドウは URL 捕捉から常に除外」という強い約束を、設定ノブなしで置けます。
| ブラウザ | URL 捕捉(現在) | プライベートウィンドウ |
|---|---|---|
| Google Chrome | ✅ 対応 | mode で incognito を確実判定 → 常に除外 |
| Brave / Edge / Vivaldi(Chromium 系) | ❌ 非対応 — collector は Chrome の bundle ID でのみ起動します | URL 捕捉自体がないため、プライベートウィンドウの扱いも発生しません |
| Safari | ❌ 非対応 | プライベート判定プロパティなし。メニュー差分ヒューリスティックは脆いため意図的に不採用 |
| Firefox | ❌ 非対応 | AppleScript に URL 取得 API が存在しない |
| Arc | ❌ 非対応(要検証) | Chromium 系だが AppleScript 対応が限定的 |
Safari / Firefox 対応は、本当に信頼できるプライベートモード判定手段が用意できた場合にのみ将来検討します。
データの 2 層
- 生イベント層 — 完全・機械可読。
query・record・exportが返すもの。 - タイムライン層 — 人間 / LLM 可読。セッション分割・重複除去・coalesce・token budget 付き serialize。
timelineとget_timelineが返すもの。
タイムラインの各セッションは背後の生イベントへの event_ids 逆参照を持ちます。含まれるのは JSON 形式(--format json)のみで、token budget に収めるため出力を粗くする際には省略されます。