stdin, stdout, and stderr
Behave like a Unix tool
Everything covered so far in this track has treated an LLM call as something a Python script or a web API makes. This module covers a third, very practical pattern: wiring a local model directly into ordinary shell pipelines, the same way you'd chain together grep, sort, and wc. To fit into that world cleanly, a CLI tool that calls an LLM needs to respect the same three channels every well-behaved Unix program uses. Standard input (stdin) is the channel data flows into the program through. Standard output (stdout) is where its actual, useful result goes. Standard error (stderr) is a separate channel reserved for warnings, progress messages, and diagnostics - kept apart specifically so it never gets mixed into the real output that a downstream command might be parsing. A program's numeric exit code (0 for success, nonzero for failure) tells the shell, and any script calling it, whether it actually succeeded.
$ git diff --cached | ai-summarize > commit-message.txt
$ cat commit-message.txt
Refactor payment retry logic to use exponential backoff.
In that example, ai-summarize reads the staged diff from stdin, writes only its finished summary to stdout (which gets redirected into a file), and would write anything else - like "loading model..." - to stderr instead, so it never contaminates the saved commit message. A well-designed tool like this should also reject an empty or suspiciously oversized input stream outright, and avoid popping up any interactive prompts when it detects its input is coming from a pipe rather than a live terminal - an interactive prompt in the middle of an automated pipeline just hangs forever waiting for a human who isn't there.
Tip: Keep stdout scrupulously machine-clean. A single decorative progress message accidentally mixed into what's supposed to be pure JSON output can silently break every downstream command in the pipeline that's expecting to parse valid JSON.