Simple developer documentation for the current state of the project.
I own the implementation of a custom AI Agent CLI with the following design:
- Accepts coding tasks — You give the agent a task (e.g. “find all Python files in this folder” or “summarize the layout of the project”).
- Uses predefined functions — The agent chooses from a fixed set of tools, such as:
- Scanning/list files in a directory (e.g.
get_files_info), - Reading file content with truncation (e.g.
get_file_content), - and other functions as they are added.
- Scanning/list files in a directory (e.g.
- Runs until done or stopped — The agent calls the Gemini API, selects functions, runs them, and repeats until the task is complete or the run is interrupted/fails.
- Powered by Gemini API — All reasoning and tool choice go through Google’s Gemini model.
The code in this repository is my implementation of that agent and its tools. The calculator directory is an example code repo that runs on this CLI (code the agent can work with, run, or reason about). The file-scanning utility and other predefined functions are tools the agent uses; both are documented below.
This repo currently contains:
- Agent CLI (
main.py) — Entrypoint that talks to the Gemini API. Implements the full agent loop: accept task → Gemini chooses a tool → execute → append result → repeat until a final text response orMAX_ITERSis reached. - Example code repo — Calculator (
calculator/) — An example codebase that runs on this CLI. The agent can run it, inspect it, or perform coding tasks against it (e.g. run tests, modify code). It provides a small infix calculator CLI and JSON output. - Predefined tools — Implemented for the agent to call:
- Directory listing (
functions/get_files_info.py) —get_files_info: lists directory contents (names, sizes, is_dir) with path-safety so the agent cannot escape the allowed working directory. - File content (
functions/get_file_content.py) —get_file_content: reads file content up to a character limit (CHARACTER_LIMITinconfig.py), with a truncation message when the file exceeds it. - Write file (
functions/write_file.py) —write_file: writes or overwrites a file inside the working directory; creates parent directories as needed. - Run Python (
functions/run_python_file.py) —run_python_file: executes a Python file via subprocess, captures stdout/stderr, and enforces the working-directory boundary.
- Directory listing (
Python 3.13+, managed with uv (see pyproject.toml and uv.lock).
ai-agent/
├── main.py # AI Agent CLI entrypoint (Gemini API)
├── call_functions.py # Tool declarations + dispatcher for Gemini API
├── config.py # Constants: CHARACTER_LIMIT, MAX_ITERS
├── prompts.py # System prompt string(s)
├── pyproject.toml # Project metadata and dependencies
├── pyrightconfig.json # Type-checker extra paths
├── .env # GEMINI_API_KEY (not committed)
├── .gitignore
│
├── test_get_files_info.py # Tests for get_files_info
├── test_get_file_content.py # Tests for get_file_content
├── test_write_file.py # Tests for write_file
├── test_run_python_file.py # Tests for run_python_file
│
├── calculator/ # Example code repo (runs on this CLI)
│ ├── main.py # CLI: expression from argv → JSON result
│ ├── tests.py # unittest for Calculator
│ └── pkg/
│ ├── calculator.py # Infix expression evaluator (+, -, *, /)
│ └── render.py # JSON formatting of expression + result
│
└── functions/
├── get_files_info.py # List dir contents; respects working dir boundary
├── get_file_content.py # Read file content with truncation; path-safe
├── write_file.py # Write/overwrite file; creates parent dirs
└── run_python_file.py # Execute a Python file; captures stdout/stderr
-
Environment
- Create a venv (e.g.
uv venv→.venv) and install:
uv sync - Copy or create
.envwith:GEMINI_API_KEY— required formain.py(Gemini client).
- Create a venv (e.g.
-
Dependencies (from
pyproject.toml)google-genai— Gemini API clientpython-dotenv— load.envformain.py
Optional: use the project’s
.venv(ignored by git).
-
Gemini CLI (from repo root):
python main.py "Your prompt here" python main.py "Your prompt" --verbose # show token usage
-
Calculator — Example code repo that runs on this CLI (from repo root):
python calculator/main.py "3 + 5" python calculator/main.py "2 * 3 - 8 / 2 + 5"
Output is JSON:
{"expression": "...", "result": <number>}. The agent can execute this code or work on it as part of a coding task. -
Directory listing (programmatic):
get_files_info(working_directory, directory=".")- Returns a string of lines:
name : file_size=<bytes>, is_dir=<bool>. - Restricts listing to paths under
working_directory; raises ifdirectoryis outside it or not a directory.
-
File content (programmatic):
get_file_content(working_directory, file_path)- Returns file content up to
CHARACTER_LIMITcharacters; appends a truncation message if the file is longer. - Path must be under
working_directory; raises if outside, not found, or not a regular file.
-
Calculator (from repo root):
python -m pytest calculator/tests.py -v # or python calculator/tests.pyCovers: addition, subtraction, multiplication, division, operator precedence, empty expression, invalid operator, and not enough operands.
-
get_files_info (from repo root):
python -m pytest test_get_files_info.py -v # or python test_get_files_info.pyCovers: current dir, subdir (
pkg), and rejection of/binand../(outside permitted working directory); nonexistent path and file-as-path raise. -
get_file_content (from repo root):
python -m pytest test_get_file_content.py -v # or python test_get_file_content.pyCovers: truncation when file exceeds limit, short file and nested path return content below limit, path outside working directory raises, file not found raises.
-
write_file (from repo root):
python -m pytest test_write_file.py -v # or python test_write_file.pyCovers: write to file in root of working directory, write to nested path (creates parent dirs), path outside working directory raises.
-
run_python_file (from repo root):
python -m pytest test_run_python_file.py -v # or python test_run_python_file.pyCovers: no-args run (usage message), run with expression argument, run test suite, path outside working directory raises, non-existent file raises, non-Python file raises.
-
Calculator (example code repo)
- Tokenizes on spaces; supports
+,-,*,/with standard precedence (*, / over +, -). - Uses a stack-based infix evaluator; raises
ValueErroron invalid tokens or malformed expressions. - Lives under
calculator/as the example codebase that runs on the CLI.
- Tokenizes on spaces; supports
-
get_files_info
- Takes absolute/normalized paths and ensures the target directory is under
working_directory(no escaping outside the allowed root). - Returns a string of entry lines; errors are raised as exceptions. Skips
.and..in the listing.
- Takes absolute/normalized paths and ensures the target directory is under
-
get_file_content
- Resolves
file_pathunderworking_directory, reads up toCHARACTER_LIMITcharacters, and appends a truncation message if the file is longer. - Raises if the path is outside the working directory, the file is not found, or it is not a regular file.
- Resolves
-
write_file
- Resolves
file_pathunderworking_directory; rejects paths that escape it. - Calls
os.makedirsto create missing parent directories before writing. - Raises if the target path is a directory; always appends a trailing newline.
- Resolves
-
run_python_file
- Resolves
file_pathunderworking_directory; rejects paths outside it and non-.pyfiles. - Runs via
subprocess.runwith a 30-second timeout,cwdset toworking_directory_abs. - Returns a string combining exit code (if non-zero), stdout, and stderr.
- Resolves
-
Type checking
pyrightconfig.jsonsetsextraPaths: ["."]so imports likecalculator.pkg,functions.get_files_info, andfunctions.get_file_contentresolve from the project root.
| Area | Status |
|---|---|
| Agent vision | Custom AI Agent CLI: accept coding task → choose predefined functions (e.g. scan files) → run until complete or interrupted; Gemini API. |
| Agent entrypoint | main.py — Gemini client + full agent loop (tool choice → execute → repeat, up to MAX_ITERS) implemented and working. |
| Predefined tools | get_files_info, get_file_content, write_file, run_python_file — all implemented, tested, and path-safe. |
| Example code repo | calculator/ — Example codebase that runs on the CLI; agent can run/inspect it. |
| Packaging | pyproject.toml + uv.lock; no scripts entrypoints. |
No web UI or long-running services; everything is CLI or library-style.