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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ jobs:
with:
persist-credentials: false

- name: Test Hermes installation and launch
run: python3 test/hermes-desktop-test.py

# An Arch container for vercmp: version ordering has to be decided by
# the same comparator pacman uses on users' machines.
- name: Run self-tests
Expand Down
102 changes: 75 additions & 27 deletions pkgbuilds/hermes-desktop/PKGBUILD
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# Maintainer: David Heinemeier Hansson <david@hey.com>

# Build a prebuilt release; Omarchy seeds it into the user's Hermes checkout
# so the upstream updater can rebuild and relaunch it in place.

pkgname=hermes-desktop
pkgver=2026.8.31
pkgrel=1
pkgdesc='Installer and launcher for the self-updating Hermes desktop'
pkgrel=2
pkgdesc='Native desktop shell for Hermes Agent'
arch=('x86_64')
url='https://github.com/NousResearch/hermes-agent'
license=('MIT')

# Hermes builds its desktop under the user's runtime so both the app and CLI
# can update it. The compiler and Electron libraries must survive installation.
depends=(
'alsa-lib'
'at-spi2-core'
'bash'
'cairo'
'curl'
'dbus'
'expat'
'curl'
'gcc'
'gdk-pixbuf2'
'git'
Expand Down Expand Up @@ -48,39 +48,74 @@ depends=(
'python'
'systemd-libs'
'util-linux'
'xdg-terminal-exec'
'xdg-utils'
)

optdepends=('omarchy: sets up the user installation for in-app updates')

# The build runs the repo's own npm workspace install, which fetches Electron
# and rebuilds node-pty against it.
makedepends=('imagemagick')

# Snapshot the bootstrap installer, including upstream's Linux sandbox fixes.
# Only installation uses it; updates belong to the native runtime on main.
_commit=245e48008fa814b3251f50755eb656bd9fb86cb1
source=("install-${_commit}.sh::https://raw.githubusercontent.com/NousResearch/hermes-agent/${_commit}/scripts/install.sh"
"LICENSE-${_commit}::https://raw.githubusercontent.com/NousResearch/hermes-agent/${_commit}/LICENSE"
# Electron bundles prebuilt binaries that stripping corrupts.
options=('!strip' '!debug')

# The tag's commit. apps/desktop/scripts/write-build-stamp.mjs pins the app's
# first-launch bootstrap to a Hermes commit, and resolves it from $GITHUB_SHA
# before falling back to `git rev-parse`. That fallback is wrong here: makepkg
# builds inside this repository, so git ascends out of srcdir and stamps the
# app with an omarchy-pkgs commit that means nothing upstream.
_commit=29112bef099274229cadff79cdff7bf7b99c4b77

_srcdir="hermes-agent-${pkgver}"
source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz"
'hermes-desktop.sh'
'hermes-desktop.desktop'
'hermes-desktop.png')
sha256sums=('5854b15670b51a8daae8f59ddfa917062de9f74be261eb73b4b8d719710f8968'
'821556e6336796450ab852d375117b48a4887e71d255794fd6318d99982a5ab6'
'27040084e691421dc1748e7646ae7ee79d5777e8ee1e1ec7581a68432d4a29c4'
'c37d4cfa4801eccbd769fddaebb2115d54faa49a5b7bc0f305f563e3cefd9bd8'
'd60d164e24fdcf6532133b8ea43c77a201e4b9e9dbc396187b58d51d8590ef52')
'hermes-desktop.png'
'runtime.patch'
'runtime-test.py')
sha256sums=('78fb3ff707ec1d17044b875ecac8bef28aa39d44242824f6871ca40afe7bf217'
'7324b1d5e7db16c6169dd9e685f4093925c4a8c0568cb7ce416ac734f3336606'
'3ef685bfcf366776b025d26c37d32854d8d4aa2023b2bd07c8e08b001ef1e8c4'
'd60d164e24fdcf6532133b8ea43c77a201e4b9e9dbc396187b58d51d8590ef52'
'03b67e26c234c797a6b1d4c9f34a57502dba37f462540e47ce6c88f6ea79302a'
'69bc57d04610567eca35679328668619fcd3f129ed099bf5e2a1f24d1f197de9')

