Skip to content

v3.11.3

Choose a tag to compare

@github-actions github-actions released this 11 Oct 14:01
· 21 commits to main since this release
a6a2040

PathJail opens the home directory by default, the gateway keeps downstream MCP sessions alive between calls, Windows updates and CUDA 13 GPU embeddings work, and Claude Code gets a gateway cockpit. Agent Tools protocol and data formats are unchanged.

Changed

  • PathJail opens your whole home directory by default. The default path_jail_scope = home now admits everything below ~ for reading and writing; before, it admitted only paths inside a project, read-only outside the session's project. Protected locations stay closed: every top-level dot entry (~/.ssh, ~/.aws, ~/.config, shell rc files, other agents' ~/.claude, ~/.codex, …), ~/Library, ~/AppData and ~/snap, and everything outside ~. The previous behaviour is the new scope projects (lean-ctx config set path_jail_scope projects), the strictest one stays project. A scope you set yourself is kept; home set explicitly now means the wider scope too. Every installation without its own setting shows a one-time notice on its next interactive command.

Fixed

  • Windows: a second update or enable-gpu no longer fails (#2048). Each update moves the running lean-ctx.exe aside to lean-ctx.old.exe. The process that does this is still running from that file, so it cannot delete it, and the next update refused to start with stale Windows rollback binary exists. The next update now deletes the leftover file. If an old lean-ctx process (an editor's MCP server, a daemon) still runs from it, the file is renamed aside and removed by a later update once that process has exited; only when even that rename fails does the update stop and say which process to close. lean-ctx dev-install uses the same cleanup.
  • lean-ctx enable-gpu on the CUDA build it would install says so (#2048) instead of downloading and reinstalling the same binary. lean-ctx enable-gpu --force still reinstalls it.
  • GPU embeddings work with CUDA 13 runtimes (#2049). onnxruntime-gpu on PyPI is built for CUDA 13 since 1.27, and pip install "onnxruntime-gpu[cuda,cudnn]" installs the CUDA 13 wheels, which put the DLLs into site-packages\nvidia\cu13\bin\x86_64 (Linux: nvidia/cu13/lib). LeanCTX looked only for CUDA 12 libraries (cudart64_12.dll, libcudart.so.12) in the CUDA 12 wheel directories, so lean-ctx embeddings status reported CUDA runtime: not loadable although everything was installed. LeanCTX now reads which CUDA major the selected ONNX Runtime's CUDA provider was built for from the provider's import table and searches and preloads the matching CUDA 12 or CUDA 13 libraries, including the new wheel layout and CUDA_PATH_V13_* toolkits.
  • Windows: the CUDA check no longer fails on every machine (#2049). The check loads onnxruntime_providers_cuda.dll directly; outside ONNX Runtime its initialisation refuses to run, which Windows reports as error 1114 after every dependency has already loaded (Linux reports the same case as a missing Provider_GetHost, which was already handled). embeddings status therefore said not loadable and indexing warned about a CPU fallback while ONNX Runtime was in fact using the GPU, and GPU-sized embedding batches were never used. Error 1114 now counts as loaded; other loader errors show their Windows error code and meaning instead of a bare LoadLibraryExW failed.
  • CUDA runtime: OK means the GPU is really used (#2049). ONNX Runtime loads cudart and cuDNN by name only when a session starts, so a provider DLL that loads (for example through a CUDA toolkit on PATH) could still fall back to CPU without a word. embeddings status now also requires the CUDA runtime and cuDNN to resolve, preloads them before the provider is registered, and names the library that is missing otherwise.
  • Clearer CUDA diagnostics on Windows (#2048, #2049). Instead of a bare LoadLibraryExW failed, lean-ctx embeddings status lists the missing DLLs and every directory it searched, says when no NVIDIA driver (nvcuda.dll) is installed, and states the CUDA major the provider needs instead of the CUDA version of the ONNX Runtime LeanCTX was compiled against.
  • ONNX Runtime and CUDA libraries from more Windows Python installs are found (#2048): every python.exe on PATH, system-wide installs under %ProgramFiles%\Python3* and C:\Python3*, the Python install manager's %LOCALAPPDATA%\Python\pythoncore-* (the default for Python 3.14) and the Microsoft Store Python, in addition to the per-user installs and active virtual or conda environments.
  • lean-ctx embeddings status says which setting chose the embedding model (#2049): LEAN_CTX_EMBEDDING_MODEL (which overrides the config), [embedding] model in the named config.toml, or the default, plus how to change it.
  • Every second gateway call no longer fails with Transport closed (#2040, reported by @smollgreymouse). ctx_tools (find, list, call) and gateway compression addons each built their own Tokio runtime per call and dropped it afterwards. A pooled downstream MCP session's transport lives on the runtime that opened it, so the next call got a session whose connection was already gone. All gateway I/O now runs on one runtime that lives as long as the process, so a downstream server is started once and reused across calls.
  • The status line shows this conversation's numbers. When several agents run LeanCTX in the same project, the Claude Code status line showed whichever session had written last, so its figures jumped between conversations or stood still. Each session now records the process of the AI client it serves, and the status line reads the session that belongs to its own client.
  • Polling a background shell job no longer inflates the session counts. Every ctx_shell status or cancel call for a background job counted as one more tool call and one more command in the session statistics; a single long build polled by an agent could add hundreds. These polls no longer count.

Tool calls that failed although the agent's request was sound, found in the usage telemetry of 3.11.1 and 3.11.2:

  • ctx_read answers an empty file, an SVG and a directory. An empty file returned File is empty as an error; it now reads as <path>: empty file (0 bytes). SVG files were rejected as binary; they are XML text and read like source (a real binary behind any extension is still caught by its content). A directory failed with the OS error Is a directory; it now lists its entries.
  • ctx_search searches an invalid regex literally. Code text such as foo(, items[0 or fn run(&self is not valid regex and failed the call; it is now searched verbatim, with a one-line note. action=symbol also takes the symbol name from symbol, query or pattern when name is missing.
  • ctx_patch infers replace_unique. An edit with old and new text but no op failed with missing 'op'; such an edit can only be replace_unique, at the top level and inside ops[].
  • An edit whose result already holds is not an error. ctx_edit (and ctx_patch replace_unique) with identical old and new text, where that text is in the file, reports No change: instead of failing. Text that is absent still fails.
  • Dependency source reads on the first call. Reading a file in a language cache registered the cache as a read-only root but still failed the call with "Retry the read"; it now resolves in the same call. The Rust toolchain source (~/.rustup/toolchains), Cargo git dependencies (~/.cargo/git/checkouts) and the Bun, Dart pub and Ruby gem caches are recognized alongside the existing ones. Credential and configuration directories (~/.claude, ~/.codex, ~/.config, ~/.cargo/credentials.toml) stay jailed, and writes into any cache stay denied.
  • Usage telemetry counts each tool call once. The daily total of tool calls and failures, and the latency histogram, counted every call twice: once where the call is dispatched and again when its lifecycle finished. The per-tool counts were already right; the totals now match them.
  • A failed inline shell command is one error, filed as a failed command. The shell worker also recorded every non-zero exit of a command that finished in the foreground as a LeanCTX-internal error, next to the pipeline's own command entry, and did so even for exit 1 with output (grep, diff, test), which is not an error. The worker now records only background jobs, as command or timeout; inline runs are classified once by the call pipeline.
  • Telemetry opt-outs and CI detection reach MCP servers started by Codex. Codex starts MCP servers with only HOME, PATH, USER, LANG and a few more variables, so a server it started could not see DO_NOT_TRACK=1, LEAN_CTX_TELEMETRY=off or the CI markers set in the shell or job around it: an opt-out did not reach the server, and a CI job counted as a local machine. On Linux the server now also reads these few keys, and the runtime-environment markers, from its nearest ancestor processes. Nothing else from their environment is read or kept.
  • Containers under cgroup v2 report as container. A container that has no /.dockerenv (containerd, Kubernetes, Podman) and runs under cgroup v2 reported as a local machine. Its overlay root filesystem, the container variable and the Kubernetes service-account directory now mark it too.

Added

  • Notices from the LeanCTX team reach the installations they concern. The acknowledgement of a telemetry send can carry up to three short notices, for example "the fix for this ctx_read failure is in 3.11.3". The server picks them by what the batch already reports (version, AI client, OS, runtime environment, a tool that failed), so nothing extra is sent and nobody needs to know who you are. A notice is shown once, on the terminal of the next interactive lean-ctx command, and never in an MCP response: text from a server does not reach the AI model. Only plain text up to 280 characters with an optional link to leanctx.com or the LeanCTX GitHub repository is accepted. With telemetry off, no notices arrive.
  • Usage telemetry counts MCP server starts that answered no tool call. Some clients start every configured MCP server, often in a throwaway container, and their agent never calls a tool. Such a start is now counted as an empty session (mcp.session.empty, next to mcp.session), so these starts can be told apart from real sessions.
  • Gateway cockpit for Claude Code. The LeanCTX plugin for Claude Code adds a sidebar that shows what passed the gateway in this conversation: which sources Claude saw and at what depth (structure, passage, full file, search, command), the two checks every delivery passed (may it be read, may it leave), the receipts, and the tokens kept out of the context. A line above the prompt pulses while LeanCTX works and shows the handoff from sources to Claude; short overlays mark a finished turn and milestones. The status line below the prompt groups the session as SELECT (files and commands), CONTROL (enforced decisions) and TOKENS (kept out, leaner, cached). It only reads LeanCTX's local session data; nothing is sent anywhere.
  • The Claude Code plugin is set up with LeanCTX. When Claude Code is installed, lean-ctx setup, lean-ctx onboard and every update install or refresh the plugin. If you remove it with lean-ctx claude-mod uninstall, it stays removed until you run lean-ctx claude-mod install.

Upgrade

lean-ctx update                 # recommended (auto-downloads + refreshes shell hooks)
cargo install lean-ctx          # or
npm update -g lean-ctx-bin      # or
brew upgrade lean-ctx

Note: After upgrading via cargo/npm/brew, run lean-ctx setup to refresh shell aliases. lean-ctx update does this automatically.

Full Changelog: v3.11.2...v3.11.3