Runtime distributions
For everyday use on a supported Linux or macOS host, install the prebuilt native
release. It does not need Java. The dev track runs from source on the JVM. Both
install vis-agent, which runs the engine and gateway, and vis-tui, the terminal
client that connects to it. The desktop apps connect to
the same gateway from Windows, macOS or Linux.
When to use
- You are installing Vis and must choose a build. Compare native and JVM, then install.
- You want to upgrade Vis to a newer release. See Updating and selecting a track.
- A fix you need is only in a beta. Switch to that version, and back to the stable release afterwards.
- You develop Vis or need the latest code from
main. Use thedevtrack, or run on the JVM for one launch. - The gateway runs a different version than your terminal after an update. See How you learn that a newer version is running.
- You want the desktop app. Open the desktop app for your platform and release track.
- CI or a team must stay on a tested version. Pin an exact version and verify what you download.
- A desktop fix you need is only in a beta. Open the beta desktop app, which stays separate from your stable app.
- You want Vis in a browser. Open the web app that your gateway serves.
To add Java or Clojure code inside the engine, see Native builds for Java and Clojure extensions.
Native vs JVM
Choose native for everyday use. Choose JVM when developing Vis itself or
running the latest code from main.
| What matters | Native | JVM |
|---|---|---|
| Best for | Daily work and multiple sessions | Developing Vis and trying the latest changes |
| Version track | release (default) or beta |
dev |
| Java / Git | Not needed | Git and JDK 25+ |
| Gateway startup | ~0.7 s | ~8.6 s |
| Gateway RAM | ~122 MiB | ~566 MiB |
| RAM per session (light use) | ~60 MiB | ~153 MiB |
Approximate figures, measured on an Apple M4 Max.
Installing
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash
By default the installer downloads the latest complete stable native release. It
puts the engine, bundled Python worker and matching TUI in ~/.local/bin and adds
that directory to the shell profile if needed. Use --install-dir PATH to change it.
Native installation requires curl and tar, not Java or Git. Missing or incomplete
native packages fail without installing a JVM fallback.
The installer accepts the same tracks as update:
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash -s -- --track beta
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash -s -- --track dev
The bootstrap scripts refresh after successful main CI, independently of stable
releases. They are published as GitHub release assets because some networks block
raw.githubusercontent.com. Native installations still use the matching launcher
from their selected release. Running bin/install-vis-agent from a clone also works.
Pin an exact version
Use --version when a CI pipeline or a team must stay on a tested release or beta.
The installer then installs exactly that build, never a newer one.
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash -s -- --version 0.2.46
# The same with an environment variable:
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | VIS_AGENT_VERSION=0.2.46 bash
You can write 0.2.46 or v0.2.46. The installer takes the vis-agent command from
that release and runs vis-agent update v0.2.46. If the release does not exist or
has no bundle for your platform, the installation stops. It never falls back to the
latest release. A stable version selects the release track, so you cannot add --track beta
or --track dev.
To pin a tested beta, give its full tag: beta- and the 40-character commit.
vis-agent switch list shows the published beta tags.
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash -s -- --version beta-<commit>
A beta tag selects the beta track, so you cannot add --track release or --track dev.
The installer runs vis-agent update beta-<commit>. The update takes the engine, Python, TUI and
web app from that beta. It checks each download against the SHA256SUMS of the beta. The
installation stops if the beta does not exist, has no SHA256SUMS or misses a selected part. It
never falls back to the latest beta, and the installed build and track stay the same.
Choose what to install
By default the installer adds the terminal client (TUI) and the web app. If you use
only the vis-agent command line, for example on a server or in CI, install less
with --components:
# Only the command line, the engine and Python:
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash -s -- --components none
# The TUI, without the web app:
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | bash -s -- --components tui
# Everything, and the desktop app now:
curl -fsSL https://github.com/Blockether/vis/releases/download/installer/install-vis-agent | VIS_COMPONENTS=all bash
| Component | What it adds |
|---|---|
tui |
The terminal client for vis-agent tui. |
web |
The web app for vis-agent web. |
desktop |
The desktop app, downloaded during the installation. |
The engine and the Python runtime are always installed. Use none, all or a list
separated by commas. Vis saves your selection, and vis-agent update keeps it. To
change it later, run vis-agent update --components tui,web. An update removes the
parts that you do not select. Without desktop, vis-agent desktop still downloads
the desktop app the first time that you open it.
Verify what you download
Each release publishes SHA256SUMS, with the SHA-256 hash of each of its assets.
The installer checks the vis-agent command against this list before it runs it.
vis-agent update checks each archive before it unpacks it. A changed file or a
missing entry stops the installation, and the installed version stays. Older releases
have no SHA256SUMS, so Vis installs them with a warning.
SHA256SUMS comes from the same place as the assets. In CI, keep the hashes in your
repository instead, so a replaced asset cannot pass. Pin the installer with
sha256sum --check, and pin the vis-agent command with --sha256 or
VIS_AGENT_SHA256:
tag=v0.2.46
base=https://github.com/Blockether/vis/releases/download/$tag
curl -fsSLO "$base/install-vis-agent"
echo "<installer hash> install-vis-agent" | sha256sum --check
bash install-vis-agent --version "$tag" --sha256 "<vis-agent hash>"
With a stable --version, the command comes from that release, so its hash does not change.
A beta publishes no separate command. With a beta tag, the installer uses the command of the
rolling installer assets, so its hash changes when they refresh. The update then installs the
command from the beta bundle. A different command stops the installation before it runs.
To check release assets by hand, download them and SHA256SUMS to one directory:
tag=v0.2.46
base=https://github.com/Blockether/vis/releases/download/$tag
curl -fsSLO "$base/SHA256SUMS"
curl -fsSLO "$base/vis-agent"
sha256sum --check --ignore-missing SHA256SUMS
The expected output is vis-agent: OK. On macOS, use shasum -a 256 --check --ignore-missing SHA256SUMS. Use sha256sum vis-agent to get the hash to pin.
Updating and selecting a track
vis-agent update # release, always the default
vis-agent update --track release # latest complete stable native release
vis-agent update --track beta # latest complete native beta
vis-agent update beta-<commit> # that published beta build
vis-agent update --track dev # newest main source, always JVM
| Track | Source | Execution |
|---|---|---|
release |
Latest complete stable GitHub release | Native engine, gateway, workers and TUI |
beta |
Published beta of a main commit that passed CI and native checks | Native engine, gateway, workers and TUI |
dev |
Newest commit of main |
JVM engine, gateway, workers and TUI |
Every update without --track or a beta tag selects release, also after beta or dev. A successful update
records the selection for later launches. To stay on beta or dev, name that track in each update. A
failed download does not change the recorded selection. Dev ignores any native binaries from a
previous install.
vis-agent update vX.Y.Z installs a specific stable version on the release track.
vis-agent update beta-<commit> installs that published beta on the beta track. A missing,
incomplete or unverified beta stops the update. Dev accepts no version pin. Native updates acquire the engine,
Python worker and TUI from the same immutable release before replacing installed files.
A missing native TUI fails rather than starting a JVM client.
How you learn that a newer version is running
The gateway is a daemon that keeps running after the command that started it ends. So the gateway can already run a newer Vis than your client. For example, an open TUI can stay alive through an update, or you can point a client at a gateway on another machine.
When the client and the gateway run different releases, Vis tells you in three places:
- The terminal client prints one line per run.
- The TUI shows a notice in its header.
vis-agent gateway statusnames both releases.
Vis refuses nothing, because both halves still use the same wire protocol. To close the gap, run
vis-agent update on the machine that is behind.
Switching between versions
update follows a track forward. switch names the build that you want to run. So you can move to
a published beta to try a fix, and then back to the stable release.
vis-agent switch list # installed build, tracks and published versions
vis-agent switch release # newest stable release
vis-agent switch beta # the beta the installer index selects today
vis-agent switch v0.2.46 # that stable release
vis-agent switch beta-<commit> # that published beta build
vis-agent switch dev # newest main source, always JVM
switch list first prints the installed version and track. Then it lists the tracks, the published
releases and the published betas, and marks the entry that the installed build came from. It needs
GitHub only for the published lists. If Vis cannot read them, you can still name a version.
A switch installs the bundle it names through the same installer update uses, and records
the selection, so later launches use it. Configuration, sessions and extensions are shared by
every version, so switching back costs only the download. --keep-gateway leaves a running
gateway alone, exactly as it does for update.
If managed source already exists in ~/.vis/install/src, a native update also pins it to the exact
commit of the selected native build. This needs Git. Native-only installations do not download
source.
If that checkout has staged, unstaged or untracked changes, the update stops and shows the checkout path. Commit or stash your changes, then run the same command again. Until then, nothing changes: not the source, the native installation or the selected track. A failed source fetch also changes nothing.
Managed source is a detached commit, not a tracking branch. For a manual pull, name a branch.
An update stops an idle managed gateway before it replaces the files. It never stops a busy gateway
or one that you started yourself. Add --keep-gateway to leave an idle gateway running too.
Dev needs Git and JDK 25+. The launcher can install the Clojure CLI.
VIS_NO_AUTO_INSTALL=1 disables that installation. Dev does not build native images.
To run local repository edits independently of installed tracks, use
clojure -M:vis inside that checkout. Build those edits with clojure -T:build native.
One-launch JVM override
Use --jvm to run on the JVM without changing the installed track:
vis-agent tui --jvm
# Equivalent:
vis-agent --jvm tui
# Start a foreground gateway on the JVM:
vis-agent gateway start --jvm
# Equivalent:
vis-agent --jvm gateway start
The flag applies to this launch only and is consumed by the launcher, not the
engine or terminal client. It uses the managed source in ~/.vis/install/src. If
no managed source exists, a checkout-owned launcher uses its own source tree:
./bin/vis-agent tui --jvm. An installed launcher with no source reports how to
install it with vis-agent update --track dev. It does not download source or
change tracks automatically. JVM execution requires JDK 25+.
For gateway inspection and control commands, --jvm selects the local command's
runtime. It does not change the runtime of an already-running or remote daemon.
--jvm is not an update option. Use --track dev to install or update JVM source.
Arguments after -- or python uv are passed through unchanged.
Terminal gateway lifecycle
vis-agent tui discovers the local gateway and starts one when none is running.
A native installation starts a native gateway. Dev or an explicit --jvm launch
starts it with the same JVM and engine classpath. A compatible gateway already
serving other clients is reused, never killed to change its runtime.
You do not need to start a gateway before you run vis-agent tui. A start can take a while, most of
all with --jvm, which runs Vis from source. vis-agent tui waits while the new gateway starts. If
the start takes longer than 15 seconds, it prints the path of the gateway's boot log under
~/.vis/logs/. If the gateway exits before it is ready, or is not ready after 10 minutes,
vis-agent tui stops. It then shows the last lines of that boot log, so you can see what went
wrong.
The launcher holds a client lease until the TUI exits. The TUI also registers its local PID so crashed clients and their event streams can be reaped. A managed gateway stops after its last client disconnects and no work remains. Closing one TUI does not stop another TUI, the companion, or an active turn. Manually started gateways remain user-owned.
--gateway or VIS_GATEWAY_URL selects an explicit gateway: the TUI only connects
to it and never starts or stops a local replacement. If your shell profile sets
VIS_GATEWAY_URL, unset it to let vis-agent tui start a local gateway again.
Help and version commands do not start a gateway. Direct vis-tui execution
remains a connection-only client. Use vis-agent tui for automatic local
lifecycle management.
Open the web app
The web app is the Companion app, served by your own gateway. Use it to open Vis in a browser without a desktop app. It works on the computer where Vis runs and on other devices on your network.
vis-agent web # use or start the gateway on 127.0.0.1:7890 and open the app
vis-agent web --port 8080 # use or start the gateway on port 8080 instead
vis-agent web --host 0.0.0.0 # also serve other devices on your network
vis-agent web --no-open # print the address without opening a browser
vis-agent web --pair # also print a pairing QR for the Companion app on your phone
The command prints the address it opens. Keep it running while you use the app, and
press Ctrl-C when you are done. If the gateway stops answering, the command ends and
tells you. vis-agent gateway start serves the web app too, and prints its address when
the web app is installed.
The address that vis-agent web prints connects the browser to this gateway. You do not
type a token. The address works once, within 5 minutes, and does not contain the gateway
token. If the address is too old or was already used, the web app shows an error and the
connection screen. Run vis-agent web again to get a new address.
With --no-open, open the printed address yourself, or give it to a script that opens it. A
script can replace the host with localhost and keep the rest of the address.
--pair prints the same pairing block as vis-agent gateway start --pair: the link, the
token and a QR code. Without --host, it starts the gateway on an address that your phone can
reach. --advertise sets the address in the pairing link, as it does for vis-agent gateway start.
Voice input works only on a secure page: HTTPS, or localhost and 127.0.0.1 on the computer
that runs Vis. Browsers block the microphone on other http:// addresses. For example, a Windows
browser that opens the address of Vis in WSL cannot record. To allow such an address in Chrome:
- Open
chrome://flags/#unsafely-treat-insecure-origin-as-secure. - Add the address of the web app, for example
http://172.20.1.2:7890. - Set the flag to Enabled and relaunch Chrome.
Choose the gateway address
--host and --port name the gateway the web app uses. They default to 127.0.0.1
and 7890.
- If your gateway already answers at that address, the web app uses it.
- If no gateway is running,
vis-agent webstarts one there. - If your gateway runs at another address and nothing uses it,
vis-agent webrestarts it at the new address. Some gateways stay where they are: a gateway that another Vis session uses, or one that you started withvis-agent gateway start. For those, the command tells you where the gateway runs and how to open the web app there. - If the host is another machine, or another gateway already answers at that address,
vis-agent webopens the web app of that gateway. SetVIS_GATEWAY_TOKENwhen that gateway requires a token.
A gateway bound to 0.0.0.0 or to a network address always requires its token, also in
your own browser. The address that vis-agent web prints gives the token to that browser. On
other devices, the web app asks for the token, and vis-agent gateway pair shows it. The
command also prints the addresses that other devices can open.
Get the web app
Release and beta builds publish the web app with the native runtime. vis-agent update installs it
next to the runtime, so you do not need Node.js. If the web app is missing, the first
vis-agent web downloads the copy published with your installed build.
The dev track runs Vis from source. There, the first vis-agent web builds the web app with Node.js
and npm. Later runs rebuild it only after the Companion sources change. A gateway that is already
running serves the new build without a restart. To serve a different build, set VIS_WEB_DIR before
the gateway starts. Point it to a directory that contains the build's index.html.
Open the desktop app
- Download the installer from GitHub Releases for your computer.
- Install the package and open Vis from your application launcher.
- Connect to your gateway to open your projects and continue your sessions.
| Platform | Package | Install |
|---|---|---|
| Windows 10/11 x64 | .msi |
Run the installer. |
| macOS, Apple silicon or Intel | Universal .dmg |
Open the disk image and copy Vis to Applications. |
| Linux x64 or ARM64 | .AppImage or .deb |
Make the AppImage executable and open it, or install the Debian package with your package manager. |
The Windows installer downloads Microsoft Edge WebView2 if needed. Installation may require network access and administrator approval. To update the app, close Vis and install the newer package from the same release page.
Each published beta has the same installers. A desktop fix can reach a beta before a stable release.
To try it, download the installers from that beta's prerelease on the releases
page. A beta package installs as the same Vis app as
the stable package. To keep your stable app, use
vis-agent desktop --track beta on macOS or Linux instead.
Run the gateway on the computer where your projects live: macOS, Linux, or Linux in WSL2 on Windows. For a local WSL2 gateway, enable localhost forwarding. The connection guide covers both local addresses and remote pairing. Isolated drafts have more filesystem requirements.
Notifications on the desktop
The desktop app raises a system alert when a session on a connected machine answers you or asks you a question. The alert carries the session's name and what Vis said, the same as the alert on your phone. Turn it on for each machine in Settings, under Notifications: pick the machine and switch its notifications on. macOS asks for permission the first time, and System Settings, under Notifications, controls how those alerts appear.
Alerts arrive while the desktop app is open. It cannot receive push notifications, so nothing reaches it after you quit. To hear about a session while the desktop app is closed, keep a connection to that machine open. Use the Companion app on your phone or a browser tab.
Microphone and camera on the desktop
Dictation uses the microphone and pairing by QR code uses the camera, so macOS asks for permission the first time you use each one. Allow it once and the desktop app keeps that access. To change it later, open System Settings, under Privacy & Security, and look at Microphone and Camera.
macOS and Linux launcher
Open the desktop Companion for your selected release track:
vis-agent desktop # use the track selected by vis-agent update
vis-agent desktop --update # check for a release or beta update, or rebuild dev
vis-agent desktop --track release # download and open stable for this launch
vis-agent desktop --track beta # download and open the newest beta for this launch
vis-agent desktop --track dev # build and open your current source checkout
vis-agent desktop --no-gateway # open the app without the local gateway
vis-agent desktop --help
--track overrides the desktop track for one launch. It does not change your
engine selection. With no installed track, a source-only checkout defaults to dev.
Otherwise the default is release.
On macOS, the launcher also copies the app to /Applications when you can write
there. Launchpad, Spotlight and the Dock then open the version that the launcher
installed. Each track has its own copy: Vis.app, Vis Beta.app or Vis Dev.app.
Each install, update or dev build refreshes the copy of its track.
The launcher never replaces an app with that name from another publisher. Before it
opens the app, it closes a copy that runs from /Applications. Set
VIS_APPLICATIONS_DIR to use another folder, or set it to an empty value to turn the
copy off.
Release: download and reuse
On macOS and Linux, the release track chooses the universal macOS app (Apple
silicon or Intel), or the Linux AppImage for x64 or ARM64. Downloads need curl
and network access. On macOS, the launcher copies Vis.app from the signed
disk image into your Vis cache. On Linux, it runs the AppImage with built-in
extraction, so FUSE is not required. You still need a graphical
desktop and the system libraries required by the app.
Later release launches reuse the cached app and do not contact GitHub. vis-agent update updates an
installed release app together with the engine. So the desktop app that you open matches the runtime
that you installed. It never installs an app that you do not have.
--update checks for a newer stable version and downloads it only when it is not cached. If a
download or an installation step fails, the app that you selected before stays as it was. An engine
update still succeeds. Retry the command, or omit --update to open the existing copy. If a cached
executable is missing, Vis downloads it again automatically.
Beta: the newest published beta
The beta track downloads the desktop app from the newest published beta, the same
build that vis-agent update --track beta installs. It otherwise works like release:
later launches reuse the cached app, --update checks for a newer beta, and
vis-agent update --track beta refreshes an installed beta app. Beta apps are kept
apart from stable ones, so opening one track never removes the other's app.
If the newest beta has no app for your platform, the launcher says so and keeps any cached beta app.
Open --track release instead.
Dev: build from source
On macOS and Linux, the dev track builds the web bundle and native desktop app
from your selected source on every launch, including uncommitted changes. It uses the managed
checkout at ~/.vis/install/src when present. Otherwise, a checkout-owned
bin/vis-agent builds that checkout. It never downloads a released desktop app or
falls back to an older build after a failure.
Before you run it, install these tools:
- Node.js 20 or newer, with npm.
- Rust 1.85 or newer, with Cargo.
- The native build tools. macOS needs Xcode and its command-line tools. Linux needs a C/C++
toolchain, WebKitGTK 4.1 development packages and
xdg-utils.
The desktop build workflow lists the Ubuntu packages. Some of these installs need administrator access. Dependency downloads need network access, and the first native build can take several minutes. Later builds reuse the npm and Rust download and build caches, but they still run the build steps.
The launcher runs npm ci, npm run build, and npm run package:desktop -- --dev
in apps/vis-companion. This reinstalls that checkout's node_modules and updates
its build outputs. The result targets only your machine's architecture, needs no
release signing credentials, and has a separate app identity from stable.
desktop --update also builds the current checkout. To fetch newer source
first, run vis-agent update --track dev.
Cached files and pairing
Release files live in ~/.vis/install/desktop/<platform>/<version>/, beta files in
~/.vis/install/desktop/beta/<platform>/<version>-beta.<commit>/, and source builds
in ~/.vis/install/desktop/dev/<platform>/<version>.<build>/. All of them respect
VIS_HOME, and installing an app there needs no administrator access.
Only one desktop app runs at a time. A launch closes a desktop running from another version or track, then opens the version you selected. If that version is already running, its window comes to the front.
The launch then deletes the other versions in that track's folder, leaving one app on disk. The other tracks keep their files. Release and beta apps deleted this way download again when you need them, and dev builds are rebuilt from source on every launch.
A desktop launch does not change your engine track. If no local gateway runs, it starts one
in the background through your installed engine. The gateway stays up while the app runs.
After you quit the app, a gateway started this way stops when no other client or work
remains. A gateway that you started with vis-agent gateway start keeps running.
--no-gateway opens the app alone. --gateway or VIS_GATEWAY_URL names another gateway, so
a launch with either one also opens the app alone. The TUI and vis-agent web follow the
same rule. A launch without an installed engine also opens the app alone.
On first launch, add this machine in the app with http://127.0.0.1:7890 and an empty
bearer token. For a gateway on another machine, use its URL and bearer token.
See Desktop and mobile setup for connection options.
Automatic native betas
The Beta Native workflow starts after successful push CI on main. It verifies
that CI passed for the exact commit in this repository and selects the latest
successful main run. A newer successful run cancels an older beta build. New
commits whose CI is pending or failed do not block publication of a green beta.
Beta uses the same native build and test workflow as stable releases on Linux x86-64, Linux ARM64
and macOS ARM64. It also uses the same desktop packaging for macOS, Windows and Linux. Each build
has an immutable beta-<commit> tag. Its prerelease stays a draft until two conditions are true:
- All native tests, SDK checks, TUI checks and desktop packaging pass.
- The six engine and TUI archives, the web app and the six desktop installers are present and not empty.
A failed or cancelled build cannot replace the last published beta. A beta never becomes the latest stable release on GitHub, and it does not publish mobile apps.
Files
| Path | Contents |
|---|---|
~/.local/bin/vis-agent-native |
Installed native engine |
~/.local/bin/vis-agent-python/ |
Its bundled Python worker and interpreter |
~/.local/bin/vis-tui |
Matching native terminal client |
~/.local/bin/vis-web/ |
Web app that the gateway serves |
~/.vis/install/desktop/ |
Desktop apps by platform and version, with beta apps in beta/ and dev builds in dev/ |
~/.vis/install/track |
Selection for later launches |
~/.vis/install/src |
Managed dev checkout at a detached main commit |
~/.vis/install/ref |
Commit pinned by the last dev update |
~/.vis/install/vis-agent-native |
Native engine for a checkout-owned launcher |
Each native engine has a vis-agent-native.build file beside it, containing its
version, commit, build track and timestamp. vis-agent --version reports the version.
VIS_HOME changes the state directory from ~/.vis. vis-agent --measure prints
startup timings. --jfr saves Java Flight Recorder profiles.
Native bundles
vis-agent-<os>-<arch>.tar.gz
├── vis-agent
├── vis-agent-native
├── vis-agent-native.build
├── vis-agent-python/
└── install-vis-agent
vis-tui-<os>-<arch>.tar.gz
└── vis-tui
To build an image, you need the GraalVM CE version in .graalvm-version and about 32 GB of RAM.
bin/release-native builds and smoke-tests the assets that the host supports. On Apple silicon, it
builds macOS natively, Linux ARM64 in a container and Linux x86-64 through Rosetta.
Enable Rosetta in Docker Desktop or podman, because the build rejects qemu.
VIS_CONTAINER_CONNECTION and VIS_CONTAINER_CLI select the container machine and engine. On
platforms without native bundles, use the dev track.
See also
- Native builds for JVM extensions — only for adding Java/Clojure capabilities inside Vis.
- Getting started — download a client and connect to your sessions.
- Configuration
