Repository navigation
Conversation
pyrech
approved these changes
Oct 22, 2026
PHP creates the PTY without a size (0x0): the commands fell back on 80 columns, and a full screen one was unusable. The command now runs through a shell which gives the PTY the size of the terminal of Castor, then runs the command in its place. Only when Castor has a terminal, and only the size at the start of the command.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PHP creates the PTY of a process without a size (0x0), and has no API to change it. So every command run by Castor in a PTY (the default) saw a 0x0 terminal: PHPStan, PHP-CS-Fixer, etc. fell back on 80 columns,
docker compose rungave a 0x0 terminal to the container, and Node tools saw 0 columns.The command now runs through
sh, which copies the size of the terminal of Castor (/dev/tty) to the PTY, thenexecs the command: same PID, signals and exit code.getCommandLine()still returns the command as asked, so logs, errors and notifications don't change. Without a terminal (CI, AI agents), the command is not wrapped at all. Only the size at the start of the command: following a resize would need the master side of the PTY, which is private in Symfony Process.This code scares me a bit (a subclass of Symfony's
Process, a shell around every command), but it's well tested.tests/PtySizeTest.phpruns Castor in a pseudo terminal (script) and checks the size for array and string commands, the command line shown, the exit code, the failure message, and that nothing changes without a terminal (setsid). It costs about 3.5 ms per command in a PTY, only when Castor has a terminal. Not tested on macOS.There is also a lighter alternative, which passes
COLUMNSandLINESinstead: see the end of this description.By use case
pty-sizeis this PR,pty-columnsthe alternative.mainpty-sizepty-columnscastor phpstanin Castor)qa:phpstan,qa:twig-cs)-e COLUMNS -e LINEScastor-php/dockerplugin (redirection.io:backend:qa:phpstan)castor phpstan)COLUMNScastor builder)withTty()(vim,top)castor phpstan > log)On a docker-starter project, only
pty-sizefixes the width without changing each project.Lighter alternative:
COLUMNSandLINESThe PTY stays 0x0, but Castor gives the size of its terminal in
COLUMNSandLINES, which most tools read first (Symfony Console, Python,tput,ls). Node ignores them, and they don't reach the containers unless the project passes them with-e. Known issue:buildRunnableCommand()readsgetEnv(), so the error message of a failed command showsLINES='40' COLUMNS='150' 'false'. It could be fixed by passing the variables tostart()instead.