When a command fails, its last stderr line is a JSON error and it exits 1, with nothing on stdout. Logs can come before that line, so capture stderr and read the error with jq:
if ship pane send --pane "$PANE" "Continue" --key enter --wait 2>ship-error.log; then echo "Turn finished"else tail -n 1 ship-error.log | jq -r '.message, .caused_by.message'fiFor a pane blocked on permission, that prints:
nothing was sentpane pane:0371d3719292450397e5cd5c40295d25 is blocked on permissionFor send --wait, the outer message tells you whether the input went out:
nothing was sentmeans the command refused before writing.the input was sentmeans you shouldn't send it again, so read the pane or usepane wait.the input may have been sentmeans you should check the pane before you decide whether to retry.
The specific failure is under caused_by. Other command errors also have a category, such as .type.kind being not_found for a missing pane.
A mistyped flag or invalid argument keeps the argument parser's text and exits 2, with no JSON. ship config check is another exception. It prints its findings as text and exits 1 with no extra error line, and a valid config prints nothing and exits 0. --help and --version still exit 0.