build() {
cd "${srcdir}/${_srcdir}"

export GITHUB_SHA="${_commit}"
export GITHUB_REF_NAME="main"

# The desktop workspace resolves against the repo root, so the install has to
# happen there rather than in apps/desktop.
npm ci

cd apps/desktop
npm run pack
}

check() {
python "${srcdir}/runtime-test.py" "${srcdir}/${_srcdir}" "${srcdir}/runtime.patch" "${srcdir}/hermes-desktop.sh"
}

package() {
install -Dm644 "${srcdir}/install-${_commit}.sh" \
"${pkgdir}/usr/share/${pkgname}/install.sh"
install -Dm644 "${srcdir}/LICENSE-${_commit}" \
"${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
cd "${srcdir}/${_srcdir}/apps/desktop/release/linux-unpacked"

install -dm755 "${pkgdir}/opt/${pkgname}"
cp -a . "${pkgdir}/opt/${pkgname}/"

install -Dm755 "${srcdir}/hermes-desktop.sh" "${pkgdir}/usr/bin/${pkgname}"

# Native registration uses hermes.desktop but omits URI handling. Keep the
# original handler ID hidden, and let the native entry replace the visible one.
install -Dm644 "${srcdir}/${_srcdir}/scripts/install.sh" \
"${pkgdir}/usr/share/${pkgname}/install.sh"
# Let the release's first updater relaunch with the user-namespace sandbox.
install -Dm644 "${srcdir}/runtime.patch" "${pkgdir}/usr/share/${pkgname}/runtime.patch"


install -Dm644 "${srcdir}/hermes-desktop.desktop" \
"${pkgdir}/usr/share/applications/hermes-desktop.desktop"
printf 'NoDisplay=true\n' >>"${pkgdir}/usr/share/applications/hermes-desktop.desktop"
sed '/^MimeType=/d' "${srcdir}/hermes-desktop.desktop" >"${pkgdir}/usr/share/applications/hermes.desktop"
"${pkgdir}/usr/share/applications/${pkgname}.desktop"

install -Dm644 "${srcdir}/hermes-desktop.png" \
"${pkgdir}/usr/share/icons/hicolor/1024x1024/apps/${pkgname}.png"
local size
Expand All @@ -89,4 +124,17 @@ package() {
install -Dm644 "${srcdir}/icon-${size}.png" \
"${pkgdir}/usr/share/icons/hicolor/${size}x${size}/apps/${pkgname}.png"
done

install -Dm644 "${srcdir}/${_srcdir}/LICENSE" \
"${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
install -Dm644 "${pkgdir}/opt/${pkgname}/LICENSE.electron.txt" \
"${pkgdir}/usr/share/licenses/${pkgname}/LICENSE.electron.txt"

# Chromium's setuid sandbox is only needed where unprivileged user namespaces
# are unavailable; where they work, setuid root is the worse of the two.
if ! { [[ -L /proc/self/ns/user ]] && unshare --user true; }; then
chmod 4755 "${pkgdir}/opt/${pkgname}/chrome-sandbox"
else
chmod 0755 "${pkgdir}/opt/${pkgname}/chrome-sandbox"
fi
}
2 changes: 1 addition & 1 deletion pkgbuilds/hermes-desktop/hermes-desktop.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Type=Application
Name=Hermes
GenericName=AI Agent
Comment=The self-improving AI agent that grows with you
Exec=/usr/bin/hermes-desktop %U
Exec=hermes-desktop %U
Icon=hermes-desktop
Terminal=false
Categories=Development;
Expand Down
Loading
Loading