Brings the public tree back in line with the development repo after several weeks of drift caused by a stale publish include list. New: - In-app update path: GET /update/check compares the checkout against origin/main and POST /update/apply runs `ncp upgrade` detached (pull, rebuild, restart). The sidebar shows the version, checks on click, and offers an "update available" pill. - Projects: a project workspace groups chats and RAG documents, with per-project instructions and document retrieval scoped to the active project. Replaces the standalone Documents page. - modules/: auto-discovered feature plugins (mail, network) with their frontend counterparts and tests. - Memory curation runs in-process (synapse/memory/curator.py) on the chat model when a conversation goes idle. The separate memory service on :8001 is gone, along with the launcher lines that started it. Also: the KDE theme, panel and Promethean terminal assets, the full test suite, and VERSION 1.2.0. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
305 lines
14 KiB
Bash
305 lines
14 KiB
Bash
#!/usr/bin/env bash
|
|
# NexusOS KDE Plasma theme installer — idempotent, safe to re-run.
|
|
# Equivalent of assets/themes/install-theme.sh but for KDE.
|
|
#
|
|
# Usage:
|
|
# assets/themes/KDE/install-plasma.sh [--no-sddm]
|
|
#
|
|
# --no-sddm skip the SDDM step (requires sudo) — useful for live testing
|
|
set -euo pipefail
|
|
|
|
KDE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO="$(cd "$KDE/../../.." && pwd)"
|
|
|
|
NO_SDDM=0
|
|
FORCE_PANEL=0
|
|
for arg in "$@"; do
|
|
[[ "$arg" == "--no-sddm" ]] && NO_SDDM=1
|
|
[[ "$arg" == "--panel" ]] && FORCE_PANEL=1
|
|
done
|
|
|
|
echo "NexusOS KDE installer — repo: $REPO"
|
|
|
|
# ── 1. Create target directories ────────────────────────────────────────
|
|
mkdir -p \
|
|
~/.local/share/aurorae/themes \
|
|
~/.local/share/plasma/desktoptheme \
|
|
~/.local/share/color-schemes \
|
|
~/.local/share/konsole \
|
|
~/.config/Kvantum
|
|
|
|
# ── 2. Symlink theme directories (update automatically on git pull) ──────
|
|
ln -sfn "$KDE/aurorae/NexusOS" ~/.local/share/aurorae/themes/NexusOS
|
|
ln -sfn "$KDE/plasma/NexusOS" ~/.local/share/plasma/desktoptheme/NexusOS
|
|
ln -sfn "$KDE/kvantum/NexusOS" ~/.config/Kvantum/NexusOS
|
|
|
|
echo " [ok] theme symlinks"
|
|
|
|
# ── 3. Copy files that need to be in specific locations (not symlinks) ───
|
|
cp -f "$KDE/plasma/NexusOS/NexusOS.colors" ~/.local/share/color-schemes/
|
|
cp -f "$KDE/konsole/NexusOS.colorscheme" ~/.local/share/konsole/
|
|
cp -f "$KDE/konsole/NexusOS-Promethean.colorscheme" ~/.local/share/konsole/
|
|
cp -f "$KDE/konsole/Promethean.profile" ~/.local/share/konsole/
|
|
|
|
echo " [ok] color scheme + konsole files"
|
|
|
|
# ── 4. KDE color scheme ──────────────────────────────────────────────────
|
|
if command -v plasma-apply-colorscheme &>/dev/null; then
|
|
plasma-apply-colorscheme NexusOS 2>/dev/null && echo " [ok] color scheme applied"
|
|
else
|
|
echo " [skip] plasma-apply-colorscheme not found — apply color scheme manually"
|
|
fi
|
|
|
|
# ── 5. Kvantum ───────────────────────────────────────────────────────────
|
|
if command -v kvantummanager &>/dev/null; then
|
|
kvantummanager --set NexusOS 2>/dev/null && echo " [ok] Kvantum set to NexusOS"
|
|
else
|
|
echo " [skip] kvantummanager not found — install qt5-style-kvantum and run: kvantummanager --set NexusOS"
|
|
fi
|
|
|
|
# ── 6. KWin Aurorae decoration ───────────────────────────────────────────
|
|
if command -v kwriteconfig5 &>/dev/null; then
|
|
kwriteconfig5 --file kwinrc \
|
|
--group "org.kde.kdecoration2" --key library "org.kde.kwin.aurorae"
|
|
kwriteconfig5 --file kwinrc \
|
|
--group "org.kde.kdecoration2" --key theme "__aurorae__svg__NexusOS"
|
|
# Buttons on the right: minimize, maximize, close (I=minimize, A=maximize, X=close)
|
|
kwriteconfig5 --file kwinrc \
|
|
--group "org.kde.kdecoration2" --key ButtonsOnLeft ""
|
|
kwriteconfig5 --file kwinrc \
|
|
--group "org.kde.kdecoration2" --key ButtonsOnRight "IAX"
|
|
echo " [ok] KWin decoration: Aurorae NexusOS, buttons right"
|
|
else
|
|
echo " [skip] kwriteconfig5 not found — configure KWin decoration manually"
|
|
fi
|
|
|
|
# ── 7. Plasma shell theme ────────────────────────────────────────────────
|
|
if command -v plasma-apply-desktoptheme &>/dev/null; then
|
|
plasma-apply-desktoptheme NexusOS 2>/dev/null && echo " [ok] Plasma shell theme: NexusOS"
|
|
else
|
|
echo " [skip] plasma-apply-desktoptheme not found — apply desktop theme manually"
|
|
fi
|
|
|
|
# ── 8. Lock screen ───────────────────────────────────────────────────────
|
|
# Plasma 5.27 draws the lock screen from a look-and-feel package's
|
|
# contents/lockscreen, and [Greeter]Theme names that PACKAGE. The old value here
|
|
# ("NexusOS") was not a look-and-feel id, so it silently fell back to Breeze.
|
|
# The standalone kscreenlocker theme that value referred to targeted an earlier
|
|
# kscreenlocker API that 5.27 no longer loads, and has been deleted.
|
|
#
|
|
# Breeze's lock UI is deliberately kept rather than replaced: a lock screen that
|
|
# fails to load is one you cannot get back through. Only the wallpaper is ours,
|
|
# which is what carries the brushed-metal look.
|
|
if command -v kwriteconfig5 &>/dev/null; then
|
|
kwriteconfig5 --file kscreenlockerrc --group Greeter --key Theme org.kde.breeze.desktop
|
|
LOCK_BG="$KDE/sddm/NexusOS-QML/assets/background.png"
|
|
if [[ -f "$LOCK_BG" ]]; then
|
|
kwriteconfig5 --file kscreenlockerrc \
|
|
--group Greeter --group Wallpaper --group org.kde.image --group General \
|
|
--key Image "$LOCK_BG"
|
|
echo " [ok] lock screen wallpaper: NexusOS brushed metal"
|
|
fi
|
|
fi
|
|
|
|
# ── 9. GTK apps under Plasma ─────────────────────────────────────────────
|
|
if command -v kwriteconfig5 &>/dev/null; then
|
|
kwriteconfig5 --file kdeglobals --group KDE --key widgetStyle "kvantum-dark"
|
|
kwriteconfig5 --file kdeglobals --group Icons --key Theme NexusOS
|
|
kwriteconfig5 --file kdeglobals --group General \
|
|
--key font "Ubuntu,10,-1,5,50,0,0,0,0,0"
|
|
echo " [ok] kdeglobals: Kvantum style, NexusOS icons, Ubuntu 10"
|
|
fi
|
|
if command -v gsettings &>/dev/null; then
|
|
gsettings set org.gnome.desktop.interface gtk-theme NexusOS 2>/dev/null || true
|
|
gsettings set org.gnome.desktop.interface icon-theme NexusOS 2>/dev/null || true
|
|
echo " [ok] gsettings: GTK theme + icons = NexusOS"
|
|
fi
|
|
|
|
# ── 10. SDDM login theme ─────────────────────────────────────────────────
|
|
if [[ $NO_SDDM -eq 0 ]]; then
|
|
echo " Deploying SDDM theme + KDE session entry (requires sudo)..."
|
|
sudo cp -r "$KDE/sddm/NexusOS-QML" /usr/share/sddm/themes/
|
|
sudo cp "$REPO/management/sessions/nexusos-kde.desktop" /usr/share/xsessions/
|
|
if command -v kwriteconfig5 &>/dev/null; then
|
|
sudo kwriteconfig5 --file /etc/sddm.conf.d/nexusos.conf --group Theme --key Current NexusOS-QML
|
|
else
|
|
# Fallback: write the INI directly
|
|
sudo bash -c 'printf "[Theme]\nCurrent=NexusOS-QML\n" > /etc/sddm.conf.d/nexusos.conf'
|
|
fi
|
|
echo " [ok] SDDM theme: NexusOS-QML"
|
|
echo " [ok] KDE session: NexusOS-KDE added to /usr/share/xsessions/"
|
|
else
|
|
echo " [skip] SDDM (--no-sddm passed)"
|
|
fi
|
|
|
|
# ── 11. Promethean Terminal desktop launcher ──────────────────────────────
|
|
DESKTOP_SRC="$REPO/bin/promethean/promethean-terminal.desktop"
|
|
DESKTOP_DEST="$HOME/.local/share/applications/promethean-terminal.desktop"
|
|
if [[ -f "$DESKTOP_SRC" ]]; then
|
|
cp -f "$DESKTOP_SRC" "$DESKTOP_DEST"
|
|
echo " [ok] Promethean Terminal launcher updated"
|
|
fi
|
|
|
|
# ── 11b. Global Theme + wallpaper ────────────────────────────────────────
|
|
# Copied, NOT symlinked, unlike the theme dirs above: KPackage silently skips a
|
|
# symlinked package directory, so a symlinked look-and-feel never appears in
|
|
# `lookandfeeltool -l` or System Settings at all. Aurorae/desktoptheme/Kvantum
|
|
# read their directories directly and are fine as symlinks.
|
|
LNF_SRC="$KDE/look-and-feel/com.nexusos.desktop"
|
|
WALL_SRC="$KDE/wallpaper/NexusOS"
|
|
if [[ -d "$LNF_SRC" ]]; then
|
|
mkdir -p ~/.local/share/plasma/look-and-feel ~/.local/share/wallpapers
|
|
rm -rf ~/.local/share/plasma/look-and-feel/com.nexusos.desktop
|
|
cp -rL "$LNF_SRC" ~/.local/share/plasma/look-and-feel/
|
|
rm -rf ~/.local/share/wallpapers/NexusOS
|
|
cp -rL "$WALL_SRC" ~/.local/share/wallpapers/
|
|
echo " [ok] Global Theme + wallpaper packages installed"
|
|
|
|
if command -v lookandfeeltool &>/dev/null; then
|
|
# Verify registration before applying. KPackage reports nothing when it
|
|
# rejects a package, so without this check a botched install is silent and
|
|
# you only find out by opening System Settings.
|
|
if lookandfeeltool -l 2>/dev/null | grep -qx "com.nexusos.desktop"; then
|
|
lookandfeeltool -a com.nexusos.desktop 2>/dev/null \
|
|
&& echo " [ok] Global Theme applied (splash, colors, decoration)"
|
|
else
|
|
echo " [WARN] com.nexusos.desktop did not register with KPackage."
|
|
echo " Most likely it was symlinked instead of copied -- KPackage"
|
|
echo " skips symlinked package directories silently."
|
|
fi
|
|
fi
|
|
if command -v plasma-apply-wallpaperimage &>/dev/null; then
|
|
plasma-apply-wallpaperimage ~/.local/share/wallpapers/NexusOS &>/dev/null \
|
|
&& echo " [ok] wallpaper applied"
|
|
fi
|
|
fi
|
|
|
|
# ── 11c. Panel layout + dock ─────────────────────────────────────────────
|
|
# The XFCE panel rebuilt with native Plasma widgets, plus Plank for the dock
|
|
# (its config and NexusOS theme already exist under assets/themes/restore-snapshot).
|
|
#
|
|
# Applied ONCE, guarded by a marker file. This rewrites the panel from scratch,
|
|
# so re-running it on every restore would wipe any widget you added since. Pass
|
|
# --panel to force it, e.g. after a fresh install or to undo panel experiments.
|
|
PANEL_MARKER="$HOME/.config/nexusos-panel-applied"
|
|
PANEL_JS="$KDE/panel-layout.js"
|
|
if [[ -f "$PANEL_JS" ]] && { [[ ! -f "$PANEL_MARKER" ]] || [[ $FORCE_PANEL -eq 1 ]]; }; then
|
|
if qdbus org.kde.plasmashell /PlasmaShell evaluateScript \
|
|
"$(sed "s|__NEXUS_ROOT__|$REPO|g" "$PANEL_JS")" &>/dev/null; then
|
|
touch "$PANEL_MARKER"
|
|
echo " [ok] panel layout applied (top, 36px, Nexus launcher)"
|
|
else
|
|
echo " [skip] panel layout — plasmashell not running"
|
|
fi
|
|
elif [[ -f "$PANEL_MARKER" ]]; then
|
|
echo " [ok] panel layout already applied (--panel to redo)"
|
|
fi
|
|
|
|
# Plank autostart. Plank is a GTK X11 app and runs fine under Plasma; this is
|
|
# the same dock, config and theme the XFCE session used.
|
|
if command -v plank &>/dev/null; then
|
|
mkdir -p ~/.config/autostart
|
|
# Symlink, matching bin/panel/install.sh. cp fails outright when the target is
|
|
# already a symlink back to this same file ("are the same file"), which made
|
|
# the step look like it had silently done nothing.
|
|
ln -sfn "$REPO/management/autostart/plank.desktop" ~/.config/autostart/plank.desktop \
|
|
&& echo " [ok] Plank autostart installed"
|
|
pgrep -x plank &>/dev/null || { setsid plank </dev/null &>/dev/null & disown; }
|
|
fi
|
|
|
|
# ── 11d. Custom shortcut: region screenshot to clipboard ─────────────────
|
|
# Meta+Shift+S -> `xfce4-screenshooter -rc`, the equivalent of the XFCE binding.
|
|
# Spectacle is not installed by kde-plasma-desktop, and xfce4-screenshooter
|
|
# works fine under Plasma, so this keeps the tool that is already here.
|
|
#
|
|
# Written as ONE atomic replace rather than a series of kwriteconfig5 calls,
|
|
# because khotkeys watches khotkeysrc and rewrites it from its own model on
|
|
# every change.
|
|
#
|
|
# The UUID below is FIXED, not generated. kglobalaccel records the key binding
|
|
# in kglobalshortcutsrc against the action's UUID, so a fresh UUID on each run
|
|
# cannot take a key that the previous run's UUID already holds: the entry gets
|
|
# registered with no shortcut at all, and every re-run leaves another dead
|
|
# registration behind. A stable UUID means a re-run re-claims its own binding.
|
|
if ! grep -q "^Key=Meta+Shift+S$" ~/.config/khotkeysrc 2>/dev/null; then
|
|
python3 - <<'PYEOF'
|
|
import pathlib, re
|
|
|
|
# Fixed so re-runs reclaim the same kglobalaccel registration.
|
|
SHORTCUT_UUID = "87a4ba1e-4f01-4a79-9cd1-b73c17d459ea"
|
|
p = pathlib.Path.home() / ".config" / "khotkeysrc"
|
|
s = p.read_text() if p.exists() else "[Data]\nDataCount=0\n"
|
|
|
|
# Drop any half-written entry from an earlier failed attempt.
|
|
for m in re.findall(r"\[Data_(\d+)\]\n(?:[^\[]*)", s):
|
|
blk = re.search(r"\[Data_%s\]\n((?:[^\[]*))" % m, s)
|
|
if blk and "Screenshot region to clipboard" in blk.group(1):
|
|
s = re.sub(r"\n\[Data_%s[^\]]*\]\n(?:[^\[]*)" % m, "\n", s)
|
|
|
|
count = int(re.search(r"\[Data\]\nDataCount=(\d+)", s).group(1))
|
|
n = count + 1
|
|
s = re.sub(r"(\[Data\]\nDataCount=)\d+", r"\g<1>%d" % n, s, count=1)
|
|
s = s.rstrip("\n") + """
|
|
|
|
[Data_%d]
|
|
Comment=Select a region and copy it straight to the clipboard
|
|
Enabled=true
|
|
Name=Screenshot region to clipboard
|
|
Type=SIMPLE_ACTION_DATA
|
|
|
|
[Data_%dActions]
|
|
ActionsCount=1
|
|
|
|
[Data_%dActions0]
|
|
CommandURL=xfce4-screenshooter -rc
|
|
Type=COMMAND_URL
|
|
|
|
[Data_%dConditions]
|
|
Comment=
|
|
ConditionsCount=0
|
|
|
|
[Data_%dTriggers]
|
|
Comment=Simple_action
|
|
TriggersCount=1
|
|
|
|
[Data_%dTriggers0]
|
|
Key=Meta+Shift+S
|
|
Type=SHORTCUT
|
|
Uuid={%s}
|
|
""" % (n, n, n, n, n, n, SHORTCUT_UUID)
|
|
|
|
tmp = p.with_suffix(".nexustmp")
|
|
tmp.write_text(s)
|
|
tmp.replace(p)
|
|
PYEOF
|
|
qdbus org.kde.kded5 /modules/khotkeys reread_configuration &>/dev/null \
|
|
&& echo " [ok] Meta+Shift+S -> region screenshot to clipboard"
|
|
else
|
|
echo " [ok] screenshot shortcut already bound"
|
|
fi
|
|
|
|
# ── 12. Apply live changes (if Plasma is running) ────────────────────────
|
|
if qdbus org.kde.KWin /KWin reconfigure 2>/dev/null; then
|
|
echo " [ok] KWin reconfigured"
|
|
# Restart plasmashell to pick up new shell theme.
|
|
# setsid + closed stdio is load-bearing, not tidiness: the restarted shell
|
|
# outlives this script, and if it inherits our stdout it holds the write end
|
|
# of the caller's pipe open forever. `ncp restore` captures output, so a
|
|
# plain `kstart5 plasmashell &` hangs the entire restore after the theme is
|
|
# already applied -- which looks like a failure and isn't one.
|
|
if command -v kquitapp5 &>/dev/null && command -v kstart5 &>/dev/null; then
|
|
kquitapp5 plasmashell 2>/dev/null
|
|
sleep 1
|
|
setsid kstart5 plasmashell </dev/null >/dev/null 2>&1 &
|
|
disown 2>/dev/null || true
|
|
echo " [ok] plasmashell restarted"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "NexusOS KDE theme installed. On first KDE session:"
|
|
echo " 1. System Settings → Appearance → verify all components show NexusOS"
|
|
echo " 2. Panel: right-click → Edit Panel to adjust height/position"
|
|
echo " 3. Konsole: Settings → Edit Profile → select Promethean (for Promethean Terminal)"
|
|
echo " 4. Test lock screen: Meta+L"
|