llm-code is a small command-line coding agent built on top of
pydantic-ai.
The current goal is simple: run an agent from your terminal, let it inspect and modify files in the current project, and stream the model's response back to stdout.
Today, the CLI has two entry modes:
uv run llm_code "write hello world"
uv run llm_code- If you pass arguments, everything after
llm_codeis treated as one prompt string. - If you pass no prompt,
llm-codelaunches a small Textual TUI.
In CLI mode, the tool loads configuration, constructs an agent, and streams the result to the terminal.
The agent currently has access to a few local tools:
read: read a file or glob of files under the current working directorywrite: write a single file under the current working directorysearch: search files by regex, usingrgwhen available andgrepas a fallbackbash: execute a shell command in the current working directory
The codebase is deliberately split into a few small modules.
This is the CLI entrypoint.
It is responsible for:
- parsing the command line with
click - loading settings
- joining the remaining CLI arguments into a single prompt string
- launching the Textual TUI when no prompt is provided
- building the runtime agent
- streaming the final output to the terminal with
rich
This module contains the initial Textual interface.
Right now it is intentionally minimal:
- a read-only output area at the top
- a multiline prompt box at the bottom
Entersubmits the promptShift+Enterinserts a newline
This module handles configuration loading and precedence.
Current settings precedence is:
- built-in defaults
- user config from
XDG_CONFIG_HOME/llm_code/config.toml - fallback user config from
~/.config/llm_code/config.toml - nearest project config found by walking upward for
.config.yaml - environment variables
In other words, project config overrides user config, and environment variables override both.
At the moment, settings are modeled with a small pydantic model.
This module builds the pydantic_ai.Agent and registers its tools.
The agent currently uses:
- a fixed instruction string
- a configurable model name from settings
Thinking(effort="high")
It also contains the implementation details for the agent tools.
The current tools are local-first and cwd-scoped.
- file reads, writes, and searches are restricted to the current working directory
- absolute paths and
..traversal are rejected for file-oriented tools - search results are normalized back to relative paths
Tool summary:
read(path)- accepts a relative path or glob
- returns a mapping of file paths to file contents
write(path, content)- writes one file
- creates parent directories as needed
search(pattern, path=".", context_lines=2)- searches with
rg --jsonwhen available - falls back to
grep -R -n -E - returns grouped matches with a small numbered context snippet
- searches with
bash(command)- executes a shell command with
shell=True - returns
returncode,stdout, andstderr
- executes a shell command with
The bash tool is intentionally permissive right now and should be treated as unsafe.
Tests live in tests/.
Current coverage focuses on:
- settings precedence and config loading
- file tool behavior
- search behavior, including
rgfallback togrep - path safety for read/write/search
- bash command execution
Run tests with:
uv run pytestInstall dependencies:
uv sync --all-groupsRun the CLI:
uv run llm_code "summarize this repository"Run lint and tests:
uv run ruff check src tests
uv run pytestThis project is in an early, exploratory stage.
The current implementation is intentionally small so the core architecture is easy to change:
- simple CLI
- simple settings model
- one agent module
- local tools with lightweight tests
- improve the system prompt and overall agent behavior
- add better tool result formatting so prompts stay compact
- add truncation and size limits for large file reads and large search results
- add stdin and richer project-context input modes
- add better search filtering and more useful snippets
- add structured logging / execution traces for debugging agent runs
- add streaming or incremental feedback for long-running tool calls
- add approval flows for dangerous tool use
- add timeouts for shell execution
- add output truncation for shell execution
- add command allow/deny rules for shell execution
- add explicit approval before executing shell commands
- add sandboxing for shell commands
- add no-network execution mode for shell commands
- add stronger filesystem isolation beyond starting in the current working directory