Scripting Cecli

You can script cecli via the command line or python.

Command line

Cecli takes a --message argument, where you can give it a natural language instruction. It will do that one thing, apply the edits to the files and then exit. So you could do:

cecli --message "make a script that prints hello" hello.js

Or you can write simple shell scripts to apply the same instruction to many files:

for FILE in *.py ; do
    cecli --message "add descriptive docstrings to all the functions" $FILE
done

Note: --message (-m) and --message-file (-f) are one-shot.
Cecli sends the message, lets the model act on it, then exits. There is no
follow-up prompt in this mode, so an instruction that ends by asking you a
question has nowhere to collect your answer. Pass --yes for fully
non-interactive runs, or use one of the multi-turn routes below.

Use cecli --help to see all the command line options, but these are useful for scripting:

--stream, --no-stream
                      Enable/disable streaming responses (default: True) [env var:
                      CECLI_STREAM]
--message COMMAND, --msg COMMAND, -m COMMAND
                      Specify a single message to send GPT, process reply then exit
                      (disables chat mode) [env var: CECLI_MESSAGE]
--message-file MESSAGE_FILE, -f MESSAGE_FILE
                      Specify a file containing the message to send GPT, process reply,
                      then exit (disables chat mode) [env var: CECLI_MESSAGE_FILE]
--yes                 Always say yes to every confirmation [env var: CECLI_YES]
--auto-commits, --no-auto-commits
                      Enable/disable auto commit of GPT changes (default: True) [env var:
                      CECLI_AUTO_COMMITS]
--dirty-commits, --no-dirty-commits
                      Enable/disable commits when repo is found dirty (default: True) [env
                      var: CECLI_DIRTY_COMMITS]
--dry-run, --no-dry-run
                      Perform a dry run without modifying files (default: False) [env var:
                      CECLI_DRY_RUN]
--commit              Commit all pending changes with a suitable commit message, then exit
                      [env var: CECLI_COMMIT]

Multi-turn input

Run cecli without --message and it stays up for a back-and-forth session. Where
your input comes from depends on the mode:

  • TUI (tui: true, the default): type into the chat input box.
  • Non-TUI (--no-tui, or tui: false): input is read from stdin and
    re-prompted after every turn. Queued programmatic input is delivered too,
    even while the terminal prompt is open.
  • Programmatic: an external driver pushes {"text": ...} (and
    {"confirmed": ...} for confirmations) onto the coder’s input queue.
    The WebSocket/ACP server and the AgentService wake path use
    this route.

Both input paths consume the same per-coder queue. A queued payload is checked
before the terminal prompt and every 100 ms while the prompt is open, so a
driver can answer a prompt without a terminal. If no cancellable prompt session
is available (a dumb terminal, or when prompt_toolkit could not start), the
terminal read blocks and queued input is picked up at the next prompt instead.

{"confirmed": ...} accepts true/false, or one of the special responses
"never", "tweak", "all", and "skip".

Python

You can also script cecli from python:

from cecli.coders import Coder
from cecli.models import Model

# This is a list of files to add to the chat
fnames = ["greeting.py"]

model = Model("gpt-4-turbo")

# Create a coder object
coder = Coder.create(main_model=model, fnames=fnames)

# This will execute one instruction on those files and then return
coder.run("make a script that prints hello world")

# Send another instruction
coder.run("make it say goodbye")

# You can run in-chat "/" commands too
coder.run("/tokens")

See the Coder.create() and Coder.init() methods for all the supported arguments.

It can also be helpful to set the equivalent of --yes by doing this:

from cecli.io import InputOutput
io = InputOutput(yes=True)
# ...
coder = Coder.create(model=model, fnames=fnames, io=io)

Note: The python scripting API is not officially supported or documented, and could change in future releases without providing backwards compatibility.