Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
b758465
chore(desktop): add "NewInstance" action to .desktop files and update…
Leay15 May 17, 2026
6048dea
chore(updater): add cache cleanup utilities and integrate workspace p…
Leay15 May 19, 2026
89809dc
chore(updater): bump version to 0.8.1 and update changelog with works…
Leay15 May 19, 2026
623b1c7
chore(tests): add `ready-to-show` window state patch test for Linux apps
Leay15 May 19, 2026
1da1420
chore(patches): add `ready-to-show` window state patch integration fo…
Leay15 May 19, 2026
1b94d9c
chore(patches): enhance Linux launch actions with support for scoped …
Leay15 May 19, 2026
e4a0ba7
chore(desktop): refine .desktop file actions and update scripts for i…
Leay15 May 19, 2026
79a998b
chore(updater): add `cache_cleanup.rs` with workspace pruning and cle…
Leay15 May 19, 2026
5323ca1
chore(desktop): update WMClass fields in .desktop files to `codex-des…
Leay15 May 19, 2026
337818c
chore(desktop): add `codex-desktop-entry-doctor.sh` for managing and …
Leay15 May 20, 2026
9a4bc1d
chore(scripts): update packaging scripts to dynamically handle shadow…
Leay15 May 20, 2026
070cfa0
chore(desktop): add `new-window` action to .desktop files and integra…
Leay15 May 20, 2026
dd2cb0b
chore(postinst): integrate desktop entry repair logic into post-insta…
Leay15 May 20, 2026
f3206a3
chore(scripts): integrate `codex-desktop-entry-doctor.sh` and refacto…
Leay15 May 20, 2026
2d7f71f
chore(scripts): extend packaging scripts with `codex-desktop-entry-do…
Leay15 May 20, 2026
e500336
chore(tests): add tests for `codex-desktop-entry-doctor.sh` and updat…
Leay15 May 20, 2026
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).

### Fixed

- `codex-update-manager` now prunes unreferenced updater workspaces under `~/.cache/codex-update-manager/workspaces`, removing heavy build artifacts (`builder/`, `codex-app/`, `dist/`) while preserving lightweight diagnostics such as `logs/` and rebuild reports.
- The Chrome native-messaging host now evicts stale browser clients when a newer Codex browser client connects, preventing old Node REPL sessions from repeatedly reattaching CDP and driving extension service-worker CPU.
- The bundled Chrome plugin is now auto-installed during app startup, matching Browser Use, so the plugin page no longer falls back to an install button after restart when the Linux native host is already staged.
- Nix builds, installer apps, and dev shells now use modern `7zz`, and the installer dependency check accepts `7zz` without requiring a separate legacy `7z` binary.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ pacman -Qlp dist/codex-desktop-*.pkg.tar.zst | sed -n '1,40p'

## Versioning

`codex-update-manager` current crate version: `0.8.0`
`codex-update-manager` current crate version: `0.8.1`

SemVer policy:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ Type=Application
Version=1.0
Name=Codex Desktop
Comment=OpenAI Codex desktop wrapper for Linux
Exec=@HOME@/.local/bin/codex-desktop %U
Exec=env BAMF_DESKTOP_FILE_HINT=@HOME@/.local/share/applications/codex-desktop.desktop CHROME_DESKTOP=codex-desktop.desktop @HOME@/.local/bin/codex-desktop %U
TryExec=@HOME@/.local/bin/codex-desktop
Terminal=false
Categories=Development;IDE;
MimeType=x-scheme-handler/codex;x-scheme-handler/codex-browser-sidebar;
Keywords=codex;openai;ai;coding;
StartupNotify=true
StartupWMClass=codex-desktop
X-GNOME-WMClass=codex-desktop
Icon=codex-desktop
Actions=new-window;

[Desktop Action new-window]
Name=New Window
Exec=env BAMF_DESKTOP_FILE_HINT=@HOME@/.local/share/applications/codex-desktop.desktop CHROME_DESKTOP=codex-desktop.desktop CODEX_MULTI_LAUNCH=1 @HOME@/.local/bin/codex-desktop --new-instance
13 changes: 8 additions & 5 deletions contrib/user-local-install/install-user-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
FILES_DIR="${SCRIPT_DIR}/files"
SCRIPT_REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
SOURCE_REPO_ROOT="${CODEX_USER_LOCAL_SOURCE_REPO_DIR:-$SCRIPT_REPO_ROOT}"
DESKTOP_ENTRY_DOCTOR="${SOURCE_REPO_ROOT}/packaging/linux/codex-desktop-entry-doctor.sh"
OPT_ROOT="${HOME}/.local/opt/codex-desktop-linux"
OPT_BIN_DIR="${OPT_ROOT}/bin"
OPT_LIB_DIR="${OPT_ROOT}/lib/codex-desktop-linux"
Expand All @@ -19,6 +20,9 @@ FROM_UPDATE=0
ENABLE_TIMER=0
USER_LOCAL_OZONE_PLATFORM_SETTING=""

