Merge remote-tracking branch 'origin/master' into hermes-agent

This commit is contained in:
Omabot
2026-08-22 07:52:24 -07:00
56 changed files with 1440 additions and 364 deletions
+102
View File
@@ -0,0 +1,102 @@
name: Sync Rebuild Triggers
on:
schedule:
# Every 6 hours, off the hour to dodge the scheduling backlog at :00
- cron: '40 */6 * * *'
workflow_dispatch:
inputs:
packages:
description: 'Specific packages to update (space-separated, leave empty for all)'
required: false
default: ''
jobs:
sync:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
# Runs in an Arch container against the mirror the x86_64 builder itself
# uses, because the question being asked is what that builder will link
# against and a different mirror can be hours ahead of it. Recording a
# version the build never saw is the one failure this command must not
# have: nothing re-fires once the record matches.
- name: Bump pkgrel for packages whose dependencies moved
run: |
docker run --rm \
-e PACKAGES="$PACKAGES" \
-e HOST_UID="$(id -u)" \
-e HOST_GID="$(id -g)" \
-v "$PWD/bin:/workspace/bin:ro" \
-v "$PWD/helpers:/workspace/helpers:ro" \
-v "$PWD/pkgbuilds:/workspace/pkgbuilds" \
-w /workspace \
archlinux:base-devel bash -lc '
set -euo pipefail
printf "Server = https://mirror.omarchy.org/\$repo/os/\$arch\n" > /etc/pacman.d/mirrorlist
pacman -Syu --noconfirm jq
groupadd -g "$HOST_GID" runner
useradd -m -u "$HOST_UID" -g "$HOST_GID" runner
chown -R runner:runner /workspace/pkgbuilds
if [[ -n "${PACKAGES:-}" ]]; then
read -r -a package_args <<< "$PACKAGES"
runuser -u runner -- ./bin/sync-rebuilds "${package_args[@]}"
else
runuser -u runner -- ./bin/sync-rebuilds
fi
'
env:
PACKAGES: ${{ github.event.inputs.packages }}
- name: Check for changes
id: changes
run: |
if [ -z "$(git status --porcelain)" ]; then
echo "has_changes=false" >> "$GITHUB_OUTPUT"
else
echo "has_changes=true" >> "$GITHUB_OUTPUT"
fi
- name: Create Pull Request
if: steps.changes.outputs.has_changes == 'true'
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: 'chore: rebuild against updated dependencies'
title: 'chore: rebuild against updated dependencies'
body: |
Automated pkgrel bump for packages that link against a dependency
which has moved in the official repositories.
Each package names those dependencies in `rebuild_on` and carries the
versions its current pkgrel was bumped for in `rebuilt_against`. The
bump is what makes the rebuilt package an upgrade pacman will offer;
without it the build produces the version already published and no
one receives it.
branch: auto/sync-rebuilds
delete-branch: true
labels: automated
reviewers: ryanrhughes
- name: Notify Basecamp on failure
if: failure() && env.BASECAMP_CHATBOT_URL != ''
env:
BASECAMP_CHATBOT_URL: ${{ secrets.BASECAMP_CHATBOT_URL }}
run: |
curl -s -o /dev/null \
-H "Content-Type: application/json" \
-d "$(jq -n --arg content \
"🔴 <strong>Rebuild trigger sync failed</strong><br><a href=\"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\">View run</a>" \
'{content: $content}')" \
"$BASECAMP_CHATBOT_URL"
+34
View File
@@ -283,6 +283,34 @@ than downloading the artifacts — see `pkgbuilds/openai-codex-desktop/.omarchy/
which reads OpenAI's Debian package index and never fetches the 750 MB of debs
it describes.
### Sync Rebuild Triggers
```bash
bin/sync-rebuilds # Bump every package whose dependencies moved
bin/sync-rebuilds quickshell-git # Update specific packages
bin/sync-rebuilds --self-test # Run the regression tests
```
Some packages have to be rebuilt when something they link against changes, even though nothing in their own source moved. A Qt private-API consumer is the usual case: `Qt_6_PRIVATE_API` symbols are not covered by the soname, so a qt6-base point release can leave an installed binary unable to resolve a symbol at startup, and pacman upgrades Qt out from under it because the dependency is unversioned. The package still builds from the same git commit, so nothing in the normal version check notices.
A package names those dependencies in `.omarchy/package.json`:
```json
{ "source": "aur", "sync": false, "rebuild_on": ["qt6-base", "qt6-declarative", "qt6-wayland"] }
```
`bin/sync-rebuilds` reads each named package's version from the official repositories and compares it to `rebuilt_against`, the record of what the checked-in pkgrel was last bumped for. pkgrel is bumped unless every name in `rebuild_on` is recorded and still matches, so a name the record does not carry reads as changed rather than going unexamined forever. Opting a package in therefore buys one rebuild: what its published build actually linked against is not knowable from here, and a record written without a rebuild would certify a build nobody checked.
The bump is the point of the command, and it has to land in git rather than in the builder. A rebuild that reuses the published version string produces a package pacman will never offer anyone, so merely unlocking the build gate would ship nothing. Bumping pkgrel needs no other change: `bin/check-versions` and the builder both already rebuild when pkgrel moves.
For an AUR-synced package the bump is expressed as the dotted Omarchy pkgrel suffix in the metadata as well as in the PKGBUILD, because the next AUR sync replaces the PKGBUILD wholesale and would otherwise drop it.
The bumped version is checked against the published one as well as the checked-in one, and refused when pacman would not order it higher. The checked-in version is not the floor; what a user already has is, and a checkout that has fallen behind the repository can otherwise be bumped to something that loses to the package it means to replace. That check is skipped with a warning when the published database cannot be read.
Versions are read from the local pacman database, so this runs on Arch or in an Arch container against a synced database. Only `core`, `extra` and `multilib` count: a Qt release sitting in testing or kde-unstable is not what the builder will link against, and rebuilding for it would ship a package built against the wrong ABI. The workflow points that database at `mirror.omarchy.org`, the mirror the x86_64 builder itself uses, because a mirror running ahead of the builder would record a version the build never linked against and nothing re-fires once the record matches.
aarch64 is not covered. Those builds resolve Qt from Arch Linux ARM, which can lag Arch, so one record cannot describe both architectures. Only x86_64 is published today, so nothing currently ships from the untracked side; if ARM publishing starts, `rebuilt_against` has to become per-architecture before this can be trusted there.
### Other
```bash
@@ -296,6 +324,7 @@ bin/add-package <package> # Add an AUR/local package with metadata
bin/package-worktree <package> # Create upstream/patched/current scratch workspace
bin/repo remove <package> # Remove package
bin/sync-upstream # Update packages that track a vendor release feed
bin/sync-rebuilds # Bump pkgrel for packages whose dependencies moved
bin/clean-docker # Clear Docker images/cache (forces fresh rebuild)
```
@@ -439,6 +468,8 @@ Fields:
- `release_ring`: optional. `fast` means the package is built directly for stable as well as edge. Packages without a ring build in edge and reach stable through tested artifact promotion (`bin/repo migrate`).
- `skip_build`: optional boolean; defaults to `false`. Set `true` to exclude a package from scheduled version checks and unscoped builds. The package can still be built explicitly with `bin/repo release --package <name>`.
- `pkgrel`: optional Omarchy pkgrel suffix for a version-pinned rebuild bump. This emits `<aur pkgrel>.<suffix>` instead of replacing AUR's pkgrel. `offset` can be used only when preserving monotonic upgrades from old absolute pkgrel bumps. The metadata is removed automatically when AUR sync changes `pkgver`; the current package version is read from the checked-in PKGBUILD, so the version is not duplicated in JSON.
- `rebuild_on`: optional array of package names this package links against closely enough that it must be rebuilt when they change, independent of its own source. Read by `bin/sync-rebuilds`.
- `rebuilt_against`: written by `bin/sync-rebuilds`. Records the version of each `rebuild_on` package that the current pkgrel was bumped for.
- `upstream_commit`: set by `bin/sync-aur` for AUR packages. Used by `bin/package-worktree` to recreate the exact raw AUR package that Omarchy last synced.
### Build Matrix
@@ -567,6 +598,8 @@ Packages are only rebuilt if:
- PKGBUILD version is newer than repository version
- Package doesn't exist in production
Neither notices a package that has to be rebuilt because something underneath it changed. That case is handled by turning it into a version change: `bin/sync-rebuilds` bumps pkgrel when a dependency named in `rebuild_on` moves.
## Automated Releases
The repository includes GitHub workflows and systemd services for automated releases.
@@ -577,6 +610,7 @@ The repository includes GitHub workflows and systemd services for automated rele
1. **sync-aur.yml** (Every 6 hours): Syncs AUR packages according to `.omarchy/package.json` and opens a PR when changes are found.
2. **sync-upstream.yml** (Every 6 hours): Runs `.omarchy/upstream.sh` for packages that track a vendor release feed and opens a PR when a newer version is out.
3. **sync-rebuilds.yml** (Every 6 hours): Bumps pkgrel for packages whose `rebuild_on` dependencies have moved in the official repositories and opens a PR.
#### Systemd Services
+4 -1
View File
@@ -246,7 +246,10 @@ apply_pkgrel_override() {
jq -e 'has("pkgrel")' "$metadata" >/dev/null || return 1
local current_pkgver suffix offset base rel tmpfile
current_pkgver=$(grep -m1 '^pkgver=' "$pkgbuild" | cut -d= -f2)
# Read through the same accessor that produced previous_pkgver. Parsing it a
# second time here let a quoted pkgver= compare unequal to itself, which threw
# away the pkgrel metadata of an unchanged package on every sync.
current_pkgver=$(get_pkgbuild_field "$package_dir" pkgver)
if [[ -n "$previous_pkgver" && "$current_pkgver" != "$previous_pkgver" ]]; then
print_info "Removing stale pkgrel metadata for $(display_package_name "$package_dir") (pkgver changed: $previous_pkgver -> $current_pkgver)"
+638
View File
@@ -0,0 +1,638 @@
#!/bin/bash
set -euo pipefail
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/package-metadata.sh"
TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT
SPECIFIC_PACKAGES=()
SELF_TEST=false
# Only the repositories a user actually installs from. A Qt release sitting in
# testing or kde-unstable is not what the build container will link against, and
# rebuilding for it would ship a package built against the wrong ABI.
OFFICIAL_REPOS=" core extra multilib core-debug extra-debug "
# The published repository, used as the floor a bumped pkgrel has to clear.
# Only x86_64 is published today; aarch64 has no repository to compare against.
PUBLISHED_BASE_URL="${OMARCHY_PUBLISHED_BASE_URL:-https://pkgs.omarchy.org}"
PUBLISHED_MIRRORS=(edge stable)
PUBLISHED_ARCH=x86_64
usage() {
cat <<EOF
Usage: $0 [PACKAGE...]
Bump pkgrel for packages that have to be rebuilt when a dependency changes
underneath them, rather than when their own source moves.
A package opts in by naming those dependencies in .omarchy/package.json:
{ "source": "aur", "sync": false, "rebuild_on": ["qt6-base"] }
The versions the current pkgrel was bumped for are recorded alongside, in
rebuilt_against, and written by this command:
{ "rebuild_on": ["qt6-base"], "rebuilt_against": { "qt6-base": "6.11.2-2" } }
pkgrel is bumped unless every package named in rebuild_on is recorded and still
matches. A name that is missing from the record counts as changed, so opting a
package in, or adding a dependency to one already opted in, buys one rebuild
rather than a record that certifies a build nobody checked.
The bump has to happen in git rather than in the builder, because a rebuild that
reuses the published version string is a package pacman will never offer anyone.
For the same reason the bumped version is checked against the published one and
refused if it would not be an upgrade.
Arguments:
PACKAGE One or more package names to update (optional)
Options:
--self-test Run the built-in regression tests and exit
-h, --help Show this help
Examples:
$0 # Update every package that declares rebuild_on
$0 quickshell-git # Update specific packages
Trigger versions are read from the local pacman database, so sync it first
(pacman -Sy) or this reports whatever that database last saw.
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
--self-test)
SELF_TEST=true
shift
;;
--*)
print_error "Unknown option: $1"
exit 1
;;
*)
SPECIFIC_PACKAGES+=("$1")
shift
;;
esac
done
UPDATED=0
SKIPPED=0
FAILED=0
SPECIFIC_MODE=false
# The version of a trigger package as the build container would resolve it.
# A name pacman does not know reports nothing rather than failing, so the caller
# gets to say which package was left alone instead of the run dying here.
repo_version() {
local package="$1"
local info
info=$(LC_ALL=C pacman -Si "$package" 2>/dev/null) || return 0
awk -v allowed="$OFFICIAL_REPOS" '
/^Repository[[:space:]]*:/ { repo = $3 }
/^Version[[:space:]]*:/ {
if (index(allowed, " " repo " ") > 0) { print $3; exit }
}
' <<<"$info"
}
declare -A PUBLISHED_VERSION=()
PUBLISHED_LOADED=false
PUBLISHED_AVAILABLE=true
remember_published() {
local name="$1"
local version="$2"
local known="${PUBLISHED_VERSION[$name]:-}"
# A package can be in both mirrors at different revisions. The floor is the
# highest of them, because that is what a user could already have installed.
if [[ -z "$known" || "$(vercmp "$version" "$known")" -gt 0 ]]; then
PUBLISHED_VERSION["$name"]="$version"
fi
}
# Versions currently published, read from the repository databases. Split
# packages are stored under their own pkgname, so both %NAME% and %BASE% are
# recorded to make a pkgbase findable.
load_published_versions() {
[[ "$PUBLISHED_LOADED" == true ]] && return 0
PUBLISHED_LOADED=true
local mirror db name base version
for mirror in "${PUBLISHED_MIRRORS[@]}"; do
db="$TEMP_DIR/published-$mirror.db.tar.zst"
if ! curl -fsSL --max-time 120 -o "$db" \
"$PUBLISHED_BASE_URL/$mirror/$PUBLISHED_ARCH/omarchy.db.tar.zst" 2>/dev/null; then
print_warning "Could not read the published $mirror database; bumps are not checked against it this run"
PUBLISHED_AVAILABLE=false
continue
fi
while IFS=$'\t' read -r name base version; do
[[ -n "$name" && -n "$version" ]] && remember_published "$name" "$version"
[[ -n "$base" && -n "$version" ]] && remember_published "$base" "$version"
done < <(
tar -xOf "$db" --wildcards '*/desc' 2>/dev/null | awk '
function emit() {
if (name != "" && version != "") print name "\t" base "\t" version
name=""; base=""; version=""
}
$0 == "%FILENAME%" { emit(); next }
$0 == "%NAME%" { if (name != "" && version != "") emit(); getline; name=$0; next }
$0 == "%BASE%" { getline; base=$0; next }
$0 == "%VERSION%" { getline; version=$0; next }
END { emit() }
'
)
done
}
published_version() {
local package="$1"
load_published_versions
echo "${PUBLISHED_VERSION[$package]:-}"
}
# The pkgver of a full version string, with any epoch and pkgrel removed.
version_pkgver() {
local version="${1#*:}"
echo "${version%-*}"
}
pkgbuild_field() {
local package_dir="$1"
local field="$2"
(cd "$package_dir" && env -u OMARCHY_SRC bash -c "source PKGBUILD 2>/dev/null; echo \"\${$field:-}\"")
}
# 2 -> 3, and 1.1 -> 1.2. Anything else is a pkgrel this command has no business
# rewriting.
bump_pkgrel() {
local pkgrel="$1"
[[ "$pkgrel" =~ ^[0-9]+(\.[0-9]+)?$ ]] || return 1
local head tail
if [[ "$pkgrel" == *.* ]]; then
head="${pkgrel%.*}."
tail="${pkgrel##*.}"
else
head=""
tail="$pkgrel"
fi
echo "${head}$((tail + 1))"
}
write_pkgrel() {
local package_dir="$1"
local pkgrel="$2"
local pkgbuild="$package_dir/PKGBUILD"
if [[ $(grep -c '^pkgrel=' "$pkgbuild") -ne 1 ]]; then
print_error "Expected exactly one pkgrel assignment in $pkgbuild"
return 1
fi
# Every edit lands on a scratch copy that replaces the PKGBUILD in one rename,
# so a failed rewrite leaves the original alone rather than half updated.
local scratch="$pkgbuild.sync-rebuilds"
cp "$pkgbuild" "$scratch" || return 1
sed -i "s/^pkgrel=.*/pkgrel=$pkgrel/" "$scratch"
if ! bash -n "$scratch" 2>/dev/null; then
print_error "Rewritten PKGBUILD is not valid shell"
rm -f "$scratch"
return 1
fi
local written
written=$(CARCH=x86_64 bash -c 'source "$1" >/dev/null 2>&1 || exit 1; echo "$pkgrel"' _ "$scratch" 2>/dev/null)
if [[ "$written" != "$pkgrel" ]]; then
print_error "Rewritten PKGBUILD reads back pkgrel=$written, not $pkgrel"
rm -f "$scratch"
return 1
fi
chmod --reference="$pkgbuild" "$scratch"
mv "$scratch" "$pkgbuild"
}
write_metadata() {
local package_dir="$1"
local filter="$2"
shift 2
local metadata
metadata=$(metadata_file_for_dir "$package_dir")
local scratch="$metadata.sync-rebuilds"
jq "$@" "$filter" "$metadata" > "$scratch" || { rm -f "$scratch"; return 1; }
chmod --reference="$metadata" "$scratch"
mv "$scratch" "$metadata"
}
record_triggers() {
local package_dir="$1"
local current="$2"
write_metadata "$package_dir" '.rebuilt_against = $current' --argjson current "$current"
}
# Metadata that does not parse would otherwise drop its package out of the run
# without a word, because every query of it reports nothing and an absent
# rebuild_on is indistinguishable from an unreadable one.
check_metadata_readable() {
local package_dir="$1"
local metadata
metadata=$(metadata_file_for_dir "$package_dir")
[[ -f "$metadata" ]] || return 0
if ! jq empty "$metadata" 2>/dev/null; then
print_error "Unreadable metadata, skipping $(basename "$package_dir"): $metadata"
((++FAILED))
return 1
fi
}
sync_package() {
local package="$1"
local package_dir="$PKGBUILDS_DIR/$package"
if [[ ! -f "$package_dir/PKGBUILD" ]]; then
print_error "Package $package has no PKGBUILD"
((++FAILED))
return 0
fi
check_metadata_readable "$package_dir" || return 0
local triggers=()
mapfile -t triggers < <(package_rebuild_triggers "$package_dir")
if [[ ${#triggers[@]} -eq 0 ]]; then
if [[ "$SPECIFIC_MODE" == true ]]; then
print_error "Package $package does not declare rebuild_on"
((++FAILED))
else
print_info "Skipping $package: no rebuild triggers"
((++SKIPPED))
fi
return 0
fi
print_info "Checking $package against ${triggers[*]}..."
local current="{}" trigger version
for trigger in "${triggers[@]}"; do
version=$(repo_version "$trigger")
if [[ -z "$version" ]]; then
print_error " $trigger is in no official repository; leaving $package alone"
((++FAILED))
return 0
fi
if ! current=$(jq -c --arg name "$trigger" --arg version "$version" '.[$name] = $version' <<<"$current"); then
print_error " Could not record $trigger $version for $package"
((++FAILED))
return 0
fi
done
local recorded
if ! recorded=$(package_metadata_value "$package_dir" '.rebuilt_against' ""); then
print_error " Could not read .omarchy/package.json for $package"
((++FAILED))
return 0
fi
[[ -n "$recorded" && "$recorded" != "null" ]] || recorded="{}"
# Walk the declared triggers rather than the record, so a name the record does
# not carry reads as changed instead of going unexamined forever.
local moved
if ! moved=$(jq -r --argjson recorded "$recorded" '
to_entries
| map(select($recorded[.key] != .value)
| "\(.key) \($recorded[.key] // "unrecorded") -> \(.value)")
| join(", ")
' <<<"$current"); then
print_error " Could not compare recorded trigger versions for $package"
((++FAILED))
return 0
fi
if [[ -z "$moved" ]]; then
print_info " Already rebuilt against $(jq -r 'to_entries | map("\(.key) \(.value)") | join(", ")' <<<"$current")"
((++SKIPPED))
return 0
fi
local pkgrel next_pkgrel
pkgrel=$(pkgbuild_field "$package_dir" pkgrel)
# An AUR-synced package gets its PKGBUILD replaced wholesale on the next sync,
# so the bump only survives as the dotted Omarchy suffix that sync-aur
# reapplies from .omarchy/package.json.
local suffix=""
if package_sync_enabled "$package_dir"; then
if [[ "$pkgrel" == *.* ]]; then
next_pkgrel=$(bump_pkgrel "$pkgrel") || next_pkgrel=""
suffix="${next_pkgrel##*.}"
else
next_pkgrel="$pkgrel.1"
suffix="1"
fi
else
next_pkgrel=$(bump_pkgrel "$pkgrel") || next_pkgrel=""
fi
if [[ -z "$next_pkgrel" ]]; then
print_error " Cannot bump pkgrel=$pkgrel for $package; bump it by hand"
((++FAILED))
return 0
fi
local pkgver epoch old_version new_version
pkgver=$(pkgbuild_field "$package_dir" pkgver)
epoch=$(pkgbuild_field "$package_dir" epoch)
old_version="${epoch:+$epoch:}$pkgver-$pkgrel"
new_version="${epoch:+$epoch:}$pkgver-$next_pkgrel"
if [[ "$(vercmp "$new_version" "$old_version")" -le 0 ]]; then
print_error " pkgrel $pkgrel -> $next_pkgrel would not be an upgrade for $package"
((++FAILED))
return 0
fi
# The checked-in version is not the floor. What a user already has is, and a
# checkout that has fallen behind the repository can otherwise be bumped to
# something pacman orders below what it would replace.
local floor
floor=$(published_version "$package")
if [[ -n "$floor" && "$(version_pkgver "$floor")" == "$pkgver" ]]; then
if [[ "$(vercmp "$new_version" "$floor")" -le 0 ]]; then
print_error " $new_version would not be an upgrade over the published $floor; leaving $package alone"
((++FAILED))
return 0
fi
fi
if ! write_pkgrel "$package_dir" "$next_pkgrel"; then
print_error " Failed to bump pkgrel for $package"
((++FAILED))
return 0
fi
if [[ -n "$suffix" ]] && ! write_metadata "$package_dir" '.pkgrel.suffix = ($suffix | tonumber)' --arg suffix "$suffix"; then
print_error " Failed to record pkgrel suffix for $package"
((++FAILED))
return 0
fi
if ! record_triggers "$package_dir" "$current"; then
print_error " Failed to record trigger versions for $package"
((++FAILED))
return 0
fi
print_success " $moved; pkgrel $pkgrel -> $next_pkgrel"
((++UPDATED))
}
run_sync() {
if [[ ${#SPECIFIC_PACKAGES[@]} -gt 0 ]]; then
SPECIFIC_MODE=true
for package in "${SPECIFIC_PACKAGES[@]}"; do
sync_package "$package"
done
else
# Enumerated up front rather than streamed, so a producer that dies partway
# cannot quietly shorten the list of packages considered.
local packages=()
mapfile -t packages < <(package_dirs)
local package_dir
for package_dir in "${packages[@]}"; do
check_metadata_readable "$package_dir" || continue
if package_has_rebuild_triggers "$package_dir"; then
sync_package "$(basename "$package_dir")"
fi
done
fi
echo ""
if [[ $FAILED -gt 0 ]]; then
print_error "Rebuild trigger sync completed with failures"
else
print_success "Rebuild trigger sync complete!"
fi
echo " Target: $PKGBUILDS_DIR"
echo " Updated: $UPDATED"
echo " Skipped: $SKIPPED"
echo " Failed: $FAILED"
[[ $FAILED -eq 0 ]]
}
# --- self-test ---------------------------------------------------------------
# Each case runs the real script against a throwaway repository root, with
# pacman and curl replaced by stubs, so what is exercised is the decision path
# itself rather than a restatement of it.
selftest_root() {
local name="$1"
local root="$TEMP_DIR/case-$name"
mkdir -p "$root/bin" "$root/helpers" "$root/pkgbuilds" "$root/stub"
cp "$BUILD_ROOT/bin/sync-rebuilds" "$root/bin/"
cp "$BUILD_ROOT"/helpers/*.sh "$root/helpers/"
echo "$root"
}
selftest_package() {
local root="$1" name="$2" pkgrel="$3" metadata="$4" pkgver="${5:-1.0}"
local dir="$root/pkgbuilds/$name"
mkdir -p "$dir/.omarchy"
printf 'pkgname=%s\npkgver=%s\npkgrel=%s\narch=(x86_64)\n' "$name" "$pkgver" "$pkgrel" > "$dir/PKGBUILD"
printf '%s\n' "$metadata" > "$dir/.omarchy/package.json"
}
selftest_pacman() {
local root="$1"
shift
printf '%s\n' "$@" > "$root/stub/versions"
cat > "$root/stub/pacman" <<'STUB'
#!/bin/bash
[[ "$1" == "-Si" ]] || exit 1
version=$(awk -F= -v p="$2" '$1 == p { print $2; exit }' "$(dirname "$0")/versions")
[[ -n "$version" ]] || exit 1
printf 'Repository : extra\nName : %s\nVersion : %s\n\n' "$2" "$version"
STUB
chmod +x "$root/stub/pacman"
}
# Serves a repository database assembled by hand from name=version pairs. With
# none given the stub fails, which is how the unreachable-repository path is
# exercised.
selftest_published() {
local root="$1"
shift
local staging="$root/stub/db"
local entry name version
if [[ $# -gt 0 ]]; then
rm -rf "$staging"
mkdir -p "$staging"
for entry in "$@"; do
name="${entry%=*}"
version="${entry#*=}"
mkdir -p "$staging/$name-$version"
printf '%%FILENAME%%\n%s-%s-x86_64.pkg.tar.zst\n\n%%NAME%%\n%s\n\n%%BASE%%\n%s\n\n%%VERSION%%\n%s\n' \
"$name" "$version" "$name" "$name" "$version" > "$staging/$name-$version/desc"
done
tar --zstd -cf "$root/stub/omarchy.db.tar.zst" -C "$staging" .
fi
cat > "$root/stub/curl" <<'STUB'
#!/bin/bash
out=""
while [[ $# -gt 0 ]]; do
case "$1" in
-o) out="$2"; shift 2 ;;
*) shift ;;
esac
done
db="$(dirname "$0")/omarchy.db.tar.zst"
[[ -f "$db" && -n "$out" ]] || exit 22
cp "$db" "$out"
STUB
chmod +x "$root/stub/curl"
}
cmd_self_test() {
local failures=0
local root
check() {
local label="$1" expected="$2" got="$3"
if [[ "$got" == "$expected" ]]; then
echo " ok: $label"
else
echo " FAIL: $label -> $got (expected $expected)"
failures=$((failures + 1))
fi
}
run_case() {
local root="$1"
shift
local status=0
PATH="$root/stub:$PATH" "$root/bin/sync-rebuilds" "$@" > "$root/output" 2>&1 || status=$?
echo "$status"
}
pkgrel_of() {
grep -m1 '^pkgrel=' "$1/PKGBUILD" | cut -d= -f2
}
print_header "sync-rebuilds self-test"
echo "A trigger missing from the record counts as changed:"
root=$(selftest_root partial)
selftest_package "$root" t-partial 1 '{"source":"local","rebuild_on":["dep-a","dep-b"],"rebuilt_against":{"dep-a":"1-1"}}'
selftest_pacman "$root" dep-a=1-1 dep-b=2-2
selftest_published "$root"
check "run succeeds" 0 "$(run_case "$root")"
check "pkgrel bumped" 2 "$(pkgrel_of "$root/pkgbuilds/t-partial")"
check "unrecorded trigger now recorded" "2-2" \
"$(jq -r '.rebuilt_against["dep-b"]' "$root/pkgbuilds/t-partial/.omarchy/package.json")"
echo "Opting a package in buys a rebuild rather than a bare record:"
root=$(selftest_root fresh)
selftest_package "$root" t-fresh 1 '{"source":"local","rebuild_on":["dep-a"]}'
selftest_pacman "$root" dep-a=1-1
selftest_published "$root"
check "run succeeds" 0 "$(run_case "$root")"
check "pkgrel bumped" 2 "$(pkgrel_of "$root/pkgbuilds/t-fresh")"
check "trigger recorded" "1-1" \
"$(jq -r '.rebuilt_against["dep-a"]' "$root/pkgbuilds/t-fresh/.omarchy/package.json")"
echo "An unchanged package is left alone:"
root=$(selftest_root current)
selftest_package "$root" t-current 1 '{"source":"local","rebuild_on":["dep-a"],"rebuilt_against":{"dep-a":"1-1"}}'
selftest_pacman "$root" dep-a=1-1
selftest_published "$root"
check "run succeeds" 0 "$(run_case "$root")"
check "pkgrel untouched" 1 "$(pkgrel_of "$root/pkgbuilds/t-current")"
echo "Metadata that does not parse fails the run instead of vanishing from it:"
root=$(selftest_root unreadable)
selftest_package "$root" t-broken 1 '{"source":"local","rebuild_on":["dep-a"'
selftest_package "$root" t-good 1 '{"source":"local","rebuild_on":["dep-a"]}'
selftest_pacman "$root" dep-a=1-1
selftest_published "$root"
check "run fails" 1 "$(run_case "$root")"
check "the readable package is still processed" 2 "$(pkgrel_of "$root/pkgbuilds/t-good")"
echo "A bump that pacman would not order above the published package is refused:"
root=$(selftest_root floor)
selftest_package "$root" t-floor 1 '{"source":"local","rebuild_on":["dep-a"],"rebuilt_against":{"dep-a":"0-0"}}'
selftest_pacman "$root" dep-a=1-1
selftest_published "$root" t-floor=1.0-5
check "run fails" 1 "$(run_case "$root")"
check "pkgrel untouched" 1 "$(pkgrel_of "$root/pkgbuilds/t-floor")"
check "record untouched" "0-0" \
"$(jq -r '.rebuilt_against["dep-a"]' "$root/pkgbuilds/t-floor/.omarchy/package.json")"
echo "An AUR-synced package is bumped as a dotted suffix that sync-aur reapplies:"
root=$(selftest_root aur)
selftest_package "$root" t-aur 3 '{"source":"aur","rebuild_on":["dep-a"],"rebuilt_against":{"dep-a":"0-0"}}'
selftest_pacman "$root" dep-a=1-1
selftest_published "$root"
check "run succeeds" 0 "$(run_case "$root")"
check "pkgrel suffixed" "3.1" "$(pkgrel_of "$root/pkgbuilds/t-aur")"
check "suffix recorded for the next AUR sync" 1 \
"$(jq -r '.pkgrel.suffix' "$root/pkgbuilds/t-aur/.omarchy/package.json")"
echo ""
if [[ "$failures" -eq 0 ]]; then
print_success "Self-test passed"
return 0
fi
print_error "$failures self-test failure(s)"
return 1
}
if [[ "$SELF_TEST" == true ]]; then
cmd_self_test
exit $?
fi
for tool in pacman vercmp jq curl; do
if ! command -v "$tool" >/dev/null 2>&1; then
print_error "$tool not found: reading trigger versions and ordering pkgrels both need pacman"
exit 1
fi
done
print_header "Rebuild Trigger Sync"
run_sync
+45 -1
View File
@@ -10,9 +10,11 @@
# { "source": "aur", "release_ring": "fast" }
# { "source": "aur", "skip_build": true }
# { "source": "aur", "pkgrel": { "suffix": 1, "offset": 1 } }
# { "source": "aur", "rebuild_on": ["qt6-base"] }
# { "source": "local" }
#
# bin/sync-aur also writes upstream_commit for AUR-backed packages.
# bin/sync-aur also writes upstream_commit for AUR-backed packages, and
# bin/sync-rebuilds writes rebuilt_against for packages declaring rebuild_on.
if [[ -z "${PKGBUILDS_DIR:-}" ]]; then
if [[ -n "${BUILD_ROOT:-}" ]]; then
@@ -148,6 +150,33 @@ packages_for_upstream_sync() {
done
}
# Packages that must be rebuilt when a dependency they link against changes,
# even though nothing in their own source moved. `rebuild_on` names those
# dependencies; `rebuilt_against` records the versions the checked-in pkgrel was
# last bumped for.
package_rebuild_triggers() {
local pkgdir="$1"
local metadata
metadata=$(metadata_file_for_dir "$pkgdir")
[[ -f "$metadata" ]] || return 0
jq -r '(.rebuild_on // [])[]' "$metadata"
}
package_has_rebuild_triggers() {
local pkgdir="$1"
[[ -n "$(package_rebuild_triggers "$pkgdir")" ]]
}
packages_for_rebuild_sync() {
package_dirs | while IFS= read -r pkgdir; do
if package_has_rebuild_triggers "$pkgdir"; then
basename "$pkgdir"
fi
done
}
packages_for_mirror() {
local mirror="$1"
@@ -299,4 +328,19 @@ validate_package_metadata() {
echo "invalid upstream_commit for $(basename "$pkgdir"): must be a string"
return 1
fi
if ! jq -e '(.rebuild_on // []) | type == "array" and all(type == "string" and length > 0)' "$metadata" >/dev/null; then
echo "invalid rebuild_on for $(basename "$pkgdir"): must be an array of package names"
return 1
fi
if ! jq -e '(.rebuilt_against // {}) | type == "object" and (to_entries | all(.value | type == "string" and length > 0))' "$metadata" >/dev/null; then
echo "invalid rebuilt_against for $(basename "$pkgdir"): must be an object mapping package names to versions"
return 1
fi
if ! jq -e '((.rebuilt_against // {}) | keys) - (.rebuild_on // []) | length == 0' "$metadata" >/dev/null; then
echo "invalid rebuilt_against for $(basename "$pkgdir"): records a package that rebuild_on does not name"
return 1
fi
}
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "0dc154feba89c35a03b31044f4b68e23b0cc8763"
"upstream_commit": "a0f4262f94eb8a5b604146e71d42a3bb522feedf"
}
+6 -6
View File
@@ -1,6 +1,6 @@
pkgname=1password-beta
_tarver=8.12.32-26.BETA
_tarver=8.12.34-29.BETA
case "${CARCH}" in
x86_64)
_archdir="x64"
@@ -10,7 +10,7 @@ case "${CARCH}" in
;;
esac
pkgver=${_tarver//-/_}
pkgrel=26.1
pkgrel=29.1
conflicts=('1password' '1password-beta-bin')
pkgdesc="Password manager and secure wallet"
arch=('x86_64' 'aarch64')
@@ -22,10 +22,10 @@ source=()
sha256sums=()
source_x86_64=(https://downloads.1password.com/linux/tar/beta/x86_64/1password-${_tarver}.x64.tar.gz{,.sig})
source_aarch64=(https://downloads.1password.com/linux/tar/beta/aarch64/1password-${_tarver}.arm64.tar.gz{,.sig})
sha256sums_x86_64=('f4bb6c3917bfa35f92c417de18215fea188ed6ec2e056c888c756cda35b414da'
'fd58f8b63b9fad8f154388a77cca400b1578a02569f9e9127fef00a82527a961')
sha256sums_aarch64=('cf24f2a93108ab8997b6dcb2e5509a8bda01813368f2db26b6a53e3ee64eb460'
'f7fb7b1fddf4d34e18f655d01c76345cde91fbd711da32a99cb39d0bb13f36fa')
sha256sums_x86_64=('6894b283a534cf94b07903fb38966a0aab2e37f75ee3848ce340308819aadddb'
'8d4df4d0a80d2be7aad7d91ad964a750c8f32db5007261045003c191690c8246')
sha256sums_aarch64=('c77ce6ddf36dbd6054c64d91b7f644274d3218f465fd60e211d0296f6443124a'
'91c7249a1cf5e7924ef2810cb0cb1b893d8a9a424b373b433f45d7aaa5a8369b')
validpgpkeys=('3FEF9748469ADBE15DA7CA80AC2D62742012EA22')
package() {
+3 -3
View File
@@ -1,3 +1,3 @@
SSH_PRIVATE_KEY_B64 = "op://cgl-build-release-archlinux-aur-prod/AUR_SSH_PRIVATE_KEY_B64/credential"
SSH_PASSPHRASE_B64 = "op://cgl-build-release-archlinux-aur-prod/AUR_SSH_PASSPHRASE_B64/credential"
SSH_KNOWN_HOSTS = "op://cgl-build-release-archlinux-aur-prod/AUR_SSH_KNOWN_HOSTS/credential"
SSH_PRIVATE_KEY_B64 = "op://core-release-archlinux-aur-prod/AUR_SSH_PRIVATE_KEY_B64/credential"
SSH_PASSPHRASE_B64 = "op://core-release-archlinux-aur-prod/AUR_SSH_PASSPHRASE_B64/credential"
SSH_KNOWN_HOSTS = "op://core-release-archlinux-aur-prod/AUR_SSH_KNOWN_HOSTS/credential"
+1 -1
View File
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "dafe1ccc184afe7d88fcfc71a659cda565928599"
"upstream_commit": "493c7874a18da7b24f869ee576c5c33d4e726c69"
}
+4 -4
View File
@@ -1,6 +1,6 @@
# Maintainer: Bjarne Øverli <bjarne@oever.li>
pkgname=aether
pkgver=4.29.0
pkgver=4.29.2
pkgrel=1
pkgdesc='Desktop theming application - extract colors from wallpapers and apply cohesive themes'
arch=('x86_64' 'aarch64')
@@ -10,9 +10,9 @@ depends=('webkit2gtk-4.1' 'gtk3')
source=("aether-${pkgver}.tar.gz::https://github.com/bjarneo/aether/archive/refs/tags/v${pkgver}.tar.gz")
source_x86_64=("aether-linux-amd64-${pkgver}::https://github.com/bjarneo/aether/releases/download/v${pkgver}/aether-linux-amd64")
source_aarch64=("aether-linux-arm64-${pkgver}::https://github.com/bjarneo/aether/releases/download/v${pkgver}/aether-linux-arm64")
sha256sums=('fa9b31d1218b1d367cb43755015768474749d69a172694826242afba940a49f3')
sha256sums_x86_64=('bbb56ec3004ae5e83cfdaf89d2e28b727c0ca94a44c1942c5dd6bf8a7f261197')
sha256sums_aarch64=('876c5f1c46bbc31a88868ce8899a3b7bcbeb907f2927067c15d7b865fd3c6a0f')
sha256sums=('1756a54f1f823ea78d3e0011ba51696e751e9372bf24ddcf0269d57ef2322043')
sha256sums_x86_64=('1722a8abaa9379cf592bc5886984398d5b2dac8e6a0007071ef809f4e4118bd5')
sha256sums_aarch64=('d9dc740c92ff29ee9f1e954af1d33e0dcbf513745dcd88f36db8faea995aa897')
noextract=("aether-linux-amd64-${pkgver}" "aether-linux-arm64-${pkgver}")
package() {
+1 -1
View File
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "7c3ef4648d591f88e10bb3ce7e5286a7d805741a"
"upstream_commit": "2aa37e5f390a52c5cd5406da55ea971229b08666"
}
+3 -3
View File
@@ -4,7 +4,7 @@
# Automation repository: https://github.com/fabifont/claude-code-aur
pkgname=claude-code
pkgver=2.1.233
pkgver=2.1.235
pkgrel=1
pkgdesc="An agentic coding tool that lives in your terminal"
arch=('x86_64' 'aarch64')
@@ -29,8 +29,8 @@ source_x86_64=("claude-${pkgver}-x86_64::https://downloads.claude.ai/claude-code
source_aarch64=("claude-${pkgver}-aarch64::https://downloads.claude.ai/claude-code-releases/${pkgver}/linux-arm64/claude")
sha256sums=('SKIP')
sha256sums_x86_64=('55d281096f57d411ebbdd94dbf5e9ff3accb7c05713e37348c2c11d4b83bf9d9')
sha256sums_aarch64=('42df1841f74e9b2ac13f2c1a2a820ef6b9ac5b2efb8646bb25c9a92b8bd69194')
sha256sums_x86_64=('bfcf0ae2dbf94b2b6a106074aabf3938b9a10889c3b678e4cb5a00c03274d5d5')
sha256sums_aarch64=('cff9592faa292db0f6ac21874f151b8c3d44e23bf0ab9fd1bcca95edc3469549')
package() {
install -Dm755 "${srcdir}/claude-${pkgver}-${CARCH}" "${pkgdir}/opt/claude-code/bin/claude"
+1 -1
View File
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "3d08ca4a239916ab489dbd4a5794cc66aaf1b3b4"
"upstream_commit": "dcb9ca9a1a5720f845c3e56f75a105f0ec91b002"
}
+3 -3
View File
@@ -1,7 +1,7 @@
# Maintainer: Gunther Schulz <dev@guntherschulz.de>
pkgname=cursor-bin
pkgver=3.16.17
pkgver=3.16.29
pkgrel=1
pkgdesc='AI-first coding environment'
arch=('x86_64')
@@ -12,7 +12,7 @@ _electron=electron40
depends=(xdg-utils ripgrep $_electron nodejs
'gcc-libs' 'hicolor-icon-theme' 'libxkbfile')
options=(!strip !debug) # Don't break ext of VSCode
_commit=6b2afae0257df2bb5e1835f15165dc2f0de056b2
_commit=6246455961129c32969845e00aa25d87ae926ec9
source=("https://downloads.cursor.com/production/${_commit}/linux/x64/deb/amd64/deb/cursor_${pkgver}_amd64.deb"
"https://gitlab.archlinux.org/archlinux/packaging/packages/code/-/raw/main/code."{sh,mjs}
rg.sh)
@@ -20,7 +20,7 @@ sha512sums=('SKIP'
'937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37'
'793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033'
'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a')
sha512sums[0]=d33b0269fa8ff4ac8780c1119024a84ca37cc884653aa0ae5e7f51f871ca0d85a52afa7faea441c09fd3e2695a52626521917b3dfc2f2477ac73db4563297735
sha512sums[0]=1b637fdfcffb1764e3e5590da2fb0760dbc7ff93264477ae041ec3c40bb4bad88248e0fa452ec93c58602f3682c24f188d0c2634bd445ff2c0f3547b97525a7b
noextract=(cursor_${pkgver}_amd64.deb) # avoid double tarball
_app=usr/share/cursor/resources/app
package() {
+1 -1
View File
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "6e0c64df004f98631b7836d19a054bc182f4eb96"
"upstream_commit": "3dfb688acd5c2a14b2919eb4435007e08223a293"
}
+13 -21
View File
@@ -1,11 +1,13 @@
Terms of Service
Last Updated: June 13, 2025
Last Updated: August 13, 2026
Welcome, and thank you for your interest in Anysphere, Inc. (“Anysphere,” “we,” or “us”), makers of the Cursor software platform. These Terms of Service (“Terms”) govern your access to and use of Anysphere's software, platform, APIs, Documentation, and related tools, including the website www.cursor.com, and all related software made available by Anysphere to build, deploy, host, and manage software projects (collectively, the “Service”). By using the Service, you agree to these Terms.
Welcome, and thank you for your interest in Anysphere, Inc. (“Anysphere,” “we,” or “us”), makers of the Cursor software platform. These Terms of Service (“Terms”) govern your access to and use of Anysphere's software, platform, APIs, Documentation, and related tools, including the website www.cursor.com, and all related software made available by Anysphere to build, deploy, host, and manage software projects (collectively, the “Service”). By using the Service, you agree to these Terms including our Acceptable Use Policy.
Please also read our Privacy Policy⁠, which explains how we collect, use, disclose, and process personal data.
Please also carefully read the sections below regarding Limitation of Liability and Dispute Resolution, which affect your rights.
If you are using the Service as part of your work for a company or organization that has a Master Services Agreement (“MSA”) with Anysphere, your use of the Service is governed by that MSA.
If you are entering into these Terms on behalf of an entity, you represent that you have the legal authority to bind that entity.
@@ -85,36 +87,26 @@ If you are entering into these Terms on behalf of an entity, you represent that
15.2. LIABILITY CAP. TO THE FULLEST EXTENT PERMITTED BY LAW, THE AGGREGATE LIABILITY OF THE ANYSPHERE ENTITIES TO YOU FOR ALL CLAIMS, DAMAGES AND LOSSES ARISING OUT OF OR RELATING TO THESE TERMS, THE SERVICE, AND CONTENT, WHETHER IN CONTRACT, TORT, OR OTHERWISE, IS LIMITED TO THE GREATER OF: (A) THE AMOUNT YOU HAVE PAID TO ANYSPHERE FOR ACCESS TO AND USE OF THE SERVICE IN THE SIX (6) MONTHS PRIOR TO THE EVENT OR CIRCUMSTANCE GIVING RISE TO THE CLAIM OR, IF GREATER, (B) $100. THE FOREGOING LIMITATIONS ARE ESSENTIAL TO THESE TERMS, AND WE WOULD NOT OFFER THE SERVICE TO YOU UNDER THESE TERMS WITHOUT THESE LIMITATIONS. THE LIMITATIONS IN THIS SECTION WILL APPLY EVEN IF ANY LIMITED REMEDY FAILS OF ITS ESSENTIAL PURPOSE.
15.3. Limitations Period. You and Anysphere agree that you must initiate any proceeding or action asserting a federal claim within one (1) year of the date of the occurrence of the event or facts giving rise to a dispute that is arising out of or related to these Terms or the Service, or if such limitation period is unenforceable under applicable law, then the shortest limitation period permitted by applicable law. You and Anysphere agree that you must initiate any proceeding or action asserting a state law claim within two (2) years of the date of the occurrence of the event or facts giving rise to a dispute that is arising out of or related to these Terms or the Service. Otherwise, to the extent permitted by applicable law, you forever waive the right to pursue any claim or cause of action, of any kind or character, based on such events or facts, and such claims or causes of action are permanently barred.
16. DISPUTE RESOLUTION
PLEASE READ THIS SECTION CAREFULLY AS IT AFFECTS YOUR RIGHTS.
16.1. Agreement to Arbitrate. This Dispute Resolution by Binding Arbitration section is referred to in these Terms as the “Arbitration Agreement.” You agree that any and all disputes or claims that have arisen or may arise between you and Anysphere, whether arising out of or relating to these Terms (including any alleged breach thereof), the Service, any advertising, or any aspect of the relationship or transactions between us, will be resolved exclusively through final and binding arbitration, rather than a court, in accordance with the terms of this Arbitration Agreement, except that you may assert individual claims in small claims court, if your claims qualify. Further, this Arbitration Agreement does not preclude you from bringing issues to the attention of federal, state, or local agencies, and such agencies can, if the law allows, seek relief against us on your behalf. You agree that, by entering into these Terms, you and Anysphere are each waiving the right to a trial by jury or to participate in a class action. Your rights will be determined by a neutral arbitrator, not a judge or jury. The Federal Arbitration Act governs the interpretation and enforcement of this Arbitration Agreement. You may opt out of arbitration within 30 days of account creation or of any updates to these arbitration terms within 30 days after the update has taken effect, by sending an email to legal@cursor.com from the email address used to create your account, and providing your first and last name and a clear statement of intent that you intend to exercise your right to opt out of mandatory arbitration.
16.1. Governing Law, Forum Selection, Jurisdiction, and Venue. Unless prohibited by your country’s applicable law, the laws of the State of Texas, excluding its choice of law provisions, will govern these Terms and any dispute that arises between you and Anysphere, notwithstanding any other agreement between you and us to the contrary. Notwithstanding any other agreement to the contrary, unless prohibited by your country’s applicable law, all disputes related to these Terms, the Service, or any patents – including without limitation disputes related to or arising from any Content (whether your or others' Content), or your or others' use of the Service or the complete or partial termination thereof – shall be brought and must proceed exclusively in the federal or state courts located in Wichita County or Tarrant County, Texas, United States, and you and Anysphere consent to personal jurisdiction in those forums and waive any objection as to inconvenient forum. For the avoidance of doubt, the choice of law and forum selection provisions of this paragraph shall apply regardless of whether a dispute or any claims contained therein are based in contract, tort, statute, common law, or otherwise, and the choice of law and forum selection provisions of this paragraph shall apply to pending and future disputes and shall apply to your dispute regardless of when the conduct relating to the dispute arose or occurred. The choice of law and forum selection provisions of this paragraph shall also extend to disputes involving our U.S. corporate affiliates, who consent to and are intended third-party beneficiaries of this paragraph.
16.2. Prohibition of Class and Representative Actions and Non-Individualized Relief. YOU AND ANYSPHERE AGREE THAT EACH OF US MAY BRING CLAIMS AGAINST THE OTHER ONLY ON AN INDIVIDUAL BASIS AND NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY PURPORTED CLASS OR REPRESENTATIVE ACTION OR PROCEEDING. UNLESS BOTH YOU AND ANYSPHERE AGREE OTHERWISE, THE ARBITRATOR MAY NOT CONSOLIDATE OR JOIN MORE THAN ONE PERSON’S OR PARTY’S CLAIMS AND MAY NOT OTHERWISE PRESIDE OVER ANY FORM OF A CONSOLIDATED, REPRESENTATIVE, OR CLASS PROCEEDING. ALSO, THE ARBITRATOR MAY AWARD RELIEF (INCLUDING MONETARY, INJUNCTIVE, AND DECLARATORY RELIEF) ONLY IN FAVOR OF THE INDIVIDUAL PARTY SEEKING RELIEF AND ONLY TO THE EXTENT NECESSARY TO PROVIDE RELIEF NECESSITATED BY THAT PARTY’S INDIVIDUAL CLAIM(S), EXCEPT THAT YOU MAY PURSUE A CLAIM FOR AND THE ARBITRATOR MAY AWARD PUBLIC INJUNCTIVE RELIEF UNDER APPLICABLE LAW TO THE EXTENT REQUIRED FOR THE ENFORCEABILITY OF THIS PROVISION.
16.2. Prohibition of Class and Representative Actions and Non-Individualized Relief. YOU AND ANYSPHERE AGREE THAT EACH OF US MAY BRING CLAIMS AGAINST THE OTHER ONLY ON AN INDIVIDUAL BASIS AND NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY PURPORTED CLASS OR REPRESENTATIVE ACTION OR PROCEEDING. UNLESS BOTH YOU AND ANYSPHERE AGREE OTHERWISE, YOU AND ANYSPHERE AGREE NOT TO SEEK TO CONSOLIDATE OR JOIN MORE THAN ONE PERSON’S OR PARTY’S CLAIMS AND NOT TO OTHERWISE SEEK ANY FORM OF A CONSOLIDATED, REPRESENTATIVE, OR CLASS PROCEEDING. ALSO, YOU AND ANYSPHERE AGREE TO SEEK RELIEF (INCLUDING MONETARY, INJUNCTIVE, AND DECLARATORY RELIEF) ONLY IN FAVOR OF THE INDIVIDUAL PARTY SEEKING RELIEF AND ONLY TO THE EXTENT NECESSARY TO PROVIDE RELIEF NECESSITATED BY THAT PARTY’S INDIVIDUAL CLAIM(S), EXCEPT THAT YOU AND ANYSPHERE MAY PURSUE A CLAIM FOR PUBLIC INJUNCTIVE RELIEF UNDER APPLICABLE LAW TO THE EXTENT REQUIRED FOR THE ENFORCEABILITY OF THIS PROVISION.
16.3. Pre-Arbitration Dispute Resolution. Anysphere is always interested in resolving disputes amicably and efficiently, and most customer concerns can be resolved quickly and to the customer’s satisfaction by emailing legal@cursor.com. If such efforts prove unsuccessful, a party who intends to seek arbitration must first send to the other, by certified mail, a written Notice of Dispute (“Notice”) to Anysphere, Inc., 2261 Market Street STE 86466, San Francisco, CA 94114, with an electronic copy additionally sent to legal@cursor.com. The Notice must (i) describe the nature and basis of the claim or dispute and (ii) set forth the specific relief sought. If Anysphere and you do not resolve the claim within sixty (60) calendar days after the Notice is received, you or Anysphere may commence an arbitration proceeding. During the arbitration, the amount of any settlement offer made by Anysphere or you will not be disclosed to the arbitrator until after the arbitrator determines the amount, if any, to which you or Anysphere is entitled.
16.4. Arbitration Procedures. Arbitration will be conducted by a neutral arbitrator in accordance with the American Arbitration Association’s (“AAA”) rules and procedures, including the AAA’s Consumer Arbitration Rules (collectively, the “AAA Rules”), as modified by this Arbitration Agreement. For information on the AAA, please visit its website, https://www.adr.org. Information about the AAA Rules and fees for consumer disputes can be found at the AAA’s consumer arbitration page, https://www.adr.org/consumer. If there is any inconsistency between any term of the AAA Rules and any term of this Arbitration Agreement, the applicable terms of this Arbitration Agreement will control unless the arbitrator determines that the application of the inconsistent Arbitration Agreement terms would not result in a fundamentally fair arbitration. The arbitrator must also follow the provisions of these Terms as a court would. All issues are for the arbitrator to decide, including issues relating to the scope, enforceability, and arbitrability of this Arbitration Agreement. Although arbitration proceedings are usually simpler and more streamlined than trials and other judicial proceedings, the arbitrator can award the same damages and relief on an individual basis that a court can award to an individual under these Terms and applicable law. Decisions by the arbitrator are enforceable in court and may be overturned by a court only for very limited reasons. Unless Anysphere and you agree otherwise, any arbitration hearings will take place in a reasonably convenient location for both parties with due consideration of their ability to travel and other pertinent circumstances. If the parties are unable to agree on a location, the determination will be made by AAA. If your claim is for $10,000 or less, Anysphere agrees that you may choose whether the arbitration will be conducted solely on the basis of documents submitted to the arbitrator, through a telephonic hearing, or by an in-person hearing as established by the AAA Rules. If your claim exceeds $10,000, the right to a hearing will be determined by the AAA Rules. Regardless of the manner in which the arbitration is conducted, the arbitrator will issue a reasoned written decision sufficient to explain the essential findings and conclusions on which the award is based.
16.5. Costs of Arbitration. Payment of all filing, administration, and arbitrator fees (collectively, the “Arbitration Fees”) will be governed by the AAA Rules, unless otherwise provided in this Arbitration Agreement. To the extent any Arbitration Fees are not specifically allocated to either Anysphere or you under the AAA Rules, Anysphere and you shall split them equally; provided that if you are able to demonstrate to the arbitrator that you are economically unable to pay your portion of such Arbitration Fees or if the arbitrator otherwise determines for any reason that you should not be required to pay your portion of any Arbitration Fees, Anysphere will pay your portion of such fees. In addition, if you demonstrate to the arbitrator that the costs of arbitration will be prohibitive as compared to the costs of litigation, Anysphere will pay as much of the Arbitration Fees as the arbitrator deems necessary to prevent the arbitration from being cost-prohibitive. Any payment of attorneys’ fees will be governed by the AAA Rules.
16.6. Confidentiality. All aspects of the arbitration proceeding, and any ruling, decision, or award by the arbitrator, will be strictly confidential for the benefit of all parties.
16.7. Severability. If a court or the arbitrator decides that any term or provision of this Arbitration Agreement (other than the subsection above titled “Prohibition of Class and Representative Actions and Non-Individualized Relief”) is invalid or unenforceable, the parties agree to replace such term or provision with a term or provision that is valid and enforceable and that comes closest to expressing the intention of the invalid or unenforceable term or provision, and this Arbitration Agreement will be enforceable as so modified. If a court or the arbitrator decides that any of the provisions of the subsection above titled “Prohibition of Class and Representative Actions and Non-Individualized Relief” are invalid or unenforceable, then the entirety of this Arbitration Agreement will be null and void, unless such provisions are deemed to be invalid or unenforceable solely with respect to claims for public injunctive relief. The remainder of these Terms will continue to apply.
16.8. Future Changes to Arbitration Agreement. Notwithstanding any provision in these Terms to the contrary, Anysphere agrees that if it makes any future change to this Arbitration Agreement (other than a change to the Notice Address) while you are a user of the Service, you may reject any such change by sending Anysphere written notice within thirty (30) calendar days of the change to the Notice Address provided above. By rejecting any future change, you are agreeing that you will arbitrate any dispute between us in accordance with the language of this Arbitration Agreement as of the date you first accepted these Terms (or accepted any subsequent changes to these Terms).
16.3. Dispute Resolution. Anysphere is always interested in resolving disputes amicably and efficiently, and most customer concerns can be resolved quickly and to the customer’s satisfaction by emailing legal@cursor.com. In the event of a dispute, claim or controversy relating to this Agreement (“Dispute”), the Parties will first attempt in good faith to informally resolve the matter. The Party raising the Dispute must notify the other party (“Dispute Notice”), who will have thirty (30) days from the date of delivery of the Dispute Notice to propose a time for the Parties to meet to attempt to resolve the Dispute. If the Parties have not resolved the dispute within forty-five (45) days of delivery of the Dispute Notice, either Party may seek to resolve the dispute through litigation as stated in Section 16.1.
17. Miscellaneous
17.1. General. These Terms, including the Privacy Policy, and any other agreements expressly incorporated by reference into these Terms, are the entire and exclusive understanding and agreement between you and Anysphere regarding your use of the Service. You may not assign or transfer these Terms or your rights under these Terms, in whole or in part, by operation of law or otherwise, without our prior written consent. We may assign these Terms and all rights granted under these Terms, including with respect to your Content, at any time without notice or consent. The failure to require performance of any provision will not affect our right to require performance at any other time after that, nor will a waiver by us of any breach or default of these Terms, or any provision of these Terms, be a waiver of any subsequent breach or default or a waiver of the provision itself. If any part of these Terms is held to be invalid or unenforceable, then the unenforceable part will be given effect to the greatest extent possible, and the remaining parts will remain in full force and effect.
17.2. Governing Law. California law will govern these Terms except for its conflicts of laws principles. Except as provided in the Dispute Resolution section above, all claims arising out of or relating to these Terms will be brought exclusively in the federal or state courts of San Francisco, California.
17.2. Consent to Electronic Communications. By using the Service, you consent to receiving certain electronic communications from us as further described in our Privacy Policy. Please read our Privacy Policy to learn more about our electronic communications practices. You agree that any notices, agreements, disclosures, or other communications that we send to you electronically will satisfy any legal communication requirements, including that those communications be in writing.
17.3. Consent to Electronic Communications. By using the Service, you consent to receiving certain electronic communications from us as further described in our Privacy Policy. Please read our Privacy Policy to learn more about our electronic communications practices. You agree that any notices, agreements, disclosures, or other communications that we send to you electronically will satisfy any legal communication requirements, including that those communications be in writing.
17.3. Contact Information. You may contact us by sending correspondence to Anysphere, Inc., 2261 Market Street STE 86466, San Francisco, CA 94114, or by emailing us at hi@cursor.com.
17.4. Contact Information. You may contact us by sending correspondence to Anysphere, Inc., 2261 Market Street STE 86466, San Francisco, CA 94114, or by emailing us at hi@cursor.com.
17.4. No Support. We are under no obligation to provide support for the Service. In instances where we may offer support, the support will be subject to published policies.
17.5. No Support. We are under no obligation to provide support for the Service. In instances where we may offer support, the support will be subject to published policies.
17.6. Export and Trade Controls. You must comply with all applicable trade laws, including sanctions and export control laws. The Service may not be used in or for the benefit of, or exported or re-exported to (a) any U.S. embargoed country or territory or (b) any individual or entity with whom dealings are prohibited or restricted under applicable trade laws. Our Service may not be used for any end use prohibited by applicable trade laws, and your Input may not include material or information that requires a government license for release or export.
17.5. Export and Trade Controls. You must comply with all applicable trade laws, including sanctions and export control laws. The Service may not be used in or for the benefit of, or exported or re-exported to (a) any U.S. embargoed country or territory or (b) any individual or entity with whom dealings are prohibited or restricted under applicable trade laws. Our Service may not be used for any end use prohibited by applicable trade laws, and your Input may not include material or information that requires a government license for release or export.
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright Christopher Cooper
Copyright Arch Linux Contributors
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.
+1
View File
@@ -0,0 +1 @@
../LICENSE
@@ -0,0 +1,112 @@
Terms of Service
Last Updated: August 13, 2026
Welcome, and thank you for your interest in Anysphere, Inc. (“Anysphere,” “we,” or “us”), makers of the Cursor software platform. These Terms of Service (“Terms”) govern your access to and use of Anysphere's software, platform, APIs, Documentation, and related tools, including the website www.cursor.com, and all related software made available by Anysphere to build, deploy, host, and manage software projects (collectively, the “Service”). By using the Service, you agree to these Terms including our Acceptable Use Policy.
Please also read our Privacy Policy⁠, which explains how we collect, use, disclose, and process personal data.
Please also carefully read the sections below regarding Limitation of Liability and Dispute Resolution, which affect your rights.
If you are using the Service as part of your work for a company or organization that has a Master Services Agreement (“MSA”) with Anysphere, your use of the Service is governed by that MSA.
If you are entering into these Terms on behalf of an entity, you represent that you have the legal authority to bind that entity.
1. Access and Use
1.1. Provision of Access. Anysphere is an applied research company working on automating coding. The Service offers a suite of coding tools driven by machine learning to help developers write code more easily and efficiently and can provide suggested code, outputs or other functions. Subject to your compliance with these Terms, Anysphere grants you a limited right to access and use the Service.
1.2. Content. You may provide inputs to the Service (“Inputs”) and receive code, outputs, or other functions based on the Inputs provided by you (collectively, “Suggestions”) (Inputs and Suggestions are collectively “Content”). We may use Content to provide the Service, comply with applicable law, enforce our terms and policies, and keep the Service safe. By submitting Inputs to the Service, you represent and warrant that you have all rights, licenses, and permissions that are necessary for us to process the Inputs under these Terms and to provide the Service to you.
1.3. Model Training. ANYSPHERE WILL NOT USE CONTENT TO TRAIN, OR ALLOW ANY THIRD PARTY TO TRAIN, ANY AI MODELS, UNLESS YOU’VE EXPLICITLY AGREED TO THE USE OF CONTENT FOR TRAINING. You can find instructions in the Service for how to manage your preferences regarding the use of Inputs and Suggestions for training.
1.4. Limitations for Suggestions. You acknowledge that Suggestions are generated automatically by machine learning technology and may be similar to or the same as Suggestions provided to other customers, and no rights to any Suggestions generated, provided, or returned by the Service for or to other customers are granted to you under these Terms. Further, you acknowledge that there are numerous limitations that apply with respect to Suggestions provided by large language and other AI models (each an “AI Model”), including that (i) Suggestions may contain errors or misleading information, (ii) AI Models are based on predefined rules and algorithms that lack the ability to think creatively and come up with new ideas and can result in repetitive or formulaic content, (iii) AI Models can struggle with understanding the nuances of language, including slang, idioms, and cultural references, (iv) AI Models can struggle with complex tasks that require reasoning, judgment and decision-making, and (v) data used to train AI models may be of poor quality or biased. You agree that you are responsible for evaluating, and bearing all risks associated with, the use of any Suggestions, including any reliance on the accuracy, completeness, or usefulness of Suggestions.
1.5. Use Restrictions. Except and solely to the extent such a restriction is impermissible under applicable law, you may not: (i) reverse engineer, disassemble, decompile, decode, or otherwise attempt to derive or gain access to the source code, object code or underlying structure of the Service; (ii) reproduce, modify, translate, or create derivative works of the Service; (iii) rent, lease, lend, or sell the Service; (iv) remove any proprietary notices from the Service; (v) use the Service or any Suggestions to develop or train a model that is competitive with the Service, or engage in model extraction or theft attacks; (vi) probe, scan or attempt to penetrate the Service; (vii) provide to any third party the results of any benchmark tests of the Service, unless you include all necessary information for others to replicate the tests; (viii) harvest, scrape, or extract data from the Service; (ix) use the Service in any manner that infringes, misappropriates, or otherwise violates any third party’s intellectual or other rights, or that violates any applicable laws or regulations; (x) send or otherwise provide to Anysphere data or information that is subject to specific protections under applicable laws beyond any requirements that apply to "personal information" or "personal data" generally, such as for illustrative purposes, information that is regulated by the Health Insurance Portability and Accountability Act, the Payment Card Industry Data Security Standard, the Gramm-Leach-Bliley Act, and other U.S. federal, state or foreign laws applying specific security standards; or (xi) knowingly permit any third party to do any of the foregoing. You will promptly notify Anysphere of any unauthorized use that comes to your attention and provide reasonable cooperation to prevent and terminate such use to the extent it is within your control.
1.6. Beta Services. From time to time, Anysphere may make Beta Services available to you. Beta Services shall be clearly designated as beta, pilot, limited release, non-production, early access, evaluation or a similar description. You may choose to use or not use such Beta Services in your sole discretion. Beta Services are intended for evaluation purposes and not for production use, are not fully supported, and may be subject to additional terms that may be presented to you. Beta Services are provided on an "as-is" and "as available" basis without any warranty, support, maintenance, or storage of any kind. Anysphere may discontinue Beta Services at any time in its sole discretion and may never make them generally available. ANYSPHERE SHALL HAVE NO LIABILITY WHATSOEVER ARISING OUT OF OR IN CONNECTION WITH BETA SERVICES - USE AT YOUR OWN RISK.
1.7. Auto-Code Execution. The Service may include a feature that automatically executes code Suggestions without manual review or confirmation, and will be clearly labeled accordingly. By enabling this feature, you acknowledge and agree that you are assuming all risks associated with the execution of automatically generated code, including without limitation system outages, software defects, data loss, and security vulnerabilities. YOU ARE SOLELY RESPONSIBLE FOR ANY IMPACT RESULTING FROM USE OF THIS FEATURE, INCLUDING ENSURING APPROPRIATE SAFEGUARDS, TESTING, AND MONITORING ARE IN PLACE.
2. Eligibility. You must be at least the age of majority in your jurisdiction (e.g., 18 years old in the United States) or 18 years old, whichever is higher, to use the Service. By agreeing to these Terms, you represent and warrant to us that: (a) you are at least 18 years old or the age of majority in your jurisdiction, whichever is higher; (b) you have not previously been suspended or removed from the Service; and (c) your registration and use of the Service is in compliance with all applicable laws in your region.
3. Account Registration and Access. To access most features of the Service, you must register for an account. When you register for an account, you may be required to provide us with information about yourself, such as your name, email address, or other contact information. You agree that the information you provide to us is accurate, complete, and not misleading, and that you will keep it accurate and up to date at all times. When you register, you will be asked to create a password. You are solely responsible for maintaining the confidentiality of your account and password, and you accept responsibility for all activities that occur under your account. If you believe that your account is no longer secure, you must immediately notify us at hi@cursor.com.
4. Payment Terms
4.1. Paid Services. Certain features of the Service may require you to pay fees. Before you pay any fees, you will have an opportunity to review and accept the fees that you will be charged. Unless otherwise specifically provided for in these Terms, all fees are in U.S. Dollars and are non-refundable, except as required by law. The pricing and payment terms in this Section 4 are subject to any pricing and payment terms set forth in an Order Form.
4.2. Pricing. Anysphere reserves the right to determine pricing for the Service. Anysphere will make reasonable efforts to keep pricing information published on the Service up to date. We encourage you to check our pricing page periodically for current pricing information. Anysphere may change the fees for any feature of the Service, including additional fees or charges, if Anysphere gives you advance notice of changes before they apply through the Service user interface, a pop-up notice, email, or through other reasonable means. Your continued use of the Service after the price change becomes effective constitutes your agreement to pay the changed amount. You will be responsible for all taxes associated with the Service, other than taxes based on Anysphere’s net income. Anysphere, at its sole discretion, may make promotional offers with different features and different pricing to any of Anysphere’s customers. These promotional offers, unless made to you, will not apply to your offer or these Terms.
4.3. Payment Processing. To facilitate payment for the Service via bank account, credit card, or debit card, we use Stripe, Inc. and its affiliates (“Stripe”), a third-party payment processor. These payment processing services are provided by Stripe and are subject to the Stripe terms and conditions and other policies available at https://stripe.com/legal and Stripe’s Global Privacy Policy available at: https://stripe.com/privacy (collectively, the "Stripe Agreements"). By agreeing to these Terms, users that use the payment functions of the Service also agree to be bound by the Stripe Agreements, as the same may be modified by Stripe from time to time. You hereby authorize Stripe to store and continue billing your specified payment method even after such payment method has expired, to avoid interruptions in payment for your use of the Service. Please contact Stripe for more information. Anysphere assumes no liability or responsibility for any payments you make through the Service.
4.4. Subscription Service. The Service may include certain subscription-based plans with automatically recurring payments for periodic charges (“Subscription Service”). The “Subscription Billing Date” is the date when you purchase your first subscription to the Service. The Subscription Service will begin on the Subscription Billing Date and continue for the subscription period that you select on your account (such period, the “Initial Subscription Period”), and will automatically renew for successive periods of the same duration as the Initial Subscription Period (the Initial Subscription Period and each such renewal period, each a “Subscription Period”) unless you cancel the Subscription Service or we terminate it. If you activate a Subscription Service, then you authorize Anysphere or its third-party payment processors to periodically charge, on a going-forward basis and until cancellation of the Subscription Service, all accrued sums on or before the payment due date. Information on the recurring fee charged by Anysphere for access to the Subscription Service during each Subscription Period (“Subscription Fee”), is available on our Pricing Page, or otherwise described in the Service. Your account will be charged automatically on the Subscription Billing Date and thereafter on the renewal date of your Subscription Service for all applicable fees and taxes for the next Subscription Period. You must cancel your Subscription Service at least 24 hours before it renews in order to avoid billing of the next periodic Subscription Fee to your account. Anysphere or its third-party payment processor will bill the periodic Subscription Fee to the payment method associated with your account or that you otherwise provide to us. You may cancel the Subscription Service by using the cancellation functionality made available in your billing menu or by contacting us at hi@cursor.com. YOUR CANCELLATION MUST BE RECEIVED BEFORE THE RENEWAL DATE IN ORDER TO AVOID CHARGE FOR THE NEXT SUBSCRIPTION PERIOD.
4.5. Add-On and Usage-Based Features. You may purchase additional products, services or features that are not individually essential for the functioning of the Service, but that Anysphere makes available to its users for enhanced capabilities on a supplemental basis, including usage-based pricing features that are described in the Service ("Add-Ons"). Add-Ons are deemed part of the Service and governed by these Terms. Fees for Add-Ons include our model-based pricing features, available here, or as otherwise described in the Service.
4.6. Delinquent Accounts. Anysphere may suspend or terminate access to the Service, including fee-based portions of the Service, for any account for which any amount is due but unpaid. In addition to the amount due for the Service, a delinquent account will be charged with fees or charges that are incidental to any chargeback or collection of any unpaid amount, including collection fees. If your payment method is no longer valid at the time a renewal Subscription Fee is due, then Anysphere reserves the right to delete your account and any information associated with your account without any liability to you.
5. Ownership and Licenses
5.1. Service. Anysphere and its licensors shall own and retain all right, title and interest in and to the Service, all improvements, enhancements or modifications thereto, and all intellectual property rights associated with the foregoing. There are no implied licenses in these Terms and Anysphere reserves all rights to the Service not granted in these Terms.
5.2. Feedback. We appreciate the thoughts and comments from our users. If you choose to provide input and suggestions regarding existing functionalities, problems with or proposed modifications or improvements to the Service (“Feedback”), then you grant Anysphere the right to exploit the Feedback without restriction or compensation to you.
5.3. Content. You retain all of your right, title, and interest that you have in Inputs, and Anysphere hereby assigns to you all of our right, title, and interest if any in and to any Suggestions.
5.4. Usage Data. Anysphere may: (i) collect, analyze, and otherwise process Usage Data internally for its business purposes, including for security and analytics, to enhance the Service, and for other development and corrective purposes; and (ii) disclose Usage Data to third parties only in an aggregated and/or de-identified form and in a manner that does not identify you. “Usage Data” means technical logs, data, and learnings about Customer’s use of and interactions with the Service, but excludes Content.
6. Third-Party Services. The Service may include or incorporate optional third-party services, including without limitation extensions and plug-ins that you may install yourself (“Third-Party Services”). Anysphere will clearly indicate such content or features as Third-Party Services via prominent notices or descriptions in the Service. If you elect, in your sole discretion, to access or use a Third-Party Service, your access and use of the Third-Party Service is subject to the terms provided by that Third-Party Service, and you remain responsible for complying with those terms. Anysphere does not make any representations or warranties with respect to Third-Party Services.
7. Communications. We may send you emails concerning our products and services, as well as those of third parties. You may opt out of promotional emails by using any unsubscribe or similar functionality or instructions in the promotional email.
8. Modification of Terms. We may, from time to time, change these Terms. Please check these Terms periodically for changes. If we make any material modifications, we will notify you by updating the date at the top of these Terms and by maintaining a current version of these Terms on this page. All modifications will be effective when they are posted, and your continued accessing or use of the Service will serve as confirmation of your acceptance of those modifications. If you do not agree to the modified Terms, then you must discontinue your use of the Service.
9. Termination. You may stop accessing the Services at any time. We reserve the right to modify, suspend, or discontinue the Services or your access to the Services, in whole or in part, at any time without notice to you. Although we will strive to provide you with reasonable advance notice if we stop offering a Service, there may be urgent situations, such as preventing abuse or addressing security issues or responding to legal requirements, where providing advance notice is not feasible. We will not be liable for any change to or any suspension or discontinuation of the Services or your access to them. If you have a Subscription Service, we may terminate the Subscription Service at any time for any other reason. If we exercise this right, we will refund you on a pro rata basis the fees you paid for the remaining portion of your Subscription Service after termination, provided that if we terminate your access to the Service due to a violation of these Terms, you will not be entitled to any refund. We also may terminate your account if it has been inactive for over a year and you do not have a paid account. If we do, we will provide you with advance notice. Upon termination of these Terms, a Subscription Service, or your access to the Service, we may at our option delete any Content or other data associated with your account. Sections 1.5, 4 (with respect to fees outstanding as of such expiration or termination), 5, and 13-17 will survive any expiration or termination of our Terms or a Subscription Service. If you believe we have suspended or terminated your account in error, you can file an appeal with us by contacting hi@cursor.com.
10. Modification of the Service. Anysphere may modify or discontinue all or any portion of the Service at any time (including by limiting or discontinuing certain features of the Service), temporarily or permanently, without notice to you. Anysphere will have no liability for any change to the Service, including any paid-for functionalities of the Service, or any suspension or termination of your access to or use of the Service. You should retain copies of any Content as needed so that you have access in the event the Service is modified and you lose access to such Content.
11. Copyright complaints. If you believe that your intellectual property rights have been infringed, please send notice to legal@cursor.com. We may delete or disable content that we believe violates these Terms or is alleged to be infringing and will terminate accounts of repeat infringers where appropriate. Written claims concerning copyright infringement must include the following information:
A physical or electronic signature of the person authorized to act on behalf of the owner of the copyright interest.
A description of the copyrighted work that you claim has been infringed upon.
A description of where the allegedly infringing material is located in the Service so we can find it.
Your address, telephone number, and e-mail address.
A statement by you that you have a good-faith belief that the disputed use is not authorized by the copyright owner, its agent, or the law.
A statement by you that the above information in your notice is accurate and, under penalty of perjury, that you are the copyright owner or authorized to act on the copyright owner’s behalf.
12. Privacy. Please read the Anysphere Privacy Policy (“Privacy Policy”) carefully for information relating to our collection, use, storage, and disclosure of your personal data.
13. Indemnity. To the fullest extent permitted by law, you are responsible for your use of the Service, and you will defend and indemnify Anysphere, its affiliates and each of their respective shareholders, directors, managers, members, officers, employees, consultants, and agents (together, the “Anysphere Entities”) from and against any and all liabilities, claims, damages, expenses (including reasonable attorneys’ fees), and other losses arising out of or relating to: (1) your unauthorized use of, or misuse of, the Service; (2) your violation of any portion of these Terms, any representation, warranty, or agreement referenced in these Terms, or any applicable law or regulation; and (3) any claim that your Input violates any third-party intellectual property, publicity, confidentiality, privacy, or other rights. We reserve the right, at our own expense, to assume the exclusive defense and control of any matter otherwise subject to indemnification by you (without limiting your indemnification obligations with respect to that matter), and in that case, you agree to cooperate with our defense of those claims.
14. DISCLAIMER OF WARRANTIES. THE SERVICE AND SUGGESTIONS ARE PROVIDED “AS IS” AND ON AN “AS AVAILABLE” BASIS. ANYSPHERE DISCLAIMS ALL WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, RELATING TO THE SERVICE AND SUGGESTIONS, INCLUDING: (a) ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, QUIET ENJOYMENT, OR NON-INFRINGEMENT; AND (b) ANY WARRANTY ARISING OUT OF COURSE OF DEALING, USAGE, OR TRADE. ANYSPHERE DOES NOT WARRANT THAT THE SERVICE OR SUGGESTIONS WILL BE UNINTERRUPTED, SECURE, OR FREE OF ERRORS, VIRUSES, OR OTHER HARMFUL COMPONENTS, AND ANYSPHERE DOES NOT WARRANT THAT ANY OF THOSE ISSUES WILL BE CORRECTED. YOU AGREE THAT ANY USE OF SUGGESTIONS FROM OUR SERVICE IS AT YOUR SOLE RISK AND YOU WILL NOT RELY ON ANY SUGGESTION AS A SOURCE OF TRUTH. THE LAWS OF SOME JURISDICTIONS DO NOT ALLOW THE DISCLAIMER OF IMPLIED WARRANTIES, SO SOME OR ALL OF THESE DISCLAIMERS MAY NOT APPLY TO YOU.
15. LIMITATION OF LIABILITY
15.1. NO INDIRECT DAMAGES. TO THE FULLEST EXTENT PERMITTED BY LAW, IN NO EVENT WILL THE ANYSPHERE ENTITIES BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES (INCLUDING DAMAGES FOR LOSS OF PROFITS, GOODWILL, OR ANY OTHER INTANGIBLE LOSS) ARISING OUT OF OR RELATING TO THESE TERMS, THE SERVICE, OR CONTENT, WHETHER BASED ON WARRANTY, CONTRACT, TORT (INCLUDING NEGLIGENCE), STATUTE, OR ANY OTHER LEGAL THEORY, AND WHETHER OR NOT ANY ANYSPHERE ENTITY HAS BEEN INFORMED OF THE POSSIBILITY OF DAMAGE.
15.2. LIABILITY CAP. TO THE FULLEST EXTENT PERMITTED BY LAW, THE AGGREGATE LIABILITY OF THE ANYSPHERE ENTITIES TO YOU FOR ALL CLAIMS, DAMAGES AND LOSSES ARISING OUT OF OR RELATING TO THESE TERMS, THE SERVICE, AND CONTENT, WHETHER IN CONTRACT, TORT, OR OTHERWISE, IS LIMITED TO THE GREATER OF: (A) THE AMOUNT YOU HAVE PAID TO ANYSPHERE FOR ACCESS TO AND USE OF THE SERVICE IN THE SIX (6) MONTHS PRIOR TO THE EVENT OR CIRCUMSTANCE GIVING RISE TO THE CLAIM OR, IF GREATER, (B) $100. THE FOREGOING LIMITATIONS ARE ESSENTIAL TO THESE TERMS, AND WE WOULD NOT OFFER THE SERVICE TO YOU UNDER THESE TERMS WITHOUT THESE LIMITATIONS. THE LIMITATIONS IN THIS SECTION WILL APPLY EVEN IF ANY LIMITED REMEDY FAILS OF ITS ESSENTIAL PURPOSE.
15.3. Limitations Period. You and Anysphere agree that you must initiate any proceeding or action asserting a federal claim within one (1) year of the date of the occurrence of the event or facts giving rise to a dispute that is arising out of or related to these Terms or the Service, or if such limitation period is unenforceable under applicable law, then the shortest limitation period permitted by applicable law. You and Anysphere agree that you must initiate any proceeding or action asserting a state law claim within two (2) years of the date of the occurrence of the event or facts giving rise to a dispute that is arising out of or related to these Terms or the Service. Otherwise, to the extent permitted by applicable law, you forever waive the right to pursue any claim or cause of action, of any kind or character, based on such events or facts, and such claims or causes of action are permanently barred.
16. DISPUTE RESOLUTION
PLEASE READ THIS SECTION CAREFULLY AS IT AFFECTS YOUR RIGHTS.
16.1. Governing Law, Forum Selection, Jurisdiction, and Venue. Unless prohibited by your country’s applicable law, the laws of the State of Texas, excluding its choice of law provisions, will govern these Terms and any dispute that arises between you and Anysphere, notwithstanding any other agreement between you and us to the contrary. Notwithstanding any other agreement to the contrary, unless prohibited by your country’s applicable law, all disputes related to these Terms, the Service, or any patents – including without limitation disputes related to or arising from any Content (whether your or others' Content), or your or others' use of the Service or the complete or partial termination thereof – shall be brought and must proceed exclusively in the federal or state courts located in Wichita County or Tarrant County, Texas, United States, and you and Anysphere consent to personal jurisdiction in those forums and waive any objection as to inconvenient forum. For the avoidance of doubt, the choice of law and forum selection provisions of this paragraph shall apply regardless of whether a dispute or any claims contained therein are based in contract, tort, statute, common law, or otherwise, and the choice of law and forum selection provisions of this paragraph shall apply to pending and future disputes and shall apply to your dispute regardless of when the conduct relating to the dispute arose or occurred. The choice of law and forum selection provisions of this paragraph shall also extend to disputes involving our U.S. corporate affiliates, who consent to and are intended third-party beneficiaries of this paragraph.
16.2. Prohibition of Class and Representative Actions and Non-Individualized Relief. YOU AND ANYSPHERE AGREE THAT EACH OF US MAY BRING CLAIMS AGAINST THE OTHER ONLY ON AN INDIVIDUAL BASIS AND NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY PURPORTED CLASS OR REPRESENTATIVE ACTION OR PROCEEDING. UNLESS BOTH YOU AND ANYSPHERE AGREE OTHERWISE, YOU AND ANYSPHERE AGREE NOT TO SEEK TO CONSOLIDATE OR JOIN MORE THAN ONE PERSON’S OR PARTY’S CLAIMS AND NOT TO OTHERWISE SEEK ANY FORM OF A CONSOLIDATED, REPRESENTATIVE, OR CLASS PROCEEDING. ALSO, YOU AND ANYSPHERE AGREE TO SEEK RELIEF (INCLUDING MONETARY, INJUNCTIVE, AND DECLARATORY RELIEF) ONLY IN FAVOR OF THE INDIVIDUAL PARTY SEEKING RELIEF AND ONLY TO THE EXTENT NECESSARY TO PROVIDE RELIEF NECESSITATED BY THAT PARTY’S INDIVIDUAL CLAIM(S), EXCEPT THAT YOU AND ANYSPHERE MAY PURSUE A CLAIM FOR PUBLIC INJUNCTIVE RELIEF UNDER APPLICABLE LAW TO THE EXTENT REQUIRED FOR THE ENFORCEABILITY OF THIS PROVISION.
16.3. Dispute Resolution. Anysphere is always interested in resolving disputes amicably and efficiently, and most customer concerns can be resolved quickly and to the customer’s satisfaction by emailing legal@cursor.com. In the event of a dispute, claim or controversy relating to this Agreement (“Dispute”), the Parties will first attempt in good faith to informally resolve the matter. The Party raising the Dispute must notify the other party (“Dispute Notice”), who will have thirty (30) days from the date of delivery of the Dispute Notice to propose a time for the Parties to meet to attempt to resolve the Dispute. If the Parties have not resolved the dispute within forty-five (45) days of delivery of the Dispute Notice, either Party may seek to resolve the dispute through litigation as stated in Section 16.1.
17. Miscellaneous
17.1. General. These Terms, including the Privacy Policy, and any other agreements expressly incorporated by reference into these Terms, are the entire and exclusive understanding and agreement between you and Anysphere regarding your use of the Service. You may not assign or transfer these Terms or your rights under these Terms, in whole or in part, by operation of law or otherwise, without our prior written consent. We may assign these Terms and all rights granted under these Terms, including with respect to your Content, at any time without notice or consent. The failure to require performance of any provision will not affect our right to require performance at any other time after that, nor will a waiver by us of any breach or default of these Terms, or any provision of these Terms, be a waiver of any subsequent breach or default or a waiver of the provision itself. If any part of these Terms is held to be invalid or unenforceable, then the unenforceable part will be given effect to the greatest extent possible, and the remaining parts will remain in full force and effect.
17.2. Consent to Electronic Communications. By using the Service, you consent to receiving certain electronic communications from us as further described in our Privacy Policy. Please read our Privacy Policy to learn more about our electronic communications practices. You agree that any notices, agreements, disclosures, or other communications that we send to you electronically will satisfy any legal communication requirements, including that those communications be in writing.
17.3. Contact Information. You may contact us by sending correspondence to Anysphere, Inc., 2261 Market Street STE 86466, San Francisco, CA 94114, or by emailing us at hi@cursor.com.
17.4. No Support. We are under no obligation to provide support for the Service. In instances where we may offer support, the support will be subject to published policies.
17.5. Export and Trade Controls. You must comply with all applicable trade laws, including sanctions and export control laws. The Service may not be used in or for the benefit of, or exported or re-exported to (a) any U.S. embargoed country or territory or (b) any individual or entity with whom dealings are prohibited or restricted under applicable trade laws. Our Service may not be used for any end use prohibited by applicable trade laws, and your Input may not include material or information that requires a government license for release or export.
+31 -26
View File
@@ -1,46 +1,51 @@
# Maintainer: Christopher Cooper <christopher@cg505.com>
# Maintainer: Ismet Togay <ismet.togay at gmail dot com>
# Contributor: Christopher Cooper <christopher@cg505.com>
pkgname=cursor-cli
# extracted from https://cursor.com/install (managed by 'update-pkgver.sh')
_upstream_ver='2026.07.23-e383d2b'
# Baseline pkgver; update using './update-pkgver.sh'
pkgver=2026.07.23.1.e383d2b
pkgver=2026.08.11.1.e8db854
# Upstream is YYYY.MM.DD-<hash>. pkgver cannot contain hyphens, and hashes are
# not monotonically ordered, so pkgver is YYYY.MM.DD.<n>.<hash>: n resets to 1
# on a new date and increments when the same date gets a new hash.
# Derive the upstream version (YYYY.MM.DD-<hash>) from that pkgver.
_upstream_ver="${pkgver%.*}"
_upstream_ver="${_upstream_ver%.*}-${pkgver##*.}"
pkgrel=1
# epoch=1: bumped when switching from the original `20250808.0.<sha>` scheme
# to the current `YYYY.MM.DD.<n>.<hash>` scheme (2025-08-09). Never decrease.
epoch=1
pkgdesc="Cursor Agent CLI - AI-powered code assistant"
pkgdesc="CLI tool for Cursor, the AI-first coding agent"
arch=('x86_64' 'aarch64')
url="https://cursor.com"
license=('LicenseRef-Cursor')
depends=('gcc-libs' 'bash' 'glibc' 'nodejs' 'ripgrep')
depends=('gcc-libs' 'git' 'zlib')
options=('!strip')
install=cursor-cli.install
source=('Cursor-TOS')
source=('Cursor-TOS'
'auto-update-block.patch')
source_x86_64=("cursor-cli-${_upstream_ver}-x86_64.tar.gz::https://downloads.cursor.com/lab/${_upstream_ver}/linux/x64/agent-cli-package.tar.gz")
source_aarch64=("cursor-cli-${_upstream_ver}-aarch64.tar.gz::https://downloads.cursor.com/lab/${_upstream_ver}/linux/arm64/agent-cli-package.tar.gz")
b2sums=('7079c023e03ea4d78b067ed0f22b5cc1982c306721b2ea6be3c7f73bbbe0e8f05b148fd6571902b838464ee80a787ef7be73135c622f0a4fdb16c38429ced8d6')
b2sums_x86_64=('98df7f3d41efd1178a114aef6beeeb00dfc8b33a592e9b699c4eaa6df530f9b85d37fecd818c175d7b1aa6f7543c35dc3d42c8899087ba0d211bcf747333316d')
b2sums_aarch64=('71f0df95054f168a324f7bd57ae9850504f8bd0293e0620cf193de8729ef97a127f90e7e60ceb83e5908883cb412a448cc3e1600aeba3fe060bc0afded4e7853')
b2sums=('d241ee9895bdb1c17514438fde8528222a8f2326568bd7a033d7a1b11432ce6b4575ff1a50625764bfe6bc6f8a9dc060f7439c3be7e95f8fd02912cdd37a011d'
'1928e04c713e13911ea607f84c3e4a2fed1f76af9795503811078f43d2b53c753e28b2233e553fc17e766831800fb0dbc272aad2a80b387f95ba6071d7d4116a')
b2sums_x86_64=('4787401fbdf14e72e5f98cce70db932cdc6cc6030d3b5531adce715f95e1ddc5dfce029e0def8da06d676bbe9c5cc9ed94f49270fe107a0e4b17274716f9dead')
b2sums_aarch64=('c499a9a75d46c6289d9c9011a72eef70964872aca9f7660406e566e11d188a87d194cfe2133a97a3a461d547b94dd4f2280b4ad9e8a1990ddcaddc78d7897ddc')
prepare() {
# Block cursor-agent auto-updates by making its versions directory
# non-searchable (chmod -x; see auto-update-block.patch).
patch -Np1 -d "${srcdir}/dist-package" -i "${srcdir}/auto-update-block.patch"
}
package() {
# Create necessary directories
install -dm755 "${pkgdir}/opt/cursor-agent"
install -dm755 "${pkgdir}/usr/bin"
# Copy all files from the extracted package
# Copy all files from the extracted package (including upstream's
# bundled node and rg runtimes).
cp -r "${srcdir}"/dist-package/* "${pkgdir}/opt/cursor-agent/"
# Replace node and rg with system versions
ln -sf "/usr/bin/node" "${pkgdir}/opt/cursor-agent/node"
ln -sf "/usr/bin/rg" "${pkgdir}/opt/cursor-agent/rg"
# Patch cursor-agent script to block auto-updates
sed -i '/^NODE_BIN=/a\
# Block cursor-agent auto-updates\
mkdir -p "${XDG_DATA_HOME:-$HOME/.local/share}/cursor-agent/versions"\
chmod -x "${XDG_DATA_HOME:-$HOME/.local/share}/cursor-agent/versions"' "${pkgdir}/opt/cursor-agent/cursor-agent"
# Create symlink in /usr/bin
ln -s "/opt/cursor-agent/cursor-agent" "${pkgdir}/usr/bin/cursor-agent"
# Install license
# This is downloaded from https://cursor.com/terms-of-service
install -Dm644 Cursor-TOS "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
# Install license
# This is downloaded from https://cursor.com/terms-of-service
install -Dm644 Cursor-TOS "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}
+26
View File
@@ -0,0 +1,26 @@
version = 1
# Package source files written by the maintainer.
[[annotations]]
path = [
"PKGBUILD",
".SRCINFO",
"update-pkgver.sh",
"cursor-cli.install",
"LICENSE",
"REUSE.toml",
"auto-update-block.patch",
"nvchecker.toml",
".gitignore",
]
SPDX-FileCopyrightText = [
"2026 Ismet Togay <ismet.togay at gmail dot com>",
"2025-2026 Christopher Cooper <christopher@cg505.com>",
]
SPDX-License-Identifier = "0BSD"
# Upstream Cursor Terms of Service, redistributed as the installed license.
[[annotations]]
path = "Cursor-TOS"
SPDX-FileCopyrightText = "Anysphere, Inc."
SPDX-License-Identifier = "LicenseRef-Cursor"
@@ -0,0 +1,11 @@
--- a/cursor-agent
+++ b/cursor-agent
@@ -8,6 +8,8 @@
SCRIPT_DIR="$(dirname "$(readlink "$0" || echo "$0")")"
fi
NODE_BIN="$SCRIPT_DIR/node"
+# Block cursor-agent auto-updates
+[[ -n "${HOME:-}" ]] && mkdir -p "$HOME/.local/share/cursor-agent/versions" && chmod -x "$HOME/.local/share/cursor-agent/versions" || true
# Enable Node.js compile cache for faster CLI startup (requires Node.js >= 22.1.0)
# Cache is automatically invalidated when source files change
+12 -5
View File
@@ -1,12 +1,19 @@
# shellcheck shell=bash
post_install() {
post_upgrade "$@"
}
post_upgrade() {
cat << 'EOF'
==> The AUR package will now block cursor-agent automatic updates.
Clean up old auto-update files from previous installations:
==> cursor-agent updates are managed by your package manager.
==> If a previous install allowed the CLI to self-update,
clean up the leftover files:
rm ~/.local/bin/cursor-agent
chmod +x ~/.local/share/cursor-agent/versions/
rm -r ~/.local/share/cursor-agent/versions/
rm -f ~/.local/bin/cursor-agent
chmod +x ~/.local/share/cursor-agent/versions/ 2>/dev/null
rm -rf ~/.local/share/cursor-agent/versions/
EOF
}
+7
View File
@@ -0,0 +1,7 @@
# Detect new cursor-agent CLI releases.
# Run: nvchecker -c nvchecker.toml
# After a bump is detected, run ./update-pkgver.sh to apply it.
[cursor-cli]
source = "regex"
url = "https://cursor.com/install"
regex = 'downloads\.cursor\.com/lab/(\d{4}\.\d{2}\.\d{2}-[A-Za-z0-9]+)'
+53 -7
View File
@@ -3,6 +3,7 @@ set -euo pipefail
PKGBUILD_PATH="${1:-PKGBUILD}"
[[ ! -f "${PKGBUILD_PATH}" ]] && { echo "Error: PKGBUILD file not found at '${PKGBUILD_PATH}'" >&2; exit 1; }
PKGBUILD_DIR="$(cd "$(dirname "${PKGBUILD_PATH}")" && pwd)"
CURRENT_PKGVER="$(sed -nE "s/^pkgver=['\"]?([^'\"#]+).*/\1/p" "${PKGBUILD_PATH}" | head -n1)"
UPSTREAM_VER_NEW="$(curl -fsSL "https://cursor.com/install" | grep -Eo 'downloads\.cursor\.com/lab/([0-9]{4}\.[0-9]{2}\.[0-9]{2}-[A-Za-z0-9]+)' | head -n1 | sed -E 's@.*lab/([^/]+).*@\1@')"
@@ -12,13 +13,10 @@ UPSTREAM_VER_NEW="$(curl -fsSL "https://cursor.com/install" | grep -Eo 'download
# Parse upstream version: YYYY.MM.DD-<id>
[[ "${UPSTREAM_VER_NEW}" =~ ^([0-9]{4}\.[0-9]{2}\.[0-9]{2})[.-](.+)$ ]] || { echo "Error: upstream version '${UPSTREAM_VER_NEW}' does not start with YYYY.MM.DD" >&2; exit 1; }
release_date_dotted="${BASH_REMATCH[1]}"
rest="${BASH_REMATCH[2]}"
new_hash="${rest##*.}"
new_hash="${new_hash//-/.}"
new_hash="${BASH_REMATCH[2]}"
# Expect current pkgver in the form: YYYY.MM.DD.DATE_VER.HASH
[[ "${CURRENT_PKGVER}" =~ ^([0-9]{4}\.[0-9]{2}\.[0-9]{2})\.([0-9]+)\.([A-Za-z0-9\.]+)$ ]] || { echo "Error: current pkgver='${CURRENT_PKGVER}' invalid; expected YYYY.MM.DD.DATE_VER.HASH" >&2; exit 1; }
[[ "${CURRENT_PKGVER}" =~ ^([0-9]{4}\.[0-9]{2}\.[0-9]{2})\.([0-9]+)\.([A-Za-z0-9]+)$ ]] || { echo "Error: current pkgver='${CURRENT_PKGVER}' invalid; expected YYYY.MM.DD.DATE_VER.HASH" >&2; exit 1; }
prev_date="${BASH_REMATCH[1]}"
prev_date_ver="${BASH_REMATCH[2]}"
prev_hash="${BASH_REMATCH[3]}"
@@ -31,8 +29,56 @@ fi
NEW_PKGVER="${release_date_dotted}.${new_date_ver}.${new_hash}"
sed -i -E "s/^_upstream_ver=.*/_upstream_ver='${UPSTREAM_VER_NEW}'/" "${PKGBUILD_PATH}"
if [[ "${NEW_PKGVER}" == "${CURRENT_PKGVER}" ]]; then
echo "${NEW_PKGVER}"
exit 0
fi
if ! command -v updpkgsums >/dev/null 2>&1; then
echo "Error: updpkgsums not found; cannot refresh b2sums." >&2
exit 1
fi
if ! command -v makepkg >/dev/null 2>&1; then
echo "Error: makepkg not found; cannot regenerate .SRCINFO." >&2
exit 1
fi
PKGBUILD_BACKUP="$(mktemp)"
SRCINFO_BACKUP=""
cp "${PKGBUILD_PATH}" "${PKGBUILD_BACKUP}"
if [[ -f "${PKGBUILD_DIR}/.SRCINFO" ]]; then
SRCINFO_BACKUP="$(mktemp)"
cp "${PKGBUILD_DIR}/.SRCINFO" "${SRCINFO_BACKUP}"
fi
restore() {
cp "${PKGBUILD_BACKUP}" "${PKGBUILD_PATH}"
if [[ -n "${SRCINFO_BACKUP}" ]]; then
cp "${SRCINFO_BACKUP}" "${PKGBUILD_DIR}/.SRCINFO"
fi
rm -f "${PKGBUILD_BACKUP}"
[[ -n "${SRCINFO_BACKUP}" ]] && rm -f "${SRCINFO_BACKUP}"
}
sed -i -E "s/^pkgver=.*/pkgver=${NEW_PKGVER}/" "${PKGBUILD_PATH}"
[[ "${NEW_PKGVER}" != "${CURRENT_PKGVER}" ]] && sed -i -E "s/^pkgrel=.*/pkgrel=1/" "${PKGBUILD_PATH}"
sed -i -E "s/^pkgrel=.*/pkgrel=1/" "${PKGBUILD_PATH}"
if ! (cd "${PKGBUILD_DIR}" && updpkgsums); then
echo "Error: updpkgsums failed; PKGBUILD restored." >&2
restore
exit 1
fi
SRCINFO_TMP="$(mktemp)"
if ! (cd "${PKGBUILD_DIR}" && makepkg --printsrcinfo > "${SRCINFO_TMP}"); then
echo "Error: makepkg --printsrcinfo failed; files restored." >&2
rm -f "${SRCINFO_TMP}"
restore
exit 1
fi
mv "${SRCINFO_TMP}" "${PKGBUILD_DIR}/.SRCINFO"
rm -f "${PKGBUILD_BACKUP}"
[[ -n "${SRCINFO_BACKUP}" ]] && rm -f "${SRCINFO_BACKUP}"
echo "${NEW_PKGVER}"
+8 -9
View File
@@ -1,11 +1,11 @@
# Maintainer: David Heinemeier Hansson <david@hey.com>
pkgname=herdr
pkgver=0.8.0.r13
pkgver=0.8.2
pkgrel=1
pkgdesc="Herdr terminal workspace manager built from the Omarchy fork"
pkgdesc="Herdr terminal workspace manager for AI coding agents"
arch=('x86_64' 'aarch64')
url="https://github.com/omacom-io/herdr"
url="https://github.com/herdrdev/herdr"
license=('Apache-2.0')
depends=('gcc-libs' 'glibc')
makedepends=('cargo')
@@ -13,23 +13,22 @@ replaces=('omarchy-herdr')
conflicts=('omarchy-herdr')
options=('!debug' '!lto')
_commit=0766aa57ee0ceb4410ae064e94c0f0557853eee7
_zigver=0.15.2
source=("herdr-$_commit.tar.gz::$url/archive/$_commit.tar.gz")
source=("herdr-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz")
source_x86_64=("zig-x86_64-linux-$_zigver.tar.xz::https://ziglang.org/download/$_zigver/zig-x86_64-linux-$_zigver.tar.xz")
source_aarch64=("zig-aarch64-linux-$_zigver.tar.xz::https://ziglang.org/download/$_zigver/zig-aarch64-linux-$_zigver.tar.xz")
sha256sums=('61d33624fd3af77ccf695d20c3c31689a44f8c2dc3855edd405eec7bc1af0318')
sha256sums=('60453051025ee44ebf055d26cdaf665a0accd99a992cddd22c166a26c49cd161')
sha256sums_x86_64=('02aa270f183da276e5b5920b1dac44a63f1a49e55050ebde3aecc9eb82f93239')
sha256sums_aarch64=('958ed7d1e00d0ea76590d27666efbf7a932281b3d7ba0c6b01b0ff26498f667f')
prepare() {
cd "herdr-$_commit"
cd "herdr-$pkgver"
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
}
build() {
cd "herdr-$_commit"
cd "herdr-$pkgver"
export CARGO_TARGET_DIR=target
export ZIG="$srcdir/zig-$CARCH-linux-$_zigver/zig"
@@ -38,7 +37,7 @@ build() {
}
package() {
cd "herdr-$_commit"
cd "herdr-$pkgver"
install -Dm755 target/release/herdr "$pkgdir/usr/bin/herdr"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
@@ -1,4 +0,0 @@
{
"source": "aur",
"upstream_commit": "f13b5cb28f56989648651b4fe0cf6e0b0f431495"
}
-12
View File
@@ -1,12 +0,0 @@
Copyright Arch Linux Contributors
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-29
View File
@@ -1,29 +0,0 @@
# Maintainer: Norbert Preining <norbert@preining.info>
pkgname=intel-lpmd
pkgver=0.1.0
pkgrel=2
pkgdesc="Intel Low Power Mode Daemon"
arch=('x86_64')
url="https://github.com/intel/$pkgname"
license=('GPL-2.0-or-later')
makedepends=('git' 'automake' 'autoconf-archive' 'gtk-doc' 'glib2-devel' 'systemd')
depends=('libxml2-legacy' 'libnl' 'systemd-libs' 'polkit' 'upower')
source=(git+${url}.git#tag=v${pkgver})
sha256sums=('23f4c8588cc057c327c6b031c377b03193d62554f3b5a68284582f4e5a35c462')
prepare() {
cd "$pkgname"
./autogen.sh prefix=/usr sysconfdir=/etc sbindir=/usr/bin
}
build() {
cd "$pkgname"
make
}
package() {
cd "$pkgname"
DESTDIR="$pkgdir" make install
install -Dm 644 -t "${pkgdir}/usr/share/doc/${pkgname}" "$srcdir/${pkgname}"/README.md
install -Dm 644 -t "${pkgdir}/usr/share/doc/${pkgname}" "$srcdir/${pkgname}"/doc/WLT_proxy.md
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "32b7c658ecb718dfd44f3d3deea785bcc5034de7"
"upstream_commit": "7e0b6692a655426df8b205e19d44bd455e87bf6c"
}
+65 -21
View File
@@ -1,6 +1,11 @@
# Maintainer:
# Contributor: Patrick Northon <northon_patrick3@yahoo.ca>
: ${CARGO_HOME:=$SRCDEST/cargo-home}
: ${CARGO_TARGET_DIR:=target}
: ${RUSTUP_TOOLCHAIN:=stable}
export CARGO_HOME CARGO_TARGET_DIR RUSTUP_TOOLCHAIN
: ${_use_sodeps:=false}
: ${_install_path:=usr/lib}
@@ -8,7 +13,7 @@
_pkgname="localsend"
pkgname="$_pkgname"
pkgver=1.18.1
pkgrel=1
pkgrel=2
pkgdesc="An open source cross-platform alternative to AirDrop"
url="https://github.com/localsend/localsend"
license=('Apache-2.0')
@@ -27,6 +32,7 @@ depends=(
'pango'
)
makedepends=(
'cargo'
'clang'
'cmake'
'fvm'
@@ -35,7 +41,6 @@ makedepends=(
'llvm'
'ninja'
'patchelf'
'rustup'
)
options=('!lto')
@@ -45,31 +50,67 @@ _pkgext="tar.gz"
source=("$_pkgsrc.$_pkgext"::"$url/archive/refs/tags/v$pkgver.$_pkgext")
sha256sums=('555a73c39e2cfc01ee8cf0033ae11610725829d8289aa9c4794446241d9de2b0')
prepare() {
sed -E 's&^(channel) = .*$&\1 = "stable"&' -i "$_pkgsrc/packages/localsend_isolates/rust-toolchain.toml"
}
_rust_setup() {
if [ -n "$_arch" ]; then
return
fi
# bypass Cargokit rustup requirement to use system toolchain
if ! pacman -Qs rustup &> /dev/null; then
install -Dm755 /dev/stdin fakebin/rustup << END
#!/usr/bin/env true
END
fi
if [ -e "$srcdir/fakebin" ]; then
export PATH="$srcdir/fakebin:$PATH"
fi
_arch="x64"
if [[ "${CARCH::1}" == "a" ]]; then
_arch="arm64"
fi
build() (
local _units=$(($(nproc) > 16 ? $(nproc) : 16))
export CARGO_PROFILE_RELEASE_LTO=false
export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=$_units
}
prepare() {
_rust_setup
cd "$_pkgsrc"
cargo fetch --locked --target host-tuple
}
build() {
_rust_setup
export FVM_CACHE_PATH="$SRCDEST/fvm-cache"
export CXXFLAGS+=' -Wno-error=deprecated-declarations'
cd "$_pkgsrc/app"
cd "$_pkgsrc"
cargo build --frozen --release --all-features
# copy isolate for flutter to find
local _isolates="app/build/linux/$_arch/release/plugins/rust_lib_localsend_app"
mkdir -p "$_isolates"
cp "$srcdir/$_pkgsrc/$CARGO_TARGET_DIR/release/librust_lib_localsend_app.so" "$_isolates/"
cd "app"
fvm install
fvm flutter --disable-analytics
#fvm flutter pub upgrade --major-versions
fvm flutter --no-version-check pub get
fvm flutter build linux --no-pub --release
)
}
package() {
_rust_setup
if [[ "${_use_sodeps::1}" == "t" ]]; then
eval "depends=(
eval "depends+=(
libatk-1.0.so
libcairo.so
libepoxy.so
@@ -85,28 +126,31 @@ package() {
)"
fi
local _arch="x64"
if [[ "${CARCH::1}" == "a" ]]; then
_arch="arm64"
fi
# cli, server
install -Dm755 "$_pkgsrc/$CARGO_TARGET_DIR/release"/{localsend-cli,server} -t "$pkgdir/$_install_path/$_pkgname/"
# app, lib, data
cd "$_pkgsrc/app/build/linux/$_arch/release/bundle"
# files
install -Dm755 "localsend_app" "$pkgdir/$_install_path/$_pkgname/$_pkgname"
install -Dm755 "localsend_app" -t "$pkgdir/$_install_path/$_pkgname"
cp -r lib/ "$pkgdir/$_install_path/$_pkgname/"
cp -r data/ "$pkgdir/$_install_path/$_pkgname/"
# runpath
patchelf --set-rpath '$ORIGIN/lib' "$pkgdir/$_install_path/$_pkgname/$_pkgname"
for i in "$pkgdir/$_install_path/$_pkgname"/*; do
if [ -f "$i" ] && readelf -h "$i" &> /dev/null; then
patchelf --set-rpath '$ORIGIN/lib' "$i"
fi
done
for i in "$pkgdir/$_install_path/$_pkgname/lib"/*.so; do
[ -z "$(patchelf --print-rpath "$i")" ] && continue
patchelf --set-rpath '$ORIGIN' "$i"
if [ -f "$i" ] && readelf -h "$i" &> /dev/null; then
patchelf --set-rpath '$ORIGIN' "$i"
fi
done
# symlink
mkdir -pm755 "${pkgdir}/usr/bin"
ln -sfr "$pkgdir/$_install_path/$_pkgname/$_pkgname" "$pkgdir/usr/bin/${_pkgname}"
ln -sfr "$pkgdir/$_install_path/$_pkgname/${_pkgname}_app" "$pkgdir/usr/bin/${_pkgname}"
ln -sfr "$pkgdir/$_install_path/$_pkgname/${_pkgname}-cli" "$pkgdir/usr/bin/${_pkgname}-cli"
# icon
install -Dm644 "$srcdir/$_pkgsrc/app/build/flutter_assets/assets/img/logo-512.png" "$pkgdir/usr/share/icons/hicolor/512x512/apps/$_pkgname.png"
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Tobi Lütke <tobi@lutke.com>
pkgname=omasnap
pkgver=1.12.0
pkgver=1.15.0
pkgrel=1
pkgdesc="Native Wayland screenshot and annotation overlay for Hyprland"
arch=('x86_64')
@@ -26,7 +26,7 @@ makedepends=(
options=('!debug')
source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('cf09929e104fe29783ec93157120972e751481daed6dcd7272875c109b7f7312')
sha256sums=('3a87d475c4a12462ace139bb881882c342bc51da4c74b6606ff8cc21e74f6592')
build() {
cmake -S "$pkgname-$pkgver" -B build -G Ninja \
+3 -3
View File
@@ -1,7 +1,7 @@
# Maintainer: David Heinemeier Hansson <david@hey.com>
pkgname=omatrack
pkgver=0.9.11
pkgver=1.2.0
pkgrel=1
pkgdesc="Cross-format motorsport telemetry analysis workstation"
arch=('x86_64' 'aarch64')
@@ -11,9 +11,9 @@ depends=('qt6-base' 'qt6-declarative' 'mpv' 'libyaml' 'gcc-libs' 'glibc' 'hicolo
makedepends=('cmake' 'ninja' 'rust')
options=('!debug' '!lto')
_commit=122c59f3911289c7ae4b11ecb0d5992699b08d75
_commit=ebe7f4f6b05845a85a2b713f889e676442fd0e82
source=("omatrack-$_commit.tar.gz::$url/archive/$_commit.tar.gz")
sha256sums=('3a2d457cb7c85d62147d98f2896e2b157a20f40f88b5496ae56b236b3337209a')
sha256sums=('8e6c62de5f8c98239a84abe9696c83f1155bef12004ee2c028bd99d64b8263a4')
prepare() {
cd "omatrack-$_commit/third_party/motorsport-telemetry"
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "64f60e2276e88adb066b48a18b663455e5f9024d"
"upstream_commit": "86b771a4294509f86e62ac7802fec7715090f283"
}
+5 -5
View File
@@ -2,7 +2,7 @@
# shellcheck disable=SC2034
# Maintainer: Chmouel Boudjnah <chmouel@chmouel.com>
pkgname=openai-codex-bin
pkgver=0.147.0
pkgver=0.148.0
pkgrel=1
pkgdesc="Arch Linux package for OpenAI's Codex CLI - Auto Updated"
arch=('x86_64' 'aarch64')
@@ -21,10 +21,10 @@ source_x86_64=(
"codex-${pkgver}-x86_64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-x86_64-unknown-linux-musl.tar.gz"
"codex-code-mode-host-${pkgver}-x86_64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-code-mode-host-x86_64-unknown-linux-musl.tar.gz"
)
sha256sums_x86_64=('0246e2e773834e07f0fb5249ed6ebad12e4591e608f8c7bb97dd6a9690544c36'
'0146adfaac8363ec9fcdb5895f7624db5b2e8617a283887938b7fb97a1dd4356')
sha256sums_aarch64=('eb677c80f666b1ab8b4b1d083b66e8d614b1281d960bb6f9fd8ca98f58b38b90'
'dfd4ff98ea4db30ed078af9c31b6f86e3da4836d0573aa87e225e5a5b54d3c7c')
sha256sums_x86_64=('1a36f762f6b3bef533bb86345ad9517661c2d84d53996a250cf2ca89d2cfee5a'
'8e6e559b228fa61b18fb2c28c31ec02068751025bcce3f00cf63c79499d59829')
sha256sums_aarch64=('410c6ae0c763eb39c6da17665e63f9aa4a98e6ee663d81f8e8b779c97cb175ac'
'1c410fe4bb174949649efe05c150b1512fb4775d5874eb54b2edb624cf7513a4')
source_aarch64=(
"codex-${pkgver}-aarch64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-aarch64-unknown-linux-musl.tar.gz"
+3 -3
View File
@@ -5,7 +5,7 @@
# the version and checksums below from that repository's package index.
pkgname=openai-codex-desktop
pkgver=26.810.52044
pkgver=26.814.41957
pkgrel=1
pkgdesc="Official ChatGPT desktop app with Codex"
arch=('x86_64' 'aarch64')
@@ -71,8 +71,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}")
source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}")
noextract=("${_deb_x86_64}" "${_deb_aarch64}")
sha256sums=('b3a4503b5931f102444bc7015c3cf4e40266cf034e0d682bd2a407dc5b3ee58c')
sha256sums_x86_64=('708a15a1bb76e2bb7f0e376e5145391fa277ad3a64057c1d32537bdc2a1b4e6e')
sha256sums_aarch64=('6ebea681b1e494d218a199f638b4bc886e94e1458dd61079b1e390a6fb98fdd2')
sha256sums_x86_64=('4778b26a7abd08647214d5b05c17bd3ebe2d9688d146dabf017c1a2faf93ac7d')
sha256sums_aarch64=('8c40b31419dd4f4a8eb292d40dc3f8a418807dfe8c0101ae7164fa4ee415f818')
package() {
cd "${srcdir}"
-4
View File
@@ -1,4 +0,0 @@
["pinta"]
source = "github"
github = "PintaProject/Pinta"
use_latest_release = true
-4
View File
@@ -1,4 +0,0 @@
{
"source": "aur",
"upstream_commit": "595911f15b61a8fba991ea039852877e9bd63d1a"
}
-52
View File
@@ -1,52 +0,0 @@
# Maintainer: Rafael Baboni Dominiquini <rafaeldominiquini at gmail dot com>
pkgname=pinta
pkgver=3.1.2
pkgrel=1
pkgdesc="Drawing/editing program modeled after Paint.NET. It's goal is to provide a simplified alternative to GIMP for casual users"
arch=('x86_64')
license=('MIT')
url="https://pinta-project.com"
makedepends=('pkgconf' 'autoconf-archive' 'intltool' 'dotnet-sdk' 'dotnet-runtime' 'dotnet-host' 'dotnet-targeting-pack' 'gtk4' 'perl')
depends=('dotnet-runtime' 'dotnet-host' 'libadwaita' 'hicolor-icon-theme' 'webp-pixbuf-loader')
provides=($pkgname)
conflicts=($pkgname-git)
source=("Pinta-${pkgver}.tar.gz::https://github.com/PintaProject/Pinta/archive/refs/tags/${pkgver}.tar.gz")
sha256sums=('98ed517b33f0e40fd1e3915ea5146355845ac12efd3bb07812c68a52c714cac6')
prepare() {
cd "${srcdir}/Pinta-${pkgver}"
for file in *.md *.txt; do
basename=$(tr '[:lower:]' '[:upper:]' <<< "${file%.*}")
newname="$basename.${file#*.}"
[ ! "$file" == "$newname" ] && mv "$file" "$newname"
done
sed -i 's/net8.0/net10.0/g' Directory.Build.props
./autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var
}
build() {
cd "${srcdir}/Pinta-${pkgver}"
sed -i -r 's|^(PINTA_BUILD_OPTS\s=\s.*)|\1 -p:RuntimeIdentifier=linux-x64|g' Makefile
make
}
package() {
cd "${srcdir}/Pinta-${pkgver}"
make DESTDIR="${pkgdir}" install
chmod -v 755 "${pkgdir}/usr/lib/pinta/"*.dll
install -Dm644 -t "${pkgdir}/usr/share/doc/${pkgname}/" *.md
install -Dm644 -t "${pkgdir}/usr/share/licenses/${pkgname}/" LICENSE*.txt
}
+11 -1
View File
@@ -1,5 +1,15 @@
{
"source": "aur",
"upstream_commit": "2494139bce7b7fc71372da00b68fb745a2c72d90",
"sync": false
"sync": false,
"rebuild_on": [
"qt6-base",
"qt6-declarative",
"qt6-wayland"
],
"rebuilt_against": {
"qt6-base": "6.11.2-2",
"qt6-declarative": "6.11.2-1",
"qt6-wayland": "6.11.2-1"
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
_pkgname=quickshell
pkgname="$_pkgname-git"
pkgver=0.3.0.r20.g28771c7
pkgrel=1
pkgrel=2
pkgdesc='Flexible toolkit for making desktop shells with QtQuick'
arch=(x86_64 aarch64)
url='https://git.outfoxxed.me/quickshell/quickshell'
+1 -1
View File
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "9de27473a4cb916eed0e78c986102145987c75f3"
"upstream_commit": "d23c94c48b7cfe778a820a6b329413f173d31b6a"
}
+5 -5
View File
@@ -6,9 +6,9 @@
# Contributor: Eothred <yngve.levinsen@gmail.com>
pkgname=spotify
pkgver='1.2.95.453'
pkgver='1.2.96.518'
epoch=1
_commit=g0eeebbed
_commit=g366879e1
pkgrel=1
pkgdesc='A proprietary music streaming service'
arch=('x86_64')
@@ -34,13 +34,13 @@ source=("${pkgname}-${pkgver}-${_commit}-x86_64.deb::http://repository.spotify.c
"${pkgname}-${pkgver}-${pkgrel}-Release::http://repository.spotify.com/dists/testing/Release"
"${pkgname}-${pkgver}-${pkgrel}-Release.sig::http://repository.spotify.com/dists/testing/Release.gpg"
"${pkgname}-${pkgver}-${pkgrel}-x86_64-Packages::http://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages")
sha512sums=('902d9b8200d67e10a19ce5e34316ea14ed05e935fe5493c21f7a8db31b2ffc91375dd18a68734e781b815d57ac9e3aff36da79bce9ff6882a1f247542caab451'
sha512sums=('98d25bd748258ca8b8357313cd35c7188bb0b26ed2d4390b0208473aa9fa3491a095559762f8ba06ec0828d73e05ee8fb488f0f357340191da4c65dd1f93c519'
'da48b628a4ea925dd8521133ebf364b261b11aed252d264dde6605d915cdb631919ffe672c58534bcdb60869e5d87a49a60a8198780b99517123f0031e83fdb1'
'999abe46766a4101e27477f5c9f69394a4bb5c097e2e048ec2c6cb93dfa1743eb436bde3768af6ba1b90eaac78ea8589d82e621f9cbe7d9ab3f41acee6e8ca20'
'2e16f7c7b09e9ecefaa11ab38eb7a792c62ae6f33d95ab1ff46d68995316324d8c5287b0d9ce142d1cf15158e61f594e930260abb8155467af8bc25779960615'
'b1a317c49c32ca63be65a85a92f486ecbb39ffc402c8c459f6c6542261584f740da318d1311fb71832e68a56754d547805de0cffb19dde6a79c4a14c1914aee6'
'18f27971697835df865d63465d86d1250b20b9d1c12bbf7df1eafeef5c66bf0b3134c25b08269f72d4b7a4287151336ee3fd0f70bc46da25f13e8c91c004f710'
'SKIP'
'bd52856fb7531af4f7782fdd3b1d047e99dc00b02223035022f70112d2ecf9c80d7c2bf816eb78aeced8de577a9975fab5042c8e8ce4ca689ce3dbc46a9e4703')
'1fbb6f1f104b998265faafeb62cb3aff6d7048b2e689292049fbbe867ea4071af3b73fc5a023bff8d4c1e579e5d904c78179e3650ae4740602583db8e13bde8a')
# Import key with:
# curl -sS https://download.spotify.com/debian/pubkey_5384CE82BA52C83A.gpg | gpg --import -
@@ -0,0 +1,4 @@
{
"source": "local",
"release_ring": "fast"
}
+38
View File
@@ -0,0 +1,38 @@
#!/bin/bash
# T3 Code publishes electron-builder's update feed beside every release, so the
# newest version costs one small request. The feed's checksum is a base64
# SHA-512 and makepkg wants hex SHA-256, so a release that is actually new still
# has to be downloaded once to hash -- hence the version check before the fetch.
set -euo pipefail
FEED_URL="https://github.com/pingdotgg/t3code/releases/latest/download/latest-linux.yml"
RELEASE_URL="https://github.com/pingdotgg/t3code/releases/download"
feed=$(curl -fsSL "$FEED_URL")
version=$(awk '/^version:/ { print $2; exit }' <<<"$feed" | tr -d '"'\''')
asset=$(awk '/^path:/ { print $2; exit }' <<<"$feed" | tr -d '"'\''')
if [[ -z "$version" || -z "$asset" ]]; then
echo "Upstream feed carried no version or asset name" >&2
exit 1
fi
current=$(awk -F= '/^pkgver=/ { print $2; exit }' PKGBUILD)
if [[ -n "$current" ]] && [[ "$(vercmp "$version" "$current")" -le 0 ]]; then
echo '{}'
exit 0
fi
# The PKGBUILD builds one fixed asset name, so a feed naming anything else --
# a rename, or an arm64 build reaching the Linux feed first -- has to stop the
# sync rather than pin that file's checksum to a URL nobody will fetch.
expected="T3-Code-${version}-x86_64.AppImage"
if [[ "$asset" != "$expected" ]]; then
echo "Upstream feed names $asset, but the PKGBUILD builds $expected" >&2
exit 1
fi
sha256=$(curl -fsSL "$RELEASE_URL/v${version}/${asset}" | sha256sum | cut -d' ' -f1)
jq -n --arg pkgver "$version" --arg sha256 "$sha256" \
'{pkgver: $pkgver, sha256sums: {x86_64: [$sha256]}}'
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 T3 Tools 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.
+115
View File
@@ -0,0 +1,115 @@
# Maintainer: David Heinemeier Hansson <david@hey.com>
# T3 Code ships Linux as an AppImage and nothing else, so Omarchy unpacks it and
# keeps only the Electron tree. AppRun, the compatibility libraries bundled for
# distributions that do not ship their own, and the AppImage's icon shims are all
# dead weight here. .omarchy/upstream.sh rewrites the version and checksum below
# from the release feed the app updates itself from.
pkgname=t3code-bin
pkgver=0.0.33
pkgrel=2
pkgdesc="Open-source control plane for coding agents"
arch=('x86_64')
url="https://t3.codes"
license=('MIT')
depends=(
'alsa-lib'
'at-spi2-core'
'cairo'
'dbus'
'expat'
'gcc-libs'
'glib2'
'glibc'
'gtk3'
'hicolor-icon-theme'
'libcups'
'libnotify'
'libx11'
'libxcb'
'libxcomposite'
'libxdamage'
'libxext'
'libxfixes'
'libxkbcommon'
'libxrandr'
'mesa'
'nspr'
'nss'
'pango'
'systemd-libs'
'xdg-utils'
)
optdepends=(
'claude-code: drive Claude Code from the app'
'cursor-cli: drive Cursor from the app'
'github-copilot-cli: drive Copilot from the app'
'openai-codex: drive Codex from the app'
)
provides=("t3code=${pkgver}")
conflicts=('t3code')
options=('!debug' '!strip')
_appimage="T3-Code-${pkgver}-x86_64.AppImage"
source=('t3code-launcher.sh' 'LICENSE')
source_x86_64=("${_appimage}::https://github.com/pingdotgg/t3code/releases/download/v${pkgver}/${_appimage}")
noextract=("${_appimage}")
sha256sums=('cb905ff341372ef2ef6e402cf485959f8bd1df8f0efebee4cda1afdd5e6abc0a'
'935d8f2af0c703f9c39517ee57cc4930b19d02d533be930b63f0e82f93614b43')
sha256sums_x86_64=('415c8648f43c3d22d572f27f2c50fdc8c310ea7fcde9537b903e1e2f1c8775a1')
prepare() {
chmod +x "${srcdir}/${_appimage}"
rm -rf "${srcdir}/squashfs-root"
"${srcdir}/${_appimage}" --appimage-extract >/dev/null
}
package() {
cd "${srcdir}/squashfs-root"
# The AppImage's usr/ tree is compatibility libraries for distributions that
# lack them, and Arch is not one; its icons are the only part worth keeping.
# A release that starts shipping something else there stops the build rather
# than having it deleted quietly on the way past.
local unexpected
unexpected=$(find usr \( -type f -o -type l \) | grep -vE \
'^usr/share/icons/hicolor/[0-9]+x[0-9]+/apps/t3code\.png$|^usr/lib/lib(Xss\.so\.1|Xtst\.so\.6|appindicator\.so\.1|gconf-2\.so\.4|indicator\.so\.7|notify\.so\.4)$' || true)
if [[ -n "${unexpected}" ]]; then
echo "Unexpected files in the AppImage's usr/ tree:" >&2
echo "${unexpected}" >&2
return 1
fi
local icon size
for icon in usr/share/icons/hicolor/*/apps/t3code.png; do
size="${icon#usr/share/icons/hicolor/}"
install -Dm644 "${icon}" "${pkgdir}/usr/share/icons/hicolor/${size%%/*}/apps/t3code.png"
done
# Upstream's own entry rather than a hand-written one: it carries the
# t3code:// scheme handlers that make the app's deep links resolve.
# The name drops the "(Alpha)" upstream's electron-builder still appends; the
# app itself now calls that string legacy and keeps its data under t3code.
sed -e 's|^Exec=.*|Exec=t3code %U|' -e 's|^Name=.*|Name=T3 Code|' \
-e '/^X-AppImage-Version=/d' t3code.desktop \
> "${srcdir}/t3code.desktop.arch"
install -Dm644 "${srcdir}/t3code.desktop.arch" \
"${pkgdir}/usr/share/applications/t3code.desktop"
rm -rf AppRun .DirIcon usr t3code.desktop t3code.png
install -d "${pkgdir}/usr/lib/t3code"
cp -a . "${pkgdir}/usr/lib/t3code/"
chmod -R a+rX "${pkgdir}/usr/lib/t3code"
# 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.
chmod 4755 "${pkgdir}/usr/lib/t3code/chrome-sandbox"
install -Dm755 "${srcdir}/t3code-launcher.sh" "${pkgdir}/usr/bin/t3code"
install -Dm644 "${srcdir}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}
+31
View File
@@ -0,0 +1,31 @@
#!/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/t3code-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.
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 /usr/lib/t3code/t3code "${platform_flags[@]}" "${user_flags[@]}" "$@"
+1
View File
@@ -0,0 +1 @@
irgendwr <aur@iwr.sh>
+1 -1
View File
@@ -1,4 +1,4 @@
{
"source": "aur",
"upstream_commit": "5f816c48dc2108bdb8f6eed50a2955ed8fab2750"
"upstream_commit": "029ff738d5928db82edfa34fc365fcb6743a74e5"
}
+4 -4
View File
@@ -1,8 +1,8 @@
# Maintainer: Jonas Bögle <aur@iwr.sh>
# Maintainer: irgendwr <aur@iwr.sh>
# Contributor: Jonathan Duck <duckbrain30@gmail.com>
pkgname=typora
pkgver=1.13.6
pkgver=1.14.9
_pkgver_x86_64="$pkgver"
_pkgver_aarch64="$pkgver"
pkgrel=1
@@ -19,8 +19,8 @@ _urlbase="https://download.typora.io/linux/typora_"
source_x86_64=("${_urlbase}${_pkgver_x86_64}_amd64.deb")
source_aarch64=("${_urlbase}${_pkgver_aarch64}_arm64.deb")
sha512sums=('de9c883c63f3ea35bd551c8761e605f8e1a3468943e000abcbf94bb0c5cbb5f0f6c7fa4d49ab39c177f167e0e3d0b061c861bf828627b4a34f7f1589119c3d04')
sha512sums_x86_64=('a4b92a800731dee9186bcb3ddacbc2c3c99b66c4bec3c905dc80f945eb8900cf88bc0169077bca4660f2d4ea27562099e31093f0782ad1a849b9f4ebbf4de162')
sha512sums_aarch64=('b10a85fcbdfe89a0e2fc260d06005b60e298fc8f5513e60575d685ef8a679e73d3d90776f17dac03e0a716a05e0ae06bfa69af39a35f19aec910289db4bdfbe7')
sha512sums_x86_64=('075db5be472077b4c8f898b2995a6d47c2b932482a1536badf417db4bdc51edfef50083a18e2f2b9eda741c90fad2b1796e92f2826ec9ab03d543931916237c4')
sha512sums_aarch64=('4471a428eeb839d34bd096d84db6a235a05122da53b1a9ac01147d5efc893f1fd78240f4fcee053ed1d766292069801e33d4043aac3396e2e8837943e97bfa1d')
package() {
# unpack archive
@@ -1,4 +0,0 @@
{
"source": "aur",
"upstream_commit": "2448d265d1fefaf0fef2293c67aa00e471308e59"
}
@@ -1,55 +0,0 @@
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -8,48 +8,18 @@
url="https://github.com/Open-Wine-Components/umu-launcher"
license=('GPL-3.0-only')
depends=(
- # steam
bash
- desktop-file-utils
- diffutils
- hicolor-icon-theme
curl
dbus
- freetype2
- gdk-pixbuf2
- ttf-font
- zenity
- lsb-release
- nss
- usbutils
- xorg-xrandr
- vulkan-driver
- vulkan-icd-loader
- lsof
- python
- xdg-user-dirs
+ diffutils
glibc
- libxcrypt
- libxcrypt-compat
gcc-libs
- # umu
+ libxcrypt
+ lsof
+ python
python-xlib
python-filelock
)
-depends_x86_64=(
- lib32-glibc
- lib32-libxcrypt
- lib32-libxcrypt-compat
- lib32-libgl
- lib32-gcc-libs
- lib32-libx11
- lib32-libxss
- lib32-alsa-plugins
- lib32-libgpg-error
- lib32-nss
- lib32-vulkan-driver
- lib32-vulkan-icd-loader
-)
makedepends=(
git
scdoc
-51
View File
@@ -1,51 +0,0 @@
# Maintainer: loathingkernel <loathingkernel _a_ gmail _d_ com>
pkgname=umu-launcher
pkgver=1.1.3
pkgrel=1.1
pkgdesc="This is the Unified Launcher for Windows Games on Linux, to run Proton with fixes outside of Steam"
arch=('x86_64')
url="https://github.com/Open-Wine-Components/umu-launcher"
license=('GPL-3.0-only')
depends=(
bash
curl
dbus
diffutils
glibc
gcc-libs
libxcrypt
lsof
python
python-xlib
python-filelock
)
makedepends=(
git
scdoc
python-build
python-installer
python-hatchling
)
install=
_origin="https://github.com/Open-Wine-Components/umu-launcher.git"
source=(
"git+$_origin#tag=$pkgver"
)
prepare() {
cd "$srcdir"/umu-launcher
}
build() {
cd "$srcdir"/umu-launcher
./configure.sh --prefix=/usr
make
}
package() {
cd "$srcdir"/umu-launcher
make DESTDIR="$pkgdir" install
}
sha256sums=('14561329686b0fe4b9950841c50bf67b9419384dc25b0449064cece467a03209')
@@ -1,5 +1,5 @@
{
"source": "aur",
"release_ring": "fast",
"upstream_commit": "204b2f0626ca1e810c5e496872b12f049340c25c"
"upstream_commit": "1adf351fb67309a7fbe3311cef3a77cb697e1f2b"
}
+4 -4
View File
@@ -2,7 +2,7 @@
pkgname=visual-studio-code-bin
_pkgname=visual-studio-code
pkgver=1.133.0
pkgver=1.134.0
pkgrel=1
pkgdesc="Visual Studio Code (vscode): Editor for building and debugging modern web and cloud applications (official binary version)"
arch=('x86_64' 'aarch64' 'armv7h')
@@ -27,9 +27,9 @@ source_x86_64=(code_${pkgver}_amd64.deb::https://update.code.visualstudio.com/${
source_aarch64=(code_${pkgver}_arm64.deb::https://update.code.visualstudio.com/${pkgver}/linux-deb-arm64/stable)
source_armv7h=(code_${pkgver}_armhf.deb::https://update.code.visualstudio.com/${pkgver}/linux-deb-armhf/stable)
sha256sums=('bd0d9edf69283ebdf4e73e0a7b168d2fcf50acbd01f63674cad93ed4fe42fdad')
sha256sums_x86_64=('d064e87e22f556b8a91e1354b5227e340597324e52886dbb288551596b00e34a')
sha256sums_aarch64=('b20bfb21c5b3656e3411391c5c18df1782aedd7cd3bda0b9c08363ea261fca4b')
sha256sums_armv7h=('f68acc6874f59d829779d82e259cfb339ca168b5707f406cfc262353e5d34e45')
sha256sums_x86_64=('dcd3a2f52d53df079cd389662ff1fdbeb629938331d3a63655fed929f8d49f19')
sha256sums_aarch64=('b30f5bda4855231681cc7fe22d4a59e7dbee2be170b0e4fb04c7e83b9f9affe5')
sha256sums_armv7h=('01460717d4f4c7b3109cc06b8df5ba579e98ea373751cc0ed4ae7928f26fad89')
package() {
bsdtar -xf data.tar.xz -C "${pkgdir}/"