Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

pdfu

macrumors regular
Original poster
Apple is working on a Solar wallpaper engine for macOS 27 that groups aerial Landscape wallpapers and automatically switches variants based on the sun's position during the day.

See an updated guide for Beta 6

When the feature flag is enabled, the four Tahoe landscape wallpapers appear under one entry in Settings.

GG_Solar.png
Tahoe_Solar.png


To get the Automatic Tahoe landscape wallpaper, enable the wallpaper feature:

Bash:
sudo mkdir -p /Library/Preferences/FeatureFlags/Domain && \
sudo defaults write /Library/Preferences/FeatureFlags/Domain/Wallpaper TahoeCombined -dict Enabled -bool true

and reboot your Mac. You will no longer see the Golden Gate landscape wallpapers on the list because the new engine reads a macOS 26 wallpaper registry for now. Read below for a more involved process to add the dynamic Golden Gate wallpaper entry.

To go back to the default and bring the Golden Gate landscape wallpapers back:

Bash:
sudo defaults delete /Library/Preferences/FeatureFlags/Domain/Wallpaper TahoeCombined

and reboot your Mac.

In Beta 4, macOS ships with a macOS 26 wallpaper registry for this combined variants endpoint, so Golden Gate wallpapers don't show by default. Thankfully, you can point the wallpaper engine to a local override file and enable the dynamic switching for Golden Gate wallpapers.

1. Enable the combined-variant wallpaper feature:

Bash:
sudo mkdir -p /Library/Preferences/FeatureFlags/Domain && \
sudo defaults write /Library/Preferences/FeatureFlags/Domain/Wallpaper TahoeCombined -dict Enabled -bool true

2. Create the local catalog directory:

Bash:
WALLPAPER_CUSTOM="$HOME/Library/Application Support/com.apple.wallpaper/aerials/custom"

mkdir -p "$WALLPAPER_CUSTOM"

3. Start with Apple’s macOS 27 variant catalog, copying it into your local catalog directory:

Bash:
WALLPAPER_RESOURCES="/System/Library/ExtensionKit/Extensions/WallpaperAerialsExtension.appex/Contents/Resources"

cp "$WALLPAPER_RESOURCES/entries_variants.json" "$WALLPAPER_CUSTOM/entries.json"

4. Add some helpers:

Bash:
LANDSCAPES_ID='A33A55D9-EDEA-4596-A850-6C10B54FBBB5'
GOLDEN_GATE_ID='67512508-D33E-4CBC-8A9E-BE55CEE35C4C'
DYNAMIC_AERIALS_ID='dynamic-aerials'

find_id_index() {
  local array_path="$1"
  local wanted_id="$2"
  local catalog="$3"
  local i=0
  local current_id

  while plutil -extract "$array_path.$i" json -o /dev/null "$catalog" 2>/dev/null; do
    current_id=$(plutil -extract "$array_path.$i.id" raw -o - "$catalog" 2>/dev/null || true)

    if [[ "$current_id" == "$wanted_id" ]]; then
      printf '%s\n' "$i"
      return 0
    fi

    (( i++ ))
  done

  return 1
}

next_index() {
  local array_path="$1"
  local catalog="$2"
  local i=0

  while plutil -extract "$array_path.$i" json -o /dev/null "$catalog" 2>/dev/null; do
    (( i++ ))
  done

  printf '%s\n' "$i"
}

find_asset_index() {
  local shot_id="$1"
  local catalog="$2"
  local i=0
  local value

  while plutil -extract "assets.$i" json -o /dev/null "$catalog" 2>/dev/null; do
    value=$(plutil -extract "assets.$i.shotID" raw -o - "$catalog" 2>/dev/null || true)

    if [[ "$value" == "$shot_id" ]]; then
      printf '%s\n' "$i"
      return 0
    fi

    (( i++ ))
  done

  return 1
}

next_asset_index() {
  local catalog="$1"
  local i=0

  while plutil -extract "assets.$i" json -o /dev/null "$catalog" 2>/dev/null; do
    (( i++ ))
  done

  printf '%s\n' "$i"
}

