ZwiftScripts

March 8, 2026 ยท View on GitHub

A repo for holding various Zwift scripts, mods, etc

The repo now includes a modernized Zwift session orchestrator with:

  • Preflight validation (mandatory vs optional dependencies)
  • Timeouts everywhere (no infinite hangs)
  • try/finally cleanup (primary display, transparency, PowerToys Awake)
  • Structured logging (transcript; optional JSONL)
  • OBS control via obs-websocket (optional) (no focus/SendKeys)

Files

  • Entrypoint: MonitorZwift.ps1
  • Config: MonitorZwift.config.json
  • Module: modules/ZwiftScripts.Automation/
  • Logs: ./logs/

Run

cd path\to\ZwiftScripts
.\MonitorZwift.ps1

Configuration notes

  • All display indices in MonitorZwift.config.json are 0-based.
    • Example: ZwiftDisplayIndex: 3 means the 4th Windows display.
  • OBS WebSocket (OBS 28+):
    1. Enable Tools > obs-websocket Settings > Enable WebSocket server
    2. Set OBS.WebSocket.Enabled = true
    3. Set host/port/password in the config

Legacy

MonitorZwift-v2.ps1 remains in the repo as the legacy all-in-one script.

ActionLint Dependency Review Deploy static content to Pages GitHub Pages - Generate XML sitemap Greetings Labeler Lint Code Base Mark stale issues and pull requests Microsoft Defender for DevOps OSSAR OSV-Scanner pages-build-deployment

Alt

## File List

# Here is a list of files included in this repository:

  • .editorconfig
  • .gitignore
  • .hintrc
  • .jsbeautifyrc
  • .jscsrc
  • .pre-commit-config.yaml
  • .pre-commit-hooks.yaml
  • .prettierignore
  • .prettierrc
  • .stylelintrc.json
  • .vale.ini
  • CNAME
  • LaunchZwift.ps1
  • MonitorZwift-v2.md
  • MonitorZwift-v2.ps1
  • MonitorZwift-v2.ps1 - Shortcut.lnk
  • MonitorZwift.ps1
  • MoveZwiftCleanPhotos.ps1
  • README.md
  • SetPrimaryDefault.ps1
  • SetPrimaryZwift.ps1
  • Zwift-Bike-Combos.xlsx
  • Zwift-Setup.lnk
  • ZwiftSetup.lnk
  • file_list.md
  • filelist.html
  • filelist.md
  • sitemap.xml
  • test.ps1
  • CSS

  • sauce4zwift-mod-tippy/pages/css/DSNotes.css
  • sauce4zwift-mod-tippy/pages/css/ui.css
  • JavaScript

  • .eslintrc.js
  • YAML

  • .github/dependabot.yml
  • .github/labeler.yml
  • .github/workflows/ActionLint.yml
  • `; break; case 'file-list-2': file_list_html = ``; break; case 'file-list-3': file_list_html = ``; break; } placeholder.innerHTML = file_list_html; observer.unobserve(placeholder); console.log(`Loaded content for ${contentId}`); } }); }, { rootMargin: rootMargin, threshold: threshold });
        lazyLoadElements.forEach(element => {
            element.style.marginTop = '-17px';
            observer.observe(element);
        });
    } else {
        lazyLoadElements.forEach(placeholder => {
            let contentId = placeholder.dataset.content;
            let file_list_html = '';
            switch(contentId) {
                case 'file-list-1':
                    file_list_html = `<ul><h2 style="color: #f1841b;">Repo Root</h2>
    
  • .black
  • .editorconfig
  • .gitignore
  • .hintrc
  • .jsbeautifyrc
  • .jscsrc
  • .pre-commit-config.yaml
  • .pre-commit-hooks.yaml
  • .prettierignore
  • .prettierrc
  • .stylelintrc.json
  • .vale.ini
  • CNAME
  • LaunchZwift.ps1
  • MonitorZwift-v2.md
  • MonitorZwift-v2.ps1
  • MonitorZwift-v2.ps1 - Shortcut.lnk
  • MonitorZwift.ps1
  • MoveZwiftCleanPhotos.ps1
  • README.md
  • SetPrimaryDefault.ps1
  • SetPrimaryZwift.ps1
  • Zwift-Bike-Combos.xlsx
  • Zwift-Setup.lnk
  • ZwiftSetup.lnk
  • file_list.md
  • filelist.html
  • filelist.md
  • sitemap.xml
  • test.ps1
  • CSS

  • sauce4zwift-mod-tippy/pages/css/DSNotes.css
  • sauce4zwift-mod-tippy/pages/css/ui.css
  • JavaScript

  • .eslintrc.js
  • YAML

  • .github/dependabot.yml
  • .github/labeler.yml
  • .github/workflows/ActionLint.yml
  • `; break; case 'file-list-2': file_list_html = ``; break; case 'file-list-3': file_list_html = ``; break; } placeholder.innerHTML = file_list_html; }); } });