# shellcheck disable=SC1090
. "$DESKTOP_ENTRY_DOCTOR"

while [ $# -gt 0 ]; do
case "$1" in
--from-update)
Expand Down Expand Up @@ -109,7 +113,10 @@ set -euo pipefail
exec "${HOME}/.local/opt/codex-desktop-linux/bin/codex-desktop-version" "$@"
EOF

sed "s|@HOME@|${HOME}|g" "${FILES_DIR}/.local/share/applications/codex-desktop.desktop" > "${HOME}/.local/share/applications/codex-desktop.desktop"
codex_desktop_write_user_local_entry \
"${FILES_DIR}/.local/share/applications/codex-desktop.desktop" \
"${HOME}/.local/share/applications/codex-desktop.desktop" \
"${HOME}"

copy_file "${FILES_DIR}/.config/systemd/user/codex-desktop-update.service" "${systemd_user_dir}/codex-desktop-update.service"
copy_file "${FILES_DIR}/.config/systemd/user/codex-desktop-update.timer" "${systemd_user_dir}/codex-desktop-update.timer"
Expand Down Expand Up @@ -145,10 +152,6 @@ if command -v systemctl >/dev/null 2>&1; then
fi
fi

if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database "${HOME}/.local/share/applications" >/dev/null 2>&1 || true
fi

if [ "$FROM_UPDATE" -eq 0 ] && [ -x "${HOME}/.local/bin/codex-desktop-update" ]; then
"${HOME}/.local/bin/codex-desktop-update" --record-only >/dev/null 2>&1 || true
fi
Expand Down
9 changes: 7 additions & 2 deletions packaging/appimage/codex-desktop.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Type=Application
Categories=Development;
MimeType=x-scheme-handler/codex;x-scheme-handler/codex-browser-sidebar;
StartupNotify=true
StartupWMClass=Codex
X-GNOME-WMClass=Codex
StartupWMClass=codex-desktop
X-GNOME-WMClass=codex-desktop
X-AppImage-Version=__VERSION__
Actions=new-window;

[Desktop Action new-window]
Name=New Window
Exec=env CHROME_DESKTOP=codex-desktop.desktop CODEX_MULTI_LAUNCH=1 AppRun --new-instance
123 changes: 123 additions & 0 deletions packaging/linux/codex-desktop-entry-doctor.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/bin/sh

codex_desktop_refresh_desktop_database() {
codex_desktop_db_dir="${1:-}"
[ -n "$codex_desktop_db_dir" ] || return 0

if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database "$codex_desktop_db_dir" >/dev/null 2>&1 || true
fi
}

codex_desktop_write_user_local_entry() {
codex_desktop_template_path="${1:?missing desktop template path}"
codex_desktop_target_path="${2:?missing desktop target path}"
codex_desktop_home_dir="${3:?missing home directory}"

mkdir -p "$(dirname "$codex_desktop_target_path")"
sed "s|@HOME@|${codex_desktop_home_dir}|g" \
"$codex_desktop_template_path" > "$codex_desktop_target_path"
chmod 0644 "$codex_desktop_target_path"
codex_desktop_refresh_desktop_database "$(dirname "$codex_desktop_target_path")"
}

codex_desktop_entry_has_sidebar_mime() {
grep -Eq '^MimeType=.*x-scheme-handler/codex-browser-sidebar([;]|$)' "$1"
}

codex_desktop_entry_has_new_window_action() {
grep -Eq '^Actions=.*new-window([;]|$)' "$1" &&
grep -Eq '^\[Desktop Action new-window\]$' "$1"
}

codex_desktop_entry_is_legacy_generated() {
codex_desktop_file="${1:?missing desktop entry path}"
[ -f "$codex_desktop_file" ] || return 1

grep -q '^Name=Codex Desktop$' "$codex_desktop_file" || return 1
grep -Eq '(^Exec=.*codex-desktop|^TryExec=.*codex-desktop|^Icon=codex-desktop$)' \
"$codex_desktop_file" || return 1

if grep -Eq 'codex-desktop-open-next|^Actions=NewWindow([;]|$)|^\[Desktop Action NewWindow\]$|^Actions=NewInstance([;]|$)|^\[Desktop Action NewInstance\]$' \
"$codex_desktop_file"; then
return 0
fi

if ! codex_desktop_entry_has_sidebar_mime "$codex_desktop_file"; then
return 0
fi

if ! codex_desktop_entry_has_new_window_action "$codex_desktop_file"; then
return 0
fi

return 1
}

