Linux launcher drops application arguments before spawning the main process
Summary
I found a reproducible Linux launcher issue where application arguments reach the Electrobun launcher but are not forwarded to the application process.
This affects ordinary application arguments in general, not only file paths or MIME-associated files.
I initially found this while integrating a real Electrobun application on Linux, but I reproduced the behavior independently across several argument types so the result does not depend on that application.
I would appreciate confirmation of whether dropping non-launcher arguments is intentional. If it is not intentional, this appears to be a small but important launcher issue because applications cannot receive normal command-line arguments when started through the packaged Linux launcher.
Environment
- OS: Ubuntu 24.04.5 LTS
- Architecture: x86_64
- Desktop: GNOME
- Display server: Wayland
- Electrobun: 2.0.1 linux-x64
- Electrobun core SHA256: 29da550b3cb30c0b868b6155aa35b791548baa044f97118951e1c7a413c95307
- Electrobun launcher SHA256: eac32746ea0fc765f8fa5e6d9685cd76c8e172ff312671c862fd26cb3db2b3fa
- Electrobun launcher size: 243896 bytes
- Cottontail: 0.5.0, revision e5660061
- Bun toolchain: 1.4.0
- Test date: 2026-09-11
The launcher binary used by the packaged application was byte-identical to the Electrobun 2.0.1 release launcher from the Hutch release cache.
The tested launcher therefore was not a modified downstream launcher.
Minimal reproduction
Run a packaged Electrobun Linux application launcher with an ordinary argument:
./MyApp/bin/launcher /tmp/probe/test.txtThe launcher process receives the argument.
For example, /proc/<launcher-pid>/cmdline contains:
.../app/bin/launcher
/tmp/probe/test.txtThe child process does not receive it.
The child process is started as:
.../app/bin/bun .../Resources/main.jsrather than:
.../app/bin/bun .../Resources/main.js /tmp/probe/test.txtIn the tested application, the resulting process.argv was equivalent to:
[bun, main.js]with no application argument present.
The same result can be observed directly from /proc/<child-pid>/cmdline.
Argument matrix
I tested the launcher with different kinds of arguments to determine whether this was related to MIME types, file extensions, paths, or a particular number of arguments.
| Case | User arguments | Launcher receives | Main process receives |
|---|---|---|---|
| test.txt | 1 | yes | 0 |
| test.md | 1 | yes | 0 |
| test.bin | 1 | yes | 0 |
| README, no extension | 1 | yes | 0 |
| directory | 1 | yes | 0 |
| directory containing files | 1 | yes | 0 |
| three files | 3 | yes | 0 |
| directory plus file | 2 | yes | 0 |
| path containing spaces | 1 | yes | 0 |
| hello-world, not a path | 1 | yes | 0 |
The three-file test used:
test.txt test.md test.jsonAll three arguments reached the launcher, but none reached the child process.
The directory tests also reached the launcher and were dropped before the child process was created.
The hello-world test is important because it is not a file path, directory, MIME type, or file association. It is just an ordinary argument. It was also dropped.
This does not appear to be MIME related
The same behavior was observed for:
- text files
- Markdown files
- binary files
- files without extensions
- directories
- arbitrary string arguments
No MIME database was changed during the tests.
This suggests the problem occurs below MIME association and below desktop file association handling.
The desktop entry path is not where the argument is lost
The original downstream use case involves a Linux desktop entry using:
Exec=myapp %FThe %F field represents one or more local paths as separate arguments.
The downstream wrapper used for the test is:
exec /opt/myapp/bin/launcher "$@"The wrapper was verified to preserve the arguments exactly.
The launcher then receives the expected arguments.
The loss happens after the launcher receives them and before the application main process starts.
So the observed chain is:
desktop or shell
|
v
wrapper
|
| arguments preserved
v
Electrobun launcher
|
| arguments received
|
| arguments dropped
v
main processLauncher source analysis
In the current Electrobun source, package/src/launcher/main.zig constructs the child argument vector as:
argv = &[_][]const u8{ runtime_path, main_script };This creates a child argv containing only the runtime and main script.
The launcher does receive the original arguments and stores them as launcher_args.
The launcher also has its own recognized options. Inspection of the 2.0.1 launcher binary found:
--automation
--bootstrap-install
--delete-data
--quiet
--uninstallThis suggests that there is already a conceptual distinction between arguments owned by the launcher and arguments intended for the application.
The issue is that the remaining arguments are not forwarded to the child process.
For example, unrecognized arguments such as:
--help
--versionalso start the application normally and do not appear in the child argv.
I am not assuming this behavior is accidental. I would like to confirm whether dropping all non-launcher arguments is intentional.
Expected behavior
For a normal application argument such as:
./MyApp/bin/launcher /tmp/probe/test.txtI would expect the application process to receive the argument in the same order and multiplicity, for example:
bun Resources/main.js /tmp/probe/test.txtLikewise:
./MyApp/bin/launcher file1.txt file2.txtwould result in the application receiving:
file1.txt
file2.txtas two separate arguments.
Arguments containing spaces should remain a single argument.
I am not trying to prescribe the exact implementation. In particular, I would be happy to follow whatever argument forwarding contract Electrobun considers correct.
Why this matters on Linux
Normal Linux desktop integration commonly needs an application to receive paths when launched from a desktop entry, file manager, xdg-open, or another application.
A desktop entry can provide paths through %F, but those paths are only useful if the packaged application launcher preserves them.
This also affects non-file use cases because the test with the plain string:
hello-worldis dropped as well.
So the observed behavior appears broader than file opening:
Linux launcher does not forward ordinary application argumentsrather than:
Markdown files cannot be openedRelation to file associations
The current Electrobun documentation states that file associations are currently packaged on macOS and that Windows and Linux URL schemes and file associations are not yet implemented.
I am not relying on the file association API for this report.
The issue here is lower level: when an application is invoked with an ordinary command-line argument on Linux, the launcher receives that argument but does not pass it to the application process.
The expected Linux mechanism could therefore be independent of Electrobun's macOS open-url behavior.
Current upstream status
I also checked the current upstream source rather than assuming that 2.0.1 was simply outdated.
The 2.0.2 beta line is active, and the relevant launcher source in current main still constructs the child argv with only:
runtime_path
main_scriptI could not find an existing issue or pull request specifically covering Linux launcher application argument forwarding.
I searched for issues and pull requests involving:
- argv
- arguments
- launcher
- launcher arguments
- file association
- open-url
- deep link
- desktop
- %F
No matching issue was found.
Downstream use case
This was first discovered while packaging Fulvid, an Electrobun application for Linux.
Fulvid already has an application-side argument adapter that:
- reads application arguments;
- resolves paths;
- distinguishes files and directories;
- passes them to a single host-side external-open handler.
That code is currently unreachable for packaged Linux launches because the arguments disappear in the Electrobun launcher before the application main process starts.
We deliberately did not work around this with an environment variable, socket, daemon, localhost listener, or another side channel. Such a workaround would introduce a second authority for document opening and would not solve the underlying launcher behavior for other Electrobun applications.
The Fulvid use case is therefore provided only as a real downstream example, not as a requirement for the proposed solution.
Possible direction
I do not want to prescribe an implementation without knowing the intended Electrobun argument contract.
If the intended behavior is to forward application arguments, one possible direction would be:
- consume arguments owned by the launcher;
- keep launcher-specific behavior unchanged;
- forward the remaining application arguments to the main process;
- preserve order, multiplicity, and argument boundaries.
For example:
launcher --launcher-option file1.txt file2.txtcould result in the application receiving:
file1.txt
file2.txtif that matches the intended Electrobun contract.
If instead Electrobun intentionally keeps the launcher argument namespace closed and does not forward arbitrary arguments, I would appreciate guidance on the supported Linux mechanism for applications that need to receive arguments from the desktop or another process.
Questions
Could you please confirm:
- Is dropping ordinary non-launcher arguments intentional?
- If it is intentional, what is the supported mechanism for a Linux application to receive arguments such as file paths?
- If forwarding is intended, should launcher-owned flags be consumed while all remaining arguments are passed to the main process?
- Is there an existing argument forwarding mechanism that I have missed?
- Should Linux use argv for this purpose while macOS continues to use
open-url, or is a common cross-platform mechanism planned?
Thanks for taking the time to look at this. I wanted to provide a minimal, reproducible case with several argument types rather than report this only as a file association problem from one downstream application.
Source: blackboardsh/electrobun