Prerequisites
Commands in this topic call an LLM provider, selected with --provider. The provider
is openai by default; claude is also supported. Each provider reads its own
API key from the environment:
OPENAI_API_KEYfor--provider openai(the default)ANTHROPIC_API_KEYfor--provider claude
When --model is omitted, each command uses the provider's default model: gpt-6-luna
for openai (gpt-image-1 for generate-image) and claude-sonnet-5-5
for claude. Pass --model to override.
Provider capabilities
Each command checks that the selected provider supports what it needs before any API key is read,
input file is opened, history is accessed or network call is made. An unsupported combination prints
an Error: message and exits with status 1.
| Capability | Commands | openai | claude |
|---|---|---|---|
| Text chat | chat, translate, corpospeak | Yes | Yes |
| Image input | ocaaar, paint | Yes | Yes |
| Image generation | generate-image | Yes | No |
| Tool calling | paint | Yes | Yes |
--reasoning-effort values | chat, paint | low, medium, high | low, medium, high, xhigh, max |
Session History
Every llm command automatically persists conversation history — including the system
prompt — to a shared SQLite database at ~/.pbtk/history.db. Each invocation creates a
new session and stores the full message exchange along with token usage counts.
Sessions are identified by an integer ID that is consistent across all commands, making it possible
to inspect history from chat, translate, ocaaar, and
corpospeak in a single unified view.
Use llm history list to see all sessions and
llm history delete to remove one.
chat
Sends a message to the LLM chat completion API and prints the response. Every invocation is recorded as a session in the history database. Ongoing conversations are resumed by passing the session ID returned from a previous call.
When --session-id is omitted a new session is created. When provided, all prior
messages from that session are loaded and prepended to the API request so the model has full
context. The session ID is always written to stderr after the call — capture it
to continue the conversation later.
translate) can be continued with
chat --session-id since all commands share the same history database. History is
provider-agnostic, so a session started with one --provider can be continued with the other.
| Option | Required | Default | Description |
|---|---|---|---|
--message | Yes | — | The user message to send |
--session-id | No | — | Session ID to continue a previous conversation |
--provider | No | openai | LLM provider: openai or claude |
--model | No | Provider default (gpt-6-luna or claude-sonnet-5-5) | Model to use |
--reasoning-effort | No | — | Reasoning effort level. Values depend on the provider: openai accepts low, medium, high; claude accepts low, medium, high, xhigh, max |
translate
Translates a given text into a specified target language using the LLM. The output is the translated text printed to stdout. Each invocation creates a new history session.
| Option | Required | Default | Description |
|---|---|---|---|
--text | Yes | — | The text to translate |
--target-language | Yes | — | Target language (e.g. Spanish, French, Japanese) |
--provider | No | openai | LLM provider: openai or claude |
--model | No | Provider default (gpt-6-luna or claude-sonnet-5-5) | Model to use |
ocaaar
OCR as a Pirate. Sends an image file to the LLM vision API, extracts any text found in the image, and returns it rewritten in pirate speak. Each invocation creates a new history session; the image is recorded as a reference path rather than binary data.
openai and claude support image input.
| Option | Required | Default | Description |
|---|---|---|---|
--image-path | Yes | — | Path to the image file to process |
--provider | No | openai | LLM provider: openai or claude |
--model | No | Provider default (gpt-6-luna or claude-sonnet-5-5) | Model to use (must support image input) |
corpospeak
Rewrites source text in the communication style appropriate for a chosen enterprise audience, optionally learning from example messages to match an individual's idiolect. Input can be a literal string or a file path. Each invocation creates a new history session.
Audiences
Executive language, strategic framing.
Technical, precise, low jargon.
User-focused, outcome-driven.
Value propositions, persuasive tone.
Brand voice, engaging copy.
Process-oriented, practical.
Metrics-focused, precise numbers.
Formal, risk-aware language.
People-centric, inclusive tone.
Empathetic, supportive language.
When --user-messages is provided, the examples are included in the prompt so the
model can infer and mimic the writer's personal style. Each value can be a literal string or
a path to a file containing example text. Multiple values are accepted.
| Option | Required | Default | Description |
|---|---|---|---|
--source | Yes | — | Source text to rewrite (or file path) |
--audience | Yes | — | Target audience slug (see list above) |
--user-messages | No | — | Example messages to learn idiolect from (text or file paths, repeatable) |
--provider | No | openai | LLM provider: openai or claude |
--model | No | Provider default (gpt-6-luna or claude-sonnet-5-5) | Model to use |
generate-image
Generates an image from a text prompt using the OpenAI image API (gpt-image-1 by default)
and writes it to the given file. Uses the OPENAI_API_KEY environment variable. This
command does not create a history session.
openai provider. --provider claude
is rejected before any work is done, for example:
Error: The 'generate-image' action requires image generation which is not supported by the 'claude' provider.
| Option | Required | Default | Description |
|---|---|---|---|
--prompt | Yes | — | Prompt describing the image to generate |
--out-file | Yes | — | Path to write the generated image to |
--provider | No | openai | LLM provider. Only openai supports image generation |
--model | No | Provider default (gpt-image-1 for openai) | Image model to use |
--overwrite | No | off | Replace --out-file if it already exists (otherwise the command fails) |
paint
The model paints a 256×256 full-colour canvas through tools in an agentic loop while the
terminal redraws it live. The canvas starts white. Each model turn can call the tools below, and
every write that changes pixels is shown on screen as it happens. Works with openai
(uses the OpenAI Responses API) and claude. Uses the OPENAI_API_KEY or
ANTHROPIC_API_KEY environment variable. This command does not create a history session.
The tools available to the model:
| Tool | Purpose |
|---|---|
read_canvas | Returns the full canvas as a PNG image |
read_region | Returns the exact hex colour values of a region (width and height up to 32) |
set_pixels | Sets individual pixels from a list of {x, y, color} entries (up to 4096 per call) |
fill_rect | Fills a rectangle with one colour |
draw_line | Draws a line between two points (thickness 1–16) |
fill_ellipse | Fills an ellipse given its centre and radii |
finish | Ends the run with a summary |
Colours are written as #RRGGBB. Coordinates start at the top-left corner, with x
increasing to the right and y increasing downwards. Invalid tool arguments are returned to the model
as an error result and the run continues.
The run ends when one of these happens:
- The model calls
finish. Any remaining tool calls in that response still run. - A model reply contains no tool calls.
- The
--max-stepslimit is reached. The command printsStep limit reached (N steps).
The output file is written when the run ends in any of these ways. If the provider returns an API error, or you press Ctrl+C, the command exits with status 1 and writes nothing. Ctrl+C restores the terminal and keeps the last frame on screen.
Pass --animation-out to also save an animated GIF of the painting. The first frame is the
blank canvas, and there is one more frame after every tool call that paints. Every frame is the full
256×256 canvas, whatever the size of the terminal. Each frame lasts 150 ms, the final frame is
held for 2 s, and the GIF loops forever. Runs keep at most 500 frames; longer runs keep every second
frame. Like the PNG, the GIF is written only when the run ends cleanly.
On an interactive terminal that supports truecolour, the display uses the alternate screen and repaints only the cells that changed. When the run ends, the final image is printed to the normal screen so it stays in your scrollback. When output is redirected, or the terminal does not support truecolour, the command falls back to Spectre rendering. Redirected output prints one line per tool call and the final image once.
| Option | Required | Default | Description |
|---|---|---|---|
--prompt | Yes | — | What to paint |
--provider | No | openai | LLM provider: openai or claude |
--model | No | Provider default (gpt-6-luna or claude-sonnet-5-5) | Model to use (must support tool calling and image input) |
--max-steps | No | 40 | Maximum number of model turns (1–200) |
--out-file | No | — | Write the final canvas to this PNG file |
--animation-out | No | — | Write an animated GIF of the painting to this file |
--overwrite | No | off | Replace --out-file or --animation-out if it already exists |
--reasoning-effort | No | — | Reasoning effort level. Values depend on the provider: openai accepts low, medium, high; claude accepts low, medium, high, xhigh, max |
--out-file or --animation-out already exists and --overwrite is
not given, the command stops before the first model call, for example:
Error: Output file already exists: <path>. Use --overwrite to replace it.
The two paths must differ: --out-file and --animation-out must be different paths.
history list
Prints a tabular summary of all stored sessions in reverse chronological order, showing the session ID, originating command, creation timestamp, and cumulative token usage.
Example output:
ID Command Created (UTC) Tokens (in/out) -------------------------------------------------------------------- 3 corpospeak 2026-05-28 14:30:00 200/90 2 translate 2026-05-28 11:15:00 80/35 1 chat 2026-05-28 09:00:00 350/120
The database file is at ~/.pbtk/history.db. It is created automatically on first use
and shared by all llm commands.
history delete
Deletes a session and all of its stored messages from the history database. This operation is permanent.
| Option | Required | Default | Description |
|---|---|---|---|
--session-id | Yes | — | ID of the session to delete |
Command Reference
| Command | Required options | Optional options | Output |
|---|---|---|---|
llm chat |
--message |
--session-id --provider --model --reasoning-effort |
Assistant reply to stdout; session ID to stderr |
llm translate |
--text --target-language |
--provider --model |
Translated text to stdout |
llm ocaaar |
--image-path |
--provider --model |
Pirate-speak OCR result to stdout |
llm corpospeak |
--source --audience |
--user-messages --provider --model |
Rewritten text to stdout |
llm generate-image |
--prompt --out-file |
--provider --model --overwrite |
Image file written to --out-file |
llm paint |
--prompt |
--provider --model --max-steps --out-file --animation-out --overwrite --reasoning-effort |
Live canvas on the terminal; final image to the normal screen, to --out-file if given, and an animated GIF to --animation-out if given |
llm history list |
— | — | Session table to stdout |
llm history delete |
--session-id |
— | Confirmation message to stdout |