Can I use a TV for a computer monitor? Yes, and plugging it in quietly resizes the overlay window every app on your PC is drawing.
The cable advice is fine. HDMI 2.1, 4:4:4 chroma, game mode, refresh rate, input lag. All written. The part that lives one layer below, that nobody on the first page of Google touches, is what happens to the virtual-screen bounding box the moment the TV becomes display 2. Every overlay on your PC, including the one Terminator paints for each automation step, sizes itself against that box. So the TV does not just show more pixels. It quietly joins the status UI of every tool already running.
Virtual screen, before and after the TV
Windows exposes four metrics that together describe the bounding rectangle of every monitor the OS can see. SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN. Plug a 4K TV to the right of a 2560x1600 laptop, and the bounding box changes like this.
The anchor fact: four GetSystemMetrics calls, one overlay, every display
Inside create_overlay_window() in crates/terminator/src/platforms/windows/action_overlay.rs, lines 287 through 291 read the virtual screen directly from Windows and pass those values to CreateWindowExW. No branching on monitor count, no special TV handling. The OS tells Terminator how big the desktop is; Terminator makes an overlay that size.
That is the entire reason the banner stretches onto the TV. It is not a multi-monitor mode. It is four Windows system metrics feeding a single WS_EX_TRANSPARENT window. Everything else in the overlay system, the cooldowns, the RAII guard, the env var, is built on top of that one geometry call.
Watch the overlay follow the TV in
Four-frame walkthrough of what happens between “you plug in the TV” and “Terminator's status banner is painting across two displays.”
From HDMI-in to ambient dashboard
Step 1. One display, everything normal
SM_CXVIRTUALSCREEN returns the laptop's width (2560). The action overlay paints a 2560x1600 rectangle across the laptop panel. Every click shows a status banner. Everything works the same as always.
Every automation step flows through the same overlay HWND
Six concrete things the overlay gives you on a TV
All of this is in one file: crates/terminator/src/platforms/ windows/action_overlay.rs. Grep for any of these names in a fresh clone of the repo and the implementation is right there.
One overlay window, N displays
The action overlay is a single HWND sized by (SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN). Add a TV, and that rectangle grows to include it. Remove the TV, it shrinks back. No per-monitor bookkeeping.
Click-through by design
WS_EX_TRANSPARENT + WS_EX_LAYERED + WS_EX_NOACTIVATE. The overlay is visible on the TV but cannot intercept a click anywhere, so your hands on the laptop stay in control even when the overlay is painting across both screens.
Cooldowns tuned for TV refresh
OVERLAY_CHANGE_COOLDOWN_MS = 100, MINIMUM_DISPLAY_MS = 300. Those two constants stop the banner from strobing when the automation fires many actions per second, which matters on a 60 Hz TV further away from your eyes.
One env var to opt out
TERMINATOR_ACTION_OVERLAY=0 disables the overlay globally. Use it when the TV is showing a movie, a Figma mirror, or a browser window you are screen sharing. The automation still runs; the status banner just stops drawing.
Recording-aware highlighter
When you record a workflow across laptop + TV, set_recording_mode(true) in highlighting.rs tells the per-element highlighter to stop calling scroll_into_view, so the recording does not capture spurious scroll events the user did not actually do.
RAII guard around every action
ActionOverlayGuard wraps each click, type, and press_key. Overlay shows on .new(), hides on drop. Even if the automation panics mid-step, Drop runs and the overlay goes away. The TV never gets stuck with a stale banner.
“Terminator is an open-source desktop automation framework. Every file and line number on this page is grep-able in a fresh clone of mediar-ai/terminator.”
github.com/mediar-ai/terminator
Two commands: overlay on, overlay off
Same automation script. First invocation paints the status banner across laptop + TV. Second invocation runs silently because TERMINATOR_ACTION_OVERLAY=0 flips 0 atomic bool in process memory.
What it prints when you actually run it
Two monitors listed, cx=6400 from GetSystemMetrics, one CreateWindowExW call sized to that. This is the entire round-trip on a laptop plus 4K TV setup.
How to set this up in practice
Five steps from a cold laptop to a TV showing automation feedback in real time. None of them require recompiling Terminator.
1. Plug the TV into HDMI, extend the desktop
Windows renumbers monitors immediately; no reboot needed. In Display Settings, pick Extend (not Duplicate). The TV becomes display 2 with its own resolution and scale factor.
2. Verify the virtual screen grew
Run GetSystemMetrics(SM_CXVIRTUALSCREEN) (system metric index 78) and SM_CYVIRTUALSCREEN (79). On a laptop alone you will see your laptop width; after plugging in a 4K TV to the right, expect 2560 + 3840 = 6400 as the new width.
3. Run any Terminator flow
Every click, type, and press_key call goes through show_action_overlay(), which spawns a single full-virtual-screen overlay window. You will now see the status banner span both displays without any configuration.
4. Decide: feature or nuisance
If the TV is your ambient dashboard, leave it on. If the TV is for video, streaming, or a mirrored presentation, set TERMINATOR_ACTION_OVERLAY=0 in the environment before launching the automation.
5. Recording a workflow? Flip the recording mode flag
set_recording_mode(true) in highlighting.rs stops the per-element highlighter from triggering scroll_into_view. Without that flag, a TV-as-display-2 workflow picks up scroll events the user did not make, and replay drifts.
Naive full-screen overlay vs virtual-screen-aware
Most tools that draw a status overlay bind to the primary monitor and ignore additional displays. Terminator sizes itself to the bounding box of every display at once, then uses WS_EX_TRANSPARENT so the overlay stays out of the way.
| Feature | Naive overlay | Terminator |
|---|---|---|
| Overlay placement when TV is plugged in | Bound to primary monitor only, TV shows nothing | Window uses SM_CXVIRTUALSCREEN, auto-spans both displays |
| User clicks on the TV while overlay is up | Overlay eats the click, user gets a weird dead zone | WS_EX_TRANSPARENT, input passes through on every display |
| Turning the overlay off while watching TV | Recompile or edit a config file | TERMINATOR_ACTION_OVERLAY=0 env var (action_overlay.rs:38) |
| Overlay flashes every frame during a long automation | Visible flicker on the TV as it redraws | OVERLAY_CHANGE_COOLDOWN_MS=100 + MINIMUM_DISPLAY_MS=300 |
| Recording a workflow that uses the TV as display 2 | Highlight triggers scroll_into_view, pollutes the recording | set_recording_mode(true) disables scroll during highlights |
| Highlight rectangle on a TV-side element | Hardcoded to primary monitor rect | Per-element bounds resolved via element.monitor().bounds |
When to set TERMINATOR_ACTION_OVERLAY=0
Green checks are cases to turn the overlay off. Empty circles are cases to leave it on. Pick by the intent for the TV, not by reflex.
Disable the overlay in these situations
- TV is for watching video while automation runs in the background
- TV is mirroring a presentation where a status banner would be distracting
- Screen sharing the whole desktop and you do not want 'Clicking X' on the call
- TV is an ambient dashboard and you WANT the readout (leave the env var unset)
- Recording a workflow and every visual artifact matters (leave it on, use recording mode instead)
The unintended good thing: TV as an ambient automation readout
The cable-advice articles treat a TV-as-monitor as a compromise: bigger pixels, more distance, probably OK for casual use. That framing misses the shape of how people actually use a TV at a desk. A TV is usually off to the side, a little further away, easier to glance at than to focus on. That is exactly the ergonomics of a status display.
Terminator's action overlay hits that ergonomics on accident. Because the banner is already as big as the virtual screen, the TV portion of it becomes a giant readout of what your automation is currently doing. “Clicking Chrome->Extensions.” “Typing on email field.” Legible from the couch, invisible to the automation itself (the cursor never leaves the laptop).
Terminator is a developer framework for desktop automation, not a consumer app. It gives existing AI coding assistants the ability to control your whole OS (not just write code), which is exactly the shape of workload where you want a second-screen status readout anyway.
Related flags and constants in the overlay path
One env var, two cooldown constants, one recording-mode flag, one RAII guard. Every name here resolves to a real line in the open-source repo.
See it on your own TV
Clone Terminator, plug in a TV, run any automation script. The status banner will show up on both displays without any multi-monitor code. To opt out, set TERMINATOR_ACTION_OVERLAY=0 before launch. The file lives at crates/terminator/src/platforms/windows/action_overlay.rs, 620 lines total.
Open mediar-ai/terminator on GitHub →Frequently asked questions
Can I use a TV for a computer monitor at all?
Yes. Any modern TV with an HDMI input works as a display. Windows and macOS treat it as monitor 2 the moment you extend the desktop onto it. The SERP answer stops there, which is fine for most people. The part that matters for anyone running automation software on the PC is that plugging the TV in also changes what Windows reports for the virtual screen bounding box (SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN), and any overlay or full-screen tool that sizes itself by those metrics will now extend onto the TV.
What is the anchor fact nobody else writes about?
Terminator's action overlay window is created at crates/terminator/src/platforms/windows/action_overlay.rs lines 287 through 291 by calling GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), then passing those four values to CreateWindowExW with the WS_EX_TRANSPARENT flag. The overlay is one HWND that covers every display the OS can see. Plug in a 4K TV to the right of a 2560-wide laptop and SM_CXVIRTUALSCREEN returns 6400. The overlay HWND is now 6400 pixels wide. Running Grep on the open-source repo reproduces this verbatim.
Why does Terminator even draw an overlay in the first place?
So a human glancing at the screen can tell what the AI agent is currently doing. The overlay says things like 'Clicking Chrome -> Subscribe' or 'Typing on email field'. Each action method (UIElement.click, UIElement.type_text, UIElement.press_key in element.rs) wraps itself in an ActionOverlayGuard RAII type defined at action_overlay.rs line 242. The guard calls show_action_overlay in its constructor and hide_action_overlay in its Drop impl, so the banner is always in sync with whatever step is running. On a single display this is a small status bar. With a TV as display 2, the same status bar extends onto the TV, which makes it a perfectly readable dashboard from further away.
How do I turn the overlay off when the TV is showing a movie?
Set the environment variable TERMINATOR_ACTION_OVERLAY=0 (or 'false' or 'off', all case-insensitive) before launching your automation. The check lives at action_overlay.rs line 38. When the var is set, ACTION_OVERLAY_ENABLED flips to false, show_action_overlay becomes a no-op, and nothing paints on either display. Your automation still runs identically, you just lose the status banner. On Windows PowerShell: $env:TERMINATOR_ACTION_OVERLAY='0'; python run.py. On Linux/macOS: TERMINATOR_ACTION_OVERLAY=0 python run.py.
Does the overlay block me from clicking things on the TV?
No. The overlay window is created with WS_EX_TRANSPARENT in its extended style flags, which means every mouse event passes through to whatever is behind it. It is also created with WS_EX_NOACTIVATE, so it never steals focus. You can keep working on the laptop or interact with the TV as a touch display (if it is one) while the banner is painting across both. The overlay is strictly cosmetic output, not input capture.
What about flicker if the automation runs actions very fast?
Two constants in action_overlay.rs handle that. OVERLAY_CHANGE_COOLDOWN_MS is 100 milliseconds, so if two actions fire within 100ms of each other, the second one does not trigger a fresh show/hide cycle. MINIMUM_DISPLAY_MS is 300 milliseconds, so once the overlay is visible it stays visible for at least that long even if the action completes sooner. Together those mean a burst of fast clicks shows up as a continuous status banner on the TV, not a strobe.
I want to record a workflow that uses the TV as display 2. Anything to watch out for?
Yes. The per-element highlighter in crates/terminator/src/platforms/windows/highlighting.rs will by default call scroll_into_view on whatever it is about to highlight, to make the highlight visible. During a recording that is exactly what you do not want, because it creates a synthetic scroll event that was not part of the user's real workflow. Call set_recording_mode(true) (highlighting.rs line 60) before you start capturing. It flips a global AtomicBool that the highlight path reads, and scroll_into_view is skipped for the duration. Call set_recording_mode(false) when you are done.
Does this work the same on macOS with a TV as a second display?
The overall story is the same, but the concrete metric names differ. macOS reports the equivalent bounding box through NSScreen.screens.reduce over the .frame property, not GetSystemMetrics. Terminator's macOS engine does not ship the same SM_CXVIRTUALSCREEN-style action overlay today (action_overlay.rs is Windows-specific; it sits in src/platforms/windows/). The element highlighter has a cross-platform path, but the full-screen banner is Windows-only at the moment. On macOS you still get per-monitor screenshots via the capture_monitor_by_id path described in the companion guide.
Is this overlay related to the Monitor struct in lib.rs?
They are complementary. The Monitor struct at crates/terminator/src/lib.rs line 274 is the read side: it tells your automation code what displays exist, where they are, and at what scale factor. The action overlay in action_overlay.rs is the write side: it uses the OS-level virtual screen metrics to draw visible feedback across every display, no Monitor struct required. You can run one without the other, or combine them (for example: enumerate monitors, decide the TV is display 2, then set TERMINATOR_ACTION_OVERLAY=0 if the TV is is_primary=false and you know it is being used for video).
How is this different from just resizing my taskbar or wallpaper across monitors?
Taskbar and wallpaper extension are OS-level affordances: Windows takes care of them, and every app sees them passively. The action overlay is app-level: it is drawn by Terminator specifically because Terminator wants to give the user a live status readout. The reason it stretches onto a TV plugged into the PC is that Terminator sizes its overlay window by the exact same virtual-screen metrics the OS uses, so when the OS says 'the desktop is now 6400 by 2160', the overlay says yes to that without any special-case code. This is why it just works when you plug in a TV and just stops working (correctly) when you unplug it.