Useful ToolsDiff Writer
DocsUseful ToolsDiff Writer

DiffWriter

Human-in-the-loop file writing with diff display and approval.

Installation

main.py
from connectonion import DiffWriter writer = DiffWriter()

Want to customize? Run co copy diff_writer to get an editable copy.

API

write(agent, path, content)

Write content to a file with diff display and user approval. agent is injected automatically when this is used as an agent tool — the LLM never sees that parameter.

main.py
result = writer.write(agent, "hello.py", "print('hello')") # Sends a diff preview + approval prompt over agent.io (WebSocket) # If no io channel is attached, auto-approves and writes immediately # Returns: "Wrote 15 bytes to hello.py" or a rejection + feedback message

diff(path, content)

Show diff without writing (preview mode).

main.py
diff_text = writer.diff("hello.py", "print('hello')") # Returns the diff string without writing

read(path)

Read file contents.

main.py
content = writer.read("hello.py") # Returns: "print('hello')"

Approval Options

When a file change is proposed in mode="normal", DiffWriter sends a diff preview and an approval question over agent.io (a WebSocket channel) — there's no built-in terminal prompt. The frontend renders whatever UI it wants around these three options:

OptionEffect
"Yes, apply this change"Apply this change, ask again for next change
"Yes to all (auto-approve)"Apply this and switch to auto mode for the rest of the session
"No, reject and give feedback"Reject + provide feedback for agent to try again

If no io channel is attached (e.g. running outside a hosted/web session), the write is auto-approved without prompting.

Modes

mode

Three permission modes, like Claude Code's Shift+Tab cycle.

main.py
# Prompt for every edit (default) writer = DiffWriter(mode="normal") # Auto-approve all writes, no prompting writer = DiffWriter(mode="auto") # Read-only: preview what would happen, never write writer = DiffWriter(mode="plan") # Also configurable: preview_limit (max chars in diff preview, default 2000) writer = DiffWriter(mode="normal", preview_limit=5000)

Use with Agent

main.py
from connectonion import Agent, DiffWriter writer = DiffWriter() # mode="normal" by default agent = Agent("coder", tools=[writer]) agent.input("create a hello.py file with a hello world function") # Agent calls write(agent, path, content) — the tool executor injects "agent" # User sees a diff preview and approves, auto-approves, or rejects with feedback

Feedback Flow

When the user rejects a change:

  1. User is asked: "What should the agent do instead for hello.py?"
  2. User types feedback, e.g., "use snake_case for function names"
  3. Agent receives: "User rejected changes to hello.py. Feedback: use snake_case for function names"
  4. Agent can retry with the feedback

Common Use Cases

main.py
# Interactive coding with approval writer = DiffWriter(mode="normal") agent = Agent("coder", tools=[writer]) # CI/CD automation - skip prompts writer = DiffWriter(mode="auto") agent = Agent("automation", tools=[writer]) # Preview changes only, no writes diff = writer.diff("config.py", new_config) print(diff)

Customizing

Need to modify DiffWriter's behavior? Copy the source to your project:

code
co copy diff_writer

Then import from your local copy:

main.py
# from connectonion import DiffWriter # Before from tools.diff_writer import DiffWriter # After - customize freely!

Star us on GitHub

If ConnectOnion saves you time, a ⭐ goes a long way — and earns you a coffee chat with our founder.