Add flow-launcher:// deep link protocol, .flowplugin file association, and --query command line argument
What
Adds a flow-launcher:// deep link protocol and .flowplugin file association, plus a --query "text" (also -query) command-line flag, so scripts, browsers, and other apps can open/focus Flow Launcher to run a query, open settings, or install a plugin.
--query "text"/-q "text": opens/focuses Flow Launcher with the query pre-filled and searched.flow-launcher://query?q=...,flow-launcher://settings,flow-launcher://plugin/install?path=|id=|url=: routed through a general verb-dispatch framework. Plugin installs always show the existing Yes/No confirmation dialog — never silent, whether triggered by a local.flowplugindouble-click, a store id, or an https download URL..flowpluginfile association and theflow-launcher://URI scheme are self-healing HKCU registrations applied at every startup (no admin rights required), with a new Settings toggle, "Allow websites to open Flow Launcher", to opt out.- Cold start (no instance running): the deep link is dispatched right after plugin initialization, then the main window is shown.
- Warm start (instance already running): the second process normalizes its args to a
flow-launcher://URI and sends it to the first instance over the existing single-instance named pipe, then exits; the first instance dispatches it. - No args: behavior is unchanged — a second launch just shows/focuses the window.
How
Flow.Launcher/Helper/DeepLink.cs: normalizes command-line args (--query,.flowpluginpaths, rawflow-launcher://URIs) into a single URI string, parses a URI into a verb + query parameters, and dispatches to handlers forquery,settings, andplugin/install.Flow.Launcher/Helper/DeepLinkRegistration.cs: idempotent HKCU registration for the.flowpluginProgID and theflow-launcher://scheme, called on every startup so stale executable paths self-heal after updates.Flow.Launcher.Core/Plugin/PluginInstaller.cs: addsInstallPluginFromWebAndCheckRestartAsync(url), reusing the existing unknown-source warning and the always-promptingInstallPluginAndCheckRestartAsync.App.xaml.cs:Main(string[] args)normalizes args viaDeepLink.FromCommandLineArgs; the pending deep link is dispatched afterPluginManager.InitializePluginsAsync, before the home-page refresh check;OnSecondAppStarted(string payload)dispatches the warm-path payload (or just shows the window when empty).SingleInstance.cs: the named pipe now carries an optional payload — the normalized deep link URI (or legacy plain query text). The client writes it as a newline-terminated UTF-8 line and blocks (up to 3 s) since the process exits immediately after; the server reads one line guarded by a 2 s timeout and try/catch, so a client that connects but never writes degrades to a plain activation and can never hang the server loop.Settings.EnableDeepLinkProtocol(defaulttrue) gates the URI scheme registration; toggling it in Settings registers/unregisters the scheme immediately viaDeepLinkRegistration.
Test matrix (manual, Windows)
- No args, cold start — unchanged behavior (home page etc.)
--query "foo"/-query "foo", cold and warm — window opens/focuses with "foo" searched- Warm start, no args — window just shows/focuses (regression check)
--query ""— treated as no query- Double-click a
.flowplugin(Flow running and not running) — confirmation dialog, install only on Yes flow-launcher://query?q=foo,flow-launcher://settings,flow-launcher://plugin/install?id=.../?path=.../?url=https://...zipfrom a browser — routed correctly, every install prompts?url=http://...(non-https) — rejected with an https-only messageflow-launcher://nope— error notification, no crash- Settings toggle off —
HKCU\Software\Classes\flow-launcherremoved, browser links no longer open Flow;.flowplugindouble-click and--querystill work. Toggle on — restored - Corrupt the registered command path manually, relaunch — self-healed
- Robustness: a client that connects to the pipe without writing/closing — server loop recovers after the 2 s read timeout and keeps accepting connections
Summary by cubic
Summary of changes
Adds a flow-launcher:// deep link and .flowplugin association plus a --query/-q flag so scripts and websites can open Flow Launcher, run searches, open settings, or install plugins. When the URI scheme is disabled or no args are provided, launch behavior is unchanged; second-instance invocations forward a normalized deep link to the running app over IPC.
- Changed
- Single-instance IPC now carries an optional UTF-8 deep-link payload; server cancels the read after 2s, client connect waits up to 3s, and the outer delivery wait is 5s so payloads are not dropped; dispatcher activation exceptions are observed.
- Pipe read timeouts become plain activations; genuine read failures are logged.
App.Main(string[] args)normalizes args to a deep link; dispatch happens after plugins initialize. Links received during startup are queued so none are lost.OnSecondAppStarted(string payload)routes a payload; empty payload focuses the window.- CLI supports
--queryand-q; empty queries are ignored. - Deep link protocol toggle updates registry immediately and reverts the toggle if registration fails.
- Logging keeps full deep-link payloads at Debug; Warn logs only the actionable fact.
- Added
- Deep link parser/dispatcher with verbs: query, settings, and plugin/install (by
.flowpluginpath, store id, or https URL). HelperHasExactlyOneInstallIdentifiervalidates install links. - HKCU registration for
.flowpluginand theflow-launcher://scheme, gated by a new General Settings toggle “Allow websites to open Flow Launcher”; registration is ensured at startup. PluginInstaller.InstallPluginFromWebAndCheckRestartAsyncwith unknown-source confirmation;DerivePluginNameFromUrlsanitizes filenames and falls back to a safe default;TryPopulateIdFromZiprecovers the real plugin ID for URL installs to keep modified-plugin tracking correct.- UI strings and a General Settings toggle. Unit tests:
DeepLinkTest(arg normalization, scheme-disabled behavior, URI parsing) andPluginInstallerTest(URL filename derivation edge cases).
- Deep link parser/dispatcher with verbs: query, settings, and plugin/install (by
- Removed
- Old
OnSecondAppStarted()overload; no user-visible features removed.
- Old
- Memory
- Negligible: short-lived strings and small stream buffers; no persistent allocations.
- Security
- URI scheme is opt-in and per-user (HKCU). Named pipe remains per-user. Deep links are parsed/validated; plugin installs require https URLs or an existing local file; store-id installs validate against the manifest. Payload logging is minimized; IPC timeouts prevent hangs.
- Tests
- Added
DeepLinkTestandPluginInstallerTest; manual verification of cold/warm starts, empty queries, startup-queued links, and all plugin install paths.
- Added
Release Note
Open Flow Launcher from your browser or scripts to search, open settings, or install plugins using special links or the new --query option.