The trace command shows the current call stack, revealing how execution reached the current point in your code. Unlike wtf, which shows exception backtraces, trace shows the stack trace from the current execution context.
Syntax
Options
Alias: -pInclude PsySH internal frames in the call stack. By default, PsySH’s own function calls are hidden for clarity.
Alias: -nLimit output to the specified number of stack frames
Filter stack frames by pattern (supports regular expressions)
Alias: -iMake grep search case-insensitive
Alias: -vInvert grep match (show frames that don’t match)
Usage Examples
Basic Stack Trace
>>> function level3() {
... trace
... }
>>> function level2() {
... level3()
... }
>>> function level1() {
... level2()
... }
>>> level1()
0: level3()
at eval():2
1: level2()
at eval():5
2: level1()
at eval():8
3: eval()
The trace shows the call stack from innermost (current) to outermost (entry point).
Limit Number of Frames
>>> trace -n 5
>>> trace --num 10
Shows only the first 5 or 10 frames.
>>> trace -n 3
0: currentFunction()
1: caller()
2: topLevelCaller()
Include PsySH Internals
By default, PsySH filters out its own internal calls:
>>> trace
0: myFunction()
1: eval()
With --include-psy, you see the complete stack:
>>> trace --include-psy
>>> trace -p
0: myFunction()
at eval():1
1: eval()
2: Psy\Shell->execute()
at /vendor/psy/psysh/src/Shell.php:542
3: Psy\ExecutionLoop\Loop->run()
at /vendor/psy/psysh/src/ExecutionLoop/Loop.php:87
4: Psy\Shell->run()
at /vendor/psy/psysh/src/Shell.php:345
... (many more PsySH internal frames)
Including PsySH internals can be useful for debugging PsySH itself or understanding its execution flow.
Filter Stack Frames
>>> trace --grep /MyApp/
>>> trace --grep /Controller/
Shows only frames matching the pattern.
>>> trace --grep /App\\/
2: App\UserController->store()
5: App\Services\UserService->create()
8: App\Repositories\UserRepository->save()
Case-Insensitive Filter
>>> trace --grep /database/ -i
>>> trace --grep /controller/ --insensitive
Invert Filter
>>> trace --grep /Psy/ --invert
Shows all frames except those containing “Psy”.
Understanding the Output
Each stack frame shows:
N: ClassName->methodName($arg1, $arg2)
at /path/to/file.php:123
- N - Frame number (0 is current, increasing numbers go up the stack)
- ClassName->methodName - The method or function being called
- at /path/to/file.php:123 - Where the call was made from
Frame Types
// Instance method call
0: MyClass->instanceMethod()
// Static method call
1: MyClass::staticMethod()
// Function call
2: someFunction()
// Closure/anonymous function
3: {closure}()
// Eval'd code
4: eval()
Practical Use Cases
Debug Deep Call Chains
See how you ended up at the current point:
0: App\Services\OrderProcessor->process()
1: App\Http\Controllers\OrderController->store()
2: Illuminate\Routing\Controller->callAction()
3: Illuminate\Routing\ControllerDispatcher->dispatch()
...
Find Who Called a Function
function debugMe() {
trace
// ... rest of function
}
When debugMe() is called, you’ll see the complete call path.
Verify Execution Path
>>> trace --grep /Controller/
Confirm which controllers are in the call stack.
Limit Deep Stacks
When dealing with very deep recursion or long call chains, limit output to the most relevant frames.
Comparison with wtf
| Feature | trace | wtf |
|---|
| Purpose | Current call stack | Exception backtrace |
| When to use | Debug execution flow | Debug errors |
| Shows | How you got here | What went wrong |
| Context | Any time | After an exception |
>>> function foo() { trace; }
>>> foo()
0: foo()
1: eval()
>>> throw new Exception('Error')
>>> wtf
Exception with message 'Error'
--
0: throw new Exception('Error')
1: eval()
Debugging Patterns
Trace from Specific Point
class UserService {
public function create($data) {
trace // Insert trace to see call stack
// ... rest of method
}
}
Compare Execution Paths
>>> firstPath()
>>> trace --num 5
>>> secondPath()
>>> trace --num 5
Compare which functions are called in different scenarios.
Filter Application Code
>>> trace --grep /^App\\/ -n 10
Show only your application’s stack frames, ignoring framework code.
Tips
Use trace to understand recursion:function factorial($n) {
if ($n === 1) trace;
return $n === 1 ? 1 : $n * factorial($n - 1);
}
>>> factorial(5)
0: factorial(1)
1: factorial(2)
2: factorial(3)
3: factorial(4)
4: factorial(5)
Combine with grep to focus on specific classes:>>> trace --grep /Service/ -n 10
Shows service layer calls only.
Compare with and without PsySH internals:>>> trace -n 5 # Clean view
>>> trace -p -n 20 # See PsySH machinery
Very deep recursion may produce overwhelming output:>>> trace # Could be hundreds of frames!
>>> trace -n 10 # Better - just the recent calls
Advanced Usage
Regular Expression Filtering
>>> trace --grep "/Controller|Service/"
Shows frames containing either “Controller” or “Service”.
>>> trace --grep "/^(?!Illuminate)/"
Shows frames NOT starting with “Illuminate” (excludes Laravel framework).
Focused Debugging
>>> trace --grep /Repository/ -n 3
Find the 3 most recent repository calls.
See Also
- wtf - View exception backtraces
- whereami - Show current code location
- show —ex - View exception code context