{"id":15063139,"url":"https://github.com/spikehd/crowser","last_synced_at":"2026-03-03T00:39:19.722Z","repository":{"id":257792409,"uuid":"840092645","full_name":"SpikeHD/Crowser","owner":"SpikeHD","description":"Create \"desktop apps\" using user-provided browsers","archived":false,"fork":false,"pushed_at":"2024-11-27T18:18:50.000Z","size":167,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T09:21:20.557Z","etag":null,"topics":["browsers","chrome","firefox","rust","web","webapp"],"latest_commit_sha":null,"homepage":"https://docs.rs/crowser/latest","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SpikeHD.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-09T00:43:06.000Z","updated_at":"2025-03-11T06:22:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"2d11ec85-d68f-41ed-be77-885451502ed4","html_url":"https://github.com/SpikeHD/Crowser","commit_stats":null,"previous_names":["spikehd/crowser"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpikeHD%2FCrowser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpikeHD%2FCrowser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpikeHD%2FCrowser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SpikeHD%2FCrowser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SpikeHD","download_url":"https://codeload.github.com/SpikeHD/Crowser/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248199244,"owners_count":21063641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browsers","chrome","firefox","rust","web","webapp"],"created_at":"2024-09-24T23:51:59.007Z","updated_at":"2026-03-03T00:39:19.633Z","avatar_url":"https://github.com/SpikeHD.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eCrowser\u003c/h1\u003e\n  \u003cp\u003eCreate \"desktop apps\" using user-supplied browsers\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/SpikeHD/crowser/check.yml\" /\u003e\n  \u003cimg src=\"https://img.shields.io/github/repo-size/SpikeHD/crowser\" /\u003e\n  \u003cimg src=\"https://img.shields.io/github/commit-activity/m/SpikeHD/crowser\" /\u003e\n\u003c/div\u003e\n\n# Features and Support\n\n## Main features\n\n* Single-digit binary size with minimal dependencies (except for the browser, of course!)\n* Multi-platform. Supports Windows, macOS, and Linux. Even on ARM!\n* Two-way IPC.\n* Support for both local and remote websites.\n* Maximizes performance of whatever browser is chosen, and uses an entirely separate browser profile.\n\n\u003e [!NOTE]\n\u003e This library will basically forever and always be intended for low-stakes or experimental use. It's really hard to guarantee working functionality and consistency across a bunch of different browsers, so please keep that in mind! \n\n## Browser support\n\nAll browser support comes with a few small caveats. You may notice small inconsistencies between, say, your app running in Firefox and in Chrome. Many of these are also not properly tested, so if you find any issues, feel free to [submit an issue](https://github.com/SpikeHD/Crowser/issues/new/choose)!\n\n* Chrome/Chromium (stable, beta, dev, canary)\n* Edge (stable, beta, dev, canary)\n* Firefox (stable, beta, dev, nightly)\n* Floorp\n* Thorium\n* Brave\n* Vivaldi\n* Librewolf\n* Waterfox\n* Mercury\n\nWant to see what browsers are detected on your system? Run the `browsers` example with `cargo run --example browsers`!\n\n\u003e [!TIP]\n\u003e Not seeing your favorite browser? Feel free to submit an issue!\n\u003e\n\u003e If you have some programming/Rust experience, it's trivial to add new browsers to the [supported list](./src/browser/mod.rs).\n\n# Usage\n\nMore examples can be found in the [examples](./examples) directory. Try them with `cargo run --example \u003cexample\u003e`!\n\n## Displaying a remote website\n```rust\nuse crowser::{error::CrowserError, RemoteConfig, Window};\n\nfn main() -\u003e Result\u003c(), CrowserError\u003e {\n  // Profile directories are specified by you, so put it wherever makes sense!\n  let mut profile_dir = PathBuf::from(\"/path/to/your/app/profiles\");\n\n  let config = RemoteConfig {\n    url: \"https://example.com\".to_string(),\n  };\n\n  let mut window = Window::new(config, None, profile_dir)?;\n\n  // Make sure the profile is brand-new before launch\n  window.clean_profile()?;\n\n  // This will spawn the window and block until it is closed\n  window.create()?;\n\n  Ok(())\n}\n```\n\n## Embedding a local website\n```rust\nuse crowser::{error::CrowserError, include_dir, LocalConfig, Window};\n\nfn main() -\u003e Result\u003c(), CrowserError\u003e {\n  let mut profile_dir = PathBuf::from(\"/path/to/your/app/profiles\");\n\n  // include_dir is a re-export of the include_dir crate\n  let dir = include_dir::include_dir!(\"/path/to/your/app/dist\");\n\n  let config = LocalConfig {\n    directory: dir.clone(),\n  };\n\n  let mut window = Window::new(config, None, profile_dir.clone())?;\n\n  window.clean_profile()?;\n\n  window.create()?;\n\n  Ok(())\n}\n```\n\n## Registering a command\n```rust\nuse crowser::{error::CrowserError, ipc::BrowserIpc, RemoteConfig, Window};\n\nfn main() -\u003e Result\u003c(), CrowserError\u003e {\n  let mut profile_dir = std::env::current_dir()?;\n  profile_dir.push(\"example_profiles\");\n\n  let config = RemoteConfig {\n    url: \"https://example.com\".to_string(),\n  };\n\n  let mut window = Window::new(config, None, profile_dir)?;\n  let ipc = window.ipc();\n\n  window.clear_profile().unwrap_or_default();\n\n  std::thread::spawn(move || {\n    ipc.block_until_initialized().unwrap_or_default();\n\n    ipc\n      .register_command(\n        \"hello\",\n        |_| {\n          println!(\"Got hello command\");\n          Ok(serde_json::json!(\"Hello from Crowser!\"))\n        },\n      )\n      .unwrap_or_default();\n\n    std::thread::sleep(std::time::Duration::from_secs(1));\n\n    // Eval some JS that calls that command\n    let result = ipc.eval(\"window.__CROWSER.ipc.invoke('hello')\").unwrap_or_default();\n    println!(\"Result: {:?}\", result);\n  });\n\n  window.create()?;\n\n  Ok(())\n}\n```\n\n# How does it work?\n\nOn a high level, Crowser works by first detecting browser installations on the user's system (using known paths and ~~registry keys~~). Then, depending on the browser chosen, it will make some specific changes to the browser's CLI arguments,\nprofile directory, or both. For example, for Firefox there is a `user.js` file in all profiles that can control much of the browser's default behavior. In Chromium-based browsers, there are a stupid amount of command-line arguments that can be\nused to control the browser's behavior ([check out this huge list!](https://peter.sh/experiments/chromium-command-line-switches/)).\n\nIPC is facilitated through the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). To keep the binary size small, the implementation is custom and therefore a little scuffed, but developers do not have to\ncare about it anyways!\n\n# Contributing\n\nIssues, PRs, etc. are all welcome!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspikehd%2Fcrowser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspikehd%2Fcrowser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspikehd%2Fcrowser/lists"}