div align"center"
A modular and scale coding agent architecture designed for on-device exec w/ local LLM models
/div
- Overview
- Features
- Project Structure
- install
- CLI Usage
- Plan Mode in CLI
- CLI Options Reference
- Quick Start
- Usage exs
- Plan Mode ex
- Plan Mode
- Available Tools
- File sys Tools
- Shell Process Tools
- Browser Automation Tools
- Messaging Integration Tools
- config
- Creating Custom Tools
- Design Principles
- reqs
- License
The Coding Agent is a , modular AI assistant designed to help w/ software dev tasks. It leverages local Large Language Models (LLMs) thru OpenAI-compatible APIs, enabling privacy-focused, offline-capable code gen, file manipulation, and task automation.
Built w/ clean architecture principles, the coding agent follows the ReAct pattern (Reasoning Acting) to plan and run complex dev tasks by combining LLM reasoning w/ practical tool exec.
- Code gen: Write new code files or funcs
- Code Analysis: Read and understand existing codebases
- Refactoring: Modify and improve existing code
- Testing: run code snippets and run tests
- File Management: Navigate, read, and modify project files
- Automation: run shell commands and scripts
| Feature | desc | | ** OpenAI-Compatible API** | Works w/ local models like Qwen2.5-Coder via Ollama, LM Studio, or any OpenAI-compatible endpoint | | ** Modular Tool sys** | Easy-to-extend architecture for adding custom tools and caps | | ** ReAct Pattern** | Advanced reasoning and acting loop for complex task completion | | ** Conversation History** | persist context across sessions for continuous workflows | | ** Well Documented** | complete docstrings follow Google Style Guide | | ** Clean Architecture** | KISS and DRY principles for maintainable code | | ** Privacy-1st** | Runs entirely locally w/ no external API deps req | | ** Type-Safe** | Full type hints throughout the codebase |
/workspace/
coding_agent/ # Main pkg dir
__init__.py # pkg init
README.md # pkg-specific documentation
reqs.txt # Python deps
config/ # config mods
__init__.py
settings.py # Agent settings and config
model_config.py # LLM model config
core/ # Core agent logic
__init__.py
agent.py # Main CodingAgent class
context.py # Conversation context management
llm/ # LLM client impl
__init__.py
client.py # OpenAI-compatible client
msg.py # msg and role definitions
tools/ # Tool implementations
__init__.py
base.py # Base tool classes and registry
filesystem.py # File sys ops
shell.py # Shell command exec
utils/ # Utility funcs
__init__.py
logging_config.py # Logging setup
exs/ # Usage exs
basic_usage.py # Interactive agent ex
custom_tools.py # Custom tool demonstration
README.md # This file - Project overview
- Python 3.10 recommended
- Local LLM (opt but recommended for offline use)
# mk and activate virtual env
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install directly from GitHub repo
pip install githttps://github.com/yourusername/coding-agent.git
# init curr dir
agent init
# Or init a specific dir
agent init /path/to/your/project
This creates:
.agent_config.json- config file for the agent.gitignore- Pre-configured to ignore agent history and cache files
Install Ollama for local model inference:
# Install Ollama (Linux/Mac)
curl -fsSL https://ollama.ai/install.sh | sh
# Pull a coding-optimized model
ollama pull qwen2.5-coder:7b
# Start Ollama server (usu auto-starts)
ollama serve
Alternative models you can use:
codellama:7b- General purpose coding modeldeepseek-coder:6.7b- Specialized for code genstarcoder2:7b- Multi-language code model
The coding agent provides a command-line iface for easy interaction.
# init curr dir
agent init
# init a specific dir
agent init /path/to/project
# Start chat in curr dir
agent chat
# Specify workspace dir
agent chat -w /path/to/project
# Use custom model config
agent chat --model codellama:7b --base-url http://localhost:11434/v1
# run a single task
agent run "List all Python files in the curr dir"
# w/ custom workspace
agent run "mk a README.md file" -w /path/to/project
| Command | desc |
| agent init [dir] | init a dir for use w/ the agent |
| agent chat | Start interactive chat session |
| agent run "command" | run a single command |
When using agent chat, you can use these special commands:
| Command | desc |
| /help | Show available commands |
| /clear | Clear conversation history |
| /tools | List available tools |
| /plan req | gen and run a plan for your req |
| /quit | Exit the chat session |
The /plan command in interactive chat allows you to gen, review, and run plans:
agent chat
/plan mk a Flask API w/ user auth
Generating plan...
Plan: mk Flask API w/ auth
1. [] mk project dir structure
2. [] Install Flask and deps
3. [] mk app.py w/ basic Flask setup
4. [] impl user registration endpoint
5. [] impl login/logout endpoints
6. [] Add password hashing w/ bcrypt
7. [] mk db models
8. [] Write basic tests
Select plan items to run (or press Enter to run all):
_
You can then select which steps to run by toggling them on/off b4 confirmation.
# 1. init a new project dir
agent init my-flask-app
cd my-flask-app
# 2. mk virtual env
python -m venv venv
source venv/bin/activate
# 3. Start interactive chat
agent chat --model qwen2.5-coder:7b
# In the chat session:
# mk a Flask app w/ a hello world endpoint
# Add a /users endpoint that returns a list of users
# /plan Add user auth w/ JWT tokens
# /quit
# 4. Or run a single command non-interactively
agent run "Add type hints to all funcs in app.py"
# Use OpenAI GPT-4
agent chat \
--base-url https://api.openai.com/v1 \
--api-key OPENAI_API_KEY \
--model gpt-4-turbo-preview
# Use Anthropic Claude via proxy
agent chat \
--base-url https://your-claude-proxy.com/v1 \
--api-key ANTHROPIC_API_KEY \
--model claude-3-opus-20240229
# Enable DEBUG logging to see detailed agent reasoning
agent chat --log-level DEBUG
# Logs will show:
# - LLM reqs and resps
# - Tool exec details
# - Agent decision-making process
| Option | desc | def |
| --base-url | LLM API base URL | http://localhost:11434/v1 |
| --api-key | LLM API key | ollama |
| --model | LLM model name | qwen2.5-coder:7b |
| --log-level | Logging level (DEBUG/INFO/warn/ERROR) | INFO |
| -w, --workspace | Workspace dir | curr dir |
You can configure defs using env vars:
export LLM_BASE_URLhttp://localhost:11434/v1
export LLM_API_KEYyour-api-key
export LLM_MODELqwen2.5-coder:7b
Here's a minimal ex to get started:
from coding_agent.config import ModelConfig, Settings
from coding_agent.core import CodingAgent
from coding_agent.tools import ReadFileTool, WriteFileTool, ListDirTool
from coding_agent.utils import setup_logging
# Setup logging
setup_logging(level"INFO")
# Configure settings
settings Settings(workspace_dir".")
# Configure model connection
model_config ModelConfig(
base_url"http://localhost:11434/v1", # Ollama def endpoint
api_key"ollama", # Dummy key for local models
model_name"qwen2.5-coder:7b", # Model to use
)
# mk and run agent
w/ CodingAgent(settingssettings, model_configmodel_config) as agent:
# Register tools
agent.register_tool(ReadFileTool())
agent.register_tool(WriteFileTool())
agent.register_tool(ListDirTool())
# Run a task
resp agent.run("List all Python files in the curr dir")
print(resp)
cd /workspace
python -m coding_agent.exs.basic_usage
This launches an interactive REPL where you can chat w/ the agent and give it tasks.
from coding_agent.core import CodingAgent
from coding_agent.tools import ReadFileTool, WriteFileTool
w/ CodingAgent() as agent:
agent.register_tool(ReadFileTool())
agent.register_tool(WriteFileTool())
# mk a new file
resp agent.run(
"mk a new Python file called 'hello.py' that prints 'Hello, World!'"
)
print(resp)
# Read the file to verify
resp agent.run("Read the contents of hello.py")
print(resp)
from coding_agent.tools import ReadFileTool, SearchFilesTool, ListDirTool
w/ CodingAgent() as agent:
agent.register_tool(ReadFileTool())
agent.register_tool(SearchFilesTool())
agent.register_tool(ListDirTool())
# Analyze project structure
resp agent.run(
"Find all Python files containing 'class' definition and summarize their purpose"
)
print(resp)
from coding_agent.tools import RunPythonTool, WriteFileTool
w/ CodingAgent() as agent:
agent.register_tool(RunPythonTool())
agent.register_tool(WriteFileTool())
# mk and test a func
resp agent.run(
"mk a func that calculates factorial, then test it w/ input 5"
)
print(resp)
from coding_agent.tools import RunCommandTool
w/ CodingAgent() as agent:
agent.register_tool(RunCommandTool())
# run git commands
resp agent.run(
"Check git status and show the last 5 commits"
)
print(resp)
from coding_agent.tools import StartProcessTool, ListProcessesTool, StopProcessTool
w/ CodingAgent() as agent:
agent.register_tool(StartProcessTool())
agent.register_tool(ListProcessesTool())
agent.register_tool(StopProcessTool())
# Start a web server in background
resp agent.run(
"Start a Python HTTP server on port 8000 in the background"
)
print(resp)
# List running processes
resp agent.run("List all running processes")
print(resp)
# Stop the server when done
resp agent.run("Stop the HTTP server process")
print(resp)
from coding_agent.tools import (
BrowserNavigateTool,
BrowserScreenshotTool,
BrowserGetContentTool
)
w/ CodingAgent() as agent:
agent.register_tool(BrowserNavigateTool())
agent.register_tool(BrowserScreenshotTool())
agent.register_tool(BrowserGetContentTool())
# Navigate and capture content
resp agent.run(
"Navigate to https://ex.com, take a screenshot, and extract the main content"
)
print(resp)
Plan Mode allows you to gen a detailed plan 1st, review and modify it, then run the approved steps:
from coding_agent.core import CodingAgent, PlanMode
from coding_agent.config import ModelConfig
from coding_agent.tools import ReadFileTool, WriteFileTool, RunCommandTool
# Setup
model_config ModelConfig(
base_url"http://localhost:11434/v1",
api_key"ollama",
model_name"qwen2.5-coder:7b"
)
w/ CodingAgent() as agent:
agent.register_tool(ReadFileTool())
agent.register_tool(WriteFileTool())
agent.register_tool(RunCommandTool())
# init plan mode
plan_mode PlanMode(model_config)
# gen a plan for a complex task
plan_request "mk a Python pkg w/ setup.py, README.md, and a basic mod structure"
# Get sys prompt and available tools
context agent.get_context()
system_prompt context.system_prompt
available_tools agent.tool_registry.get_all_schemas()
# gen plan
plan plan_mode.generate_plan(plan_request, system_prompt, available_tools)
# Review the plan
print(plan)
# Output:
# Plan: mk Python pkg Structure
# 1. [] mk dir structure: mypackage/__init__.py
# 2. [] mk setup.py w/ pkg metadata
# 3. [] mk README.md w/ project desc
# 4. [] mk ex mod file
# Enable/disable specific plan items as needed
plan_mode.toggle_plan_item(index2) # Disable README mk for now
# run the enabled plan items
enabled_items plan.get_enabled_items()
print(f"Executing {len(enabled_items)} steps...")
# Agent will run the enabled steps in sequence
for item in enabled_items:
resp agent.run(f"run: {item.desc}")
print(resp)
item.completed True
print("Plan exec complete!")
Plan Mode is a feature that separates planning from exec, giving you full control over complex tasks.
- gen Plan: The LLM analyzes your req and creates a structured plan w/ discrete steps
- Review Modify: You can review each step, enable/disable specific items, or reorder them
- run: Only the enabled steps are executed in sequence
- Track Progress: Each completed step is marked, allowing you to track progress
- Transparency: See exactly what the agent plans to do b4 it does it
- Control: Disable risky steps or reorganize the exec order
- Debugging: Easier to identify where things went wrong in a multi-step task
- Learning: Understand the agent's reasoning and decision-making process
The PlanMode class consists of:
Plan: Container for the plan title and list of itemsPlanItem: single step w/ desc, opt tool assignment, and enabled/completed statusgenerate_plan(): Creates a plan from user req using LLMtoggle_plan_item(): Enable/disable specific stepsget_current_plan(): Retrieve the active plan
Plan Mode is esp useful for:
- Complex multi-file refactoring tasks
- db migrations or schema changes
- Deployments w/ multiple steps
- Tasks requiring user approval at each stage
- Learning and understanding the agent's approach
The coding agent comes w/ a complete set of built-in tools organized into several categories:
| Tool | Class | desc |
| read_file | ReadFileTool | Read contents of a file w/ opt line range |
| write_file | WriteFileTool | Write content to a file (creates or overwrites) |
| list_dir | ListDirTool | List dir contents w/ file details (type, size, modified time) |
| search_files | SearchFilesTool | Search files by glob pattern (e.g., *.py, **/*.md) |
| get_tree | GetTreeTool | Get a tree view of dir structure |
| Tool | Class | desc |
| run_command | RunCommandTool | run shell commands safely w/in workspace |
| run_python | RunPythonTool | run Python code snippets in isolated env |
| start_process | StartProcessTool | Start a long-running process in the background |
| stop_process | StopProcessTool | Stop a previously started process by PID |
| list_processes | ListProcessesTool | List all processes started by the agent |
| get_process_info | GetProcessInfoTool | Get detailed info about a specific process |
| Tool | Class | desc |
| browser_navigate | BrowserNavigateTool | Navigate to a URL in a headless browser |
| browser_click | BrowserClickTool | Click on an element identified by CSS selector |
| browser_fill | BrowserFillTool | Fill a form field w/ text |
| browser_screenshot | BrowserScreenshotTool | Take a screenshot of the curr page |
| browser_get_content | BrowserGetContentTool | Extract text content from the curr page |
| browser_evaluate | BrowserEvaluateTool | run JavaScript in the browser context |
| browser_close | BrowserCloseTool | Close the browser session |
| Tool | Class | desc |
| slack_receive | SlackReceiveTool | Receive msgs from Slack channels |
| slack_send | SlackSendTool | Send msgs to Slack channels |
| telegram_receive | TelegramReceiveTool | Receive msgs from Telegram chats |
| telegram_send | TelegramSendTool | Send msgs to Telegram chats |
| jira_receive | JiraReceiveTool | Fetch tasks/issues from Jira |
| jira_create | JiraCreateTool | mk new issues in Jira |
| analyze_tasks | AnalyzeTasksTool | Analyze and prioritize tasks from messaging platforms |
| Tool | Class | desc |
| git_diff | GitDiffTool | Check git diff between curr branch and main/master branch |
| git_commit | GitCommitTool | mk a git commit w/ specified msg |
| git_push | GitPushTool | Push git commits to remote repo |
| git_pull_request | GitPullRequestTool | mk pull reqs on GitHub or GitLab |
All file sys and shell tools operate w/in a configured workspace_root dir to prevent unauthorized access to sensitive files outside the project scope. Process tools track spawned processes and allow for proper cleanup.
from coding_agent.tools import ReadFileTool, WriteFileTool, ListDirTool
# Read a specific file
tool ReadFileTool()
result tool.run(path"src/main.py")
# Write a new file
tool WriteFileTool()
result tool.run(path"test.py", content"print('Hello')")
# List dir w/ details
tool ListDirTool()
result tool.run(path".")
from coding_agent.tools import StartProcessTool, StopProcessTool
# Start a long-running server
tool StartProcessTool()
result tool.run(command"python -m http.server 8000")
# Returns: {"pid": 12345, "status": "running"}
# Stop the process later
tool StopProcessTool()
result tool.run(pid12345)
from coding_agent.tools import BrowserNavigateTool, BrowserClickTool, BrowserScreenshotTool
# Navigate to a website
tool BrowserNavigateTool()
result tool.run(url"https://ex.com")
# Take a screenshot
tool BrowserScreenshotTool()
result tool.run(path"screenshot.png")
# Click a button
tool BrowserClickTool()
result tool.run(selector"#login-button")
from coding_agent.tools import SlackSendTool, TelegramSendTool, JiraCreateTool
# Send a Slack msg
tool SlackSendTool()
result tool.run(
channel"#general",
text"Deployment complete! "
)
# Send a Telegram msg
tool TelegramSendTool()
result tool.run(
chat_id"123456789",
text"Alert: Server CPU usage above 90"
)
# mk a Jira issue
tool JiraCreateTool()
result tool.run(
project"PROJ",
summary"Fix login bug",
desc"Users unable to login w/ special characters in password",
issuetype"Bug",
priority"High"
)
from coding_agent.tools import GitDiffTool, GitCommitTool, GitPushTool, GitPullRequestTool
# Check git diff against main/master branch
tool GitDiffTool()
result tool.run()
# Or specify base branch: result tool.run(base_branch"develop")
# mk a commit
tool GitCommitTool()
result tool.run(msg"feat: add new feature", all_filesTrue)
# Push to remote
tool GitPushTool()
result tool.run(set_upstreamTrue)
# Or specify remote and branch: result tool.run(remote"origin", branch"feature-branch")
# mk a pull req (requires gh CLI for GitHub or glab CLI for GitLab)
tool GitPullRequestTool()
result tool.run(
title"Add new feature",
body"This PR adds the new feature described in issue #123",
draftFalse
)
All tools follow a consistent architecture:
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any, opt
@dataclass
class ToolResult:
"""Standard result structure for all tools."""
success: bool
output: str ""
error: opt[str] None
data: opt[Any] None
class Tool(ABC):
"""Base class for all tools."""
@property
@abstractmethod
def name(self) - str:
"""Unique tool identifier."""
pass
@property
@abstractmethod
def desc(self) - str:
"""Human-readable desc for LLM."""
pass
@property
@abstractmethod
def schema(self) - dict:
"""JSON Schema for tool params."""
pass
@abstractmethod
def run(self, **kwargs: Any) - ToolResult:
"""run the tool w/ given params."""
pass
This consistent iface allows:
- Easy registration w/ the agent
- auto schema gen for LLM func calling
- Standardized error handling
- Simple testing and mocking
Configure agent behavior w/ the Settings class:
from coding_agent.config import Settings
settings Settings(
workspace_dir".", # Root dir for file ops
max_iterations50, # max agent loop iterations
timeout_seconds300, # Tool exec timeout (seconds)
log_level"INFO", # Logging level: DEBUG, INFO, warn, ERROR
enable_historyTrue, # Persist conversation history
history_dir".agent_history", # dir for history storage
max_context_length128000, # max context tokens
temperature0.7, # LLM temperature (creativity)
top_p0.95, # LLM nucleus sampling parameter
)
Configure LLM connection params:
from coding_agent.config import ModelConfig
model_config ModelConfig(
base_url"http://localhost:11434/v1", # API endpoint URL
api_key"ollama", # API key (use actual key for cloud APIs)
model_name"qwen2.5-coder:7b", # Model identifier
max_tokens4096, # max resp tokens
timeout120, # req timeout (seconds)
retry_count3, # num of retry attempts
streamTrue, # Enable streaming resps
)
You can also use cloud-based LLM providers:
# OpenAI GPT-4
model_config ModelConfig(
base_url"https://api.openai.com/v1",
api_key"your-openai-api-key",
model_name"gpt-4-turbo-preview",
)
# Anthropic Claude (via OpenAI-compatible proxy)
model_config ModelConfig(
base_url"https://your-proxy.com/v1",
api_key"your-api-key",
model_name"claude-3-opus-20240229",
)
Extend the agent w/ your own custom tools:
from typing import Any
from coding_agent.tools import Tool, ToolResult
class WeatherTool(Tool):
"""Custom tool to fetch weather data."""
@property
def name(self) - str:
return "get_weather"
@property
def desc(self) - str:
return "Get curr weather for a specified city"
@property
def schema(self) - dict:
return {
"type": "object",
"props": {
"city": {
"type": "string",
"desc": "Name of the city"
},
"unit": {
"type": "string",
"desc": "Temperature unit (celsius or fahrenheit)",
"enum": ["celsius", "fahrenheit"]
}
},
"req": ["city"],
}
def run(self, **kwargs: Any) - ToolResult:
"""run the weather lookup."""
city kwargs.get("city")
unit kwargs.get("unit", "celsius")
# Your impl here
try:
# Simulated weather data
weather_data f"Weather in {city}: 22{unit[0].upper()}"
return ToolResult(successTrue, outputweather_data)
except Exception as e:
return ToolResult(successFalse, errorstr(e))
# Register and use the custom tool
w/ CodingAgent() as agent:
agent.register_tool(WeatherTool())
resp agent.run("What's the weather in London?")
print(resp)
- Single Responsibility: Each tool should do one thing well
- Clear Descriptions: Write detailed descs for the LLM
- Proper Schemas: Define clear JSON schemas for params
- Error Handling: Always handle exceptions gracefully
- sec: Validate inputs and respect workspace boundaries
- Identify the Need: Determine what capability is missing
- Design the iface: Define clear inputs and outputs
- impl the Tool: Extend the
Toolbase class - Write Tests: Ensure reliable behavior
- Register and Test: Add to agent and test w/ real scenarios
# ex: Testing a custom tool
import pytest
from coding_agent.tools import ToolResult
from your_module import YourCustomTool
def test_your_tool():
tool YourCustomTool()
result tool.run(param1"value1")
assert isinstance(result, ToolResult)
assert result.success is True
assert "expected" in result.output
The project includes complete tests for all built-in tools. When creating custom tools, follow similar testing patterns:
# tests/test_custom_tools.py
import pytest
from coding_agent.tools import ToolResult
from coding_agent.tools.browser import BrowserNavigateTool
class TestBrowserTools:
def test_navigate_valid_url(self):
tool BrowserNavigateTool()
result tool.run(url"https://ex.com")
assert result.success is True
assert "navigated" in result.output.lower()
def test_navigate_invalid_url(self):
tool BrowserNavigateTool()
result tool.run(url"not-a-valid-url")
assert result.success is False
assert "error" in result.output.lower()
Run tests w/ pytest:
# Run all tests
pytest tests/
# Run specific test file
pytest tests/test_custom_tools.py
# Run w/ coverage
pytest --covcoding_agent tests/
- Each tool has a single, clear responsibility
- Minimal abstraction layers
- Straightforward control flow
- Easy to understand and debug
- Shared utils in common mods
- Centralized tool registry
- Reusable msg and config classes
- Consistent patterns across components
- complete docstrings w/ Args, Returns, Raises
- Type hints throughout the codebase
- Clear naming conventions
- Well-organized mod structure
- Workspace isolation for file ops
- Input validation on all tool params
- Timeout limits on tool exec
- Safe shell command exec
- Python: 3.10 or higher
- httpx: Async HTTP client for LLM API calls
- Ollama: For local LLM inference
- pytest: For running tests
- black: For code formatting
- mypy: For type checking
| Model | Size | perf | Use Case | | Qwen2.5-Coder-7B | 7B | Excellent | General coding tasks | | CodeLlama-7B | 7B | Very Good | Code completion | | DeepSeek-Coder-6.7B | 6.7B | Excellent | Multi-language support | | StarCoder2-7B | 7B | Very Good | Open-source alternative |
Run the included exs to verify your setup:
# Test basic functionality
python -m coding_agent.exs.basic_usage
# Test custom tools
python -m coding_agent.exs.custom_tools
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2024 Coding Agent Project
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software w/o restriction, incl w/o limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the follow conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", w/o WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, incl BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A specific PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION w/ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Contributions are welcome! plz follow these guidelines:
- Fork the repo
- mk a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull req
For issues, questions, or suggestions:
- Check the documentation in
/workspace/coding_agent/README.md - Report bugs via issue tracker
- Discuss features and improvements
div align"center"
**Happy Coding! **
Built w/ using local LLMs
/div