Lemon is an AI coding assistant that runs on your own machine, built as a distributed system of concurrent processes on the BEAM (Erlang VM). You talk to it via Telegram while it runs locally — or use the terminal UI or web UI directly.
Named after a very good cat.
- Elixir 1.19.5+ and Erlang/OTP 28.5+
- A model provider API key (Anthropic, OpenAI, etc.)
- Node.js 24 LTS+ (TUI/Web clients only)
git clone https://github.com/z80dev/lemon.git
cd lemon
mix deps.get
mix compileCreate ~/.lemon/config.toml:
[providers.anthropic]
api_key_secret = "llm_anthropic_api_key_raw"
[defaults]
provider = "anthropic"
model = "anthropic:claude-sonnet-4-20250514"
engine = "lemon"Store your API key:
mix lemon.secrets.set llm_anthropic_api_key_raw "sk-ant-..."./bin/lemon setup # interactive walkthrough
./bin/lemon channels
./bin/lemon config validate
./bin/lemon doctor # verify everything is working
./bin/lemon media --limit 5
./bin/lemon models --provider anthropic
./bin/lemon providers --provider openai
./bin/lemon policy list
./bin/lemon proofs --limit 5
./bin/lemon readiness --limit 5
./bin/lemon secrets status
./bin/lemon skill list
./bin/lemon usage
scripts/verify_source_install --skip-compile # optional local install proofThe source wrapper commands delegate to the same Mix tasks:
./bin/lemon setup ... -> mix lemon.setup ...,
./bin/lemon channels ... -> mix lemon.channels ...,
./bin/lemon config ... -> mix lemon.config ...,
./bin/lemon doctor ... -> mix lemon.doctor ...,
./bin/lemon media ... -> mix lemon.media ...,
./bin/lemon models ... -> mix lemon.models ...,
./bin/lemon providers ... -> mix lemon.providers ...,
./bin/lemon policy ... -> mix lemon.policy ...,
./bin/lemon proofs ... -> mix lemon.proofs ...,
./bin/lemon readiness ... -> mix lemon.readiness ...,
./bin/lemon secrets status -> mix lemon.secrets.status,
./bin/lemon skill ... -> mix lemon.skill ...,
./bin/lemon usage ... -> mix lemon.usage ..., and
./bin/lemon update ... -> mix lemon.update ....
For source-checkout maintenance, ./bin/lemon update --check delegates to the
stage-1 local mix lemon.update task. It reports the current version, checks
config migration state, and can sync bundled skills when run without
--no-skill-sync; it does not download or swap remote release binaries.
TUI (development/local):
./bin/lemon-dev /path/to/your/projectTelegram gateway:
./bin/lemon-gatewayWeb UI / operations dashboard:
./bin/lemon
# open http://localhost:4080/ for the session console
# open http://localhost:4080/ops for health, active runs, approvals, and support commandsScript notification:
./bin/lemon send --to telegram:<chat_id> "deploy finished"
echo "RAM 92%" | ./bin/lemon send --to discord:<channel_id>
./bin/lemon send --to discord:#ops --attach report.txt --attach trace.log "deploy report"
./bin/lemon send --dry-run --to discord:#ops --attach report.txt "validate only"./bin/lemon send supports Telegram and Discord targets, optional :thread_id, --thread, --topic, --account, --reply-to, --subject, --file, --file -, repeated --attach uploads up to 10 files, --dry-run, --json, --quiet, --help, and filtered --list. Platform-only targets use env defaults first, then [gateway.telegram] default_chat_id / default_thread_id / default_topic_id or [gateway.discord] default_channel_id / default_thread_id. Default account ids use LEMON_TELEGRAM_DEFAULT_ACCOUNT_ID / LEMON_DISCORD_DEFAULT_ACCOUNT_ID, then [gateway.telegram] default_account_id / [gateway.discord] default_account_id. Dry-run validates targets, body/caption resolution, and attachment metadata without platform credentials or delivery. List mode reports env/config defaults plus bounded recent Telegram/Discord known-target windows with exact reusable aliases when the BEAM store has seen chats, channels, or threads. --account <id> selects the channel account for delivery and scopes known-target listing/name resolution. --thread <id-or-name> and Telegram-friendly --topic <id-or-name> set the thread/topic separately from --to and fail if the target already embeds a thread. --reply-to <message-id> replies under an existing platform message when the channel adapter supports it. Unique known names work for Telegram and Discord, such as telegram:#lemon-ops, telegram:@lemon_ops, telegram:#lemon-ops:deploys, discord:#ops, or discord:#ops:deploys.
- Create a bot via
@BotFather— run/newbot, copy the token - Add to config:
gateway.telegram.bot_token = "..."andallowed_chat_ids = [your_id] - Restart the gateway, then message your bot
Full Telegram setup details: docs/user-guide/setup.md
| Feature | How |
|---|---|
| Chat with an AI coding assistant | Telegram, TUI, or Web UI |
| Run tasks in a specific repo | /new /path/to/repo or bind a project in config |
| Use skills (reusable knowledge modules) | ./bin/lemon skill list / install / inspect |
| Search past runs by content | search_memory tool (enable session_search flag) |
| Generate skill drafts from memory | mix lemon.skill draft generate |
| Schedule recurring tasks | Cron configuration in ~/.lemon/config.toml |
| Send shell/CI notifications | ./bin/lemon send --to telegram:<chat_id> "done" |
| Check Telegram/Discord readiness | ./bin/lemon channels |
| Check media/provider proof readiness | ./bin/lemon media --limit 5 |
| List model catalog | ./bin/lemon models --provider anthropic |
| Check provider readiness | ./bin/lemon providers --provider openai |
| Set route model policy | ./bin/lemon policy set telegram --model anthropic:claude-sonnet-4-20250514 |
| Inspect redacted proof artifacts | ./bin/lemon proofs --limit 5 |
| Check launch readiness gates | ./bin/lemon readiness --limit 5 (--strict fails unless ready) |
| Check secret store | ./bin/lemon secrets status |
| Check usage/cost totals | ./bin/lemon usage |
| Use multiple LLM providers | 26 providers supported; configure in [providers] |
| Command | What it does |
|---|---|
/new |
Start a new session |
/new /path/to/repo |
Start session bound to a repo |
/cwd [path|clear] |
Set working directory for this chat |
/resume |
List previous sessions |
/cancel |
Cancel a running run |
/lemon, /claude, /codex |
Switch engine for one message |
/steer, /followup, /interrupt |
Queue mode overrides |
Agent:
- 23 built-in tools:
bash,read,read_skill,skill_manage,search_memory,write,edit,grep,websearch,webfetch,task,agent, and more - Real-time streaming with live steering (inject messages mid-run)
- Session persistence via JSONL with tree-structured history
- Context compaction and branch summarization
Routing & Execution:
- Lane-aware scheduling: main (4), subagent (8), background (2)
- 26 LLM providers with automatic model selection
- Multi-engine: native Lemon + Codex CLI, Claude CLI, OpenCode CLI, Pi CLI
- Adaptive routing: learns from past run outcomes (enable
routing_feedback)
Skills:
- Reusable knowledge modules loaded by the agent when relevant
- Manifest v2 format with category, required tools, and structured body
- Automatic draft synthesis from successful runs (enable
skill_synthesis_drafts)
Infrastructure:
- Telegram channel adapter for stable text-first remote chat; Discord, X/Twitter, XMTP, and other channel adapters are preview unless promoted by release notes
- Preview cron scheduling with heartbeats
- Event-driven architecture with pub/sub across all components
- Encrypted secrets keychain
| Audience | Start here |
|---|---|
| Public docs site | docs/index.md — homepage and launch-stage entry points |
| Install landing page | docs/install.md — short source install path and release status |
| New users | docs/user-guide/setup.md — full setup walkthrough |
| Skills | docs/user-guide/skills.md — listing, installing, synthesizing |
| Memory & search | docs/user-guide/memory.md — session search, retention |
| Adaptive features | docs/user-guide/adaptive.md — routing feedback, synthesis |
| Architecture | docs/architecture/overview.md — system design |
| Config reference | docs/config.md — full TOML reference |
| Non-Elixir users | docs/for-dummies/README.md — plain-English tour |
| Contributors | AGENTS.md — project navigation and conventions |
| Full docs index | docs/README.md — complete documentation map |
scripts/test fast # compile with warnings as errors + ExUnit excluding integration
scripts/test path apps/lemon_skills/test
scripts/test quality # lint + doc freshness + architecture boundaries
scripts/test clients # Python CLI package check + Node client CI paritySee docs/testing.md for the canonical local test lanes and
how they map to CI.
GitHub Copilot coding-agent runs use
/.github/workflows/copilot-setup-steps.yml
to preinstall BEAM/Rust toolchains plus Hex dependencies before the agent firewall is
enabled. Keep it aligned with the versions and dependency bootstrap steps in
/.github/workflows/quality.yml.
Release profiles:
| Profile | Use case |
|---|---|
lemon_runtime_min |
Headless/API runtime with gateway, router, channels, and control plane |
lemon_runtime_full |
Full local runtime with automation, skills, web UI, and sim UI |
sim_broadcast_platform |
Public sim broadcast and replay deployment (lemon_sim_ui) |
MIX_ENV=prod mix release lemon_runtime_fullSee docs/plans/lemon-1.0-mainstream-readiness.md
for the Hermes-on-BEAM product goal, docs/plans/lemon-hermes-feature-parity-matrix-2026-05-12.md
for the source-grounded Hermes feature comparison, and docs/plans/lemon-hermes-agent-harness-parity-scorecard.md
for the harness contract ledger. See
docs/plans/lemon-sim-platform-mission-2026-05-12.md
for the LemonSim platform mission covering watchable Werewolf and Vending Bench
2.0.
MIT — see LICENSE file.
Lemon is heavily inspired by pi (Mario Zechner), draws architectural ideas from Oh-My-Pi (can1357), takopi (banteg), OpenClaw, and Ironclaw. Skill library bootstrapped from Hermes Agent (Nous Research).
Built with Elixir and the BEAM. TUI powered by @mariozechner/pi-tui.