Releases: rijverse/phpvm
Releases · rijverse/phpvm
phpvm v2.6.1
Changed
- Per-shell switching now self-heals. The shell hooks (bash/zsh/fish) previously forced the shim dir to the front
ofPATHonly at source time, so anything that re-prepended/usr/binor/binafter the rc hook ran (login
profiles,/etc/environment, snapprofile.dscripts, IDE-injectedPATH) silently demoted the shim and the pin
stopped taking effect until a new terminal. The PATH-front logic is now a function,_phpvm_path_fix, re-asserted
from the cd-hook on every directory change. The case-guard makes the already-front case a no-op, so the per-cd
cost is negligible. When it does reorderPATH, it also drops the shell command-location cache (hash -rin bash,
rehashin zsh) so the nextphpruns from the restored order. phpvm shell <ver>now repairs the current terminal in place. When the shim is onPATHbut shadowed by
anotherphp, the eval'd snippet calls_phpvm_path_fix, so the pin takes effect immediately, with no "open a new
terminal" step. The hint is reserved for the genuine case where the hook isn't loaded at all.
Fixed
- Misleading and false "shim not on PATH" warning. The check in
phpvm shellandphpvm --currentsaid the shim was
not on PATH when it actually was, just shadowed by an earlierphp, and used a brittle exact-string compare that
also misfired on symlinked$HOME/ user installs (~/.phpvm). On those,detect_hook_dirreturned an unresolved
path while the hooks put the symlink-resolved dir onPATH, so they never matched and the warning fired even when
switching worked. Replaced with a singleshim_statushelper (active/shadowed/absent/noshim) that
compares resolved paths and is shared byphpvm shell,phpvm --current, andphpvm --doctorso the three stay
consistent.detect_hook_dirnow canonicalizes its result (pwd -P). tests/test_cli.sh: thesh-shellshim-hint test now covers all three states. Absent gives the hook-not-loaded
hint, shadowed does an in-place repair with no stale wording, and active stays silent.tests/test_install.sh: new
runtime check that the cd-hook restores the shim toPATHfront after a simulated late demotion, for both bash and
zsh.
Docs
- Rewrote the "Per-shell switching" section of the README so the everyday flow is the automatic, project-driven
cd-switch (zero commands), andphpvm shellis presented as the manual per-terminal override that sits above it.
Documents the three layersphpvm --currentreports and explains thatshell: not pinnedis normal when the
project layer is the one in charge.
phpvm v2.6.0
Added
phpvm which <version>prints the absolute binary path (e.g./usr/bin/php8.2) for one installed PHP version.
Mirrorsnvm which/pyenv which/rbenv whichso scripts and IDE config tools can pipe the result straight
into wherever an interpreter path is needed (PhpStorm CLI Interpreter, VS Codephp.validate.executablePath,
LSP-IntelephensephpExecutablePath, NetBeans interpreters, CI configs). Returns the bare path on stdout, nothing
else, so it composes. Accepts both8.2andphp8.2.phpvm --list --pathsadds an absolute-path column next to each version, with the active marker preserved.
Designed for visual IDE setup: one command lists every interpreter you can register and where it lives. Includes
a dim footer pointing at the README's "Using with your IDE" section so the recipe is one prompt away.phpvm --list --jsonemits[{"version":"8.2","path":"/usr/bin/php8.2","active":true}, ...]on a single pass:
dependency-free (nojqneeded to produce), stable schema (version/path/active), one entry per
installed PHP, valid JSON ready for tooling and shell-scripted pipelines
(jq -r '.[] | select(.active).path').phpvm shell <ver>andphpvm shell --unsetnow emit a confirmation line via stderr ("pinned this terminal to
PHP 8.2." / "shell pin removed for this terminal."). Previously silent on success, which left users wondering
whether anything happened. The line is emitted inside the eval'd snippet so it preserves "after the eval"
ordering.- Inactive-shim hint: when
phpvm shell <ver>succeeds but the shim isn't on PATH in the caller's terminal
(common scenario: terminal was opened before the hook landed), the eval'd snippet prints "shim not on PATH in
this terminal, so php still resolves to<bin>." plus the exactsourcecommand to activate it. The same
warning block shows up at the bottom ofphpvm --currentwhen a shell or project pin is set butphpresolves
to a non-shim binary, so the layer view explains the mismatch users were hitting. tests/test_install.sh: new behavioral suite (18 checks) forinstall.shanduninstall.sh. Static guards
against the sudo-$HOMEregression class, behavioral install in a fake HOME (writes to the right rc, no
leakage, idempotent on re-run,--upgraderestores a missing hook), uninstall round-trip (hook removed, backup
left, hook dir cleared), and a static + runtime check on the zsh hook (noBASH_SOURCE/PROMPT_COMMAND,
zsh-native chpwd handler, shim prepended,phpvm()defined). The runtime block auto-skips when zsh isn't
installed. Wired intotests/local-compat.shso the docker matrix (Ubuntu 20.04 / 22.04 / 24.04) runs it, zsh
added to the apt install step.
Fixed
install.shwrote the per-user rc + autostart files using$HOME, which undersudopoints at/root. The
shell hook line landed in root's bashrc (or got silently dropped when that file didn't exist), so users who
ransudo ./install.shnever gotsource /etc/phpvm/php-auto.bashin their own rc.phpvm shell <ver>then
printed the "needs the shell wrapper" guidance every time. Resolved by resolvingUSER_HOMEandUSER_SHELL
fromgetent passwd "$CURRENT_USER"whenEUID=0, and writing the rc file viasudo -u "$CURRENT_USER" tee -a
so ownership stays with the invoking user. Same treatment for fish's~/.config/fish/directory creation.
Consolidated the duplicateUSER_HOMEresolution that the autostart block had been doing inline.install.sh --upgradesilently skipped the shell-hook block entirely. Users hit by the prior$HOMEbug
couldn't recover via--upgrade/--self-updateand the hook stayed missing forever. Upgrade mode now writes
the hook line when it's missing (no prompt, since upgrade implies "I want this installed").shell/php-auto.zshwas a copy of the bash hook and broken in zsh on two counts:${BASH_SOURCE[0]}is empty
outside bash so_PHPVM_HOOK_DIRresolved to the current working directory instead of the hook's own location,
andPROMPT_COMMANDdoesn't exist in zsh so the cd auto-switch never fired. Rewrote using${(%):-%x}for the
script-self path (zsh prompt-expansion%x) andadd-zsh-hook chpwd _php_switcher_auto(with an array-append
fallback for older zsh without theadd-zsh-hookautoload). Idempotent on re-source:add-zsh-hook -d chpwd
first strips the prior registration, and the fallback path uses an${array[(r)pattern]}check to skip
duplicates.uninstall.shaborted at the firstsudo rmwhen sudo couldn't prompt (running underset -ewithout a
controlling terminal, or with cached creds expired), leaving rc files unswept and~/.phpvmhalf-removed.
Wrapped removals in a new_rm_pathhelper that triessudo -n(non-interactive), falls back to a regular
sudo rmwith stderr suppressed, and warns + continues instead of failing the script. Result: a user without
active sudo creds still gets a usable partial uninstall (their own files cleaned, system files left alone with
a clear warning).
Changed
- Internal cleanup: install.sh autostart block no longer duplicates the
USER_HOMElookup, as both that block and
the new shell-hook writer read from the single resolution near the top. No user-visible change.
Docs
- README: new "Using with your IDE" section explaining why a GUI IDE doesn't pick up shell env vars, the three
primitives phpvm exposes (which,--list --paths,--list --json), and copy-pasteable recipes for PhpStorm,
VS Code (Intelephense / PHP Tools workspace settings), Sublime / Zed / Helix (LSP), NetBeans, and CI/jq.
States the reasoning (forward-compat: paths instead of IDE config files) so contributors don't try to add a
per-IDE config writer later. CLI table gains rows for--list --paths,--list --json, andphpvm which. --doctorsample output in README bumped to v2.6.0.
phpvm v2.5.1
Added
install.shnow launchesphpvm-guiimmediately after installation when the user selected GUI (options 2 or 3).
Runs in the background withnohup+disownso the tray icon appears without the installer blocking. When run
undersudo, the session env is mostly stripped; the installer harvests the full set it needs (DISPLAY,
WAYLAND_DISPLAY,XDG_RUNTIME_DIR,XDG_SESSION_TYPE,XDG_CURRENT_DESKTOP,XDG_DATA_DIRS,
XDG_CONFIG_DIRS,XAUTHORITY,DBUS_SESSION_BUS_ADDRESS) from a user-owned graphical process via
/proc/<pid>/environand re-launches as the real user withsudo -u env .... WithoutXDG_RUNTIME_DIRthe
AppIndicator backend can't render the label next to the tray icon, and agnome-terminallater spawned from the
tray menu (Open Terminal UI) can't reach its session bus, so all of those vars matter for the tray to be usable.
Skipped silently in non-interactive mode (CI/scripts) or whenpython3-giis absent.
Fixed
- Shell hook only ensured the shim dir was somewhere in
PATH, not first. On boxes where something prepends/bin:
or/usr/bin:toPATHafter the hook runs (login shells re-reading/etc/environment, snapprofile.dscripts,
IDE-injected environments), the shim got demoted andphpresolved to/usr/bin/php(the global symlink), so
phpvm shell <ver>setPHPVM_SHELL_VERSIONcorrectly but had no effect on subsequentphpcalls. The hook now
forces the shim to position 0 every time it is sourced, stripping any stale copies first so PATH does not grow on
re-source. Applied to all three hooks (php-auto.bash,php-auto.zsh,php-auto.fish). - Uninstaller failed to stop a running
phpvm-guibecausepgrep/pkill -x phpvm-guimatched oncomm, which is
python3(from the shebang), notphpvm-gui. The kill step was silently skipped, the binary got removed, and the
Python process kept its tray indicator registered on D-Bus, so the icon stuck around after uninstall. Switched to
pgrep/pkill -fwith a tight cmdline pattern ((^|[/ ])phpvm-gui( |$)so it won't match unrelated processes that
happen to mention the name), plus a short post-TERM wait and a SIGKILL fallback if the GTK loop ignores SIGTERM.
Changed
install.shnow prints a prominent warning at the end when it has just added the shell hook, telling the user that
already-open terminals won't pick it up until theysourcetheir rc. New terminals work automatically. Replaces the
easy-to-miss dim one-liner that fired regardless. The same gotcha is now documented in README's "Installing" section.- Repo-wide typography sweep: removed all em dashes and Unicode ellipses from code, comments, prose, and CLI output
(62 occurrences). Replaced with commas, semicolons, colons, periods, or parens; ellipses became ASCII.... Unicode
arrows (→) kept as house style for status glyphs.
Docs
- README: new
Installingblockquote calling out the post-installsource ~/.bashrcstep for the terminal that ran
the installer, plus a new collapsed<details>block with samplephpvm --doctoroutput showing what each
subsystem check looks like on a healthy install. Documentedsudo bash install.sh --upgrade/-Ufor local-clone
upgrades (same path--self-updateruns after it pulls). - CONTRIBUTING: added the typography rule to ground rules, a Tests section listing
tests/test_cli.sh,
tests/test_gui.sh, andtests/local-compat.sh, a CI pointer at.github/workflows/compat.yml, and a Changelog
section pointing PR authors at the[Unreleased]block.
phpvm v2.5.0
Added
- Per-shell switching, now the default.
phpvm shell <ver>switches PHP for the current terminal only, with no sudo,
so two terminals can run two versions at once. It follows the rbenv / pyenv / asdf model: aphpshim onPATH
(installed to<hook dir>/shims/php) readsPHPVM_SHELL_VERSIONand execs the matching/usr/bin/phpX.Y, falling
back to the global symlink.phpvm shell --unsetdrops the pin. phpvm local <ver>andphpvm global <ver>as the project and system-wide verbs.localwrites.php-version
(no sudo);globalmoves theupdate-alternativessymlink (sudo). The old--setand--set-projectflags stay as
aliases, so existing usage and scripts keep working.- A
phpshim template (shell/shim-php) plus aphpvm()shell wrapper in each hook. The wrapper routesshelland
the bare TUI througheval(fish uses| source) so they can change the current shell; everything else calls the
binary directly. - Resolution is now three layers: shell pin (
PHPVM_SHELL_VERSION), then project (PHPVM_AUTO_VERSION, set by the
cd-hook from.php-version/composer.json), then the global symlink. An explicit shell pin always wins, so it is
never overridden by a latercd.
Changed
- The cd-hook no longer runs a sudo global switch. It now resolves the project version with
phpvm --auto --printand
exportsPHPVM_AUTO_VERSION(or unsets it on leaving), which the shim reads. The everyday path is sudo-free. - The TUI now pins the current shell on Enter when launched through the wrapper (drawing to the terminal while emitting
the assignment on stdout, the way fzf does), withgfor a global switch andpfor the project. Run without the
wrapper, Enter falls back to a global switch and notes how to enable per-shell pinning. phpvm --currentreports the shell pin, project, and global layers separately, plus the effective version.--doctor
gains a "Per-shell switching" section that checks the shim and whether the shim dir is onPATH.install.shinstalls the shim, enables the shell hook by default (the everyday behavior depends on it), and reframes
the sudoers prompt as needed only forphpvm global.- The GUI is documented as global by nature: the tray reflects and sets the system default, and a shell pinned with
phpvm shellcan legitimately sit above it.
Fixed
phpvm installno longer risks hanging on an unattended--yesrun. apt is now invoked as
sudo env DEBIAN_FRONTEND=noninteractive apt-get ..., so a package postinst (e.g. tzdata) can't block on an
interactive debconf prompt.sudoresets the environment, which is why the frontend is set throughenvrather than
an inline assignment; apt stays password-gated exactly as before.
phpvm v2.4.0
Added
phpvm install <ver>installs a PHP minor version from the upstream repo so you no longer hand-runapt install.
Detects the distro from/etc/os-release: Ubuntu (and derivatives carryingubuntuinID_LIKE, e.g. Mint, Pop!_OS)
use Ondřej Surý'sppa:ondrej/php; Debian uses the deb.sury.org repo with a keyring under/etc/apt/keyrings/sury-php.gpg
and a[signed-by=...]source list pinned to$VERSION_CODENAME. Other distros get a clean error. Default package set is
phpX.Y-cli phpX.Y-common phpX.Y-fpm;--minimaldrops fpm and--with curl,mbstringappendsphpX.Y-<ext>. Accepts
explicitX.Yorlatest(resolved viaapt-cacheonce the repo is configured); patch levels like8.2.13are rejected.
Idempotent: reports and exits if the version is already present. After installing it defensively registers thephp
alternative if the package didn't, then offers to switch (--useauto-switches).--printis a dependency-free, CI-safe
dry-run that prints the repo and package list without touching the system.phpvm --helpdocuments the newinstallverb and its flags.
Security
phpvm installkeepsapt/add-apt-repositoryunder a normal password-gatedsudo. The passwordless sudoers rule stays
scoped toupdate-alternatives --setonly; install never widens it.
phpvm v2.3.3
Changed
- Repository moved to
github.com/rijverse/phpvm(previouslyrijoanul-shanto/phpvm). ThePHPVM_REMOTEdefault in
install.sh— used by the remote bootstrap clone and by the--self-updatefallback when no URL was recorded at
install time — now points at the new location, along with every repo link inREADME.md,CONTRIBUTING.md,
index.html, andsocial-preview.html.
Added
- Project landing page (
index.html) — a feature showcase of the taskbar indicator, tray menu, GUI window, and TUI
picker, each with an annotated screenshot. - Social preview —
social-preview.htmlrendered toassets/social-preview.png(1280×640) for the GitHub repo
preview, plus Open Graph / Twitter Card meta tags on the landing page and arijverseworkspace badge linking to the
organization.
phpvm v2.3.2
Fixed
install.shprompts were silently skipped undercurl … | sudo bashbecause piping replaces stdin with the pipe,
making[[ -t 0 ]]return false even when a real terminal is attached. All interactivity checks now use
{ true < /dev/tty; } 2>/dev/nullto detect a controlling terminal instead of testing stdin, and allreadcalls
redirect from/dev/ttydirectly. The one-line installer is now fully interactive — same prompts as running
bash install.shlocally. Truly headless environments (CI,nohup, no controlling tty) still fall back to defaults.
Changed
- README: corrected the installer interactivity note to reflect
/dev/tty-based detection. - README: added
## Uninstallingsection — remote one-liner (curl … | sudo bash), local clone form, itemized list of
what gets removed (binaries, hook dir, sudoers rule, desktop/autostart entries, icons, shell RC lines), RC backup
behaviour, and the sudo-user note.
phpvm v2.3.1
Added
- One-line remote installer —
install.shnow self-bootstraps. When invoked without sibling repo files (e.g.
curl -fsSL …/install.sh | sudo bash), it git-clones the repo into amktemp -d, retargetsSCRIPT_DIRat the
clone, and continues in the same process so the EXIT trap removes the tmp dir on exit (noexec, no orphaned clone).
PHPVM_REMOTEandPHPVM_REFenv vars override the default repo URL and ref (main); falls back to a default-branch
clone +git fetch origin <ref> && checkout FETCH_HEADwhen--branch <ref>doesn't match a branch (so tags/SHAs
work). Hard-fails with a clear message whengitis missing. phpvm --doctor— full diagnostic that checks CLI install, PHP runtimes, composer, PHP-FPM units, sudoers rule, shell
hook wiring, GUI/tray deps (python3-gi / GTK 3 / Ayatana or legacy AppIndicator3 / icon /.desktopentry /
autostart / running process), and project detection. Counts pass / warn / fail and exits non-zero on any fail.install.shnow offers to enable autostart on login. Writes~/.config/autostart/phpvm-gui.desktopand, under sudo,
drops it into the invoking user's$HOME(resolved viagetent passwd) with correct ownership. Upgrade mode
refreshes the file in place if it already exists.- CI compatibility matrix (
.github/workflows/compat.yml) — CLI and GUI jobs build onubuntu:20.04 / 22.04 / 24.04
containers. Runs shellcheck (-S warning), CLI smoke tests, and a GUI import + xvfb--helpsmoke test on every push
and PR touchingphpvm.sh,phpvm-gui.py,install.sh,uninstall.sh,shell/**, ortests/**. tests/test_cli.sh,tests/test_gui.sh,tests/local-compat.sh— smoke tests for CLI flags, GUI imports, and a
Docker-driven local matrix runner.
Changed
- README overhaul: centered logo + GUI screenshots (
assets/gui-window.png,assets/gui-tray-menu.png,
assets/tui.png), expanded--doctorrow in the CLI table, new--auto --print [dir]row, "Things it won't do"
limitations section, and explicitBash 4.3+requirement (badge + "What you need"). - Installer + GUI visual presentation polished — new box-drawing styles, clearer status labels in the GTK window,
refactored icon-install feedback. Restart FPM button now sits to the left of Switch in the row so the
destructive-looking action isn't the primary target. install.shautostart heredoc deduplicated into a singleAUTOSTART_CONTENTtemplate; the root and non-root branches
differ only by the write wrapper (teeundersudo -uvs plain redirect).shell/php-auto.zshandshell/php-auto.fishheaders now document both/etc/phpvm/(system) and~/.phpvm/(user)
install paths, matching the bash hook.phpvm-gui.pydocstring clarifies that Ayatana AppIndicator3 is preferred and legacy AppIndicator3 is accepted as
a fallback.tests/local-compat.shaligned with CI — Ubuntu 18.04 dropped from the local matrix (CI never tested it; README only
claims 20/22/24).CONTRIBUTING.md— real repo URL, Bash target tightened to4.3+(local -nis required), matchingphpvm.sh's
guard..github/workflows/release.yml— every step now earns its keep. Added a repo-integrity pre-check that fails the tag
if any shipped file is missing (includingassets/phpvm.svg, which the installer needs but the previous workflow
never verified). Added abash -nsyntax gate acrossphpvm.sh,install.sh,uninstall.sh, and
shell/php-auto.bash. Everyrun:block now usesset -euo pipefailso the changelogawkpipeline (and friends)
can't silently produce empty output.actions/checkoutandsoftprops/action-gh-releaseare pinned to commit SHAs
with version comments for supply-chain hardening. Dropped theshellcheck … || truestep (lint that always passes is
theater — lint lives incompat.ymlnow). Dropped thefiles:upload list andfetch-depth: 0— the installer and
phpvm --self-updateboth bootstrap viagit clone, never via release artifacts, so the per-file uploads were
decorative; GitHub's auto-attached source tarball still covers the "I want a versioned download" case..github/workflows/compat.yml—shellcheckis now a real gate. Removed the|| truethat silently swallowed every
warning, hoisted lint into a dedicatedlintjob so it runs once instead of three times per matrix OS, and expanded
the lint scope to includetests/test_cli.shandtests/test_gui.sh. Split the GUI dependency install into a
required step (python3, python3-gi, GTK 3, xvfb, libglib2.0-0 — fails fast) and an optional AppIndicator step (
Ayatana → legacy →::warning::), removing the blanket|| truethat was masking missing-python3 failures. Pinned
actions/checkoutto a commit SHA and addedset -euo pipefailto every script block.
Fixed
phpvm.shheader comment saidv2.1.0whileVERSION="2.2.0"— header bumped to v2.2.0.tests/test_cli.shwas exercising non-existent subcommands (list,current,use) that the CLI never accepted;
tests only passed because unknown commands return non-zero. Rewritten against the real flags (--list,--current,
--set), with a regression test that asserts unknown positionaluseis rejected withUnknown option.uninstall.shundersudoonly cleaned the invoking user's autostart, desktop, and icon files — it left
~/.local/bin/phpvm{,-gui}, the~/.phpvmhook directory, and the user's shell rc lines untouched.SUDO_HOMEnow
propagates toBIN_DIRS,HOOK_DIRS, and the rc-cleanup loop.set_project_tuiwrote.php-versionwithout normalizing the version string or warning when an existing file held a
different value — diverged fromcmd_set_project. TUI now normalizes vianormalize_versionand prints an overwrite
warning before the confirm prompt.- README CLI table missed
phpvm --auto --print [dir]and undersold--doctor("install location, sudoers rule, and
shell-hook setup") versus its actual scope.
phpvm v2.3.0
🎉 phpvm v2.3.0 Release Notes
Added
- One-line remote installer —
install.shnow self-bootstraps. When invoked without sibling repo files (e.g.curl -fsSL …/install.sh | sudo bash), it git-clones the repo into amktemp -d, retargetsSCRIPT_DIRat the clone, and continues in the same process so the EXIT trap removes the tmp dir on exit (noexec, no orphaned clone).PHPVM_REMOTEandPHPVM_REFenv vars override the default repo URL and ref (main); falls back to a default-branch clone +git fetch origin <ref> && checkout FETCH_HEADwhen--branch <ref>doesn't match a branch (so tags/SHAs work). Hard-fails with a clear message whengitis missing. phpvm --doctor— full diagnostic that checks CLI install, PHP runtimes, composer, PHP-FPM units, sudoers rule, shell hook wiring, GUI/tray deps (python3-gi / GTK 3 / Ayatana or legacy AppIndicator3 / icon /.desktopentry / autostart / running process), and project detection. Counts pass / warn / fail and exits non-zero on any fail.install.shnow offers to enable autostart on login. Writes~/.config/autostart/phpvm-gui.desktopand, under sudo, drops it into the invoking user's$HOME(resolved viagetent passwd) with correct ownership. Upgrade mode refreshes the file in place if it already exists.- CI compatibility matrix (
.github/workflows/compat.yml) — CLI and GUI jobs build onubuntu:20.04 / 22.04 / 24.04containers. Runs shellcheck (-S warning), CLI smoke tests, and a GUI import + xvfb--helpsmoke test on every push and PR touchingphpvm.sh,phpvm-gui.py,install.sh,uninstall.sh,shell/**, ortests/**. tests/test_cli.sh,tests/test_gui.sh,tests/local-compat.sh— smoke tests for CLI flags, GUI imports, and a Docker-driven local matrix runner.
Changed
- README overhaul: centered logo + GUI screenshots (
assets/gui-window.png,assets/gui-tray-menu.png,assets/tui.png), expanded--doctorrow in the CLI table, new--auto --print [dir]row, "Things it won't do" limitations section, and explicitBash 4.3+requirement (badge + "What you need"). - Installer + GUI visual presentation polished — new box-drawing styles, clearer status labels in the GTK window, refactored icon-install feedback. Restart FPM button now sits to the left of Switch in the row so the destructive-looking action isn't the primary target.
install.shautostart heredoc deduplicated into a singleAUTOSTART_CONTENTtemplate; the root and non-root branches differ only by the write wrapper (teeundersudo -uvs plain redirect).shell/php-auto.zshandshell/php-auto.fishheaders now document both/etc/phpvm/(system) and~/.phpvm/(user) install paths, matching the bash hook.phpvm-gui.pydocstring clarifies that Ayatana AppIndicator3 is preferred and legacy AppIndicator3 is accepted as a fallback.tests/local-compat.shaligned with CI — Ubuntu 18.04 dropped from the local matrix (CI never tested it; README only claims 20/22/24).CONTRIBUTING.md— real repo URL, Bash target tightened to4.3+(local -nis required), matchingphpvm.sh's guard.
Fixed
phpvm.shheader comment saidv2.1.0whileVERSION="2.2.0"— header bumped to v2.2.0.tests/test_cli.shwas exercising non-existent subcommands (list,current,use) that the CLI never accepted; tests only passed because unknown commands return non-zero. Rewritten against the real flags (--list,--current,--set), with a regression test that asserts unknown positionaluseis rejected withUnknown option.uninstall.shundersudoonly cleaned the invoking user's autostart, desktop, and icon files — it left~/.local/bin/phpvm{,-gui}, the~/.phpvmhook directory, and the user's shell rc lines untouched.SUDO_HOMEnow propagates toBIN_DIRS,HOOK_DIRS, and the rc-cleanup loop.set_project_tuiwrote.php-versionwithout normalizing the version string or warning when an existing file held a different value — diverged fromcmd_set_project. TUI now normalizes vianormalize_versionand prints an overwrite warning before the confirm prompt.- README CLI table missed
phpvm --auto --print [dir]and undersold--doctor("install location, sudoers rule, and shell-hook setup") versus its actual scope.
phpvm v2.2.0
🎉 phpvm v2.2.0 Release Notes
Overview
This release brings significant improvements to the GUI components, authentication workflow, and system integration. The focus is on better user experience, improved reliability, and reduced friction in password handling.
✨ New Features
GUI Enhancements
- In-window status messages: Real-time feedback for switch and FPM restart operations displayed directly in the window instead of system notifications
- Polkit support: Added fallback to graphical authentication (pkexec) when passwordless sudo isn't configured
- File monitoring: Automatic detection of PHP version changes from external sources via
/etc/alternatives/phpmonitoring - Instance locking: Single instance enforcement to prevent multiple GUI windows running simultaneously
🔧 Major Changes
Authentication Improvements
- Simplified sudo workflow: Removed the dependency on passwordless sudo configuration
- Primary method: Fast path with
sudo -n(passwordless) - Fallback: Graphical polkit dialog (
pkexec) with user-friendly password prompts
- Primary method: Fast path with
- Better error messages: Removed confusing error codes like "needs_sudo" and replaced with actionable status messages
- Shell script improvements: Updated
phpvm.shto use interactive password prompts (-pflag) instead of silent mode
System Integration
- Service restart enhancements: FPM restart now supports both passwordless sudo and graphical auth fallback
- Tray integration: Window state is now properly synchronized with system tray mode
- Uninstall improvements:
uninstall.shnow gracefully stops running phpvm-gui instances
Developer Experience
- Removed notification dependency: Window status messages replace desktop notifications for better UX
- Improved callback system: Added
on_switchcallback mechanism for GUI-tray synchronization - Better module imports: Added
fcntlsupport for instance locking
🐛 Bug Fixes
- Fixed window mode vs tray mode logic (was reversed in previous version)
- Improved error handling for missing commands
- Better cache clearing on system state changes
- Fixed modal dialog handling in folder selection
📋 Technical Details
Files Modified:
phpvm-gui.py- Major refactoring of GUI logic and authentication flowphpvm.sh- Updated version number and sudo handlinguninstall.sh- Added graceful shutdown of running processes
Version String Updated:
v2.1.0→v2.2.0
🚀 Migration Notes
- No breaking changes for existing installations
- The install.sh passwordless sudo setup is now optional (polkit provides fallback)
- Users can continue using existing configurations without changes