Skip to main content

macos/set_accent_colour

1#!/usr/bin/env swift
2// A script to set the accent colour of your Mac.
3//
4// This mimics the accent colour picker in the General pane of
5// System Preferences, and should cause all apps to pick up the change.
6//
7// Usage: pass the colour you want to use as a single command-line argument,
8// e.g.
9//
10// $ set_accent_colour red
11// $ set_accent_colour green
12//
13// Tested on macOS Monterey.
14//
15// You may need to run `chmod +x set_accent_colour` first and install the Xcode
16// command-line tools.
17//
18// == How it works ==
19//
20// You can set the accent colour using a `defaults write` command,
21// e.g. to change your accent colour to pink:
22//
23// $ defaults write -globalDomain AppleAccentColor -int 6
24//
25// But this doesn't take effect immediately -- we have to send notifications
26// AppleColorPreferencesChangedNotification and
27// AppleAquaColorVariantChanged to tell apps they should update their UIs.
28//
29// == Attribution ==
30//
31// Based on code/ideas by Henrik Helmers, Garth Mortensen, and Robert Sesek.
32//
33// See https://alexwlchan.net/2022/11/changing-the-macos-accent-colour/
35import Foundation
37// A map of colour names to the int values in AppleAccentColor.
38//
39// I created this map by selected all the accent colours in System Preferences,
40// then running `defaults read -globalDomain AppleAccentColor` and recording
41// the result.
42let colourMap = [
43 ("red", 0),
44 ("orange", 1),
45 ("yellow", 2),
46 ("green", 3),
47 ("blue", 4),
48 ("purple", 5),
49 ("pink", 6),
50 ("graphite", -1),
53// Read the selected colour from the command-line arguments.
54func getSelectedColour() -> String {
55 let arguments = CommandLine.arguments
57 let colourNames = colourMap.map { $0.0 }
59 // If the user hasn't supplied a colour, of they've selected an invalid
60 // colour, print a helpful help message. e.g.
61 //
62 // $ set_accent_colour blurple
63 // Usage: set_accent_colour <red|orange|yellow|green|blue|purple|pink|graphite>
64 //
65 if arguments.count != 2 || !colourNames.contains(arguments[1]) {
66 let colours = colourNames.joined(separator:"|")
67 fputs("Usage: \(arguments[0]) <\(colours)>\n", stderr)
68 exit(1)
69 }
71 return arguments[1]
74func setAccentColour(colour: String) -> () {
75 let colourDict = Dictionary(uniqueKeysWithValues: colourMap)
76 let accentValue: Int = colourDict[colour]!
78 // This is the equivalent of
79 //
80 // $ defaults write -globalDomain AppleAccentColor -int <prefValue>
81 //
82 UserDefaults.standard.setPersistentDomain(
83 ["AppleAccentColor": Optional(accentValue) as Any],
84 forName: UserDefaults.globalDomain
85 )
87 let notifications = [
88 "AppleColorPreferencesChangedNotification",
89 "AppleAquaColorVariantChanged"
90 ]
92 for name in notifications {
93 let notifyEvent = Notification.Name(name)
94 DistributedNotificationCenter.default().post(name: notifyEvent, object: nil)
95 }
98let colour = getSelectedColour()
99setAccentColour(colour: colour)