Compare commits
7 Commits
2bd9ebc5da
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f9073ee40 | |||
| d756e966b1 | |||
| fa4591c6b3 | |||
| 329703abf0 | |||
| 43cdb7c747 | |||
| 5dd038586f | |||
| 532bc09e26 |
91
home/sam/bin/task-due-notify.sh
Executable file
91
home/sam/bin/task-due-notify.sh
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/nix/store/x12lw455sq6qy2wcya85d7rb88ybc3df-bash-interactive-5.3p9/bin/bash
|
||||||
|
|
||||||
|
# Simple Taskwarrior Notification Script
|
||||||
|
# Just checks: if time_until_due <= reminder_time, send notification
|
||||||
|
|
||||||
|
NTFY_URL="https://ntfy.lab.audasmedia.com.au/tasks"
|
||||||
|
NOW=$(date -u +%s)
|
||||||
|
|
||||||
|
# Auto-add +notify to tasks with due dates or remind tags
|
||||||
|
task status:pending '( due.any: or tags.has:remindMins or tags.has:remindHours or tags.has:remindDays or tags.has:remindWeeks or tags.has:remindMonths )' -notify export 2>/dev/null | \
|
||||||
|
/nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -r '.[].uuid' 2>/dev/null | \
|
||||||
|
while read -r uuid; do
|
||||||
|
/nix/store/syqlfcifpih00fknzailx8xxn4cnv42d-taskwarrior-3.4.2/bin/task "$uuid" modify +notify 2>/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
# Process tasks with +notify
|
||||||
|
task status:pending +notify export 2>/dev/null | \
|
||||||
|
/nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -c '.[] | select(.due) | {uuid: .uuid, description: .description, due: .due, tags: .tags}' 2>/dev/null | \
|
||||||
|
while read -r task_json; do
|
||||||
|
|
||||||
|
uuid=$(echo "$task_json" | /nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -r '.uuid')
|
||||||
|
desc=$(echo "$task_json" | /nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -r '.description')
|
||||||
|
due_date=$(echo "$task_json" | /nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -r '.due')
|
||||||
|
tags=$(echo "$task_json" | /nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -r '.tags[]? // empty' 2>/dev/null)
|
||||||
|
|
||||||
|
# Convert due date (UTC) to epoch
|
||||||
|
formatted_date=$(echo "$due_date" | /nix/store/ryz8kcrm2bxpccllfqlb7qldsfnqp5c2-gnused-4.9/bin/sed 's/T/ /; s/Z$//; s/^\(....\)\(..\)\(..\)/\1-\2-\3/; s/ \(..\)\(..\)\(..\)$/ \1:\2:\3/')
|
||||||
|
due_epoch=$(/nix/store/i2vmgx46q9hd3z6rigaiman3wl3i2gc4-coreutils-9.9/bin/date -d "$formatted_date UTC" +%s 2>/dev/null || echo 0)
|
||||||
|
|
||||||
|
if [ "$due_epoch" = "0" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
time_until_due=$((due_epoch - NOW))
|
||||||
|
|
||||||
|
# Check reminder tags
|
||||||
|
echo "$tags" | /nix/store/02vv0r262agf9j5n2y1gmbjvdf12zkl0-gnugrep-3.12/bin/grep -E '^remind(Mins|Hours|Days|Weeks|Months)' 2>/dev/null | \
|
||||||
|
while read -r remind_tag; do
|
||||||
|
|
||||||
|
# Parse: remindMins2, remindHours1, etc
|
||||||
|
if [[ "$remind_tag" =~ ^remind(Mins|Hours|Days|Weeks|Months)([0-9]+)$ ]]; then
|
||||||
|
unit="${BASH_REMATCH[1]}"
|
||||||
|
num="${BASH_REMATCH[2]}"
|
||||||
|
|
||||||
|
# Convert to seconds
|
||||||
|
case "$unit" in
|
||||||
|
Mins) remind_secs=$((num * 60)); time_str="$num minutes" ;;
|
||||||
|
Hours) remind_secs=$((num * 3600)); time_str="$num hours" ;;
|
||||||
|
Days) remind_secs=$((num * 86400)); time_str="$num days" ;;
|
||||||
|
Weeks) remind_secs=$((num * 604800)); time_str="$num weeks" ;;
|
||||||
|
Months) remind_secs=$((num * 2592000)); time_str="$num months" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# SIMPLE: If time until due <= reminder time AND still in future, send it
|
||||||
|
if [ $time_until_due -le $remind_secs ] && [ $time_until_due -gt 0 ]; then
|
||||||
|
/nix/store/xgdl4gzjzwj7ixs83f17sqppd08lfd03-libnotify-0.8.7/bin/notify-send -u normal "Reminder" "🔔 $desc - Due in $time_str"
|
||||||
|
/nix/store/jqfr3p49g3lch84y45jfzw9fshlv8jyp-curl-8.17.0-bin/bin/curl -s -d "Reminder: $desc - Due in $time_str" "$NTFY_URL" >/dev/null 2>&1 &
|
||||||
|
/nix/store/syqlfcifpih00fknzailx8xxn4cnv42d-taskwarrior-3.4.2/bin/task "$uuid" modify -"$remind_tag" 2>/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if task is due (overdue)
|
||||||
|
if [ $time_until_due -le 0 ] && ! echo "$tags" | /nix/store/02vv0r262agf9j5n2y1gmbjvdf12zkl0-gnugrep-3.12/bin/grep -q "^notified$"; then
|
||||||
|
/nix/store/xgdl4gzjzwj7ixs83f17sqppd08lfd03-libnotify-0.8.7/bin/notify-send -u critical "Task Due" "⚠️ $desc"
|
||||||
|
/nix/store/jqfr3p49g3lch84y45jfzw9fshlv8jyp-curl-8.17.0-bin/bin/curl -s -d "Task due: $desc" "$NTFY_URL" >/dev/null 2>&1 &
|
||||||
|
/nix/store/syqlfcifpih00fknzailx8xxn4cnv42d-taskwarrior-3.4.2/bin/task "$uuid" modify +notified 2>/dev/null
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Cleanup: Remove notification tags from completed/deleted tasks
|
||||||
|
task '( status:completed or status:deleted )' '( +notify or +notified or tags.has:remindMins or tags.has:remindHours or tags.has:remindDays or tags.has:remindWeeks or tags.has:remindMonths )' export 2>/dev/null | \
|
||||||
|
/nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -r '.[].uuid' 2>/dev/null | \
|
||||||
|
while read -r uuid; do
|
||||||
|
tags=$(/nix/store/syqlfcifpih00fknzailx8xxn4cnv42d-taskwarrior-3.4.2/bin/task "$uuid" export 2>/dev/null | /nix/store/qnaw7i777j52fpgbl5pgmzkq85znp083-jq-1.8.1-bin/bin/jq -r '.[0].tags[]? // empty' 2>/dev/null)
|
||||||
|
|
||||||
|
remove_args=""
|
||||||
|
echo "$tags" | /nix/store/02vv0r262agf9j5n2y1gmbjvdf12zkl0-gnugrep-3.12/bin/grep -q "^notify$" && remove_args="$remove_args -notify"
|
||||||
|
echo "$tags" | /nix/store/02vv0r262agf9j5n2y1gmbjvdf12zkl0-gnugrep-3.12/bin/grep -q "^notified$" && remove_args="$remove_args -notified"
|
||||||
|
|
||||||
|
remind_tags=$(echo "$tags" | /nix/store/02vv0r262agf9j5n2y1gmbjvdf12zkl0-gnugrep-3.12/bin/grep "^remind(Mins|Hours|Days|Weeks|Months)" 2>/dev/null || true)
|
||||||
|
if [ -n "$remind_tags" ]; then
|
||||||
|
while read -r tag; do
|
||||||
|
remove_args="$remove_args -$tag"
|
||||||
|
done <<< "$remind_tags"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$remove_args" ]; then
|
||||||
|
/nix/store/syqlfcifpih00fknzailx8xxn4cnv42d-taskwarrior-3.4.2/bin/task "$uuid" modify $remove_args 2>/dev/null
|
||||||
|
fi
|
||||||
|
done
|
||||||
@@ -76,6 +76,13 @@ input {
|
|||||||
// https://yalter.github.io/niri/Configuration:-Outputs
|
// https://yalter.github.io/niri/Configuration:-Outputs
|
||||||
// Remember to uncomment the node by removing "/-"!
|
// Remember to uncomment the node by removing "/-"!
|
||||||
|
|
||||||
|
// input {
|
||||||
|
// "*" allow
|
||||||
|
// }
|
||||||
|
// output {
|
||||||
|
// "*" allow
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
environment {
|
environment {
|
||||||
MOZ_DBUS_REMOTE "1"
|
MOZ_DBUS_REMOTE "1"
|
||||||
@@ -748,4 +755,6 @@ binds {
|
|||||||
// Powers off the monitors. To turn them back on, do any input like
|
// Powers off the monitors. To turn them back on, do any input like
|
||||||
// moving the mouse or pressing any other key.
|
// moving the mouse or pressing any other key.
|
||||||
Mod+Shift+P { power-off-monitors; }
|
Mod+Shift+P { power-off-monitors; }
|
||||||
|
Mod+N { spawn "swaync-client" "-t"; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
"modules-left": ["niri/workspaces"],
|
"modules-left": ["niri/workspaces"],
|
||||||
"modules-center": ["niri/window"],
|
"modules-center": ["niri/window"],
|
||||||
"modules-right": [
|
"modules-right": [
|
||||||
|
"custom/tasks", // <-- ADD THIS LINE
|
||||||
|
"custom/notification", // <-- ADD THIS
|
||||||
"keyboard-state",
|
"keyboard-state",
|
||||||
"cpu",
|
"cpu",
|
||||||
"memory",
|
"memory",
|
||||||
@@ -15,23 +17,60 @@
|
|||||||
"clock"
|
"clock"
|
||||||
],
|
],
|
||||||
|
|
||||||
"clock": { "format": "{:%a %d %b %H:%M}" },
|
"tray": {
|
||||||
|
"icon-size": 20,
|
||||||
|
"spacing": 8
|
||||||
|
},
|
||||||
|
|
||||||
"cpu": { "format": " {usage}%" },
|
|
||||||
"memory": { "format": " {percentage}%" },
|
|
||||||
|
|
||||||
"network": {
|
"clock": {
|
||||||
"format-wifi": " {signalStrength}%",
|
"format": " {:%a %d %b %H:%M}",
|
||||||
"format-ethernet": "",
|
"on-click": "niri msg action spawn -- gnome-calendar",
|
||||||
"format-disconnected": ""
|
"tooltip": true,
|
||||||
},
|
"tooltip-format": "{:%Y-%m-%d %H:%M:%S}"
|
||||||
|
},
|
||||||
"pulseaudio": {
|
|
||||||
"format": " {volume}%",
|
"cpu": {
|
||||||
"format-muted": ""
|
"format": " {usage}%",
|
||||||
|
"on-click": "niri msg action spawn -- kitty -e btop",
|
||||||
|
"tooltip": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"memory": {
|
||||||
|
"format": " {percentage}%",
|
||||||
|
"on-click": "niri msg action spawn -- kitty -e btop",
|
||||||
|
"tooltip": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"network": {
|
||||||
|
"format-wifi": " {signalStrength}%",
|
||||||
|
"format-ethernet": " Wired",
|
||||||
|
"format-disconnected": " Offline",
|
||||||
|
"on-click": "nm-connection-editor",
|
||||||
|
"on-click-right": "nmcli networking toggle",
|
||||||
|
"tooltip": true,
|
||||||
|
"tooltip-format": "{essid}\nLeft-click: Network settings\nRight-click: Toggle networking"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"pulseaudio": {
|
||||||
|
"format": "{icon} {volume}%",
|
||||||
|
"format-muted": " Muted",
|
||||||
|
"format-icons": {
|
||||||
|
"default": ["", "", ""],
|
||||||
|
"headphone": "",
|
||||||
|
"headset": ""
|
||||||
},
|
},
|
||||||
|
"on-click": "pavucontrol",
|
||||||
|
"on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
|
||||||
|
"on-scroll-up": "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02+ -l 1.0",
|
||||||
|
"on-scroll-down": "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02-",
|
||||||
|
"tooltip": true,
|
||||||
|
"tooltip-format": "{icon} {volume}%\nLeft-click: Mixer\nRight-click: Toggle mute\nScroll: Adjust volume"
|
||||||
|
},
|
||||||
|
|
||||||
"keyboard-state": {
|
"keyboard-state": {
|
||||||
|
"device": "/dev/input/event*",
|
||||||
"numlock": true,
|
"numlock": true,
|
||||||
"capslock": true,
|
"capslock": true,
|
||||||
"format": "{name} {icon}",
|
"format": "{name} {icon}",
|
||||||
@@ -39,5 +78,41 @@
|
|||||||
"locked": "",
|
"locked": "",
|
||||||
"unlocked": ""
|
"unlocked": ""
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
"custom/tasks": {
|
||||||
|
"format": "{icon} {text}",
|
||||||
|
"format-icons": ["", ""],
|
||||||
|
"interval": 30,
|
||||||
|
"exec": "task status:pending count",
|
||||||
|
"exec-if": "which task",
|
||||||
|
"on-click": "niri msg action spawn -- kitty -e taskwarrior-tui",
|
||||||
|
"on-click-right": "niri msg action spawn -- kitty -e task add",
|
||||||
|
"tooltip": true,
|
||||||
|
"tooltip-format": "{} pending tasks\nLeft-click: Open TUI\nRight-click: Add task",
|
||||||
|
"min-length": 3,
|
||||||
|
"max-length": 20
|
||||||
|
},
|
||||||
|
"custom/notification": {
|
||||||
|
"tooltip": false,
|
||||||
|
"format": "{icon}",
|
||||||
|
"format-icons": {
|
||||||
|
"notification": "<span foreground='red'><sup></sup></span>",
|
||||||
|
"none": "",
|
||||||
|
"dnd-notification": "<span foreground='red'><sup></sup></span>",
|
||||||
|
"dnd-none": ""
|
||||||
|
},
|
||||||
|
"return-type": "json",
|
||||||
|
"exec-if": "which swaync-client",
|
||||||
|
"exec": "swaync-client -swb",
|
||||||
|
"on-click": "swaync-client -t -sw",
|
||||||
|
"on-click-right": "swaync-client -d -sw",
|
||||||
|
"escape": true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ export EDITOR="nvim"
|
|||||||
export VISUAL="nvim"
|
export VISUAL="nvim"
|
||||||
|
|
||||||
|
|
||||||
|
export TICKER_WATCH="^GSPC,^DJI,^IXIC,^AXJO,^AORD,CBA.AX,NAB.AX,WBC.AX,ANZ.AX,BHP.AX,RIO.AX,FMG.AX,NST.AX,^VIX,CL=F,NG=F,ZC=F,KE=F,^TNX,BDRY,BTC-USD,DX-Y.NYB,000001.SS,399001.SZ,^HSI,TIO=F,EURUSD=X,AUDUSD=X,GC=F,SI=F,AAPL,MSFT,GOOG,NVDA,AMZN,META,TSLA"
|
||||||
|
export TICKER_REFRESH=120 # Refresh rate in seconds
|
||||||
|
|
||||||
|
|
||||||
# This must be at the top for Powerlevel10k Instant Prompt to work.
|
# This must be at the top for Powerlevel10k Instant Prompt to work.
|
||||||
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
|
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
|
||||||
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
|
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
|
||||||
|
|||||||
@@ -29,6 +29,159 @@ home.stateVersion = "25.11";
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
services.swaync = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
positionX = "right";
|
||||||
|
positionY = "top";
|
||||||
|
control-center-margin-top = 10;
|
||||||
|
control-center-margin-right = 10;
|
||||||
|
control-center-width = 380;
|
||||||
|
notification-window-width = 400;
|
||||||
|
notification-icon-size = 64;
|
||||||
|
notification-body-image-height = 100;
|
||||||
|
notification-body-image-width = 200;
|
||||||
|
timeout = 10;
|
||||||
|
timeout-low = 5;
|
||||||
|
timeout-critical = 0;
|
||||||
|
widgets = [
|
||||||
|
"notifications"
|
||||||
|
"mpris"
|
||||||
|
"volume"
|
||||||
|
"backlight"
|
||||||
|
"buttons-grid"
|
||||||
|
];
|
||||||
|
"widget-config" = {
|
||||||
|
notifications = {
|
||||||
|
"hide-on-clear" = false;
|
||||||
|
"hide-on-action" = true;
|
||||||
|
};
|
||||||
|
mpris = {
|
||||||
|
"image-size" = 96;
|
||||||
|
"image-radius" = 12;
|
||||||
|
};
|
||||||
|
volume = {
|
||||||
|
label = "";
|
||||||
|
};
|
||||||
|
backlight = {
|
||||||
|
label = "";
|
||||||
|
};
|
||||||
|
"buttons-grid" = {
|
||||||
|
actions = [
|
||||||
|
{
|
||||||
|
label = "";
|
||||||
|
command = "systemctl poweroff";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
label = "";
|
||||||
|
command = "systemctl reboot";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
label = "";
|
||||||
|
command = "swaylock";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# services.mako = {
|
||||||
|
# enable = true;
|
||||||
|
#
|
||||||
|
# # Essential Wayland integration
|
||||||
|
# layer = "overlay"; # Required for Niri
|
||||||
|
# output = ""; # Shows on all outputs
|
||||||
|
#
|
||||||
|
# # Design (matches your Dunst preferences)
|
||||||
|
# font = "JetBrainsMono Nerd Font 10";
|
||||||
|
# backgroundColor = "#1e1e2e";
|
||||||
|
# borderColor = "#89b4fa";
|
||||||
|
# borderSize = 2;
|
||||||
|
# borderRadius = 5;
|
||||||
|
#
|
||||||
|
# # Positioning
|
||||||
|
# anchor = "top-right";
|
||||||
|
# margin = "30,30"; # X,Y from anchor
|
||||||
|
# width = 300;
|
||||||
|
# height = 200;
|
||||||
|
#
|
||||||
|
# # Behavior
|
||||||
|
# defaultTimeout = 10000; # ms
|
||||||
|
# sort = "-time"; # Newest on top-right
|
||||||
|
#
|
||||||
|
# settings = {
|
||||||
|
# "[urgency=high]" = {
|
||||||
|
# background-color = "#f38ba8";
|
||||||
|
# default-timeout = 0;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
|
||||||
|
# Deploy the script to ~/.local/bin (Nix handles creation/permissions)
|
||||||
|
home.file.".local/bin/task-due-notify" = {
|
||||||
|
source = ./bin/task-due-notify.sh;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.user.timers.task-due-notify = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Timer for Taskwarrior due notifications";
|
||||||
|
};
|
||||||
|
Timer = {
|
||||||
|
OnBootSec = "1min";
|
||||||
|
OnCalendar = "*:*:0/1"; # Every 5 minutes
|
||||||
|
Persistent = true;
|
||||||
|
};
|
||||||
|
Install = {
|
||||||
|
WantedBy = ["timers.target"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# systemd.user.services.task-due-notify = {
|
||||||
|
# Unit = {
|
||||||
|
# Description = "Check for due Taskwarrior tasks and notify";
|
||||||
|
# };
|
||||||
|
# Service = {
|
||||||
|
# Type = "oneshot";
|
||||||
|
# ExecStart = "${pkgs.bash}/bin/bash${config.home.homeDirectory}/.local/bin/task-due-notify";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# Systemd user timer to run the service periodically
|
||||||
|
# systemd.user.timers.task-due-notify = {
|
||||||
|
# Unit = {
|
||||||
|
# Description = "Timer for Taskwarrior due notifications";
|
||||||
|
# };
|
||||||
|
# Timer = {
|
||||||
|
# OnBootSec = "1min";
|
||||||
|
# OnUnitActiveSec = "1min";
|
||||||
|
# AccuracySec = "30s";
|
||||||
|
# Persistent = true;
|
||||||
|
# };
|
||||||
|
# Install = {
|
||||||
|
# WantedBy = ["timers.target"];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
|
systemd.user.services.task-due-notify = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Check for due Taskwarrior tasks and notify";
|
||||||
|
};
|
||||||
|
Service = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${pkgs.bash}/bin/bash ${config.home.homeDirectory}/.local/bin/task-due-notify";
|
||||||
|
Environment = [
|
||||||
|
"PATH=${pkgs.gnugrep}/bin:${pkgs.gnused}/bin:${pkgs.coreutils}/bin:${pkgs.taskwarrior3}/bin:${pkgs.jq}/bin:${pkgs.curl}/bin:${pkgs.libnotify}/bin:/usr/bin:/bin"
|
||||||
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
systemd.user.services.kdeconnect-indicator = {
|
systemd.user.services.kdeconnect-indicator = {
|
||||||
Unit = {
|
Unit = {
|
||||||
Description = "KDE Connect indicator";
|
Description = "KDE Connect indicator";
|
||||||
@@ -140,26 +293,90 @@ dconf.settings."org/gnome/desktop/interface" = {
|
|||||||
extraPackages = with pkgs; [ tree-sitter gcc gnumake];
|
extraPackages = with pkgs; [ tree-sitter gcc gnumake];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
programs.yazi = {
|
||||||
|
enable = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
|
enableBashIntegration = true;
|
||||||
|
# This sets the command name for the wrapper.
|
||||||
|
# Many people use 'y' or 'yy' for quick access.
|
||||||
|
shellWrapperName = "y";
|
||||||
|
};
|
||||||
|
|
||||||
|
home.sessionVariables = {
|
||||||
|
QT_QPA_PLATFORM = "wayland";
|
||||||
|
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
|
||||||
|
};
|
||||||
|
|
||||||
|
gtk = {
|
||||||
|
enable = true;
|
||||||
|
theme = {
|
||||||
|
name = "Adwaita-dark";
|
||||||
|
package = pkgs.gnome-themes-extra;
|
||||||
|
};
|
||||||
|
iconTheme = {
|
||||||
|
name = "breeze-dark";
|
||||||
|
package = pkgs.kdePackages.breeze-icons;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
qt = {
|
||||||
|
enable = true;
|
||||||
|
platformTheme.name = "gtk3";
|
||||||
|
style.name = "adwaita-dark";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
# Packages (NOW list + a few safe essentials)
|
# Packages (NOW list + a few safe essentials)
|
||||||
# ---
|
# ---
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
|
|
||||||
# NOT YET INSTALLED
|
|
||||||
|
# Input device support
|
||||||
|
libinput
|
||||||
|
seatd
|
||||||
|
|
||||||
|
# Audio controls
|
||||||
|
pamixer
|
||||||
|
playerctl
|
||||||
|
|
||||||
|
# Network
|
||||||
|
networkmanagerapplet
|
||||||
|
|
||||||
|
# System Monitoring
|
||||||
|
swaynotificationcenter # For notification daemon
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
libnotify
|
||||||
|
|
||||||
|
kdePackages.dolphin
|
||||||
|
kdePackages.kio-extras
|
||||||
|
kdePackages.kdegraphics-thumbnailers
|
||||||
|
kdePackages.ffmpegthumbs
|
||||||
|
kdePackages.ark
|
||||||
|
|
||||||
|
adwaita-qt
|
||||||
|
adwaita-qt6
|
||||||
|
kdePackages.breeze-icons
|
||||||
|
|
||||||
nushell
|
nushell
|
||||||
bun
|
bun
|
||||||
pnpm
|
pnpm
|
||||||
typescript
|
vite
|
||||||
nodePackages.vite
|
|
||||||
python3Packages.beautifulsoup4
|
|
||||||
python3Packages.scrapy
|
|
||||||
python3Packages.pillow
|
|
||||||
python3Packages.playwright
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# INSTALLED
|
# CLI tools
|
||||||
|
# python3Packages.autogpt
|
||||||
|
# agentops
|
||||||
|
|
||||||
|
|
||||||
|
(callPackage ../../pkgs/cao-cli.nix { })
|
||||||
|
|
||||||
|
ollama
|
||||||
|
|
||||||
tickrs
|
tickrs
|
||||||
taskwarrior3
|
taskwarrior3
|
||||||
taskwarrior-tui
|
taskwarrior-tui
|
||||||
@@ -205,7 +422,7 @@ dconf.settings."org/gnome/desktop/interface" = {
|
|||||||
zellij
|
zellij
|
||||||
tealdeer
|
tealdeer
|
||||||
navi
|
navi
|
||||||
yazi
|
# yazi
|
||||||
dua
|
dua
|
||||||
jq
|
jq
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ home-manager.backupFileExtension = "hm-bak";
|
|||||||
# Networking
|
# Networking
|
||||||
# ---
|
# ---
|
||||||
networking.networkmanager.enable = true;
|
networking.networkmanager.enable = true;
|
||||||
|
networking.interfaces.enp0s31f6.wakeOnLan.enable = true;
|
||||||
|
|
||||||
# Static IP policy:
|
# Static IP policy:
|
||||||
# - Static IP must be on Wi-Fi SSID "Aussie Broadband 8729"
|
# - Static IP must be on Wi-Fi SSID "Aussie Broadband 8729"
|
||||||
@@ -122,6 +123,16 @@ home-manager.backupFileExtension = "hm-bak";
|
|||||||
# ---
|
# ---
|
||||||
|
|
||||||
|
|
||||||
|
users.users.sam.openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC3yxLtvBY6ClGliUfKA6eJLwUoCmagT5aZTrMsJnguUIch5lmdIGqz8gbGoy9ADEBaUpSA9nQsZZaXQE34t4xEqAzqra7hYogHR2uT6bIoML0ZWPiiMvSHOtknKcnfK/MBBPKjGYJSMhy2nzP02ORZs9D+DlfV8nVknsJa/G5jkgJXpA4za0bhxIZWJE7DPFF/utfSjxs6AB2wOzjfLPeuqSyUVq8nze+b1zf8baMBYVNxxpbHCyEXCvpuoxDw3JVk5Ha+hYyWb7563cCSeakrGM3f5048pFdPRGdbi4qcNsQV1KCBEd939VsOSNcY7Yr69zjnWzZNDCRBWxzlu+3DNY8I7ukHzxR78FPAQ6eCDR4druwIiGqlo5CE6S4P1h0uqKH2RW75qXoLb/orlwHKnAi3YOxDvELTQnxnLVgp6ahRpRu7ZqtLfJfwMLVcjTaExm8Yo4fLTJMgNv7U4bY/yRgenRzzRKHwL+kR/+SfY6KOH+8X0Jf0J653d9Z3VcVrXgo8r4vv6wx8CE605AfgQAsK9RN0cmtaDgd5GaXs3BOWMz+IeeiauSF2EXvPK5BsnvnZbBfATgpqsfi+iShoIDJ0+6mbwFqbczc17Ss9Z0mkSZyg3fsQHpWo9UFBNq5Jic1UGcjUKcvvZaB6/5bPvc6dVL/JKGcj0xqogr1paQ== root@core-ssh"
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
services.ollama.enable = true;
|
||||||
|
|
||||||
|
services.udisks2.enable = true;
|
||||||
|
services.dbus.enable = true;
|
||||||
|
|
||||||
programs.kdeconnect.enable = true;
|
programs.kdeconnect.enable = true;
|
||||||
services.gvfs.enable = true;
|
services.gvfs.enable = true;
|
||||||
services.tumbler.enable = true;
|
services.tumbler.enable = true;
|
||||||
@@ -176,6 +187,18 @@ PermitRootLogin = "no";
|
|||||||
# especially in minimal Wayland sessions.
|
# especially in minimal Wayland sessions.
|
||||||
security.polkit.enable = true;
|
security.polkit.enable = true;
|
||||||
|
|
||||||
|
|
||||||
|
security.polkit.extraConfig = ''
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if (action.id == "org.freedesktop.login1.suspend" &&
|
||||||
|
subject.user == "sam") {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
# Firmware / microcode (stability)
|
# Firmware / microcode (stability)
|
||||||
# ---
|
# ---
|
||||||
@@ -220,18 +243,48 @@ PermitRootLogin = "no";
|
|||||||
# fsType = "ext4";
|
# fsType = "ext4";
|
||||||
# options = [ "nofail" "x-systemd.device-timeout=1s" ];
|
# options = [ "nofail" "x-systemd.device-timeout=1s" ];
|
||||||
# };
|
# };
|
||||||
fileSystems."/mnt/integral300" = {
|
|
||||||
device = "/dev/disk/by-uuid/27febd74-20aa-4a3a-92c1-6fdd1ad7e88e";
|
|
||||||
fsType = "ext4";
|
systemd.services.wake-on-lan-resume = {
|
||||||
options = [
|
description = "Re-enable Wake-on-LAN after resume";
|
||||||
"nofail"
|
wantedBy = [ "post-resume.target" ];
|
||||||
"noauto"
|
after = [ "post-resume.target" ];
|
||||||
"x-systemd.automount"
|
serviceConfig = {
|
||||||
"x-systemd.idle-timeout=60"
|
Type = "oneshot";
|
||||||
"x-systemd.device-timeout=30s"
|
ExecStart = "${pkgs.ethtool}/bin/ethtool -s enp0s31f6 wol g";
|
||||||
];
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Allow sam to suspend without password (for Home Assistant WOL)
|
||||||
|
security.sudo.extraRules = [
|
||||||
|
{
|
||||||
|
users = [ "sam" ];
|
||||||
|
commands = [
|
||||||
|
{
|
||||||
|
command = "${pkgs.systemd}/bin/systemctl suspend";
|
||||||
|
options = [ "NOPASSWD" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# This was the integral drive that died.
|
||||||
|
|
||||||
|
# fileSystems."/mnt/integral300" = {
|
||||||
|
# device = "/dev/disk/by-uuid/27febd74-20aa-4a3a-92c1-6fdd1ad7e88e";
|
||||||
|
# fsType = "ext4";
|
||||||
|
# options = [
|
||||||
|
# "nofail"
|
||||||
|
# "noauto"
|
||||||
|
# "x-systemd.automount"
|
||||||
|
# "x-systemd.idle-timeout=60"
|
||||||
|
# "x-systemd.device-timeout=30s"
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
|
||||||
fileSystems."/mnt/backup" = {
|
fileSystems."/mnt/backup" = {
|
||||||
device = "/dev/disk/by-uuid/0806B92006B90FA4";
|
device = "/dev/disk/by-uuid/0806B92006B90FA4";
|
||||||
fsType = "ntfs3";
|
fsType = "ntfs3";
|
||||||
@@ -315,6 +368,7 @@ systemd.tmpfiles.rules = lib.mkAfter [
|
|||||||
extraPortals = [
|
extraPortals = [
|
||||||
pkgs.xdg-desktop-portal-gtk
|
pkgs.xdg-desktop-portal-gtk
|
||||||
pkgs.xdg-desktop-portal-wlr
|
pkgs.xdg-desktop-portal-wlr
|
||||||
|
pkgs.kdePackages.xdg-desktop-portal-kde
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -327,6 +381,9 @@ fonts.packages = with pkgs; [
|
|||||||
|
|
||||||
# Minimal system packages needed for the session and core usability
|
# Minimal system packages needed for the session and core usability
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
|
|
||||||
|
ethtool
|
||||||
|
|
||||||
swww
|
swww
|
||||||
uv
|
uv
|
||||||
(pkgs.callPackage ../../pkgs/agentpipe.nix { })
|
(pkgs.callPackage ../../pkgs/agentpipe.nix { })
|
||||||
@@ -334,6 +391,14 @@ fonts.packages = with pkgs; [
|
|||||||
xfce.thunar
|
xfce.thunar
|
||||||
xfce.tumbler
|
xfce.tumbler
|
||||||
ffmpegthumbnailer
|
ffmpegthumbnailer
|
||||||
|
|
||||||
|
|
||||||
|
# Optional: ensure Qt apps look okay in Niri
|
||||||
|
kdePackages.qtwayland
|
||||||
|
kdePackages.qtsvg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
poppler-utils
|
poppler-utils
|
||||||
kdePackages.kdeconnect-kde
|
kdePackages.kdeconnect-kde
|
||||||
tmux
|
tmux
|
||||||
@@ -364,6 +429,11 @@ fonts.packages = with pkgs; [
|
|||||||
grim
|
grim
|
||||||
slurp
|
slurp
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
services.tailscale.enable = true;
|
services.tailscale.enable = true;
|
||||||
# ---
|
# ---
|
||||||
# NVIDIA (simple, first-boot stable config; PRIME tuning later)
|
# NVIDIA (simple, first-boot stable config; PRIME tuning later)
|
||||||
|
|||||||
28
pkgs/agentops.nix
Normal file
28
pkgs/agentops.nix
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{ lib
|
||||||
|
, python3Packages
|
||||||
|
, fetchPypi
|
||||||
|
}:
|
||||||
|
python3Packages.buildPythonPackage rec {
|
||||||
|
pname = "agentops";
|
||||||
|
version = "0.4.21";
|
||||||
|
pyproject = true;
|
||||||
|
build-system = with python3Packages; [ hatchling ];
|
||||||
|
src = fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
hash = "sha256-R3Wcbf1upYutL3dkJX5HeMsuNK4YDO9kL2D1atztZRA=";
|
||||||
|
};
|
||||||
|
# Bypasses strict dependency version checks that fail in Nixpkgs
|
||||||
|
pythonRelaxDeps = [ "packaging" "psutil" "termcolor" ];
|
||||||
|
propagatedBuildInputs = with python3Packages; [
|
||||||
|
pydantic requests httpx websockets aiohttp
|
||||||
|
opentelemetry-api opentelemetry-exporter-otlp-proto-http
|
||||||
|
opentelemetry-instrumentation opentelemetry-sdk opentelemetry-semantic-conventions
|
||||||
|
ordered-set packaging psutil pyyaml termcolor wrapt
|
||||||
|
];
|
||||||
|
pythonImportsCheck = [ "agentops" ];
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Observability and DevTool Platform for AI Agents";
|
||||||
|
homepage = "https://github.com/AgentOps-AI/agentops";
|
||||||
|
license = licenses.mit;
|
||||||
|
};
|
||||||
|
}
|
||||||
26
pkgs/autogpt.nix
Normal file
26
pkgs/autogpt.nix
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{ lib, buildPythonPackage, fetchFromGitHub, python3Packages }:
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "autogpt";
|
||||||
|
version = "0.5.2";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "Significant-Gravitas";
|
||||||
|
repo = "AutoGPT";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-0000000000000000000000000000000000000000000000000000"; # NEEDS UPDATE
|
||||||
|
};
|
||||||
|
|
||||||
|
propagatedBuildInputs = with python3Packages; [
|
||||||
|
openai
|
||||||
|
langchain
|
||||||
|
chromadb
|
||||||
|
sqlalchemy
|
||||||
|
beautifulsoup4
|
||||||
|
requests
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "AutoGPT - Autonomous AI agent";
|
||||||
|
homepage = "https://github.com/Significant-Gravitas/AutoGPT";
|
||||||
|
license = licenses.mit;
|
||||||
|
};
|
||||||
|
}
|
||||||
29
pkgs/cao-cli.nix
Normal file
29
pkgs/cao-cli.nix
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{ lib
|
||||||
|
, python3Packages
|
||||||
|
, fetchFromGitHub
|
||||||
|
}:
|
||||||
|
python3Packages.buildPythonPackage rec {
|
||||||
|
pname = "cli-agent-orchestrator";
|
||||||
|
version = "1.0.3";
|
||||||
|
pyproject = true;
|
||||||
|
build-system = with python3Packages; [ hatchling ];
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "awslabs";
|
||||||
|
repo = "cli-agent-orchestrator";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-syfUQaHeubQnFLgAcIoMozcYA8wuFfcuR2at/J96FoE=";
|
||||||
|
};
|
||||||
|
# Relaxes version bounds on dependencies for NixOS compatibility
|
||||||
|
pythonRelaxDeps = true;
|
||||||
|
propagatedBuildInputs = with python3Packages; [
|
||||||
|
fastapi pydantic sqlalchemy uvicorn websockets libtmux
|
||||||
|
click requests aiofiles python-frontmatter watchdog
|
||||||
|
apscheduler fastmcp
|
||||||
|
];
|
||||||
|
pythonImportsCheck = [ "cli_agent_orchestrator" ];
|
||||||
|
meta = with lib; {
|
||||||
|
description = "CLI Agent Orchestrator - multi-agent collaboration via tmux";
|
||||||
|
homepage = "https://github.com/awslabs/cli-agent-orchestrator";
|
||||||
|
license = licenses.asl20;
|
||||||
|
};
|
||||||
|
}
|
||||||
34
pkgs/mediapipe.nix
Normal file
34
pkgs/mediapipe.nix
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, python3Packages
|
||||||
|
, fetchurl
|
||||||
|
, autoPatchelfHook
|
||||||
|
, opencv
|
||||||
|
, libglvnd
|
||||||
|
}:
|
||||||
|
python3Packages.buildPythonPackage rec {
|
||||||
|
pname = "mediapipe";
|
||||||
|
version = "0.10.32";
|
||||||
|
format = "wheel";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://files.pythonhosted.org/packages/e3/98/00cd8b2dcb563f2298655633e6611a791b2c1a7df1dae064b2b96084f1bf/mediapipe-0.10.32-py3-none-manylinux_2_28_x86_64.whl";
|
||||||
|
hash = "sha256-SwlB+7vOQYYvE8sYUMSHjBPbxizV6B50iABRt6IM47Y=";
|
||||||
|
};
|
||||||
|
nativeBuildInputs = [ autoPatchelfHook ];
|
||||||
|
buildInputs = [
|
||||||
|
stdenv.cc.cc.lib
|
||||||
|
opencv
|
||||||
|
libglvnd
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = with python3Packages; [
|
||||||
|
numpy
|
||||||
|
absl-py
|
||||||
|
protobuf
|
||||||
|
opencv4
|
||||||
|
];
|
||||||
|
meta = with lib; {
|
||||||
|
description = "MediaPipe - Google's media processing framework";
|
||||||
|
homepage = "https://github.com/google/mediapipe";
|
||||||
|
license = licenses.asl20;
|
||||||
|
};
|
||||||
|
}
|
||||||
27
pkgs/react-doctor.nix
Normal file
27
pkgs/react-doctor.nix
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{ lib, nodejs, pkgs, buildNpmPackage, fetchFromGitHub }:
|
||||||
|
buildNpmPackage rec {
|
||||||
|
pname = "react-doctor";
|
||||||
|
version = "0.0.1";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "millionco";
|
||||||
|
repo = "react-doctor";
|
||||||
|
rev = "0.0.1";
|
||||||
|
hash = "sha256-T8szJcXeqIWmZQU/D4KpeFU1ZXilThL5JBmw2Y0hZkw=";
|
||||||
|
};
|
||||||
|
|
||||||
|
npmDepsHash = lib.fakeHash;
|
||||||
|
|
||||||
|
# CRITICAL: Generate package-lock.json during build
|
||||||
|
postPatch = ''
|
||||||
|
cd $sourceRoot
|
||||||
|
npm install --package-lock-only --no-audit --progress=false
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Let coding agents diagnose and fix your React code";
|
||||||
|
homepage = "https://github.com/millionco/react-doctor";
|
||||||
|
license = licenses.mit;
|
||||||
|
mainProgram = "react-doctor";
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user