refactor: major architectural restructure for theme-centric organization
Theme System: - Move all theme app configs to apps/ subdirectory (20 themes) - Add theme-loader.nix for dynamic theme config deployment - Simplify stylix.nix to focus on base theming only Override System: - Add overrides.nix for file-based config overrides - Add behavior-configs.nix for non-visual configuration - Split hypr/nomarchy.conf into behavior vs visual sections Module Improvements: - Add lib.mkDefault to all customizable settings - Add modules/lib/ with shared utilities and state schema - Update all home and system modules for downstream overridability Installer: - New minimal TTY installer (installer/install.sh) - Golden path: BTRFS + LUKS2 (disko-golden.nix) - New installer-iso.nix for TTY-only installation - Keep graphical installer as installerIsoGraphical option Cleanup: - Remove obsolete install.sh, disko-ext4.nix, install-nomarchy.sh - Update live-iso.nix references - Add .claude/ to .gitignore for local IDE settings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,13 +14,13 @@ if [ ! -f "$STATE_FILE" ]; then
|
||||
echo "[]" > "$STATE_FILE"
|
||||
fi
|
||||
|
||||
if jq -e ". | index(\"$PKG_NAME\")" "$STATE_FILE" >/dev/null; then
|
||||
if jq -e --arg pkg "$PKG_NAME" '. | index($pkg)' "$STATE_FILE" >/dev/null; then
|
||||
echo "Package $PKG_NAME is already in your user-packages.json"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Append package to the JSON array
|
||||
jq ". + [\"$PKG_NAME\"]" "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
||||
# Append package to the JSON array safely
|
||||
jq --arg pkg "$PKG_NAME" '. + [$pkg]' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
||||
|
||||
echo "Package $PKG_NAME added declaratively to $STATE_FILE."
|
||||
echo "Applying changes with env-update..."
|
||||
|
||||
@@ -14,13 +14,13 @@ if [ ! -f "$STATE_FILE" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! jq -e ". | index(\"$PKG_NAME\")" "$STATE_FILE" >/dev/null; then
|
||||
if ! jq -e --arg pkg "$PKG_NAME" '. | index($pkg)' "$STATE_FILE" >/dev/null; then
|
||||
echo "Package $PKG_NAME is not in your user-packages.json"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Remove package from the JSON array
|
||||
jq ". - [\"$PKG_NAME\"]" "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
||||
# Remove package from the JSON array safely
|
||||
jq --arg pkg "$PKG_NAME" '. - [$pkg]' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
||||
|
||||
echo "Package $PKG_NAME removed declaratively from $STATE_FILE."
|
||||
echo "Applying changes with env-update..."
|
||||
|
||||
@@ -2,22 +2,32 @@
|
||||
# Nomarchy Pre-flight State Migration
|
||||
# Migrates legacy state files into the unified state.json before Nix evaluation
|
||||
|
||||
STATE_DIR="$HOME/.config/home-manager"
|
||||
STATE_DIR="$HOME/.config/nomarchy"
|
||||
OLD_STATE_DIR="$HOME/.config/home-manager"
|
||||
OLD_TOGGLES_DIR="$HOME/.local/state/nomarchy/toggles"
|
||||
IDLE_STATE_FILE="$STATE_DIR/idle-state.json"
|
||||
NIGHTLIGHT_STATE_FILE="$STATE_DIR/hyprsunset-state.json"
|
||||
HYPRLAND_STATE_FILE="$STATE_DIR/hyprland-state.json"
|
||||
THEME_STATE_FILE="$STATE_DIR/theme-state.nix"
|
||||
WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix"
|
||||
FONT_STATE_FILE="$STATE_DIR/font-state.nix"
|
||||
IDLE_STATE_FILE="$OLD_STATE_DIR/idle-state.json"
|
||||
NIGHTLIGHT_STATE_FILE="$OLD_STATE_DIR/hyprsunset-state.json"
|
||||
HYPRLAND_STATE_FILE="$OLD_STATE_DIR/hyprland-state.json"
|
||||
THEME_STATE_FILE="$OLD_STATE_DIR/theme-state.nix"
|
||||
WALLPAPER_STATE_FILE="$OLD_STATE_DIR/wallpaper-state.nix"
|
||||
FONT_STATE_FILE="$OLD_STATE_DIR/font-state.nix"
|
||||
OLD_STATE_FILE="$OLD_STATE_DIR/state.json"
|
||||
NEW_STATE_FILE="$STATE_DIR/state.json"
|
||||
|
||||
# We expect jq to be in PATH (it's a dependency of nomarchy-scripts)
|
||||
JQ="jq"
|
||||
|
||||
mkdir -p "$(dirname "$NEW_STATE_FILE")"
|
||||
mkdir -p "$STATE_DIR"
|
||||
[[ ! -f $NEW_STATE_FILE ]] && echo "{}" > "$NEW_STATE_FILE"
|
||||
|
||||
# 0. Migrate from old home-manager state.json location
|
||||
if [[ -f "$OLD_STATE_FILE" ]] && [[ "$OLD_STATE_FILE" != "$NEW_STATE_FILE" ]]; then
|
||||
# Merge old state into new state
|
||||
TMP_FILE=$(mktemp)
|
||||
$JQ -s '.[0] * .[1]' "$OLD_STATE_FILE" "$NEW_STATE_FILE" > "$TMP_FILE" && mv "$TMP_FILE" "$NEW_STATE_FILE"
|
||||
rm "$OLD_STATE_FILE" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 1. Migrate .local/state/nomarchy/toggles
|
||||
if [[ -d $OLD_TOGGLES_DIR ]]; then
|
||||
for file in "$OLD_TOGGLES_DIR"/*; do
|
||||
@@ -43,7 +53,7 @@ fi
|
||||
if [[ -f $IDLE_STATE_FILE ]]; then
|
||||
ENABLED=$($JQ '.enabled' "$IDLE_STATE_FILE")
|
||||
if [[ "$ENABLED" == "true" || "$ENABLED" == "false" ]]; then
|
||||
$JQ ".idle = $ENABLED" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
$JQ --argjson val "$ENABLED" '.idle = $val' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
fi
|
||||
rm "$IDLE_STATE_FILE"
|
||||
fi
|
||||
@@ -51,7 +61,7 @@ fi
|
||||
if [[ -f $NIGHTLIGHT_STATE_FILE ]]; then
|
||||
ENABLED=$($JQ '.enabled' "$NIGHTLIGHT_STATE_FILE")
|
||||
TEMP=$($JQ '.temperature' "$NIGHTLIGHT_STATE_FILE")
|
||||
$JQ ".nightlight = $ENABLED | .nightlightTemperature = $TEMP" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
$JQ --argjson enabled "$ENABLED" --argjson temp "$TEMP" '.nightlight = $enabled | .nightlightTemperature = $temp' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
rm "$NIGHTLIGHT_STATE_FILE"
|
||||
fi
|
||||
|
||||
@@ -59,25 +69,25 @@ if [[ -f $HYPRLAND_STATE_FILE ]]; then
|
||||
GAPS_OUT=$($JQ '.gaps_out' "$HYPRLAND_STATE_FILE")
|
||||
GAPS_IN=$($JQ '.gaps_in' "$HYPRLAND_STATE_FILE")
|
||||
BORDER_SIZE=$($JQ '.border_size' "$HYPRLAND_STATE_FILE")
|
||||
$JQ ".hyprland = {\"gaps_out\": $GAPS_OUT, \"gaps_in\": $GAPS_IN, \"border_size\": $BORDER_SIZE}" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
$JQ --argjson go "$GAPS_OUT" --argjson gi "$GAPS_IN" --argjson bs "$BORDER_SIZE" '.hyprland = {"gaps_out": $go, "gaps_in": $gi, "border_size": $bs}' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
rm "$HYPRLAND_STATE_FILE"
|
||||
fi
|
||||
|
||||
# 3. Migrate plaintext string state files
|
||||
if [[ -f $THEME_STATE_FILE ]]; then
|
||||
THEME=$(cat "$THEME_STATE_FILE" | tr -d '\n')
|
||||
$JQ ".theme = \"$THEME\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
$JQ --arg theme "$THEME" '.theme = $theme' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
rm "$THEME_STATE_FILE"
|
||||
fi
|
||||
|
||||
if [[ -f $WALLPAPER_STATE_FILE ]]; then
|
||||
WALLPAPER=$(cat "$WALLPAPER_STATE_FILE" | tr -d '\n')
|
||||
$JQ ".wallpaper = \"$WALLPAPER\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
$JQ --arg wp "$WALLPAPER" '.wallpaper = $wp' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
rm "$WALLPAPER_STATE_FILE"
|
||||
fi
|
||||
|
||||
if [[ -f $FONT_STATE_FILE ]]; then
|
||||
FONT=$(cat "$FONT_STATE_FILE" | tr -d '\n')
|
||||
$JQ ".font = \"$FONT\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
$JQ --arg font "$FONT" '.font = $font' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE"
|
||||
rm "$FONT_STATE_FILE"
|
||||
fi
|
||||
|
||||
@@ -13,7 +13,7 @@ fi
|
||||
|
||||
case "$dns" in
|
||||
Cloudflare|Google|DHCP)
|
||||
sudo jq ".dns = \"$dns\"" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
sudo jq --arg dns "$dns" '.dns = $dns' "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
;;
|
||||
|
||||
Custom)
|
||||
@@ -24,10 +24,10 @@ Custom)
|
||||
echo "Error: No DNS servers provided."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Convert to JSON array
|
||||
|
||||
# Convert to JSON array safely
|
||||
dns_array=$(echo "$dns_servers" | jq -R 'split(" ")')
|
||||
sudo jq ".dns = \"Custom\" | .customDns = $dns_array" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
sudo jq --arg dns "Custom" --argjson servers "$dns_array" '.dns = $dns | .customDns = $servers' "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
STATE_FILE="/etc/nixos/state.json"
|
||||
|
||||
if [[ "--remove" == $1 ]]; then
|
||||
sudo jq ".features.fido2 = false" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
sudo jq '.features.fido2 = false' "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
echo "FIDO2 support disabled. Applying changes..."
|
||||
sudo sys-update
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sudo jq ".features.fido2 = true" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
sudo jq '.features.fido2 = true' "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
echo "FIDO2 support enabled. Applying changes..."
|
||||
sudo sys-update
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
STATE_FILE="/etc/nixos/state.json"
|
||||
|
||||
if [[ "--remove" == $1 ]]; then
|
||||
sudo jq ".features.fingerprint = false" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
sudo jq '.features.fingerprint = false' "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
echo "Fingerprint support disabled. Applying changes..."
|
||||
sudo sys-update
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sudo jq ".features.fingerprint = true" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
sudo jq '.features.fingerprint = true' "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
echo "Fingerprint support enabled. Applying changes..."
|
||||
sudo sys-update
|
||||
|
||||
|
||||
@@ -3,24 +3,25 @@
|
||||
# Toggles the idle daemon (hypridle) between enabled and disabled.
|
||||
# Hybrid: updates state.json and provides instant feedback.
|
||||
|
||||
STATE_FILE="$HOME/.config/home-manager/state.json"
|
||||
mkdir -p "$(dirname "$STATE_FILE")"
|
||||
STATE_DIR="$HOME/.config/nomarchy"
|
||||
STATE_FILE="$STATE_DIR/state.json"
|
||||
mkdir -p "$STATE_DIR"
|
||||
|
||||
# Initialize if doesn't exist
|
||||
[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE"
|
||||
|
||||
if [[ $NNOMARCHY_TOGGLE_IDLE == "false" ]]; then
|
||||
if [[ $NOMARCHY_TOGGLE_IDLE == "false" ]]; then
|
||||
NEW_VALUE="true"
|
||||
setsid hypridle >/dev/null 2>&1 &
|
||||
notify-send -u low " Now locking computer when idle"
|
||||
notify-send -u low " Now locking computer when idle"
|
||||
else
|
||||
NEW_VALUE="false"
|
||||
pkill -x hypridle
|
||||
notify-send -u low " Stop locking computer when idle"
|
||||
notify-send -u low " Stop locking computer when idle"
|
||||
fi
|
||||
|
||||
TMP_JSON=$(mktemp)
|
||||
jq ".idle = $NEW_VALUE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE"
|
||||
jq --argjson val "$NEW_VALUE" '.idle = $val' "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE"
|
||||
|
||||
echo "Idle state set to $NEW_VALUE. Environment will be fully updated on next rebuild."
|
||||
|
||||
|
||||
@@ -3,25 +3,25 @@
|
||||
# Toggles the suspend menu option availability.
|
||||
# Hybrid: updates state.json and runs env-update for persistence.
|
||||
|
||||
STATE_FILE="$HOME/.config/home-manager/state.json"
|
||||
mkdir -p "$(dirname "$STATE_FILE")"
|
||||
STATE_DIR="$HOME/.config/nomarchy"
|
||||
STATE_FILE="$STATE_DIR/state.json"
|
||||
mkdir -p "$STATE_DIR"
|
||||
|
||||
# Initialize if doesn't exist
|
||||
[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE"
|
||||
|
||||
# Get current state from env or state file
|
||||
if [[ $NNOMARCHY_TOGGLE_SUSPEND == "false" ]]; then
|
||||
if [[ $NOMARCHY_TOGGLE_SUSPEND == "false" ]]; then
|
||||
NEW_VALUE="true"
|
||||
notify-send -u low " Suspend now available in system menu"
|
||||
notify-send -u low " Suspend now available in system menu"
|
||||
else
|
||||
NEW_VALUE="false"
|
||||
notify-send -u low " Suspend removed from system menu"
|
||||
notify-send -u low " Suspend removed from system menu"
|
||||
fi
|
||||
|
||||
# Update JSON using jq
|
||||
# We use a temporary file to avoid corruption if the shell is interrupted
|
||||
# Update JSON using jq with --argjson for proper boolean handling
|
||||
TMP_JSON=$(mktemp)
|
||||
jq ".suspend = $NEW_VALUE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE"
|
||||
jq --argjson val "$NEW_VALUE" '.suspend = $val' "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE"
|
||||
|
||||
echo "Suspend availability set to $NEW_VALUE. Updating environment..."
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ STATE_FILE="/etc/nixos/state.json"
|
||||
|
||||
timezone=$(timedatectl list-timezones | gum filter --height 20 --header "Set timezone") || exit 1
|
||||
|
||||
sudo jq ".timezone = \"$timezone\"" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
sudo jq --arg tz "$timezone" '.timezone = $tz' "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE"
|
||||
|
||||
echo "Timezone is now set to $timezone. Applying changes..."
|
||||
sudo sys-update
|
||||
|
||||
Reference in New Issue
Block a user