diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx
index b31cfb6cc7..007c414702 100644
--- a/packages/app/src/components/settings-general.tsx
+++ b/packages/app/src/components/settings-general.tsx
@@ -1,4 +1,4 @@
-import { Component, createMemo, type JSX } from "solid-js"
+import { Component, createEffect, createMemo, type JSX, Show } from "solid-js"
import { createStore } from "solid-js/store"
import { Button } from "@opencode-ai/ui/button"
import { Select } from "@opencode-ai/ui/select"
@@ -36,8 +36,12 @@ export const SettingsGeneral: Component = () => {
const platform = usePlatform()
const settings = useSettings()
+ type BackendMode = "native" | "wsl"
+
const [store, setStore] = createStore({
checking: false,
+ backend: "native" as BackendMode,
+ backendReady: false,
})
const check = () => {
@@ -111,6 +115,34 @@ export const SettingsGeneral: Component = () => {
})),
)
+ const backendOptions = createMemo(() => [
+ { value: "native" as const, label: language.t("settings.desktop.backend.option.native") },
+ { value: "wsl" as const, label: language.t("settings.desktop.backend.option.wsl") },
+ ])
+
+ const showBackend = () =>
+ platform.platform === "desktop" &&
+ platform.os === "windows" &&
+ !!platform.getBackendConfig &&
+ !!platform.setBackendConfig
+
+ createEffect(() => {
+ if (!showBackend()) return
+ if (store.backendReady) return
+ const get = platform.getBackendConfig
+ if (!get) {
+ setStore("backendReady", true)
+ return
+ }
+
+ void Promise.resolve(get())
+ .then((config) => {
+ const mode = config?.mode === "wsl" ? "wsl" : "native"
+ setStore({ backend: mode, backendReady: true })
+ })
+ .catch(() => setStore("backendReady", true))
+ })
+
const fontOptions = [
{ value: "ibm-plex-mono", label: "font.option.ibmPlexMono" },
{ value: "cascadia-code", label: "font.option.cascadiaCode" },
@@ -363,6 +395,38 @@ export const SettingsGeneral: Component = () => {
+
+
+
{language.t("settings.desktop.section.backend")}
+
+
+
+
+
+
+
+
{/* Updates Section */}
{language.t("settings.general.section.updates")}
diff --git a/packages/app/src/context/platform.tsx b/packages/app/src/context/platform.tsx
index 3fca502bad..16ed29735c 100644
--- a/packages/app/src/context/platform.tsx
+++ b/packages/app/src/context/platform.tsx
@@ -33,6 +33,9 @@ export type Platform = {
/** Open directory picker dialog (native on Tauri, server-backed on web) */
openDirectoryPickerDialog?(opts?: { title?: string; multiple?: boolean }): Promise
+ /** Whether native pickers should be used (desktop only) */
+ supportsNativePickers?(): boolean
+
/** Open native file picker dialog (Tauri only) */
openFilePickerDialog?(opts?: { title?: string; multiple?: boolean }): Promise
@@ -57,6 +60,12 @@ export type Platform = {
/** Set the default server URL to use on app startup (platform-specific) */
setDefaultServerUrl?(url: string | null): Promise | void
+ /** Get the configured backend mode (desktop only) */
+ getBackendConfig?(): Promise<{ mode: "native" | "wsl" } | null> | { mode: "native" | "wsl" } | null
+
+ /** Set the configured backend mode (desktop only) */
+ setBackendConfig?(config: { mode: "native" | "wsl" }): Promise | void
+
/** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */
parseMarkdown?(markdown: string): Promise
diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts
index 201d63660a..7ee84050af 100644
--- a/packages/app/src/i18n/ar.ts
+++ b/packages/app/src/i18n/ar.ts
@@ -508,6 +508,11 @@ export const dict = {
"settings.section.server": "الخادم",
"settings.tab.general": "عام",
"settings.tab.shortcuts": "اختصارات",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "المظهر",
"settings.general.section.notifications": "إشعارات النظام",
diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts
index b7f2d74857..177414c0a6 100644
--- a/packages/app/src/i18n/br.ts
+++ b/packages/app/src/i18n/br.ts
@@ -512,6 +512,11 @@ export const dict = {
"settings.section.server": "Servidor",
"settings.tab.general": "Geral",
"settings.tab.shortcuts": "Atalhos",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Aparência",
"settings.general.section.notifications": "Notificações do sistema",
diff --git a/packages/app/src/i18n/bs.ts b/packages/app/src/i18n/bs.ts
index 05eca1628e..da414b512e 100644
--- a/packages/app/src/i18n/bs.ts
+++ b/packages/app/src/i18n/bs.ts
@@ -539,6 +539,11 @@ export const dict = {
"settings.section.server": "Server",
"settings.tab.general": "Opšte",
"settings.tab.shortcuts": "Prečice",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Izgled",
"settings.general.section.notifications": "Sistemske obavijesti",
diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts
index 8ea4907c1b..5c3cdff59d 100644
--- a/packages/app/src/i18n/da.ts
+++ b/packages/app/src/i18n/da.ts
@@ -512,6 +512,11 @@ export const dict = {
"settings.section.server": "Server",
"settings.tab.general": "Generelt",
"settings.tab.shortcuts": "Genveje",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Udseende",
"settings.general.section.notifications": "Systemmeddelelser",
diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts
index a4884a1033..874665acfa 100644
--- a/packages/app/src/i18n/de.ts
+++ b/packages/app/src/i18n/de.ts
@@ -556,6 +556,11 @@ export const dict = {
"settings.section.server": "Server",
"settings.tab.general": "Allgemein",
"settings.tab.shortcuts": "Tastenkombinationen",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Erscheinungsbild",
"settings.general.section.notifications": "Systembenachrichtigungen",
diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts
index 8fba6861b0..f05bb88864 100644
--- a/packages/app/src/i18n/en.ts
+++ b/packages/app/src/i18n/en.ts
@@ -583,6 +583,11 @@ export const dict = {
"settings.section.server": "Server",
"settings.tab.general": "General",
"settings.tab.shortcuts": "Shortcuts",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Appearance",
"settings.general.section.notifications": "System notifications",
diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts
index 50d9060703..cc67f708e1 100644
--- a/packages/app/src/i18n/es.ts
+++ b/packages/app/src/i18n/es.ts
@@ -515,6 +515,11 @@ export const dict = {
"settings.section.server": "Servidor",
"settings.tab.general": "General",
"settings.tab.shortcuts": "Atajos",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Apariencia",
"settings.general.section.notifications": "Notificaciones del sistema",
diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts
index 7ad39f3406..ed97d13a6c 100644
--- a/packages/app/src/i18n/fr.ts
+++ b/packages/app/src/i18n/fr.ts
@@ -522,6 +522,11 @@ export const dict = {
"settings.section.server": "Serveur",
"settings.tab.general": "Général",
"settings.tab.shortcuts": "Raccourcis",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Apparence",
"settings.general.section.notifications": "Notifications système",
diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts
index a39bfbaf33..6e83c9f03a 100644
--- a/packages/app/src/i18n/ja.ts
+++ b/packages/app/src/i18n/ja.ts
@@ -507,6 +507,11 @@ export const dict = {
"settings.section.server": "サーバー",
"settings.tab.general": "一般",
"settings.tab.shortcuts": "ショートカット",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "外観",
"settings.general.section.notifications": "システム通知",
diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts
index b5927b2107..73c5a31450 100644
--- a/packages/app/src/i18n/ko.ts
+++ b/packages/app/src/i18n/ko.ts
@@ -513,6 +513,11 @@ export const dict = {
"settings.section.server": "서버",
"settings.tab.general": "일반",
"settings.tab.shortcuts": "단축키",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "모양",
"settings.general.section.notifications": "시스템 알림",
diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts
index 7d8cdd27f3..c1e3d27393 100644
--- a/packages/app/src/i18n/no.ts
+++ b/packages/app/src/i18n/no.ts
@@ -515,6 +515,11 @@ export const dict = {
"settings.section.server": "Server",
"settings.tab.general": "Generelt",
"settings.tab.shortcuts": "Snarveier",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Utseende",
"settings.general.section.notifications": "Systemvarsler",
diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts
index 76a47ea26f..56ac398125 100644
--- a/packages/app/src/i18n/pl.ts
+++ b/packages/app/src/i18n/pl.ts
@@ -514,6 +514,11 @@ export const dict = {
"settings.section.server": "Serwer",
"settings.tab.general": "Ogólne",
"settings.tab.shortcuts": "Skróty",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Wygląd",
"settings.general.section.notifications": "Powiadomienia systemowe",
diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts
index e83ce37618..11fac2644a 100644
--- a/packages/app/src/i18n/ru.ts
+++ b/packages/app/src/i18n/ru.ts
@@ -517,6 +517,11 @@ export const dict = {
"settings.section.server": "Сервер",
"settings.tab.general": "Основные",
"settings.tab.shortcuts": "Горячие клавиши",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "Внешний вид",
"settings.general.section.notifications": "Системные уведомления",
diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts
index 2be19d15b1..3ad38cba2a 100644
--- a/packages/app/src/i18n/th.ts
+++ b/packages/app/src/i18n/th.ts
@@ -516,6 +516,11 @@ export const dict = {
"settings.section.server": "เซิร์ฟเวอร์",
"settings.tab.general": "ทั่วไป",
"settings.tab.shortcuts": "ทางลัด",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "รูปลักษณ์",
"settings.general.section.notifications": "การแจ้งเตือนระบบ",
diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts
index a48f9e5494..10c7642f35 100644
--- a/packages/app/src/i18n/zh.ts
+++ b/packages/app/src/i18n/zh.ts
@@ -548,6 +548,11 @@ export const dict = {
"settings.section.server": "服务器",
"settings.tab.general": "通用",
"settings.tab.shortcuts": "快捷键",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "外观",
"settings.general.section.notifications": "系统通知",
diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts
index 60363fc99e..659b495ac1 100644
--- a/packages/app/src/i18n/zht.ts
+++ b/packages/app/src/i18n/zht.ts
@@ -545,6 +545,11 @@ export const dict = {
"settings.section.server": "伺服器",
"settings.tab.general": "一般",
"settings.tab.shortcuts": "快速鍵",
+ "settings.desktop.section.backend": "Backend",
+ "settings.desktop.backend.title": "Server backend",
+ "settings.desktop.backend.description": "Choose where the OpenCode server runs.",
+ "settings.desktop.backend.option.native": "Native (Windows)",
+ "settings.desktop.backend.option.wsl": "WSL (Linux)",
"settings.general.section.appearance": "外觀",
"settings.general.section.notifications": "系統通知",
diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx
index 10f7dac530..c1d0d6ef11 100644
--- a/packages/app/src/pages/home.tsx
+++ b/packages/app/src/pages/home.tsx
@@ -46,7 +46,8 @@ export default function Home() {
}
}
- if (platform.openDirectoryPickerDialog && server.isLocal()) {
+ const allowNative = platform.supportsNativePickers?.() !== false
+ if (platform.openDirectoryPickerDialog && server.isLocal() && allowNative) {
const result = await platform.openDirectoryPickerDialog?.({
title: language.t("command.project.open"),
multiple: true,
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx
index 59adef4694..1c02d49539 100644
--- a/packages/app/src/pages/layout.tsx
+++ b/packages/app/src/pages/layout.tsx
@@ -1182,7 +1182,8 @@ export default function Layout(props: ParentProps) {
}
}
- if (platform.openDirectoryPickerDialog && server.isLocal()) {
+ const allowNative = platform.supportsNativePickers?.() !== false
+ if (platform.openDirectoryPickerDialog && server.isLocal() && allowNative) {
const result = await platform.openDirectoryPickerDialog?.({
title: language.t("command.project.open"),
multiple: true,
diff --git a/packages/desktop/src-tauri/src/cli.rs b/packages/desktop/src-tauri/src/cli.rs
index 98c38677b4..85adcc6cf6 100644
--- a/packages/desktop/src-tauri/src/cli.rs
+++ b/packages/desktop/src-tauri/src/cli.rs
@@ -3,8 +3,9 @@ use tauri_plugin_shell::{
ShellExt,
process::{Command, CommandChild, CommandEvent},
};
+use tauri_plugin_store::StoreExt;
-use crate::{LogState, constants::MAX_LOG_ENTRIES};
+use crate::{LogState, constants::{BACKEND_MODE_KEY, MAX_LOG_ENTRIES, SETTINGS_STORE}};
const CLI_INSTALL_DIR: &str = ".opencode/bin";
const CLI_BINARY_NAME: &str = "opencode";
@@ -21,7 +22,7 @@ pub struct Config {
}
pub async fn get_config(app: &AppHandle) -> Option {
- create_command(app, "debug config")
+ create_command(app, "debug config", &[])
.output()
.await
.inspect_err(|e| eprintln!("Failed to read OC config: {e}"))
@@ -150,22 +151,95 @@ fn get_user_shell() -> String {
std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string())
}
-pub fn create_command(app: &tauri::AppHandle, args: &str) -> Command {
+fn is_wsl_backend(app: &tauri::AppHandle) -> bool {
+ let Ok(store) = app.store(SETTINGS_STORE) else {
+ return false;
+ };
+
+ store
+ .get(BACKEND_MODE_KEY)
+ .and_then(|value| value.as_str())
+ .is_some_and(|value| value == "wsl")
+}
+
+fn shell_escape(input: &str) -> String {
+ if input.is_empty() {
+ return "''".to_string();
+ }
+
+ let mut escaped = String::from("'");
+ escaped.push_str(&input.replace("'", "'\"'\"'"));
+ escaped.push('\'');
+ escaped
+}
+
+pub fn create_command(app: &tauri::AppHandle, args: &str, extra_env: &[(&str, String)]) -> Command {
let state_dir = app
.path()
.resolve("", BaseDirectory::AppLocalData)
.expect("Failed to resolve app local data dir");
+ let mut envs = vec![
+ ("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY".to_string(), "true".to_string()),
+ ("OPENCODE_EXPERIMENTAL_FILEWATCHER".to_string(), "true".to_string()),
+ ("OPENCODE_CLIENT".to_string(), "desktop".to_string()),
+ ("XDG_STATE_HOME".to_string(), state_dir.to_string_lossy().to_string()),
+ ];
+ envs.extend(extra_env.iter().map(|(key, value)| (key.to_string(), value.clone())));
+
#[cfg(target_os = "windows")]
- return app
+ if is_wsl_backend(app) {
+ let version = app.package_info().version.to_string();
+ let mut script = vec![
+ "set -e".to_string(),
+ "BIN=\"$HOME/.opencode/bin/opencode\"".to_string(),
+ "if [ ! -x \"$BIN\" ]; then".to_string(),
+ format!(
+ " curl -fsSL https://opencode.ai/install | bash -s -- --version {} --no-modify-path",
+ shell_escape(&version)
+ ),
+ "fi".to_string(),
+ ];
+
+ let mut env_prefix = vec![
+ "OPENCODE_EXPERIMENTAL_ICON_DISCOVERY=true".to_string(),
+ "OPENCODE_EXPERIMENTAL_FILEWATCHER=true".to_string(),
+ "OPENCODE_CLIENT=desktop".to_string(),
+ "XDG_STATE_HOME=\"$HOME/.local/state\"".to_string(),
+ ];
+ env_prefix.extend(
+ envs
+ .iter()
+ .filter(|(key, _)| key != "OPENCODE_EXPERIMENTAL_ICON_DISCOVERY")
+ .filter(|(key, _)| key != "OPENCODE_EXPERIMENTAL_FILEWATCHER")
+ .filter(|(key, _)| key != "OPENCODE_CLIENT")
+ .filter(|(key, _)| key != "XDG_STATE_HOME")
+ .map(|(key, value)| format!("{}={}", key, shell_escape(value))),
+ );
+
+ script.push(format!(
+ "{} exec \"$BIN\" {}",
+ env_prefix.join(" "),
+ args
+ ));
+
+ return app
+ .shell()
+ .command("wsl")
+ .args(["-e", "bash", "-lc", &script.join("\n")]);
+ }
+
+ let mut cmd = app
.shell()
.sidecar("opencode-cli")
.unwrap()
- .args(args.split_whitespace())
- .env("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", "true")
- .env("OPENCODE_EXPERIMENTAL_FILEWATCHER", "true")
- .env("OPENCODE_CLIENT", "desktop")
- .env("XDG_STATE_HOME", &state_dir);
+ .args(args.split_whitespace());
+
+ for (key, value) in envs {
+ cmd = cmd.env(key, value);
+ }
+
+ return cmd;
#[cfg(not(target_os = "windows"))]
return {
@@ -178,13 +252,15 @@ pub fn create_command(app: &tauri::AppHandle, args: &str) -> Command {
format!("\"{}\" {}", sidecar.display(), args)
};
- app.shell()
+ let mut cmd = app.shell()
.command(&shell)
- .env("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", "true")
- .env("OPENCODE_EXPERIMENTAL_FILEWATCHER", "true")
- .env("OPENCODE_CLIENT", "desktop")
- .env("XDG_STATE_HOME", &state_dir)
- .args(["-il", "-c", &cmd])
+ .args(["-il", "-c", &cmd]);
+
+ for (key, value) in envs {
+ cmd = cmd.env(key, value);
+ }
+
+ cmd
};
}
@@ -194,12 +270,16 @@ pub fn serve(app: &AppHandle, hostname: &str, port: u32, password: &str) -> Comm
println!("spawning sidecar on port {port}");
+ let envs = [
+ ("OPENCODE_SERVER_USERNAME", "opencode".to_string()),
+ ("OPENCODE_SERVER_PASSWORD", password.to_string()),
+ ];
+
let (mut rx, child) = create_command(
app,
format!("serve --hostname {hostname} --port {port}").as_str(),
+ &envs,
)
- .env("OPENCODE_SERVER_USERNAME", "opencode")
- .env("OPENCODE_SERVER_PASSWORD", password)
.spawn()
.expect("Failed to spawn opencode");
diff --git a/packages/desktop/src-tauri/src/constants.rs b/packages/desktop/src-tauri/src/constants.rs
index ac3e1d02ad..8340cf5326 100644
--- a/packages/desktop/src-tauri/src/constants.rs
+++ b/packages/desktop/src-tauri/src/constants.rs
@@ -2,6 +2,7 @@ use tauri_plugin_window_state::StateFlags;
pub const SETTINGS_STORE: &str = "opencode.settings.dat";
pub const DEFAULT_SERVER_URL_KEY: &str = "defaultServerUrl";
+pub const BACKEND_MODE_KEY: &str = "serverBackendMode";
pub const UPDATER_ENABLED: bool = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some();
pub const MAX_LOG_ENTRIES: usize = 200;
diff --git a/packages/desktop/src-tauri/src/lib.rs b/packages/desktop/src-tauri/src/lib.rs
index 14105e5dd3..382cd18a54 100644
--- a/packages/desktop/src-tauri/src/lib.rs
+++ b/packages/desktop/src-tauri/src/lib.rs
@@ -209,6 +209,8 @@ pub fn run() {
await_initialization,
server::get_default_server_url,
server::set_default_server_url,
+ server::get_backend_config,
+ server::set_backend_config,
markdown::parse_markdown_command,
check_app_exists
])
diff --git a/packages/desktop/src-tauri/src/server.rs b/packages/desktop/src-tauri/src/server.rs
index 2a78411a43..7cfb1bdccc 100644
--- a/packages/desktop/src-tauri/src/server.rs
+++ b/packages/desktop/src-tauri/src/server.rs
@@ -8,9 +8,38 @@ use tokio::task::JoinHandle;
use crate::{
cli,
- constants::{DEFAULT_SERVER_URL_KEY, SETTINGS_STORE},
+ constants::{BACKEND_MODE_KEY, DEFAULT_SERVER_URL_KEY, SETTINGS_STORE},
};
+#[derive(Clone, Copy, serde::Serialize, serde::Deserialize, specta::Type, Debug)]
+#[serde(rename_all = "snake_case")]
+pub enum BackendMode {
+ Native,
+ Wsl,
+}
+
+impl BackendMode {
+ fn as_str(&self) -> &'static str {
+ match self {
+ BackendMode::Native => "native",
+ BackendMode::Wsl => "wsl",
+ }
+ }
+}
+
+#[derive(Clone, serde::Serialize, serde::Deserialize, specta::Type, Debug)]
+pub struct BackendConfig {
+ pub mode: BackendMode,
+}
+
+impl Default for BackendConfig {
+ fn default() -> Self {
+ Self {
+ mode: BackendMode::Native,
+ }
+ }
+}
+
#[tauri::command]
#[specta::specta]
pub fn get_default_server_url(app: AppHandle) -> Result