The install is done and the daemon says host_connected=1. What now?
Everything below was run on a live System 7.6.1 guest in Basilisk II while this page was being written, and the two pictures are the guest’s own framebuffer — not a mock-up, not a photograph of a screen.
Two ways in, the same bridge underneath
From a shell, the control port on localhost:9001 speaks a small set of
verbs. No client library, no dependencies:
printf 'MACSTATUS\n\n' | nc -w 5 localhost 9001
printf 'DISKINFO\n\n' | nc -w 5 localhost 9001
From Claude Code, the same capabilities arrive as MCP tools — thirty of them — so you can write “build this and show me the window” and the agent picks the verbs. The tool names below are the MCP ones; the uppercase words are what goes over the wire if you prefer typing.
Neither route is privileged. The MCP server talks to the same control port you
can reach with nc.
Ask the machine about itself
DISKINFO returns every mounted volume — name, reference number, total and free
bytes — straight from the guest’s File Manager:
MeinMac -1 2 144 363 520 1 622 366 720
Unix -2 1 073 725 440 1 073 725 440
AppleBridge Kit -3 2 062 336 1 842 688
LISTDIR lists a folder with type and creator, which is what you actually need
on a Mac — a file’s type is not in its name:
AppleBridge APPL ABrg 83566
AppleBridge Welcome TEXT ABrg 0
AppleBridgeConfig APPL ABcf 15688
AppleBridgeInstaller APPL ABis 41884
AppleBridgeWatchdog APPL ABwd 8992
Both work without MPW or ToolServer. They are answered by the daemon itself, which matters more than it sounds: a guest with no development tools installed is still fully inspectable.
See the screen
mac_screenshot — or screenshot on the control port — captures the
emulated framebuffer: the daemon reads the main GDevice’s PixMap, streams
the pixels with their colour table, and the host decodes a PNG. It is not a
capture of your Mac’s screen with the emulator window in it, so overlapping
windows and window position cannot spoil it, and it works when the emulator is
not even frontmost.
Every image on this page came out of that path.
Move files, with both forks
A classic Mac file has two forks, and a transfer that keeps only the data fork
silently destroys applications, fonts and anything with resources.
mac_put_file and mac_get_file carry both, using MacBinary in transit.
Measured on the guest shown here, round-tripped host → guest → host and compared byte for byte: 4 KB at roughly 16 KiB/s, 64 KB at 138, 512 KB at 246 KiB/s. The data fork comes back identical; the resource fork comes back intact apart from the Resource Manager’s own name stamp, which it writes when it opens the file.
For text there is mac_write_file, which converts UTF-8 to MacRoman and LF to
CR on the way — a step people forget once and then debug for an hour.
Type and click
mac_type, mac_key and mac_click post into the guest’s event queue, so they
arrive at whatever application is frontmost. Modifiers work: the daemon stamps
the modifier field and holds the low-memory key map, so Command-shortcuts
reach the front application’s menu handling.
Here the host typed an address into the AppleBridge control panel in the guest — no mouse, no VNC, no remote desktop:

The clipboard is bridged too: mac_clipboard_get reads the guest’s TEXT scrap
and mac_clipboard_set replaces it, which is the shortest path for moving a
snippet in either direction.
Build and run software
This is the part the whole thing exists for. With MPW and ToolServer in the guest — both optional, both free — the host can compile.
The program below was written on macOS, in a normal editor. Then, over the bridge:
# convert to MacRoman + CR, drop into the shared folder
uv run python host/encoding_convert.py to-share bridgedemo.c
# in the guest, over the wire:
Duplicate -y Unix:bridgedemo.c :src:bridgedemo.c
SC -i :include: -model far :src:bridgedemo.c -o :obj:bridgedemo.c.o
Link -model far -o :bin:BridgeDemo :obj:bridgedemo.c.o Interface.o MacRuntime.o
SetFile -t APPL -c BDmo :bin:BridgeDemo
and then LAUNCH. Thirty seconds later the window is on the emulated screen —
and behind it, the daemon’s own console shows the whole sequence that put it
there:

One rule governs any program you build this way, and it is not stylistic:
yield. System 7 schedules cooperatively, so a program that spins in a loop
instead of calling WaitNextEvent starves the AppleBridge daemon running behind
it and takes the bridge down with it. The demo above yields every fifteen ticks.
mac_build does the whole SC → Link → Rez → SetFile sequence in one call and
verifies by the artifact rather than the status code — which matters because a
long link can return an Apple Event timeout and still have succeeded.
Lifecycle
launch_app starts an application. mac_restart_toolserver brings ToolServer
back when it has been quit — using the launch verb, so it needs no ToolServer to
do it. mac_reboot restarts the guest in-process, and mac_shutdown stops it
the way the Shutdown Manager intends.
That last one is worth its own sentence: do not kill the emulator process. An unclean stop can corrupt the guest’s disk image, and the guest will greet you on the next boot with a modal dialog that synthetic clicks cannot reach.
bridge_doctor diagnoses across layers — the launchd job, the listeners, the
emulator’s Ethernet backend, the address the guest is configured to dial — and
answers even when the host server is down.
What it cannot do
Stated plainly, because finding out by experiment costs an evening:
Menus and modal dialogs do not take synthetic clicks. Classic tracking loops
poll the hardware pointer, so mac_click reaches windows and controls but not
an open menu or a Standard File dialog. For a local emulator there are host-side
tools that drive the real pointer; for a guest on another machine, keyboard
equivalents are the reliable route — which is why the AppleBridge installer’s
own buttons answer Return.
Typing can be slow, and it depends on the target. Injected keystrokes are
delivered as the front application yields, so an application with a long
WaitNextEvent sleep receives them slowly: thirteen characters into one
particular panel took around a hundred seconds here and tripped the client
timeout. The link recovers by itself — the characters all arrive — but do not
build a tight loop on it.
Command output needs ToolServer, not MPW Shell. MPW Shell executes what you send and hands back empty replies. That is not a bug you can fix from the host; it is why ToolServer is the one worth installing.
AppleTalk is not carried on the slirp backend. No Chooser, no AFP mounts. TCP is unaffected, which is exactly how that gap disguises itself as something else.
Where to start
If the bridge is up, try this and watch the guest:
printf 'DISKINFO\n\n' | nc -w 5 localhost 9001
printf 'LISTDIR:MeinMac:\n\n' | nc -w 5 localhost 9001
printf 'screenshot\n\n' | nc -w 60 localhost 9001 > shot.b64
Then open the same machine in Claude Code and ask it to write you a program.