install_solar_asset() {
  local shot_id="$1"
  local altitude="$2"
  local azimuth="$3"
  local source_index
  local target_index
  local asset_json
  local variant_json

  if ! target_index=$(find_asset_index "$shot_id" "$WALLPAPER_CUSTOM/entries.json"); then
    source_index=$(find_asset_index "$shot_id" "$WALLPAPER_RESOURCES/entries.json") || {
      echo "Could not find $shot_id in Apple’s catalog." >&2
      return 1
    }

    asset_json=$(
      plutil -extract "assets.$source_index" json -o - \
        "$WALLPAPER_RESOURCES/entries.json"
    ) || return 1

    target_index=$(next_asset_index "$WALLPAPER_CUSTOM/entries.json")

    plutil -insert "assets.$target_index" -json "$asset_json" \
      "$WALLPAPER_CUSTOM/entries.json" || return 1
  fi

  variant_json="{\"solar\":{\"altitude\":$altitude,\"azimuth\":$azimuth}}"

  if plutil -extract "assets.$target_index.variant" json -o /dev/null \
      "$WALLPAPER_CUSTOM/entries.json" 2>/dev/null; then
    plutil -replace "assets.$target_index.variant" -json "$variant_json" \
      "$WALLPAPER_CUSTOM/entries.json"
  else
    plutil -insert "assets.$target_index.variant" -json "$variant_json" \
      "$WALLPAPER_CUSTOM/entries.json"
  fi
}

5. Find Landscapes in both catalogs and Golden Gate inside Apple’s Landscapes category:

Bash:
SOURCE_LANDSCAPES_INDEX=$(
  find_id_index categories "$LANDSCAPES_ID" \
    "$WALLPAPER_RESOURCES/entries.json"
) || {
  echo "Could not find Landscapes in Apple’s catalog."
  exit 1
}

CUSTOM_LANDSCAPES_INDEX=$(
  find_id_index categories "$LANDSCAPES_ID" \
    "$WALLPAPER_CUSTOM/entries.json"
) || {
  echo "Could not find Landscapes in the custom catalog."
  exit 1
}

SOURCE_GOLDEN_GATE_INDEX=$(
  find_id_index \
    "categories.$SOURCE_LANDSCAPES_INDEX.subcategories" \
    "$GOLDEN_GATE_ID" \
    "$WALLPAPER_RESOURCES/entries.json"
) || {
  echo "Could not find Golden Gate in Apple’s catalog."
  exit 1
}

SOURCE_DYNAMIC_AERIALS_INDEX=$(
  find_id_index categories "$DYNAMIC_AERIALS_ID" \
    "$WALLPAPER_RESOURCES/entries.json"
) || {
  echo "Could not find Apple’s graphical macOS wallpaper category."
  exit 1
}

6. Insert Golden Gate into your local catalog and enable variant combining:

Bash:
if CUSTOM_GOLDEN_GATE_INDEX=$(
  find_id_index \
    "categories.$CUSTOM_LANDSCAPES_INDEX.subcategories" \
    "$GOLDEN_GATE_ID" \
    "$WALLPAPER_CUSTOM/entries.json"
); then
  echo "Golden Gate is already in the custom Landscapes category."
else
  CUSTOM_GOLDEN_GATE_INDEX=$(
    next_index \
      "categories.$CUSTOM_LANDSCAPES_INDEX.subcategories" \
      "$WALLPAPER_CUSTOM/entries.json"
  )

  GOLDEN_GATE_JSON=$(
    plutil -extract \
      "categories.$SOURCE_LANDSCAPES_INDEX.subcategories.$SOURCE_GOLDEN_GATE_INDEX" \
      json -o - \
      "$WALLPAPER_RESOURCES/entries.json"
  )

  plutil -insert \
    "categories.$CUSTOM_LANDSCAPES_INDEX.subcategories.$CUSTOM_GOLDEN_GATE_INDEX" \
    -json "$GOLDEN_GATE_JSON" \
    "$WALLPAPER_CUSTOM/entries.json"
fi

GOLDEN_GATE_PATH="categories.$CUSTOM_LANDSCAPES_INDEX.subcategories.$CUSTOM_GOLDEN_GATE_INDEX"

if plutil -extract "$GOLDEN_GATE_PATH.combineVariants" raw -o - \
    "$WALLPAPER_CUSTOM/entries.json" >/dev/null 2>&1; then
  plutil -replace "$GOLDEN_GATE_PATH.combineVariants" -bool true \
    "$WALLPAPER_CUSTOM/entries.json"
else
  plutil -insert "$GOLDEN_GATE_PATH.combineVariants" -bool true \
    "$WALLPAPER_CUSTOM/entries.json"
fi

if CUSTOM_DYNAMIC_AERIALS_INDEX=$(
  find_id_index categories "$DYNAMIC_AERIALS_ID" \
    "$WALLPAPER_CUSTOM/entries.json"
); then
  echo "The graphical macOS wallpaper category is already installed."
