ScreenMode Preferences on a Workbench screen in WinUAE, a UAE row selected and 640 by 480 typed into the size fields, captured by AmiPilot.

Component · September 2026

AmiPilot

The eyes. What AmiPilot is, how it lets a script inside a 1992 computer press Save and read back what happened, what it proves about this disk on every restart, and the four things it cannot reach.

Everything else on this bench is a file copied onto a disk before the Amiga boots. That gets you a disk that ought to work. It does not tell you that it does, and the Amiga has a long history of disks that ought to work: a preference file in the wrong version, a monitor for the wrong card, a palette that reaches four pens and not eight. For twenty years the check has been a person looking at the screen. Intune and Jamf did not just push the files to the laptop; they reported back. That is the missing half.

AmiPilot is the report-back. It is two programs. One runs on the Amiga, a commodity called AmiPilotServer, which walks the operating system’s own list of screens, windows and gadgets and can act on them with real synthesised input: click this button, type into that string gadget, pick that menu item, drag this window. The other runs on the host, a Python client, which talks to the server over a serial link or TCP and asks it questions. Find me the window titled ScreenMode Preferences. Find the gadget labelled Width. What does it say? Press Use. Give me a picture of the screen. Selenium, for a machine that predates the web.

Not by pixels. By asking the operating system what it thinks is on the screen, then acting on that.

The distinction is the whole value. A screenshot can tell you a window is open; it cannot tell you the Width field reads 640, and it certainly cannot press the button. AmiPilot reads the number and presses the button, and the picture at the top of this page is one it took of itself doing so, early on. The project is published on GitHub under the name sidick, at version 1.1 as this is written, and it runs on anything from AmigaOS 2.04 on a plain 68000 upward. It also carries a file API, so the host can pull a preference file off the running machine or push one on, and an ARexx port, so Amiga programs can drive it from inside.

A freshly booted 640 by 256 chipset screen with Scalos open as a small window, captured during an acceptance run.
The first thing an acceptance run captures: the machine as it booted, before anything is clicked. 640 by 256 because the graphics card is not configured yet, and Scalos as a window rather than a backdrop, which is the fault this capture is evidence of.
One icon under four palette configurations, cropped from four separate captures.
Four clean restarts of WinUAE, one drawer opened by AmiPilot each time, one icon cropped from each capture. The histogram of each crop is the verdict.

How it is wired in

On this disk the server is installed by a script like everything else, and started from S:User-Startup ten seconds after Workbench so it never delays the boot. It talks over the Amiga’s serial port, which WinUAE bridges to a TCP socket on the Windows host; the emulator’s network-card emulation was tried first and was not reliable for a program that listens rather than connects. There is a timing rule: if the host connects the instant WinUAE starts, the socket is up before the server has opened serial.device, and the first command vanishes. The scripts wait for the guest to answer. By hand, wait about twenty-five seconds.

With that in place, a check of the disk is a script and not a person. Quit WinUAE through its own control pipe so the hardfile is flushed, start it again, wait for the server, and then ask: is there a window with the Workbench title, or did Scalos come up as the backdrop with no titled root window at all? Pull SYS:Disk.info and SYS:Trashcan.info off the disk and decode them: do they carry NewIcon data? Capture the emulator’s client area and count the colours. Write a report with a single ok in it. If a change is judged by that report and not by a glance, a fix that only worked until the next boot cannot pass.

A Windows desktop with WinUAE Properties open and, in front, a small WinUAE window showing a red Software Failure box.
A capture from the Windows side, mid-experiment: the guru meditation that ended one run. When the Amiga is down, AmiPilot is down with it, and the host screenshot is the only witness.

What it cannot reach

Four things, each of which shaped a script. MUI windows are, to the operating system, one gadget with everything painted inside, so AmiPilot can open MUI Preferences and cannot press anything in it; the Scalos palette file was written from the Scalos source instead of read back from a Save. WHDLoad pauses the operating system when a game starts, and the server with it, so a running game can only be photographed from outside. A Scalos backdrop has no window title to address, so drawers are opened through Scalos’s own opendrawer tool rather than by double-click. And the MiSTer has no serial bridge and no pipe, so nothing on the board can be driven at all; everything is proven in WinUAE and then minted.

