Tags: bobthecow/psysh
Tags
Project trust edge case fixes: Fixed several edge cases with the Restricted Mode introduced in v0.12.19 where non-interactive contexts (piped input, execute() calls, Composer proxy scripts) could incorrectly trigger trust prompts or restrict trusted functionality. Fixes #913 Commands work better outside the shell: Decoupled commands from ShellOutput via a new ShellOutputAdapter, so commands degrade gracefully when used in non-interactive contexts rather than failing on missing shell features. Improvements: - Added downstream compatibility tests for local and CI workflows - Moved internal helper scripts from bin/ to scripts/
Security fix: Fixed a CWD configuration poisoning vulnerability (CVE-2026-25129) where a malicious `.psysh.php` file in an attacker-writable directory could execute arbitrary code when a victim runs PsySH from that directory. This affects all versions prior to v0.12.19 and v0.11.23, including downstream consumers like Laravel Tinker when invoked from an attacker-writable CWD. **Fixed in v0.12.19 and v0.11.23.** Upgrade ASAP. Restricted Mode: PsySH now requires explicit trust before loading project-local config (`.psysh.php`), local PsySH binaries, or Composer autoloads from untrusted projects. Trust decisions are persisted per-project in `trusted_projects.json`. Configure with `trustProject`: ```php 'trustProject' => 'prompt', // default — ask interactively 'trustProject' => 'always', // trust all projects 'trustProject' => 'never', // always run restricted ``` Or use `--trust-project` / `--no-trust-project` CLI flags, or the `PSYSH_TRUST_PROJECT` env var. Non-interactive sessions automatically skip untrusted features with a warning. Magic method and property support: Tab completion, `ls`, `doc`, and `show` commands now recognize `@method` and `@property` docblock tags. Magic members display in magenta so you can tell them apart from real methods and properties. Inheritance works as expected — magic members from parent classes, interfaces, and traits are included, with child declarations taking precedence. Also fixes parsing of generic types (e.g., `array<int, string>`) in docblock tags, which previously broke on whitespace inside angle brackets. See #905 Improvements: - Excluded a few unnecessary files and folders from release source zips (Thanks @reedy!) - Fixed `--cwd` to actually change the working directory. Previously it only affected discovery for autoload/config, so relative paths and other directory-dependent behavior didn’t work as expected inside the shell. - Significantly improved memory usage with older php-parser versions (pre-v4.18.0)
- Fixed CWD configuration poisoning vulnerability (CVE-2026-25129). … …Backported Restricted Mode from v0.12. PsySH now requires explicit trust before loading local config (`.psysh.php`), local PsySH binaries, or Composer autoloads from untrusted projects. Configure with `trustProject` config option, `--trust-project` / `--no-trust-project` CLI flags, or `PSYSH_TRUST_PROJECT` env var.
Hot code reloading: Install the [uopz extension](https://www.php.net/manual/en/book.uopz.php) (5.0+) and PsySH will automatically reload modified files during your session. Edit code, switch back to PsySH, and your changes are live—no restart needed! What gets reloaded: - Method bodies (including private/protected) - Function implementations (and new functions!) - Class and global constants What can't be reloaded: - New class methods - Class properties, inheritance, or interfaces - Method signatures PsySH skips "risky" reloads by default (conditional definitions, static variables). Use the new `yolo` command to bypass safety checks: ``` >>> my_helper() Warning: Skipped conditional: if (...) { function my_helper() ... } >>> yolo !! => "result" ``` See the [documentation](https://github.com/bobthecow/psysh/wiki/Code-reloading) for more details. Bug fixes: - Fix "array offset on null" warning on `Ctrl-C` — plays nicer with Laravel + PHP 8.5 - Work around O(n^2) performance in Symfony OutputFormatter
Abbreviated output reverted: The abbreviated return value output introduced in v0.12.13 has been reverted. This feature attempted to show shorter output for statements that looked like they were trying to take an action (like assignments and method calls with side effects) while preserving full output for inspection-like statements. Unfortunately, this version of the feature just ... wasn't it. Thanks to everyone who provided feedback. If you've got thoughts on approaches that could make this better, please share them in #512! In-shell manual updates: You can now update the PHP manual directly from inside the shell! Run `doc --update-manual` to fetch the latest manual version. More robust manual handling: - Log a warning (and continue) when trying to read from an invalid manual file - Show invalid manual info in `--info` and `\Psy\info()` - Prompt to clean up invalid manual files when running `--update-manual` - Prompt to upgrade to v3 manual (preserving language selection!) when running `--update-manual` with an existing sqlite manual - Preserve legacy manuals when updating to v3, supporting systems with multiple PsySH versions installed Bug fixes: - Fix namespace and use statement edge cases where aliases weren't properly tracked across REPL inputs - Fix `history` command filtering and `--head`/`--tail` interaction to apply filters first - Fix E_STRICT warning in PHP 8.4 - Fix ParseCommand parsing (you had one job ಠ_ಠ) Other improvements: - Add a hint about `doc foo` when `help foo` doesn't match a known command - Don't call deprecated `curl_close()` on PHP >= 8.0.0 (thanks @mpesari!) - Lock phar build dependencies for reproducible builds - Improve PHP 8.5 support - Improve test coverage
Logging support:
Log user input, command invocations, and executed code to a PSR-3 logger or callback.
```php
// Simple callback
$config->setLogging(function ($kind, $data) {
file_put_contents('/tmp/psysh.log', "[$kind] $data\n", FILE_APPEND);
});
// PSR-3 logger with granular control
$config->setLogging([
'logger' => $psrLogger,
'level' => [
'input' => 'info',
'command' => false, // disable
'execute' => 'debug',
],
]);
```
This has been one of our longest-requested features (🙈) and it fixes #821, #651, and #565.
Huge documentation improvements:
This release adds a new PHP-based manual data format (v3), replacing the previously used sqlite db. The new format:
- Allows runtime formatting (especially wrapping) rather than pre-rendering at build time.
- Adds OSC 8 links to php.net!
- Is smaller, faster, and more flexible than the sqlite format.
- ... and no longer requires sqlite support to use!
The phar builds now bundle the PHP manual, so these changes work out of the box. There are also automatic update notifications, an an `--update-manual` command to keep docs current.
If you've already got a manual file installed, remove it then run `psysh --update-manual` (or `psysh --update-manual=LANG`) after upgrading!
Fixes #595 and #406.
Other improvements:
- Prettier formatting for `--help` output
- Standardized user-facing path pretty printing
- Fixed Psr\Log namespace scoping in PHAR builds
... pushing the limits of what we can plausibly put in a point release.
Autoload warming:
Added opt-in autoload warming to improve tab completion and command support. When enabled, PsySH pre-loads classes at startup, making them available to `ls`, `doc`, `show`, and tab completion.
```php
// Enable with defaults (project classes only)
'warmAutoload' => true,
// Advanced configuration
'warmAutoload' => [
'includeTests' => true,
'excludeNamespaces' => ['App\Tests\'],
'includeVendorNamespaces' => ['Symfony\', 'Doctrine\'],
],
```
Custom warmers can be implemented via `AutoloadWarmerInterface`. Fixes #650
Implicit use statements:
Auto-adds `use` statements when you reference a class by its short name (and there's exactly one match in configured namespaces).
```php
'implicitUse' => [
'includeNamespaces' => ['App\'],
'excludeNamespaces' => ['App\Legacy\'],
],
```
Works great with autoload warming to make class references feel natural.
Namespace-aware commands:
`doc`, `show`, and `ls` commands now resolve class names using the current namespace and use statements, just like code execution does.
SIGINT handling:
Hitting ctrl-c during long-running code now interrupts execution and returns to the prompt instead of exiting the shell entirely. Works with or without process forking (requires pcntl and posix support). Fixes #154
Exit status support:
PsySH now properly handles exit status codes! Use `exit(42)` for non-zero status codes or `exit('message')` to print before exiting. Also exits with non-zero status on unrecoverable errors.
Clickable documentation links:
Class names, functions, interfaces, constants, and more in `ls`, `doc`, and `show` commands are now clickable links to php.net (requires Symfony 4.3+, PsySH manual installed, and OSC 8 compatible terminal).
Other improvements:
- Added `--info` flag support
- Added `--warm-autoload` CLI option
- Included traits in `ClassNamesMatcher` tab completion
- Print shorter return values for actions than inspection
- Improved PHPStan coverage (levels 2 and 3)
- More robust smoketests
PreviousNext