Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions INSTALLATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ configuration reference.
## Desktop installer

From a source checkout, run `cargo desktop --help` for the commands and
`cargo desktop install --dry-run` to preview installation. This checkout has
the installer helper but does not yet build the desktop app executable, so
full installation cannot complete. Uninstall keeps settings, history, and
recovery copies.
`cargo desktop install --dry-run` to preview installation. Run
`cargo desktop install` to build and install the app and server.

The app opens setup on its first launch before creating app and server config files.
Existing app settings or a default server config skip setup, including after
reinstall. Settings lets you change the selected files or remove app preferences.
On Linux, open the installed app with `~/.switchyard/bin/switchyard-desktop --tui`.
See [Desktop setup](crates/switchyard-desktop/SETUP.md) for these steps.
Uninstall keeps settings, history, and recovery copies.

The installer requires the repository's Rust toolchain. macOS uses LaunchAgents;
Linux requires a systemd user session. Windows requires MSVC build tools,
Expand Down
10 changes: 7 additions & 3 deletions crates/switchyard-desktop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ shlex = "2"
strum = { version = "0.28", features = ["derive"] }

[target.'cfg(target_os = "macos")'.dependencies]
objc2-app-kit = { version = "0.3.2", default-features = false, features = ["NSWorkspace"] }
objc2-foundation = { version = "0.3.2", default-features = false, features = ["NSString", "NSURL"] }
objc2-quartz-core = { version = "0.3.2", default-features = false, features = ["CALayer"] }
dispatch2 = "0.3"
objc2 = "0.6"
objc2-app-kit = { version = "0.3.2", default-features = false, features = ["NSWorkspace", "NSAccessibility", "NSApplication", "NSPanel", "NSColor", "NSWindow", "NSView", "NSScreen", "NSEvent", "NSStatusItem", "NSStatusBarButton", "NSButton", "NSControl", "NSResponder", "objc2-quartz-core"] }
objc2-foundation = { version = "0.3.2", default-features = false, features = ["NSString", "NSURL", "NSProcessInfo"] }
security-framework = "3"

[target.'cfg(unix)'.dependencies]
Expand All @@ -50,7 +53,8 @@ windows = { version = "0.62.2", features = ["Management_Deployment", "Applicatio
windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_System_Threading", "Win32_System_Diagnostics_ToolHelp", "Win32_Security_Credentials", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging", "Win32_System_Console", "Win32_Storage_FileSystem"] }

[target.'cfg(any(target_os = "macos", windows))'.dependencies]
tauri = { version = "2", features = ["custom-protocol"] }
rfd = { version = "0.17", default-features = false }
tauri = { version = "2", features = ["tray-icon", "custom-protocol", "macos-private-api"] }

[target.'cfg(any(target_os = "macos", windows))'.build-dependencies]
tauri-build = "2"
Expand Down
38 changes: 38 additions & 0 deletions crates/switchyard-desktop/SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Desktop setup

Run `cargo desktop install` from the source checkout to build and install the
desktop app and server. On Linux, open the installed app with
`~/.switchyard/bin/switchyard-desktop --tui`. If you set `SY_HOME`, use its `bin`
directory instead.

Setup opens when neither the app settings file nor its default server config
exists. Existing files skip setup, including after reinstall. Invalid existing
files show an error so you can repair them in Settings. Routing logs and price
files alone do not skip setup.

Choose an existing server config or create one from bundled defaults. Select
the server address, routing log, optional price file, baseline model, and refresh
interval, then save. Use absolute file paths and an `http://` server address.
Creating a server config never replaces an existing file.
The server waits for saved app settings before starting. Save any required API
keys in **Settings → Server keys**. Use **Check config** in Settings, then restart
the server. The managed server listens on `127.0.0.1`; changing the address does
not expose it to the network.

**Settings → Configuration** uses the same form. Saving preserves comments in
the app settings file. Restart the server after changing its selected files or
port. The installed server reads those selections when it starts.

**Run setup again** reopens the form. **Remove app preferences** shows the exact
settings file before removal and checks that its contents have not changed
since review. Removal keeps a recovery copy and preserves server configs, saved
keys, history, accounts, and coding-tool settings. Use **Connect tools** to
restore a coding tool's settings.

In the terminal app, open Settings with `7`. Press `f` to edit configuration or
`d` to review removal of app preferences.

A fresh installation leaves the Codex profile unchanged. After setup saves a
server config, reinstalling creates or updates the Codex profile, which defaults
to `~/.codex/sy.config.toml`. The installer keeps a recovery copy of a changed
profile.
9 changes: 9 additions & 0 deletions crates/switchyard-desktop/capabilities/main-chrome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"identifier": "main-chrome",
"description": "The desktop titlebar supports dragging and double-click maximization.",
"windows": ["main"],
"permissions": [
"core:window:allow-start-dragging",
"core:window:allow-internal-toggle-maximize"
]
}
12 changes: 10 additions & 2 deletions crates/switchyard-desktop/src/bin/switchyard-desktop-install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,16 @@ fn key_remove(name: &str) -> Result<(), String> {
fn serve(file: &Path) -> Result<(), String> {
use std::os::unix::process::CommandExt;
let s = Settings::load(file)?;
let config = s.sy_home.join("composite.toml");
let mut server = s.server_command();
// The installed helper waits until setup atomically saves the app settings.
while !s
.desktop_settings()
.try_exists()
.map_err(|error| error.to_string())?
{
std::thread::sleep(std::time::Duration::from_millis(250));
}
let config = switchyard_desktop::config::Config::load(&s.desktop_settings())?.config_file;
let mut server = s.server_command()?;
#[cfg(target_os = "linux")]
credentials::wait_for_keyring()?;
credentials::configure(&mut server, &config)?;
Expand Down
Loading
Loading