ScreenCloneManager.exe has two modes: a visible Spectre.Console CLI and a hidden per-user controller. launch.ps1 is only the desktop context-menu entry; lifecycle and OBS logic remain in C#.
DesktopBackground context menu
-> pwsh 7 launch.ps1
-> visible CLI
-> current-user Named Pipe
-> single controller (per-user mutex)
-> one authenticated WebSocket v5 connection to 127.0.0.1
-> existing or tool-started OBS process
-> exact source UUID + current monitor index
-> exact recorded projector HWND per stable display identity
-> WM_DISPLAYCHANGE + configurable low-frequency reconciliation (5 s default)
- Windows display identity:
QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS)plusDisplayConfigGetDeviceInfo. Only read APIs are imported. No topology setter exists in the codebase. - Source identity: OBS
sourceUuid; source name is fallback/display text only. - Projector ownership: windows newly observed after a single
OpenSourceProjectorrequest, restricted to the selected OBS PID and matched by fullscreen geometry/class/title. Stop sendsWM_CLOSEonly to recorded handles after revalidating PID. - Tool-started OBS lifecycle: only when no OBS is running, remove stale OBS 32
run_*crash sentinels, start minimized without--minimize-to-tray, wait for the normal OBS/WebSocket/source path, open and track native full-screen projectors, then hide the tool-owned editor window. Existing user-started OBS windows are untouched. - Session intent:
desiredTargetsis updated before windows are closed. The reconciliation planner therefore reopens accidental closes but not intentional stop/change operations. - OBS ownership: an existing OBS process is never closed. A tool-started OBS is normally closed only when no standard OBS output is active and it has not been adopted through an output or baseline change.
- User OBS baseline: the controller never sends set-current Program/Preview/Profile/Scene Collection requests.
clone screencontains one reference to the verified internal-display input; before creating the scene, adding that reference, or removing duplicate internal-display scene items, the active Scene Collection JSON is backed up and the result is read back. - Security: the pipe server uses
PipeOptions.CurrentUserOnly; mutex/pipe names are derived from the current SID; websocket secrets use DPAPI CurrentUser.
Display/: DisplayConfig enumeration, topology inference, stable identity and OBS monitor mapping.Obs/: one small WebSocket v5 client, typed requests, OBS configuration backup/initialization, process policy, clone-scene policy.Windows/: PID-scoped window enumeration, HWND tracking, exact close, topmost and mouse pass-through.Controller/: IPC framing, singleton host, session state, and hot-plug/accidental-close reconciliation. Terminal session loss exits quietly.Cli/: immediate target selector, one-second live status menu while open, settings, and human-readable environment checks.Configuration/andInfrastructure/: atomic config, DPAPI secret, bounded JSONL logs.
- A hidden top-level tool HWND receives
WM_DISPLAYCHANGEand requests immediate reconciliation; a configurable 5-second-default timer is a low-frequency safety net. - Saved device path is matched first, then EDID manufacturer/product/connector, then stable key.
- Each online display is remapped to the current OBS monitor list. Friendly name is weighted strongly because OBS/QScreen may use logical DPI coordinates while DisplayConfig exposes physical coordinates.
- A missing expected projector is opened once and its new HWND is recorded. Existing live tracked HWNDs are retained.
- One target offline affects only that target. If all desired targets are offline, the desired session is terminated and cannot auto-resume after controller exit.
- Per-target projector errors are stored without closing successful targets.
- OBS readiness code 207 is retried only for
GetVersionwithin a fixed deadline. Other request failures propagate. - Output status code 604 means the feature is not configured and is normalized to inactive; it is not treated as connection failure.
- Config corruption is backed up and reset. Log write failure is retained in diagnostics and does not throw into the active projector loop. Tool logs older than three days are deleted by a delayed best-effort task on interactive startup.
- No forced OBS process termination is used.