Last active
July 16, 2025 22:15
-
-
Save NextdoorPsycho/013ad83455c8492888c9c424d7695dd7 to your computer and use it in GitHub Desktop.
This script enables Apple’s Game Mode by launching the Chess app in fullscreen mode, which triggers Game Mode. It then deprioritizes the Chess process to minimize its resource usage, keeping the performance boost of Game Mode active without significant CPU/GPU drain from Chess. After making Chess fullscreen, the script switches focus back to the…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
LOG_FILE="chess_script.log" | |
log() { | |
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" | |
} | |
# Requesting sudo privileges at the start | |
log "Requesting sudo privileges..." | |
sudo -v | |
if [ $? -ne 0 ]; then | |
log "Error: Failed to obtain sudo privileges." | |
exit 1 | |
fi | |
# Keep sudo privileges alive while the script runs | |
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null & | |
# Log the start of the script | |
log "Starting Chess script..." | |
# Launch Chess if it's not running | |
sleep 1 | |
if ! pgrep -x "Chess" > /dev/null; then | |
log "Chess is not running. Launching Chess..." | |
open -a Chess | |
sleep 2 # Give it a moment to open | |
if pgrep -x "Chess" > /dev/null; then | |
log "Chess launched successfully." | |
else | |
log "Error: Failed to launch Chess." | |
exit 1 | |
fi | |
else | |
log "Chess is already running." | |
fi | |
sleep 1 | |
# Make Chess fullscreen by simulating the keystroke Command + Control + F | |
osascript -e 'tell application "System Events" to keystroke "f" using {command down, control down}' | |
if [ $? -eq 0 ]; then | |
log "Chess set to fullscreen successfully." | |
else | |
log "Error: Failed to set Chess to fullscreen." | |
fi | |
sleep 1 | |
# Switch to desktop space by simulating the keystroke Control + Left Arrow | |
osascript -e 'tell application "System Events" to key code 123 using {control down}' | |
if [ $? -eq 0 ]; then | |
log "Switched focus to desktop successfully." | |
else | |
log "Error: Failed to switch focus to desktop." | |
fi | |
sleep 1 | |
# Get the process ID of Chess | |
chess_pid=$(pgrep -x "Chess") | |
# Lower the priority of Chess to give more CPU to other processes (-n 20 makes it the lowest priority) | |
if [ ! -z "$chess_pid" ]; then | |
log "Setting Chess process priority to lowest (nice value 20)..." | |
sudo renice 20 -p $chess_pid | |
if [ $? -eq 0 ]; then | |
log "Chess priority set successfully." | |
else | |
log "Error: Failed to set Chess priority." | |
fi | |
else | |
log "Error: Unable to retrieve Chess process ID." | |
exit 1 | |
fi | |
sleep 1 | |
# List all active window processes and allow the user to pick one to change its priority | |
log "Listing active window processes..." | |
active_processes=$(osascript -e 'tell application "System Events" to get the name of every application process whose visible is true') | |
IFS=", " read -r -a process_array <<< "$active_processes" | |
echo "Active window processes:" | |
for i in "${!process_array[@]}"; do | |
echo "[$i] ${process_array[$i]}" | |
done | |
read -p "Enter the number of the process you want to change the priority for: " process_number | |
if [[ $process_number -ge 0 && $process_number -lt ${#process_array[@]} ]]; then | |
selected_process="${process_array[$process_number]}" | |
selected_pid=$(pgrep -x "$selected_process") | |
if [ -z "$selected_pid" ]; then | |
log "Error: Unable to retrieve process ID for $selected_process." | |
exit 1 | |
fi | |
read -p "Enter the new priority for $selected_process (-20 for max, 0 for average, 20 for lowest): " new_priority | |
if [[ $new_priority =~ ^-?[0-9]+$ && $new_priority -ge -20 && $new_priority -le 20 ]]; then | |
log "Setting priority of $selected_process (PID: $selected_pid) to $new_priority..." | |
sudo renice $new_priority -p $selected_pid | |
if [ $? -eq 0 ]; then | |
log "$selected_process priority set to $new_priority successfully." | |
else | |
log "Error: Failed to set priority for $selected_process." | |
fi | |
else | |
log "Invalid priority value: $new_priority. Please enter a value between -20 and 20." | |
exit 1 | |
fi | |
else | |
log "Invalid selection. Please enter a number between 0 and $((${#process_array[@]} - 1))." | |
exit 1 | |
fi | |
sleep 1 | |
log "Chess script completed." |
Hello, i've improved your code as it seems you don't need to run Chess app. Here's the revised code:
#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Requesting sudo privileges at the start
echo "${BLUE}Requesting sudo privileges...${NC}"
sudo -v
if [ $? -ne 0 ]; then
echo "${RED}Error: Failed to obtain sudo privileges.${NC}"
exit 1
fi
# Keep sudo privileges alive while the script runs
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
# Prompt the user for selecting an option
while true; do
while true; do
echo "${BLUE}Select an option:${RED}"
echo "WARNING: Enabling Game mode for your process MAY or MAY NOT improve its overall performance.\nThus, keep this in mind while using this tool. In case you encounter "errors" after launching\nyour game or seems slower, restart your Mac.\n\nIf a process is already running in Game mode, please set first its priority number to 20. ${YELLOW}"
echo "[1] Revert Game mode default behavior"
echo "[2] Force Game mode on and run it for a specific software"
echo "[3] Exit"
read -p "$(echo ${BLUE}Enter the number of the option you want to select:${NC})" user_option
if [[ $user_option -eq 1 || $user_option -eq 2 || $user_option -eq 3 ]]; then
break
else
echo "${RED}Invalid option. Please enter 1, 2, or 3.${NC}"
fi
done
if [[ $user_option -eq 1 ]]; then
# Revert Game mode default behavior
sudo /Applications/Xcode.app/Contents/Developer/usr/bin/gamepolicyctl game-mode set auto
echo "${GREEN}Successfully restored Game mode default behavior.${NC}"
exit 0
elif [[ $user_option -eq 2 ]]; then
# Force Game mode on
sudo /Applications/Xcode.app/Contents/Developer/usr/bin/gamepolicyctl game-mode set on
# List all active window processes and allow the user to pick one to change its priority
echo "${BLUE}Listing active window processes...${NC}"
active_processes=$(osascript -e 'tell application "System Events" to get the name of every application process whose visible is true')
# Split the active_processes output by comma and handle multi-word process names correctly
IFS=","
read -r -a process_array <<< "$active_processes"
echo "${BLUE}Active window processes:${NC}"
for i in "${!process_array[@]}"; do
process_name=$(echo "${process_array[$i]}" | xargs)
echo "${YELLOW} [$i] $process_name${NC}"
done
# Select a process ID
while true; do
read -p "$(echo ${BLUE}Enter the number of the process you want to change the priority for:${NC})" process_number
if [[ $process_number -ge 0 && $process_number -lt ${#process_array[@]} ]]; then
selected_process=$(echo "${process_array[$process_number]}" | xargs)
selected_pid=$(pgrep -x "$selected_process")
if [ -z "$selected_pid" ]; then
echo "${RED}Error: Unable to retrieve process ID for $selected_process.${NC}"
else
break
fi
else
echo "${RED}Invalid selection. Please enter a number between 0 and $((${#process_array[@]} - 1)).${NC}"
fi
done
# Set the priority number of the selected process
while true; do
read -p "$(echo ${BLUE}Enter the new priority for $selected_process. -20 for max, 0 for average, 20 for lowest:${NC})" new_priority
if [[ $new_priority =~ ^-?[0-9]+$ && $new_priority -ge -20 && $new_priority -le 20 ]]; then
echo "${GREEN}Setting priority of $selected_process (PID: $selected_pid) to $new_priority...${NC}"
sudo renice $new_priority -p $selected_pid
if [ $? -eq 0 ]; then
echo "${GREEN}$selected_process priority set to $new_priority successfully.${NC}"
exit 0
else
echo "${RED}Error: Failed to set priority for $selected_process.${NC}"
fi
else
echo "${RED}Invalid priority value: $new_priority. Please enter a value between -20 and 20.${NC}"
fi
done
elif [[ $user_option -eq 3 ]]; then
exit 0
fi
done
sleep 1
echo "${GREEN}Game mode script completed.${NC}"
well done, but it doesnt work for me on macos 15.4 beta 2, so i changed some stuff: https://gist.github.com/daburykin/7a71a5cf92e198c627eb3e169c50f1ba
Welp the user above deleted his account, does anyone have the updated script?
Hello, I’ve tried out a new version. Jules from Google created this custom version. He mentions that this commit "significantly refactors and improves the chess_script.sh."
#!/bin/bash
#
# chess_script.sh: A script to manage macOS Game Mode and process priorities.
# This script allows users to:
# 1. Revert Game Mode to its default behavior.
# 2. Force Game Mode on and set the priority of a selected application.
# It requires sudo privileges for some operations.
# Color definitions for script output
RED='\033[0;31m' # Red
GREEN='\033[0;32m' # Green
YELLOW='\033[0;33m' # Yellow
BLUE='\033[0;34m' # Blue
NC='\033[0m' # No Color (to reset to default)
# Define the path to gamepolicyctl
GAMEPOLICYCTL_PATH="/Applications/Xcode.app/Contents/Developer/usr/bin/gamepolicyctl"
# Check if gamepolicyctl exists
if [ ! -f "$GAMEPOLICYCTL_PATH" ]; then
echo "${RED}Error: gamepolicyctl not found at $GAMEPOLICYCTL_PATH. Please ensure Xcode Command Line Tools are installed.${NC}"
exit 1
fi
# Function to request sudo privileges
# Prompts the user for sudo password upfront using `sudo -v`.
# Exits script if sudo privileges are not obtained.
# Side effects: Caches sudo credentials for subsequent sudo commands.
request_sudo() {
echo "${BLUE}This script needs sudo privileges for some operations.${NC}"
echo "${BLUE}Requesting sudo privileges upfront...${NC}"
sudo -v
if [ $? -ne 0 ]; then
echo "${RED}Error: Failed to obtain sudo privileges. Please run the script again and enter your password when prompted.${NC}"
exit 1
fi
echo "${GREEN}Sudo privileges obtained. Specific commands will be run with sudo.${NC}"
}
# Function to display the menu and get user input
# Populates the global variable `user_option` with the user's choice.
# Loops until a valid option (1, 2, or 3) is entered.
display_menu() {
while true; do
echo "${BLUE}Select an option:${RED}"
echo "WARNING: Enabling Game mode for your process MAY or MAY NOT improve its overall performance.\nThus, keep this in mind while using this tool. In case you encounter "errors" after launching\nyour game or seems slower, restart your Mac.\n\nIf a process is already running in Game mode, please set first its priority number to 20. ${YELLOW}"
echo "[1] Revert Game mode default behavior"
echo "[2] Force Game mode on and run it for a specific software"
echo "[3] Exit"
read -p "$(echo ${BLUE}Enter the number of the option you want to select:${NC})" user_option
if [[ $user_option -eq 1 || $user_option -eq 2 || $user_option -eq 3 ]]; then
break # Exit loop if option is valid
else
echo "${RED}Invalid option. Please enter 1, 2, or 3.${NC}"
fi
done
}
# Function to revert Game mode default behavior
# Uses `gamepolicyctl` to set Game Mode to 'auto'.
# Exits the script with 0 on success, 1 on failure.
revert_game_mode() {
echo "${BLUE}Reverting Game mode to default behavior...${NC}" # Added info message
sudo "$GAMEPOLICYCTL_PATH" game-mode set auto
if [ $? -ne 0 ]; then
echo "${RED}Error: Failed to revert Game mode to default behavior.${NC}"
exit 1 # Exit with error status
else
echo "${GREEN}Successfully restored Game mode default behavior.${NC}"
exit 0 # Exit with success status
fi
}
# Function to force Game mode on
# Uses `gamepolicyctl` to set Game Mode to 'on'.
# Returns: 0 on success, 1 on failure.
force_game_mode() {
echo "${BLUE}Forcing Game mode on...${NC}" # Added info message
sudo "$GAMEPOLICYCTL_PATH" game-mode set on
if [ $? -ne 0 ]; then
echo "${RED}Error: Failed to force Game mode on.${NC}"
return 1 # Return with an error code
fi
echo "${GREEN}Game mode forced on successfully.${NC}" # Added success message
return 0 # Return with a success code
}
# Function to list active processes
# Uses AppleScript to get a list of visible application processes with their names and PIDs.
# Populates the global array `process_array` with entries like "AppName (PID: 123)".
# Returns: 0 on success, 1 if osascript fails or no processes are found.
list_active_processes() {
echo "${BLUE}Listing active window processes...${NC}"
local osascript_output # Variable to store raw output from osascript
# AppleScript to get process names and PIDs, newline-separated
osascript_output=$(osascript -e '
tell application "System Events"
set procs to every application process whose visible is true
set output_list to {}
repeat with p in procs
set end of output_list to (name of p & " (PID: " & unix id of p & ")")
end repeat
return output_list
end tell
')
if [ -z "$osascript_output" ]; then
echo "${RED}Error: Could not retrieve process list from osascript.${NC}"
return 1
fi
# Convert comma-separated string from osascript to an array
# osascript returns items separated by ", "
IFS=$'\n' # Temporarily change IFS to newline if osascript -e 'return output_list' returns newline separated items
# If osascript returns "item1, item2, item3", then the original IFS approach was better.
# Let's assume osascript -e 'return output_list' where output_list is an AppleScript list
# results in a string where items are separated by ", ".
# Read the osascript output into an array, splitting by ", "
# This is tricky because process names can have spaces, but not typically commas.
# The AppleScript list coerced to string is "item1, item2, item3"
# We will store each "AppName (PID: 123)" as a single array element.
# Reset IFS to default for other commands
# Store process strings directly into process_array
# The osascript output for a list is "item1, item2, item3"
# We need to make this an array in bash.
# `read -r -a my_array <<< $(echo "$str" | tr ',' '\n')` doesn't work if items have spaces.
# A safer way for "Name1 (PID: 123), Name2 (PID: 456)"
# Let's change applescript to return newline separated items
osascript_output=$(osascript -e '
tell application "System Events"
set procs to every application process whose visible is true
set output_str to ""
repeat with p in procs
set output_str to output_str & name of p & " (PID: " & unix id of p & ")" & "\n"
end repeat
return output_str
end tell
')
# Check if osascript command was successful and produced output
if [ -z "$osascript_output" ]; then
echo "${RED}Error: Could not retrieve process list from osascript.${NC}" # Simplified error message
return 1 # Indicate failure
fi
# Read newline-separated osascript output into process_array (Bash 3 compatible)
process_array=() # Initialize an empty array
while IFS= read -r line; do
if [[ -n "$line" ]]; then # Ensure the line is not empty
process_array+=("$line")
fi
done <<< "$osascript_output" # Feed the osascript_output to the loop
# Safeguard: Remove any empty elements from process_array that might result from extra newlines
# This might be redundant due to the `if [[ -n "$line" ]]` check above, but kept for safety.
local i
for i in "${!process_array[@]}"; do
[[ -z "${process_array[$i]}" ]] && unset "process_array[$i]"
done
# Re-index array to ensure it's contiguous if elements were unset
process_array=("${process_array[@]}")
# Check if any processes were found
if [ ${#process_array[@]} -eq 0 ]; then
echo "${RED}No active window processes found.${NC}"
return 1 # Indicate failure
fi
echo "${BLUE}Active window processes:${NC}"
for i in "${!process_array[@]}"; do
echo "${YELLOW} [$i] ${process_array[$i]}${NC}" # Display each process with its index
done
return 0 # Indicate success
}
# Function to select a process from the list provided by list_active_processes
# Prompts the user to enter the number of the process.
# Parses the selected entry to extract process name and PID.
# Populates global variables: `selected_process` (name) and `selected_pid` (PID).
# Returns: 0 on successful selection and parsing, 1 if the process no longer exists or parsing fails.
select_process() {
while true; do
read -p "$(echo ${BLUE}Enter the number of the process you want to change the priority for:${NC})" process_number
# Validate if the entered number is within the bounds of the process_array
if [[ $process_number -ge 0 && $process_number -lt ${#process_array[@]} ]]; then
local selected_entry="${process_array[$process_number]}"
# Parse selected_entry "AppName (PID: 123)" to extract PID and AppName
# PID: Extracts digits between "(PID: " and ")"
selected_pid=$(echo "$selected_entry" | sed -n 's/.*(PID: \([0-9]*\)).*/\1/p')
# AppName: Extracts the part before " (PID: ..."
selected_process_name=$(echo "$selected_entry" | sed -n 's/\(.*\) (PID: [0-9]*).*/\1/p')
# Check if parsing was successful
if [ -z "$selected_pid" ] || [ -z "$selected_process_name" ]; then
echo "${RED}Error: Could not parse PID or name from '$selected_entry'. Please try again.${NC}"
# Loop again for user to re-select
continue
fi
# Verify the process with the extracted PID still exists
if ! ps -p "$selected_pid" > /dev/null; then
echo "${RED}Error: Process $selected_process_name (PID: $selected_pid) no longer exists. Please select another process.${NC}"
return 1 # Indicate failure, main loop should refresh or exit to menu
fi
# Set global variables for use in set_process_priority
selected_process="$selected_process_name"
echo "${GREEN}Selected: $selected_process (PID: $selected_pid)${NC}" # Confirmation message
break # Exit loop as selection is valid
else
echo "${RED}Invalid selection. Please enter a number between 0 and $((${#process_array[@]} - 1)).${NC}"
fi
done
return 0 # Indicate success
}
# Function to set the priority (nice value) of the selected process
# Uses `renice` command with sudo.
# `selected_process` (name) and `selected_pid` (PID) global variables should be set before calling.
# Exits script with 0 on success. Loops on failure to set priority or invalid input.
set_process_priority() {
while true; do
# Prompt user for priority, ensuring parentheses in the prompt are escaped for `read -p`
read -p "$(echo -e "${BLUE}Enter the new priority for $selected_process \(PID: $selected_pid\). Value from -20 \(max\) to 20 \(lowest\):${NC}")" new_priority
# Validate priority is an integer between -20 and 20
if [[ $new_priority =~ ^-?[0-9]+$ && $new_priority -ge -20 && $new_priority -le 20 ]]; then
echo "${GREEN}Setting priority of $selected_process (PID: $selected_pid) to $new_priority...${NC}"
sudo renice "$new_priority" -p "$selected_pid" # Added quotes for safety
if [ $? -eq 0 ]; then
echo "${GREEN}$selected_process priority set to $new_priority successfully.${NC}"
exit 0 # Exit script successfully
else
echo "${RED}Error: Failed to set priority for $selected_process. Check permissions or PID.${NC}" # Slightly more info
# Loop again to allow user to retry or enter different value
fi
else
echo "${RED}Invalid priority value: $new_priority. Please enter an integer value between -20 and 20.${NC}"
fi
done
}
# Main script execution
# This is the main control flow of the script.
request_sudo
# Prompt the user for selecting an option
while true; do
display_menu
if [[ $user_option -eq 1 ]]; then
revert_game_mode
elif [[ $user_option -eq 2 ]]; then
force_game_mode
if [ $? -ne 0 ]; then
continue
fi
list_active_processes
if [ $? -ne 0 ]; then # Check if listing processes failed
continue # Go back to main menu
fi
select_process
if [ $? -ne 0 ]; then # Check if selecting process failed (e.g. process died)
# Potentially refresh list here or just go back to menu
echo "${YELLOW}Process selection failed or process died. Returning to main menu.${NC}"
continue # Go back to main menu
fi
set_process_priority
elif [[ $user_option -eq 3 ]]; then
exit 0
fi
done
sleep 1
echo "${GREEN}Game mode script completed.${NC}"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
First of all thank you so much for that, I've been waiting for such thing for softwares like UEFN. Can't wait to test it!