From 9e396cdeccffae17d4c4392a0107c4f99a9d2b4e Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Sat, 2 May 2026 13:19:11 -0500 Subject: [PATCH] chore: optimize AI agent context and implement CI cost controls (#5335) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- .agent_memory/session_context.md | 21 + .aiexclude | 36 + .copilotignore | 55 +- .gitattributes | 13 + .skills/ci-cost-control/SKILL.md | 25 + .skills/code-review/SKILL.md | 5 + .skills/compose-ui/strings-index.txt | 1306 +++++++++ AGENTS.md | 135 +- .../composeResources/values/strings.xml | 2517 +++++++++-------- scripts/ai-guardrail.sh | 53 + scripts/sort-strings.py | 98 + 11 files changed, 2896 insertions(+), 1368 deletions(-) create mode 100644 .agent_memory/session_context.md create mode 100644 .aiexclude create mode 100644 .gitattributes create mode 100644 .skills/ci-cost-control/SKILL.md create mode 100644 .skills/compose-ui/strings-index.txt create mode 100755 scripts/ai-guardrail.sh create mode 100644 scripts/sort-strings.py diff --git a/.agent_memory/session_context.md b/.agent_memory/session_context.md new file mode 100644 index 000000000..ddc186c15 --- /dev/null +++ b/.agent_memory/session_context.md @@ -0,0 +1,21 @@ +# Agent Session Context - Meshtastic Android +# This is a dated, append-only handover log. Add new entries at the TOP. +# Do NOT edit or remove previous entries — stale state claims cause agent confusion. +# Format: ## YYYY-MM-DD — + +## 2026-05-02 — CI cost-control PR review fixes +- Applied PR review feedback: encoding fixes in sort-strings.py, NUL-delimited staged-files loop + in ai-guardrail.sh, installation instructions added, typo fix in strings.xml, command order + fixed in AGENTS.md, narrowed .aiexclude/.gitattributes patterns, allTests added to SKILL.md. + +## 2026-04-XX — Token Mitigation (Phase 1-3) +- `.copilotignore` and `.aiexclude` updated with stricter ignore rules. +- `AGENTS.md` modularized to ~3KB base; detailed rules moved to `.skills/`. +- `scripts/ai-guardrail.sh` added to prevent binary/log leaks (installation: see script header). +- CI Cost Control skill added at `.skills/ci-cost-control/SKILL.md`. + +## Golden Context (stable across sessions) +- Always check `.skills/compose-ui/strings-index.txt` before reading `strings.xml`. +- Run `python3 scripts/sort-strings.py` after adding strings to keep the index organized. +- Always check `gh run list` before pushing. +- Pre-commit hook `scripts/ai-guardrail.sh` protects against binary leaks (see script for install). diff --git a/.aiexclude b/.aiexclude new file mode 100644 index 000000000..afbe71339 --- /dev/null +++ b/.aiexclude @@ -0,0 +1,36 @@ +# Standard AI exclusion list for Cursor, Windsurf, etc. +# Mirroring .copilotignore for project-wide token discipline + +# Build & Generated +**/build/** +.gradle/ +.kotlin/ +**/generated/** + +# Agent Artifacts +.agent_artifacts/ +.agent_refs/ +tmp/ +*.log + +# Media & Binaries +**/*.png +**/*.jpg +**/*.jpeg +**/*.webp +**/*.svg +**/*.ico +**/*.gif +**/*.mp3 +**/*.wav +**/*.ogg +**/*.pdf +**/*.ttf +**/*.otf +**/*.jar +**/*.aar +**/*.apk + +# Resources (Indexing non-English strings is a token sink) +**/values-*/strings.xml +**/composeResources/**/values-*/*.xml diff --git a/.copilotignore b/.copilotignore index 02ec3ad1d..f53a45d63 100644 --- a/.copilotignore +++ b/.copilotignore @@ -1,27 +1,54 @@ -# Ignore build artifacts and generated files from Copilot indexing +# Meshtastic Android - GitHub Copilot Ignore List # This saves context window tokens and prevents Copilot from hallucinating off of minified code. -# Build directories +# ── Build & Generated ───────────────────────────────────────────────────────── **/build/** .gradle/ -.idea/ - -# Android generated files +.kotlin/ **/generated/** .cxx/ .externalNativeBuild/ -# Git history & worktrees -.git/ -.worktrees/ - -# Protobuf (Prevents Copilot from suggesting raw protobuf byte buffers) -core/proto/ - -# Environment and secrets +# ── IDE & Environment ───────────────────────────────────────────────────────── +.idea/ +.run/ +.claude/ +.gemini/ +.jdk local.properties secrets.properties *.jks +.DS_Store -# Agent References (Prevents pollution of project space with external code) +# ── Agent Artifacts (Large volumes of logs/images) ─────────────────────────── +.agent_artifacts/ +# Note: .agent_plans/ is NOT ignored to maintain implementation context. .agent_refs/ +tmp/ +*.log + +# ── Binary Assets & Media ───────────────────────────────────────────────────── +**/*.png +**/*.jpg +**/*.jpeg +**/*.webp +**/*.svg +**/*.ico +**/*.gif +**/*.mp3 +**/*.wav +**/*.ogg +**/*.pdf +**/*.ttf +**/*.otf +**/*.jar +**/*.aar +**/*.apk + +# ── External & Submodules ───────────────────────────────────────────────────── +core/proto/ + +# ── Resources ──────────────────────────────────────────────────────────────── +# Ignore translations (reduces churn and indexing tokens) +**/values-*/strings.xml +**/composeResources/**/values*/*.xml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..f0f137f25 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# Mark only generated/derived XML as linguist-generated to reduce Copilot PR summary costs. +# Hand-edited resources (layouts, string values) are intentionally excluded so they remain +# visible in diffs and code review. +**/composeResources/**/values-*/*.xml linguist-generated=true +.skills/compose-ui/strings-index.txt linguist-generated=true + +# Ensure assets are treated as binary +*.png binary +*.jpg binary +*.webp binary +*.mp3 binary +*.wav binary +*.ogg binary diff --git a/.skills/ci-cost-control/SKILL.md b/.skills/ci-cost-control/SKILL.md new file mode 100644 index 000000000..7bbd4d3a0 --- /dev/null +++ b/.skills/ci-cost-control/SKILL.md @@ -0,0 +1,25 @@ +# Skill: CI Cost Control & Monitoring + +## Description +Guidelines for agents to minimize GitHub Actions compute waste and prevent redundant or failing CI runs. + +## Rules + +### 1. Check Before You Kick +Before pushing code that triggers a CI workflow, you **MUST** check if a relevant run is already in progress: +```bash +gh run list --branch $(git branch --show-current) --limit 5 +``` +- If a run is pending/running for your current state, **DO NOT** push again unless you are fixing a specific CI failure. +- Cancel redundant runs if your new push supersedes them: `gh run cancel `. + +### 2. Local First +NEVER use CI as a "remote compiler." +- You must run `./gradlew spotlessApply spotlessCheck detekt test allTests` locally before pushing. +- If local tests fail, CI **will** fail. Do not waste the tokens or the compute. + +### 3. Modular CI Invocations +When using the `/delegate` or autonomous PR tools, explicitly limit the scope of the CI check if the tool supports it. Avoid running the full multi-OS desktop matrix for a simple documentation fix. + +## Monitoring +Use `gh run view ` to inspect failures. Do not re-run a whole suite if only one shard failed due to a known flake; use `gh run rerun --failed`. diff --git a/.skills/code-review/SKILL.md b/.skills/code-review/SKILL.md index acab253d5..b9442e07d 100644 --- a/.skills/code-review/SKILL.md +++ b/.skills/code-review/SKILL.md @@ -64,3 +64,8 @@ When reviewing code, meticulously verify the following categories. Flag any devi 2. **Reference the Docs:** Cite `AGENTS.md` and project architecture playbooks to justify change requests (e.g., "Per AGENTS.md, `java.io.*` cannot be used in `commonMain`; please migrate to Okio"). 3. **Enforce Build Health:** Remind authors to run `./gradlew test allTests` locally to verify changes, especially since KMP `test` tasks are ambiguous. 4. **Praise Good Patterns:** Acknowledge correct usage of complex architecture requirements, like proper Navigation 3 scene transitions or elegant `commonMain` helper extractions. + +## Git & PR Hygiene Rules +- **Commit Hygiene:** Squash fixup/polish/review-feedback commits before opening a PR. Each commit should represent a logical, self-contained unit of work — not a back-and-forth conversation. +- **PR Descriptions:** Keep PR descriptions concise and scannable. State *what changed* and *why*, not a per-commit play-by-play. Use a short summary paragraph followed by a bullet list of changes. Avoid tables, headers-per-commit, or verbose breakdowns. Reference the `meshtastic/firmware` repo PRs for tone and style. +- **PR Titles:** Use conventional commit format: `feat(scope):`, `fix(scope):`, `refactor(scope):`, `chore(scope):`. Keep titles under ~72 characters. diff --git a/.skills/compose-ui/strings-index.txt b/.skills/compose-ui/strings-index.txt new file mode 100644 index 000000000..65ac4f02d --- /dev/null +++ b/.skills/compose-ui/strings-index.txt @@ -0,0 +1,1306 @@ +a11y_label_value +a11y_message_from +accept +acknowledgements +### ACTION ### +action_copy_message +action_delete_message +action_react_with_emoji +action_select_device +action_select_message +action_select_network +action_send_reply +action_show_message_status +actions +adc_multiplier_override +adc_multiplier_override_ratio +### ADD ### +add +add_a_note +add_channels_description +add_custom_tile_source +add_favorite +add_layer +add_local_mbtiles_file +add_network_device +add_network_device_manually +add_network_layer +address +admin_key +admin_keys +administration +advanced +advanced_device_gps +advanced_title +### AIR ### +air_quality_icon +air_quality_metrics_module_enabled +air_quality_metrics_update_interval_seconds +air_util_definition +air_utilization +### ALERT ### +alert_bell_buzzer +alert_bell_led +alert_bell_text +alert_bell_vibra +alert_message_buzzer +alert_message_led +alert_message_vibra +all_time +allow_input_source +allow_undefined_pin_access +alt +altitude +always_point_north +ambient_lighting +ambient_lighting_config +analytics_notice +analytics_okay +analytics_platforms +any +app_notifications +app_settings +app_too_old +app_version +apply +are_you_sure +are_you_sure_change_default +audio +audio_config +available_pins +back +backup_restore +bad +bandwidth +baro_pressure +battery +battery_ina_2xx_i2c_address +ble_devices +ble_rssi_threshold_defaults_to_80 +blue +### BLUETOOTH ### +bluetooth +bluetooth_available_devices +bluetooth_config +bluetooth_enabled +bluetooth_feature_config +bluetooth_feature_config_description +bluetooth_feature_discovery +bluetooth_feature_discovery_description +bluetooth_permission +bold_heading +bottom_nav_settings +broadcast_interval +button_gpio +buzzer_gpio +calculating +cancel +cancel_reply +canned_message +canned_message_config +canned_message_enabled +cant_change_no_radio +cant_shutdown +carousel_interval +ch_util_definition +### CHANNEL ### +channel +channel_1 +channel_2 +channel_3 +channel_4 +channel_5 +channel_6 +channel_7 +channel_8 +channel_features +channel_invalid +channel_label +channel_name +channel_url +channel_utilization +channels +chirpy +choose_contrast +choose_theme +### CLEAN ### +clean_node_database_confirmation +clean_node_database_description +clean_node_database_title +clean_nodes_older_than +clean_now +clean_unknown_nodes +clear +clear_selection +clear_time_zone +client_notification +close +close_selection +codec_2_enabled +codec2_sample_rate +coding_rate +collapse_chart +communicate_off_the_grid +### COMPASS ### +compass_bearing +compass_bearing_na +compass_distance +compass_location_disabled +compass_no_location_fix +compass_no_location_permission +compass_no_magnetometer +compass_north_top +compass_orientation +compass_title +compass_uncertainty +compass_uncertainty_unknown +compromised_keys +### CONFIG ### +config_device_doubleTapAsButtonPress_summary +config_device_ledHeartbeatEnabled_summary +config_device_transmitOverLora_summary +config_device_tripleClickAsAdHocPing_summary +config_device_tzdef_summary +config_device_use_phone_tz +config_display_auto_screen_carousel_secs_summary +config_display_compass_north_top_summary +config_display_displaymode_summary +config_display_flip_screen_summary +config_display_heading_bold_summary +config_display_oled_summary +config_display_screen_on_secs_summary +config_display_units_summary +config_display_wake_on_tap_or_motion_summary +config_lora_frequency_slot_summary +config_lora_hop_limit_summary +config_lora_modem_preset_summary +config_lora_region_summary +config_network_eth_enabled_summary +config_network_udp_enabled_summary +config_network_wifi_enabled_summary +config_position_broadcast_secs_summary +config_position_broadcast_smart_minimum_distance_summary +config_position_broadcast_smart_minimum_interval_secs_summary +config_position_flags_summary +config_position_gps_update_interval_summary +config_power_is_power_saving_summary +config_security_admin_key +config_security_debug_log_api_enabled +config_security_is_managed +config_security_private_key +config_security_public_key +config_security_serial_enabled +configure_bluetooth_permissions +configure_critical_alerts +configure_location_permissions +configure_notification_permissions +connect +connect_radio_for_remote_admin +connected +connected_device +connected_sleeping +connecting +connection_status +connections +contrast +contrast_high +contrast_medium +contrast_standard +conversations +copy +create_your_own_networks +critical_alert +critical_alerts +critical_alerts_dnd_request_text +current +currently +datadog_link +date +dbm_value +### DEBUG ### +debug +debug_active_filters +debug_clear +debug_clear_logs_confirm +debug_decoded_payload +debug_default_search +debug_export_failed +debug_export_success +debug_filter_add +debug_filter_add_custom +debug_filter_clear +debug_filter_included +debug_filter_preset_title +debug_filters +debug_log_api_enabled +debug_logs_export +debug_panel +debug_search_clear +debug_search_next +debug_search_prev +debug_store_logs_summary +debug_store_logs_title +default_ +default_mqtt_address +### DELETE ### +delete +delete_custom_tile_source +delete_for_everyone +delete_for_me +delete_messages +delete_messages_title +delete_selection +delivery_confirmed +delivery_confirmed_reboot_warning +demo_mode +desc_node_filter_clear +description +desktop_notification_title +desktop_tray_quit +desktop_tray_show +desktop_tray_tooltip +details +detection_sensor +detection_sensor_config +detection_sensor_enabled +detection_trigger_type +### DEVICE ### +device +device_configuration +device_db_cache_limit +device_db_cache_limit_summary +device_gps +device_metrics_label_value +device_metrics_log +device_metrics_numeric_value +device_metrics_percent_value +device_metrics_update_interval_seconds +device_metrics_voltage_value +device_sleeping +device_storage_ui_title +device_telemetry_enabled +device_telemetry_enabled_summary +device_theme_language +dew_point +direct_message +direct_message_key +discard_changes +disconnect +disconnected +discovered_network_devices +disk_free_indexed +### DISPLAY ### +display +display_config +display_mode +display_time_in_12h_format +display_units +### DISTANCE ### +distance +distance_filters +distance_filters_description +distance_measurements +distance_measurements_description +dns +done +dont_show_again_for_device +double_tap_as_button_press +downlink_enabled +downlink_feature_description +download +duplicated_public_key_title +dynamic +easily_set_up_private_mesh_networks +echo_enabled +edit +edit_custom_tile_source +eight_hours +elevation_suffix +enable_power_saving_mode +enabled +### ENCRYPTION ### +encryption_enabled +encryption_error +encryption_error_text +encryption_pkc +encryption_pkc_text +encryption_psk +encryption_psk_text +env_metrics_log +### ENVIRONMENT ### +environment +environment_metrics_module_enabled +environment_metrics_on_screen_enabled +environment_metrics_update_interval_seconds +environment_metrics_use_fahrenheit +error +error_duty_cycle +establish_session +establishing_session +ethernet_config +ethernet_enabled +ethernet_ip +exchange_position +expand_chart +expires +### EXPORT ### +export_configuration +export_data_csv +export_keys +export_keys_confirmation +export_tak_data_package +external_notification +external_notification_config +external_notification_enabled +factory_reset +fair +fallback_node_name +favorite +favorite_add +favorite_remove +file_entry +files_available +### FILTER ### +filter_add_placeholder +filter_disable_for_contact +filter_enable +filter_enable_for_contact +filter_enable_summary +filter_hide_count +filter_icon +filter_message_label +filter_no_words +filter_regex_pattern +filter_settings +filter_show_count +filter_whole_word +filter_words +filter_words_summary +firebase_link +### FIRMWARE ### +firmware +firmware_edition +firmware_old +firmware_too_old +firmware_update_almost_there +firmware_update_alpha +firmware_update_battery_low +firmware_update_checking +firmware_update_connecting_attempt +firmware_update_copying +firmware_update_currently_installed +firmware_update_device +firmware_update_disclaimer_chirpy_says +firmware_update_disclaimer_text +firmware_update_disclaimer_title +firmware_update_disconnect_warning +firmware_update_do_not_close +firmware_update_done +firmware_update_downloading_percent +firmware_update_enabling_dfu +firmware_update_erasing +firmware_update_error +firmware_update_extracting +firmware_update_failed +firmware_update_flashing +firmware_update_hang_tight +firmware_update_hash_rejected +firmware_update_keep_device_close +firmware_update_latest +firmware_update_local_file +firmware_update_method_ble +firmware_update_method_detail +firmware_update_method_usb +firmware_update_method_wifi +firmware_update_no_device +firmware_update_node_info_missing +firmware_update_not_found_in_release +firmware_update_ota_failed +firmware_update_rak4631_bootloader_hint +firmware_update_rebooting +firmware_update_release_notes +firmware_update_retrieval_failed +firmware_update_retry +firmware_update_save_dfu_file +firmware_update_select_file +firmware_update_source_local +firmware_update_stable +firmware_update_starting_dfu +firmware_update_starting_ota +firmware_update_success +firmware_update_taking_a_while +firmware_update_target +firmware_update_title +firmware_update_unknown_error +firmware_update_unknown_hardware +firmware_update_unknown_release +firmware_update_uploading +firmware_update_usb_bootloader_warning +firmware_update_usb_failed +firmware_update_usb_instruction_text +firmware_update_usb_instruction_title +firmware_update_validating +firmware_update_verification_failed +firmware_update_verifying +firmware_update_waiting_reboot +firmware_update_waiting_reconnect +firmware_version +fixed_pin +fixed_position +flip_screen +for_more_information_see_our_privacy_policy +fr_HT +free_memory +free_memory_description +freq +frequency_slot +friendly_name +gas_resistance +gateway +generate_input_event_on_ccw +generate_input_event_on_cw +generate_input_event_on_press +generate_qr_code +get_started +good +### GPIO ### +gpio +gpio_pin +gpio_pin_for_rotary_encoder_a_port +gpio_pin_for_rotary_encoder_b_port +gpio_pin_for_rotary_encoder_press_port +gpio_pin_to_monitor +gps_en_gpio +gps_mode +gps_receive_gpio +gps_transmit_gpio +green +hardware +hardware_model +heading +heartbeat +hide_layer +hide_password +history_return_max +history_return_window +hop_limit +hops_away +host +host_metrics_log +humidity +i_agree +i_agree_to_share_my_location +i_know_what_i_m_doing +i2s_clock +i2s_data_in +i2s_data_out +i2s_word_select +iaq +iaq_definition +icon_meanings +### IGNORE ### +ignore +ignore_add +ignore_incoming +ignore_mqtt +ignore_remove +import_configuration +import_known_shared_contact_text +import_label +import_shared_contact +incoming_messages +indoor_air_quality_iaq +info +input_channel_url +input_shared_contact_url +installed_firmware_version +internal +interval_always_on +interval_unset +intro_show +intro_welcome +ip +ip_address +ip_port +ipv4_mode +json_output_enabled +key_verification_final_title +key_verification_request_title +key_verification_title +### LABEL ### +label_lite_fast +label_lite_slow +label_long_fast +label_long_moderate +label_long_slow +label_long_turbo +label_medium_fast +label_medium_slow +label_narrow_fast +label_narrow_slow +label_short_fast +label_short_slow +label_short_turbo +label_very_long_slow +last_heard_filter_label +last_position_update +latest_alpha_firmware +latest_stable_firmware +latitude +learn_more +led_heartbeat +led_state +legacy_admin_channel +library_count +licensed_amateur_radio +licensed_amateur_radio_text +### LOAD ### +load +load_15_min +load_15_min_description +load_1_min +load_1_min_description +load_5_min +load_5_min_description +load_indexed +loading +### LOCAL ### +local_mbtiles_file +local_stats_bad +local_stats_battery +local_stats_diagnostics_prefix +local_stats_dropped +local_stats_heap +local_stats_heap_value +local_stats_nodes +local_stats_noise +local_stats_relays +local_stats_traffic +local_stats_updated_at +local_stats_uptime +local_stats_utilization +location_disabled +location_sharing +locked +### LOG ### +log_retention_days +log_retention_days_quantity +log_retention_days_summary +log_retention_hours +log_retention_never +logs +long_name +longitude +lora +lora_config +low_battery +low_battery_message +low_battery_title +low_entropy_key_title +lux +manage_custom_tile_sources +manage_map_layers +managed_mode +manual_position_request +### MAP ### +map +map_cache_info +map_cache_manager +map_cache_size +map_cache_tiles +map_clear_tiles +map_download_complete +map_download_errors +map_download_region +map_filter +map_layer_formats +map_node_popup_details +map_offline_manager +map_purge_fail +map_purge_success +map_reporting +map_reporting_consent_header +map_reporting_consent_text +map_reporting_interval_seconds +map_reporting_summary +map_select_download_region +map_start_download +map_style_selection +map_subDescription +map_tile_download_estimate +map_tile_source +map_type_hybrid +map_type_normal +map_type_satellite +map_type_terrain +mark_as_read +match_all +match_any +max +mesh_map_location +mesh_map_location_description +### MESHTASTIC ### +meshtastic +meshtastic_alerts_notifications +meshtastic_app_name +meshtastic_broadcast_notifications +meshtastic_low_battery_notifications +meshtastic_low_battery_temporary_remote_notifications +meshtastic_messages_notifications +meshtastic_new_nodes_notifications +meshtastic_service_notifications +meshtastic_waypoints_notifications +### MESSAGE ### +message +message_delivery_status +message_device_managed +message_input_label +message_status_delivered +message_status_enroute +message_status_queued +message_status_sfpp_confirmed +message_status_sfpp_routing +message_status_unknown +messages +min +minimum_broadcast_seconds +minimum_distance +minimum_interval +minimum_wake_time_seconds +modem_preset +module_settings +modules_already_unlocked +modules_unlocked +more_reactions +mpwrd_os +### MQTT ### +mqtt +mqtt_config +mqtt_enabled +mqtt_probe_dns_failure +mqtt_probe_other_failure +mqtt_probe_rejected +mqtt_probe_running +mqtt_probe_success +mqtt_probe_success_with_info +mqtt_probe_tcp_failure +mqtt_probe_timeout +mqtt_probe_tls_failure +mqtt_status_connected +mqtt_status_connecting +mqtt_status_disconnected +mqtt_status_disconnected_with_reason +mqtt_status_inactive +mqtt_status_reconnecting +mqtt_status_reconnecting_with_attempt +mqtt_test_connection +must_set_region +must_update +### MUTE ### +mute_1_week +mute_8_hours +mute_add +mute_always +mute_notifications +mute_remove +mute_status_always +mute_status_muted_for_days +mute_status_muted_for_hours +mute_status_unmuted +nag_timeout_seconds +name +name_cannot_be_empty +navigate_back +navigate_into_label +neighbor_info +neighbor_info_config +neighbor_info_enabled +network +network_layer_url_hint +new_channel_rcvd +new_messages_below +new_node_seen +new_nodes +next +nfc_disabled +### NO ### +no_bluetooth_devices_hint +no_bluetooth_devices_seen +no_custom_tile_sources_found +no_device_selected +no_devices_found +no_files_manifested +no_local_stats +no_map_layers_loaded +no_network_devices_found +no_network_devices_hint +no_network_devices_seen +no_pax_metrics_logs +no_usb_devices_found +no_usb_devices_hint +no_usb_devices_seen +### NODE ### +node_count_template +node_filter_exclude_infrastructure +node_filter_exclude_mqtt +node_filter_ignored +node_filter_include_unknown +node_filter_only_direct +node_filter_only_online +node_filter_placeholder +node_filter_show_ignored +node_filter_title +node_id +node_number +node_sort_alpha +node_sort_button +node_sort_channel +node_sort_distance +node_sort_hops_away +node_sort_last_heard +node_sort_title +node_sort_via_favorite +node_sort_via_mqtt +node_status_summary +nodedb_reset +nodeinfo_broadcast_interval +### NODES ### +nodes +nodes_at_this_location +nodes_empty_disconnected_hint +nodes_empty_disconnected_title +nodes_empty_searching_hint +nodes_empty_searching_title +nodes_queued_for_deletion +none +none_quality +not_connected +note +notes +notification_permissions_description +### NOTIFICATIONS ### +notifications_for_channel_and_direct_messages +notifications_for_low_battery_alerts +notifications_for_newly_discovered_nodes +notifications_on_alert_bell_receipt +notifications_on_message_receipt +now +ntp_server +number_of_records +ok_to_mqtt +okay +oled_type +### ONE ### +one_day +one_hour +one_hour_short +one_month +one_week +one_wire_temperature +only_favorites +open_compass +open_settings +open_source_description +open_source_libraries +options +orient_north +### OUTPUT ### +output_buzzer_gpio +output_duration_milliseconds +output_led_active_high +output_led_gpio +output_vibra_gpio +overflow_menu +override_console_serial_port +override_duty_cycle +override_frequency_mhz +pa_fan_disabled +pairing_mode +password +### PAX ### +pax +pax_ble_format +pax_ble_marker +pax_metrics_log +pax_total_format +pax_total_marker +pax_wifi_format +pax_wifi_marker +paxcounter +paxcounter_config +paxcounter_enabled +periodic_position_broadcast +permission_missing_31 +phone_location +phone_location_description +play +plurals_hours +plurals_minutes +plurals_seconds +### POSITION ### +position +position_config_set_fixed_from_phone +position_enabled +position_flags +position_log +position_packet +### POWER ### +power +power_config +power_metrics_log +power_metrics_module_enabled +power_metrics_on_screen_enabled +power_metrics_update_interval_seconds +powered +precise_location +preferences_language +preferences_system_default +preserve_favorites +press_and_drag +pressure +### PREVIEW ### +preview_custom_composable_line_one +preview_custom_composable_line_two +preview_dot +preview_footer +preview_gauge +preview_gradient +preview_header +preview_item +preview_pill +preview_text +primary +primary_channel_feature +privacy_url +private_key +provide_location_to_mesh +provider_name_exists +proxy_to_client_enabled +psk +pt_BR +ptt_pin +public_key +public_key_changed +qr_code +### QUICK ### +quick_chat +quick_chat_append +quick_chat_edit +quick_chat_hide +quick_chat_instant +quick_chat_new +quick_chat_show +radiation +radio_configuration +rainfall_1h +rainfall_24h +range_test +range_test_config +range_test_enabled +react +reboot +### REBROADCAST ### +rebroadcast_mode +rebroadcast_mode_all_desc +rebroadcast_mode_all_skip_decoding_desc +rebroadcast_mode_core_portnums_only_desc +rebroadcast_mode_known_only_desc +rebroadcast_mode_local_only_desc +rebroadcast_mode_none_desc +recent_network_devices +red +refresh +refresh_metadata +regenerate_keys_confirmation +regenerate_private_key +region_frequency_plan +relays +### REMOTE ### +remote +remote_admin +remote_admin_unreachable +remote_hardware +remote_hardware_config +remote_hardware_enabled +remotely_administrating +### REMOVE ### +remove +remove_favorite +remove_filter +remove_ignored +remove_layer +remove_node_text +replace +replace_channels_and_settings_description +reply +replying_to +report +### REQUEST ### +request +request_air_quality_metrics +request_device_metrics +request_environment_metrics +request_host_metrics +request_metadata +request_pax_metrics +request_power_metrics +request_telemetry +requesting_from +resend +reset +reset_to_defaults +retry +ringtone +ringtone_file_empty +ringtone_import_error +ringtone_imported +### ROLE ### +role +role_client_base_desc +role_client_desc +role_client_hidden_desc +role_client_mute_desc +role_lost_and_found_desc +role_repeater_desc +role_router_client_desc +role_router_desc +role_router_late_desc +role_sensor_desc +role_tak_desc +role_tak_tracker_desc +role_tracker_desc +root_topic +rotary_encoder_1_enabled +router_role_confirmation_text +### ROUTING ### +routing_error_admin_bad_session_key +routing_error_admin_public_key_unauthorized +routing_error_bad_request +routing_error_duty_cycle_limit +routing_error_got_nak +routing_error_max_retransmit +routing_error_no_channel +routing_error_no_interface +routing_error_no_response +routing_error_no_route +routing_error_none +routing_error_not_authorized +routing_error_pki_failed +routing_error_pki_send_fail_public_key +routing_error_pki_unknown_pubkey +routing_error_rate_limit_exceeded +routing_error_timeout +routing_error_too_large +rssi +rsyslog_server +sample_message +sats +save +save_changes +save_csv_in_storage_esp32_only +save_rangetest +### SCAN ### +scan +scan_bluetooth_devices +scan_channels_nfc +scan_channels_qr +scan_network_devices +scan_nfc +scan_nfc_text +scan_shared_contact_nfc +scan_shared_contact_qr +scanning_bluetooth +scanning_network +screen_on_for +scroll_to_bottom +search_emoji +secondary +secondary_channel_position_feature +secondary_no_telemetry +### SECURITY ### +security +security_icon_badge_warning_description +security_icon_description +security_icon_help_dismiss +security_icon_help_green_lock +security_icon_help_red_open_lock +security_icon_help_show_all +security_icon_help_show_less +security_icon_help_title +security_icon_help_title_all +security_icon_help_warning_precise_mqtt +security_icon_help_yellow_open_lock +security_icon_insecure_no_precise +security_icon_insecure_precise_only +security_icon_secure +security_icon_warning_precise_mqtt +select +select_all +selected +selected_map_type +send +send_bell +send_bell_with_alert_message +sender_message_interval_seconds +### SERIAL ### +serial +serial_baud_rate +serial_config +serial_console +serial_enabled +serial_mode +serial_rx_pin +serial_tx_pin +server +session_active +session_refresh_required +set_up_connection +set_your_region +settings +### SHARE ### +share +share_channels_qr +share_contact +share_location +share_location_description +share_to +share_your_location_in_real_time +short_name +should_update +should_update_firmware +### SHOW ### +show_all_key_title +show_iaq_legend +show_layer +show_password +show_precision_circle +show_waypoints +shutdown +shutdown_node_name +shutdown_on_power_loss +shutdown_warning +signal +signal_quality +skip +slot +smart_position +snr +soil_moisture +soil_temperature +speed +speed_kmh +spread_factor +ssid +state_broadcast_seconds +status_message +status_message_config +stay_connected_anywhere +store_forward +store_forward_config +store_forward_enabled +subnet +super_deep_sleep_duration_seconds +supported +supported_by_community +sx126x_rx_boosted_gain +system_settings +### TAK ### +tak +tak_config +tak_role +tak_role_forwardobserver +tak_role_hq +tak_role_k9 +tak_role_medic +tak_role_rto +tak_role_sniper +tak_role_teamlead +tak_role_teammember +tak_role_unspecified +tak_server_enabled +tak_server_enabled_desc +tak_team +tak_team_blue +tak_team_brown +tak_team_cyan +tak_team_dark_blue +tak_team_dark_green +tak_team_green +tak_team_magenta +tak_team_maroon +tak_team_orange +tak_team_purple +tak_team_red +tak_team_teal +tak_team_unspecified_color +tak_team_white +tak_team_yellow +telemetry +telemetry_config +temperature +theme +theme_dark +theme_light +theme_system +time +time_zone +timeout +timestamp +tls_enabled +toggle_my_position +### TRACEROUTE ### +traceroute +traceroute_diff +traceroute_direct +traceroute_duration +traceroute_endpoint_missing +traceroute_forward_hops +traceroute_hops +traceroute_log +traceroute_map_no_data +traceroute_no_response +traceroute_outgoing_route +traceroute_return_hops +traceroute_return_route +traceroute_round_trip +traceroute_route_back_to_us +traceroute_route_towards_dest +traceroute_showing_nodes +track_and_share_locations +track_point +### TRAFFIC ### +traffic_management +traffic_management_config +traffic_management_drop_unknown_enabled +traffic_management_enabled +traffic_management_exhaust_hop_position +traffic_management_exhaust_hop_telemetry +traffic_management_nodeinfo_direct_response +traffic_management_nodeinfo_direct_response_max_hops +traffic_management_position_dedup +traffic_management_position_min_interval +traffic_management_position_precision +traffic_management_rate_limit_enabled +traffic_management_rate_limit_max_packets +traffic_management_rate_limit_window +traffic_management_router_preserve_hops +traffic_management_unknown_packet_threshold +transmit_over_lora +transport_ble +transport_tcp +transport_usb +triple_click_adhoc_ping +twenty_four_hours +two_days +two_weeks +tx_enabled +tx_power_dbm +type +type_a_message +udp_enabled +### UNKNOWN ### +unknown +unknown_age +unknown_channel +unknown_device +unknown_error +unknown_username +unmessageable +unmonitored_or_infrastructure +unmute +unrecognized +unset +up_down_select_input_enabled +update_interval +update_interval_seconds +updated +uplink_enabled +uplink_feature_description +uptime +### URL ### +url +url_cannot_be_empty +url_must_contain_placeholders +url_template +url_template_hint +usb +### USE ### +use_12h_format +use_homoglyph_characters_encoding +use_i2s_as_buzzer +use_input_pullup_mode +use_modem_preset +use_pwm_buzzer +### USER ### +user +user_config +user_id +user_info +user_string +userinfo +username +uv_lux +via_api +via_mqtt +via_udp +view_on_map +view_release +voltage +wait_for_bluetooth_duration_seconds +wake_on_tap_or_motion +warning +waypoint_delete +waypoint_edit +waypoint_new +waypoint_received +weight +### WIFI ### +wifi_config +wifi_devices +wifi_enabled +wifi_ip +wifi_provision_available_networks +wifi_provision_connect_failed +wifi_provision_description +wifi_provision_device_found +wifi_provision_device_found_detail +wifi_provision_mpwrd_disclaimer +wifi_provision_no_networks +wifi_provision_scan_failed +wifi_provision_scan_networks +wifi_provision_scanning_ble +wifi_provision_scanning_wifi +wifi_provision_sending_credentials +wifi_provision_signal_strength +wifi_provision_ssid_label +wifi_provision_ssid_placeholder +wifi_provision_status_applied +wifi_provision_status_failed +wifi_provision_success_description +wifi_provision_success_device_connected +wifi_provision_success_done +wifi_provision_success_ip_address +wifi_provision_success_missing_ip +wifi_provision_success_open_ssh +wifi_provision_success_open_ssh_fallback +wifi_provision_success_password_value +wifi_provision_success_setup_description +wifi_provision_success_setup_title +wifi_provision_success_ssh_command +wifi_provision_success_ssh_label +wifi_provision_success_ssh_unavailable +wifi_provision_success_username +wifi_provision_success_username_value +wifi_provisioning +wifi_qr_code_error +wifi_qr_code_scan +wifi_rssi_threshold_defaults_to_80 +### WIND ### +wind +wind_direction +wind_gust +wind_lull +wind_speed +you +zh_CN +zh_TW diff --git a/AGENTS.md b/AGENTS.md index e22717f9c..7f74d0372 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,113 +1,46 @@ # Meshtastic Android - Unified Agent & Developer Guide -You are an expert Android and Kotlin Multiplatform (KMP) engineer working on Meshtastic-Android, a decentralized mesh networking application. You must maintain strict architectural boundaries, use Modern Android Development (MAD) standards, and adhere to Compose Multiplatform and JetBrains Navigation 3 patterns. +You are an expert Android/KMP engineer. Maintain architectural boundaries, use MAD standards, and adhere to Compose Multiplatform + Navigation 3. -- **Project Goal:** Decouple business logic from the Android framework for seamless multi-platform execution (Android, Desktop, iOS) while maintaining a high-performance native Android experience. -- **Language & Tech:** Kotlin 2.3+ (JDK 21 REQUIRED), Gradle Kotlin DSL, Ktor, Okio, Room KMP. -- **Core Architecture:** - - `commonMain` is pure KMP. `androidMain` is strictly for Android framework bindings. - - App root DI and graph assembly live in the `app` and `desktop` host shells. -- **Skills Directory:** You **MUST** consult the relevant `.skills/` module before executing work: - - `.skills/project-overview/` - Codebase map, module directory, namespacing, environment setup, troubleshooting. - - `.skills/kmp-architecture/` - Bridging, expect/actual, source-sets, catalog aliases, build-logic conventions. - - `.skills/compose-ui/` - Adaptive UI, placeholders, string resources. - - `.skills/navigation-and-di/` - JetBrains Navigation 3 & Koin 4.2+ annotations. - - `.skills/testing-ci/` - Validation commands, CI pipeline architecture, CI Gradle properties. - - `.skills/implement-feature/` - Step-by-step feature workflow. - - `.skills/code-review/` - PR validation checklist. - - `.skills/new-branch/` - Canonical recipe for branching off upstream/main and rebasing stale PRs. -- **Active Status:** Read `docs/kmp-status.md` and `docs/roadmap.md` to understand the current KMP migration epoch. +- **Project Goal:** Decouple business logic from Android for multi-platform (Android, Desktop, iOS). +- **Tech:** Kotlin 2.3+ (JDK 21), Ktor, Okio, Room KMP, Koin 4.2+. +- **Agent Memory:** Consult `.agent_memory/session_context.md` for the latest task-specific handovers and project state. +- **Skills Directory (CONSULT THESE FIRST):** + - `.skills/project-overview/` - Codebase map, namespacing, **Bootstrap Steps**. + - `.skills/kmp-architecture/` - Expect/actual, source-sets, conventions. + - `.skills/compose-ui/` - Adaptive UI, **String Resources (consult strings-index.txt first)**. + - `.skills/navigation-and-di/` - Navigation 3 & Koin annotations. + - `.skills/testing-ci/` - Validation commands, **CI Architecture**. + - `.skills/ci-cost-control/` - **CI Budgeting & Monitoring**. + - `.skills/implement-feature/` - Feature workflow. + - `.skills/code-review/` - **PR & Commit Hygiene**, validation checklist. + - `.skills/new-branch/` - Branching and rebasing recipes. - -- **Workspace Bootstrap (MUST run first):** Before executing any Gradle task in a new workspace, agents MUST automatically: - 1. **Find the Android SDK** — `ANDROID_HOME` is often unset in agent worktrees. Probe `~/Library/Android/sdk`, `~/Android/Sdk`, and `/opt/android-sdk`. Export the first one found. If none exist, ask the user. - 2. **Init the proto submodule** — Run `git submodule update --init`. The `core/proto/src/main/proto` submodule contains Protobuf definitions required for builds. - 3. **Init secrets** — If `local.properties` does not exist, copy `secrets.defaults.properties` to `local.properties`. Without this the `google` flavor build fails. -- **Think First:** Reason through the problem before writing code. For complex KMP tasks involving multiple modules or source sets, outline your approach step-by-step before executing. -- **Plan Before Execution:** Use the git-ignored `.agent_plans/` directory to write markdown implementation plans (`plan.md`) and Mermaid diagrams (`.mmd`) for complex refactors before modifying code. -- **Atomic Execution:** Follow your plan step-by-step. Do not jump ahead. Use TDD where feasible (write `commonTest` fakes first). -- **Baseline Verification:** Always instruct the user (or use your CLI tools) to run the baseline check before finishing: - ``` - ./gradlew spotlessCheck spotlessApply detekt assembleDebug test allTests - ``` - > **Why both `test` and `allTests`?** In KMP modules, `test` is ambiguous and Gradle silently skips them. `allTests` is the KMP lifecycle task that covers KMP modules. Conversely, `allTests` does NOT cover pure-Android modules (`:app`, `:core:api`), so both tasks are required. - > For KMP cross-platform compilation, also run `./gradlew kmpSmokeCompile` (compiles all KMP modules for JVM + iOS Simulator — used by CI's `lint-check` job). - - - -- **Codebase Search:** Use whatever search and navigation tools your environment provides (file search, grep/ripgrep, symbol lookup, semantic search, etc.) to map out project boundaries before coding. Prefer `rg` (ripgrep) over `grep` or `find` for raw text search. -- **Terminal Pagers:** When running shell commands like `git diff` or `git log`, ALWAYS use `--no-pager` (e.g., `git --no-pager diff`) to prevent getting stuck in an interactive prompt. -- **Fetch Up-to-Date Docs:** If your environment supports web search, MCP servers, or documentation lookup tools, actively query them for the latest documentation on Koin 4.x, JetBrains Navigation 3, and Compose Multiplatform 1.11. -- **Clone Reference Repos:** If documentation is insufficient, use shell commands to clone bleeding-edge KMP dependency repositories into the local `.agent_refs/` directory (git-ignored) to inspect their source and test suites. Recommended: - - `https://github.com/JetBrains/kotlin-multiplatform-dev-docs` (Official Docs) - - `https://github.com/InsertKoinIO/koin` (Koin Annotations 4.x) - - `https://github.com/JetBrains/compose-multiplatform` (Navigation 3, Adaptive UI) - - `https://github.com/JuulLabs/kable` (BLE) - - `https://github.com/coil-kt/coil` (Coil 3 KMP) - - `https://github.com/ktorio/ktor` (Ktor Networking) -- **Formatting Hooks:** Always run `./gradlew spotlessApply` as an automatic formatting hook to fix style violations after editing. - - - -`AGENTS.md` is the single source of truth for agent instructions. Agent-specific files redirect here: -- `.github/copilot-instructions.md` — Copilot redirect to `AGENTS.md`. -- `CLAUDE.md` — Claude Code entry point; imports `AGENTS.md` via `@AGENTS.md` and adds Claude-specific instructions. -- `GEMINI.md` — Gemini redirect to `AGENTS.md`. Gemini CLI also configured via `.gemini/settings.json` to read `AGENTS.md` directly. - -Do NOT duplicate content into agent-specific files. When you modify architecture, module targets, CI tasks, validation commands, or agent workflow rules, update `AGENTS.md`, `.skills/`, and `docs/kmp-status.md` as needed. - + +- **Think First:** Read only what you need. Consult indices (like `strings-index.txt`) before reading large files. +- **Hygiene:** Run `python3 scripts/sort-strings.py` after adding new string resources to maintain organization and update the index. +- **Memory Persistence:** Update `.agent_memory/session_context.md` at the end of every session or major task. +- **Bootstrap First:** Run the mandatory bootstrap steps in `.skills/project-overview/SKILL.md` before any build. +- **Plan Before Execution:** Use `.agent_plans/` (git-ignored) for complex refactors. +- **Baseline Verification:** Always run: `./gradlew spotlessApply spotlessCheck detekt assembleDebug test allTests` + -- **No Lazy Coding:** DO NOT use placeholders like `// ... existing code ...`. Always provide complete, valid code blocks for the sections you modify to ensure correct diff application. -- **No Framework Bleed:** NEVER import `java.*` or `android.*` in `commonMain`. Use KMP equivalents: `Okio` for `java.io.*`, `kotlinx.coroutines.sync.Mutex` for `java.util.concurrent.locks.*`, `atomicfu` or Mutex-guarded `mutableMapOf()` for `ConcurrentHashMap`. Use `org.meshtastic.core.common.util.ioDispatcher` instead of `Dispatchers.IO` directly. -- **Koin Annotations:** Use `@Single`, `@Factory`, and `@KoinViewModel` inside `commonMain` instead of manual constructor trees. Do not enable A1 module compile safety — A3 full-graph validation (`VerifyModule`) is the correct approach because interfaces and implementations live in separate modules. Always register new feature modules in **both** `AppKoinModule.kt` and `DesktopKoinModule.kt`; they are not auto-activated. -- **CMP Over Android:** Use `compose-multiplatform` constraints. `stringResource` only supports `%N$s` and `%N$d` — pre-format floats with `NumberFormatter.format()` from `core:common` and pass as `%N$s`. In ViewModels/coroutines use `getStringSuspend(Res.string.key)`; never blocking `getString()`. Always use `MeshtasticNavDisplay` (not raw `NavDisplay`) as the navigation host, and `NavigationBackHandler` (not Android's `BackHandler`) for back gestures in shared code. -- **ProGuard:** When adding a reflection-heavy dependency, add keep rules to **both** `app/proguard-rules.pro` and `desktop/proguard-rules.pro` and verify release builds. -- **Always Check Docs:** If unsure about an abstraction, search `core:ui/commonMain` or `core:navigation/commonMain` before assuming it doesn't exist. -- **Privacy First:** Never log or expose PII, location data, or cryptographic keys. Meshtastic is used for sensitive off-grid communication — treat all user data with extreme caution. -- **Dependency Discipline:** Never add a library without first checking `libs.versions.toml` and justifying its inclusion against the project's size and complexity goals. Prefer removing dependencies over adding them. -- **Zero Lint Tolerance:** A task is incomplete if `detekt` fails or `spotlessCheck` does not pass for touched modules. -- **Read Before Refactoring:** When a pattern contradicts best practices, analyze whether it is legacy debt or a deliberate architectural choice before proposing a change. -- **Verify Before Push:** Treat any "push", "commit and push", or "push and pr" request as **verify-then-push**. Before `git push`, run `./gradlew spotlessApply detekt` (and the relevant `:module:test` / `:module:lintDebug` for touched modules). CI has repeatedly failed on `UnusedParameter`, `CyclomaticComplexMethod`, and `MagicNumber` from skipping this step. Only push on green; if a check fails, fix it before pushing. -- **Never Touch Protos or Secrets:** `core/proto/src/main/proto` is an upstream submodule — **do not modify** any `.proto` file. If a feature request requires a proto change, stop and report it as upstream (label issue `upstream`, point at `meshtastic/protobufs`). Likewise, never `git add` `app/google-services.json`, `local.properties`, `secrets.properties`, or any `*.keystore` / `*.jks` file — these are gitignored and contain secrets. -- **Multi-Flavor Install Hygiene:** When using the `android` CLI MCP to install/run on a connected device, the `fdroid` (`com.geeksville.mesh`) and `google` (`com.geeksville.mesh.google`) flavors have different signatures and **cannot coexist**. Before any install: pick a flavor explicitly, force-stop and uninstall the other flavor on every connected device, then install. Stale installs of the other flavor are a recurring source of "the fix didn't work" red herrings. -- **Verify UI With Annotated Screenshots:** For any UI/UX task, do **not** claim a fix works based on logs or assumed state. Capture an annotated screenshot via the `android` CLI MCP (or its annotated-screenshot tool) on a real connected device, and inspect the result before reporting back. -- **Branch Scope Discipline:** If a working branch grows beyond ~5 logical commits, crosses unrelated concerns, or accumulates a large blast radius, proactively propose a fresh branch off `upstream/main` and cherry-pick only the high-signal, low-risk changes (see `.skills/new-branch/SKILL.md`). Don't keep piling onto a sprawling branch. +- **Token Hygiene:** NEVER read binary files (PNG, MP3, etc.) or large non-code resources unless essential. Use file paths to reason about assets. +- **Context Discipline:** Limit your context to relevant modules. Do not "vacuum" the entire codebase for localized fixes. +- **No Lazy Coding:** DO NOT use placeholders like `// ... existing code ...`. Provide complete, valid code blocks. +- **No Framework Bleed:** NEVER import `java.*` or `android.*` in `commonMain`. Use KMP equivalents (Okio, Mutex, atomicfu). +- **CMP Over Android:** Use `compose-multiplatform` constraints. Pre-format floats with `NumberFormatter.format()`. Use `MeshtasticNavDisplay` and `NavigationBackHandler`. +- **Zero Lint Tolerance:** Task is incomplete if `detekt` or `spotlessCheck` fails. +- **Verify Before Push:** Treat any "push" as verify-then-push. CI has failed repeatedly due to skipped local checks. +- **Never Touch Protos or Secrets:** `core/proto` is an upstream submodule. Secrets are git-ignored. +- **Privacy First:** Never log or expose PII, location, or cryptographic keys. - -These tips apply when the agent is the GitHub Copilot CLI. Other agent runtimes may ignore this -section. - -- **Delegate long autonomous work.** For sweeping audits, multi-hour investigations, or "fleet" - prompts (*"investigate why X is broken on release"*, *"audit the diff since tag vX.Y.Z"*, - *"review the codebase for best practices against spec Z"*), prefer `/delegate` so the GitHub - cloud agent opens a PR while the user keeps working locally. Don't tie up an interactive - session on work that can run unattended. -- **Use `/research` for "latest hotness" prompts.** When the user asks for *"the latest scoop"* - on Kotlin / KMP / Compose / Koin trends, the built-in `/research` slash command performs deep - research across GitHub and the web with better source grounding than an ad-hoc prompt. -- **Use `/plan` mode for "noodle it out" prompts.** When the user asks for an implementation - plan, a "walk me through next steps", or explicitly says "don't do anything yet" — switch to - plan mode (Shift+Tab or `/plan`). Plans persist in the session workspace and keep the agent - from prematurely editing files. Continue to write long-form plans and Mermaid diagrams to - `.agent_plans/` (git-ignored) for multi-module refactors. -- **`/share` audit and review outputs.** After large audits, PR safety reviews, or release-cycle - quality passes, offer `/share` to export the findings to a gist or markdown file. These - reports are valuable artifacts — don't let them die in session history. -- **Prefer `/rewind` or `ctrl+s` over retyping.** If a turn went sideways, `/rewind` reverts - file changes and the turn; `ctrl+s` submits while preserving the input for quick iteration. - Avoid re-issuing the same prompt verbatim. -- **New-branch flow lives in a skill.** When the user says "fresh branch off fetched origin/main" - or "rebase PR #NNNN", consult `.skills/new-branch/SKILL.md` rather than re-deriving the recipe. - - - -- **Commit Hygiene:** Squash fixup/polish/review-feedback commits before opening a PR. Each commit should represent a logical, self-contained unit of work — not a back-and-forth conversation. -- **PR Descriptions:** Keep PR descriptions concise and scannable. State *what changed* and *why*, not a per-commit play-by-play. Use a short summary paragraph followed by a bullet list of changes. Avoid tables, headers-per-commit, or verbose breakdowns. Reference the `meshtastic/firmware` repo PRs for tone and style. -- **PR Titles:** Use conventional commit format: `feat(scope):`, `fix(scope):`, `refactor(scope):`, `chore(scope):`. Keep titles under ~72 characters. - + +`AGENTS.md` is the source of truth. Redirects: `.github/copilot-instructions.md`, `CLAUDE.md`, `GEMINI.md`. + diff --git a/core/resources/src/commonMain/composeResources/values/strings.xml b/core/resources/src/commonMain/composeResources/values/strings.xml index fe5f0b808..4c4792161 100644 --- a/core/resources/src/commonMain/composeResources/values/strings.xml +++ b/core/resources/src/commonMain/composeResources/values/strings.xml @@ -16,466 +16,113 @@ --> - Meshtastic - - - Kreyòl ayisyen - Português do Brasil - 简体中文 - 繁體中文 - - hey I found the cache, it is over here next to the big tiger. I'm kinda scared. - - mqtt.meshtastic.org - - Meshtastic %1$s - Filter - clear node filter - Filter by - Include unknown - Exclude infrastructure - Hide offline nodes - Only show direct nodes - You are viewing ignored nodes,\nPress to return to the node list. - Sort by - Node sorting options - A-Z - Channel - Distance - Hops away - Last heard - via MQTT - via MQTT - via UDP - via API - Internal - via Favorite - Only show ignored Nodes - Exclude MQTT - Unrecognized - Waiting to be acknowledged - Queued for sending - Delivered to mesh - Unknown - Routing via SF++ chain… - Confirmed on SF++ chain - Acknowledged - No route - Received a negative acknowledgment - Timeout - No Interface - Max Retransmission Reached - No Channel - Packet too large - No response - Bad Request - Regional Duty Cycle Limit Reached - Not Authorized - Encrypted Send Failed - Unknown Public Key - Bad session key - Public Key unauthorized - PKI send failed, no public key - App connected or standalone messaging device. - Device that does not forward packets from other devices. - Treats packets from or to favorited nodes as ROUTER_LATE, and all other packets as CLIENT. - Infrastructure node for extending network coverage by relaying messages. Visible in nodes list. - Combination of both ROUTER and CLIENT. Not for mobile devices. - Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in nodes list. - Broadcasts GPS position packets as priority. - Broadcasts telemetry packets as priority. - Optimized for ATAK system communication, reduces routine broadcasts. - Device that only broadcasts as needed for stealth or power savings. - Broadcasts location as message to default channel regularly for to assist with device recovery. - Enables automatic TAK PLI broadcasts and reduces routine broadcasts. - Infrastructure node that always rebroadcasts packets once but only after all other modes, ensuring additional coverage for local clusters. Visible in nodes list. - - Rebroadcast any observed message, if it was on our private channel or from another mesh with the same lora parameters. - Same as behavior as ALL but skips packet decoding and simply rebroadcasts them. Only available in Repeater role. Setting this on any other roles will result in ALL behavior. - Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. Only rebroadcasts message on the nodes local primary / secondary channels. - Ignores observed messages from foreign meshes like LOCAL ONLY, but takes it step further by also ignoring messages from nodes not already in the node's known list. - Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role. - Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc. Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing. - - Treat double tap on supported accelerometers as a user button press. - Send a position on the primary channel when the user button is triple clicked. - Controls the blinking LED on the device. For most devices this will control one of the up to 4 LEDs, the charger and GPS LEDs are not controllable. - Time zone for dates on the device screen and log. - Use phone time zone - Whether in addition to sending it to MQTT and the PhoneAPI, our NeighborInfo should be transmitted over LoRa. Not available on a channel with default key and name. - - How long the screen remains on after the user button is pressed or messages are received. - Automatically toggles to the next page on the screen like a carousel, based the specified interval. - The compass heading on the screen outside of the circle will always point north. - Flip screen vertically. - Units displayed on the device screen. - Override automatic OLED screen detection. - Override default screen layout. - Bold the heading text on the screen. - Requires that there be an accelerometer on your device. - - The region where you will be using your radios. - Available modem presets, default is Long Fast. - Sets the maximum number of hops, default is 3. Increasing hops also increases congestion and should be used carefully. 0 hop broadcast messages will not get ACKs. - Your node’s operating frequency is calculated based on the region, modem preset, and this field. When 0, the slot is automatically calculated based on the primary channel name and will change from the default public slot. Change back to the public default slot if private primary and public secondary channels are configured. - - Very Long Range - Slow - Long Range - Fast - Long Range - Turbo - Long Range - Moderate - Long Range - Slow - Medium Range - Fast - Medium Range - Slow - Short Range - Turbo - Short Range - Fast - Short Range - Slow - Lite - Fast - Lite - Slow - Narrow - Fast - Narrow - Slow - - Enabling WiFi will disable the bluetooth connection to the app. - Enabling Ethernet will disable the bluetooth connection to the app. TCP node connections are not available on Apple devices. - Enable broadcasting packets via UDP over the local network. - - The maximum interval that can elapse without a node broadcasting a position. - The fastest that position updates will be sent if the minimum distance has been satisfied. - The minimum distance change in meters to be considered for a smart position broadcast. - How often should we try to get a GPS position (<10sec keeps GPS on). - Optional fields to include when assembling position messages. the more fields are included, the larger the message will be - leading to longer airtime and a higher risk of packet loss. - - Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio. Don't use this setting if you want to use your device with the phone apps or are using a device without a user button. - - Generated from your private key and sent out to other nodes on the mesh to allow them to compute a shared secret key. - Used to create a shared key with a remote device. - The public key authorized to send admin messages to this node. - Device is managed by a mesh administrator, the user is unable to access any of the device settings. - Serial Console over the Stream API. - Output live debug logging over serial, view and export position-redacted device logs over Bluetooth. - - - Position Packet - Broadcast Interval - Smart Position - Smart Interval - Smart Distance - Device GPS - Fixed Position - Altitude - GPS Polling Interval - Advanced Device GPS - GPS Receive GPIO - GPS Transmit GPIO - GPS EN GPIO - GPIO - Debug - - MSL - - Ch - Channel Name - QR code - Unknown Username - Send - You - Allow analytics and crash reporting. - Accept - Cancel - Discard - Save - New Channel URL received - Report - Location access is turned off, can not provide position to mesh. - Share - New Node Seen: %1$s - Disconnected - Device sleeping - IP Address: - Port: - Connected - Current connections: - Wifi IP: - Ethernet IP: - Connecting - Not connected - No device selected - Unknown Device - No network devices found - No USB devices found - USB - BLE - TCP - USB - Demo Mode - Connected to radio, but it is sleeping - Application update required - You must update this application on the app store (or Github). It is too old to talk to this radio firmware. Please read our docs on this topic. - None (disable) - Service notifications - Acknowledgements - Open Source Libraries - Meshtastic is built with the following open source libraries. Tap any library to view its license. - %1$d libraries - This Channel URL is invalid and can not be used - Debug Panel - Decoded Payload: - Export Logs - %1$d logs exported - Failed to write log file: %1$s - - - %1$d hour - %1$d hours - - - - %1$d day - %1$d days - - Filters - Active filters - Search in logs… - Next match - Previous match - Clear search - Add filter - Filter included - Clear all filters - Add custom filter - Preset Filters - Store mesh logs - Disable to skip writing mesh logs to disk - Clear Logs - Match Any | All - Match All | Any - This will remove all log packets and database entries from your device - It is a full reset, and is permanent. - Clear - Search emoji... - More reactions - Channel %1$s: %2$s Message from %1$s: %2$s - Header - Item %1$d - Footer - Pill - Dot - Text - Gauge - Gradient - This is a custom composable - With multiple lines and styles - Message delivery status - New messages below - Direct message notifications - Broadcast message notifications - Waypoint notifications - Alert notifications - Firmware update required. - The radio firmware is too old to talk to this application. For more information on this see our Firmware Installation guide. - OK - You must set a region! - Couldn't change channel, because radio is not yet connected. Please try again. - Export rangetest packets - Export all packets - Reset - Scan - Add - Are you sure you want to change to the default channel? - Reset to defaults - Apply - Theme - Contrast - Light - Dark - System default - Choose theme - Contrast level - Standard - Medium - High - Provide phone location to mesh - Compact encoding for Cyrillic - - Delete message? - Delete %1$s messages? - - Delete - Delete for everyone - Delete for me - Select - Select all - Close selection - Delete selected - Download Region - Name - Description - Locked - Save - Language - System default - Resend - Shutdown - Shutdown not supported on this device - ⚠️ This will SHUTDOWN the node. Physical interaction will be required to turn it back on. - Node: %1$s - Reboot - Traceroute - Show Introduction - Message - Quick chat options - New quick chat - Edit quick chat - Append to message - Instantly send - Show quick chat menu - Hide quick chat menu - Factory reset - Open settings - Firmware version: %1$s - Meshtastic needs "Nearby devices" permissions enabled to find and connect to devices via Bluetooth. You can disable when not in use. - Direct Message - NodeDB reset - Delivery confirmed - Your device may disconnect and reboot while settings are applied. - Error - Unknown error - Ignore - Remove from ignored - Add '%1$s' to ignore list? - Remove '%1$s' from ignore list? - Select download region - Tile download estimate: - Start Download - Exchange position - Close - Radio configuration - Module configuration + Accept + Acknowledgements + + Copy message + Delete message + React with emoji + Select device + Select message + Select network + Send reply + Show message status + Actions + ADC multiplier override + ADC multiplier override ratio + Add - Edit - Calculating… - Offline Manager - Current Cache size - Cache Capacity: %1$d MB\nCache Usage: %2$d MB - Clear Downloaded Tiles - Tile Source - SQL Cache purged for %1$s - SQL Cache purge failed, see logcat for details - Cache Manager - Download complete! - Download complete with %1$d errors - %1$d tiles - bearing: %1$d° distance: %2$s - Edit waypoint - Delete waypoint? - New waypoint - Received waypoint: %1$s - Duty Cycle limit reached. Cannot send messages right now, please try again later. - Remove - This node will be removed from your list until your node receives data from it again. - Mute notifications - 8 hours - 1 week - Always - Currently: - Always muted - Not muted - Muted for %1$d days, %2$s hours - Muted for %1$s hours - Mute notifications for '%1$s'? - Unmute notifications for '%1$s'? - Replace - Scan WiFi QR code - Invalid WiFi Credential QR code format - Navigate Back - Battery - ChUtil - AirUtil - %1$s: %2$s%% - %1$s: %2$s V - %1$s - %1$s: %2$s - Temp - Hum - Soil Temp - Soil Moist - Logs - Hops Away - Information - Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). - Percent of airtime for transmission used within the last hour. - IAQ - Encryption Key Meanings - Shared Key - Only channel messages can be sent/received. Direct Messages require the Public Key Infrastructure feature in 2.5+ firmware. - Public Key Encryption - Direct messages are using the new public key infrastructure for encryption. - Public key mismatch - The public key does not match the recorded key. You may remove the node and let it exchange keys again, but this may indicate a more security problem. Contact the user through another trusted channel, to determine if the key change was due to a factory reset or other intentional action. - User Info - New node notifications - SNR - RSSI - (Indoor Air Quality) relative scale IAQ value as measured by Bosch BME680. Value Range 0–500. - Device Metrics - Position - Last position update - Environment Metrics - Administration - Remote Administration - Bad - Fair - Good - None - Share to… - Signal - Signal Quality - Traceroute - Direct - - 1 hop - %1$d hops - - Hops towards %1$d Hops back %2$d - Outgoing route - Return route - Cannot show traceroute map because the start or destination node has no position information. - View on map - This traceroute does not have any mappable nodes yet. - Showing %1$d/%2$d nodes - Duration: %1$s s - Route traced toward destination:\n\n - Route traced back to us:\n\n - Forward Hops - Return Hops - Round Trip - No Response - Load 1m - Load 5m - Load 15m - One-minute system load average - Five-minute system load average - Fifteen-minute system load average - Available system memory in bytes - 1H - 24H - 1W - 2W - 1M - Max - Min - Expand chart - Collapse chart - Unknown Age - Copy - Alert Bell Character! - Critical Alert! - Favorite + Add a private note… + The following channels were found in the QR code. Select the ones you would like to add to your device. Existing channels will be preserved. + Add Network Tile Source Add to favorites - Remove from favorites - Add '%1$s' as a favorite node? - Remove '%1$s' as a favorite node? - Power Metrics + Add Layer + Add Local MBTiles File + Add + Add device manually… + Add Network Layer + Address + Admin Key + Admin Keys + Administration + Advanced + Advanced Device GPS + Advanced + + Air quality icon + Air quality metrics module enabled + Air quality metrics update interval + Percent of airtime for transmission used within the last hour. + AirUtil + + Alert bell buzzer + Alert bell LED + Alert Bell Character! + Alert bell vibra + Alert message buzzer + Alert message LED + Alert message vibra + All + Allow input source + Allow undefined pin access + Alt + Altitude + Always point north + Ambient Lighting + Ambient Lighting Config + Analytics are collected to help us improve the Android app (thank you), we will receive anonymized information about user behavior. This includes crash reports, screens used in the app, etc. + Allow analytics and crash reporting. + Analytics platforms: + Any + App Notifications + App + Application update required + Version + Apply + Are you sure? + Are you sure you want to change to the default channel? + Audio + Audio Config + Available pins + Back + Backup & Restore + Bad + Bandwidth + Baro + Battery + Battery INA_2XX I2C address + Bluetooth Devices + BLE RSSI threshold (defaults to -80) + Blue + + Bluetooth + Available Bluetooth Devices + Bluetooth Config + Bluetooth enabled + Configuration + Wirelessly manage your device settings and channels. + Discovery + Find and identify Meshtastic devices near you. + Bluetooth + Bold Heading + Settings + Broadcast Interval + Button GPIO + Buzzer GPIO + Calculating… + Cancel + Cancel reply + Canned Message + Canned Message Config + Canned message enabled + Couldn't change channel, because radio is not yet connected. Please try again. + Shutdown not supported on this device + Carousel interval + Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). + + Ch Channel 1 Channel 2 Channel 3 @@ -484,859 +131,1223 @@ Channel 6 Channel 7 Channel 8 - Current - Voltage - Are you sure? - Device Role Documentation and the blog post about Choosing The Right Device Role.]]> - I know what I'm doing. - Node %1$s has a low battery (%2$d%) - Low battery notifications - Low battery: %1$s - Low battery notifications (favorite nodes) - Baro - Enabled - Last heard: %2$s
Last position: %3$s
Battery: %4$s]]>
- Toggle my position - Orient north - User + Channel Features + This Channel URL is invalid and can not be used + Channel + Channel Name + Channel URL + ChUtil Channels - Device - Position - Power - Network - Display - LoRa - Bluetooth - Security - MQTT - Serial - External Notification - - Range Test - Telemetry - Canned Message - Audio - Remote Hardware - Neighbor Info - Ambient Lighting - Detection Sensor - Paxcounter - Audio Config - CODEC 2 enabled - PTT pin - CODEC2 sample rate - I2S word select - I2S data in - I2S data out - I2S clock - Bluetooth Config - Bluetooth enabled - Pairing mode - Fixed PIN - Uplink enabled - Downlink enabled - Default - Position enabled - Precise location - GPIO pin - Type - Hide password - Show password - Details - Environment - Ambient Lighting Config - LED state - Red - Green - Blue - Canned Message Config - Canned message enabled - Rotary encoder #1 enabled - GPIO pin for rotary encoder A port - GPIO pin for rotary encoder B port - GPIO pin for rotary encoder Press port - Generate input event on Press - Generate input event on CW - Generate input event on CCW - Up/Down/Select input enabled - Allow input source - Send bell - Messages - Device DB cache limit - Max device databases to keep on this phone - MeshLog retention period - Choose how long to keep logs. Select Never to keep all logs. - Never delete logs - Detection Sensor Config - Detection Sensor enabled - Minimum broadcast (seconds) - State broadcast (seconds) - Send bell with alert message - Friendly name - GPIO pin to monitor - Detection trigger type - Use INPUT_PULLUP mode - Device Role - Button GPIO - Buzzer GPIO - Rebroadcast Mode - Node Info Broadcast Interval - Double Tap as Button - Triple Click Ad Hoc Ping - Time Zone - LED Heartbeat - Device Display - Screen on for - Carousel interval - Compass north top - Flip screen - Display units - OLED type - Display mode - Always point north - Bold Heading - Wake on tap or motion - Compass orientation - External Notification Config - External notification enabled - Notifications on message receipt - Alert message LED - Alert message buzzer - Alert message vibra - Notifications on alert/bell receipt - Alert bell LED - Alert bell buzzer - Alert bell vibra - Output LED (GPIO) - Output LED active high - Output buzzer (GPIO) - Use PWM buzzer - Output vibra (GPIO) - Output duration (milliseconds) - Nag timeout (seconds) - Ringtone - Imported ringtone - File is empty - Error importing: %1$s - Play - Use I2S as buzzer - LoRa - Options - Advanced - Use Preset - Presets - Bandwidth - Spread Factor - Coding Rate - Region - Number of Hops - Transmit Enabled - Transmit Power - Frequency Slot - Override Duty Cycle - Ignore incoming - RX Boosted Gain - Frequency Override - PA fan disabled - Ignore MQTT - Ok to MQTT - MQTT Config - Inactive - Disconnected - Disconnected — %1$s - Connecting… - Connected - Reconnecting… - Reconnecting (attempt %1$d) — %2$s - Test connection - Probing broker… - Reachable. Broker accepted credentials. - Reachable (%1$s) - Broker rejected: %1$s - Host not found - Cannot reach broker (TCP) - TLS handshake failed - Timed out after %1$d ms - Connection failed - MQTT enabled - Address - Username - Password - Encryption enabled - JSON output enabled - TLS enabled - Root topic - Proxy to client enabled - Map reporting - Map reporting interval (seconds) - Neighbor Info Config - Neighbor Info enabled - Update interval (seconds) - Transmit over LoRa - WiFi Options - Enabled - WiFi enabled - SSID - PSK - Ethernet Options - Ethernet enabled - NTP server - rsyslog server - IPv4 mode - IP - Gateway - Subred - DNS - Paxcounter Config - Paxcounter enabled - Status Message - Status Message Config - The actual status string - WiFi RSSI threshold (defaults to -80) - BLE RSSI threshold (defaults to -80) - Latitude - Longitude - Set from current phone location - GPS Mode (Physical Hardware) - Position Flags - Power Config - Enable power saving mode - Shutdown on power loss - ADC multiplier override - ADC multiplier override ratio - Wait for Bluetooth duration - Super deep sleep duration - Minimum wake time - Battery INA_2XX I2C address - Range Test Config - Range test enabled - Sender message interval (seconds) - Save .CSV in storage (ESP32 only) - Remote Hardware Config - Remote Hardware enabled - Allow undefined pin access - Available pins - Direct Message Key - Admin Keys - Public Key - Private Key - Admin Key - Managed Mode - Serial console - Debug log API enabled - Legacy Admin channel - Serial Config - Serial enabled - Echo enabled - Serial baud rate - RX - TX - Timeout - Serial mode - Override console serial port - - Heartbeat - Number of records - History return max - History return window - Server - Telemetry Config - Device metrics update interval - Environment metrics update interval - Environment metrics module enabled - Environment metrics on-screen enabled - Environment metrics use Fahrenheit - Air quality metrics module enabled - Air quality metrics update interval - Air quality icon - Power metrics module enabled - Power metrics update interval - Power metrics on-screen enabled - User Config - Node ID - Long Name - Short Name - Hardware model - Licensed amateur radio (Ham) - Enabling this option disables encryption and is not compatible with the default Meshtastic network. - Dew Point - Pressure - Gas Resistance - Distance - Lux - Wind - Wind Speed - Wind Gust - Wind Lull - Wind Dir - Rain (1h) - Rain (24h) - Weight - Radiation - 1-Wire Temp - - Indoor Air Quality (IAQ) - URL - - Import configuration - Export configuration - Hardware - Supported - Node Number - User ID - Uptime - Load %1$d - Disk Free %1$d - Timestamp - Heading - Speed - %1$d Km/h - Sats - Alt - Freq - Slot - Primary - Periodic position and telemetry broadcast - Secondary - No periodic telemetry broadcast - Manual position request required - Press and drag to reorder - Unmute - Dynamic - Share Contact - Notes - Add a private note… - Import Shared Contact? - Unmessageable - Unmonitored or Infrastructure - Warning: This contact is known, importing will overwrite the previous contact information. - Public Key Changed - Import - Request - Requesting %1$s from %2$s - User info - Request Telemetry - Device Metrics - Environment Metrics - Air-Quality Metrics - Power Metrics - Host Metrics - Pax Metrics - Metadata - Refresh metadata - Connect & administer - Establishing remote session… - Session active - Refresh required - Connect to a radio to administer remote nodes. - Could not reach node — try again or move closer. - Retry - Actions - Firmware - Use 12h clock format - When enabled, the device will display the time in 12-hour format on screen. - Host Metrics - Host - Free Memory - Load - User String - Navigate Into - Connection - Mesh Map - Conversations - Nodes - Settings - Selected - Set your region - Reply - Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, long and short name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name. - Consent to Share Unencrypted Node Data via MQTT - By enabling this feature, you acknowledge and expressly consent to the transmission of your device’s real-time geographic location over the MQTT protocol without encryption. This location data may be used for purposes such as live map reporting, device tracking, and related telemetry functions. - I have read and understand the above. I voluntarily consent to the unencrypted transmission of my node data via MQTT - I agree. - Firmware Update Recommended. - To benefit from the latest fixes and features, please update your node firmware.\n\nLatest stable firmware version: %1$s - Expires - Time - Date - Map Filter\n - Only Favorites - Show Waypoints - Show Precision Circles - Client Notification - Key Verification - Key Verification Request - Key Verification Complete - Duplicate Public Key Detected - Weak Encryption Key Detected - Compromised keys detected, select OK to regenerate. - Regenerate Private Key - Are you sure you want to regenerate your Private Key?\n\nNodes that may have previously exchanged keys with this node will need to Remove that node and re-exchange keys in order to resume secure communication. - Export Keys - Exports public and private keys to a file. Please store somewhere securely. - Modules unlocked - Modules already unlocked - Remote - (%1$d online / %2$d shown / %3$d total) - React - Disconnect - Scroll to bottom - Meshtastic - Security Status - Secure - Warning Badge - Unknown Channel - Warning - Overflow menu - UV Lux - Unknown - - This radio is managed and can only be changed by a remote admin. - Advanced + Chirpy + Contrast level + Choose theme + + This will remove %1$d nodes from your database. This action cannot be undone. + Caution: This removes nodes from in-app and on-device databases.\nSelections are additive. Clean Node Database Clean up nodes last seen older than %1$d days - Clean up only unknown nodes Clean Now - This will remove %1$d nodes from your database. This action cannot be undone. - - A green lock means the channel is securely encrypted with either a 128 or 256 bit AES key. - - - Insecure Channel, Not Precise - A yellow open lock means the channel is not securely encrypted, is not used for precise location data, and uses either no key at all or a 1 byte known key. - - - Insecure Channel, Precise Location - A red open lock means the channel is not securely encrypted, is used for precise location data, and uses either no key at all or a 1 byte known key. - - - Warning: Insecure, Precise Location & MQTT Uplink - A red open lock with a warning means the channel is not securely encrypted, is used for precise location data which is being uplinked to the internet via MQTT, and uses either no key at all or a 1 byte known key. - - - Channel Security - Channel Security Meanings - Show All Meanings - Show Current Status - Dismiss - Replying to %1$s - Cancel reply - Delete Messages? + Clean up only unknown nodes + Clear Clear selection - Message - Type a message - PAX Metrics - PAX - PAX: %1$d - B:%1$d - W:%1$d - PAX: %1$s - BLE: %1$s - WiFi: %1$s - No PAX metrics available. - Wi-Fi Provisioning for mPWRD-OS - Bluetooth Devices - Connected Device - - Rate Limit Exceeded. Please try again later. - View Release - Download - Currently Installed - Latest stable - Latest alpha - Supported by Meshtastic Community - Firmware Edition - Recent Network Devices - Discovered Network Devices - Scan for network devices - Scanning… - Scan for Bluetooth devices - Scanning… - Available Bluetooth Devices - Add device manually… - No devices found - No Bluetooth devices seen - Ensure you're within range of the device. - No network devices seen - Ensure you're connected to the same network as the device. - No USB devices seen - Connect the device via serial or USB. - No device connected - Connect to a device to discover nearby nodes. - Searching for nodes - Nearby nodes will appear here as they're discovered. - Set up connection - - Get started - Welcome to - Stay Connected Anywhere + Clear time zone + Client Notification + Close + Close selection + CODEC 2 enabled + CODEC2 sample rate + Coding Rate + Collapse chart Communicate off-the-grid with your friends and community without cell service. - Create Your Own Networks - Easily set up private mesh networks for secure and reliable communication in remote areas. - Track and Share Locations - Share your location in real-time and keep your group coordinated with integrated GPS features. - App Notifications - Incoming Messages - Notifications for channel and direct messages. - New Nodes - Notifications for newly discovered nodes. - Low Battery - Notifications for low battery alerts for the connected device. - Configure notification permissions - Phone Location - Meshtastic uses your phone's location to enable a number of features. You can update your location permissions at any time from settings. - Share Location - Use your phone GPS to send locations to your node to instead of using a hardware GPS on your node. - Distance Measurements - Display the distance between your phone and other Meshtastic nodes with positions. - Distance Filters - Filter the node list and mesh map based on proximity to your phone. - Mesh Map Location - Enables the blue location dot for your phone in the mesh map. + + Bearing: %1$s + Bearing: N/A + Distance: %1$s + Location provider is disabled. Turn on location services. + Waiting for a GPS fix to calculate distance and bearing. + Location permission is required to show distance and bearing. + This device does not have a compass sensor. Heading is unavailable. + Compass north top + Compass orientation + Compass + Estimated area: \u00b1%1$s (\u00b1%2$s) + Estimated area: unknown accuracy + Compromised keys detected, select OK to regenerate. + + Treat double tap on supported accelerometers as a user button press. + Controls the blinking LED on the device. For most devices this will control one of the up to 4 LEDs, the charger and GPS LEDs are not controllable. + Whether in addition to sending it to MQTT and the PhoneAPI, our NeighborInfo should be transmitted over LoRa. Not available on a channel with default key and name. + Send a position on the primary channel when the user button is triple clicked. + Time zone for dates on the device screen and log. + Use phone time zone + Automatically toggles to the next page on the screen like a carousel, based the specified interval. + The compass heading on the screen outside of the circle will always point north. + Override default screen layout. + Flip screen vertically. + Bold the heading text on the screen. + Override automatic OLED screen detection. + How long the screen remains on after the user button is pressed or messages are received. + Units displayed on the device screen. + Requires that there be an accelerometer on your device. + Your node’s operating frequency is calculated based on the region, modem preset, and this field. When 0, the slot is automatically calculated based on the primary channel name and will change from the default public slot. Change back to the public default slot if private primary and public secondary channels are configured. + Sets the maximum number of hops, default is 3. Increasing hops also increases congestion and should be used carefully. 0 hop broadcast messages will not get ACKs. + Available modem presets, default is Long Fast. + The region where you will be using your radios. + Enabling Ethernet will disable the bluetooth connection to the app. TCP node connections are not available on Apple devices. + Enable broadcasting packets via UDP over the local network. + Enabling WiFi will disable the bluetooth connection to the app. + The maximum interval that can elapse without a node broadcasting a position. + The minimum distance change in meters to be considered for a smart position broadcast. + The fastest that position updates will be sent if the minimum distance has been satisfied. + Optional fields to include when assembling position messages. the more fields are included, the larger the message will be - leading to longer airtime and a higher risk of packet loss. + How often should we try to get a GPS position (<10sec keeps GPS on). + Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio. Don't use this setting if you want to use your device with the phone apps or are using a device without a user button. + The public key authorized to send admin messages to this node. + Output live debug logging over serial, view and export position-redacted device logs over Bluetooth. + Device is managed by a mesh administrator, the user is unable to access any of the device settings. + Used to create a shared key with a remote device. + Generated from your private key and sent out to other nodes on the mesh to allow them to compute a shared secret key. + Serial Console over the Stream API. + Configure Bluetooth Permissions + Configure Critical Alerts Configure Location Permissions - Skip - settings + Configure notification permissions + Connect + Connect to a radio to administer remote nodes. + Connected + Connected Device + Connected to radio, but it is sleeping + Connecting + Current connections: + Connection + Contrast + High + Medium + Standard + Conversations + Copy + Create Your Own Networks + Critical Alert! Critical Alerts To ensure you receive critical alerts, such as SOS messages, even when your device is in "Do Not Disturb" mode, you need to grant special permission. Please enable this in the notification settings. - Configure Critical Alerts - Meshtastic uses notifications to keep you updated on new messages and other important events. You can update your notification permissions at any time from settings. - Next - %1$d nodes queued for deletion: - Caution: This removes nodes from in-app and on-device databases.\nSelections are additive. + Current + Currently: + Datadog: https://www.datadoghq.com/ + Date + %1$d dBm + + Debug + Active filters + Clear Logs + This will remove all log packets and database entries from your device - It is a full reset, and is permanent. + Decoded Payload: + Search in logs… + Failed to write log file: %1$s + %1$d logs exported + Add filter + Add custom filter + Clear all filters + Filter included + Preset Filters + Filters + Debug log API enabled + Export Logs + Debug Panel + Clear search + Next match + Previous match + Disable to skip writing mesh logs to disk + Store mesh logs + Default + mqtt.meshtastic.org + + Delete + Delete Network Tile Source + Delete for everyone + Delete for me + + Delete message? + Delete %1$s messages? + + Delete Messages? + Delete selected + Delivery confirmed + Your device may disconnect and reboot while settings are applied. + Demo Mode + clear node filter + Description + Meshtastic + Quit + Show Meshtastic + Meshtastic Desktop + Details + Detection Sensor + Detection Sensor Config + Detection Sensor enabled + Detection trigger type + + Device + Device configuration + Device DB cache limit + Max device databases to keep on this phone + Device GPS + %1$s: %2$s + Device Metrics + %1$s + %1$s: %2$s%% + Device metrics update interval + %1$s: %2$s V + Device sleeping + Device Storage & UI (Read-Only) + Send Device Telemetry + Enable/Disable the device telemetry module to send metrics to the mesh. These are nominal values. Congested meshes will automatically scale to longer intervals based on number of online nodes. + Theme: %1$s, Language: %2$s + Dew Point + Direct Message + Direct Message Key + Discard + Disconnect + Disconnected + Discovered Network Devices + Disk Free %1$d + + Display + Device Display + Display mode + When enabled, the device will display the time in 12-hour format on screen. + Display units + + Distance + Distance Filters + Filter the node list and mesh map based on proximity to your phone. + Distance Measurements + Display the distance between your phone and other Meshtastic nodes with positions. + DNS + Done + Don't show again for this device + Double Tap as Button + Downlink enabled + Messages from a public internet gateway are forwarded to the local mesh. Due to the zero-hop policy, traffic from the default MQTT server will not propagate further than this device. + Download + Duplicate Public Key Detected + Dynamic + Easily set up private mesh networks for secure and reliable communication in remote areas. + Echo enabled + Edit + Edit Network Tile Source + 8 Hours + MSL + Enable power saving mode + Enabled + + Encryption enabled + Public key mismatch + The public key does not match the recorded key. You may remove the node and let it exchange keys again, but this may indicate a more security problem. Contact the user through another trusted channel, to determine if the key change was due to a factory reset or other intentional action. + Public Key Encryption + Direct messages are using the new public key infrastructure for encryption. + Shared Key + Only channel messages can be sent/received. Direct Messages require the Public Key Infrastructure feature in 2.5+ firmware. + Environment Metrics + + Environment + Environment metrics module enabled + Environment metrics on-screen enabled + Environment metrics update interval + Environment metrics use Fahrenheit + Error + Duty Cycle limit reached. Cannot send messages right now, please try again later. + Connect & administer + Establishing remote session… + Ethernet Options + Ethernet enabled + Ethernet IP: + Exchange position + Expand chart + Expires + + Export configuration + Export all packets + Export Keys + Exports public and private keys to a file. Please store somewhere securely. + Export TAK Data Package + External Notification + External Notification Config + External notification enabled + Factory reset + Fair + Meshtastic %1$s + Favorite + Add '%1$s' as a favorite node? + Remove '%1$s' as a favorite node? + - %1$s (%2$d bytes) + Files available (%1$d): + + Add word or regex:pattern + Disable filtering + Enable Filtering + Enable filtering + Hide messages containing filter words + Hide %1$d filtered + Filter + Filtered + No filter words configured + Regex pattern + Message Filter + Show %1$d filtered + Whole word match + Filter Words + Messages containing these words will be hidden + Firebase: https://firebase.google.com/ + + Firmware + Firmware Edition + The radio firmware is too old to talk to this application. For more information on this see our Firmware Installation guide. + Firmware update required. + Almost there... + Alpha + Battery too low (%1$d%). Please charge your device before updating. + Checking for updates... + Connecting to device (attempt %1$d/%2$d)... + High-five! Wait, copying firmware... + Currently Installed: %1$s + Device: %1$s + Chirpy says, "Keep your ladder handy!" + You are about to flash new firmware to your device. This process carries risks.\n\n• Ensure your device is charged.\n• Keep the device close to your phone.\n• Do not close the app during the update.\n\nVerify you have selected the correct firmware for your hardware. + Update Warning + Note: This will temporarily disconnect your device during the update. + Do not close the app. + Done + Downloading firmware... %1$d% + Enabling DFU mode... + Erasing... + Error: %1$s + Extracting firmware... + Update failed + Flashing device, please wait... + Hang tight, we are working on it... + Firmware hash rejected. Device may require hash provisioning or bootloader update. + Keep your device close to your phone. + Update To: %1$s + Local File + BLE OTA + Update via %1$s + USB File Transfer + WiFi OTA + No device connected + Node user information is missing. + Could not find firmware for %1$s in release. + OTA update failed: %1$s + For RAK WisBlock RAK4631, use the vendor's serial DFU tool (for example, adafruit-nrfutil dfu serial with the provided bootloader .zip file). Copying the .uf2 file alone will not update the bootloader. + Rebooting to DFU... + Release Notes + Could not retrieve firmware file. + Retry + Please save the .uf2 file to your device's DFU drive. + Select Local File + Source: Local File + Stable + Starting DFU... + Starting OTA update... + Update Successful! + This might take a minute... + Target: %1$s + Firmware Update + Unknown error + Unknown hardware model: %1$d + Unknown remote release + Uploading firmware... + %1$s usually ships with a bootloader that does not support OTA updates. You may need to flash an OTA-capable bootloader over USB before flashing OTA. + USB Update failed + Your device has rebooted into DFU mode and should appear as a USB drive (e.g., RAK4631).\n\nWhen the file picker opens, please select the root of that drive to save the firmware file. + Select DFU USB Drive + Validating firmware... + Verification timed out. Device did not reconnect in time. + Verifying update... + Waiting for device to reboot into OTA mode... + Waiting for device to reconnect... + Firmware version: %1$s + Fixed PIN + Fixed Position + Flip screen + For more information, see our privacy policy. + Kreyòl ayisyen + Free Memory + Available system memory in bytes + Freq + Frequency Slot + Friendly name + Gas Resistance + Gateway + Generate input event on CCW + Generate input event on CW + Generate input event on Press + Generate QR Code + Get started + Good + + GPIO + GPIO pin + GPIO pin for rotary encoder A port + GPIO pin for rotary encoder B port + GPIO pin for rotary encoder Press port + GPIO pin to monitor + GPS EN GPIO + GPS Mode (Physical Hardware) + GPS Receive GPIO + GPS Transmit GPIO + Green + Hardware + Hardware model + Heading + Heartbeat + Hide Layer + Hide password + History return max + History return window + Number of Hops + Hops Away + Host + Host Metrics + Hum + I agree. + I have read and understand the above. I voluntarily consent to the unencrypted transmission of my node data via MQTT + I know what I'm doing. + I2S clock + I2S data in + I2S data out + I2S word select + IAQ + (Indoor Air Quality) relative scale IAQ value as measured by Bosch BME680. Value Range 0–500. + Icon Meanings + + Ignore + Add '%1$s' to ignore list? + Ignore incoming + Ignore MQTT + Remove '%1$s' from ignore list? + Import configuration + Warning: This contact is known, importing will overwrite the previous contact information. + Import + Import Shared Contact? + Incoming Messages + Indoor Air Quality (IAQ) + Information + Input Channel URL + Input Shared Contact URL + Currently Installed + Internal + Always On + Unset + Show Introduction + Welcome to + IP + IP Address: + Port: + IPv4 mode + JSON output enabled + Key Verification Complete + Key Verification Request + Key Verification + + Lite - Fast + Lite - Slow + Long Range - Fast + Long Range - Moderate + Long Range - Slow + Long Range - Turbo + Medium Range - Fast + Medium Range - Slow + Narrow - Fast + Narrow - Slow + Short Range - Fast + Short Range - Slow + Short Range - Turbo + Very Long Range - Slow + Filter by Last Heard time: %1$s + Last position update + Latest alpha + Latest stable + Latitude + Learn more + LED Heartbeat + LED state + Legacy Admin channel + %1$d libraries + Licensed amateur radio (Ham) + Enabling this option disables encryption and is not compatible with the default Meshtastic network. + + Load + Load 15m + Fifteen-minute system load average + Load 1m + One-minute system load average + Load 5m + Five-minute system load average + Load %1$d + Loading + + Local MBTiles File + Bad %1$d + Battery: %1$d% + Diagnostics: %1$s + Dropped %1$d + Heap + %1$d / %2$d + Nodes: %1$d online / %2$d total + Noise %1$d dBm + Relays: %1$d (Canceled: %2$d) + Traffic: TX %1$d / RX %2$d (D: %3$d) + %1$s + Uptime: %1$s + ChUtil: %1$s% | AirTX: %2$s% + Location access is turned off, can not provide position to mesh. + Location Sharing + Locked + + MeshLog retention period + + %1$d day + %1$d days + + Choose how long to keep logs. Select Never to keep all logs. + + %1$d hour + %1$d hours + + Never delete logs + Logs + Long Name + Longitude + LoRa + LoRa + Low Battery + Node %1$s has a low battery (%2$d%) + Low battery: %1$s + Weak Encryption Key Detected + Lux + Manage Custom Tile Sources + Manage Map Layers + Managed Mode + Manual position request required + + Mesh Map + Cache Capacity: %1$d MB\nCache Usage: %2$d MB + Cache Manager + Current Cache size + %1$d tiles + Clear Downloaded Tiles + Download complete! + Download complete with %1$d errors + Download Region + Map Filter\n + Map layers support .kml, .kmz, or GeoJSON formats. + %1$s<br>Last heard: %2$s<br>Last position: %3$s<br>Battery: %4$s + Offline Manager + SQL Cache purge failed, see logcat for details + SQL Cache purged for %1$s + Map reporting + Consent to Share Unencrypted Node Data via MQTT + By enabling this feature, you acknowledge and expressly consent to the transmission of your device’s real-time geographic location over the MQTT protocol without encryption. This location data may be used for purposes such as live map reporting, device tracking, and related telemetry functions. + Map reporting interval (seconds) + Your node will periodically send an unencrypted map report packet to the configured MQTT server, this includes id, long and short name, approximate location, hardware model, role, firmware version, LoRa region, modem preset and primary channel name. + Select download region + Start Download + Map style selection + bearing: %1$d° distance: %2$s + Tile download estimate: + Tile Source + Hybrid Normal Satellite Terrain - Hybrid - Manage Map Layers - Map layers support .kml, .kmz, or GeoJSON formats. - No map layers loaded. - Hide Layer - Show Layer - Remove Layer - Add Layer - Nodes at this location - Selected Map Type - Manage Custom Tile Sources - Add Network Tile Source - No custom tile sources found. - Edit Network Tile Source - Delete Network Tile Source + Mark as read + Match All | Any + Match Any | All + Max + Mesh Map Location + Enables the blue location dot for your phone in the mesh map. + + Meshtastic + Alert notifications + Meshtastic + Broadcast message notifications + Low battery notifications + Low battery notifications (favorite nodes) + Direct message notifications + New node notifications + Service notifications + Waypoint notifications + + Message + Message delivery status + This radio is managed and can only be changed by a remote admin. + Message + Delivered to mesh + Waiting to be acknowledged + Queued for sending + Confirmed on SF++ chain + Routing via SF++ chain… + Unknown + Messages + Min + Minimum broadcast (seconds) + Smart Distance + Smart Interval + Minimum wake time + Presets + Module configuration + Modules already unlocked + Modules unlocked + More reactions + mPWRD-OS + + MQTT + MQTT Config + MQTT enabled + Host not found + Connection failed + Broker rejected: %1$s + Probing broker… + Reachable. Broker accepted credentials. + Reachable (%1$s) + Cannot reach broker (TCP) + Timed out after %1$d ms + TLS handshake failed + Connected + Connecting… + Disconnected + Disconnected — %1$s + Inactive + Reconnecting… + Reconnecting (attempt %1$d) — %2$s + Test connection + You must set a region! + You must update this application on the app store (or Github). It is too old to talk to this radio firmware. Please read our docs on this topic. + + 1 week + 8 hours + Mute notifications for '%1$s'? + Always + Mute notifications + Unmute notifications for '%1$s'? + Always muted + Muted for %1$d days, %2$s hours + Muted for %1$s hours + Not muted + Nag timeout (seconds) + Name Name cannot be empty. - Provider name exists. - URL cannot be empty. - URL must contain placeholders. - URL Template - https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png - track point - App - Version - Channel Features - Location Sharing - Periodic position broadcast - Messages from the mesh will be sent to the public internet through any node's configured gateway. - Messages from a public internet gateway are forwarded to the local mesh. Due to the zero-hop policy, traffic from the default MQTT server will not propagate further than this device. - Icon Meanings - Disabling position on the primary channel allows periodic position broadcasts on the first secondary channel with the position enabled, otherwise manual position request required. - Device configuration - "[Remote] %1$s" - Send Device Telemetry - Enable/Disable the device telemetry module to send metrics to the mesh. These are nominal values. Congested meshes will automatically scale to longer intervals based on number of online nodes. - Any - 1 Hour - 8 Hours - 24 Hours - 48 Hours - Filter by Last Heard time: %1$s - %1$d dBm - System Settings + Navigate Back + Navigate Into + Neighbor Info + Neighbor Info Config + Neighbor Info enabled + Network + https://example.com/map.kml or .geojson + New Channel URL received + New messages below + New Node Seen: %1$s + New Nodes + Next + NFC is disabled. Please enable it in system settings. + + Ensure you're within range of the device. + No Bluetooth devices seen + No custom tile sources found. + No device selected + No devices found + No files manifested. No Stats Available - Analytics are collected to help us improve the Android app (thank you), we will receive anonymized information about user behavior. This includes crash reports, screens used in the app, etc. - Analytics platforms: - Firebase: https://firebase.google.com/ - Datadog: https://www.datadoghq.com/ - For more information, see our privacy policy. - https://meshtastic.org/docs/legal/privacy/ - Unset - 0 - - Heard %1$d relay - Heard %1$d relays - - - %1$s usually ships with a bootloader that does not support OTA updates. You may need to flash an OTA-capable bootloader over USB before flashing OTA. - Learn more - For RAK WisBlock RAK4631, use the vendor's serial DFU tool (for example, adafruit-nrfutil dfu serial with the provided bootloader .zip file). Copying the .uf2 file alone will not update the bootloader. - Don't show again for this device - Preserve Favorites? - - - Firmware Update - Checking for updates... - Device: %1$s - Currently Installed: %1$s - Update To: %1$s - Stable - Alpha - Note: This will temporarily disconnect your device during the update. - Downloading firmware... %1$d% - Error: %1$s - Retry - Update Successful! - Done - Starting DFU... - Enabling DFU mode... - Validating firmware... - Unknown hardware model: %1$d - No device connected - Could not find firmware for %1$s in release. - Extracting firmware... - Update failed - Hang tight, we are working on it... - Keep your device close to your phone. - Do not close the app. - Almost there... - This might take a minute... - Select Local File - Local File - Source: Local File - Unknown remote release - Update Warning - You are about to flash new firmware to your device. This process carries risks.\n\n• Ensure your device is charged.\n• Keep the device close to your phone.\n• Do not close the app during the update.\n\nVerify you have selected the correct firmware for your hardware. - Chirpy says, "Keep your ladder handy!" - Chirpy - Rebooting to DFU... - High-five! Wait, copying firmware... - Please save the .uf2 file to your device's DFU drive. - Flashing device, please wait... - USB File Transfer - BLE OTA - WiFi OTA - Update via %1$s - Select DFU USB Drive - Your device has rebooted into DFU mode and should appear as a USB drive (e.g., RAK4631).\n\nWhen the file picker opens, please select the root of that drive to save the firmware file. - Verifying update... - Verification timed out. Device did not reconnect in time. - Waiting for device to reconnect... - Target: %1$s - Release Notes - Unknown error - Node user information is missing. - Battery too low (%1$d%). Please charge your device before updating. - Could not retrieve firmware file. - USB Update failed - Firmware hash rejected. Device may require hash provisioning or bootloader update. - OTA update failed: %1$s - Waiting for device to reboot into OTA mode... - Connecting to device (attempt %1$d/%2$d)... - Starting OTA update... - Uploading firmware... - Erasing... - Back - - Unset - Always On - - %1$d second - %1$d seconds + No map layers loaded. + No network devices found + Ensure you're connected to the same network as the device. + No network devices seen + No PAX metrics available. + No USB devices found + Connect the device via serial or USB. + No USB devices seen + + (%1$d online / %2$d shown / %3$d total) + Exclude infrastructure + Exclude MQTT + You are viewing ignored nodes,\nPress to return to the node list. + Include unknown + Only show direct nodes + Hide offline nodes + Filter + Only show ignored Nodes + Filter by + Node ID + Node Number + A-Z + Node sorting options + Channel + Distance + Hops away + Last heard + Sort by + via Favorite + via MQTT + The actual status string + NodeDB reset + Node Info Broadcast Interval + + Nodes + Nodes at this location + Connect to a device to discover nearby nodes. + No device connected + Nearby nodes will appear here as they're discovered. + Searching for nodes + %1$d nodes queued for deletion: + None (disable) + None + Not connected + Note + Notes + Meshtastic uses notifications to keep you updated on new messages and other important events. You can update your notification permissions at any time from settings. + + Notifications for channel and direct messages. + Notifications for low battery alerts for the connected device. + Notifications for newly discovered nodes. + Notifications on alert/bell receipt + Notifications on message receipt + Now + NTP server + Number of records + Ok to MQTT + OK + OLED type + + 24 Hours + 1 Hour + 1H + 1M + 1W + 1-Wire Temp + Only Favorites + Open Compass + Open settings + Meshtastic is built with the following open source libraries. Tap any library to view its license. + Open Source Libraries + Options + Orient north + + Output buzzer (GPIO) + Output duration (milliseconds) + Output LED active high + Output LED (GPIO) + Output vibra (GPIO) + Overflow menu + Override console serial port + Override Duty Cycle + Frequency Override + PA fan disabled + Pairing mode + Password + + PAX + B:%1$d + BLE: %1$s + PAX Metrics + PAX: %1$d + PAX: %1$s + W:%1$d + WiFi: %1$s + Paxcounter + Paxcounter Config + Paxcounter enabled + Periodic position broadcast + Meshtastic needs "Nearby devices" permissions enabled to find and connect to devices via Bluetooth. You can disable when not in use. + Phone Location + Meshtastic uses your phone's location to enable a number of features. You can update your location permissions at any time from settings. + Play + + %1$d hour + %1$d hours %1$d minute %1$d minutes - - %1$d hour - %1$d hours + + %1$d second + %1$d seconds - - - Compass - Open Compass - Distance: %1$s - Bearing: %1$s - Bearing: N/A - This device does not have a compass sensor. Heading is unavailable. - Location permission is required to show distance and bearing. - Location provider is disabled. Turn on location services. - Waiting for a GPS fix to calculate distance and bearing. - Estimated area: \u00b1%1$s (\u00b1%2$s) - Estimated area: unknown accuracy - Mark as read - Now - The following channels were found in the QR code. Select the once you would like to add to your device. Existing channels will be preserved. + + Position + Set from current phone location + Position enabled + Position Flags + Position + Position Packet + + Power + Power Config + Power Metrics + Power metrics module enabled + Power metrics on-screen enabled + Power metrics update interval + Powered + Precise location + Language + System default + Preserve Favorites? + Press and drag to reorder + Pressure + + This is a custom composable + With multiple lines and styles + Dot + Footer + Gauge + Gradient + Header + Item %1$d + Pill + Text + Primary + Periodic position and telemetry broadcast + https://meshtastic.org/docs/legal/privacy/ + Private Key + Provide phone location to mesh + Provider name exists. + Proxy to client enabled + PSK + Português do Brasil + PTT pin + Public Key + Public Key Changed + QR code + + Quick chat options + Append to message + Edit quick chat + Hide quick chat menu + Instantly send + New quick chat + Show quick chat menu + Radiation + Radio configuration + Rain (1h) + Rain (24h) + Range Test + Range Test Config + Range test enabled + React + Reboot + + Rebroadcast Mode + Rebroadcast any observed message, if it was on our private channel or from another mesh with the same lora parameters. + Same as behavior as ALL but skips packet decoding and simply rebroadcasts them. Only available in Repeater role. Setting this on any other roles will result in ALL behavior. + Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc. Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing. + Ignores observed messages from foreign meshes like LOCAL ONLY, but takes it step further by also ignoring messages from nodes not already in the node's known list. + Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. Only rebroadcasts message on the nodes local primary / secondary channels. + Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role. + Recent Network Devices + Red + Refresh + Refresh metadata + Are you sure you want to regenerate your Private Key?\n\nNodes that may have previously exchanged keys with this node will need to Remove that node and re-exchange keys in order to resume secure communication. + Regenerate Private Key + Region + + Heard %1$d relay + Heard %1$d relays + + + Remote + Remote Administration + Could not reach node — try again or move closer. + Remote Hardware + Remote Hardware Config + Remote Hardware enabled + "[Remote] %1$s" + + Remove + Remove from favorites + Remove filter + Remove from ignored + Remove Layer + This node will be removed from your list until your node receives data from it again. + Replace This QR code contains a complete configuration. This will REPLACE your existing channels and radio settings. All existing channels will be removed. - Loading - - - Message Filter - Enable Filtering - Hide messages containing filter words - Filter Words - Messages containing these words will be hidden - Add word or regex:pattern - No filter words configured - Regex pattern - Whole word match - Show %1$d filtered - Hide %1$d filtered - Filtered - Enable filtering - Disable filtering - Channel URL - Scan NFC - Scan Shared Contact NFC - Scan Shared Contact QR Code - Input Shared Contact URL + Reply + Replying to %1$s + Report + + Request + Air-Quality Metrics + Device Metrics + Environment Metrics + Host Metrics + Metadata + Pax Metrics + Power Metrics + Request Telemetry + Requesting %1$s from %2$s + Resend + Reset + Reset to defaults + Retry + Ringtone + File is empty + Error importing: %1$s + Imported ringtone + + Device Role + Treats packets from or to favorited nodes as ROUTER_LATE, and all other packets as CLIENT. + App connected or standalone messaging device. + Device that only broadcasts as needed for stealth or power savings. + Device that does not forward packets from other devices. + Broadcasts location as message to default channel regularly for to assist with device recovery. + Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in nodes list. + Combination of both ROUTER and CLIENT. Not for mobile devices. + Infrastructure node for extending network coverage by relaying messages. Visible in nodes list. + Infrastructure node that always rebroadcasts packets once but only after all other modes, ensuring additional coverage for local clusters. Visible in nodes list. + Broadcasts telemetry packets as priority. + Optimized for ATAK system communication, reduces routine broadcasts. + Enables automatic TAK PLI broadcasts and reduces routine broadcasts. + Broadcasts GPS position packets as priority. + Root topic + Rotary encoder #1 enabled + I have read the <a href="https://meshtastic.org/docs/configuration/radio/device/#roles">Device Role Documentation</a> and the blog post about <a href="http://meshtastic.org/blog/choosing-the-right-device-role">Choosing The Right Device Role</a>. + + Bad session key + Public Key unauthorized + Bad Request + Regional Duty Cycle Limit Reached + Received a negative acknowledgment + Max Retransmission Reached + No Channel + No Interface + No response + No route + Acknowledged + Not Authorized + Encrypted Send Failed + PKI send failed, no public key + Unknown Public Key + Rate Limit Exceeded. Please try again later. + Timeout + Packet too large + RSSI + rsyslog server + hey I found the cache, it is over here next to the big tiger. I'm kinda scared. + Sats + Save + Save + Save .CSV in storage (ESP32 only) + Export rangetest packets + + Scan + Scan for Bluetooth devices Scan Channels NFC Scan Channels QR Code - Input Channel URL - Share Channels QR Code + Scan for network devices + Scan NFC Bring your device close to the NFC tag to scan. - Generate QR Code - NFC is disabled. Please enable it in system settings. - All - - Bluetooth - Configure Bluetooth Permissions - Discovery - Find and identify Meshtastic devices near you. - Configuration - Wirelessly manage your device settings and channels. - Map style selection - - Battery: %1$d% - Nodes: %1$d online / %2$d total - Uptime: %1$s - ChUtil: %1$s% | AirTX: %2$s% - Traffic: TX %1$d / RX %2$d (D: %3$d) - Relays: %1$d (Canceled: %2$d) - Diagnostics: %1$s - Noise %1$d dBm - Bad %1$d - Dropped %1$d - Heap - %1$d / %2$d - %1$s - Powered - Refresh - Updated - - - Add Network Layer - https://example.com/map.kml or .geojson - - Local MBTiles File - Add Local MBTiles File - + Scan Shared Contact NFC + Scan Shared Contact QR Code + Scanning… + Scanning… + Screen on for + Scroll to bottom + Search emoji... + Secondary + Disabling position on the primary channel allows periodic position broadcasts on the first secondary channel with the position enabled, otherwise manual position request required. + No periodic telemetry broadcast + + Security + Warning Badge + Security Status + Dismiss + A green lock means the channel is securely encrypted with either a 128 or 256 bit AES key. + A red open lock means the channel is not securely encrypted, is used for precise location data, and uses either no key at all or a 1 byte known key. + Show All Meanings + Show Current Status + Channel Security + Channel Security Meanings + A red open lock with a warning means the channel is not securely encrypted, is used for precise location data which is being uplinked to the internet via MQTT, and uses either no key at all or a 1 byte known key. + A yellow open lock means the channel is not securely encrypted, is not used for precise location data, and uses either no key at all or a 1 byte known key. + Insecure Channel, Not Precise + Insecure Channel, Precise Location + Secure + Warning: Insecure, Precise Location & MQTT Uplink + Select + Select all + Selected + Selected Map Type + Send + Send bell + Send bell with alert message + Sender message interval (seconds) + + Serial + Serial baud rate + Serial Config + Serial console + Serial enabled + Serial mode + RX + TX + Server + Session active + Refresh required + Set up connection + Set your region + settings + + Share + Share Channels QR Code + Share Contact + Share Location + Use your phone GPS to send locations to your node to instead of using a hardware GPS on your node. + Share to… + Share your location in real-time and keep your group coordinated with integrated GPS features. + Short Name + To benefit from the latest fixes and features, please update your node firmware.\n\nLatest stable firmware version: %1$s + Firmware Update Recommended. + + Encryption Key Meanings + Show air quality legend + Show Layer + Show password + Show Precision Circles + Show Waypoints + Shutdown + Node: %1$s + Shutdown on power loss + ⚠️ This will SHUTDOWN the node. Physical interaction will be required to turn it back on. + Signal + Signal Quality + Skip + Slot + Smart Position + SNR + Soil Moist + Soil Temp + Speed + %1$d Km/h + Spread Factor + SSID + State broadcast (seconds) + Status Message + Status Message Config + Stay Connected Anywhere + Store & Forward + Store & Forward Config + Store & Forward enabled + Subred + Super deep sleep duration + Supported + Supported by Meshtastic Community + RX Boosted Gain + System Settings + TAK (ATAK) TAK Configuration + Member Role + Forward Observer + Headquarters + Doggo (K9) + Medic + Radio Telephone Operator + Sniper + Team Lead + Team Member + Unspecified Enable Local TAK Server Starts a TCP server on port 8089 for ATAK connections Team Color - Member Role - + Blue + Brown + Cyan + Dark Blue + Dark Green + Green + Magenta + Maroon + Orange + Purple + Red + Teal Unspecified White Yellow - Orange - Magenta - Red - Maroon - Purple - Dark Blue - Blue - Cyan - Teal - Green - Dark Green - Brown - - Unspecified - Team Member - Team Lead - Headquarters - Sniper - Medic - Forward Observer - Radio Telephone Operator - Doggo (K9) - + Telemetry + Telemetry Config + Temp + Theme + Dark + Light + System default + Time + Time Zone + Timeout + Timestamp + TLS enabled + Toggle my position + + Traceroute + Hops towards %1$d Hops back %2$d + Direct + Duration: %1$s s + Cannot show traceroute map because the start or destination node has no position information. + Forward Hops + + 1 hop + %1$d hops + + Traceroute + This traceroute does not have any mappable nodes yet. + No Response + Outgoing route + Return Hops + Return route + Round Trip + Route traced back to us:\n\n + Route traced toward destination:\n\n + Showing %1$d/%2$d nodes + Track and Share Locations + track point + Traffic Management Traffic Management Configuration + Drop Unknown Packets Module Enabled - Position Deduplication - Position Precision (bits) - Min Position Interval (secs) + Local-only Position (Relays) + Local-only Telemetry (Relays) NodeInfo Direct Response Max Hops for Direct Response + Position Deduplication + Min Position Interval (secs) + Position Precision (bits) Rate Limiting - Rate Limit Window (secs) Max Packets in Window - Drop Unknown Packets - Unknown Packet Threshold - Local-only Telemetry (Relays) - Local-only Position (Relays) + Rate Limit Window (secs) Preserve Router Hops - Note - - Device Storage & UI (Read-Only) - Theme: %1$s, Language: %2$s - Files available (%1$d): - - %1$s (%2$d bytes) - No files manifested. - - Connect - Done - Wi-Fi Provisioning for mPWRD-OS + Unknown Packet Threshold + Transmit over LoRa + BLE + TCP + USB + Triple Click Ad Hoc Ping + 24H + 48 Hours + 2W + Transmit Enabled + Transmit Power + Type + Type a message + Enabled + + Unknown + Unknown Age + Unknown Channel + Unknown Device + Unknown error + Unknown Username + Unmessageable + Unmonitored or Infrastructure + Unmute + Unrecognized + Unset - 0 + Up/Down/Select input enabled + GPS Polling Interval + Update interval (seconds) + Updated + Uplink enabled + Messages from the mesh will be sent to the public internet through any node's configured gateway. + Uptime + + URL + URL cannot be empty. + URL must contain placeholders. + URL Template + https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png + USB + + Use 12h clock format + Compact encoding for Cyrillic + Use I2S as buzzer + Use INPUT_PULLUP mode + Use Preset + Use PWM buzzer + + User + User Config + User ID + User info + User String + User Info + Username + UV Lux + via API + via MQTT + via UDP + View on map + View Release + Voltage + Wait for Bluetooth duration + Wake on tap or motion + Warning + Delete waypoint? + Edit waypoint + New waypoint + Received waypoint: %1$s + Weight + + WiFi Options + Wi-Fi Provisioning for mPWRD-OS + WiFi enabled + Wifi IP: + Available Networks + Could not connect: %1$s Provision Wi-Fi credentials to your mPWRD-OS device via Bluetooth. - Learn more about the mPWRD-OS project\nhttps://github.com/mPWRD-OS - Searching for device… Device found Ready to scan for WiFi networks. + Learn more about the mPWRD-OS project\nhttps://github.com/mPWRD-OS + No networks found + Failed to scan for WiFi networks: %1$s Scan for Networks + Searching for device… Scanning… Applying WiFi configuration… - No networks found - Could not connect: %1$s - Failed to scan for WiFi networks: %1$s %1$d% - Available Networks Network Name (SSID) Enter or select a network WiFi configured successfully! Failed to apply WiFi configuration - Device Connected Your mPWRD-OS device has joined the Wi-Fi network. + Device Connected + Done IP Address - Complete Device Setup - Sign in over SSH to change the default username and password. - Username - root - 1234 - SSH Command - ssh %1$s@%2$s - SSH command available after IP is assigned. + IP unavailable Open SSH Client If no app opens, copy the SSH command and paste it into your SSH client. - IP unavailable - Done - Meshtastic Desktop - Show Meshtastic - Quit - Meshtastic - Export TAK Data Package - mPWRD-OS - Clear time zone - Filter - Remove filter - Show air quality legend - Show message status - Send reply - Copy message - Select message - Delete message - React with emoji - Select device - Select network + 1234 + Sign in over SSH to change the default username and password. + Complete Device Setup + ssh %1$s@%2$s + SSH Command + SSH command available after IP is assigned. + Username + root + Wi-Fi Provisioning for mPWRD-OS + Invalid WiFi Credential QR code format + Scan WiFi QR code + WiFi RSSI threshold (defaults to -80) + + Wind + Wind Dir + Wind Gust + Wind Lull + Wind Speed + You + 简体中文 + 繁體中文
+ diff --git a/scripts/ai-guardrail.sh b/scripts/ai-guardrail.sh new file mode 100755 index 000000000..c6ec5c5f4 --- /dev/null +++ b/scripts/ai-guardrail.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Meshtastic AI Guardrail - Prevent binary/log leaks in commits +# +# INSTALLATION +# ------------ +# Option 1 (recommended): set core.hooksPath so all devs share it automatically: +# git config core.hooksPath scripts/hooks +# mkdir -p scripts/hooks +# ln -sf ../../ai-guardrail.sh scripts/hooks/pre-commit +# +# Option 2: copy/symlink directly into the local .git directory: +# ln -sf ../../scripts/ai-guardrail.sh .git/hooks/pre-commit +# chmod +x .git/hooks/pre-commit +# +# To run manually: bash scripts/ai-guardrail.sh + +# List of patterns that should NEVER be committed by an AI Agent +FORBIDDEN_PATTERNS=( + "\.log$" + "\.png$" + "\.jpg$" + "\.jpeg$" + "\.webp$" + "\.mp3$" + "tmp/" + "\.agent_artifacts/" + "build/" + "google-services\.json$" + "local\.properties$" + "secrets\.properties$" +) + +VIOLATIONS=() + +while IFS= read -r -d '' file; do + for pattern in "${FORBIDDEN_PATTERNS[@]}"; do + if [[ $file =~ $pattern ]]; then + VIOLATIONS+=("$file (matched $pattern)") + fi + done +done < <(git diff --cached --name-only -z) + +if [ ${#VIOLATIONS[@]} -ne 0 ]; then + echo "❌ AI GUARDRAIL VIOLATION: Staged files contain high-token or sensitive artifacts:" + for violation in "${VIOLATIONS[@]}"; do + echo " - $violation" + done + echo "" + echo "Please unstage these files before committing. Use .copilotignore to prevent this in the future." + exit 1 +fi + +exit 0 diff --git a/scripts/sort-strings.py b/scripts/sort-strings.py new file mode 100644 index 000000000..6c20ddd62 --- /dev/null +++ b/scripts/sort-strings.py @@ -0,0 +1,98 @@ +import xml.etree.ElementTree as ET +import os +import re + +# Meshtastic String Sorter & Indexer +# Usage: python3 scripts/sort-strings.py +# This script alphabetizes strings.xml, adds prefix markers, and regenerates strings-index.txt. + +def sort_strings(xml_path, index_path): + print(f"Reading {xml_path}...") + with open(xml_path, 'r', encoding='utf-8', newline='\n') as f: + content = f.read() + + # Extract license header + header_match = re.search(r'^(.*?)', content, re.DOTALL) + header = header_match.group(1) if header_match else '\n' + + # Parse XML + tree = ET.parse(xml_path) + root = tree.getroot() + + # Extract elements and their names + elements = [] + for child in root: + name = child.get('name') + if name: + elements.append((name, child)) + + # Sort elements by name + elements.sort(key=lambda x: x[0]) + + # Group by prefix + grouped_elements = {} + for name, element in elements: + prefix = name.split('_')[0] + if prefix not in grouped_elements: + grouped_elements[prefix] = [] + grouped_elements[prefix].append(element) + + # Reconstruct XML and prepare Index + new_root = ET.Element('resources') + index_lines = [] + + sorted_prefixes = sorted(grouped_elements.keys()) + + for prefix in sorted_prefixes: + group = grouped_elements[prefix] + if len(group) >= 5: + marker = prefix.upper() + new_root.append(ET.Comment(f' {marker} ')) + index_lines.append(f"### {marker} ###") + + for element in group: + new_root.append(element) + index_lines.append(element.get('name')) + + # Pretty print helper + def prettify(elem, level=0): + indent = " " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = "\n" + (level + 1) * indent + if not elem.tail or not elem.tail.strip(): + elem.tail = "\n" + level * indent + for i, child in enumerate(elem): + prettify(child, level + 1) + if i < len(elem) - 1: + if not child.tail or not child.tail.strip(): + child.tail = "\n" + (level + 1) * indent + else: + if not child.tail or not child.tail.strip(): + child.tail = "\n" + level * indent + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = "\n" + level * indent + + prettify(new_root) + + # Write XML + xml_str = ET.tostring(new_root, encoding='unicode') + final_content = header + xml_str + '\n' + with open(xml_path, 'w', encoding='utf-8', newline='\n') as f: + f.write(final_content) + print(f"Successfully sorted {xml_path}") + + # Write Index + with open(index_path, 'w', encoding='utf-8', newline='\n') as f: + f.write('\n'.join(index_lines) + '\n') + print(f"Successfully regenerated {index_path}") + +if __name__ == "__main__": + xml_file = 'core/resources/src/commonMain/composeResources/values/strings.xml' + index_file = '.skills/compose-ui/strings-index.txt' + + if os.path.exists(xml_file): + sort_strings(xml_file, index_file) + else: + print(f"Error: {xml_file} not found.")