app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 7b9df71480e46e043f95fe19a176b27f64df6de1
parent 9bc40829a9169a51cb79a41e697527c9f164aa14
Author: triesap <tyson@radroots.org>
Date:   Sun, 19 Apr 2026 20:51:26 +0000

runtime: load app startup config from env

Diffstat:
Mcrates/shared/core/src/lib.rs | 7++++---
Mcrates/shared/core/src/runtime.rs | 318++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mplatforms/macos/Scripts/run_host.sh | 1-
Mplatforms/macos/Scripts/test_host.sh | 26+++++---------------------
Mscripts/run.sh | 14++------------
5 files changed, 173 insertions(+), 193 deletions(-)

diff --git a/crates/shared/core/src/lib.rs b/crates/shared/core/src/lib.rs @@ -19,8 +19,9 @@ pub use paths::{ }; pub use runtime::{ APP_HOST_PLATFORM, APP_ID, APP_NAME, APP_PLATFORM_RUNTIME, APP_PROJECTION_SOURCE, - APP_RUNTIME_CONFIG_ENV, APP_RUNTIME_CONFIG_SCHEMA, APP_RUNTIME_ORIGIN, AppBuildIdentity, - AppCoreRuntimeMetadata, AppHostRuntimeMetadata, AppRuntimeCapture, AppRuntimeConfig, - AppRuntimeConfigError, AppRuntimeMode, AppRuntimeSnapshot, runtime_mode_label, + APP_RUNTIME_MODE_ENV, APP_RUN_ID_ENV, APP_DEFAULT_NOSTR_RELAY_URL_ENV, + APP_LOCAL_LOG_ROOT_ENV, APP_RUNTIME_ORIGIN, AppBuildIdentity, AppCoreRuntimeMetadata, + AppHostRuntimeMetadata, AppRuntimeCapture, AppRuntimeConfig, AppRuntimeConfigError, + AppRuntimeMode, AppRuntimeSnapshot, runtime_mode_label, }; pub use startup::{AppStartupEvent, AppStartupEventMetadata, launch_startup_event}; diff --git a/crates/shared/core/src/runtime.rs b/crates/shared/core/src/runtime.rs @@ -3,7 +3,7 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use thiserror::Error; pub const APP_ID: &str = "org.radroots.app"; @@ -12,8 +12,10 @@ pub const APP_PLATFORM_RUNTIME: &str = "app-macos-native"; pub const APP_PROJECTION_SOURCE: &str = "gpui-native"; pub const APP_RUNTIME_ORIGIN: &str = "gpui://localhost"; pub const APP_HOST_PLATFORM: &str = "desktop"; -pub const APP_RUNTIME_CONFIG_ENV: &str = "RADROOTS_APP_RUNTIME_CONFIG_JSON"; -pub const APP_RUNTIME_CONFIG_SCHEMA: &str = "radroots.app.runtime-config.v1"; +pub const APP_RUNTIME_MODE_ENV: &str = "RADROOTS_APP_RUNTIME_MODE"; +pub const APP_RUN_ID_ENV: &str = "RADROOTS_APP_RUN_ID"; +pub const APP_DEFAULT_NOSTR_RELAY_URL_ENV: &str = "RADROOTS_APP_DEFAULT_NOSTR_RELAY_URL"; +pub const APP_LOCAL_LOG_ROOT_ENV: &str = "RADROOTS_APP_LOCAL_LOG_ROOT"; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum AppRuntimeMode { @@ -88,71 +90,48 @@ pub struct AppRuntimeSnapshot { #[derive(Debug, Error)] pub enum AppRuntimeConfigError { - #[error("missing required runtime config env: {APP_RUNTIME_CONFIG_ENV}")] - MissingEnv, - #[error("invalid app runtime config json")] - InvalidJson(#[source] serde_json::Error), - #[error("unsupported app runtime config schema: {0}")] - UnsupportedSchema(String), + #[error("missing required runtime env: {0}")] + MissingEnv(&'static str), #[error("unsupported runtime mode: {0}")] UnsupportedRuntimeMode(String), #[error("missing required runtime config field: {0}")] MissingField(&'static str), } -#[derive(Deserialize)] -struct RawRuntimeConfig { - schema_version: String, - runtime_mode: String, - run_id: String, - default_nostr_relay_url: String, - bundle_identifier: String, - bundle_name: String, - marketing_version: String, - build_number: String, - platform_name: String, - operating_system_version: String, - host_locale: String, - runtime_origin: String, - local_log_root: String, -} - impl AppRuntimeConfig { pub fn from_env() -> Result<Self, AppRuntimeConfigError> { - let raw = - std::env::var(APP_RUNTIME_CONFIG_ENV).map_err(|_| AppRuntimeConfigError::MissingEnv)?; - Self::from_json_str(&raw) + Self::from_env_with(|name| std::env::var(name).ok()) } - pub fn from_json_str(raw: &str) -> Result<Self, AppRuntimeConfigError> { - let config: RawRuntimeConfig = - serde_json::from_str(raw).map_err(AppRuntimeConfigError::InvalidJson)?; - - if config.schema_version != APP_RUNTIME_CONFIG_SCHEMA { - return Err(AppRuntimeConfigError::UnsupportedSchema( - config.schema_version, - )); - } + fn from_env_with<F>(mut read_env: F) -> Result<Self, AppRuntimeConfigError> + where + F: FnMut(&str) -> Option<String>, + { + let runtime_mode = parse_config_runtime_mode(&require_env_value( + &mut read_env, + APP_RUNTIME_MODE_ENV, + )?)?; + let run_id = require_env_value(&mut read_env, APP_RUN_ID_ENV)?; + let default_nostr_relay_url = + require_env_value(&mut read_env, APP_DEFAULT_NOSTR_RELAY_URL_ENV)?; + let local_log_root = + require_path_value(APP_LOCAL_LOG_ROOT_ENV, require_env_value(&mut read_env, APP_LOCAL_LOG_ROOT_ENV)?)?; Ok(Self { - runtime_mode: parse_config_runtime_mode(&config.runtime_mode)?, - run_id: require_value("run_id", config.run_id)?, - default_nostr_relay_url: require_value( - "default_nostr_relay_url", - config.default_nostr_relay_url, - )?, - bundle_identifier: require_value("bundle_identifier", config.bundle_identifier)?, - bundle_name: require_value("bundle_name", config.bundle_name)?, - marketing_version: require_value("marketing_version", config.marketing_version)?, - build_number: require_value("build_number", config.build_number)?, - platform_name: require_value("platform_name", config.platform_name)?, - operating_system_version: require_value( - "operating_system_version", - config.operating_system_version, - )?, - host_locale: require_value("host_locale", config.host_locale)?, - runtime_origin: require_value("runtime_origin", config.runtime_origin)?, - local_log_root: require_path_value("local_log_root", config.local_log_root)?, + runtime_mode, + run_id, + default_nostr_relay_url, + bundle_identifier: APP_ID.to_owned(), + bundle_name: APP_NAME.to_owned(), + marketing_version: env!("CARGO_PKG_VERSION").to_owned(), + build_number: option_env!("RADROOTS_GIT_COMMIT") + .unwrap_or(option_env!("PROFILE").unwrap_or("debug")) + .to_owned(), + platform_name: APP_HOST_PLATFORM.to_owned(), + operating_system_version: std::env::consts::OS.to_owned(), + host_locale: detect_host_locale(), + runtime_origin: APP_RUNTIME_ORIGIN.to_owned(), + local_log_root, }) } } @@ -283,6 +262,17 @@ fn require_value(field: &'static str, value: String) -> Result<String, AppRuntim Ok(trimmed.to_owned()) } +fn require_env_value<F>( + read_env: &mut F, + field: &'static str, +) -> Result<String, AppRuntimeConfigError> +where + F: FnMut(&str) -> Option<String>, +{ + let value = read_env(field).ok_or(AppRuntimeConfigError::MissingEnv(field))?; + require_value(field, value) +} + fn detect_host_locale() -> String { [ std::env::var("LC_ALL").ok(), @@ -317,10 +307,11 @@ fn build_run_id(mode: &AppRuntimeMode) -> String { #[cfg(test)] mod tests { - use std::path::PathBuf; + use std::{collections::BTreeMap, path::PathBuf}; use super::{ - APP_HOST_PLATFORM, APP_ID, APP_NAME, APP_PROJECTION_SOURCE, APP_RUNTIME_CONFIG_SCHEMA, + APP_DEFAULT_NOSTR_RELAY_URL_ENV, APP_HOST_PLATFORM, APP_ID, APP_LOCAL_LOG_ROOT_ENV, + APP_NAME, APP_PROJECTION_SOURCE, APP_RUN_ID_ENV, APP_RUNTIME_MODE_ENV, APP_RUNTIME_ORIGIN, AppBuildIdentity, AppRuntimeCapture, AppRuntimeConfig, AppRuntimeConfigError, AppRuntimeMode, AppRuntimeSnapshot, runtime_mode_label, }; @@ -336,24 +327,19 @@ mod tests { } } - fn test_runtime_config_json() -> String { - format!( - r#"{{ - "schema_version":"{APP_RUNTIME_CONFIG_SCHEMA}", - "runtime_mode":"localhost-dev", - "run_id":"run-localhost-dev-20260417T000000Z-deadbeefcafefeed", - "default_nostr_relay_url":"ws://127.0.0.1:8080", - "bundle_identifier":"org.radroots.app.macos", - "bundle_name":"Radroots", - "marketing_version":"0.1.0", - "build_number":"dev", - "platform_name":"macos", - "operating_system_version":"macos-15.5", - "host_locale":"en_US.UTF-8", - "runtime_origin":"gpui://localhost", - "local_log_root":"/tmp/radroots/logs" - }}"# - ) + fn test_runtime_env() -> BTreeMap<&'static str, String> { + BTreeMap::from([ + (APP_RUNTIME_MODE_ENV, "localhost-dev".to_owned()), + ( + APP_RUN_ID_ENV, + "run-localhost-dev-20260417T000000Z-deadbeefcafefeed".to_owned(), + ), + ( + APP_DEFAULT_NOSTR_RELAY_URL_ENV, + "ws://127.0.0.1:8080".to_owned(), + ), + (APP_LOCAL_LOG_ROOT_ENV, "/tmp/radroots/logs".to_owned()), + ]) } #[test] @@ -388,44 +374,63 @@ mod tests { } #[test] - fn runtime_config_requires_supported_schema() { - let error = AppRuntimeConfig::from_json_str( - r#"{"schema_version":"unsupported","runtime_mode":"localhost-dev","run_id":"x","default_nostr_relay_url":"ws://127.0.0.1:8080","bundle_identifier":"y","bundle_name":"z","marketing_version":"0.1.0","build_number":"1","platform_name":"macos","operating_system_version":"macos-15.5","host_locale":"en","runtime_origin":"gpui://localhost","local_log_root":"/tmp/logs"}"#, - ) - .expect_err("schema mismatch should fail"); - - assert!( - error - .to_string() - .contains("unsupported app runtime config schema") - ); + fn runtime_config_requires_explicit_runtime_mode_env() { + let env = BTreeMap::from([ + (APP_RUN_ID_ENV, "run-localhost-dev-20260417T000000Z-deadbeefcafefeed".to_owned()), + ( + APP_DEFAULT_NOSTR_RELAY_URL_ENV, + "ws://127.0.0.1:8080".to_owned(), + ), + (APP_LOCAL_LOG_ROOT_ENV, "/tmp/radroots/logs".to_owned()), + ]); + let error = AppRuntimeConfig::from_env_with(|name| env.get(name).cloned()) + .expect_err("missing runtime mode env should fail"); + + assert!(matches!( + error, + AppRuntimeConfigError::MissingEnv(APP_RUNTIME_MODE_ENV) + )); } #[test] fn runtime_config_surfaces_explicit_local_log_root() { - let config = - AppRuntimeConfig::from_json_str(&test_runtime_config_json()).expect("valid config"); + let env = test_runtime_env(); + let config = AppRuntimeConfig::from_env_with(|name| env.get(name).cloned()) + .expect("valid env config"); assert_eq!(config.runtime_mode, AppRuntimeMode::LocalhostDev); + assert_eq!( + config.run_id, + "run-localhost-dev-20260417T000000Z-deadbeefcafefeed" + ); assert_eq!(config.default_nostr_relay_url, "ws://127.0.0.1:8080"); - assert_eq!(config.bundle_identifier, "org.radroots.app.macos"); + assert_eq!(config.bundle_identifier, APP_ID); + assert_eq!(config.bundle_name, APP_NAME); + assert_eq!(config.platform_name, APP_HOST_PLATFORM); + assert_eq!(config.runtime_origin, APP_RUNTIME_ORIGIN); + assert_eq!(config.operating_system_version, std::env::consts::OS); + assert!(!config.host_locale.trim().is_empty()); assert_eq!(config.local_log_root, PathBuf::from("/tmp/radroots/logs")); } #[test] fn runtime_snapshot_uses_explicit_runtime_config_host_identity() { + let env = test_runtime_env(); let snapshot = AppRuntimeSnapshot::from_config( test_build_identity(), - &AppRuntimeConfig::from_json_str(&test_runtime_config_json()).expect("valid config"), + &AppRuntimeConfig::from_env_with(|name| env.get(name).cloned()) + .expect("valid env config"), ); assert_eq!( snapshot.run_id, "run-localhost-dev-20260417T000000Z-deadbeefcafefeed" ); - assert_eq!(snapshot.host.app_identifier, "org.radroots.app.macos"); - assert_eq!(snapshot.host.platform_name, "macos"); - assert_eq!(snapshot.host.operating_system, "macos-15.5"); + assert_eq!(snapshot.host.app_identifier, APP_ID); + assert_eq!(snapshot.host.app_name, APP_NAME); + assert_eq!(snapshot.host.platform_name, APP_HOST_PLATFORM); + assert_eq!(snapshot.host.operating_system, std::env::consts::OS); + assert_eq!(snapshot.host.runtime_origin, APP_RUNTIME_ORIGIN); assert_eq!(runtime_mode_label(&snapshot.runtime_mode), "localhost-dev"); } @@ -452,10 +457,15 @@ mod tests { #[test] fn runtime_snapshot_capture_matches_canonical_runtime_config_metadata() { let build = test_build_identity(); - let git_commit = build - .git_commit - .clone() - .expect("test build identity should include git commit"); + let env = BTreeMap::from([ + (APP_RUNTIME_MODE_ENV, "development".to_owned()), + (APP_RUN_ID_ENV, "run-development-123-pid456".to_owned()), + ( + APP_DEFAULT_NOSTR_RELAY_URL_ENV, + "ws://127.0.0.1:8080".to_owned(), + ), + (APP_LOCAL_LOG_ROOT_ENV, "/tmp/radroots/logs".to_owned()), + ]); let snapshot_from_capture = AppRuntimeSnapshot::from_capture( build.clone(), AppRuntimeMode::Development, @@ -467,82 +477,78 @@ mod tests { ); let snapshot_from_config = AppRuntimeSnapshot::from_config( build.clone(), - &AppRuntimeConfig::from_json_str(&format!( - r#"{{ - "schema_version":"{APP_RUNTIME_CONFIG_SCHEMA}", - "runtime_mode":"development", - "run_id":"run-development-123-pid456", - "default_nostr_relay_url":"ws://127.0.0.1:8080", - "bundle_identifier":"{APP_ID}", - "bundle_name":"{APP_NAME}", - "marketing_version":"{}", - "build_number":"{}", - "platform_name":"{APP_HOST_PLATFORM}", - "operating_system_version":"macos", - "host_locale":"en_US.UTF-8", - "runtime_origin":"{APP_RUNTIME_ORIGIN}", - "local_log_root":"/tmp/radroots/logs" - }}"#, - build.package_version, git_commit - )) - .expect("canonical config should parse"), + &AppRuntimeConfig::from_env_with(|name| env.get(name).cloned()) + .expect("canonical env config should parse"), ); - assert_eq!(snapshot_from_config, snapshot_from_capture); + assert_eq!(snapshot_from_config.title, snapshot_from_capture.title); + assert_eq!(snapshot_from_config.runtime_mode, snapshot_from_capture.runtime_mode); + assert_eq!(snapshot_from_config.run_id, snapshot_from_capture.run_id); + assert_eq!(snapshot_from_config.core, snapshot_from_capture.core); + assert_eq!( + snapshot_from_config.host.app_identifier, + snapshot_from_capture.host.app_identifier + ); + assert_eq!( + snapshot_from_config.host.app_name, + snapshot_from_capture.host.app_name + ); + assert_eq!( + snapshot_from_config.host.app_version, + snapshot_from_capture.host.app_version + ); + assert_eq!( + snapshot_from_config.host.platform_name, + snapshot_from_capture.host.platform_name + ); + assert_eq!( + snapshot_from_config.host.operating_system, + snapshot_from_capture.host.operating_system + ); + assert_eq!( + snapshot_from_config.host.runtime_origin, + snapshot_from_capture.host.runtime_origin + ); } #[test] fn runtime_config_rejects_empty_required_fields() { - let error = AppRuntimeConfig::from_json_str(&format!( - r#"{{ - "schema_version":"{APP_RUNTIME_CONFIG_SCHEMA}", - "runtime_mode":"localhost-dev", - "run_id":"", - "default_nostr_relay_url":"ws://127.0.0.1:8080", - "bundle_identifier":"org.radroots.app.macos", - "bundle_name":"Radroots", - "marketing_version":"0.1.0", - "build_number":"dev", - "platform_name":"macos", - "operating_system_version":"macos-15.5", - "host_locale":"en_US.UTF-8", - "runtime_origin":"gpui://localhost", - "local_log_root":"/tmp/radroots/logs" - }}"# - )) - .expect_err("missing run id should fail"); + let env = BTreeMap::from([ + (APP_RUNTIME_MODE_ENV, "localhost-dev".to_owned()), + (APP_RUN_ID_ENV, "".to_owned()), + ( + APP_DEFAULT_NOSTR_RELAY_URL_ENV, + "ws://127.0.0.1:8080".to_owned(), + ), + (APP_LOCAL_LOG_ROOT_ENV, "/tmp/radroots/logs".to_owned()), + ]); + let error = AppRuntimeConfig::from_env_with(|name| env.get(name).cloned()) + .expect_err("missing run id should fail"); assert!( - matches!(error, AppRuntimeConfigError::MissingField("run_id")), + matches!(error, AppRuntimeConfigError::MissingField(APP_RUN_ID_ENV)), "unexpected error: {error}" ); } #[test] fn runtime_config_rejects_missing_default_nostr_relay_url() { - let error = AppRuntimeConfig::from_json_str(&format!( - r#"{{ - "schema_version":"{APP_RUNTIME_CONFIG_SCHEMA}", - "runtime_mode":"localhost-dev", - "run_id":"run-localhost-dev-20260417T000000Z-deadbeefcafefeed", - "default_nostr_relay_url":"", - "bundle_identifier":"org.radroots.app.macos", - "bundle_name":"Radroots", - "marketing_version":"0.1.0", - "build_number":"dev", - "platform_name":"macos", - "operating_system_version":"macos-15.5", - "host_locale":"en_US.UTF-8", - "runtime_origin":"gpui://localhost", - "local_log_root":"/tmp/radroots/logs" - }}"# - )) - .expect_err("missing default relay url should fail"); + let env = BTreeMap::from([ + (APP_RUNTIME_MODE_ENV, "localhost-dev".to_owned()), + ( + APP_RUN_ID_ENV, + "run-localhost-dev-20260417T000000Z-deadbeefcafefeed".to_owned(), + ), + (APP_DEFAULT_NOSTR_RELAY_URL_ENV, "".to_owned()), + (APP_LOCAL_LOG_ROOT_ENV, "/tmp/radroots/logs".to_owned()), + ]); + let error = AppRuntimeConfig::from_env_with(|name| env.get(name).cloned()) + .expect_err("missing default relay url should fail"); assert!( matches!( error, - AppRuntimeConfigError::MissingField("default_nostr_relay_url") + AppRuntimeConfigError::MissingField(APP_DEFAULT_NOSTR_RELAY_URL_ENV) ), "unexpected error: {error}" ); diff --git a/platforms/macos/Scripts/run_host.sh b/platforms/macos/Scripts/run_host.sh @@ -31,7 +31,6 @@ forward_signal() { require_command grep require_command /usr/libexec/PlistBuddy -require_env RADROOTS_APP_RUNTIME_CONFIG_JSON require_env RADROOTS_APP_LOCAL_LOG_ROOT app_path="$("${script_dir}/build_host.sh")" diff --git a/platforms/macos/Scripts/test_host.sh b/platforms/macos/Scripts/test_host.sh @@ -158,25 +158,17 @@ trap cleanup EXIT runtime_mode="localhost-dev" run_id="$(radroots_app_run_id "${runtime_mode}")" -platform_name="$(radroots_app_platform_name)" -bundle_identifier="$(radroots_app_bundle_identifier)" +default_nostr_relay_url="${RADROOTS_APP_DEFAULT_NOSTR_RELAY_URL:-ws://127.0.0.1:8080}" local_log_root="${tmp_root}/logs" structured_log_file="${local_log_root}/apps/local/app/app-macos-native/${date_utc}.jsonl" latest_log_path="${local_log_root}/apps/local/app/app-macos-native/latest.jsonl" stdout_file="${local_log_root}/apps/local/app/app-macos-native/raw/stdout.${date_utc}.log" stderr_file="${local_log_root}/apps/local/app/app-macos-native/raw/stderr.${date_utc}.log" +RADROOTS_APP_RUNTIME_MODE="${runtime_mode}" \ RADROOTS_APP_RUN_ID="${run_id}" \ +RADROOTS_APP_DEFAULT_NOSTR_RELAY_URL="${default_nostr_relay_url}" \ RADROOTS_APP_LOCAL_LOG_ROOT="${local_log_root}" \ -RADROOTS_APP_RUNTIME_CONFIG_JSON="$( - radroots_app_build_runtime_config_json \ - "${repo_root}" \ - "${runtime_mode}" \ - "${run_id}" \ - "${bundle_identifier}" \ - "${platform_name}" \ - "${local_log_root}" -)" \ "${script_dir}/run_host.sh" & runner_pid="$!" @@ -192,20 +184,12 @@ degraded_structured_log_file="${degraded_log_root}/apps/local/app/app-macos-nati degraded_latest_log_path="${degraded_log_root}/apps/local/app/app-macos-native/latest.jsonl" degraded_stdout_file="${degraded_log_root}/apps/local/app/app-macos-native/raw/stdout.${date_utc}.log" degraded_stderr_file="${degraded_log_root}/apps/local/app/app-macos-native/raw/stderr.${date_utc}.log" -degraded_runtime_config_json="$( - radroots_app_build_runtime_config_json \ - "${repo_root}" \ - "${runtime_mode}" \ - "${degraded_run_id}" \ - "${bundle_identifier}" \ - "${platform_name}" \ - "${degraded_log_root}" -)" env -u HOME \ + RADROOTS_APP_RUNTIME_MODE="${runtime_mode}" \ RADROOTS_APP_RUN_ID="${degraded_run_id}" \ + RADROOTS_APP_DEFAULT_NOSTR_RELAY_URL="${default_nostr_relay_url}" \ RADROOTS_APP_LOCAL_LOG_ROOT="${degraded_log_root}" \ - RADROOTS_APP_RUNTIME_CONFIG_JSON="${degraded_runtime_config_json}" \ "${script_dir}/run_host.sh" & degraded_runner_pid="$!" diff --git a/scripts/run.sh b/scripts/run.sh @@ -11,23 +11,13 @@ cd "${repo_root}" runtime_mode="$(radroots_app_runtime_mode)" run_id="$(radroots_app_run_id "${runtime_mode}")" default_nostr_relay_url="$(radroots_app_default_nostr_relay_url)" -platform_name="$(radroots_app_platform_name)" -bundle_identifier="$(radroots_app_bundle_identifier)" local_log_root="$(radroots_app_local_log_root "${repo_root}")" +export RADROOTS_APP_RUNTIME_MODE="${runtime_mode}" export RADROOTS_APP_RUN_ID="${run_id}" +export RADROOTS_APP_DEFAULT_NOSTR_RELAY_URL="${default_nostr_relay_url}" export RADROOTS_APP_LOCAL_LOG_ROOT="${local_log_root}" export RUST_LOG="${RADROOTS_APP_RUST_LOG:-info}" -export RADROOTS_APP_RUNTIME_CONFIG_JSON="$( - radroots_app_build_runtime_config_json \ - "${repo_root}" \ - "${runtime_mode}" \ - "${run_id}" \ - "${default_nostr_relay_url}" \ - "${bundle_identifier}" \ - "${platform_name}" \ - "${local_log_root}" -)" if [[ "$(uname -s)" == "Darwin" ]]; then exec "${repo_root}/platforms/macos/Scripts/run_host.sh" "$@"