
Chat with OpenAI models through your own installed Codex CLI
Source:R/api_codex_cli.R
codex_cli_chat.Rdcodex_cli() runs the codex command line tool installed on your machine and
reads its JSON output back. It uses the login Codex already has, for example
a ChatGPT plan, or your OpenAI API key if you set .use_api_key = TRUE.
Usage
codex_cli_chat(
.llm,
.model = NULL,
.reasoning_effort = NULL,
.system_prompt_mode = "append",
.json_schema = NULL,
.cli_tools = FALSE,
.sandbox = "read-only",
.stateful = FALSE,
.session_id = NULL,
.use_api_key = FALSE,
.binary = "codex",
.verbose = FALSE,
.timeout = 300,
.stream = FALSE,
.dry_run = FALSE
)Arguments
- .llm
An
LLMMessageobject.- .model
Character; the model Codex should use. Default NULL uses the model Codex is configured with. The metadata reports the model only when you set one here, because Codex does not include it in its output.
- .reasoning_effort
Character; how much the model reasons before it answers: "minimal", "low", "medium", "high" or "xhigh". Default NULL uses Codex's own setting.
- .system_prompt_mode
One of "append" or "ignore". With "append" the message's system prompt is passed to Codex as developer instructions, next to Codex's own instructions. With "ignore" it is dropped.
- .json_schema
A schema to enforce an output structure; a list, or an ellmer type object. Passed to Codex's
--output-schemaflag.- .cli_tools
Logical; FALSE, the default, turns off Codex's shell, browser, plugin and web search tools, so the call behaves like an ordinary completion. TRUE hands over to Codex's own configuration.
- .sandbox
Character; what commands Codex runs may do when
.cli_tools = TRUE. "read-only" (the default) or "workspace-write", which lets Codex change files in the working directory.- .stateful
Logical; if TRUE, Codex keeps the conversation on its side. The first call sends the conversation and records the session id in the metadata; later calls resume that session and send only the newest user message instead of replaying the history. Default FALSE sends the whole conversation every time and saves no session files.
- .session_id
Character; resume this Codex session explicitly. Normally left NULL, because
.stateful = TRUEpicks the id up from the message history on its own.- .use_api_key
Logical; if TRUE, passes your
OPENAI_API_KEYto Codex, so the call is billed to your API key instead of the login Codex has. Default FALSE.- .binary
Character; the command to run, or a full path to it. Defaults to "codex", which is looked for on the PATH and then in the places the installers use. If R does not find it, set
options(tidyllm_codex_cli_path = "/path/to/codex")in your.Rprofile, or theTIDYLLM_CODEX_CLIenvironment variable.- .verbose
Logical; if TRUE, prints rate limit information after the response.
- .timeout
Integer; seconds to wait. On a stream this is the idle deadline between events rather than a total.
- .stream
Logical; if TRUE, prints each message as Codex finishes it. Codex sends whole messages, not word by word.
- .dry_run
Logical; if TRUE, returns the command that would be run instead of running it.
Details
Codex is an agent, not a plain completion endpoint. By default it can run
shell commands and use a browser. tidyllm turns those tools off unless you set
.cli_tools = TRUE, and even then Codex runs in its read-only sandbox unless
you choose another with .sandbox.
Codex adds its own instructions to every call, so even a one-line prompt sends about 12,000 input tokens. The token counts in the metadata include them.
Examples
if (FALSE) { # \dontrun{
llm_message("What is R's S7 class system?") |>
chat(codex_cli())
# Pay with your OpenAI API key instead of a ChatGPT login
llm_message("Explain vapply() in two sentences.") |>
chat(codex_cli(.use_api_key = TRUE, .reasoning_effort = "low"))
} # }