Repository navigation
v3.11.3
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 = homenow 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,~/AppDataand~/snap, and everything outside~. The previous behaviour is the new scopeprojects(lean-ctx config set path_jail_scope projects), the strictest one staysproject. A scope you set yourself is kept;homeset 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-gpuno longer fails (#2048). Each update moves the runninglean-ctx.exeaside tolean-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 withstale 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-installuses the same cleanup. lean-ctx enable-gpuon the CUDA build it would install says so (#2048) instead of downloading and reinstalling the same binary.lean-ctx enable-gpu --forcestill reinstalls it.- GPU embeddings work with CUDA 13 runtimes (#2049).
onnxruntime-gpuon PyPI is built for CUDA 13 since 1.27, andpip install "onnxruntime-gpu[cuda,cudnn]"installs the CUDA 13 wheels, which put the DLLs intosite-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, solean-ctx embeddings statusreportedCUDA runtime: not loadablealthough 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 andCUDA_PATH_V13_*toolkits. - Windows: the CUDA check no longer fails on every machine (#2049). The check loads
onnxruntime_providers_cuda.dlldirectly; 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 missingProvider_GetHost, which was already handled).embeddings statustherefore saidnot loadableand 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 bareLoadLibraryExW failed. CUDA runtime: OKmeans 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 onPATH) could still fall back to CPU without a word.embeddings statusnow 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 statuslists 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.exeonPATH, system-wide installs under%ProgramFiles%\Python3*andC:\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 statussays which setting chose the embedding model (#2049):LEAN_CTX_EMBEDDING_MODEL(which overrides the config),[embedding] modelin the namedconfig.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_shellstatus 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_readanswers an empty file, an SVG and a directory. An empty file returnedFile is emptyas 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 errorIs a directory; it now lists its entries.ctx_searchsearches an invalid regex literally. Code text such asfoo(,items[0orfn run(&selfis not valid regex and failed the call; it is now searched verbatim, with a one-line note.action=symbolalso takes the symbol name fromsymbol,queryorpatternwhennameis missing.ctx_patchinfersreplace_unique. An edit with old and new text but noopfailed withmissing 'op'; such an edit can only bereplace_unique, at the top level and insideops[].- An edit whose result already holds is not an error.
ctx_edit(andctx_patchreplace_unique) with identical old and new text, where that text is in the file, reportsNo 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
commandentry, and did so even forexit 1with output (grep, diff, test), which is not an error. The worker now records only background jobs, ascommandortimeout; 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,LANGand a few more variables, so a server it started could not seeDO_NOT_TRACK=1,LEAN_CTX_TELEMETRY=offor 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, thecontainervariable 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_readfailure 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 interactivelean-ctxcommand, 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 tomcp.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 onboardand every update install or refresh the plugin. If you remove it withlean-ctx claude-mod uninstall, it stays removed until you runlean-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-ctxNote: After upgrading via cargo/npm/brew, run
lean-ctx setupto refresh shell aliases.lean-ctx updatedoes this automatically.
Full Changelog: v3.11.2...v3.11.3