else
  DYNAMIC_AERIALS_JSON=$(
    plutil -extract \
      "categories.$SOURCE_DYNAMIC_AERIALS_INDEX" \
      json -o - \
      "$WALLPAPER_RESOURCES/entries.json"
  )

  plutil -insert categories.0 \
    -json "$DYNAMIC_AERIALS_JSON" \
    "$WALLPAPER_CUSTOM/entries.json"
fi

for SHOT_ID in GG_LM_H GG_LM_V GG_DM_H GG_DM_V; do
  if find_asset_index "$SHOT_ID" \
      "$WALLPAPER_CUSTOM/entries.json" >/dev/null; then
    echo "$SHOT_ID is already installed."
    continue
  fi

  SOURCE_ASSET_INDEX=$(
    find_asset_index "$SHOT_ID" \
      "$WALLPAPER_RESOURCES/entries.json"
  ) || {
    echo "Could not find $SHOT_ID in Apple’s catalog."
    exit 1
  }

  TARGET_ASSET_INDEX=$(
    next_asset_index "$WALLPAPER_CUSTOM/entries.json"
  )

  ASSET_JSON=$(
    plutil -extract "assets.$SOURCE_ASSET_INDEX" \
      json -o - \
      "$WALLPAPER_RESOURCES/entries.json"
  )

  plutil -insert "assets.$TARGET_ASSET_INDEX" \
    -json "$ASSET_JSON" \
    "$WALLPAPER_CUSTOM/entries.json"
done

CATEGORY_COUNT=$(
  next_index categories "$WALLPAPER_CUSTOM/entries.json"
)

for (( CATEGORY_INDEX=0; CATEGORY_INDEX<CATEGORY_COUNT; CATEGORY_INDEX++ )); do
  CATEGORY_PATH="categories.$CATEGORY_INDEX.preferredOrder"

  if plutil -extract "$CATEGORY_PATH" raw -o - \
      "$WALLPAPER_CUSTOM/entries.json" >/dev/null 2>&1; then
    plutil -replace "$CATEGORY_PATH" -integer "$CATEGORY_INDEX" \
      "$WALLPAPER_CUSTOM/entries.json"
  else
    plutil -insert "$CATEGORY_PATH" -integer "$CATEGORY_INDEX" \
      "$WALLPAPER_CUSTOM/entries.json"
  fi
done

7. Add the Golden Gate Sunset video and its daytime solar coordinate. See at the end for an explanation on how this is calculated:

Bash:
install_solar_asset GG_A_SUNSET 35 180

8. Add the Golden Gate Night video and its nighttime solar coordinate:

Bash:
install_solar_asset GG_A_NIGHT -35 180

9. Verify both records:

Bash:
SUNSET_INDEX=$(find_asset_index GG_A_SUNSET "$WALLPAPER_CUSTOM/entries.json")
plutil -extract "assets.$SUNSET_INDEX.variant" json -o - "$WALLPAPER_CUSTOM/entries.json"

Bash:
NIGHT_INDEX=$(find_asset_index GG_A_NIGHT "$WALLPAPER_CUSTOM/entries.json")
plutil -extract "assets.$NIGHT_INDEX.variant" json -o - "$WALLPAPER_CUSTOM/entries.json"

The output should show:

JSON:
{"solar":{"altitude":35,"azimuth":180}}

and:

JSON:
{"solar":{"altitude":-35,"azimuth":180}}

10. Point the wallpaper extension at the custom catalog:

Bash:
defaults write com.apple.wallpaper.aerial AerialManifestLocalPathOverride -string "$WALLPAPER_CUSTOM/entries.json"

11. Force it to use the local catalog:

Bash:
defaults write com.apple.wallpaper.aerial AerialManifestForceLocal -bool true

12. Restart the Mac.

After restarting, Golden Gate should appear as one item and automatically use Sunset during the day and Night after sunset.

Bash:
defaults delete com.apple.wallpaper.aerial AerialManifestLocalPathOverride

Bash:
defaults delete com.apple.wallpaper.aerial AerialManifestForceLocal

Bash:
rm -rf -- "$HOME/Library/Application Support/com.apple.wallpaper/aerials/custom"

Bash:
sudo defaults delete /Library/Preferences/FeatureFlags/Domain/Wallpaper TahoeCombined

Then reboot your Mac.

