Tool Surfaces for Coding (Read, Edit, Bash)
The minimum tools a code agent needs: read file, edit file, run shell, run tests.
Tool Surfaces for Coding (Read, Edit, Bash) is a free AI Agents lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AI Agents learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Tools Does a Code Agent Need?
The minimum:
- read_file — see code
- edit_file / write_file — change code
- bash — run shell commands (tests, builds)
- search / grep — find code by string or symbol
read_file
def read_file(path: str, start_line: int = 0, end_line: int | None = None) -> str:
with open(path) as f:
lines = f.readlines()
return ''.join(lines[start_line:end_line])
# --- demo ---
with open('demo_source.py', 'w', encoding='utf-8') as f:
f.write('line0\nline1\nline2\nline3\nline4\n')
snippet = read_file('demo_source.py', start_line=1, end_line=3)
print('Lines 1-2 of demo_source.py:')
print(snippet)
Line-Range Reads Save Tokens
For large files, read only the relevant range. Massive token savings vs reading the entire file every call.
edit_file (String Replace)
Anthropic's str_replace pattern: find a unique string in a file and replace it:
def edit_file(path: str, old_string: str, new_string: str):
contents = read_file(path)
occurrences = contents.count(old_string)
if occurrences == 0:
raise ValueError('old_string not found')
if occurrences > 1:
raise ValueError('old_string is not unique')
contents = contents.replace(old_string, new_string)
with open(path, 'w') as f:
f.write(contents)Why String-Replace Over Diffs
- Simpler for the model than producing valid diff syntax
- Forces the model to look at REAL code (helps catch hallucinations)
- Errors on ambiguity
It's the format used by Claude Code.
write_file
For creating new files:
def write_file(path: str, content: str):
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, 'w') as f:
f.write(content)bash
Shell commands — for tests, builds, package installs:
def bash(command: str, timeout: int = 60) -> dict:
import subprocess
try:
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=timeout)
return {'stdout': result.stdout[-5000:], 'stderr': result.stderr[-5000:], 'exit_code': result.returncode}
except subprocess.TimeoutExpired:
return {'error': 'timeout', 'exit_code': -1}
# --- demo ---
result = bash("echo hello from the sandboxed shell")
print(f"exit_code={result['exit_code']}")
print(f"stdout={result['stdout'].strip()!r}")
Sandbox the Bash Tool
NEVER run bash on your host. Use Docker / Firecracker / E2B. (See the previous course on sandboxing.)
Truncate Long Output
Test failures can spew megabytes. Truncate to the last few KB — usually contains the actual error:
stderr = 'error line\n' * 1000
if len(stderr) > 5000:
stderr = '...[truncated]...' + stderr[-5000:]
print(f'Truncated stderr length: {len(stderr)}')search / grep
def grep(pattern: str, path: str = '.', file_glob: str = '**/*') -> list[str]:
matches = []
for f in glob(file_glob, recursive=True):
for i, line in enumerate(open(f)):
if re.search(pattern, line):
matches.append(f'{f}:{i+1}: {line.rstrip()}')
return matches[:50]list_files
def list_files(path: str = '.') -> list[str]:
return [p for p in glob(f'{path}/**', recursive=True) if os.path.isfile(p)][:200]Optional: AST Tools
For deeper code understanding:
def find_function(name: str, path: str):
tree = ast.parse(open(path).read())
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef) and node.name == name:
return ast.unparse(node)Tool Descriptions Matter Most Here
Code agents pick the wrong tool more than chat agents. Spend extra time on descriptions:
description='Edit a file by replacing a unique string. The old_string MUST appear exactly once in the file. Reads the file first to validate. Use this for any code change in an existing file.'That's the Whole Toolset
Read, edit, write, bash, grep, list. With these six tools, an agent can do almost any software engineering task. Add specialised tools only when measured benefit exists.
Edit Pattern
Why is "string-replace" edit safer than "send full file" edit?
Recap
Read, edit (str_replace), write, bash, grep, list. Six tools, properly described and sandboxed, are enough for almost any coding agent.
Frequently asked questions
Is the “Tool Surfaces for Coding (Read, Edit, Bash)” lesson free?
Yes — the full text of “Tool Surfaces for Coding (Read, Edit, Bash)” is free to read here on the web, and the AI Agents course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AI Agents course, upgrade to CoddyKit PRO.
What will I learn in “Tool Surfaces for Coding (Read, Edit, Bash)”?
The minimum tools a code agent needs: read file, edit file, run shell, run tests. You practise AI Agents with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start AI Agents?
No prior experience is required. AI Agents on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Tool Surfaces for Coding (Read, Edit, Bash)” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this AI Agents lesson?
Yes. Every AI Agents lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Agentic Patterns: Plan-Execute-Verify
- Tool Surfaces for Coding (Read, Edit, Bash)
- Iterative Self-Correction Loops
- SWE-Agent and OpenDevin Architectures