codex_desktop_next_backup_path() {
codex_desktop_backup_target="${1:?missing desktop entry path}.bak"
codex_desktop_backup_index=0

while [ -e "$codex_desktop_backup_target" ]; do
codex_desktop_backup_index=$((codex_desktop_backup_index + 1))
codex_desktop_backup_target="${1}.bak.${codex_desktop_backup_index}"
done

printf '%s\n' "$codex_desktop_backup_target"
}

codex_desktop_repair_shadow_entry() {
codex_desktop_target_path="${1:?missing desktop entry path}"
codex_desktop_backup_target=""

if ! codex_desktop_entry_is_legacy_generated "$codex_desktop_target_path"; then
return 1
fi

codex_desktop_backup_target="$(codex_desktop_next_backup_path "$codex_desktop_target_path")"
mv "$codex_desktop_target_path" "$codex_desktop_backup_target"
codex_desktop_refresh_desktop_database "$(dirname "$codex_desktop_target_path")"
}

codex_desktop_repair_system_package_shadow_entries() {
codex_desktop_package_name="${1:-codex-desktop}"
codex_desktop_target_file="${codex_desktop_package_name}.desktop"

if ! command -v runuser >/dev/null 2>&1 || ! command -v getent >/dev/null 2>&1; then
return 0
fi

for codex_desktop_runtime_dir in /run/user/*; do
[ -d "$codex_desktop_runtime_dir" ] || continue

codex_desktop_uid="$(basename "$codex_desktop_runtime_dir")"
case "$codex_desktop_uid" in
''|*[!0-9]*|0)
continue
;;
esac

codex_desktop_passwd_entry="$(getent passwd "$codex_desktop_uid" || true)"
[ -n "$codex_desktop_passwd_entry" ] || continue

codex_desktop_user_name="$(printf '%s\n' "$codex_desktop_passwd_entry" | cut -d: -f1)"
codex_desktop_home_dir="$(printf '%s\n' "$codex_desktop_passwd_entry" | cut -d: -f6)"
[ -n "$codex_desktop_user_name" ] || continue
[ -n "$codex_desktop_home_dir" ] || continue
[ "$codex_desktop_home_dir" != "/" ] || continue

codex_desktop_user_entry="$codex_desktop_home_dir/.local/share/applications/$codex_desktop_target_file"
if ! codex_desktop_entry_is_legacy_generated "$codex_desktop_user_entry"; then
continue
fi

codex_desktop_backup_target="$(codex_desktop_next_backup_path "$codex_desktop_user_entry")"
runuser -u "$codex_desktop_user_name" -- mv \
"$codex_desktop_user_entry" "$codex_desktop_backup_target" >/dev/null 2>&1 || true
runuser -u "$codex_desktop_user_name" -- sh -c '
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database "$1" >/dev/null 2>&1 || true
fi
' sh "$codex_desktop_home_dir/.local/share/applications" >/dev/null 2>&1 || true
done
}
10 changes: 7 additions & 3 deletions packaging/linux/codex-desktop.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ Type=Application
Categories=Development;
MimeType=x-scheme-handler/codex;x-scheme-handler/codex-browser-sidebar;
StartupNotify=true
StartupWMClass=Codex
X-GNOME-WMClass=Codex
Actions=CheckForUpdates;InstallReadyUpdate;
StartupWMClass=codex-desktop
X-GNOME-WMClass=codex-desktop
Actions=new-window;CheckForUpdates;InstallReadyUpdate;

[Desktop Action new-window]
Name=New Window
Exec=env BAMF_DESKTOP_FILE_HINT=/usr/share/applications/codex-desktop.desktop CHROME_DESKTOP=codex-desktop.desktop CODEX_MULTI_LAUNCH=1 /usr/bin/codex-desktop --new-instance

[Desktop Action CheckForUpdates]
Name=Check for Updates
Expand Down
8 changes: 8 additions & 0 deletions packaging/linux/codex-desktop.install
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
SERVICE_HELPER="/opt/codex-desktop/update-builder/packaging/linux/codex-update-manager-user-service.sh"
DESKTOP_ENTRY_DOCTOR="/opt/codex-desktop/.codex-linux/codex-desktop-entry-doctor.sh"
if [ -f "$SERVICE_HELPER" ]; then
# shellcheck source=/opt/codex-desktop/update-builder/packaging/linux/codex-update-manager-user-service.sh
. "$SERVICE_HELPER"
fi
if [ -f "$DESKTOP_ENTRY_DOCTOR" ]; then
# shellcheck source=/opt/codex-desktop/.codex-linux/codex-desktop-entry-doctor.sh
. "$DESKTOP_ENTRY_DOCTOR"
fi

post_install() {
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database /usr/share/applications >/dev/null 2>&1 || true
fi
if [ -f "$DESKTOP_ENTRY_DOCTOR" ]; then
codex_desktop_repair_system_package_shadow_entries codex-desktop || true
fi
if [ -f "$SERVICE_HELPER" ]; then
codex_ensure_user_service_running || true
fi
Expand Down
5 changes: 5 additions & 0 deletions packaging/linux/codex-desktop.spec
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ cp -a "__RPM_STAGING_DIR__/." "%{buildroot}/"
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database /usr/share/applications >/dev/null 2>&1 || true
fi
DESKTOP_ENTRY_DOCTOR=/opt/__PACKAGE_NAME__/.codex-linux/codex-desktop-entry-doctor.sh
if [ -f "$DESKTOP_ENTRY_DOCTOR" ]; then
. "$DESKTOP_ENTRY_DOCTOR"
codex_desktop_repair_system_package_shadow_entries __PACKAGE_NAME__ || true
fi

%if __PACKAGE_WITH_UPDATER__
SERVICE_HELPER=/opt/__PACKAGE_NAME__/update-builder/packaging/linux/codex-update-manager-user-service.sh
Expand Down
6 changes: 6 additions & 0 deletions packaging/linux/codex-update-manager.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
set -eu

SERVICE_HELPER="/opt/codex-desktop/update-builder/packaging/linux/codex-update-manager-user-service.sh"
DESKTOP_ENTRY_DOCTOR="/opt/codex-desktop/.codex-linux/codex-desktop-entry-doctor.sh"
if [ -f "$SERVICE_HELPER" ]; then
# shellcheck source=/opt/codex-desktop/update-builder/packaging/linux/codex-update-manager-user-service.sh
. "$SERVICE_HELPER"
codex_ensure_user_service_running || true
fi
if [ -f "$DESKTOP_ENTRY_DOCTOR" ]; then
# shellcheck source=/opt/codex-desktop/.codex-linux/codex-desktop-entry-doctor.sh
. "$DESKTOP_ENTRY_DOCTOR"
codex_desktop_repair_system_package_shadow_entries codex-desktop || true
fi

exit 0
5 changes: 4 additions & 1 deletion scripts/build-deb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ CONTROL
fi
chmod 0644 "$PKG_ROOT/DEBIAN/control"
if package_with_updater_enabled; then
sed -e "s|/opt/codex-desktop|/opt/$PACKAGE_NAME|g" "$POSTINST_TEMPLATE" > "$PKG_ROOT/DEBIAN/postinst"
sed \
-e "s|/opt/codex-desktop|/opt/$PACKAGE_NAME|g" \
-e "s|codex_desktop_repair_system_package_shadow_entries codex-desktop|codex_desktop_repair_system_package_shadow_entries $PACKAGE_NAME|g" \
"$POSTINST_TEMPLATE" > "$PKG_ROOT/DEBIAN/postinst"
cp "$PRERM_TEMPLATE" "$PKG_ROOT/DEBIAN/prerm"
cp "$POSTRM_TEMPLATE" "$PKG_ROOT/DEBIAN/postrm"
chmod 0755 "$PKG_ROOT/DEBIAN/postinst" "$PKG_ROOT/DEBIAN/prerm" "$PKG_ROOT/DEBIAN/postrm"
Expand Down
1 change: 1 addition & 0 deletions scripts/build-pacman.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ main() {
"$PKGBUILD_TEMPLATE" >"$build_root/PKGBUILD"
if package_with_updater_enabled; then
sed -e "s|/opt/codex-desktop|/opt/$PACKAGE_NAME|g" \
-e "s|codex_desktop_repair_system_package_shadow_entries codex-desktop|codex_desktop_repair_system_package_shadow_entries $PACKAGE_NAME|g" \
"$INSTALL_HOOKS" >"$build_root/${PACKAGE_NAME}.install"
else
write_no_updater_pacman_install_hooks "$build_root/${PACKAGE_NAME}.install"
Expand Down
Loading
Loading