How to use the Apple Foundation Model from AWK

April 15, 2026 ยท View on GitHub

AWK can't do HTTP on its own - it was designed for text processing, not networking. The UNIX convention is to pair AWK with curl: curl handles transport, AWK parses the response. That's what every script in this guide does.

Runnable scripts + tests: Arthur-Ficial/apfel-guides-lab/scripts/awk.

Prerequisites

  • macOS 26+ Tahoe, Apple Silicon, Apple Intelligence enabled
  • brew install apfel jq (jq is only needed for the JSON-mode + tool-calling examples)
  • apfel --serve running (port 11434)
  • awk (ships with macOS)

1. One-shot

#!/usr/bin/env bash
set -euo pipefail

PROMPT="In one sentence, what is the Swift programming language?"
PAYLOAD=$(awk -v prompt="$PROMPT" 'BEGIN {
  gsub(/"/, "\\\"", prompt)
  printf "{\"model\":\"apple-foundationmodel\",\"messages\":[{\"role\":\"user\",\"content\":\"%s\"}],\"max_tokens\":80}", prompt
}')

curl -sS http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" -d "$PAYLOAD" \
  | awk 'BEGIN { RS="\"content\" :" } NR==2 {
      match(\$0, /"([^"\\]|\\.)*"/)
      s = substr(\$0, RSTART+1, RLENGTH-2)
      gsub(/\\n/, "\n", s); gsub(/\\"/, "\"", s); gsub(/\\\\/, "\\", s)
      print s
    }'

Real output:

Swift is a modern, open-source programming language developed by Apple for developing apps and systems across platforms, known for its safety, performance, and ease of use.

Lab script: 01_oneshot.sh.

2. Streaming

#!/usr/bin/env bash
set -euo pipefail

curl -sS -N http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"apple-foundationmodel","messages":[{"role":"user","content":"List three Apple silicon chips, one per line."}],"max_tokens":80,"stream":true}' \
  | awk '
      /^data: / {
        json = substr(\$0, 7)
        if (json == "[DONE]" || json == "") next
        if (match(json, /"content":"([^"\\]|\\.)*"/)) {
          s = substr(json, RSTART + 11, RLENGTH - 12)
          gsub(/\\n/, "\n", s); gsub(/\\"/, "\"", s); gsub(/\\\\/, "\\", s)
          printf "%s", s
          fflush()
        }
      }
      END { print "" }
    '

Real output:

Apple M1
Apple M1 Pro
Apple M1 Max

Lab script: 02_stream.sh.

3. JSON mode

AWK is not a JSON parser. It can extract the string content field well enough, but for real validation we hand off to jq:

PAYLOAD='{"model":"apple-foundationmodel","messages":[{"role":"user","content":"Return JSON with fields chip, year, cores. Describe the Apple M1 chip. Return ONLY JSON."}],"response_format":{"type":"json_object"},"max_tokens":120}'

curl -sS http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" -d "$PAYLOAD" \
  | awk 'BEGIN { RS="\"content\" :" } NR==2 {
      match(\$0, /"([^"\\]|\\.)*"/)
      s = substr(\$0, RSTART+1, RLENGTH-2)
      gsub(/\\n/, "\n", s); gsub(/\\"/, "\"", s); gsub(/\\\\/, "\\", s)
      print s
    }' \
  | sed -E 's/^```(json)?//; s/```$//' \
  | jq '.'

Real output:

{
  "chip": "Apple M1",
  "year": 2020,
  "cores": {
    "CPU": 8,
    "GPU": 8
  }
}

Lab script: 03_json.sh.

4. Error handling

Use AWK to extract the .error.message string from the JSON body after curl gives you the HTTP status:

tmp=$(mktemp)
status=$(curl -sS -o "$tmp" -w '%{http_code}' \
  http://localhost:11434/v1/embeddings \
  -H "Content-Type: application/json" \
  -d '{"model":"apple-foundationmodel","input":"apfel runs 100% on-device."}')

if [[ "$status" -ge 400 ]]; then
  msg=$(awk 'BEGIN { RS="\"message\" :" } NR==2 {
    match(\$0, /"([^"\\]|\\.)*"/)
    s = substr(\$0, RSTART+1, RLENGTH-2)
    gsub(/\\"/, "\"", s); gsub(/\\\\/, "\\", s)
    print s
  }' "$tmp")
  echo "Got expected error: HTTP $status - ${msg:-see response}"
fi
rm -f "$tmp"

Real output:

Got expected error: HTTP 501 - Embeddings not supported by Apple's on-device model.

Lab script: 04_errors.sh.

5. Tool calling (delegate to Bash)

Tool calling requires constructing nested JSON with escaped strings, modifying the conversation, and posting back - this is outside AWK's sweet spot. The idiomatic AWK solution is to delegate to the Bash tool-calling script:

#!/usr/bin/env bash
here=$(cd "$(dirname "\$0")" && pwd)
bash "$here/../bash-curl/05_tools.sh"

Real output:

The current temperature in Vienna is 14 degrees Celsius.

Lab script: 05_tools.sh. For tool-heavy code, reach for python.md or nodejs.md.

6. Real example - summarize stdin

AWK does what AWK is good at - text cleanup - then hands the clean text to apfel:

cleaned=$(awk '
  { sub(/^[[:space:]]+/, ""); sub(/[[:space:]]+$/, ""); gsub(/[[:space:]]+/, " ") }
  { print }
' | awk 'NF')

payload=$(jq -n --arg text "$cleaned" '{
  model:"apple-foundationmodel",
  messages:[
    {role:"system", content:"You are a concise summarizer. Reply with one short paragraph."},
    {role:"user", content:("Summarize:\n\n" + $text)}
  ],
  max_tokens:150
}')

curl -sS http://localhost:11434/v1/chat/completions \
  -H "Content-Type: application/json" -d "$payload" \
  | awk 'BEGIN { RS="\"content\" :" } NR==2 {
      match(\$0, /"([^"\\]|\\.)*"/)
      s = substr(\$0, RSTART+1, RLENGTH-2)
      gsub(/\\n/, "\n", s); gsub(/\\"/, "\"", s); gsub(/\\\\/, "\\", s)
      print s
    }'

Real output:

The Apple M1 chip, launched in November 2020, marked Apple's first ARM-based system-on-a-chip for Macs. This chip features an 8-core CPU with four performance and four efficiency cores, along with an integrated GPU capable of up to 8 cores. By consolidating the CPU, GPU, memory, and neural engine on a single die, the M1 chip achieved notable performance-per-watt improvements compared to its Intel counterparts.

Lab script: 06_example.sh.

Troubleshooting

  • AWK doesn't parse JSON - true, and we don't pretend it does. Use AWK for the content string extraction and delegate nested work to jq.
  • Escaped characters leaking through - order matters: unescape \\n first, then \\", then \\\\, as shown in the gsub chain.
  • macOS awk vs gawk - the scripts above use only POSIX AWK features that work with the system BSD awk.

Tested with

  • apfel v1.0.3 / macOS 26.3.1 Apple Silicon
  • BSD awk 20200816 (system) / jq 1.7 / curl
  • Date: 2026-04-16

Runnable tests: tests/test_awk.py.

See also

bash-curl.md, perl.md, zsh.md, apfel-guides-lab