Skip to content
jifengwu2kPublic

About

A Python 2.7+ REPL for interacting with LLMs with an OpenAI Chat Completions-compatible API.

Resources

Stars

8 stars

Watchers

1 watching

Forks

Latest commit

 

History

16 Commits

Folders and files

Repository files navigation

chatrepl

A minimal agent for OpenAI-compatible Chat Completions APIs with four built-in tools:

  • read
  • write
  • edit
  • shell

Features

  • Interactive Python-powered REPL
  • Python 2.7+ and Python 3 compatible
  • Works with OpenAI-compatible /chat/completions endpoints
  • Discovery of AGENTS.md and CLAUDE.md under the current working directory
  • Streaming assistant responses
  • Reasoning deltas streamed inline as [reasoning] sections when the provider reports them
  • Editable multiline input through your editor
  • Non-interactive CLI mode for piped input or one-shot prompts
  • --debug flag to print tool call deltas as they stream in

Installation

pip install chatrepl

Usage

CLI options

-k, --api-key           API key for the OpenAI-compatible endpoint
-u, --base-url          Base URL, e.g. http://localhost:11434/v1
-m, --model             Model ID
--no-stream             Disable streaming
--no-context-files      Disable AGENTS.md and CLAUDE.md discovery
--debug                 Print tool call deltas as they stream in

Interactive REPL

chatrepl \
  --api-key "your-api-key" \
  --base-url "https://api.openai.com/v1" \
  --model "gpt-5.4"

You enter a Python interactive console with helper functions preloaded.

Available commands:

Function Description
send(text='', image_path=None, stream=True) Send a message and let the agent complete tool calls, optionally with a local image path used as-is and streaming control
send(...) with reasoning When the provider streams reasoning content, it is printed under a [reasoning] header before the final text
append(text) Append a user message without sending
multiline() Append multiline input from your editor
txt(path) Append a UTF-8 text file as a user message using the provided path as-is
img(path) Append a local image as a user message; files are embedded as data URLs using the provided path as-is
reset() Reset to only the system prompt
save(path) Save the current conversation transcript as a JSON messages file
load(path) Load a saved JSON transcript and append it to the current conversation

Exit with exit() or EOF.

One-shot prompt

chatrepl \
  --api-key "your-api-key" \
  --base-url "https://api.openai.com/v1" \
  --model "gpt-4o" \
  "Inspect this repository and summarize the build system"

Piped input

cat prompt.txt | chatrepl \
  --api-key "your-api-key" \
  --base-url "https://api.openai.com/v1" \
  --model "gpt-4o"

Tool model

The agent is intentionally small and constrained.

read

Reads a text file with optional offset and limit arguments.

  • Uses the provided path as-is

write

Writes full file contents.

  • Creates parent directories automatically
  • Rewrites the destination file completely

edit

Applies exact text replacements to an existing file.

Rules:

  • each oldText must match exactly once
  • edits must not overlap
  • all edits are matched against the original file

Returns a unified diff after a successful edit.

shell

Runs a shell command in the current working directory.

  • live output is streamed to the terminal
  • stdout and stderr remain separate in the terminal and are returned to the model in labeled sections

Example session

Turn 1: appended user message, then send with no new text

This is useful because it exercises the path where send() is called with no pending user message.

>>> append("Reply with exactly APPENDED-OK.")
>>> send(stream=False)

Assistant response:

APPENDED-OK

Turn 2: streamed text + streamed tool-call deltas + follow-up tool result

>>> send("Read hello.txt and quote its contents back to me.", stream=True)

Mock streamed assistant output:

I’ll inspect the file.
[assistant is preparing tool call(s)]
[tool_call 0]
id: call_read_1
type: function
name += re
name += ad
arguments += {"path":"he
arguments += llo.txt"}

Then tool execution:

[assistant is using 1 tool(s)]

[tool read]
Hello!

Then assistant follow-up response:

The file contains `Hello!`.

Turn 3: multiple tool calls in one assistant message

This exercises:

  • multiple tool calls
  • write
  • edit
  • read
  • diff generation
  • tool index tracking in streaming
>>> send("Create tmp/demo.txt with alpha and beta on separate lines, change beta to gamma, then read it back.", stream=True)

Mock streamed assistant output:

I’ll create the file, patch it, and verify the result.
[assistant is preparing tool call(s)]
[tool_call 0]
id: call_write_1
type: function
name += wr
name += ite
arguments += {"path":"tmp/demo.txt","content":"alpha\nbeta\n"}
[tool_call 1]
id: call_edit_1
type: function
name += ed
name += it
arguments += {"path":"tmp/demo.txt","edits":[{"oldText":"beta","newText":"gamma"}]}
[tool_call 2]
id: call_read_2
type: function
name += read
arguments += {"path":"tmp/demo.txt"}

Then tool execution:

[assistant is using 3 tool(s)]

[tool write]
Successfully wrote 11 characters to <repo>/tmp/demo.txt

[tool edit]
Applied 1 edit(s) to <repo>/tmp/demo.txt

--- <repo>/tmp/demo.txt
+++ <repo>/tmp/demo.txt
@@
-alpha
-beta
+alpha
+gamma

[tool read]
alpha
gamma

Then assistant follow-up:

Done. `tmp/demo.txt` now contains:

- alpha
- gamma

Turn 4: shell tool, stdout + stderr, non-streaming

>>> send("Run a shell command that prints one line to stdout and one to stderr.", stream=False)

Assistant response with tool call:

I’ll run a small shell command.

Then tool execution:

[assistant is using 1 tool(s)]

[tool shell]
$ printf 'stdout-line\n'; printf 'stderr-line\n' >&2
Exit code: 0

stdout:
stdout-line


stderr:
stderr-line

Then assistant follow-up:

The shell command succeeded and produced both stdout and stderr output.

License

This project is licensed under the MIT License.

About

A Python 2.7+ REPL for interacting with LLMs with an OpenAI Chat Completions-compatible API.

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages