fish's 3.1 beta exposes pipeline failures and execution traces
fish 3.1b1 adds per-command pipeline statuses and execution tracing. It also changes buffering before a final shell function, addressing a different cause of apparently stalled pipelines.
A pipeline can produce useful output even when an earlier stage failed. Looking only at its final result loses information about the commands that supplied that output. fish 3.1b1 adds a list of per-command statuses, giving shell code and prompts a direct way to report that distinction.
The January 26 beta release introduces pipestatus and execution tracing through fish_trace. It also removes buffering before the last function in a pipeline. These changes improve diagnosis at separate levels, making command results observable and changing when a function can consume its input.
I like an interactive shell that makes its behavior visible without requiring extensive configuration. Per-command status information is useful in that sense. It lets a prompt report a failed stage even when a later command completed successfully.
Status becomes a list
The beta's manual source defines pipestatus as the exit statuses of the processes in the last executed pipeline. It separately describes status as the exit status of the last foreground job. The new variable retains the pipeline's component results.
A minimal fish example avoids dependencies on external files or services.
false | true
set saved_pipeline_status $pipestatus
printf '%s\n' $saved_pipeline_status
The two commands deliberately return different statuses. Saving the list immediately retains the evidence before later commands become the most recently executed work. Printing the saved values then reports both stages instead of collapsing them into one result.
The versioned set documentation explains that assigning several values creates a list. The assignment therefore preserves the separate status elements. No delimiter parsing is needed to recover the component results from a formatted string.
This matters when writing a wrapper around a real pipeline. The wrapper needs to decide whether every stage must succeed or whether some statuses have an acceptable meaning. Having the list supplies evidence for that decision without imposing one universal interpretation.
Prompts can retain the same evidence
The beta's default prompt source saves pipestatus at the start of the prompt function. It later passes the saved list to the helper that prints pipeline status.
That order is instructive because prompts run commands themselves. Computing colors, working-directory text and version-control information introduces more shell activity. Capturing the previous pipeline result before that work keeps the prompt's own execution separate from the command result it is trying to display.
The release notes say the default and example prompts print pipeline status when an earlier stage fails. That turns the variable into an immediate interactive improvement as well as a scripting facility. Users do not need to write a custom prompt merely to benefit from the information.
The mechanism also explains what a custom prompt needs to preserve. Copying the result early is more dependable than asking for the last pipeline status after several helper calls. The reported job and the prompt's implementation should remain distinct.
Tracing reveals the commands being executed
The manual says a nonempty fish_trace makes fish print commands before execution. Output goes to standard error by default, or to the destination selected through the debugging-output option.
set -g fish_trace 1
printf '%s\n' example
set -e fish_trace
This example enables tracing for a short interval and then removes the variable. It uses fish's own variable commands. The beta release compares the effect with execution tracing in other shells, but that comparison does not make their variable syntax interchangeable.
A trace answers a different question from a status list. The trace helps establish what the shell executed. The status list establishes how the pipeline stages exited. A command can be exactly the one expected and still return an error, so both observations can be relevant to the same investigation.
Buffering can delay execution without a failed command
The tagged changelog says fish no longer buffers pipes to the last function in a pipeline. It associates the change with cases where pipelines appeared to block or hang.
That addresses timing of input delivery rather than interpretation of exit codes. A function waiting to receive data may look inactive even though no command has returned an error. Status reporting alone cannot explain a pipeline that has not reached termination.
The release therefore improves both the execution behavior and the information available about it. Those improvements should remain separate in an explanation. Removing a buffering boundary can allow useful progress earlier, while tracing and pipeline statuses help explain the commands that actually ran.
I regard that combination as well suited to an interactive shell. A short pipeline is easier to reason about when input can reach its consumer and component failures remain visible afterward. In this January release, those behaviors are available in a beta build, so the prerelease status is part of the version being discussed.