Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkgbuilds/cua-driver-bin/.omarchy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"source": "local",
"release_ring": "fast",
"min_release_age": "24h"
}
90 changes: 90 additions & 0 deletions pkgbuilds/cua-driver-bin/.omarchy/upstream.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/bin/bash
# cua-driver ships from the trycua/cua monorepo, whose single release feed
# interleaves many products (cua-driver-rs-v*, fleet-v*, sandbox-v*, and
# nightly-* builds). The declarative github provider reads a feed as one
# product and stops on the first foreign tag, so this hook selects the newest
# stable cua-driver-rs release itself and reads its checksums.txt manifest.
set -euo pipefail

REPO="trycua/cua"
TAG_PREFIX="cua-driver-rs-v"

releases=$(curl -fsSL "https://api.github.com/repos/$REPO/releases?per_page=100")

min_age="${MIN_RELEASE_AGE_SECONDS:-0}"
now=$(date +%s)
candidates=0
best_pkgver="" best_tag="" best_published=""
while IFS=$'\t' read -r tag published_at; do
[[ "$tag" == "$TAG_PREFIX"* ]] || continue
pkgver=${tag#"$TAG_PREFIX"}
# Upstream marks every driver release "prerelease" so the monorepo's
# "latest" can point at another product; stability lives in the tag shape
# instead. Stable driver versions are plain dotted numbers -- nightlies
# carry a nightly- tag prefix and a -nightly.N version suffix, and both
# fall out here.
[[ "$pkgver" =~ ^[0-9]+(\.[0-9]+)*$ ]] || continue

# Strict ISO 8601 before GNU date sees it, matching bin/sync-upstream's
# backstop: date alone also accepts relative expressions, which would let a
# malformed feed fabricate an age instead of failing closed.
if [[ ! "$published_at" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?(Z|[+-][0-9]{2}:?[0-9]{2})$ ]] \
|| ! published_epoch=$(date --date="$published_at" +%s 2>/dev/null); then
echo "$REPO release $tag has an invalid published_at: ${published_at:-<empty>}" >&2
exit 1
fi
candidates=$((candidates + 1))

if (( now - published_epoch < min_age )); then
if [[ "${BYPASS_MIN_RELEASE_AGE:-}" == "1" ]]; then
echo "Bypassing release-age gate for $REPO $tag" >&2
else
continue
fi
fi

if [[ -z "$best_pkgver" ]] || [[ "$(vercmp "$pkgver" "$best_pkgver")" -gt 0 ]]; then
best_pkgver=$pkgver
best_tag=$tag
best_published=$published_at
fi
done < <(jq -r '.[] | select(.draft | not) | [.tag_name // "", .published_at // ""] | @tsv' <<<"$releases")

# A feed page with no stable driver release at all is an anomaly worth a loud
# error; every candidate merely being inside the quarantine window is not.
if (( candidates == 0 )); then
echo "no stable $TAG_PREFIX releases in the feed for $REPO" >&2
exit 1
fi
if [[ -z "$best_tag" ]]; then
echo "every recent $TAG_PREFIX release is still inside the release-age quarantine; skipping" >&2
echo '{}'
exit 0
fi

current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'")
if [[ -n "$current" ]] && [[ "$(vercmp "$best_pkgver" "$current")" -le 0 ]]; then
echo '{}'
exit 0
fi

checksums=$(curl -fsSL "https://github.com/$REPO/releases/download/$best_tag/checksums.txt")

sums_json='{}'
for arch in x86_64 aarch64; do
case "$arch" in
x86_64) platform="linux-x86_64" ;;
aarch64) platform="linux-arm64" ;;
esac
asset="cua-driver-rs-${best_pkgver}-${platform}.tar.gz"
sum=$(awk -v f="$asset" '$2 == f { print $1; exit }' <<<"$checksums")
if [[ ! "$sum" =~ ^[0-9a-f]{64}$ ]]; then
echo "no valid checksum for $asset in $REPO $best_tag checksums.txt" >&2
exit 1
fi
sums_json=$(jq -c --arg arch "$arch" --arg sum "$sum" '.[$arch] = [$sum]' <<<"$sums_json")
done

jq -n --arg pkgver "$best_pkgver" --arg published_at "$best_published" \
--argjson sums "$sums_json" \
'{pkgver: $pkgver, published_at: $published_at, sha256sums: $sums}'
21 changes: 21 additions & 0 deletions pkgbuilds/cua-driver-bin/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Cua AI, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
113 changes: 113 additions & 0 deletions pkgbuilds/cua-driver-bin/PKGBUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Maintainer: Spencer Bull <spencerbull2554@gmail.com>

# cua-driver ships prebuilt from the trycua/cua monorepo release feed, so this
# repackages the vendor tarball. Upstream keeps the CLI, its cursor-theme
# compiler, and the SDK artifacts together in one directory and exposes the
# CLI through a symlink -- the binary resolves its helpers as siblings of
# /proc/self/exe -- so the whole tree lands under /usr/lib/cua-driver with a
# /usr/bin symlink. .omarchy/upstream.sh rewrites the version and checksums
# below from the release feed.
#
# The binary carries its own updater: `cua-driver update --apply` pipes the
# vendor installer into bash, which would install a second copy under
# ~/.cua-driver and link it into ~/.local/bin, stepping around pacman and
# this repository's release gate. Upstream offers no switch for that path,
# and a /usr/bin wrapper would not cover it either, since the MCP
# configurations the binary generates record the resolved executable. So
# prepare() rewrites the installer URL inside the binary to point at pm.sh,
# a stand-in that declines and names pacman instead.

