Luke Oliff.

TIL: Debugging Pipelines With the tee Command

·TIL·3 min read·Luke Oliff

How do you see what’s happening in the middle of a pipeline without breaking it? tee.

curl -s https://api.example.com/v1/models | tee models-raw.json | jq '.data[] | {id, status}'

tee reads from stdin and writes to stdout AND one or more files. The pipeline keeps running. You get the filtered output AND a saved copy of the raw response.

Instead of rerunning the request or commenting out half the pipe, add tee filename wherever you need a snapshot.

The pattern I use most

For API debugging:

curl -s "https://api.deepgram.com/v1/projects/$PROJECT_ID/requests?limit=50" \
  -H "Authorization: Token $DEEPGRAM_API_KEY" \
  | tee raw-response.json \
  | jq -r '.requests[] | "\(.created): \(.status) \(.path)"'

This saves the full API response to raw-response.json while piping a filtered view to stdout. If the output looks wrong, you open the saved file and inspect the full response structure without calling the API again.

The -a flag appends instead of overwriting, which is useful for logging across multiple requests in a loop:

for id in $(cat model-ids.txt); do
  curl -s "https://api.example.com/status/$id" | tee -a status-log.json | jq '.name'
done

Why this beats rerunning

Every API call is a different moment in time. A cached or rate-limited response might not reproduce the same result. Saving the actual response that produced your filtered output gives you a forensic record of exactly what the API returned when you asked.

tee has been in Unix since the 1970s. It’s in every shell, every CI image, every Docker container. No install step. It’s just there.

FAQ

What does the tee command do?

tee reads from standard input and writes to standard output and one or more files simultaneously. It splits the data stream so you can inspect intermediate results, log output for later analysis, or duplicate a pipeline without restarting it.

When would I use tee instead of redirect?

Use redirect (>) when you only need the output saved to a file and don’t need to see it on screen. Use tee when you want both: the output on screen AND saved to a file. tee is for debugging and logging mid-pipeline, not for final output capture.

Can tee handle binary data?

Yes. tee works at the byte level and handles binary data without corruption. It doesn’t interpret the stream, it just copies it. Use it to capture raw audio files mid-pipeline when testing streaming transcription workflows.