A from-scratch coding agent — bring your own OpenRouter API key
Project description
██╗ ███████╗████████╗███████╗ ██████╗ ██████╗ ██████╗ ███████╗
██║ ██╔════╝╚══██╔══╝██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝
██║ █████╗ ██║ ███████╗██║ ██║ ██║██║ ██║█████╗
██║ ██╔══╝ ██║ ╚════██║██║ ██║ ██║██║ ██║██╔══╝
███████╗███████╗ ██║ ███████║╚██████╗╚██████╔╝██████╔╝███████╗
╚══════╝╚══════╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝╚══════╝
Building Claude Code from scratch — a minimal coding agent you own and understand.
What is this?
letscode is a coding agent built from first principles. It replicates the core loop of tools like Claude Code:
- You describe a coding task in plain English
- The agent calls tools (read files, list directories, edit files) to get the job done
- It keeps looping — reading, reasoning, editing — until the task is complete
The entire agent fits in a single file. No magic, no abstractions you didn't write yourself.
Features
- Model-agnostic — works with any model on OpenRouter: Claude, GPT-4o, Gemini, Llama, Mistral, DeepSeek, and more
- Free tier support — defaults to
meta-llama/llama-3.3-70b-instruct:free(no cost) - Built-in tools — read files, list directories, edit files, search file contents, run shell commands
- Interactive
/menu — type/for a navigable dropdown of every command and tool (arrow keys + Enter), just like Claude Code; pick a tool to run it locally without spending tokens - Text-protocol tool-calling — no vendor lock-in; the LLM emits tool calls as plain text
- Full conversation history — the agent remembers context across turns
Quickstart
1. Clone the repo
git clone https://github.com/srinivasankh/letscode.git
cd letscode
2. Set up your API key
Copy the example config and add your OpenRouter key:
cp .env.example .env
Edit .env:
OPENROUTER_API_KEY=sk-or-your-key-here
That's all you need. The default model is free — no credit card required.
3. Run it
uv run letscode
Or, if you prefer pip:
pip install -e .
letscode
Bring Your Own API Key (BYOK)
letscode routes all LLM calls through OpenRouter, which gives you a single API key that works with dozens of models.
Get a free key:
- Sign up at openrouter.ai
- Go to openrouter.ai/keys → create a key
- Paste it into your
.envfile asOPENROUTER_API_KEY
Choose your model by setting OPENROUTER_MODEL in .env:
# Free models (no cost)
OPENROUTER_MODEL=meta-llama/llama-3.3-70b-instruct:free
OPENROUTER_MODEL=google/gemma-3-27b-it:free
OPENROUTER_MODEL=deepseek/deepseek-r1:free
# Frontier models (paid, best quality)
OPENROUTER_MODEL=anthropic/claude-sonnet-4
OPENROUTER_MODEL=openai/gpt-4o
OPENROUTER_MODEL=google/gemini-2.5-pro
Browse all available models at openrouter.ai/models.
How it works
The agent runs a simple loop:
User input
└─▶ LLM reasons about the task
└─▶ Emits a tool call (e.g. tool: read_file({"filename": "app.py"}))
└─▶ Agent executes the tool
└─▶ Result fed back to LLM
└─▶ Repeat until done
Available tools:
| Tool | What it does |
|---|---|
read_file(filename) |
Read the full content of a file |
list_files(path) |
List files and directories at a path |
edit_file(path, old_str, new_str) |
Replace text in a file, or create a new file |
search_text(pattern, path) |
Recursively search file contents for a regex, returning file:line:text hits |
run_command(command) |
Run a shell command (with confirm-before-run gate) |
Slash menu: type / to open an interactive dropdown of commands (/exit, /help)
and tools. Use the arrow keys and Enter to select. Picking a command runs it; picking a
tool inserts a /tool({"arg": "value"}) template you fill in — the tool then runs locally
(no LLM call) and prints its result.
Project structure
src/letscode/
agent.py # the entire agent: tools, prompt, parser, loop
pyproject.toml # package config
.env.example # config template — copy to .env
Requirements
- Python 3.12+
- uv (recommended) or pip
- A free OpenRouter API key
- prompt_toolkit (installed automatically) — powers the interactive
/menu
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file letscode_cli-0.1.5.tar.gz.
File metadata
- Download URL: letscode_cli-0.1.5.tar.gz
- Upload date:
- Size: 36.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed59038f7cc813ba29566e29fffc1cb0e8b7d5191264e08a4ece6bd0b5a0f524
|
|
| MD5 |
0512538777bac53d13f5d125d1d3cb40
|
|
| BLAKE2b-256 |
8bcf1f54ac8f51ee20df724507a493d727e8e42dec5549c229b9c3824597eeb8
|
File details
Details for the file letscode_cli-0.1.5-py3-none-any.whl.
File metadata
- Download URL: letscode_cli-0.1.5-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06014fac479b6c0d793e49fbe1eac98ea5acf7f333bfc7059e17bd14d97ff7c4
|
|
| MD5 |
48466f67dfa5b3f5bd1ce2e9407ba66b
|
|
| BLAKE2b-256 |
e94a1a6f8ba4cb607874c2ec9b4fed0155fb09334d0a666ee32c82537c0e219b
|