Shell tasks with the celeris CLI
The shell is where latency pays off most. A command that answers in a few
hundred milliseconds feels like part of the pipeline; a command that takes
five seconds breaks your flow, and a per-line loop over a thousand lines
becomes lunch. Celeris-1 returns small completions fast enough that semantic
operations (classify, extract, rewrite, summarize) can sit inside ordinary
shell one-liners next to grep and jq.
celeris is the official CLI. It reads stdin, writes plain text to stdout,
streams by default where it helps, and keeps diagnostics on stderr, so it
composes with pipes the way you expect.
Setup
brew install ai-celeris/tools/celeris
export CELERIS_API_KEY="<your-api-key>"
The CLI uses the global production endpoint by default. Set
CELERIS_BASE_URL only to override it; unlike the SDK examples, the CLI
expects that override without /v1.
The quick command is celeris q: arguments form the instruction, piped
stdin is appended as context, and the answer streams back as plain text.
celeris q "Reply with one word: the capital of France."
Paris
Every recipe below also works with the full-fidelity form,
celeris chat:completions create --format json, when you want the whole
response object. q defaults to max_tokens=256; see the
latency guide before increasing it.
Commit messages from the staged diff
git diff --staged | celeris q "Write a one-line conventional commit message for this diff. Reply with only the message."
Wrap it in a function and it becomes a habit:
gcm() {
git commit -m "$(git diff --staged | celeris q 'Write a one-line conventional commit message for this diff. Reply with only the message.')" -e
}
The -e flag opens the proposed message in your editor, so you approve
every commit rather than trusting the model blindly.
Log triage
Summarize the interesting part of a noisy log:
tail -200 app.log | celeris q "List the distinct errors in this log, one per line, most frequent first. Ignore INFO lines."
Classify records one at a time when you need a per-line verdict. At sub-second latency a serial loop over a few hundred lines is a coffee sip, not a batch job:
grep ERROR app.log | sort -u | while IFS= read -r line; do
verdict=$(printf '%s' "$line" | celeris q "Is this error caused by user input, our code, or a dependency? Reply with exactly one word: user, code, or dependency.")
printf '%s\t%s\n' "$verdict" "$line"
done | sort
Semantic filtering
grep matches strings; sometimes you need to match meaning. Keep the answer
contract tiny (one word) and filter on it:
cat feedback.txt | while IFS= read -r item; do
ans=$(printf '%s' "$item" | celeris q "Is this feedback about pricing or billing? Reply yes or no only.")
[ "$ans" = "yes" ] && printf '%s\n' "$item"
done
Extraction into jq
Ask for JSON only and pipe straight into jq. Temperature 0 and a seed keep
reruns stable:
cat order-email.txt | celeris q --temperature 0 --seed 7 \
"Extract items, quantities, and the delivery date from this email as JSON with keys items (array of {name, qty}) and delivery_date. Reply with JSON only." \
| jq '.items[].name'
If the model ever wraps the JSON in prose, tighten the prompt ("Reply with
JSON only, no code fences") or switch to
celeris chat:completions create --format json and extract
.choices[0].message.content with jq -r before parsing.
Quick transforms
Anything you would paste into a browser chat fits better in the pipe you are already standing in:
# Explain a cron expression before you deploy it.
echo "17 3 * * 1-5" | celeris q "Explain this cron schedule in one sentence."
# Turn a curl command into equivalent Python.
pbpaste | celeris q "Rewrite this curl command as Python requests code. Reply with code only."
# Bulk-rename messy filenames without writing the sed by hand.
ls *.MOV | celeris q "Write mv commands that rename these files to lowercase kebab-case, keeping the extension. Reply with the commands only."
Scripting patterns
A few conventions make the CLI dependable inside scripts:
- Pin the sampling.
--temperature 0 --seed 7makes reruns repeatable in the common case, which matters once output feedsjqor a test. - Demand a format. End prompts with "Reply with only X". Small answer contracts keep fast responses fast, and they make parsing trivial.
- Check exit codes.
celerisexits 0 on success, 1 when the request or API fails, and 2 on a bad invocation, and errors go to stderr, soset -epipelines andif celeris q ...; thenbehave correctly. - Budget tokens. Loops multiply cost and latency.
qdefaults to--max-tokens 256, the smallest step the API accepts; keep it there unless the answer genuinely needs more room. - Mind rate limits. Workspace tiers cap sustained request rate. For big
loops add a small
sleepbetween calls, and see the latency guide before parallelizing withxargs -P.
Runnable source for this example: guides in the celeris-cookbook repository.