Elyra
Elyra The coding agent eTerm The terminal that knows where each command ends Starf An activity monitor for Apple silicon that never invents a number etrans An SSH and SFTP client for macOS Elyra VM Virtual machines for macOS, Linux and Windows on your Mac Litr A small, native web browser for macOS Notr A notebook for macOS e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Refr Local-first PDF workspace for macOS Elyra Workspace A desktop workspace for coding agents Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Elyra
Elyra VM Tools

Elyra VM Tools

Elyra VM Tools is a small agent that runs in a guest, as root, and does what the VM's own process on the Mac asks of it. With it, a VM

  • runs commands for you, a script or an AI agent: elyravm exec <vm> -- <command>
  • gives you a shell in this terminal, with no network or SSH: elyravm shell <vm>
  • copies files and folders in and out: elyravm cp <file> <vm>:<path>
  • takes files dropped on the VM's window into the guest's Downloads (elyravm send), and, in macOS guests, lets files be dragged out of the guest into Finder
  • shares the clipboard with macOS guests, which Apple's framework doesn't (Linux has it through the SPICE agent)
  • reports who it is: the system's name and version, its host name and its addresses, in the library, the VM's settings and elyravm status --json
  • keeps its clock right after it was paused or suspended
  • mounts the shared folders at /mnt/mac (Linux; macOS mounts them by itself)
  • shuts down cleanly when you choose Shut Down, also where the power button is ignored
  • keeps itself up to date: a VM gets the agent of the Elyra VM that runs it

The agent talks to the Mac over a virtio socket (vsock), a channel between the VM and its own process only: nothing on the network, and no other VM, can reach it.

Getting it

Systems ready to use from the catalog

A VM made from a system ready to use (Ubuntu Server 26.04, Fedora Cloud 44, Debian 13, or one of their desktops) has it from the first boot, with nothing to install (Linux guests).

Other Linux guests

Every VM sees Elyra VM Tools as a read-only folder in its shared folders. Mount them and run the installer as root:

sudo mkdir -p /mnt/mac
sudo mount -t virtiofs elyravm /mnt/mac
sudo sh "/mnt/mac/Elyra VM Tools/Linux/install.sh"

It copies the agent to /usr/local/sbin/elyravm-tools and runs it as a service: a systemd unit (elyravm-tools.service), or an OpenRC service on Alpine and others without systemd. The agent is one static program, so it runs on any ARM64 Linux, with no packages to install. The kernel needs vsock for virtio (vmw_vsock_virtio_transport), which current distributions have.

Within a few seconds the VM's settings say Elyra VM Tools: Running.

macOS guests

Once macOS is set up and you are logged in, open Terminal in the guest and run:

sudo sh "/Volumes/My Shared Files/Elyra VM Tools/macOS/install.sh"

It installs the agent in /usr/local/libexec/elyravm-tools and runs it twice:

  • as a launch daemon, as root, for exec, shell, cp, the clock and shutting down, as in Linux;
  • as a launch agent in each user's session (elyravm-tools --session), as that user, for what only a session reaches: the clipboard, and files dropped on the VM's window.

macOS says a background item was added; that is it. Elyra VM Tools.pkg, in the same folder in builds that carry it, installs the same; unsigned, Gatekeeper asks you to allow it in System Settings ▸ Privacy & Security first. The script needs no such step.

