uxntal Protocol Specification Defined
This module documents the uxntal:// protocol for launching TAL/ROM files via URL.
Quick Start
uxn-tal uses this module to map urls to emulators.
cargo install uxn-tal
uxntal --register
uxntal uxntal://https://wiki.xxiivv.com/etc/catclock.tal.txt
The above will run a catclock from Windows, MacOS, and Linux.
-
--registerwill setup a protocol handler foruxntal://on your system. It will also ask you to install the e_window and cardinal-gui crates as a dependency. This feature allows you to placeuxntal://in front of any http(s) url and uxntal will download, assemble, cache, and run the tal/rom file pointed to by url.uxntal --registerbeen tested on Windows, MacOS, and Linux. On macOS,--registercreates a minimal GUI.appbundle in your~/Applicationsfolder that registers theuxntal://protocol. This bundle launches your installeduxntalbinary with the URL as an argument. -
uxntal --unregisterwill remove and disableuxntal://urls.
Bookmarklets
You can prepend the uxntal:// to any valid tal url, or you can create a bookmarklet on your bookmark toolbar to launch the protocol on click of the bookmarklet.
javascript:(function(){window.open('uxntal://' + location.href);})();
This works for most webpages, however content from raw.githubusercontent.com/... is not a normal webpage and it’s delivered inside a sandboxed iframe by GitHub. This means executing JavaScript from bookmarklets will not work on those pages.
To provide another means of opening sandboxed webpages, you can install the open-in-uxntal chrome extension via chrome://extensions "Load unpacked" button and pointing to the open-in-uxntal folder. The extension exposes a new right click context menu on the webpage for Open in uxntal.
You can just prefix any url with uxntal:// and it should work. Extensions and other things constructing a custom url should use open and url encode so that urls are not invalid and munged when parsed. The simple prefix is for the user without the extension or bookmarklet installed. Other functionality such as selection of asm/emu/pre may be added in the future and controlled via variables in the preferred open encoded form.
uxntal://open?url=ENC or uxntal://open/?url=ENC
multiple query params (...&url=...)
percent-encoded full URLs after the scheme
over-slashed forms (https///, https//, etc.)
Using the extension and the bookmarklet, you will find a chrome dialog pop that asks if you want to run uxntal.exe to open an application. Using the bookmarklet you sometimes have the option to allow always; the extension does not provide this option so you always have a second click to acknowledge the website opening the application.
The protocol handler now has a provider abstraction over Github/Codeberg/Sourcehut urls; this means that the bookmarklet will work on view/log/blame pages on these websites. Additionally, the downloader now parses and downloads all the includes.
For example uxntal uxntal://https://git.sr.ht/~rabbits/left/tree/main/item/src/left.tal, which is a project with a few includes, runs fine.
If you are often viewing code from a site like github, using the bookmarklet on a view/blame/history page instead of the raw allows you to use the protocol without the permission dialog being raised. It's possible uxntal.exe could register a NativeMessagingHosts endpoint so that the chrome extension isn't using the protocol handler but instead invoke chrome.runtime.sendNativeMessage to side step the additional chrome dialog.
uxntal:variables:key^^value:// Protocol Handler Variable Support
The protocol handler supports passing variables and flags directly in the protocol portion of URL using key-value pairs. These are used to select emulator or pass options.
Variables are specified separated by colons (:). Key-value pairs use either ^ or ^^ as separators.
cardinal-gui supports the --widget flag, which turns on transparency for white pixels, disables window decorations, enables ctrl+alt+click-and-drag to move the window, and sets the window always-on-top by default. If you want to disable always-on-top while using widget mode, pass ontop^false in the URL or use --ontop=false on the CLI.
uxntal:widget://https://wiki.xxiivv.com/etc/catclock.tal.txt will open in cardinal-gui in --widget mode. catclock will show in a transparent window with no application decorations and will be always-on-top unless you specify ontop^false.
In order to support different emulators, you can pass an emu variable, which currently supports buxn,cuxn,uxnemu emulators if they are within the PATH.
uxntal:emu^^buxn://https://wiki.xxiivv.com/etc/catclock.tal.txt will open in buxn-gui
You can use either ^ or ^^ as a separator. Both are supported and percent-encoded forms (e.g., %5E, %5E%5E) are also decoded automatically.
The reason for both ^ and ^^ is that on windows, you must escape ^ with another ^, so if you want a string that can be pasted in cmd.exe; use the double ^^ form.
Protocol Format
URLs are parsed as:
uxntal:var1:var2^val2:var3^^val3://actual_url
- Variables are separated by
: - Key-value pairs use
^or^^as separators (double^^for Windows shell escaping) - The actual URL is after the
://
Supported File Extensions
The protocol handler supports the following file extensions for remote and local files:
.tal/.tal.txt— TAL source files (assembled to .rom on the fly).rom— Binary UXN ROM files (used as-is).rom.txt— Hex-encoded ROM files (automatically converted to binary .rom before use).orca— Orca pattern files (run with canonical orca ROM, not assembled as TAL)
When you provide a URL or file ending in .rom.txt, the handler will automatically fetch and convert the hex text to a binary .rom file using the same logic as xxd -r -p. This allows you to share ROMs as plain text for easy inspection, versioning, and diffing, while still running them directly via the protocol.
Orca Mode (.orca files)
The protocol handler supports .orca files, which are not assembled as TAL but instead are run directly with the canonical orca ROM. When you provide a URL or file ending in .orca, the handler will:
- Download and cache the
.orcafile if remote. - Launch the emulator with the canonical orca ROM and the
.orcafile as arguments. - Never assemble
.orcafiles as TAL or treat them as source code.
This ensures .orca files are always run in the correct environment, matching the canonical orca UXN experience.
Example:
uxntal://https://git.sr.ht/~rabbits/orca-examples/tree/master/item/basics/u.orca
This will launch the canonical orca ROM with the specified .orca file in widget mode. You can always change the emu to run it in your preferred emulator.
Protocol Section Variables
| Name | Type | Description | Example |
|---|---|---|---|
transparent |
String | Transparent color for widget/background (hex RGB, e.g. ffffff for white) | transparent^ff00ff |
scale |
Float | Scale factor for the window (float) | scale^2.0 |
fit |
String | Fit mode for ROM display (none, contain, cover, stretch) | fit^cover |
timeout |
Float | Timeout in seconds before the emulator exits (alias: t) | timeout^60 |
t |
Float | Timeout in seconds before the emulator exits (alias for timeout) | t^60 |
emu |
Enum (buxn, cuxn, uxn) | Select emulator backend | emu^^buxn |
widget |
Bool | Enable widget mode (transparent, no decorations, always-on-top) | widget |
ontop |
Bool | Control always-on-top (true/false) | ontop^false |
debug |
Bool | Enable debug console (Windows only) | debug |
efx |
String | Effect name or identifier for emulator (string) | efx^invert |
efxmode |
String | Effect mode for emulator (string) | efxmode^blend |
orca |
Bool | Orca mode: run the orca ROM with the given .orca file. Automatically set if the URL ends with .orca. | orca |
basic |
Bool | Basic mode: run the basic ROM with the given .bas file. Automatically set if the URL ends with .bas. | basic |
x |
String | Window X position (pixels or percent or complex) | x^100 |
y |
String | Window Y position (pixels or percent or complex) | y^100 |
w |
String | Window width (pixels or percent or complex) | w^800 |
h |
String | Window height (pixels or percent or complex) | h^600 |
Bang Query Variables
| Name | Type | Description | Example |
|---|---|---|---|
fit |
Enum (none, contain, cover, stretch) | Fit mode for ROM display (none, contain, cover, stretch) | !fit=cover |
timeout |
Float | Timeout in seconds before the emulator exits (alias: t) | !timeout=60 |
t |
Float | Timeout in seconds before the emulator exits (alias for timeout) | !t=60 |
x |
String | Window X position (pixels or percent or complex) | !x=100 |
y |
String | Window Y position (pixels or percent or complex) | !y=100 |
w |
String | Window width (pixels or percent or complex) | !w=800 |
h |
String | Window height (pixels or percent or complex) | !h=600 |
arg1 |
String | First argument to pass to the emulator | !arg1=somefile.input |
stdin |
String | Data to pipe to emulator stdin (for batch-mode input, e.g. BASIC ROMs) | !stdin=RUN%0A |
Emulator Compatibility Matrix
This table shows which protocol/bang variables affect the command-line arguments for each supported emulator. An X means the variable is mapped to CLI args for that emulator.
| Variable | buxn | uxn | cuxn | Example | Type |
|---|---|---|---|---|---|
transparent |
X | transparent^ff00ff | proto | ||
scale |
X | scale^2.0 | proto | ||
fit/!fit |
X | fit^cover | both | ||
timeout/!timeout |
X | timeout^60 | both | ||
t/!t |
X | t^60 | both | ||
emu |
X | X | X | emu^^buxn | proto |
widget |
X | widget | proto | ||
ontop |
X | ontop^false | proto | ||
debug |
X | debug | proto | ||
efx |
X | efx^invert | proto | ||
efxmode |
X | efxmode^blend | proto | ||
orca |
X | X | X | orca | proto |
basic |
basic | proto | |||
x/!x |
X | x^100 | both | ||
y/!y |
X | y^100 | both | ||
w/!w |
X | w^800 | both | ||
h/!h |
X | h^600 | both | ||
!arg1 |
X | X | X | !arg1=somefile.input | bang |
!stdin |
X | X | X | !stdin=RUN%0A | bang |
Note: If both a protocol variable (e.g. x) and a bang variable (e.g. !x) are provided, the protocol variable typically takes precedence and overrides the bang variable.
Examples
uxntal:emu^uxn://https://wiki.xxiivv.com/etc/catclock.tal.txtlaunches catclock in theuxnemuemulator.uxntal:emu^buxn://https://wiki.xxiivv.com/etc/catclock.tal.txtlaunches catclock in thebuxn-guiemulator.uxntal:widget://https://wiki.xxiivv.com/etc/catclock.tal.txtpasses the--widgetflag to the emulator. (cardinal-gui is the only emu that supports this flag currently)uxntal:widget:ontop^false://https://wiki.xxiivv.com/etc/catclock.tal.txtpasses the--widgetflag but disables always-on-top, showing widget mode without ontop.uxntal:widget:debug://https://wiki.xxiivv.com/etc/cccc.tal.txtopens cccc in widget mode with debug console enabled. (windows only)
You might create multiple bookmarklets to launch urls in the emulator and with the settings you desire. Right now, the variables are restricted to widget,debug,ontop and emu to limit arbitrary input on emu invocation.
Git Repository Support
The protocol handler supports direct git repository cloning and file access using git@ URLs. This allows you to run TAL files with supporting files directly from git repositories.
Supported Git URL Formats
- SSH Format:
uxntal://git@host:owner/repo/tree/branch/path/file.tal - HTTPS Format:
uxntal://git@https://host/owner/repo/blob/branch/path/file.tal - Git .git Format:
uxntal://git@host:owner/repo.git/path/file.tal
Supported Git Providers
- GitHub:
git@github.com:orgit@https://github.com/ - SourceHut:
git@git.sr.ht:orgit@https://git.sr.ht/ - Codeberg:
git@https://codeberg.org/(HTTPS only, SSH not supported)
How Git Integration Works
When you use a git@ URL, the protocol handler will:
- Parse the URL to extract repository information (host, owner, repo, branch, file path)
- Clone or update the repository to a local cache directory
- Checkout the specified branch (defaults to
mainif not specified)
Git URL Examples
# GitHub SSH format
# GitHub HTTPS format
# GitHub .git format
# SourceHut SSH format
# SourceHut HTTPS format
# Codeberg HTTPS format
Benefits of Git Integration
- Supporting files:
git@urls will include supporting files that would not ordinarily come down based on simple tal include resolution.
Cache Location
Git repositories and downloads are cached in your local uxntal cache directory:
- Windows:
%USERPROFILE%\.uxntal\roms\ - macOS/Linux:
~/.uxntal/roms/
Each repository gets its own hash-based subdirectory for isolation.
Warning
A single click protocol handler that assembles and runs arbitrary code is a dangerous activity. uxntal protocol handler 0.1.18 and earlier had a shell exploit that could allow someone to craft a url/website which could run arbitrary code on your machine. This specific shell exploit concern has been addressed in 0.2.0 but similiar issues may develop or be uncovered.
uxntal protocol is for recreational development and might represent a risk to your data if abused by others. Consider --register at the start of your activities and then --unregister when you are done; or you can assume others aren't crafting uxntal urls to do bad things and enjoy the protocol. I hope it is used for good fun.
This disclaimer is here to educate users on the security concerns involved, to request additional eyes for security, and to remind the user to apply upgrades as they become available so that any new security concerns found can be patched.