From c79c4ec0a9c330914aa61d246c9c251517acbdd2 Mon Sep 17 00:00:00 2001 From: jlp-craigmorten Date: Tue, 31 Dec 2024 14:37:04 +0000 Subject: [PATCH 01/18] feat: try support sequoia vo preferences being sandboxed --- .../enableAppleScriptControlSystemDefaults.ts | 33 +++++++++++++-- src/macOS/enableDoNotDisturb.ts | 22 +++++----- src/macOS/getPlatformVersionMajor.ts | 4 ++ .../enabledDefaults.ts | 40 ++++++++++++++----- 4 files changed, 76 insertions(+), 23 deletions(-) create mode 100644 src/macOS/getPlatformVersionMajor.ts diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index 29fc4ba..b6d96aa 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -1,12 +1,37 @@ import { execSync } from "child_process"; +import { getPlatformVersionMajor } from "./getPlatformVersionMajor"; import { ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS } from "../errors"; +const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = + "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true"; + +const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = + "plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; + export function enableAppleScriptControlSystemDefaults(): void { + const platformMajor = getPlatformVersionMajor(); + + // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. + if (platformMajor < 24) { + try { + execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS); + + return; + } catch (e) { + throw new Error( + `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` + ); + } + } + + // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. try { - execSync( - "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true" - ); + execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL); + + return; } catch (e) { - throw new Error(`${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}`); + throw new Error( + `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` + ); } } diff --git a/src/macOS/enableDoNotDisturb.ts b/src/macOS/enableDoNotDisturb.ts index 97ade93..815420e 100644 --- a/src/macOS/enableDoNotDisturb.ts +++ b/src/macOS/enableDoNotDisturb.ts @@ -1,9 +1,9 @@ import { exec } from "child_process"; -import * as os from "os"; +import { promisify } from "util"; import { ERR_MACOS_FAILED_TO_ENABLE_DO_NOT_DISTURB } from "../errors"; import { runAppleScript } from "./runAppleScript"; -import { promisify } from "util"; import { retryOnError } from "./retryOnError"; +import { getPlatformVersionMajor } from "./getPlatformVersionMajor"; // REF: https://github.com/sindresorhus/do-not-disturb/issues/9 const enableFocusModeShellscript = `defaults write com.apple.ncprefs.plist dnd_prefs -data 62706C6973743030D60102030405060708080A08085B646E644D6972726F7265645F100F646E64446973706C6179536C6565705F101E72657065617465644661636574696D6543616C6C73427265616B73444E445875736572507265665E646E64446973706C61794C6F636B5F10136661636574696D6543616E427265616B444E44090808D30B0C0D070F1057656E61626C6564546461746556726561736F6E093341C2B41C4FC9D3891001080808152133545D6C828384858C9499A0A1AAACAD00000000000001010000000000000013000000000000000000000000000000AE && killall usernoted && killall ControlCenter`; @@ -88,22 +88,26 @@ my withTimeout(command, timeoutSeconds) }; export async function enableDoNotDisturb() { - const platformMajor = Number(os.version().split("Version ")[1].split(".")[0]); + const platformMajor = getPlatformVersionMajor(); try { if (platformMajor <= 20) { await promisify(exec)(enableFocusModeShellscript); + + return; } else if (platformMajor === 21) { // From MacOS 12 Monterey (Darwin 21) there is no known way to enable DND via system defaults await retryOnError(() => runAppleScript(enableFocusModeAppleScript)); - } else { - const { stdout: locale } = await promisify(exec)(getLocale); - // From MacOS 13 Ventura (Darwin 22) there is no known way to enable DND via system settings - await retryOnError(() => - runAppleScript(enableFocusModeVenturaAppleScript(locale)) - ); + return; } + + // From MacOS 13 Ventura (Darwin 22) there is no known way to enable DND via system settings + const { stdout: locale } = await promisify(exec)(getLocale); + + await retryOnError(() => + runAppleScript(enableFocusModeVenturaAppleScript(locale)) + ); } catch (e) { throw new Error( `${ERR_MACOS_FAILED_TO_ENABLE_DO_NOT_DISTURB}\n\n${e.message}` diff --git a/src/macOS/getPlatformVersionMajor.ts b/src/macOS/getPlatformVersionMajor.ts new file mode 100644 index 0000000..2c3097b --- /dev/null +++ b/src/macOS/getPlatformVersionMajor.ts @@ -0,0 +1,4 @@ +import { version } from "os"; + +export const getPlatformVersionMajor = () => + Number(version().split("Version ")[1].split(".")[0]); diff --git a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts index 92191e5..32d9ae0 100644 --- a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts +++ b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts @@ -1,16 +1,36 @@ -import { exec } from "child_process"; +import { execSync } from "child_process"; +import { getPlatformVersionMajor } from "../getPlatformVersionMajor"; const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults read com.apple.VoiceOver4/default SCREnableAppleScript"; -export async function enabledDefaults(): Promise { - return await new Promise((resolve) => { - exec(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, (err, stdout) => { - if (err) { - resolve(false); - } else { - resolve(stdout.trim() === "1"); - } +const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = + "plutil -extract SCREnableAppleScript raw -o - ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; + +export function enabledDefaults(): boolean { + const platformMajor = getPlatformVersionMajor(); + + // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. + if (platformMajor < 24) { + try { + const result = execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { + encoding: "utf8", + }); + + return result.trim() === "1"; + } catch { + return false; + } + } + + // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. + try { + const result = execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL, { + encoding: "utf8", }); - }); + + return result.trim() === "true"; + } catch { + return false; + } } From e85b356ef8e3ea0170e492dfc5d4007589548d85 Mon Sep 17 00:00:00 2001 From: jlp-craigmorten Date: Tue, 31 Dec 2024 14:41:46 +0000 Subject: [PATCH 02/18] temp: logging --- src/macOS/enableAppleScriptControlSystemDefaults.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index b6d96aa..ebd9b51 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -30,6 +30,8 @@ export function enableAppleScriptControlSystemDefaults(): void { return; } catch (e) { + console.error(e); + throw new Error( `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` ); From 08db7ae5dd663a9e91bb4e2d7e57c4939d2209a4 Mon Sep 17 00:00:00 2001 From: jlp-craigmorten Date: Tue, 31 Dec 2024 14:43:53 +0000 Subject: [PATCH 03/18] fix: utf8 encoding --- .github/workflows/resolutionFix.ts | 3 ++- src/macOS/disableDictationInputAutoEnable.ts | 7 +++++-- src/macOS/disableSplashScreenSystemDefaults.ts | 7 +++++-- src/macOS/enableAppleScriptControlSystemDefaults.ts | 4 ++-- src/macOS/updateTccDb.ts | 4 +++- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/resolutionFix.ts b/.github/workflows/resolutionFix.ts index 4c5dcee..0cbbbaa 100644 --- a/.github/workflows/resolutionFix.ts +++ b/.github/workflows/resolutionFix.ts @@ -3,7 +3,8 @@ import { execSync } from "child_process"; if (process.platform === "darwin") { try { execSync( - `"/Library/Application Support/VMware Tools/vmware-resolutionSet" 1920 1080` + `"/Library/Application Support/VMware Tools/vmware-resolutionSet" 1920 1080`, + { encoding: "utf8" } ); } catch (_) { // swallow diff --git a/src/macOS/disableDictationInputAutoEnable.ts b/src/macOS/disableDictationInputAutoEnable.ts index fee3235..e584799 100644 --- a/src/macOS/disableDictationInputAutoEnable.ts +++ b/src/macOS/disableDictationInputAutoEnable.ts @@ -4,9 +4,12 @@ import { ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS } from "../errors"; export function disableDictationInputAutoEnable(): void { try { execSync( - "defaults write com.apple.HIToolbox AppleDictationAutoEnable -bool false" + "defaults write com.apple.HIToolbox AppleDictationAutoEnable -bool false", + { encoding: "utf8" } ); } catch (e) { - throw new Error(`${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}`); + throw new Error( + `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` + ); } } diff --git a/src/macOS/disableSplashScreenSystemDefaults.ts b/src/macOS/disableSplashScreenSystemDefaults.ts index 5800be8..80ee8ff 100644 --- a/src/macOS/disableSplashScreenSystemDefaults.ts +++ b/src/macOS/disableSplashScreenSystemDefaults.ts @@ -4,9 +4,12 @@ import { ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS } from "../errors"; export function disableSplashScreenSystemDefaults(): void { try { execSync( - "defaults write com.apple.VoiceOverTraining doNotShowSplashScreen -bool true" + "defaults write com.apple.VoiceOverTraining doNotShowSplashScreen -bool true", + { encoding: "utf8" } ); } catch (e) { - throw new Error(`${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}`); + throw new Error( + `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` + ); } } diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index ebd9b51..4833d3b 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -14,7 +14,7 @@ export function enableAppleScriptControlSystemDefaults(): void { // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. if (platformMajor < 24) { try { - execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS); + execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { encoding: "utf8" }); return; } catch (e) { @@ -26,7 +26,7 @@ export function enableAppleScriptControlSystemDefaults(): void { // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. try { - execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL); + execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL, { encoding: "utf8" }); return; } catch (e) { diff --git a/src/macOS/updateTccDb.ts b/src/macOS/updateTccDb.ts index d2a7d4f..622a9a1 100644 --- a/src/macOS/updateTccDb.ts +++ b/src/macOS/updateTccDb.ts @@ -241,7 +241,9 @@ export function updateTccDb(path: string): void { });`; try { - execSync(`sqlite3 "${path}" "${query}" >/dev/null 2>&1`); + execSync(`sqlite3 "${path}" "${query}" >/dev/null 2>&1`, { + encoding: "utf8", + }); } catch (e) { throw new Error( `${ERR_MACOS_UNABLE_TO_WRITE_USER_TCC_DB}\n\n${e.message}` From 4e3595f025d9279457aaaa943d7c6b422a8ce355 Mon Sep 17 00:00:00 2001 From: jlp-craigmorten Date: Tue, 31 Dec 2024 15:05:13 +0000 Subject: [PATCH 04/18] fix: sudo? --- src/macOS/enableAppleScriptControlSystemDefaults.ts | 2 +- src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index 4833d3b..51d27ed 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -6,7 +6,7 @@ const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true"; const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = - "plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; + "sudo plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; export function enableAppleScriptControlSystemDefaults(): void { const platformMajor = getPlatformVersionMajor(); diff --git a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts index 32d9ae0..39bfd71 100644 --- a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts +++ b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts @@ -5,7 +5,7 @@ const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults read com.apple.VoiceOver4/default SCREnableAppleScript"; const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = - "plutil -extract SCREnableAppleScript raw -o - ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; + "sudo plutil -extract SCREnableAppleScript raw -o - ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; export function enabledDefaults(): boolean { const platformMajor = getPlatformVersionMajor(); From dc6d5316d0f2ddf5402a84eb02cf4de3bc27fb8b Mon Sep 17 00:00:00 2001 From: jlp-craigmorten Date: Tue, 31 Dec 2024 15:09:45 +0000 Subject: [PATCH 05/18] revert: sudo --- src/macOS/enableAppleScriptControlSystemDefaults.ts | 2 +- src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index 51d27ed..4833d3b 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -6,7 +6,7 @@ const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true"; const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = - "sudo plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; + "plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; export function enableAppleScriptControlSystemDefaults(): void { const platformMajor = getPlatformVersionMajor(); diff --git a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts index 39bfd71..32d9ae0 100644 --- a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts +++ b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts @@ -5,7 +5,7 @@ const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults read com.apple.VoiceOver4/default SCREnableAppleScript"; const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = - "sudo plutil -extract SCREnableAppleScript raw -o - ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; + "plutil -extract SCREnableAppleScript raw -o - ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; export function enabledDefaults(): boolean { const platformMajor = getPlatformVersionMajor(); From d3175be84ab442f023897ee447b97550e92ce1bc Mon Sep 17 00:00:00 2001 From: jlp-craigmorten Date: Tue, 31 Dec 2024 15:10:18 +0000 Subject: [PATCH 06/18] revert: remove temp log --- src/macOS/enableAppleScriptControlSystemDefaults.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index 4833d3b..1bffb85 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -30,8 +30,6 @@ export function enableAppleScriptControlSystemDefaults(): void { return; } catch (e) { - console.error(e); - throw new Error( `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` ); From 8d0778844a24b2c0fef4e0c895eecf3e1c0332da Mon Sep 17 00:00:00 2001 From: jlp-craigmorten Date: Tue, 31 Dec 2024 16:48:18 +0000 Subject: [PATCH 07/18] feat: separate permission checks for system defaults vs sandboxed defaults --- src/errors.ts | 2 ++ ...ableAppleScriptControlSandboxedDefaults.ts | 26 +++++++++++++++++++ .../enableAppleScriptControlSystemDefaults.ts | 21 ++++----------- src/macOS/setup.ts | 2 ++ 4 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 src/macOS/enableAppleScriptControlSandboxedDefaults.ts diff --git a/src/errors.ts b/src/errors.ts index feece95..62b3185 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -7,6 +7,8 @@ export const ERR_MACOS_UNSUPPORTED_VERSION = "Require macOS version 11 or later"; export const ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS = "Unable to update system defaults"; +export const ERR_MACOS_UNABLE_UPDATE_VOICE_OVER_SANDBOXED_DEFAULTS = + "Unable to update VoiceOver sandboxed defaults - SIP might not be disabled"; export const ERR_MACOS_UNABLE_TO_VERIFY_SIP = "Unable to verify macOS SIP status"; export const ERR_MACOS_UNABLE_TO_WRITE_DATABASE_FILE = diff --git a/src/macOS/enableAppleScriptControlSandboxedDefaults.ts b/src/macOS/enableAppleScriptControlSandboxedDefaults.ts new file mode 100644 index 0000000..c4be227 --- /dev/null +++ b/src/macOS/enableAppleScriptControlSandboxedDefaults.ts @@ -0,0 +1,26 @@ +import { execSync } from "child_process"; +import { getPlatformVersionMajor } from "./getPlatformVersionMajor"; +import { ERR_MACOS_UNABLE_UPDATE_VOICE_OVER_SANDBOXED_DEFAULTS } from "../errors"; + +const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = + "plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; + +export function enableAppleScriptControlSandboxedDefaults(): void { + const platformMajor = getPlatformVersionMajor(); + + // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. + if (platformMajor < 24) { + return; + } + + // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. + try { + execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL, { encoding: "utf8" }); + + return; + } catch (e) { + throw new Error( + `${ERR_MACOS_UNABLE_UPDATE_VOICE_OVER_SANDBOXED_DEFAULTS}\n\n${e.message}` + ); + } +} diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index 1bffb85..e6892f6 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -5,28 +5,17 @@ import { ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS } from "../errors"; const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true"; -const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = - "plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; - export function enableAppleScriptControlSystemDefaults(): void { const platformMajor = getPlatformVersionMajor(); - // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. - if (platformMajor < 24) { - try { - execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { encoding: "utf8" }); - - return; - } catch (e) { - throw new Error( - `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` - ); - } + // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. + if (platformMajor >= 24) { + return; } - // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. + // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. try { - execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL, { encoding: "utf8" }); + execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { encoding: "utf8" }); return; } catch (e) { diff --git a/src/macOS/setup.ts b/src/macOS/setup.ts index a7b44ad..35f30d4 100644 --- a/src/macOS/setup.ts +++ b/src/macOS/setup.ts @@ -3,6 +3,7 @@ import { macOSRecord } from "@guidepup/record"; import chalk from "chalk"; import { checkVersion } from "./checkVersion"; import { enableAppleScriptControlSystemDefaults } from "./enableAppleScriptControlSystemDefaults"; +import { enableAppleScriptControlSandboxedDefaults } from "./enableAppleScriptControlSandboxedDefaults"; import { disableSplashScreenSystemDefaults } from "./disableSplashScreenSystemDefaults"; import { disableDictationInputAutoEnable } from "./disableDictationInputAutoEnable"; import { isSipEnabled } from "./isSipEnabled"; @@ -61,6 +62,7 @@ export async function setup(): Promise { if (!isSipEnabled() && !(await enabledDbFile())) { writeDatabaseFile(); + enableAppleScriptControlSandboxedDefaults(); return; } From ecd60d0a6bb0e0180fe298d3676eed6376c525d3 Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 14:33:35 +0100 Subject: [PATCH 08/18] chore: kick ci From 287fb84da3985a0ec90787560a01a6d652869fea Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 14:41:52 +0100 Subject: [PATCH 09/18] ci: add latest set of GH runners --- .github/workflows/test.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ab27f3b..5e9bed6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,17 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-14, macos-15, macos-26, windows-2022, windows-2025] + os: + [ + macos-14, + macos-15, + macos-15-intel, + macos-26, + macos-26-intel, + windows-2022, + windows-2025, + windows-11-arm, + ] steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v6 @@ -31,7 +41,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-14] + os: [macos-latest] steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v6 @@ -49,7 +59,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [windows-2022, windows-2025] + os: [windows-2022, windows-2025, windows-11-arm] steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v6 From 1ba0afca973a4ed0845b2ccef1805fbab9c51b4d Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 14:48:45 +0100 Subject: [PATCH 10/18] revert: leave sandboxed defaults alone --- ...ableAppleScriptControlSandboxedDefaults.ts | 26 ------------------- .../enableAppleScriptControlSystemDefaults.ts | 11 +------- .../enabledDefaults.ts | 24 ++--------------- 3 files changed, 3 insertions(+), 58 deletions(-) delete mode 100644 src/macOS/enableAppleScriptControlSandboxedDefaults.ts diff --git a/src/macOS/enableAppleScriptControlSandboxedDefaults.ts b/src/macOS/enableAppleScriptControlSandboxedDefaults.ts deleted file mode 100644 index c4be227..0000000 --- a/src/macOS/enableAppleScriptControlSandboxedDefaults.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { execSync } from "child_process"; -import { getPlatformVersionMajor } from "./getPlatformVersionMajor"; -import { ERR_MACOS_UNABLE_UPDATE_VOICE_OVER_SANDBOXED_DEFAULTS } from "../errors"; - -const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = - "plutil -replace SCREnableAppleScript -bool true ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; - -export function enableAppleScriptControlSandboxedDefaults(): void { - const platformMajor = getPlatformVersionMajor(); - - // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. - if (platformMajor < 24) { - return; - } - - // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. - try { - execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL, { encoding: "utf8" }); - - return; - } catch (e) { - throw new Error( - `${ERR_MACOS_UNABLE_UPDATE_VOICE_OVER_SANDBOXED_DEFAULTS}\n\n${e.message}` - ); - } -} diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index e6892f6..c2a64e5 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -1,26 +1,17 @@ import { execSync } from "child_process"; -import { getPlatformVersionMajor } from "./getPlatformVersionMajor"; import { ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS } from "../errors"; const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true"; export function enableAppleScriptControlSystemDefaults(): void { - const platformMajor = getPlatformVersionMajor(); - - // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. - if (platformMajor >= 24) { - return; - } - - // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. try { execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { encoding: "utf8" }); return; } catch (e) { throw new Error( - `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}` + `${ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS}\n\n${e.message}`, ); } } diff --git a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts index 32d9ae0..1ff18b6 100644 --- a/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts +++ b/src/macOS/isAppleScriptControlEnabled/enabledDefaults.ts @@ -1,35 +1,15 @@ import { execSync } from "child_process"; -import { getPlatformVersionMajor } from "../getPlatformVersionMajor"; const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = "defaults read com.apple.VoiceOver4/default SCREnableAppleScript"; -const VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL = - "plutil -extract SCREnableAppleScript raw -o - ~/Library/Group\\ Containers/group.com.apple.VoiceOver/Library/Preferences/com.apple.VoiceOver4/default.plist"; - export function enabledDefaults(): boolean { - const platformMajor = getPlatformVersionMajor(); - - // For MacOS 14 Sonoma (Darwin 23) and earlier VoiceOver preferences are set via system defaults. - if (platformMajor < 24) { - try { - const result = execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { - encoding: "utf8", - }); - - return result.trim() === "1"; - } catch { - return false; - } - } - - // From MacOS 15 Sequoia (Darwin 24) VoiceOver preferences are sandboxed. try { - const result = execSync(VOICE_OVER_APPLESCRIPT_ENABLED_PLUTIL, { + const result = execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { encoding: "utf8", }); - return result.trim() === "true"; + return result.trim() === "1"; } catch { return false; } From ad5d657ce21ead161f8b5ac55ec0f4b5fe29b496 Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 14:48:56 +0100 Subject: [PATCH 11/18] feat: disable notification center in ci --- src/errors.ts | 2 ++ src/macOS/disableNotificationCenter.ts | 15 +++++++++++++++ src/macOS/setup.ts | 14 +++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 src/macOS/disableNotificationCenter.ts diff --git a/src/errors.ts b/src/errors.ts index 62b3185..edf7732 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -7,6 +7,8 @@ export const ERR_MACOS_UNSUPPORTED_VERSION = "Require macOS version 11 or later"; export const ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS = "Unable to update system defaults"; +export const ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER = + "Unable to disable the notification center"; export const ERR_MACOS_UNABLE_UPDATE_VOICE_OVER_SANDBOXED_DEFAULTS = "Unable to update VoiceOver sandboxed defaults - SIP might not be disabled"; export const ERR_MACOS_UNABLE_TO_VERIFY_SIP = diff --git a/src/macOS/disableNotificationCenter.ts b/src/macOS/disableNotificationCenter.ts new file mode 100644 index 0000000..1578744 --- /dev/null +++ b/src/macOS/disableNotificationCenter.ts @@ -0,0 +1,15 @@ +import { execSync } from "child_process"; +import { ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER } from "../errors"; + +export function disableNotificationCenter(): void { + try { + execSync( + "launchctl unload -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist", + { encoding: "utf8" }, + ); + } catch (e) { + throw new Error( + `${ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER}\n\n${e.message}`, + ); + } +} diff --git a/src/macOS/setup.ts b/src/macOS/setup.ts index 35f30d4..9604f7e 100644 --- a/src/macOS/setup.ts +++ b/src/macOS/setup.ts @@ -3,7 +3,6 @@ import { macOSRecord } from "@guidepup/record"; import chalk from "chalk"; import { checkVersion } from "./checkVersion"; import { enableAppleScriptControlSystemDefaults } from "./enableAppleScriptControlSystemDefaults"; -import { enableAppleScriptControlSandboxedDefaults } from "./enableAppleScriptControlSandboxedDefaults"; import { disableSplashScreenSystemDefaults } from "./disableSplashScreenSystemDefaults"; import { disableDictationInputAutoEnable } from "./disableDictationInputAutoEnable"; import { isSipEnabled } from "./isSipEnabled"; @@ -13,6 +12,7 @@ import { isAppleScriptControlEnabled } from "./isAppleScriptControlEnabled"; import { handleWarning, logInfo } from "../logging"; import { ERR_MACOS_REQUIRES_MANUAL_USER_INTERACTION } from "../errors"; import { enableDoNotDisturb } from "./enableDoNotDisturb"; +import { disableNotificationCenter } from "./disableNotificationCenter"; import { enabledDbFile } from "./isAppleScriptControlEnabled/enabledDbFile"; const isCi = process.argv.includes("--ci"); @@ -37,7 +37,7 @@ export async function setup(): Promise { } else { handleWarning( "Ignoring TCC.db updates", - "If the necessary permissions have not been granted by other means, using this flag may result in your environment not being set up for reliable screen reader automation." + "If the necessary permissions have not been granted by other means, using this flag may result in your environment not being set up for reliable screen reader automation.", ); } @@ -46,7 +46,7 @@ export async function setup(): Promise { const stopRecording = isRecorded ? macOSRecord( - `./recordings/macos-guidepup-setup-${osName}-${osVersion}-${+new Date()}.mov` + `./recordings/macos-guidepup-setup-${osName}-${osVersion}-${+new Date()}.mov`, ) : () => null; @@ -58,11 +58,11 @@ export async function setup(): Promise { if (isCi) { await enableDoNotDisturb(); + await disableNotificationCenter(); } if (!isSipEnabled() && !(await enabledDbFile())) { writeDatabaseFile(); - enableAppleScriptControlSandboxedDefaults(); return; } @@ -79,9 +79,9 @@ export async function setup(): Promise { "Please complete remaining setup by following this guide:\n\n--> " + chalk.underline( chalk.bold( - "https://www.guidepup.dev/docs/guides/manual-voiceover-setup" - ) - ) + "https://www.guidepup.dev/docs/guides/manual-voiceover-setup", + ), + ), ); } finally { stopRecording(); From c0d6c980216c6a9dc34ee4b296fe3f9625797cd3 Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 14:51:50 +0100 Subject: [PATCH 12/18] revert: constant --- src/errors.ts | 2 -- src/macOS/enableAppleScriptControlSystemDefaults.ts | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/errors.ts b/src/errors.ts index edf7732..3108c62 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -9,8 +9,6 @@ export const ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS = "Unable to update system defaults"; export const ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER = "Unable to disable the notification center"; -export const ERR_MACOS_UNABLE_UPDATE_VOICE_OVER_SANDBOXED_DEFAULTS = - "Unable to update VoiceOver sandboxed defaults - SIP might not be disabled"; export const ERR_MACOS_UNABLE_TO_VERIFY_SIP = "Unable to verify macOS SIP status"; export const ERR_MACOS_UNABLE_TO_WRITE_DATABASE_FILE = diff --git a/src/macOS/enableAppleScriptControlSystemDefaults.ts b/src/macOS/enableAppleScriptControlSystemDefaults.ts index c2a64e5..3b16cb3 100644 --- a/src/macOS/enableAppleScriptControlSystemDefaults.ts +++ b/src/macOS/enableAppleScriptControlSystemDefaults.ts @@ -1,12 +1,12 @@ import { execSync } from "child_process"; import { ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS } from "../errors"; -const VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS = - "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true"; - export function enableAppleScriptControlSystemDefaults(): void { try { - execSync(VOICE_OVER_APPLESCRIPT_ENABLED_DEFAULTS, { encoding: "utf8" }); + execSync( + "defaults write com.apple.VoiceOver4/default SCREnableAppleScript -bool true", + { encoding: "utf8" }, + ); return; } catch (e) { From c2a44d7679a186c24cc0b5bc0ac95979cf80757e Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 15:03:37 +0100 Subject: [PATCH 13/18] feat: optional recording --- package.json | 4 +++- src/macOS/setup.ts | 20 +++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a8832fd..538dbec 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,10 @@ "ts-node": "^10.9.2", "typescript": "^5.6.2" }, + "optionalDependencies": { + "@guidepup/record": "^0.1.0" + }, "dependencies": { - "@guidepup/record": "^0.1.0", "chalk": "^4.0.0", "decompress": "^4.2.1", "https-proxy-agent": "^7.0.5", diff --git a/src/macOS/setup.ts b/src/macOS/setup.ts index 9604f7e..e5ccaa2 100644 --- a/src/macOS/setup.ts +++ b/src/macOS/setup.ts @@ -1,5 +1,4 @@ import { platform, release } from "os"; -import { macOSRecord } from "@guidepup/record"; import chalk from "chalk"; import { checkVersion } from "./checkVersion"; import { enableAppleScriptControlSystemDefaults } from "./enableAppleScriptControlSystemDefaults"; @@ -44,11 +43,22 @@ export async function setup(): Promise { const osName = platform(); const osVersion = release(); - const stopRecording = isRecorded - ? macOSRecord( + let stopRecording: () => void = () => null; + + if (isRecorded) { + try { + const { macOSRecord } = await import("@guidepup/record"); + + stopRecording = macOSRecord( `./recordings/macos-guidepup-setup-${osName}-${osVersion}-${+new Date()}.mov`, - ) - : () => null; + ); + } catch { + handleWarning( + "@guidepup/record not available", + "Recording will be skipped. This is expected on platforms without ffmpeg support (e.g., Windows ARM64).", + ); + } + } try { checkVersion(); From e9561a54b46d6ebd8a4fc3364d93527e8b55787a Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 15:09:27 +0100 Subject: [PATCH 14/18] fix: move away from unload --- src/macOS/disableNotificationCenter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macOS/disableNotificationCenter.ts b/src/macOS/disableNotificationCenter.ts index 1578744..9079bff 100644 --- a/src/macOS/disableNotificationCenter.ts +++ b/src/macOS/disableNotificationCenter.ts @@ -4,7 +4,7 @@ import { ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER } from "../errors"; export function disableNotificationCenter(): void { try { execSync( - "launchctl unload -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist", + "launchctl bootout /System/Library/LaunchAgents/com.apple.notificationcenterui.plist", { encoding: "utf8" }, ); } catch (e) { From b962bc32ba64aaea3e2e80b781ede41846c73004 Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 15:12:55 +0100 Subject: [PATCH 15/18] fix: provide id --- src/macOS/disableNotificationCenter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macOS/disableNotificationCenter.ts b/src/macOS/disableNotificationCenter.ts index 9079bff..554990a 100644 --- a/src/macOS/disableNotificationCenter.ts +++ b/src/macOS/disableNotificationCenter.ts @@ -4,7 +4,7 @@ import { ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER } from "../errors"; export function disableNotificationCenter(): void { try { execSync( - "launchctl bootout /System/Library/LaunchAgents/com.apple.notificationcenterui.plist", + "launchctl bootout gui/$(id -u) /System/Library/LaunchAgents/com.apple.notificationcenterui.plist", { encoding: "utf8" }, ); } catch (e) { From 62c3b5a7f81858898a80a6d87add54af899c3216 Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 15:24:01 +0100 Subject: [PATCH 16/18] fix: notification center is not bootout safe --- src/macOS/disableNotificationCenter.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/macOS/disableNotificationCenter.ts b/src/macOS/disableNotificationCenter.ts index 554990a..47990b6 100644 --- a/src/macOS/disableNotificationCenter.ts +++ b/src/macOS/disableNotificationCenter.ts @@ -3,10 +3,7 @@ import { ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER } from "../errors"; export function disableNotificationCenter(): void { try { - execSync( - "launchctl bootout gui/$(id -u) /System/Library/LaunchAgents/com.apple.notificationcenterui.plist", - { encoding: "utf8" }, - ); + execSync("killall NotificationCenter", { encoding: "utf8" }); } catch (e) { throw new Error( `${ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER}\n\n${e.message}`, From b4d59ed8831a4ca2b9810d465e2d9763f6660c29 Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 15:49:21 +0100 Subject: [PATCH 17/18] revert: remove notification center disable, no reliable way... --- src/errors.ts | 2 -- src/macOS/disableNotificationCenter.ts | 12 ------------ src/macOS/setup.ts | 2 -- 3 files changed, 16 deletions(-) delete mode 100644 src/macOS/disableNotificationCenter.ts diff --git a/src/errors.ts b/src/errors.ts index 3108c62..feece95 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -7,8 +7,6 @@ export const ERR_MACOS_UNSUPPORTED_VERSION = "Require macOS version 11 or later"; export const ERR_MACOS_UNABLE_UPDATE_SYSTEM_DEFAULTS = "Unable to update system defaults"; -export const ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER = - "Unable to disable the notification center"; export const ERR_MACOS_UNABLE_TO_VERIFY_SIP = "Unable to verify macOS SIP status"; export const ERR_MACOS_UNABLE_TO_WRITE_DATABASE_FILE = diff --git a/src/macOS/disableNotificationCenter.ts b/src/macOS/disableNotificationCenter.ts deleted file mode 100644 index 47990b6..0000000 --- a/src/macOS/disableNotificationCenter.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { execSync } from "child_process"; -import { ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER } from "../errors"; - -export function disableNotificationCenter(): void { - try { - execSync("killall NotificationCenter", { encoding: "utf8" }); - } catch (e) { - throw new Error( - `${ERR_MACOS_UNABLE_DISABLE_NOTIFICATION_CENTER}\n\n${e.message}`, - ); - } -} diff --git a/src/macOS/setup.ts b/src/macOS/setup.ts index e5ccaa2..3ec9d3f 100644 --- a/src/macOS/setup.ts +++ b/src/macOS/setup.ts @@ -11,7 +11,6 @@ import { isAppleScriptControlEnabled } from "./isAppleScriptControlEnabled"; import { handleWarning, logInfo } from "../logging"; import { ERR_MACOS_REQUIRES_MANUAL_USER_INTERACTION } from "../errors"; import { enableDoNotDisturb } from "./enableDoNotDisturb"; -import { disableNotificationCenter } from "./disableNotificationCenter"; import { enabledDbFile } from "./isAppleScriptControlEnabled/enabledDbFile"; const isCi = process.argv.includes("--ci"); @@ -68,7 +67,6 @@ export async function setup(): Promise { if (isCi) { await enableDoNotDisturb(); - await disableNotificationCenter(); } if (!isSipEnabled() && !(await enabledDbFile())) { From f805eb906c8c15ce68a3419a74b5463a95d0d4a0 Mon Sep 17 00:00:00 2001 From: cmorten Date: Sun, 7 Jun 2026 15:58:17 +0100 Subject: [PATCH 18/18] chore: version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 538dbec..4feee2e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@guidepup/setup", - "version": "0.21.0", + "version": "0.22.0", "description": "Setup your environment for screen-reader automation.", "main": "lib/index.js", "typings": "lib/index.d.ts",