With it, what you copy on the Mac and in the guest follows to the other both ways, within a second (as long as the VM's settings share the clipboard): plain text, formatted text (RTF and HTML, from TextEdit, Pages, Safari, Mail) and pictures (PNG and TIFF, such as a screenshot), up to 32 MB a copy. Each copy goes with every kind it has, so the app you paste into picks the best one, as on one Mac.

Files copied in Finder go across too, up to 1 GB a copy: their contents are sent to the other side (the window's subtitle says Copying 2 items to the VM's clipboard…) into a folder of their own, with their metadata, and that side's clipboard holds them there, so pasting in Finder copies them in. Only the last copy's files are kept: in the guest in its temporary folder, on the Mac in ~/Library/Caches/Elyra VM/Clipboard. A copy of more than 1 GB stays on its side, as runner.log says; drop such files on the window instead. and files dropped on the window land in the logged-in user's Downloads. The first time something reads Downloads through the session agent, macOS asks in the guest whether elyravm-tools may use it: allow it (until then, such a command waits for the answer). elyravm exec --session <vm> -- <command> runs a command as that user, in their session, as the session agent: open -a Safari, osascript, pbpaste.

The daemon runs as root, but macOS keeps the folders it protects (Desktop, Documents, Downloads and others) from it; reach those with --session, or give elyravm-tools Full Disk Access in the guest's settings.

Running commands

elyravm exec <vm> [--user <name>] [--timeout <seconds>] [--json] -- <command> [<argument>…]

The command runs in the guest as root, or as --user, with that user's groups, in that user's home, with its HOME. It is run directly, not through a shell; for pipes and &&, run a shell:

$ elyravm exec "web server" -- uname -r
7.0.0-34-generic
$ elyravm exec "web server" --user kh -- sh -c 'cd ~/app && git pull'
$ echo "hello" | elyravm exec "web server" -- tr a-z A-Z
HELLO
  • Output comes as the command writes it: its standard output on stdout, its standard error on stderr, binary or text, of any size.
  • Standard input from a pipe or a file goes to the command as it comes; from a terminal, the command gets none.
  • The exit code is the command's own; 128 + n for one killed by signal n.
  • --timeout stops the command, and everything it started, after that many seconds (an hour when not given), and the exit code is 124, as with timeout(1).
  • Stopping exec (⌃C, or killing it) stops the command in the guest too.
  • --json prints {"exit": 0, "stdout": "…", "stderr": "…", "timed_out": false} when the command has ended, instead of the output as it comes.
  • Several commands may run at once, each on a connection of its own.
  • What a command leaves running in the background, such as a server started with &, goes on running after exec returns.

If the agent isn't running in the VM, exec says so and exits with 1.

A terminal

elyravm shell <vm> [--user <name>]
elyravm exec -t <vm> [--user <name>] [--timeout <seconds>] -- <command> [<argument>…]

shell opens a login shell in the VM, root's or the --user's, in the terminal you type it in: a terminal of its own in the guest (/dev/pts/…), the size of your window and following it, with your TERM. Every key goes to the guest, ⌃C, ⌃Z and ⌃D too; colours and full-screen programs (top, vim, less) work. exit ends it, and elyravm exits with the shell's code. It needs no network, no SSH and no password.

$ elyravm shell "web server" --user kh
kh@web-server:~$

exec -t runs a command in such a terminal, for one that wants one (htop, apt with its progress bars). Without -t, a command has no terminal, and its stdout and stderr stay apart. With -t they are one, as on any terminal, --json can't be used, and there is no time limit unless --timeout is given.

Closing the terminal, or killing elyravm, ends the shell or command in the guest. A terminal needs Elyra VM Tools 0.12.0 or later in the VM, which guests get by themselves when they start.

Copying files

elyravm cp [--user <name>] <from> <to>

One side is in the VM, written <vm>:<path>; the other is on the Mac. A path in the VM that isn't absolute is in root's home (/root), or the user's with --user.

$ elyravm cp report.pdf "web server:/tmp/"           # a file into a folder
$ elyravm cp app.conf "web server:/etc/app.conf"     # a file to a name
$ elyravm cp --user kh ~/Projects/site "web server:" # a folder into kh's home
$ elyravm cp "web server:/var/log/syslog" .          # a file out
$ elyravm cp "web server:/srv/data" ./data-copy      # a folder out, as a new name

Like cp -r: when <to> is a folder that is there, the file or folder goes into it; otherwise it becomes <to>. A file keeps its permissions and the time it was last changed; a folder comes with what is in it, symbolic links as links, times kept. On a terminal, a copy that takes more than a second shows how far it has come: Copying “big.iso” · 40 % · 1.2 GB of 3 GB. What is copied into the VM belongs to root, or to --user. What comes out belongs to you.

cp works through exec, with cat and tar in the guest, which every Linux has.

Dropping files

Drag files and folders from Finder onto a VM's window: they are copied into the Downloads folder of the guest's user, as they are, and belong to that user. The window's subtitle says Copying “report.pdf” · 40 %, then Copied “report.pdf” to ~/Downloads. A name that is taken there gets a number, as in Finder: report 2.pdf.

In Linux, the guest's user is the one the VM was set up with (a system ready to use), or else the first ordinary user in the guest (an id from 1000 with a login shell), or else root (/root/Downloads). In macOS, it is the user logged in, through the session agent.

The window takes files once the VM runs with Elyra VM Tools (in macOS, with a user logged in); otherwise its subtitle says why not while you drag.

Dragging files out

In a macOS guest with Elyra VM Tools and a user logged in, drag files or folders in the guest's Finder out over the edge of the VM's window, and on to Finder on your Mac, or any app that takes files: as the pointer leaves the window, the drag becomes the Mac's, and where you drop it, the files are copied out of the guest, as they are (a name taken there gets a number, as Finder does). In the guest, the drag is called off, and nothing moves.

Linux guests can't do this yet: their desktops (Wayland) don't let Elyra VM Tools see a drag that begins in another program. Use elyravm cp or a shared folder.

elyravm send does the same from the command line, and prints where each went:

$ elyravm send "web server" report.pdf ~/Projects/site
/home/kh/Downloads/report.pdf
/home/kh/Downloads/site
$ elyravm send "web server" --json report.pdf
{"user":"kh","paths":["/home/kh/Downloads/report 2.pdf"]}

--user sends to another user's Downloads.

Updating it

It updates itself. When a VM starts, or its agent connects, and the agent is older than the Elyra VM running the VM, Elyra VM sends it the new one (in macOS, the session agents start again as the new one within half a minute). The agent checks that the new one runs, puts it in its own place and starts again as it, in a few seconds, with nothing to restart. runner.log in the VM's folder says so:

Elyra VM Tools in the guest was updated from 0.10.0 to 0.10.1.

An agent of 0.9.0 came before this, and can neither update itself nor run exec and cp as they are now; they say it is too old. Install it again once, in the guest (over SSH, or at the console):

sudo sh "/mnt/mac/Elyra VM Tools/Linux/install.sh"

A VM sees the Elyra VM Tools of the Elyra VM that started it; after an update of Elyra VM, restart the VM before installing by hand.

Taking it out

sudo systemctl disable --now elyravm-tools
sudo rm /etc/systemd/system/elyravm-tools.service /usr/local/sbin/elyravm-tools