Apple’s Tahoe dynamic wallpaper includes four variants: Morning, Day, Evening, and Night. Apple assigns each variant a pair of solar coordinates:
  • altitude: how high the Sun is above or below the horizon.
  • azimuth: the Sun’s compass direction, where 180° means south.
macOS calculates the Sun’s current coordinates using your location, date, and time. It selects whichever wallpaper variant is closest to the Sun’s current position.

The Golden Gate landscape set only has two variants. We therefore use:
  • Golden Gate Sunset: {35, 180}
  • Golden Gate Night: {-35, 180}
These coordinates are deliberately symmetrical: one is 35° above the horizon and the other is 35° below it. Because both use the same azimuth, macOS considers them equally close when the Sun is at approximately altitude, i.e. the horizon. That makes WallpaperAgent switch to the Sunset variant around sunrise and to Night around sunset.

If you'd like to use other solar positions, use the following Python script to estimate times based on coordinates:

Bash:
DAY='35,180'
NIGHT='-35,180'
LAT=37.3230; LON=-122.0322
DATE='2026-08-02'; UTC_OFFSET=-7

python3 -c 'exec("""import sys,math,datetime
day=tuple(map(float,sys.argv[1].split(",")));night=tuple(map(float,sys.argv[2].split(",")));lat=float(sys.argv[3]);lon=float(sys.argv[4]);date=datetime.date.fromisoformat(sys.argv[5]);tz=float(sys.argv[6])
def sun(m):
 h=m/60;n=date.timetuple().tm_yday;g=2*math.pi/365*(n-1+(h-12)/24);eq=229.18*(.000075+.001868*math.cos(g)-.032077*math.sin(g)-.014615*math.cos(2*g)-.040849*math.sin(2*g));dec=.006918-.399912*math.cos(g)+.070257*math.sin(g)-.006758*math.cos(2*g)+.000907*math.sin(2*g)-.002697*math.cos(3*g)+.00148*math.sin(3*g);tst=(m+eq+4*lon-60*tz)%1440;ha=math.radians(tst/4-180);p=math.radians(lat);cz=max(-1,min(1,math.sin(p)*math.sin(dec)+math.cos(p)*math.cos(dec)*math.cos(ha)));e=90-math.degrees(math.acos(cz))
 if e>85:r=0
 elif e>5:t=math.tan(math.radians(e));r=(58.1/t-.07/t**3+.000086/t**5)/3600
 elif e>-.575:r=(1735+e*(-518.2+e*(103.4+e*(-12.79+e*.711))))/3600
 else:r=-20.772/math.tan(math.radians(e))/3600
 return e+r,(math.degrees(math.atan2(math.sin(ha),math.cos(ha)*math.sin(p)-math.tan(dec)*math.cos(p)))+180)%360
def da(a,b):return (a-b+180)%360-180
def f(m):
 a,z=sun(m);return (a-day[0])**2+da(z,day[1])**2-(a-night[0])**2-da(z,night[1])**2
