RISC OS Build EnvironmentROBE

Optional subsystems18Pyromaniac and Runtime Execution

Introduction and Overview

Some images include the RISC OS Pyromaniac runtime. When present, it allows compiled binaries and BASIC programs to be executed inside the build environment rather than only through the remote build service. This chapter explains when that runtime is available, what commands it enables, and where its limitations begin.

Runtime availability and choosing tools

When Pyromaniac is present

Pyromaniac support is optional and depends on the image variant in use. When it is present, runtime tools such as riscos-run, riscos-gos, and riscos-basic are available for local execution workflows.

The grouped command reference for these tools and the lower-level pyro, pyro-server, and pyro-client commands is in Pyromaniac and runtime tools.

Choosing the right runtime tool

The easiest way to choose between the commands is to think about how much state you want to keep. Use riscos-run for one command in a clean instance, riscos-basic for an interactive or single-shot BASIC session, and riscos-gos for a manual Supervisor prompt.

When several RISC OS commands need to share one live environment, move to pyro-server and pyro-client. When you need explicit control over configuration files, module loading, debug options, or inspection switches, use pyro directly.

Running programs and sessions

Running one command in a fresh instance

riscos-run starts a clean RISC OS instance and runs the supplied RISC OS command. The command string must use RISC OS command and filename conventions. Output and return codes are passed back to the host-side shell in the expected way.

A typical local execution command is:

riscos-run aif32.main
main 0.01 (21 Jun 2026)
Syntax: *main

riscos-run expects to be invoked from somewhere within the project tree mounted at /riscos-source; it maps that tree to the RISC OS filesystem itself, so it refuses to run outside it.

Interactive BASIC and Supervisor sessions

riscos-gos starts an interactive RISC OS Supervisor prompt. riscos-basic starts BBC BASIC interactively or can run a specified program and then exit, matching the behaviour of the RISC OS BASIC command closely enough for most development uses.

To run a BASIC program and exit again:

riscos-basic -quit MyProg
Hello from BASIC

Persistent server sessions

When a clean one-shot session is not enough, pyro-server can keep one Pyromaniac instance alive while pyro-client sends commands into it. This lets loaded modules, current directory changes, variables, and other RISC OS state persist across more than one command.

This is useful when a build or test workflow needs to interleave host commands with repeated RISC OS commands without paying the startup cost each time.

pyro-server takes over the current terminal: it prints its startup banner and then drops into a host shell with the connection already configured, so pyro-client commands and ordinary host commands can be interleaved freely. Exiting that shell tears the server down. One common pattern, once inside the pyro-server shell, is:

pyro-server --load-module modules/BASIC,ffa
Pyromaniac server: RISC OS 7.82 (21 Apr 2026) [Pyromaniac 0.82.4950 on Linux/x86_64]
pyro-client "Help Modules"
...
pyro-client /MyProgram
Hello from BASIC
exit

Configuration and low-level control

Configuration files and variables

Pyromaniac can be configured on the command line with --config, --config-safe, --set-variable, and related switches, or more conveniently with a YAML configuration file passed through --config-file.

Those configuration files may define configuration settings, variables, modules, and ordered execution actions. That makes them useful for repeatable test setups, preloaded module collections, or sessions where a command and its runtime environment should be version-controlled together.

A bare pyro invocation starts with no resident modules at all, so built-in commands such as Dir or Show are not available until the configuration loads them. The simplest way to get them is modules: internal: true in the configuration file:

%YAML 1.1
---
modules:
  internal: true

variables:
  'MyVar': 'hello'

pyro --config-file mysetup.pyro --command "Show MyVar"
MyVar : hello

The wrapper commands (riscos-run, riscos-gos, riscos-basic) avoid this gap by always passing one of the environment's own configuration files under /riscos-resources/pyromaniac/, which load the internal modules and the standard ROM module set automatically.

Low-level control with pyro

The pyro command exposes the underlying Pyromaniac configuration model directly. Use it when explicit control is needed over module loading, debug settings, variables, execution actions, or configuration files rather than the simpler wrapper behaviour of riscos-run, riscos-gos, and riscos-basic.

For illustration, to load a module and run a command in one controlled startup (MyModule,ffa and *MyCommand are placeholders, replaced with a real module below). Because MyModule registers *MyCommand itself, this works even though, as noted above, a bare pyro invocation has no built-in OS commands until internal modules are loaded:

pyro --load-module MyModule,ffa --command "*MyCommand"

Verified with the real BASIC module:

pyro --load-module /riscos-resources/Install/Modules/BASIC,ffa --command "Basic -quit MyProgram"
Hello from BASIC

Rather than writing out that absolute path, the system module set shipped with the image is more conveniently reached through ROSYSMODULES, the same variable the environment's own default configuration uses to locate BASIC,ffa, SCL,ffa, FPEmulator,ffa, and Obey,ffa. Combined with --load-internal-modules, this is enough to run a BASIC program locally with one bare pyro command and no configuration file at all:

pyro --load-internal-modules --load-module $ROSYSMODULES/BASIC,ffa --command "Basic -quit MyProgram"
Hello from BASIC

This is a lower-level equivalent of what riscos-basic does automatically; reach for it when you want exact control over which modules are present, rather than the full default set the wrapper commands load.

Inspection, graphics, and limits

Inspection and debugging

The low-level pyro command also exposes inspection and debugging switches that are not surfaced directly by the simpler wrappers. Useful inspection switches include --list-swis, --list-commands, --list-modules, --list-memory, and --list-resources.

When the question is specifically which resident module handles a service call, use riscos-modservices. That command inspects the live module chain and reports the handled service numbers it can infer for each resident module, or can be filtered to one service number with -s.

Debugging is usually enabled with --debug at startup or --boot-debug after boot. Common names include start, execute, swi, trace, traceswi, traceswiargs, fsexpand, and vectors. The trace output format and watchpoint behaviour are described in Appendix X: Pyromaniac tracing.

For example (again, --load-internal-modules is needed for Help itself to be recognised under a bare pyro invocation):

pyro --load-internal-modules --debug trace,traceswiargs --command "Help Modules"
-4: SWI OS_Byte
=> r0 = &0000000e 14 op
...

Executable format recognition

Pyromaniac can also be integrated through Linux binfmt_misc (see Glossary), a kernel facility that recognises an executable by its file format and transparently invokes a registered interpreter to run it. With the hooks installed and the executable bit set, supported RISC OS binary or BASIC file formats may be executed directly from the shell. This is a convenience layer rather than the primary workflow, but it can make repeated tests simpler.

The hooks are not installed automatically when the container starts: run docker run --privileged ... install-binfmt explicitly to register them first (the --privileged flag is required because registering a binfmt_misc interpreter needs elevated kernel access).

Graphics and VNC

Graphics are supported by the Pyromaniac runtime but are not visible through a plain terminal session. To inspect graphical output, the runtime commands may be given a --vnc switch so that the session exports a VNC server, with both control and read-only passwords provided.

The host variable ROBUILD_VNC can also request VNC exposure for supported sessions.

When graphics need to be inspected, use:

riscos-run --vnc !RunImage

Limitations

When the VNC server is active, the line editor is disabled by default, the scroll wheel is unsupported, and sound is not forwarded over the VNC protocol. The runtime is therefore useful for application testing and visual checks, but it is not identical to a full native desktop machine.