Here-documents let a Zsh script feed a readable multiline block to a command without keeping that text in a separate input file. They fit small generated messages, short configuration fragments, SQL batches, and templates that should stay visible inside the script.
The <<WORD redirection starts the block, and a later line containing only WORD ends it. An unquoted delimiter lets Zsh expand parameters and command substitutions inside the block, while a quoted delimiter leaves the document text literal.
The sample script uses one unquoted delimiter for an expanded message and one quoted delimiter for a literal template. Checking it with zsh -n catches mismatched delimiters before the script runs. Keep each closing delimiter alone on its line, because spaces or other characters after it prevent Zsh from finding the end of the block.
Related: How to create and run a Zsh script
Related: How to use variables in Zsh
Related: How to use parameter expansion in Zsh
Related: Use here-documents in Bash
#!/usr/bin/env zsh emulate -L zsh setopt err_exit recipient=operations cat <<MESSAGE To: $recipient Status: ready MESSAGE cat <<'LITERAL' Literal example: $recipient LITERAL
The first block uses <<MESSAGE, so $recipient expands. The second block uses <<'LITERAL', so the same text stays literal.
$ zsh -n heredoc-demo.zsh
No output means Zsh parsed the here-document delimiters and the rest of the script without a syntax error.
$ zsh heredoc-demo.zsh To: operations Status: ready Literal example: $recipient
cat <<EOF To: $recipient Status: ready EOF
cat <<'EOF' Literal example: $recipient EOF
Do not indent the closing delimiter with spaces. Zsh only treats a line containing the delimiter word itself as the end of a plain << here-document.
Zsh strips leading tabs with «-, but it does not strip spaces. Use plain « when an editor might convert tabs to spaces.
$ rm -f heredoc-demo.zsh