diff --git a/pkgbuilds/t3code-bin/.omarchy/package.json b/pkgbuilds/t3code-bin/.omarchy/package.json new file mode 100644 index 0000000..db153c3 --- /dev/null +++ b/pkgbuilds/t3code-bin/.omarchy/package.json @@ -0,0 +1,4 @@ +{ + "source": "local", + "release_ring": "fast" +} diff --git a/pkgbuilds/t3code-bin/.omarchy/upstream.sh b/pkgbuilds/t3code-bin/.omarchy/upstream.sh new file mode 100755 index 0000000..6bc010c --- /dev/null +++ b/pkgbuilds/t3code-bin/.omarchy/upstream.sh @@ -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]}}' diff --git a/pkgbuilds/t3code-bin/LICENSE b/pkgbuilds/t3code-bin/LICENSE new file mode 100644 index 0000000..55ee675 --- /dev/null +++ b/pkgbuilds/t3code-bin/LICENSE @@ -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. diff --git a/pkgbuilds/t3code-bin/PKGBUILD b/pkgbuilds/t3code-bin/PKGBUILD new file mode 100644 index 0000000..dbcc903 --- /dev/null +++ b/pkgbuilds/t3code-bin/PKGBUILD @@ -0,0 +1,112 @@ +# Maintainer: David Heinemeier Hansson + +# 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=1 +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. + sed -e 's|^Exec=.*|Exec=t3code %U|' -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" +} diff --git a/pkgbuilds/t3code-bin/t3code-launcher.sh b/pkgbuilds/t3code-bin/t3code-launcher.sh new file mode 100644 index 0000000..2157d1c --- /dev/null +++ b/pkgbuilds/t3code-bin/t3code-launcher.sh @@ -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[@]}" "$@"