letcode is a terminal Agent written in Rust.
中文 | English
It provides an opencode-style TUI based on Ratatui, and also keeps a REPL CLI mode.
cargo build
cargo test
cargo fmt --checkRun the default TUI:
cargo runRun the line-based CLI:
cargo run -- --cliCLI mode can also be selected with cli or repl. TUI can be selected explicitly with --tui or tui.
Show the installed version and check for a newer GitHub release:
letcode --version
letcode update checkUpdate a release-installed binary after an interactive confirmation:
letcode updateThe TUI supports English (en) and Simplified Chinese (zh-CN). Use /language or its /lang alias to switch languages at runtime.
Building from source requires the Rust toolchain. Some built-in tools also invoke the following external programs, which must be available on PATH:
| Program | Used by | Requirement |
|---|---|---|
git |
git__status, git__diff, git__log, and the TUI branch indicator |
Recommended; only Git-related capabilities are unavailable when missing |
rg |
search__rg text search |
Recommended; the search tool is unavailable when missing |
ast-grep |
code__ast_search and code__ast_replace_preview |
Optional; only AST tools are unavailable when missing |
In addition, shell__exec and local MCP servers depend on the system commands they invoke, while web__fetch and remote MCP require network access.
letcode loads configuration from:
~/.config/letcode/letcode.toml
Configuration example:
# Optional; defaults to the first provider in the file.
active_provider = "openai"
# Optional; defaults to false.
fast_mode = false
# Optional; all values below have defaults.
[global]
# max_iterations = 64
# max_tool_calls = 128
# tool_timeout_secs = 60
sessions_dir = "sessions"
log_file = "logs/combined.log"
# Optional; by default, recent context is preserved according to the active model's input budget.
[global.compaction]
# preserve_recent_tokens = 12000
# Optional; values below are the defaults.
[global.retry]
enabled = true
max_attempts = 50
max_recovery_attempts = 3
initial_delay_secs = 1
backoff_multiplier = 2.0
jitter_secs = 1
# Optional; defaults to default. Values: safe | default | auto | yolo.
[permissions]
mode = "default" # solo remains accepted as a yolo alias
# Optional; choose a default route and per-invocation allowed routes for an expert.
# [agents.explorer]
# provider = "openai"
# model = "gpt-5.5"
# allowed_models = ["openai/gpt-5.5"]
# The same shape applies to fixer, oracle, designer, librarian, general, and reviewer.
# Optional; this can only narrow parallelism declared by a tool itself.
[tools.parallelism]
# "fs__read" = "parallel"
# "web__fetch" = "exclusive"
# Optional local MCP server.
# [mcp.example_local]
# type = "local"
# command = ["/path/to/mcp-server", "--stdio"]
# environment = { FOO = "bar" }
# enabled = true
# timeout = 5000
# Optional remote MCP server; OAuth is not currently supported.
# [mcp.example_remote]
# type = "remote"
# url = "https://example.com/mcp"
# headers = { Authorization = "Bearer ..." }
# enabled = true
# timeout = 10000
# Required: configure at least one provider with at least one model.
[providers.openai]
# Optional; OPENAI_API_KEY may be used instead.
api_key = "YOUR_API_KEY"
# Optional for the OpenAI provider; defaults to https://api.openai.com/v1.
base_url = "https://api.openai.com/v1"
# Optional for the OpenAI provider, where it defaults to responses; required for other providers.
protocol = "responses" # responses | completions
# Optional; defaults to the first model configured for this provider.
default_model = "gpt-5.5"
# Required: each provider needs at least one model; every field inside the model is optional.
[providers.openai.models."gpt-5.5"]
display_name = "GPT-5.5"
# protocol = "completions" # overrides the provider protocol
# context_window = 400000
# effective_input_limit_tokens = 256000
# max_output_tokens = 128000
supports_tools = true # default: true
parallel_tool_calls = true # default: true
supports_reasoning = true # default: true
reasoning_effort = "medium"
# Optional; restricts selectable reasoning levels and the TUI cycle order.
reasoning_efforts = ["none", "low", "medium", "high", "max"]
reasoning_summary = "auto" # auto | concise | detailed
text_verbosity = "medium" # low | medium | high
# temperature = 0.2
# top_p = 1.0
# Optional model-level prompt cache.
# [providers.openai.models."gpt-5.5".prompt_cache]
# enabled = true
# retention = "in_memory" # in_memory | 24h
# namespace = "openai"Provider API keys and base URLs can also come from environment variables named from the provider, for example OPENAI_API_KEY / OPENAI_BASE_URL; for a provider named compat, use COMPAT_API_KEY / COMPAT_BASE_URL.
Relative sessions_dir and log_file paths are resolved relative to the config file directory.
Optional Langfuse/OpenTelemetry tracing is off by default. Enable it with LETCODE_LANGFUSE_ENABLED=true, and set LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, and optional LANGFUSE_HOST (or the same variables in a local .env). Missing credentials leave tracing disabled without stopping the agent.
See CHANGELOG.md for release notes.
This project is dual-licensed under the MIT License OR the Apache License 2.0. You may choose either license when using, modifying, or redistributing this project.
- MIT License: see LICENSE-MIT
- Apache License 2.0: see LICENSE-APACHE