pkgname=cua-driver-bin
pkgver=0.23.2
pkgrel=1
pkgdesc="Computer-use driver for native GUI apps: accessibility-tree snapshots and input injection"
arch=('x86_64' 'aarch64')
url="https://github.com/trycua/cua"
license=('MIT')
# at-spi2-core carries the AT-SPI accessibility bus the driver reads GUI
# trees through; the X libraries are linked, not dlopen'd.
depends=(
'at-spi2-core'
'gcc-libs'
'glibc'
'libx11'
'libxcb'
'libxext'
'libxi'
'libxkbcommon'
)
provides=("cua-driver=${pkgver}")
conflicts=('cua-driver')
# Prebuilt Rust binaries ship byte-exact apart from the installer rewrite
# below: their build ids are what upstream symbolication matches.
options=('!strip' '!debug')
source=('LICENSE' 'pm.sh')
source_x86_64=("https://github.com/trycua/cua/releases/download/cua-driver-rs-v${pkgver}/cua-driver-rs-${pkgver}-linux-x86_64.tar.gz")
source_aarch64=("https://github.com/trycua/cua/releases/download/cua-driver-rs-v${pkgver}/cua-driver-rs-${pkgver}-linux-arm64.tar.gz")
sha256sums=('c0779290c1d4783169aa3dbfb55feb505e563ef8a004bbf55298ceffcfbda8d9'
'c76e251c3ed424200eac52bec35ba534336307fabd83a175ab0b47e2084ab0d8')
sha256sums_x86_64=('478e010d2b0426de9d8a07eb839802daa92137b33cb8affb93b991e91d76ce7e')
sha256sums_aarch64=('3ad2d6c7ca7356a08e534baa2f4ca84ad02cebb2d27caef66cb268b6df71210d')

case "${CARCH}" in
x86_64) _platform="linux-x86_64" ;;
aarch64) _platform="linux-arm64" ;;
esac
_vendor_tree="cua-driver-rs-${pkgver}-${_platform}"

# Rust strings carry their length out of band, so the replacement has to be
# exactly as long as the original: 32 bytes, which is what fixes the
# stand-in's short name and location.
_vendor_installer='https://cua.ai/driver/install.sh'
_pacman_installer='file:///usr/lib/cua-driver/pm.sh'

prepare() {
cd "${srcdir}/${_vendor_tree}"

if (( ${#_vendor_installer} != ${#_pacman_installer} )); then
echo "installer URLs must be the same length to rewrite in place" >&2
return 1
fi

# The URL appears twice: once in the updater and once in the printed
# reinstall one-liner. Any other count means upstream moved the updater
# and this rewrite needs another look, so the build stops rather than
# shipping a live self-updater.
local found
found=$(grep -obUaF "${_vendor_installer}" cua-driver | wc -l)
if (( found != 2 )); then
echo "expected the vendor installer URL twice in cua-driver, found ${found}" >&2
return 1
fi

local size_before size_after
size_before=$(stat -c %s cua-driver)
sed -i "s|${_vendor_installer//./\\.}|${_pacman_installer}|g" cua-driver
size_after=$(stat -c %s cua-driver)

if (( size_before != size_after )) \
|| grep -qUaF "${_vendor_installer}" cua-driver \
|| (( $(grep -obUaF "${_pacman_installer}" cua-driver | wc -l) != 2 )); then
echo "installer URL rewrite did not land cleanly in cua-driver" >&2
return 1
fi
}

package() {
cd "${srcdir}/${_vendor_tree}"

# The vendor tree stays together: cua-driver execs cua-cursor-theme as a
# sibling of the resolved binary, and the SDK library, node runtime, ABI
# header, and the GNOME wayland-helper extension are versioned with it.
install -d "${pkgdir}/usr/lib/cua-driver"
cp -a . "${pkgdir}/usr/lib/cua-driver/"
chmod -R a+rX "${pkgdir}/usr/lib/cua-driver"

# The path prepare() wrote into the binary.
install -Dm755 "${srcdir}/pm.sh" "${pkgdir}/usr/lib/cua-driver/pm.sh"

install -d "${pkgdir}/usr/bin"
ln -s ../lib/cua-driver/cua-driver "${pkgdir}/usr/bin/cua-driver"

install -Dm644 "${srcdir}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}
12 changes: 12 additions & 0 deletions pkgbuilds/cua-driver-bin/pm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
# Stands in for the vendor installer. cua-driver-bin points the binary's
# `update --apply` here instead of https://cua.ai/driver/install.sh, which
# would otherwise install a second copy under ~/.cua-driver and link it into
# ~/.local/bin, stepping around pacman and the repository's release gate. The
# exit status is what `cua-driver update --apply` reports.
{
echo "cua-driver is installed by pacman (cua-driver-bin), so the vendor installer is disabled."
echo "Upgrade it with pacman instead:"
echo " sudo pacman -Syu cua-driver-bin"
} >&2
exit 1
Loading