Telemetry
August 14, 2026 · View on GitHub
Privacy Policy - [PAGE]
Event tracking respects user privacy settings and can be disabled through the application settings. No personally identifiable information is collected without explicit user consent.
Event Tracking
Thunderbolt uses PostHog for analytics to track user interactions and application usage. All events follow a structured naming convention for better organization and analysis.
Event properties must never include prompts, responses, API keys, or other user-authored content. Use non-secret scalar identifiers such as model_id, model_name, and provider; a final egress scrub removes any property named apiKey before sending.
Event Naming Convention
Events follow the pattern: <feature>_<action>
- Feature: The main area of the application (e.g.,
chat,task,automation) - Action: The specific action being performed (e.g.,
send_prompt,add,create)
Event Categories
Chat & Messaging (chat_*)
chat_send_prompt- User sends a message to the AI (withtrace_id,model_id,model_name,provider,length, andprompt_number)chat_send_prompt_overflow- User attempts a prompt that exceeds the model context (with the same scalar model properties,length, andprompt_number)chat_receive_reply- AI generates a response (withtrace_id,engine,model_id,model_name,provider,length, andreply_number)chat_auto_retry- A built-in turn schedules an automatic retry (withtrace_id,engine, turn-stablemodel_id/model_name/provider,attempt,max_retries, andreason)chat_retry_success- An automatically retried built-in turn succeeds (withtrace_id,engine, turn-stablemodel_id/model_name/provider, andattempts)chat_retries_exhausted- A built-in turn stops retrying (withtrace_id,engine, turn-stablemodel_id/model_name/provider,attempts, andreason)- Retry
reasonuses the stable error class. Pi-engine errors classify 408, 429, and 5xx statuses embedded by pi-ai astimeout,rate-limit, andprovider; other or unrecognized errors remainunknown. chat_turn_completed- One privacy-safe summary per built-in turn, includingtrace_id, actualengine, scalar model/provider identifiers, outcome/error class, attempts/retry layers/retry reasons, phase timings, user-perceived TTFT, step/tool counts, capped tool timings, and total duration. TTFT is measured when the first non-empty text or reasoning delta reaches the adapter response stream, after translator/smoothing overhead. MCP calls use the fixed tool labelmcp; user-authored server-name-derived identifiers are never emitted.tinfoil_attestation- A Tinfoil client attestation succeeds, fails, or times out (withoutcome,duration_ms,client, optionalerror_name, and, for turn acquisitions,trace_id,engine,model_id, andprovider)chat_select- User selects a chat threadchat_new_clicked- User creates a new chatchat_delete- User deletes a chatchat_clear_all- User clears all chats
Model Management (model_*)
model_select- User selects a different AI model
Settings (settings_*)
settings_theme_set- User changes the application themesettings_name_set- User sets their preferred name initiallysettings_name_update- User updates their preferred namesettings_name_clear- User clears their preferred namesettings_location_set- User sets their location initiallysettings_location_update- User updates their locationsettings_localization_update- User updates localization settings (temperature, wind speed, precipitation, time format, language)settings_database_reset- User resets the application databasesettings_data_collection_enabled- User enables data collectionsettings_data_collection_disabled- User disables data collection
Task Management (task_*)
task_add- User adds a new tasktask_mark_complete- User marks a task as completetask_update_text- User edits task texttask_reorder- User reorders taskstask_search- User searches through tasks
Automation (automation_*)
automation_modal_create_open- Create automation modal opensautomation_create- New automation is createdautomation_modal_edit_open- Edit automation modal opensautomation_update- Existing automation is updatedautomation_run- Automation is executedautomation_delete_clicked- Delete automation button is clickedautomation_delete_confirmed- Automation deletion is confirmed
Content View & Preview (content_view_*, preview_*)
content_view_open- Content view opens (with properties:view_type,tool_namefor object views,sideview_typefor sideviews). MCP object views use the fixedtool_namevaluemcp.content_view_close- Content view closes (with property:view_type)preview_open- Preview webview opens from a link clickpreview_close- Preview webview closespreview_copy_url- User copies URL from preview headerpreview_open_external- User opens preview URL in external browser
UI & Navigation (ui_*)
ui_shortcut_use- User uses a keyboard shortcutui_sidebar_open- Sidebar opensui_sidebar_close- Sidebar closes
Startup Performance (app_*)
Diagnostic events for investigating app initialization time. All timing values are whole milliseconds measured from navigation start (performance.timeOrigin).
app_init_timing- Fired once per initialization run, after the init pipeline completes. Properties:bundle_evaluated_ms- entry bundle downloaded, parsed and evaluatedapp_mounted_ms- first render of the root React componentstep0_fetch_config_ms…step8_initialize_posthog_ms- duration of each init step (includingstep2b_db_ready_ms— the first trivial query that pays PowerSync's deferred ready gate — plusstep4b_run_data_migrations_msandstep6_create_http_client_ms)init_total_ms- total pipeline durationinit_run- run counter (greater than 1 means the user retried after an init error)initial_sync_outcome- how the initial-sync gate resolved:disabled,synced,timed_outorfailedsync_enabled,platform- segmentation context
app_chat_ready- Fired at most once per session when the first chat finishes hydrating (withchat_ready_ms). Together withapp_init_timing, this captures the user-perceived time to a usable chat.
Sync Diagnostics (sync_*)
Diagnostic events for debugging sync issues (especially iOS). All events include shared context: platform, ps_config, ps_connected, ps_connecting, ps_has_synced, ps_last_synced_at, ps_uploading, ps_downloading, uptime_ms.
sync_connect- PowerSync connected successfullysync_connect_error- PowerSync connection failed (witherror)sync_disconnect- PowerSync disconnected (withtrigger:'user'or'reconnect')sync_reconnect_start- Reconnect attempt started (withtrigger:'visibility'or'manual')sync_reconnect_success- Reconnect succeeded (with optionalhidden_duration_ms)sync_reconnect_error- Reconnect failed (witherror,trigger)sync_visibility_change- App visibility changed (withstate,hidden_duration_ms,will_reconnect,ms_since_last_download)sync_credentials_fetch- Token refresh succeeded (withexpires_in_ms)sync_credentials_error- Token refresh failed (withstatus,error_code,had_token)sync_upload- CRUD upload succeeded (withoperation_count)sync_upload_error- CRUD upload failed (witherror,operation_count)sync_status_change- PowerSync connected↔disconnected transition (withprev_connected,ms_since_last_change)
Implementation
Events are tracked using the trackEvent function from src/lib/posthog.tsx:
import { trackEvent } from '@/lib/posthog'
// Track a simple event
trackEvent('chat_send_prompt')
// Track an event with properties
trackEvent('chat_send_prompt', {
model_id: 'model-row-id',
model_name: 'gpt-4',
provider: 'openai',
length: 150,
})
Type Safety
All event names are typed using the EventType union type, ensuring:
- Only valid event names can be used
- Autocomplete support in IDEs
- Compile-time error checking for typos
Adding New Events
To add a new event:
- Add the event name to the
EventTypeunion insrc/lib/analytics.tsx - Use the
<feature>_<action>naming convention - Add the tracking call in the appropriate component
- Include relevant properties for analytics insights
- Update this file to document it