def fmt(m):
 h=int(m//60)%24;mi=int(m%60);s=round(m%1*60)
 if s==60:mi+=1;s=0
 if mi==60:h=(h+1)%24;mi=0
 return f"{h%12 or 12}:{mi:02d}:{s:02d} {\x27AM\x27 if h<12 else \x27PM\x27}"
step=.25;prev=f(0)
for i in range(1,5761):
 x=i*step;cur=f(x)
 if prev*cur<0:
  lo=x-step;hi=x
  for _ in range(40):
   mid=(lo+hi)/2
   if f(lo)*f(mid)<=0:hi=mid
   else:lo=mid
  t=(lo+hi)/2;print(("Night -> Day" if f(t-.1)>0 else "Day -> Night")+": "+fmt(t))
 prev=cur
""")' "$DAY" "$NIGHT" "$LAT" "$LON" "$DATE" "$UTC_OFFSET"

This should print:

Code:
Night -> Day: 6:13:58 AM
Day -> Night: 8:14:41 PM
 
Last edited:
Oh cool find. When Tahoe came out I tried to work out how to script this and couldn't get anything working nicely without some awful hacks.
 
  • Like
Reactions: pdfu
Update for Beta 6:

As previously discussed, Apple is working on a dynamic solar wallpaper engine for macOS 27 that groups aerial Landscape wallpapers and automatically switches variants based on the sun's position during the day.

When properly configured, the four Tahoe and Golden Gate landscape wallpapers appear under one entry each in Settings, and a new Automatic display option appears.

Use these instructions to enable the Automatic Golden Gate and Tahoe landscape wallpapers.

1787003207586.png
1787003211934.png
 
Update for Beta 6:

As previously discussed, Apple is working on a dynamic solar wallpaper engine for macOS 27 that groups aerial Landscape wallpapers and automatically switches variants based on the sun's position during the day.

When properly configured, the four Tahoe and Golden Gate landscape wallpapers appear under one entry each in Settings, and a new Automatic display option appears.

Use these instructions to enable the Automatic Golden Gate and Tahoe landscape wallpapers.

View attachment 2653462 View attachment 2653463
What do you mean by Apple is working on? Does that mean that with the release candidate we will be able to cycle through the different wallpapers without your "workaround"?
 
What do you mean by Apple is working on? Does that mean that with the release candidate we will be able to cycle through the different wallpapers without your "workaround"?
Working on it means that they added this new feature in macOS 27 and they keep pushing code updates for it through the Betas. The new Beta 6 implementation enables the new solar behavior by default. They have removed the private feature flag, so the feature is quite mature. The only reason you're not seeing the Automatic display option is that Apple hasn't shipped a compatible wallpaper registry with solar coordinates for the Golden Gate and Tahoe wallpapers.

All it takes now is for Apple to push a new wallpaper registry under https://configuration.apple.com/configurations/internetservices/aerials/resources-config-27-0.plist with solar coordinates. It will replace the registry that currently ships with macOS 27. I don't know if/when Apple will start shipping the new wallpaper registry to replace the included one.

We only have https://configuration.apple.com/configurations/internetservices/aerials/resources-config-26-0.plist available, and macOS 27 doesn't reference it.
 
  • Like
Reactions: Godspeed8230
Finally. It's clear this has always been the intention since these animated wallpapers were introduced with Sequoia where there's always been a morning/day/night variation, I wonder why they haven't enabled it.

It's the only reason I don't use them as they're always too bright at night.
 
  • Like
Reactions: Godspeed8230
Working on it means that they added this new feature in macOS 27 and they keep pushing code updates for it through the Betas. The new Beta 6 implementation enables the new solar behavior by default. They have removed the private feature flag, so the feature is quite mature. The only reason you're not seeing the Automatic display option is that Apple hasn't shipped a compatible wallpaper registry with solar coordinates for the Golden Gate and Tahoe wallpapers.

All it takes now is for Apple to push a new wallpaper registry under https://configuration.apple.com/configurations/internetservices/aerials/resources-config-27-0.plist with solar coordinates. It will replace the registry that currently ships with macOS 27. I don't know if/when Apple will start shipping the new wallpaper registry to replace the included one.

We only have https://configuration.apple.com/configurations/internetservices/aerials/resources-config-26-0.plist available, and macOS 27 doesn't reference it.

I am not sure I really understand what they are trying to do because there is already the Big Sur wallpaper that's animated throughout the day. Isn't this what we are talking about? If not, what's the difference?
 
I am not sure I really understand what they are trying to do because there is already the Big Sur wallpaper that's animated throughout the day. Isn't this what we are talking about? If not, what's the difference?

The underlying idea is similar to previous iterations, but this is a new implementation and asset pipeline.

Mojave introduced solar-driven Dynamic Desktop wallpapers. That system is still available today to support older Dynamic Desktop wallpapers such as Mojave, Catalina, Big Sur, Monterey Graphic, Ventura Graphic, and Solar Gradients. The old system packaged multiple still frames and their solar metadata inside one portable HEIC file.

Later wallpapers reused the same general idea. The graphical Sequoia wallpaper used a solar trigger to select different color stages throughout the day. In macOS 26, that was an internal WallpaperExtensionCore.SolarTrigger implementation. In macOS 27, Apple moved and expanded that machinery into a new centralized WallpaperExtensionKit.SolarTrigger.

TahoeCombined is a new use of that implementation for grouping separate animated Aerial variants. Apple’s wallpaper manifest groups the Tahoe Day, Morning, Evening, and Night MOV files. Each video is assigned a representative solar altitude and azimuth coordinates. macOS calculates the Sun’s current position and selects the closest matching video.

There's no portable image file anymore. The media remain separate videos, and Apple’s catalog defines the relationship between them.
 
Am I right that this is still not an official feature in the recent RC versions?
Yep, they even published their new wallpaper remote config, which is meant to replace what ships in the macOS binary:


which points to:


Still doesn’t have solar coordinates for Golden Gate.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.