Skip to content

Repository files navigation

lecode

A minimalist terminal AI coding agent. No IDE, no electron, no noise — just your terminal, an OpenAI-compatible model, and a sharp set of tools.

         _                    _
        | | ___  ___ ___   __| | ___
        | |/ _ \/ __/ _ \ / _` |/ _ \
        | |  __/ (_| (_) | (_| |  __/
        |_|\___|\___\___/ \__,_|\___|
                  by wowi42

╭────────────────────────── lecode — fix-auth ───────────────────────────╮
│  ✓ session      fix-auth — new session                                 │
│  ✓ config       ~/.config/lecode/config.toml + .lecode/config.toml     │
│  ✓ provider     openrouter · https://openrouter.ai/api/v1              │
│                 model deepseek/deepseek-v4-flash · key from env        │
│  ✓ models       327 fetched live from the provider                     │
│  ✓ prompt       minimal                                                │
│  ✓ context      AGENTS.md · docs/AGENTS.md                             │
│  – skills       none                                                   │
│  ✓ agents       primaries: build, plan · custom: researcher            │
│  ✓ memory       long-term 2.4 KB injected                              │
│  ✓ tools        19 tools                                               │
│  ✓ permissions  mode yolo · custom rules                               │
│  – hooks        none configured                                        │
│  – pierre       off                                                    │
│  ✓ lsp          enabled                                                │
│  ! mcp          exa (no EXA_API_KEY)                                   │
╰─────────────────── ~/github.com/you/your-project ─────────────────────╯

Every interactive start shows you exactly what was loaded — config files, provider, prompt, project context, skills, agents, memory, permissions, hooks, LSP, MCP — before the chat opens.

Why lecode

  • Tiny harness, big ecosystem. The default system prompt is under 300 tokens; project context comes from your AGENTS.md files, skills, and memory — not from a bloated prompt.
  • OpenRouter, or anything OpenRouter-compatible. OpenRouter is the first-class preset (live catalog, pricing, caching); other gateways — Ollama, LM Studio, llama.cpp, corporate proxies — plug in with one --base-url flag or a [custom_providers] entry. Keyless local endpoints supported. The model catalog is fetched live from the provider at startup (when the fetch fails the catalog is simply empty — models lose their pricing/modality annotations; nothing cached on disk).
  • Real permissions, not vibes. Two modes (yolo by default, readonly via --safe when you want a look-but-don't-touch agent), glob + regex rules, last-match-wins, unbypassable denies, doom-loop detection, and lifecycle hooks that can narrow — never widen — any decision.
  • Money is a metric. Live token + cost totals in the statusline, and a tokens in/out · cost summary every time a chat ends.
  • Inspectable by design. Sessions are append-only JSONL you can grep; sessions are always named; every session is resumable, undoable, rewindable, exportable.

Requirements

  • Python 3.12+

  • Three external binaries on PATH (verified at startup; no auto-download, no fallback):

    binary powers install
    fd find_files brew install fd · apt install fd-find · cargo install fd-find
    rg grep brew install ripgrep · apt install ripgrep · cargo install ripgrep
    rtk bash output compaction see https://github.com/rtk-ai/rtk

Targets macOS and Linux; Windows is best-effort.

Install

uv tool install --force git+https://github.com/KalvadTech/lecode

lecode is distributed from this repository only — it is not on PyPI.

Quickstart

lecode --setup                       # import from pi/opencode or answer 4 questions
export OPENROUTER_API_KEY=sk-or-...  # or keep the key in config.toml
cd your-project
lecode                               # name the session, then ask for something
dir: lecode · commit: 974015a · branch: main · diff: ±1 +4 -4
model: deepseek/deepseek-v4-flash · cost: $0.0062 · ctx: ▓▓░░░ 36.0k/200.0k 18%
session: fix-auth · agent: build · in: 4.1k · out: 0.9k · ⠼

One fixed statusline, every element labelled: directory · commit · branch · diff / model · cost · context meter / session · agent · tokens · state (a reasoning-level override shows on the model line when /thinking is set). No configuration needed.

Useful things to type:

/help                     all slash commands, grouped
/welcome                  key bindings cheat-sheet
/tutor permissions        explain one feature
/tasks                    background tasks, live
/doctor                   health-check the install
!make test                run a shell command, see the output
!!pytest -x               run it AND feed the output to the model
@src/auth.py              attach a file (images/PDF/audio too)
.plan refactor this       run with a persona
Tab                       cycle agents: build ⇄ plan
Alt-Enter                 steer the agent mid-turn

Headless

lecode -p "write a haiku about this repo"     # one prompt, then exit
git diff | lecode -p "review this diff"       # a bare -p reads stdin
lecode --loop plan.md --loop-cmd "make test"  # iterate until the plan is done
lecode --chain "redesign the parser"          # brainstorm→plan→code→review

The final answer goes to stdout; a tokens: <in> in / <out> out · cost: $X.XXXX summary goes to stderr, so scripts can pipe the answer cleanly.

Exit codes: 0 done · 1 error · 2 startup (missing deps, bad flags, non-tty --setup) · 3 max turns / max loop iterations / context overflow.

A tour of the power features

  • Permissions — two modes (yolo allows everything, readonly allows read-class tools only; default yolo), per-tool glob/regex rules, session allow-always grants, per-agent overlays. /permissions, /mode, /toggle.
  • Sessions — always named, append-only JSONL, scoped to the folder they were created in (resume never crosses directories), /new /resume /undo /redo /rewind /retry /compact /handoff /rename, searchable picker with delete, HTML export (/export), secret-gist sharing (/share), re-import (/import). Approaching the context window, the runner compacts automatically (summary + recent tail; [compaction] tunes the trigger, buffer and overflow policy).
  • Custom agents — markdown files in ~/.config/lecode/agents/ or .lecode/agents/ with their own model, temperature, prompt and permission overlay. Tab cycles primaries; @agent or the task tool runs subagents.
  • SkillsSKILL.md packs in .agents/skills/ (project) or ~/.agents/skills/ (global), discoverable by the model, optionally registered as slash commands.
  • Memory — persistent per-project markdown: long-term MEMORY.md (auto-injected, 32 KB cap), daily logs, scratchpad, named notes. /memory to inspect; the agent has memory_* tools.
  • Hooks — shell commands on 15 lifecycle events (PreToolUse, PostToolUse, UserPromptSubmit, Stop, …) that return verdicts; they can only narrow permissions. --hooks-test dry-runs the pipeline.
  • Pierre mode — when enabled, a second model reviews every finished task: it compares your request with the agent's result and tells you plainly whether it delivered. /pierre on|off|model.
  • Structured questions — the ask_user tool lets the agent ask 1-4 multiple-choice questions mid-turn instead of guessing; you answer inline with the keyboard (1-4 to pick, enter to confirm a multi-select, esc to dismiss). Headless, loop, chain, and subagent runs get a "use your best judgment" result instead of a prompt.
  • Notifications — sound (afplay/paplay/aplay, terminal bell fallback) and desktop notifications (osascript / notify-send) on turn finish, error, and approval-needed. /notifications on|off; channels and per-event toggles in [notifications].
  • MCP — stdio, streamable-HTTP, and SSE servers, with optional OAuth 2.1 (auth = "oauth", browser flow, tokens under <config_dir>/mcp-auth/; /mcp auth to authorize, /mcp login|logout to manage). Exa web search is preconfigured (needs EXA_API_KEY); context7 is one flag away.
  • LSP — diagnostics from real language servers appended to write/edit results; fail-open, never blocks.
  • Worktrees--worktree <name> or /worktree for isolated branches, /wt-merge / /wt-exit with conflict detection.
  • Multimodal/add image.png or @file.pdf; capability-checked against the model.
  • Background tasksbash and task accept run_in_background and return a task id immediately; the agent inspects them with the tasks_list / tasks_output / tasks_wait / tasks_stop tools, you watch them with /tasks, and completions land in the feed and in the next turn. Remaining tasks are stopped (SIGTERM, then SIGKILL) when the session exits.
  • Prompts and personas — the default system prompt is minimal (<300 tokens); style = "rich" opts into a detailed prompt. 16 named personas (.review …, .plan …) overlay one turn, /prompt switches style, /editsys opens the system prompt in $EDITOR.
  • Reasoning levels/thinking sets the reasoning effort; collapsible thinking blocks in the feed; the statusline shows the active override.
  • Pickers and polish/ opens a slash-command dropdown, @ and . open fuzzy file/agent/persona pickers — all in themed panels; Tab path completion; queued prompts while the agent runs, Alt-Enter to steer mid-turn; OSC 8 hyperlinks; /copy (OSC 52 / pbcopy / xclip).
  • Status signals — start/stop/git-conflict events over a Unix socket, for external status bars and scripts.
  • Doctor/doctor health-checks the install: external binaries, config, provider connectivity, MCP servers, memory, hooks, telemetry.
  • Telemetry (opt-in) — Sentry/GlitchTip error reports and OpenTelemetry metrics (turns, tokens, cost, tool calls) via [telemetry]; needs the telemetry extra, fail-open by design.

Configuration

Global config: ~/.config/lecode/config.toml (override the directory with LECODE_CONFIG_DIR); a project-local .lecode/config.toml deep-merges over it. TOML is the only accepted format. The setup wizard writes the file with 0600 permissions because it can hold an API key — prefer the OPENROUTER_API_KEY / OPENAI_API_KEY env vars to keep secrets out of it.

Full reference: docs/configuration.md.

Docs

Development

uv sync
uv run python -m pytest        # 1200+ tests
uv run ruff check && uv run ruff format --check
prek install                   # git hooks: ruff on commit, pytest on push

Releasing

Releases are automated with release-please and follow semver, driven by conventional commits: fix: → patch, feat: → minor, feat!: (or any !) → major. Every push to main updates a release PR that bumps pyproject.toml and CHANGELOG.md; merging that PR creates the vX.Y.Z tag and the GitHub Release, with the built dists (wheel + sdist) attached to the release. Nothing is published to PyPI.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages