This is a demo CLI coding agent for use by Leo Simons (@lsimons) and his bot (@lsimons-bot).
It's inspired by stuff like
- https://ampcode.com/how-to-build-an-agent
- https://shittycodingagent.ai/
- https://rijnard.com/blog/the-code-only-agent
- https://ghuntley.com/ralph/
Things I want:
- A simple hello-world example of such a coding agent more than a daily use system.
- Optimized for readability and understandability.
- Implemented in python and using uv.
- Low on external dependencies to keep complexity down.
- Keep the python code simple and don't use advanced coding constructs.
- The CLI should also launch a simple webserver on localhost with a web UI.
- Electron application that is a thin wrapper around that web frontend.
- Use vibe coding to build the coding agent.
- Experiment with the Ralph Wiggum style of vibe coding to build this, https://awesomeclaude.ai/ralph-wiggum .
- Use a monorepo setup with multiple packages (core cli, react frontend, web server, web api, frontend server, electron app, etc).
- Get any secrets from 1password.
- Simple unit tests without mocking frameworks or complex structures.
Things I don't want or need:
- MCP
- Skills
- Async
- Performance
- Image support
- Themes (just dark mode is fine)
- Configurability (just load some env vars, hardcode the rest in python)
lsimons-agent/
├── packages/
│ ├── lsimons-agent/ # Core agent logic (python)
│ │ ├── pyproject.toml
│ │ └── src/lsimons_agent/
│ │ ├── agent.py # Main agent loop + process_message()
│ │ ├── tools.py # Tool definitions (read, write, edit, bash)
│ │ └── llm.py # LLM client (OpenAI-compatible API)
│ ├── lsimons-agent-web/ # FastAPI backend + HTML frontend
│ │ ├── pyproject.toml
│ │ ├── src/lsimons_agent_web/
│ │ │ ├── server.py # FastAPI app with WebSocket terminals
│ │ │ ├── terminal.py # PTY-based terminal management
│ │ │ └── client.py # CLI client for chat endpoint
│ │ ├── templates/ # HTML templates (terminal UI)
│ │ └── static/ # Static assets (favicon, logo)
│ ├── mock-llm-server/ # Mock LLM server for testing
│ │ ├── pyproject.toml
│ │ ├── scenarios.json # Canned responses
│ │ └── src/mock_llm/
│ │ └── server.py
│ ├── lsimons-agent-electron/ # Electron wrapper
│ │ ├── package.json
│ │ └── main.js
│ └── lsimons-agent-e2e-tests/ # Playwright end-to-end tests
│ ├── package.json
│ ├── playwright.config.js
│ └── tests/
├── scripts/ # Build scripts
│ ├── build_backend.py # PyInstaller build for backend
│ └── build_icons.py # Generate app icons
├── pyproject.toml # Root project config (uv workspace)
└── README.md
# Install uv if not already installed
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment and install dependencies
uv sync --all-packages
# Run the CLI
uv run lsimons-agent
# Run the web server
uv run lsimons-agent-web
# Run mock LLM server (for testing)
uv run mock-llm-server
# Run Python tests
uv run pytestRun the Electron app in development (launches web server automatically):
cd packages/lsimons-agent-electron && npm install && npm startBuild standalone desktop apps that bundle the Python backend:
cd packages/lsimons-agent-electron
# Build for current platform
npm run build
# Build for specific platform
npm run build:mac # macOS (.dmg)
npm run build:win # Windows (.exe)
npm run build:linux # Linux (.AppImage)The build process:
- Generates app icons from
docs/Leo-Bot.png - Bundles Python backend with PyInstaller
- Packages everything with electron-builder
Built apps are in packages/lsimons-agent-electron/dist/.
The e2e tests use Playwright to test the full stack:
chat.spec.js- Tests the web UI against mock serverelectron.spec.js- Tests the Electron app (launches electron, which starts web server)
# Install Playwright and dependencies
cd packages/lsimons-agent-e2e-tests
npm install
npx playwright install
# Run web UI tests (auto-starts mock-llm and web servers)
npm run test:web
# Run Electron tests (requires electron package to be set up)
cd ../lsimons-agent-electron && npm install && cd ../lsimons-agent-e2e-tests
npm run test:electron
# Run all tests
npm test
# Run tests in headed mode (see the browser)
npm run test:headedPlaywright → Electron → Web Server → Core Agent → Mock LLM
↓ ↓ ↓ ↓ ↓
browser desktop FastAPI process_message canned
tests app SSE + tools responses
This project uses lsimons-llm for LLM client functionality. Get LLM_API_KEY from 1password:
LLM_API_KEY=sk-... # From 1password
LLM_BASE_URL=https://litellm.sbp.ai/v1
LLM_MODEL=azure/gpt-5-1See the lsimons-llm README for full environment variable documentation.
For testing, leave these unset to use defaults (mock server on localhost:8000).
- Python 3.14+ - Main language
- uv - Package management and virtual environments
- FastAPI - Web framework for the API
- Electron - Desktop app wrapper
- Playwright - End-to-end testing
- pytest - Python unit testing (no mocking frameworks)
- Readable code over clever code - Favor explicit, simple implementations
- Minimal dependencies - Only add what's truly needed
- No abstractions until needed - Start concrete, abstract later if patterns emerge
- Synchronous by default - Async adds complexity, avoid unless necessary
- Fail fast - Simple error handling, let exceptions propagate
Use ruff for linting and formatting:
uv run ruff check . # Check for errors
uv run ruff check . --fix # Auto-fix errors
uv run ruff format . # Format codeRun linting before committing. All code must pass ruff check with no errors.
uv run pytest # Run all tests
uv run pytest tests/test_tools.py # Run one file
uv run pytest -k "test_read" # Run tests matching nameRules:
- Write tests for new functions
- Tests go in
tests/directory - Name test files
test_*.py - Name test functions
test_* - No mocking - use real implementations or the mock LLM server
- Keep tests simple: setup, action, assert
- Work on
mainbranch (no feature branches for this project) - Make small, focused commits
- Run
uv run ruff check .before committing - Run
uv run pytestbefore committing - Write clear commit messages: what changed and why
Commit message format:
Short summary (50 chars or less)
Optional longer description if needed.
- Specifications - Detailed feature specs for CLI, tools, web, and electron
- Conversation persistence
- Syntax highlighting
- Token usage display

