Several weeks ago I was testing a rather big feature using Tinker. I have spent good two-three hours without exiting Tinker session, and then closed the terminal by mistake. When I opened Tinker again, all my work was, of course, gone. I used the history command from PsySH to recover what I could. A few minutes later, I decided to check if Tinker offered an easier way to handle sessions, saving work, loading previous sessions, and so on. I was rather disappointed by Laravel's official Tinker docs, as the only thing they really provide is a link to Tinkerwell.
After concluding that Tinker indeed does not have a way of natively handling the sessions (or if they have it, they are keeping it a secret), I considered creating a PR to add this feature to Tinker. The fact that in the last year or so very few PRs got merged, and that there is an open issue that seems to provide a good base for adding autocompletion to Tinker is still open after a year, changed my mind.
So, I decided to create a package for handling sessions using PsySH called Tailor.
Basic Idea and Goal
Currently I have an Obsidian folder where I keep Tinker scripts. It looks something like this:
ProjectA
|-scriptA
|-scriptB
|-scriptC
ProjectB
|-scriptA
|-scriptB
...
Whenever I think that some script will be useful in the future I save it there. Tailor is designed to save scripts that are useful on the project level, so that they can be retrieved easily from within the terminal. So, I will do some work, save it, and have an option of uploading that session again in the future. Scripts will have a name, description and tags for easier maintaining.
Tailor is used as an artisan command: php artisan tailor. It provides several commands that will be explained in the next paragraph.
Basic Commands
This version of Tailor has several commands that allow for basic manipulation of the session and provide a good base for future improvements. I will explain each of them without going into too many details.
session:save
This command is used for saving the currently active session. When saving, it is possible to give a description and a name to the session.
session:save [-f | --force] [-d <description> | --description <description>]
[-t <tag> | --tags <tag>]... [<name>]
> $a = 1;
= 1
> $b = 2;
= 2
> $a + $b
= 3
> session:save sum-two-numbers
✓ Session saved successfully!
Name: sum-two-numbers
Commands: 3
session:list
This command lists all all saved sessions from the project and gives some basic info about them.
> session:list
Saved sessions:
sum-two-numbers - 2025-11-12T14:23:20+00:00 (3 commands)
first-user - 2025-11-12T14:21:20+00:00 (2 commands)
session:execute
Executes the session. Can be used as php artisan tailor --session=<name>
session:execute <name>
php artisan tailor --session=sum-two-numbers
Loading session: sum-two-numbers
>>> $a = 1;
=> 1
>>> $b = 2;
=> 2
>>> $a + $b
=> 3
Executed 3 command(s)
You can continue working and use 'session:update' to save new commands.
session:update
Updates the loaded session.
session:update [-d <description> | --description <description>]
[-t <tag> | --tags <tag>]...
Let's say we want to get all posts for the first user and update the script:
php artisan tailor --session=first-user
Loading session: first-user
>>> use App\Models\User;
=> \Psy\CodeCleaner\NoReturnValue::__set_state(array(
))
>>> $user = User::first();
Executed 2 command(s)
You can continue working and use 'session:update' to save new commands.
session:view
This command shows the script, so that it can be inspected before loading it.
session:view <name>
session:view first-user
Session: first-user
Metadata:
Commands: 3
Project: /home/omar/projects/tailor/playground
Duration: 0s
Commands: (3 total)
─────────────────────────────────────────────────────────────────────────────────
use App\Models\User;
$user = User::first();
$posts = $user->posts
─────────────────────────────────────────────────────────────────────────────────
session:delete
Used to delete the session.
session:delete [-f | --force] <name>
> session:delete first-user
Are you sure you want to delete session 'first-user'? [y/N] y
✓ Session 'first-user' deleted successfully!
Future Plans
The imminent goal is to allow Tailor to be used as a way to keep scripts organized. The biggest missing feature that stands in the way of that goal is adding tags to the sessions. Tags will allow users to neatly organize scripts and will allow for easier script exchanges in the team.
Speaking of which, I need to find the best possible way to allow script sharing within the team. There should probably be scripts that are user's and those on the project level.
Before that, I need to add a way to autoload classes to avoid manually writing use Namespace\ClassName. I also want to enable method name autocompletion, for example, when typing new TestClass->te and pressing Tab, it should suggest or complete the method name test().
// written in Malta