diff --git a/CHANGELOG.md b/CHANGELOG.md index 315468d6..fa79441e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,97 @@ # Changelog +## 0.2.0 + +#### Features + +* Process list page in [#208](https://github.com/software-mansion/voyager/pull/208) +* Process info page in [#233](https://github.com/software-mansion/voyager/pull/233) +* ETS table list page in [#216](https://github.com/software-mansion/voyager/pull/216) +* ETS table contents view in [#236](https://github.com/software-mansion/voyager/pull/236) +* ETS match-spec search in [#225](https://github.com/software-mansion/voyager/pull/225) +* Paged key lookup for bag and duplicate_bag ETS tables in [#239](https://github.com/software-mansion/voyager/pull/239), [#263](https://github.com/software-mansion/voyager/pull/263) +* Look up any non-truncated key from the ETS contents view in [#276](https://github.com/software-mansion/voyager/pull/276) +* Term inspector in [#221](https://github.com/software-mansion/voyager/pull/221) +* MCP tools for processes in [#230](https://github.com/software-mansion/voyager/pull/230) +* MCP tools for ETS tables in [#231](https://github.com/software-mansion/voyager/pull/231) +* In-app updates: the desktop app checks for a new release on startup and can install it, with an Updates card in Settings in [#251](https://github.com/software-mansion/voyager/pull/251) +* IPv6 support when connecting to nodes, directly and over SSH in [#159](https://github.com/software-mansion/voyager/pull/159) +* Setting to show the connected node's PIDs in local `<0.X.Y>` format in [#184](https://github.com/software-mansion/voyager/pull/184) +* Connecting-to-a-node guide in [#245](https://github.com/software-mansion/voyager/pull/245) + +#### Enhancements + +* Jump to linked processes from the supervision tree details panel, with a Back button through the jump history in [#277](https://github.com/software-mansion/voyager/pull/277) +* Default macOS menu (Hide, Minimize, Fullscreen), View → Zoom In (Cmd+=) / Zoom Out (Cmd+-) / Actual Size, Help → Report an Issue…, and Cmd/Ctrl+B to toggle the sidebar in [#238](https://github.com/software-mansion/voyager/pull/238), [#255](https://github.com/software-mansion/voyager/pull/255) +* Install the `voyager_agent` helper module on node connect (inspected node needs OTP 27+) in [#193](https://github.com/software-mansion/voyager/pull/193), [#223](https://github.com/software-mansion/voyager/pull/223) +* Version the remote agent so different Voyager versions can inspect the same node in [#273](https://github.com/software-mansion/voyager/pull/273) +* Rate limit remote node introspection calls in [#201](https://github.com/software-mansion/voyager/pull/201) +* Rate limit process fetches in the supervision tree details panel in [#260](https://github.com/software-mansion/voyager/pull/260) +* Show a notice instead of rendering supervision trees above 2,000 elements in [#258](https://github.com/software-mansion/voyager/pull/258) +* Start distribution without a listening port or EPMD registration in [#218](https://github.com/software-mansion/voyager/pull/218) +* More specific node connection error messages in [#177](https://github.com/software-mansion/voyager/pull/177) +* Only one app instance can run at a time in [#169](https://github.com/software-mansion/voyager/pull/169) +* Used-percentage column in System limits in [#261](https://github.com/software-mansion/voyager/pull/261) +* Remember the auto-refresh interval across reloads in [#197](https://github.com/software-mansion/voyager/pull/197) +* Keep the selected connection type (Direct / SSH) in the URL in [#183](https://github.com/software-mansion/voyager/pull/183) +* Select dropdowns styled to match the app in [#259](https://github.com/software-mansion/voyager/pull/259) +* Sidebar tooltips in compact mode in [#166](https://github.com/software-mansion/voyager/pull/166) +* Feedback link in the sidebar in [#160](https://github.com/software-mansion/voyager/pull/160) +* Copy buttons confirm with an icon change in [#161](https://github.com/software-mansion/voyager/pull/161) +* Better tooltips on the connect page in [#158](https://github.com/software-mansion/voyager/pull/158) +* Supervision tree icon rotated to match the tree's left-to-right layout in [#271](https://github.com/software-mansion/voyager/pull/271) + +#### Bug fixes + +* Generate a random distribution cookie per launch in [#205](https://github.com/software-mansion/voyager/pull/205) +* Bind the packaged app's endpoint to loopback instead of all interfaces in [#190](https://github.com/software-mansion/voyager/pull/190) +* Protect the MCP HTTP endpoint against DNS rebinding: reject non-loopback `Origin` and `Host` headers and always bind to `127.0.0.1` in [#247](https://github.com/software-mansion/voyager/pull/247), [#250](https://github.com/software-mansion/voyager/pull/250) +* Pin the host part of Voyager's own node name to `127.0.0.1` (long names) or `localhost` (short names) in [#149](https://github.com/software-mansion/voyager/pull/149) +* Fix SSH agent authentication option in [#222](https://github.com/software-mansion/voyager/pull/222) +* Persist the MCP enabled setting in the database in [#176](https://github.com/software-mansion/voyager/pull/176) +* Fix MCP telemetry in [#152](https://github.com/software-mansion/voyager/pull/152) +* Follow GNOME theme changes in Auto mode on Linux in [#281](https://github.com/software-mansion/voyager/pull/281) +* Fix app icon on older macOS versions in [#165](https://github.com/software-mansion/voyager/pull/165) +* Update the connection-type tooltip after disconnecting from a node in [#148](https://github.com/software-mansion/voyager/pull/148) +* Hide spinner arrows on number inputs in [#287](https://github.com/software-mansion/voyager/pull/287) +* Hide the WebKit caps lock indicator in password fields in [#265](https://github.com/software-mansion/voyager/pull/265) +* Dim the show-password toggle while connecting in [#199](https://github.com/software-mansion/voyager/pull/199) + +## 0.2.0-rc.1 (2026-10-07) + +#### Features + +* In-app updates: the desktop app checks for a new release on startup and can install it, with an Updates card in Settings in [#251](https://github.com/software-mansion/voyager/pull/251) +* Paged key lookup for bag and duplicate_bag ETS tables in [#239](https://github.com/software-mansion/voyager/pull/239), [#263](https://github.com/software-mansion/voyager/pull/263) +* Look up any non-truncated key from the ETS contents view in [#276](https://github.com/software-mansion/voyager/pull/276) +* IPv6 support when connecting to nodes, directly and over SSH in [#159](https://github.com/software-mansion/voyager/pull/159) +* Setting to show the connected node's PIDs in local `<0.X.Y>` format in [#184](https://github.com/software-mansion/voyager/pull/184) +* Help tooltips with Erlang docs links on process and ETS panels, and a connecting-to-a-node guide in [#245](https://github.com/software-mansion/voyager/pull/245) + +#### Enhancements + +* Default macOS menu (Hide, Minimize, Fullscreen), View → Zoom In / Zoom Out / Actual Size, Help → Report an Issue…, and Cmd/Ctrl+B to toggle the sidebar in [#255](https://github.com/software-mansion/voyager/pull/255) +* More specific node connection error messages in [#177](https://github.com/software-mansion/voyager/pull/177) +* Version the remote agent so different Voyager versions can inspect the same node in [#273](https://github.com/software-mansion/voyager/pull/273) +* Show a notice instead of rendering supervision trees above 2,000 elements in [#258](https://github.com/software-mansion/voyager/pull/258) +* Rate limit process fetches in the supervision tree details panel in [#260](https://github.com/software-mansion/voyager/pull/260) +* Used-percentage column in System limits in [#261](https://github.com/software-mansion/voyager/pull/261) +* Remember the auto-refresh interval across reloads in [#197](https://github.com/software-mansion/voyager/pull/197) +* Keep the selected connection type (Direct / SSH) in the URL in [#183](https://github.com/software-mansion/voyager/pull/183) +* Highlight the key in ETS record rows in [#270](https://github.com/software-mansion/voyager/pull/270) +* Select dropdowns styled to match the app in [#259](https://github.com/software-mansion/voyager/pull/259) +* Supervision tree icon rotated to match the tree's left-to-right layout in [#271](https://github.com/software-mansion/voyager/pull/271) + +#### Bug fixes + +* Protect the MCP HTTP endpoint against DNS rebinding: reject non-loopback `Origin` and `Host` headers and always bind to `127.0.0.1` in [#247](https://github.com/software-mansion/voyager/pull/247), [#250](https://github.com/software-mansion/voyager/pull/250) +* Follow GNOME theme changes in Auto mode on Linux in [#281](https://github.com/software-mansion/voyager/pull/281) +* Fix the ETS lookup sidebar button overflowing the window in [#272](https://github.com/software-mansion/voyager/pull/272) +* Fix the multiselect dropdown covering the sidebar in [#286](https://github.com/software-mansion/voyager/pull/286) +* Hide spinner arrows on number inputs in [#287](https://github.com/software-mansion/voyager/pull/287) +* Hide the WebKit caps lock indicator in password fields in [#265](https://github.com/software-mansion/voyager/pull/265) +* Dim the show-password toggle while connecting in [#199](https://github.com/software-mansion/voyager/pull/199) + ## 0.2.0-rc.0 (2026-09-10) #### Features diff --git a/README.md b/README.md index 5bffb595..9f38dfab 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,15 @@ https://github.com/user-attachments/assets/8aa3f69e-a692-4b9d-9bf5-75d972f6370f ## Overview -Voyager is a desktop app that inspects running BEAM systems — supervision trees, processes, memory and IO usage, running applications, and more — through one interface instead of a patchwork of shell commands copy-pasted into `iex`. It connects to any OTP 27+ node, local or remote, over plain Erlang distribution and surfaces the information the BEAM already exposes, in a form that is actually pleasant to read. +Voyager is a desktop app that inspects running BEAM systems through one interface instead of a patchwork of shell commands copy-pasted into `iex`. It connects to any OTP 27+ node, local or remote, over plain Erlang distribution and surfaces the information the BEAM already exposes, in a form that is actually pleasant to read: -No setup is required on the target node. Voyager gathers everything over RPC, and all rendering and storage happens on your machine. +- **Node info** — memory and IO usage, schedulers, system limits, and running applications +- **Supervision trees** — a graphical, navigable view of each application's process hierarchy +- **Processes** — rank processes by memory, reductions, or message queue length, and drill into any one of them +- **ETS tables** — list tables, browse their contents, look up keys, and search with match specs +- **MCP server** — the same data for coding agents such as Claude Code or Cursor, so they can inspect a live system instead of guessing from source code + +No setup is required on the target node. On connect, Voyager compiles and loads a small helper module (`voyager_agent`) into the node's memory and gathers everything else over RPC; nothing is written to the node's disk, and all rendering and storage happens on your machine. ### Why Voyager @@ -49,39 +55,34 @@ Download the latest build for your platform from the [website](https://voyager.s - macOS (Intel) - Linux (x64) — distributed as an AppImage, see [docs/linux_appimage_guide.md](docs/linux_appimage_guide.md) for how to run and install it -## Connecting to a node - -Voyager needs to reach the target node over Erlang distribution and needs its cookie. - -- **Local / remote node** — provide the node name (`myapp@host`) and the cookie. Voyager starts distribution on demand and connects. -- **Over SSH** — provide SSH credentials to a host that can reach the node. Voyager tunnels the distribution connection through it, which is the usual path to a production node behind a bastion. +The app checks for a new release on startup and can install it in place; the current version and update status are under **Settings → Updates**. -The target node must have distribution enabled — a node started without a name is not distributed and cannot be connected to at all. Give it a name and a cookie at boot, and make sure the name type matches the toggle next to the node name field: - -```sh -# long names — use the `--name` toggle in Voyager -iex --name my_app@127.0.0.1 --cookie my-secret-cookie -S mix phx.server -``` +## Connecting to a node -For a Mix release, set the equivalent environment variables instead: +Voyager connects to any distributed node running **OTP 27 or later**, either directly or through an SSH tunnel to a host that can reach it, which is the usual path to a production node behind a bastion. Start the node with a name and a cookie, then enter both in the connect form: ```sh -RELEASE_DISTRIBUTION=name RELEASE_NODE=my_app@10.0.0.5 RELEASE_COOKIE=my-secret-cookie bin/my_app start +# Elixir +iex --name my_app@127.0.0.1 --cookie my-secret-cookie +# Erlang +erl -name my_app@127.0.0.1 -setcookie my-secret-cookie ``` -Recent connections are saved in a local SQLite database; secrets are encrypted before being written. The encryption key never leaves your machine — it is generated on first boot at `~/.voyager/vault.key` (readable only by you), so losing that file makes previously stored secrets unrecoverable. +Check out the [connection guide](docs/connecting_to_a_node.md) for other setups or if the connection fails. -Distribution settings (node name, cookie handling) are configurable under **Settings → Distribution**. - -### Supported OTP versions +## MCP server -The inspected node must run **OTP 27 or later**, whether you connect directly or over SSH. Nodes on OTP 26 and older are refused. +The MCP server is on by default. Point your MCP client at: -## MCP server +``` +http://127.0.0.1:4040/mcp +``` -Voyager can expose the connected node to MCP clients such as Claude Code or Cursor, so an agent can inspect a live system instead of guessing from source code. +(You can change the port or turn the server off under **Settings → MCP Server**.) The endpoint only listens on loopback and rejects requests from non-local origins. The tools operate on whichever node Voyager is currently connected to: -Enable it under **Settings → MCP** and pick a port. Point your MCP client at the resulting HTTP endpoint. The tool operates on whichever node Voyager is currently connected to. +- `node_info` — system, memory, runtime, limits and scheduler snapshot +- `process_list` / `process_info` — rank processes by an attribute, then read one process's details +- `ets_list` / `ets_read_table_chunk` / `ets_search_table` — list ETS tables, page through one, or query it with a match spec ## Feedback and contributing @@ -93,46 +94,15 @@ Voyager is in active development and feedback shapes what gets built next. ## Development -Required Elixir, Erlang, Node.js, and Rust versions are pinned in [`.tool-versions`](.tool-versions). - -Install dependencies and set up the database: +With the tool versions from [`.tool-versions`](.tool-versions) installed: ```sh mix setup +mix phx.server # web app at localhost:4000 +mix tauri.dev # desktop app ``` -Run the web app on its own: - -```sh -mix phx.server -# or -iex -S mix phx.server -``` - -Then visit [localhost:4000](http://localhost:4000). - -Run the desktop application in development: - -```sh -mix tauri.dev -``` - -To check the production desktop app locally: - -```sh -mix assets.deploy -mix tauri.app -``` - -To tell a locally built desktop app apart from a release, set `VOYAGER_DEV_BUILD=true` in -`rel/app/.env` (see [`.env.sample`](rel/app/.env.sample)). Apps built or run through `mix tauri.*` -then show a `Dev Build` banner. - -Before opening a pull request, run: - -```sh -mix precommit -``` +Check out the [development guide](docs/development.md) if you want your own setup or want to contribute. ## License diff --git a/docs/connecting_to_a_node.md b/docs/connecting_to_a_node.md index a686ccc7..798d67fc 100644 --- a/docs/connecting_to_a_node.md +++ b/docs/connecting_to_a_node.md @@ -5,7 +5,9 @@ Voyager talks to your node over [Erlang distribution](https://www.erlang.org/doc 1. the node is **distributed**: it was started with a [name](https://www.erlang.org/doc/apps/erts/erl_cmd.html#name); 2. Voyager knows its [**cookie**](https://www.erlang.org/doc/system/distributed.html#security). -If either is missing the connection fails. This guide covers both connection types, what each field means and what to check when it does not work. +On connect Voyager also compiles and loads a small helper module (`voyager_agent`) into the node's memory, so the node must run **OTP 27 or later** and have the `compiler` application available. Elixir releases always include it; for an Erlang release make sure `compiler` is part of it. + +If any of this is missing the connection fails. This guide covers both connection types, what each field means and what to check when it does not work. ## Direct connection @@ -15,16 +17,32 @@ Use this when the node runs on your machine, or on a host you can reach directly [Short names](https://www.erlang.org/doc/apps/erts/erl_cmd.html#sname) work when Voyager and the node are on the same host, or on hosts that resolve each other by bare hostname: +Elixir: + ```sh iex --sname my_app --cookie my-secret-cookie -S mix phx.server ``` +Erlang: + +```sh +erl -sname my_app -setcookie my-secret-cookie +``` + [Long names](https://www.erlang.org/doc/apps/erts/erl_cmd.html#name) are required when you connect by IP or fully qualified domain name: +Elixir: + ```sh iex --name my_app@127.0.0.1 --cookie my-secret-cookie -S mix phx.server ``` +Erlang: + +```sh +erl -name my_app@127.0.0.1 -setcookie my-secret-cookie +``` + For a Mix release set the equivalent [environment variables](https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-environment-variables) instead: ```sh @@ -33,11 +51,34 @@ RELEASE_DISTRIBUTION=name RELEASE_NODE=my_app@10.0.0.5 RELEASE_COOKIE=my-secret- `RELEASE_DISTRIBUTION=sname` gives you short names. +For an Erlang release put the same `erl` flags in its `vm.args`: + +```sh +-name my_app@10.0.0.5 +-setcookie my-secret-cookie +``` + +`-sname` gives you short names. + +IPv6 works too: start the node with the IPv6 carrier and use an IPv6 address as the host, for example: + +Elixir: + +```sh +iex --name my_app@::1 --cookie my-secret-cookie --erl "-proto_dist inet6_tcp" -S mix phx.server +``` + +Erlang: + +```sh +erl -name my_app@::1 -setcookie my-secret-cookie -proto_dist inet6_tcp +``` + ### Fill in the form -- **Node name**: exactly what you passed to `--sname` or `--name`. Short names look like `my_app@my-machine`, long names like `my_app@10.0.0.5` or `my_app@server.company.com`. -- **Short / long toggle** next to the node name: must match how the node was started. A short-named node and a long-named Voyager cannot see each other, even on the same machine. -- **Cookie**: the value of [`--cookie`](https://www.erlang.org/doc/apps/erts/erl_cmd.html#setcookie) or `RELEASE_COOKIE`. If the node was started without an explicit cookie it uses the one in `~/.erlang.cookie` on its host. +- **Node name**: exactly what you passed to `--sname` or `--name` (`-sname` / `-name` in `vm.args`). Short names look like `my_app@my-machine`, long names like `my_app@10.0.0.5` or `my_app@server.company.com`. +- **`--sname` / `--name` toggle** next to the node name: must match how the node was started. A short-named node and a long-named Voyager cannot see each other, even on the same machine. +- **Cookie**: the value of `--cookie` / `RELEASE_COOKIE` (Elixir) or [`-setcookie`](https://www.erlang.org/doc/apps/erts/erl_cmd.html#setcookie) (Erlang). If the node was started without an explicit cookie it uses the one in `~/.erlang.cookie` on its host. - **Remember cookie**: stores the cookie encrypted in Voyager's local database so the next connect is one click. ## SSH tunnel @@ -53,18 +94,29 @@ Use this for a node behind a firewall or bastion, which is the usual production ### Fill in the form - **SSH User / SSH Host**: the login you would use with `ssh user@host`. -- **Node Name**: the node's name as seen *from the SSH host*. For a node on the same machine as the SSH server `my_app@127.0.0.1` is typical. +- **Node Name**: the node's name as seen *from the SSH host*. For a node on the same machine as the SSH server `my_app@127.0.0.1` is typical. The `--sname` / `--name` toggle next to it works as for direct connections. - **Cookie**: same as for direct connections. - **Authentication**: **SSH Agent** (default) uses the keys your local `ssh-agent` already holds. One catch: Erlang's [SSH agent client](https://www.erlang.org/doc/apps/ssh/ssh_agent.html) asks the agent for a single key per key type and tries only the first one it gets, so with two ed25519 keys loaded only the one added first is ever offered. If the host wants the other one, load it alone (`ssh-add -D`, then `ssh-add ~/.ssh/that_key`) or use a different key type for it. **Password** asks for the account password instead and can remember it encrypted. - **Advanced**: **SSH Port** (default 22) and **EPMD Port** (default 4369). Change them only when the host runs SSH or `epmd` on a non-standard port. -The SSH option is greyed out when Voyager was not started with its `proxy_epmd` module. That is how the local BEAM learns to route distribution traffic through the tunnel; the packaged desktop builds always enable it. +The SSH Tunnel option is disabled when Voyager was not started with its `proxy_epmd` module. That is how the local BEAM learns to route distribution traffic through the tunnel; the packaged desktop app always enables it, and in development `dev/server.sh` or `mix tauri.dev` does. + +## Voyager's own node and saved connections + +- Voyager starts its own distributed node named `voyager`, with host `127.0.0.1` for long names and `localhost` for short names. Set the suffix under **Settings → Distribution** to run several Voyager instances side by side. +- Voyager's own cookie is random per launch; only the target node's cookie is needed. +- Recent connections are saved in a local SQLite database; secrets are encrypted before being written. The encryption key never leaves your machine — it is generated on first boot at `~/.voyager/vault.key` (readable only by you), so losing that file makes previously stored secrets unrecoverable. ## When it does not connect -- **"Node down" right away**: the node is not distributed, or the name type toggle does not match. Run `node()` in the node's shell; `:nonode@nohost` means no name was given at boot. -- **Connection refused / timeout**: the host or the port is not reachable. For a direct connection check that `epmd` (4369) and the distribution port (random by default, you can pin it with [`inet_dist_listen_min` / `inet_dist_listen_max`](https://www.erlang.org/doc/apps/kernel/kernel_app.html#inet_dist_listen)) are open in the firewall. For SSH check that the SSH host itself can reach the node. +The form shows the reason under the field it relates to. + +- **"Node not found"** or **"Node unreachable"**: the node is not running, the name is wrong, or the node is not distributed. Run `node()` in the node's shell (`node().` in Erlang); `:nonode@nohost` (`nonode@nohost`) means no name was given at boot. Over SSH the name must be registered with `epmd` on the SSH host; set a non-standard `epmd` port under **Advanced**. +- **"Name type mismatch"**: flip the `--sname` / `--name` toggle to match how the node was started. +- **"Connection refused"**, **"Connection timed out"**, **"Host not found"** or **"Host unreachable"**: the host or a port is not reachable. For a direct connection check that `epmd` (4369) and the distribution port (random by default, you can pin it with [`inet_dist_listen_min` / `inet_dist_listen_max`](https://www.erlang.org/doc/apps/kernel/kernel_app.html#inet_dist_listen)) are open in the firewall. Over SSH these refer to the SSH host and port; also check that the SSH host itself can reach the node. +- **"Could not reach epmd on the host"**: `epmd` is not running on the node's host, or port 4369 is blocked. - **"SSH authentication failed"**: with SSH Agent, check that `ssh-add -l` lists a key the host accepts and that the agent is running. If it lists several keys of the same type, only the first is tried; see the Authentication note above. With Password, check the password. Try `ssh user@host` from a terminal first. -- **Cookie mismatch**: the node logs `** Connection attempt from disallowed node ... **`. Compare the cookie with [`:erlang.get_cookie()`](https://www.erlang.org/doc/apps/erts/erlang.html#get_cookie/0) on the node. +- **"Authentication failed - the Erlang cookie does not match"** (direct) or **"Handshake failed"** (SSH): the node logs `** Connection attempt from disallowed node ... **`. Compare the cookie with [`:erlang.get_cookie()`](https://www.erlang.org/doc/apps/erts/erlang.html#get_cookie/0) (`erlang:get_cookie().` in Erlang) on the node. +- **"Node runs OTP … - Voyager requires OTP 27 or newer"**: upgrade the node's Erlang/OTP. +- **"Could not load the Voyager agent on the node"**: usually the node's release does not include the `compiler` application. Add it to the release. - **Name resolves differently**: a long name must resolve to the same address from Voyager and from the node. When in doubt use an IP address instead of a hostname. - diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 00000000..15a2a0c1 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,54 @@ +# Development + +Voyager is a Phoenix app that ships as a desktop app through [Tauri](https://tauri.app/). + +## Prerequisites + +Required Elixir, Erlang, Node.js, and Rust versions are pinned in [`.tool-versions`](../.tool-versions). The desktop app also needs the Tauri CLI: + +```sh +cargo install tauri-cli --version "=2.8.0" --locked +``` + +Install dependencies and set up the database: + +```sh +mix setup +``` + +## Web app + +Run the web app on its own: + +```sh +mix phx.server +# or +iex -S mix phx.server +``` + +Then visit [localhost:4000](http://localhost:4000). SSH tunnel connections need Voyager's `proxy_epmd` module set at VM boot, so to try them in the web app start it with `dev/server.sh` instead. + +## Desktop app + +Run the desktop application in development: + +```sh +mix tauri.dev +``` + +To build and open the production desktop app locally: + +```sh +mix assets.deploy +mix tauri.app +``` + +To tell a locally built desktop app apart from a release, set `VOYAGER_DEV_BUILD=true` in +`rel/app/.env` (see [`.env.sample`](../rel/app/.env.sample)). Apps built or run through `mix tauri.*` +then show a `Dev Build` banner. + +## Before opening a pull request + +```sh +mix precommit +``` diff --git a/docs/linux_appimage_guide.md b/docs/linux_appimage_guide.md index 0a4d2a89..b0e6bd93 100644 --- a/docs/linux_appimage_guide.md +++ b/docs/linux_appimage_guide.md @@ -5,8 +5,8 @@ Voyager on Linux is distributed as an [AppImage](https://appimage.org/). Downloa ### Run directly ```sh -chmod +x Voyager-*-AppImage -./Voyager-*-AppImage +chmod +x Voyager-linux-amd64.AppImage +./Voyager-linux-amd64.AppImage ``` ### Integrate into your app menu (recommended)