From 20feae209871607faa2d5702ce87fa8f215fd76f Mon Sep 17 00:00:00 2001
From: m3tam3re
Date: Sun, 26 Jul 2026 12:09:22 +0200
Subject: [PATCH] feat: add automatic updates for vibetyper, msty-studio,
zellij-ps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- vibetyper/msty-studio: unversioned AppImage URLs → HEAD/Last-Modified
check via custom update.sh, refreshes sha256 when upstream binary changes
- zellij-ps: switch to branch-tracking (master tip via Gitea API) since
helper-scripts repo has no tags
- all three expose passthru.updateScript so the existing CI workflow
discovers them via is_custom_update_script
---
pkgs/msty-studio/default.nix | 5 +++
pkgs/msty-studio/update.sh | 62 +++++++++++++++++++++++++++++
pkgs/vibetyper/default.nix | 5 +++
pkgs/vibetyper/update.sh | 68 ++++++++++++++++++++++++++++++++
pkgs/zellij-ps/update.sh | 75 ++++++++++++++++++++++++++++++++++++
5 files changed, 215 insertions(+)
create mode 100755 pkgs/msty-studio/update.sh
create mode 100755 pkgs/vibetyper/update.sh
create mode 100755 pkgs/zellij-ps/update.sh
diff --git a/pkgs/msty-studio/default.nix b/pkgs/msty-studio/default.nix
index 0cdc07d..fa11941 100644
--- a/pkgs/msty-studio/default.nix
+++ b/pkgs/msty-studio/default.nix
@@ -1,3 +1,4 @@
+# last-modified: Wed, 24 Sep 2025 00:17:41 GMT
{
appimageTools,
fetchurl,
@@ -9,6 +10,8 @@
}: let
pname = "msty-studio";
version = "2.0.0-beta.4";
+ # Upstream publishes to an unversioned URL — ./update.sh watches Last-Modified
+ # and refreshes the sha256 when the binary changes. Bump `version` manually.
src = fetchurl {
url = "https://next-assets.msty.studio/app/alpha/linux/MstyStudio_x86_64.AppImage";
sha256 = "sha256-zJcGK7QEL3ROgVJy13mMdY/437H3Zx8EwSXy7rEhV9w=";
@@ -34,6 +37,8 @@ in
wrapProgram $out/bin/${pname} \
--prefix PATH : ${nodejs}/bin:${uv}/bin:${python3}/bin
'';
+ passthru.updateScript = ./update.sh;
+
meta = {
description = "Msty Studio enables advanced, privacy‑preserving AI workflows entirely on your local machine.";
license = lib.licenses.unfree;
diff --git a/pkgs/msty-studio/update.sh b/pkgs/msty-studio/update.sh
new file mode 100755
index 0000000..f0f136d
--- /dev/null
+++ b/pkgs/msty-studio/update.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env nix-shell
+#!nix-shell --pure -i bash -p bash curl nix nix-prefetch cacert git
+set -euo pipefail
+
+# Update msty-studio AppImage hash.
+#
+# Upstream publishes to an unversioned URL (MstyStudio_x86_64.AppImage) — no
+# version-pinned URL and no usable GitHub release. To still catch updates, we:
+# 1. HEAD the URL and read the Last-Modified header
+# 2. Compare to the value stored as a `# last-modified:` comment in default.nix
+# 3. If changed: re-download, compute sha256, update hash + comment, commit
+#
+# The version attribute stays static (manual bump) — only the binary hash is
+# refreshed automatically.
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+NIX_FILE="$SCRIPT_DIR/default.nix"
+URL="https://next-assets.msty.studio/app/alpha/linux/MstyStudio_x86_64.AppImage"
+
+echo "Checking $URL ..."
+HEADERS=$(curl -fsSIL "$URL")
+NEW_LAST_MODIFIED=$(echo "$HEADERS" | tr -d '\r' \
+ | awk -F': ' 'tolower($1)=="last-modified" {print $2; exit}')
+
+if [[ -z "$NEW_LAST_MODIFIED" ]]; then
+ echo "ERROR: Could not read Last-Modified header from $URL" >&2
+ exit 1
+fi
+
+CURRENT_LAST_MODIFIED=$(awk -F': ' '/^# last-modified:/ {sub(/^# last-modified: /, ""); print; exit}' "$NIX_FILE")
+
+echo "Current: ${CURRENT_LAST_MODIFIED:-}"
+echo "Latest: $NEW_LAST_MODIFIED"
+
+if [[ "$NEW_LAST_MODIFIED" == "$CURRENT_LAST_MODIFIED" ]]; then
+ echo "No change, nothing to do."
+ exit 0
+fi
+
+echo "==> Content changed, refreshing hash..."
+
+HASH=$(nix-prefetch-url --type sha256 "$URL" 2>/dev/null)
+SRI=$(nix hash convert --hash-algo sha256 --to sri "$HASH")
+echo "New sha256: $SRI"
+
+sed -i "s|^\([[:space:]]*\)sha256 = \"[^\"]*\";|\1sha256 = \"$SRI\";|" "$NIX_FILE"
+
+if grep -q '^# last-modified:' "$NIX_FILE"; then
+ sed -i "s|^# last-modified:.*|# last-modified: $NEW_LAST_MODIFIED|" "$NIX_FILE"
+else
+ sed -i "1i # last-modified: $NEW_LAST_MODIFIED" "$NIX_FILE"
+fi
+
+echo "Updated $NIX_FILE"
+
+NIXPKGS_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || true)
+if [[ -n "$NIXPKGS_ROOT" ]] && \
+ [[ -n "$(git -C "$NIXPKGS_ROOT" status --porcelain "$NIX_FILE")" ]]; then
+ git -C "$NIXPKGS_ROOT" add "$NIX_FILE"
+ git -C "$NIXPKGS_ROOT" commit -m "msty-studio: refresh AppImage ($NEW_LAST_MODIFIED)"
+ echo "==> Committed"
+fi
diff --git a/pkgs/vibetyper/default.nix b/pkgs/vibetyper/default.nix
index f7ce57e..27943c1 100644
--- a/pkgs/vibetyper/default.nix
+++ b/pkgs/vibetyper/default.nix
@@ -1,3 +1,4 @@
+# last-modified: Fri, 24 Jul 2026 10:50:57 GMT
{
appimageTools,
fetchurl,
@@ -6,6 +7,8 @@
}: let
pname = "vibetyper";
version = "1.4.0";
+ # Upstream publishes to an unversioned URL — ./update.sh watches Last-Modified
+ # and refreshes the sha256 when the binary changes. Bump `version` manually.
src = fetchurl {
url = "https://cdn.vibetyper.com/releases/linux/VibeTyper.AppImage";
sha256 = "sha256-p4MOTKbEMIUhwhyGSE/l6ucwpPjeTELJ0lX4TXrKf2Y=";
@@ -29,6 +32,8 @@ in
--set VIBE_DISABLE_HYPRLAND_INDICATOR_NO_BLUR 1
'';
+ passthru.updateScript = ./update.sh;
+
meta = {
description = "VibeTyper - AI-powered typing assistant";
homepage = "https://vibetyper.com";
diff --git a/pkgs/vibetyper/update.sh b/pkgs/vibetyper/update.sh
new file mode 100755
index 0000000..54862f8
--- /dev/null
+++ b/pkgs/vibetyper/update.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env nix-shell
+#!nix-shell --pure -i bash -p bash curl nix nix-prefetch cacert git
+set -euo pipefail
+
+# Update vibetyper AppImage hash.
+#
+# Upstream publishes to an unversioned URL (VibeTyper.AppImage) — there is no
+# version-pinned URL and no usable GitHub release. To still catch updates, we:
+# 1. HEAD the URL and read the Last-Modified header
+# 2. Compare to the value stored as a `# last-modified:` comment in default.nix
+# 3. If changed: re-download, compute sha256, update hash + comment, commit
+#
+# The version attribute stays static (manual bump) — only the binary hash is
+# refreshed automatically.
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+NIX_FILE="$SCRIPT_DIR/default.nix"
+URL="https://cdn.vibetyper.com/releases/linux/VibeTyper.AppImage"
+
+echo "Checking $URL ..."
+# -f: fail on HTTP errors, -s: silent, -S: show errors, -I: HEAD, -L: follow redirects
+HEADERS=$(curl -fsSIL "$URL")
+NEW_LAST_MODIFIED=$(echo "$HEADERS" | tr -d '\r' \
+ | awk -F': ' 'tolower($1)=="last-modified" {print $2; exit}')
+
+if [[ -z "$NEW_LAST_MODIFIED" ]]; then
+ echo "ERROR: Could not read Last-Modified header from $URL" >&2
+ exit 1
+fi
+
+# Read stored Last-Modified from `# last-modified:` comment in the nix file
+CURRENT_LAST_MODIFIED=$(awk -F': ' '/^# last-modified:/ {sub(/^# last-modified: /, ""); print; exit}' "$NIX_FILE")
+
+echo "Current: ${CURRENT_LAST_MODIFIED:-}"
+echo "Latest: $NEW_LAST_MODIFIED"
+
+if [[ "$NEW_LAST_MODIFIED" == "$CURRENT_LAST_MODIFIED" ]]; then
+ echo "No change, nothing to do."
+ exit 0
+fi
+
+echo "==> Content changed, refreshing hash..."
+
+# Compute new sha256 (SRI form, matches existing `sha256 = "sha256-..."` style)
+HASH=$(nix-prefetch-url --type sha256 "$URL" 2>/dev/null)
+SRI=$(nix hash convert --hash-algo sha256 --to sri "$HASH")
+echo "New sha256: $SRI"
+
+# Update the sha256 attribute (keeps the existing `sha256 = "sha256-..."` shape)
+sed -i "s|^\([[:space:]]*\)sha256 = \"[^\"]*\";|\1sha256 = \"$SRI\";|" "$NIX_FILE"
+
+# Update or insert the last-modified marker comment
+if grep -q '^# last-modified:' "$NIX_FILE"; then
+ sed -i "s|^# last-modified:.*|# last-modified: $NEW_LAST_MODIFIED|" "$NIX_FILE"
+else
+ sed -i "1i # last-modified: $NEW_LAST_MODIFIED" "$NIX_FILE"
+fi
+
+echo "Updated $NIX_FILE"
+
+# Commit when inside a git repo
+NIXPKGS_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || true)
+if [[ -n "$NIXPKGS_ROOT" ]] && \
+ [[ -n "$(git -C "$NIXPKGS_ROOT" status --porcelain "$NIX_FILE")" ]]; then
+ git -C "$NIXPKGS_ROOT" add "$NIX_FILE"
+ git -C "$NIXPKGS_ROOT" commit -m "vibetyper: refresh AppImage ($NEW_LAST_MODIFIED)"
+ echo "==> Committed"
+fi
diff --git a/pkgs/zellij-ps/update.sh b/pkgs/zellij-ps/update.sh
new file mode 100755
index 0000000..00927c6
--- /dev/null
+++ b/pkgs/zellij-ps/update.sh
@@ -0,0 +1,75 @@
+#!/usr/bin/env nix-shell
+#!nix-shell --pure -i bash -p bash curl jq nix nix-prefetch cacert git
+set -euo pipefail
+
+# Update zellij-ps to the latest commit on the helper-scripts master branch.
+# The upstream repo (m3ta.dev/m3tam3re/helper-scripts) has no tags/releases,
+# so we track the tip of master via the Gitea API.
+#
+# This is a "branch-tracking" updater: always pulls the newest commit,
+# NOT a stable release. Suitable for personal script repos.
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+NIX_FILE="$SCRIPT_DIR/default.nix"
+
+DOMAIN="code.m3ta.dev"
+OWNER="m3tam3re"
+REPO="helper-scripts"
+BRANCH="master"
+
+echo "Fetching latest commit on $BRANCH of $DOMAIN/$OWNER/$REPO..."
+LATEST_SHA=$(curl -fsSL "https://$DOMAIN/api/v1/repos/$OWNER/$REPO/branches/$BRANCH" \
+ | jq -r '.commit.id')
+
+if [[ -z "$LATEST_SHA" ]]; then
+ echo "ERROR: Failed to fetch latest commit from $DOMAIN/$OWNER/$REPO" >&2
+ exit 1
+fi
+
+# Read current rev from the nix file
+CURRENT_SHA=$(awk '
+ /^[[:space:]]*rev = "/ {
+ gsub(/^[[:space:]]*rev = "/, "")
+ gsub(/".*/, "")
+ print
+ exit
+ }
+' "$NIX_FILE")
+
+echo "Current: ${CURRENT_SHA:0:10}"
+echo "Latest: ${LATEST_SHA:0:10}"
+
+if [[ "$LATEST_SHA" == "$CURRENT_SHA" ]]; then
+ echo "Already at latest commit, nothing to do."
+ exit 0
+fi
+
+echo "==> Updating zellij-ps: ${CURRENT_SHA:0:10} -> ${LATEST_SHA:0:10}"
+
+# Compute new sha256 via nix-prefetch-url (matches existing sha256 = "..." style)
+ARCHIVE_URL="https://$DOMAIN/$OWNER/$REPO/archive/$LATEST_SHA.tar.gz"
+echo "Prefetching: $ARCHIVE_URL"
+HASH=$(nix-prefetch-url --unpack --type sha256 "$ARCHIVE_URL" 2>/dev/null)
+
+if [[ -z "$HASH" ]]; then
+ echo "ERROR: nix-prefetch-url failed" >&2
+ exit 1
+fi
+
+echo "New sha256: $HASH"
+
+# Update rev and sha256 in the nix file
+sed -i "s|^\([[:space:]]*\)rev = \"[^\"]*\";|\1rev = \"$LATEST_SHA\";|" "$NIX_FILE"
+sed -i "s|^\([[:space:]]*\)sha256 = \"[^\"]*\";|\1sha256 = \"$HASH\";|" "$NIX_FILE"
+
+echo "Updated $NIX_FILE"
+
+# Commit when inside a git repo
+NIXPKGS_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || true)
+if [[ -n "$NIXPKGS_ROOT" ]] && \
+ [[ -n "$(git -C "$NIXPKGS_ROOT" status --porcelain "$NIX_FILE")" ]]; then
+ SHORT="${LATEST_SHA:0:10}"
+ git -C "$NIXPKGS_ROOT" add "$NIX_FILE"
+ git -C "$NIXPKGS_ROOT" commit -m "zellij-ps: update helper-scripts to $SHORT"
+ echo "==> Committed"
+fi