← All one-liners·#022·synthesis·llm cli·power

Schema-validated LLM output with claude --json-schema

Pipe Reddit/HN/anything into claude with a strict JSON Schema — server-side validates the output shape. Downstream jq can trust every field.

Setup
  • → claude /login OR export ANTHROPIC_API_KEY=sk-…
Cost per run
<$0.01
The one-liner
$ curl -s -A "oneliner101/1.0" \
     "https://www.reddit.com/r/LocalLLaMA/top.json?limit=20&t=day" \
  | jq -r '.data.children[].data | "- [\(.score)] \(.title)"' \
  | claude -p \
      --output-format json \
      --json-schema '{
        "type":"object",
        "required":["theme","sentiment","top_post"],
        "properties":{
          "theme":{"type":"string"},
          "sentiment":{"type":"string","enum":["bullish","bearish","mixed"]},
          "top_post":{"type":"string"}
        }
      }' \
      "Summarize these posts: theme (one phrase), sentiment, top_post." \
  | jq -r '.result'
What each stage does
  1. [01] curlcurl … reddit.com/r/LocalLLaMA/top.json …
    Reddit JSON, custom User-Agent required.
  2. [02] jqjq -r '… | "- [\(.score)] \(.title)"'
    Tight prompt input — one '[score] title' line per post.
  3. [03] claudeclaude -p --output-format json
    Returns a JSON envelope with .result, .session_id, .duration_ms, .usage. Pair with --json-schema or it's just stringified text inside.
  4. [04] claude--json-schema '{ "type":"object", … }'
    Server-side validation. Claude's response is constrained to match — invalid shapes fail at the API, not in your shell. Downstream jq can trust every field exists.
  5. [05] jqjq -r '.result'
    Extract the validated payload from the envelope. .result is now guaranteed to match your schema.
Expected output (sample)
{
  "theme": "agentic-RAG with hybrid retrieval",
  "sentiment": "bullish",
  "top_post": "Llama 4 70B released, here are the first benchmarks"
}
Caveats & tips
  • Both --output-format json AND --json-schema are required together. Without --output-format, the schema is ignored.
  • Schema enforcement is strict — extra fields cause an error. Use `additionalProperties: false` defensively.
  • Pipe straight into a database INSERT, a webhook, or a typed config — no defensive parsing.