One smaller limit turned a script inside out. The file API has an upload cap, and a game icon with its NewIcon merged in is over it. So instead of the host merging the icon and pushing it, the host asks AmiPilot to run the Amiga’s own copynewicon on the two files already on the disk, which produces the identical result from the other side.

Still to build

The captures that judge a drawer are taken from Windows, of the emulator’s window; AmiPilot’s own screen capture refuses a 640×480 screen as over its size cap, so it is not in that path. The picture that would prove a game launched does not exist yet at all. The preference-window script promised here has since been written, capture_prefs.sh, and it taught two things on its first run. Window titles must be exact; the pattern matching AmigaDOS has, #?, this version of AmiPilot does not, and a prefix is enough to pick the wrong window when Scalos and Scalos Palette are both open. And menu items are picked by position, not by name: pass a name and you get the first item of the first menu, which is Open, and a file requester you did not ask for.

What AmiPilot took over

This ledger is different from the others. Nothing on this page is a step of the guide; it is the checking the guide never had. Each row is a thing a person used to decide by looking.

  1. Automated

    Install

    Copy the server onto the disk and start it at boot.

    install_amipilot.sh --serial-only writes AmiPilotServer and AmiInspect and the delayed start line. setup_winuae.sh --amipilot does it during the build and writes the serial bridge into the .uae file. setup_amipilot_host.sh installs the pinned host client once.

  2. Automated

    The desktop

    Boot and look: did Scalos come up as the backdrop, are the icons in colour?

    verify_winuae_desktop.sh restarts the emulator cleanly, waits for the server, checks the window list for a backdrop, pulls the disk and trashcan icons and decodes them, captures and scores the screen, and writes report.json. --icon adds any icon you name; --no-scalos checks a plain Workbench; --no-restart checks the machine already running.

  3. Automated

    A drawer

    Open it and look at the icons.

    show_drawer.sh opens the drawer through opendrawer, pulls every icon in it, runs icon_report.py on each, and captures the result. This is how Eight pens was measured.

  4. Automated

    ScreenMode

    Pick the graphics-card row, Use, Save.

    In the first-boot acceptance run, run_workbench_acceptance.py opens ScreenMode, selects the row, reads Width and Height back and presses Use, capturing at each stage; run_interactive_winuae_acceptance.sh launches it in a Windows session that can actually see the emulator, because one started over ssh cannot.

  5. Automated

    A template

    Work out a preference file’s format from documentation.

    Press Save in the real editor with AmiPilot, pull the file it wrote, and use those bytes as the template the host writes from. write_palette_prefs.py was made this way, and the saved file is kept as a test fixture so the byte-for-byte claim is checked on every run. The MiSTer screen mode took the same approach without AmiPilot: chosen by hand on the board, saved, and read back off the card.

  6. Automated

    Icons on a live disk

    Fix a RomIcon without taking the disk offline.

    whdload_newicon_guest.py has the server run the guest’s copynewicon for each game, because the merged icon is over the upload cap.

  7. Automated

    A preferences window

    Double-click the editor, look at it, press Cancel.

    capture_prefs.sh starts the editor the way Workbench would, waits for its exact title, reports the window’s position and size so the Windows capture can be cropped to it, and quits it through its own Project menu, looked up by name and picked by position. It took the pictures on the MUI, ClassAct, NewIcons and Scalos pages. NewIcons is the exception: no menu, so it opens and captures but does not close.

  8. By hand

    A game

    Start it and see whether it plays.

    Still a person. The capture from outside the Amiga that would prove a launch is not built.

  9. By hand

    The board

    Boot the MiSTer and look at the television.

    Still a person. There is no AmiPilot path to the Minimig core.

AmiPilot is sidick/amipilot, with its documentation at sidick.github.io/amipilot. The scripts that use it are in amiga-utils. The words are ours.