- Python minimum is 3.13; CI tests 3.13 and 3.14 on Linux/macOS. Use
uv;uv sync --extra telemetryincludes the optional dependencies exercised in CI. - Run checks from the repo root, in CI order:
uv run ruff check uv run ruff format --check uv run python -m pytest
- Focused test:
uv run python -m pytest tests/test_agent_builder.py; append::test_read_only_mode_denies_writesto run one case. - CLI startup requires
fd,rg, andrtkon PATH. Debian'sfd-findinstallsfdfind, so expose it asfd. Search tests skip without their binaries; CI supplies an RTK pass-through shim, not real compaction coverage. .pre-commit-config.yamlruns Ruff checks and formatting on commit, the full pytest suite on pre-push. The formatting hook modifies files.
src/lecode/cli.pydispatches interactive, headless, loop, and chain modes. They shareagent/builder.py:build_runtime()for wiring andagent/runner.py:AgentRunnerfor the model/tool loop. Keep builder wiring network-free; interactive catalog/MCP startup is deferred until chat opens.- Route tool execution through
agent/tools/base.py:ToolRegistry.dispatch_result(): it validates arguments and enforces permissions/approval. Auto-approval never overrides Deny; hooks and agent overlays can only narrow permissions. - TUI changes must preserve normal terminal scrollback, not an alternate-screen UI.
tui/feed.pykeeps live tokens in the layout and flushes completed text to scrollback; partial-line printing throughpatch_stdoutcan erase streaming output. Checktests/test_tui_feed.py,tests/test_tui_app.py, andtests/test_tui_streaming_pty.pyfor rendering changes. session/storage.pystores append-only JSONL. Replay throughload_for_model()so compaction, clear events, and undo tombstones apply. Keep lock sidecars on release: unlinking them allows competing processes to lock different inodes.
config/loader.py:load_config()creates defaults and rewrites migrated config. Tests constructing runtimes/config/session stores should isolateLECODE_CONFIG_DIR,LECODE_SKILLS_DIR, and project cwd undertmp_path. The sharedtool_ctxfixture is not autouse and isolates only the config directory.- Reuse
tests/fakes.pyfor providers/catalogs. MCP tests launch mock subprocesses and localhost servers; disable auto servers as intests/test_mcp.py:mcp_configto avoid ambient credentials activating Exa. Keep the SSE shutdown reset intests/conftest.py; it prevents order-dependent failures across server tests. docs/build-plan.mdis historical, not the current spec: permissions now have two modes, config is TOML-only, and the catalog is live with an empty fallback. For config or hook changes, consultdocs/configuration.mdordocs/hooks.mdand reconcile with the implementation.- Releases use conventional commits and release-please, with wheel/sdist attached
to GitHub Releases, not PyPI.
.github/workflows/release.ymlseparately re-locksuv.lockafter release-please bumpspyproject.toml.