From eda9236c67acdd7dba4a40b356285d7f6ec05019 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Mon, 31 Aug 2026 20:49:53 -0500 Subject: [PATCH] Add perplexity, the official Perplexity desktop app Tracks Perplexity's own Debian repository, the feed the app updates itself from, via .omarchy/upstream.sh -- same shape as openai-codex-desktop. pkgver carries the build number from the pool filename because the index's Version field drops it and upstream rebuilds under the same marketing version; the pool wants the '+' percent-encoded. The launcher replaces the postinst symlink pacman never creates and defaults Chromium to Wayland. --- pkgbuilds/perplexity/.omarchy/package.json | 4 + pkgbuilds/perplexity/.omarchy/upstream.sh | 82 ++++++++++++++ pkgbuilds/perplexity/PKGBUILD | 114 ++++++++++++++++++++ pkgbuilds/perplexity/perplexity-launcher.sh | 32 ++++++ 4 files changed, 232 insertions(+) create mode 100644 pkgbuilds/perplexity/.omarchy/package.json create mode 100755 pkgbuilds/perplexity/.omarchy/upstream.sh create mode 100644 pkgbuilds/perplexity/PKGBUILD create mode 100755 pkgbuilds/perplexity/perplexity-launcher.sh diff --git a/pkgbuilds/perplexity/.omarchy/package.json b/pkgbuilds/perplexity/.omarchy/package.json new file mode 100644 index 0000000..db153c3 --- /dev/null +++ b/pkgbuilds/perplexity/.omarchy/package.json @@ -0,0 +1,4 @@ +{ + "source": "local", + "release_ring": "fast" +} diff --git a/pkgbuilds/perplexity/.omarchy/upstream.sh b/pkgbuilds/perplexity/.omarchy/upstream.sh new file mode 100755 index 0000000..0e3997e --- /dev/null +++ b/pkgbuilds/perplexity/.omarchy/upstream.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# Perplexity ships its desktop app from its own Debian repository. The +# per-architecture package index carries the filename and SHA256 of every deb, +# so an update costs two small HTTP requests instead of a 175 MB download. The +# index's Version field drops the build number the pool filename carries, and +# upstream rebuilds under the same marketing version, so the version of record +# here is the full string embedded in the filename. +set -euo pipefail + +BASE_URL="https://packages.perplexity.ai/deb" +declare -A DEB_ARCHES=([x86_64]=amd64 [aarch64]=arm64) + +# Print " " for the newest stanza in a Packages index, version +# meaning the full string from the pool filename. Newest is vercmp's opinion, +# which is the one bin/sync-upstream and pacman both use; sort -V disagrees +# with it over versions like 1.0a. +newest_release() { + local index="$1" + local debarch="$2" + local filename sha256 version best_version="" best_sha256="" + local prefix="pool/main/p/perplexity/perplexity_" + local suffix="_${debarch}.deb" + + while read -r filename sha256; do + # The PKGBUILD reconstructs the pool URL from pkgver alone, so a stanza + # naming anything else -- a rename, or a new pool layout -- has to stop + # the sync rather than pin a checksum to a URL nobody will fetch. + if [[ "$filename" != "${prefix}"*"${suffix}" ]]; then + echo "Unexpected pool filename in the upstream index: $filename" >&2 + return 1 + fi + version="${filename#"$prefix"}" + version="${version%"$suffix"}" + + if [[ -z "$best_version" ]] || [[ "$(vercmp "$version" "$best_version")" -gt 0 ]]; then + best_version="$version" + best_sha256="$sha256" + fi + done < <(awk ' + { sub(/\r$/, "") } + /^Filename:/ { filename = $2 } + /^SHA256:/ { sha256 = $2 } + /^$/ { if (filename && sha256) print filename, sha256; filename = sha256 = "" } + END { if (filename && sha256) print filename, sha256 } + ' <<<"$index") + + [[ -n "$best_version" ]] || return 1 + echo "$best_version $best_sha256" +} + +versions=() +declare -A checksums=() + +for arch in "${!DEB_ARCHES[@]}"; do + index=$(curl -fsSL "$BASE_URL/dists/stable/main/binary-${DEB_ARCHES[$arch]}/Packages") + + read -r version sha256 <<<"$(newest_release "$index" "${DEB_ARCHES[$arch]}")" + if [[ -z "${version:-}" || -z "${sha256:-}" ]]; then + echo "No usable release found for $arch in the upstream package index" >&2 + exit 1 + fi + + versions+=("$version") + checksums[$arch]="$sha256" +done + +# A release lands one architecture at a time, and a single pkgver has to cover +# both -- including the build number, since that is what the download URLs are +# built from. Report no update until they agree; the next run picks it up. +for version in "${versions[@]}"; do + if [[ "$version" != "${versions[0]}" ]]; then + echo "Upstream architectures are mid-release (${versions[*]}); skipping" >&2 + echo '{}' + exit 0 + fi +done + +jq -n \ + --arg pkgver "${versions[0]}" \ + --arg x86_64 "${checksums[x86_64]}" \ + --arg aarch64 "${checksums[aarch64]}" \ + '{pkgver: $pkgver, sha256sums: {x86_64: [$x86_64], aarch64: [$aarch64]}}' diff --git a/pkgbuilds/perplexity/PKGBUILD b/pkgbuilds/perplexity/PKGBUILD new file mode 100644 index 0000000..e891103 --- /dev/null +++ b/pkgbuilds/perplexity/PKGBUILD @@ -0,0 +1,114 @@ +# Maintainer: Spencer Bull + +# Omarchy tracks Perplexity's own Debian repository, the feed the app updates +# itself from. .omarchy/upstream.sh rewrites the version and checksums below +# from that repository's package index. + +pkgname=perplexity +pkgver=26.8.4+build50522 +pkgrel=1 +pkgdesc="Official Perplexity desktop app" +arch=('x86_64' 'aarch64') +url="https://www.perplexity.ai" +# Upstream ships no license text with the app; its terms live at +# https://www.perplexity.ai/hub/legal/terms-of-service +license=('custom') + +depends=( + 'alsa-lib' + 'at-spi2-core' + 'bash' + 'bubblewrap' + 'cairo' + 'dbus' + 'expat' + 'gcc-libs' + 'gdk-pixbuf2' + 'glib2' + 'glibc' + 'gtk3' + 'hicolor-icon-theme' + 'libcups' + 'libdrm' + 'libglvnd' + 'libnotify' + 'libsecret' + 'libx11' + 'libxcb' + 'libxcomposite' + 'libxdamage' + 'libxext' + 'libxfixes' + 'libxkbcommon' + 'libxrandr' + 'libxss' + 'libxtst' + 'mesa' + 'nspr' + 'nss' + 'pango' + 'systemd-libs' + 'util-linux-libs' + 'vulkan-icd-loader' + 'xdg-utils' +) + +optdepends=( + 'apparmor: confine the app with the bundled user-namespace profile' + 'libappindicator-gtk3: tray icon support' +) + +makedepends=('libarchive') +options=('!debug' '!strip') + +# Omarchy: the build image compresses with zstd at its default level. Maximum +# zstd buys roughly a third off this ~600 MB Electron tree for a few extra +# minutes of build time -- worth it for a package this large on the fast ring, +# same reasoning as openai-codex-desktop. +COMPRESSZST=(zstd -c -z -q --ultra -22 --threads=0 -) + +# The pool filename carries a build number the index's Version field drops, and +# upstream rebuilds under the same marketing version, so pkgver is the full +# string from the filename. The pool's storage treats a literal '+' in a URL as +# a space and answers 403, hence the %2B in the download URL only. +_deb_x86_64="perplexity_${pkgver}_amd64.deb" +_deb_aarch64="perplexity_${pkgver}_arm64.deb" +_pool="https://packages.perplexity.ai/deb/pool/main/p/perplexity" +source=('perplexity-launcher.sh') +source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64//+/%2B}") +source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64//+/%2B}") +noextract=("${_deb_x86_64}" "${_deb_aarch64}") +sha256sums=('b180ca6fbd268712a277a34d4215f176001c0031a4f6360686458623f47fad65') +sha256sums_x86_64=('47ef208aaee9395497cefe8fbc65beb2a5c37dd8bd974125e4c4a0e3be2fd103') +sha256sums_aarch64=('5ac7b5f597e03a888f92a3aaa643138f6cc78a50fd891bc7afabfe86e1e2b994') + +package() { + cd "${srcdir}" + + local deb_var="_deb_${CARCH}" + local deb="${!deb_var}" + + bsdtar -xOf "${deb}" data.tar.xz | + bsdtar --no-same-owner -xf - -C "${pkgdir}" + + # pacman never runs the deb's postinst, so the /usr/bin entry it would have + # symlinked is a launcher here instead, and the menu entry goes through it so + # the flags file applies there too. The scheme handler stays upstream's. + install -Dm755 perplexity-launcher.sh "${pkgdir}/usr/bin/perplexity" + sed -i 's|^Exec=.*|Exec=perplexity %U|' \ + "${pkgdir}/usr/share/applications/perplexity.desktop" + + # Arch ships Chromium's and Electron's own sandbox helper setuid, which is + # what keeps the sandbox up on a kernel that denies unprivileged user + # namespaces -- linux-hardened, mainly -- instead of aborting the app. The + # deb leaves this bit to its postinst. + chmod 4755 "${pkgdir}/opt/Perplexity/chrome-sandbox" + + # The profile upstream's postinst would install. It names /opt/Perplexity + # paths, which this package keeps. + install -Dm644 "${pkgdir}/opt/Perplexity/resources/apparmor-profile" \ + "${pkgdir}/etc/apparmor.d/perplexity" + + # Debian package-policy files are not used on Arch Linux. + rm -rf "${pkgdir}/usr/share/doc" +} diff --git a/pkgbuilds/perplexity/perplexity-launcher.sh b/pkgbuilds/perplexity/perplexity-launcher.sh new file mode 100755 index 0000000..2ff179f --- /dev/null +++ b/pkgbuilds/perplexity/perplexity-launcher.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -euo pipefail + +user_flags=() +config_home="${XDG_CONFIG_HOME:-}" +[[ -n "$config_home" || -z "${HOME:-}" ]] || config_home="$HOME/.config" +flags_file="${config_home:+$config_home/perplexity-flags.conf}" + +if [[ -n "$flags_file" && -f "$flags_file" && -r "$flags_file" ]]; then + while IFS= read -r line || [[ -n "$line" ]]; do + line="${line%%#*}" + [[ -n "${line//[[:space:]]/}" ]] || continue + read -r -a flags <<<"$line" + user_flags+=("${flags[@]}") + done <"$flags_file" +fi + +# Chromium's own Ozone detection falls back to XWayland often enough to matter, +# and the result is a blurry window on every scaled display. Ask for Wayland +# directly, unless the user has already picked a platform themselves. +platform_flags=() +if [[ -n "${WAYLAND_DISPLAY:-}" || "${XDG_SESSION_TYPE:-}" == wayland ]]; then + platform_flags=(--ozone-platform=wayland) + + for flag in "${user_flags[@]}" "$@"; do + case "$flag" in + --ozone-platform=* | --ozone-platform-hint=*) platform_flags=() ;; + esac + done +fi + +exec /opt/Perplexity/perplexity "${platform_flags[@]}" "${user_flags[@]}" "$@"