Skip to main content

Code Editing

PraisonAI provides a powerful code editing module for AI-powered code manipulation, inspired by Kilo Code’s architecture.

Installation

The code editing module is included with PraisonAI:

Quick Start

SEARCH/REPLACE Diff Format

The code editing module uses a SEARCH/REPLACE diff format for precise code modifications:

Line Number Hints

For faster matching in large files, use line number hints:

Available Tools

code_read_file

Read file contents with optional line range:

code_write_file

Create or overwrite a file:
Writes are atomic — a mid-write interrupt leaves the original file untouched. See Crash-safe writes.

code_apply_diff

Apply SEARCH/REPLACE diffs:
Writes are atomic — a mid-write interrupt leaves the original file untouched. See Crash-safe writes.

code_search_replace

Apply multiple search/replace operations:
Writes are atomic — a mid-write interrupt leaves the original file untouched. See Crash-safe writes.

code_list_files

List files in a directory:

code_execute_command

Execute shell commands:
Commands run without a shell, so shell operators are rejected rather than passed through as literal arguments.
Unquoted >, >>, <, <<, |, ||, &&, ;, & or newlines return a failure without running anything. Backticks and $(…) are rejected even inside double quotes (only single quotes make them literal):
To redirect output, write output["stdout"] to a file in Python.
The child process gets the parent environment minus secret-looking variables — names (case-insensitive) ending in _KEY, or with an underscore-separated word equal to TOKEN, SECRET, PASSWORD, PASSWD, CREDENTIAL(S) or APIKEY (e.g. OPENAI_API_KEY, GITHUB_TOKEN, DB_PASSWORD). Allow specific names back in with a comma-separated list:
Variables passed via env={...} are always added on top. Your own Python process is unaffected.

code_run_python

Execute Python source in a subprocess (not a sandbox — the child inherits the current interpreter and environment). Source is passed as an argv list, so newlines, backslashes and quotes reach the child interpreter exactly as written, identically on POSIX and Windows.
Not a sandbox. Do not pass untrusted code from end users without isolating the host process (subprocess with setrlimit, container, or VM). See python_tools for the safer, already-timeout-boxed alternative for user-supplied code.

Using with Agents

The code tools can be used directly with PraisonAI agents:

Features

Fuzzy Matching

The diff application uses fuzzy matching with Levenshtein distance:

Indentation Preservation

The module automatically preserves indentation when applying diffs:

Workspace & Write Safety

Every file-modifying tool (code_apply_diff, code_search_replace, code_write_file, code_read_file, code_list_files, and the low-level append_to_file) is confined to the workspace root. Paths that resolve outside the workspace are rejected with "Path '<path>' is outside the workspace".
  • Default workspace is the current working directory. If you never call set_workspace(...), the tools confine writes and reads to cwd. Absolute paths outside cwd are rejected.
  • Explicit set_workspace(...) is still recommended — it makes the confinement boundary explicit and portable across working directories.
  • Protected-path check runs first. System paths (e.g. /etc/hosts, ~/.ssh/) are rejected even if they sit inside the workspace. See Protected Paths.
  • Gitignore Support: Respects .gitignore patterns for listing.
  • Access Control: Configurable file access rules.
Behaviour change (PraisonAI #3087, commit d1d0272). Before this fix, workspace confinement was silently skipped in apply_diff, search_replace, and append_to_file whenever no workspace was set. Agents could escape cwd via absolute paths like apply_diff("/etc/hosts", ...). After the fix, cwd is used as the default workspace and confinement is always enforced. If you relied on writing to absolute paths outside cwd without calling set_workspace(), call set_workspace(...) at the intended root instead.

Crash-safe writes

code_write_file, code_search_replace, and code_apply_diff write through a temp file + fsync + os.replace, so an interrupted write (cancellation, timeout, SIGTERM, disk-full) never leaves the target zero-byte or half-written — the original file stays intact until the atomic rename. Permission bits are preserved (a 0o755 script stays 0o755; a 0o600 .env stays 0o600 and its new content is never world-readable while the temp file exists). On POSIX, owner (uid/gid) is preserved best-effort when the process has privilege. Symlinks are written through (the link stays, its target gets the new content); read-only targets are refused with PermissionError instead of being replaced via inode swap.
The same atomic_write helper backs the multiedit tool — see MultiEdit → Safety Guarantees.
Behaviour change (PraisonAI PR #6205): before this release, these three tools used open(path, 'w'), which truncated the target on open. A mid-write interrupt lost the original content. The atomic temp-file + fsync + rename pattern now protects every write to the target file (optional backup=True copies are still written directly).

append_to_file

append_to_file is available as a low-level import: from praisonai.code.tools.write_file import append_to_file. An agent-tool wrapper (code_append_to_file) is not yet exported from praisonai.code.
Append content to a file (creates it if missing):
Returns {"success": bool, "path": str, "created": bool, "bytes_appended": int} on success, or {"success": False, "error": str} on failure.

Configuration

Set Workspace

Environment Variables

Module Structure