Skip to content

v3.11.1

Choose a tag to compare

@github-actions github-actions released this 09 Oct 10:28
· 35 commits to main since this release
b4fd337

Highlights

  • Agents can read across all your projects at once: the path jail now admits every project below your home directory for reading by default, while writes stay in the session's own project and ~/.ssh, ~/.aws, ~/.config, other top-level dot directories, ~/Library, ~/AppData and ~/snap stay closed.
  • Each agent session binds to the project it was started in. Setup no longer pins one project into an agent's global MCP config, and existing pins are removed.

Upgrade notes

  • Path jail scope: the new path_jail_scope setting defaults to "home": reads anywhere below your home directory outside the protected zones; writes only in the session's project, host-declared roots and allow entries. Set lean-ctx config set path_jail_scope project to keep the previous single-project boundary. The setting is global-only; a project-local .lean-ctx.toml cannot change it. With an implausible $HOME (/, a single path component, not owned by you) the scope falls back to project. path_jail = false still disables the jail.
  • Protected zones are a hard deny in both scopes: a project root or allow entry that only contains a zone (for example a dotfiles repository at ~) no longer opens ~/.ssh and the like; add an entry inside the zone (lean-ctx allow-path ~/.config/myapp) if a tool must reach it.
  • Project pins: earlier lean-ctx setup / doctor --fix runs and MCP-start hook refreshes copied the installing session's LEAN_CTX_PROJECT_ROOT and LEAN_CTX_EXTRA_ROOTS into user-global agent configs (~/.codex/config.toml, ~/.grok/config.toml, global JSON MCP entries), so every later session of that agent opened the same project. The Codex and Grok entries are cleaned on the next agent refresh; lean-ctx doctor reports remaining pins under "Project binding" and lean-ctx doctor --fix removes them line by line, keeping key order and comments (a pin that shares a line with other keys is listed for a manual edit). LEAN_CTX_EXTRA_ROOTS values move into extra_roots; per-project entries in ~/.claude.json are left alone. Restart the agent once afterwards.
  • Telemetry: the daily aggregates report more (see Changed), and setup no longer asks: setup and the first interactive command after this update print a three-line notice instead. Turn telemetry off any time with lean-ctx telemetry off, DO_NOT_TRACK=1 or LEAN_CTX_TELEMETRY=off; an explicit opt-out made since 3.11.0 stays in effect, and lean-ctx telemetry show prints the exact payload. What the server keeps, including a keyed network hash and the network operator's public name derived from the connection (never the IP address), and how long, is described at leanctx.com/privacy.

Security

  • Agent shells can no longer loosen lean-ctx itself. lean-ctx is on the default shell allowlist, so an agent could run lean-ctx yolo --yes, lean-ctx allow <cmd>, lean-ctx allow-path <dir>, lean-ctx trust, lean-ctx security open, lean-ctx security secrets off or lean-ctx config set <security key> through ctx_shell (or a hook-rewritten Bash call) and then do what the jail or the allowlist had just refused. Those subcommands are now blocked in agent shells with a message to ask the user; listing (--list, status, config show), narrowing (--remove) and tightening (secure, untrust, security secrets on) still run. Run the blocked commands in your own terminal.
  • Path jail writes: the new home scope opens other projects for reading only; writes outside the session's project need an explicit lean-ctx allow-path, so an agent in one repository cannot plant another repository's Git hooks or a binary on your PATH.

Added

  • lean-ctx allow-path <dir> admits one directory for reading and writing — outside your home directory, a sibling project to edit, or one protected location — effective on the next tool call without a restart. --list shows the jail scope and added directories; --remove takes one out. It refuses /, the home directory and any directory containing it.
  • lean-ctx security status shows the active jail scope, and lean-ctx doctor reports global project pins.

Changed

  • A refused path names the one command that admits it (lean-ctx allow-path <dir>, offered for the enclosing project) for the user to run in their terminal. The previous hints to open a new IDE window or set an env var that the running server cannot see are gone.
  • When a stale LEAN_CTX_PROJECT_ROOT pin is still set and the MCP server starts inside a different real project, the session binds to that project and logs a warning. Host-specific roots (CLAUDE_PROJECT_DIR, workspace folders) keep their precedence.
  • Telemetry reports where and how long LeanCTX runs, as coarse ranges. The daily heartbeat adds the runtime environment (local, container, Codespaces, Gitpod, Replit, cloud agent, CI), the installation age (under an hour … 30+ days) and the number of active days in the last 30 (1 … 15+), each as a closed value. They let usage numbers separate people from short-lived agent sandboxes. No machine, account, network or path information is sent. The disclosure lists the new category, so every installation sees the one-time notice again; DO_NOT_TRACK=1, LEAN_CTX_TELEMETRY=off and lean-ctx telemetry off still turn telemetry off.
  • The install channel is detected. It was unknown for every installation because no build set it; it now follows the location of the running executable (npm, Homebrew, cargo, PyPI, AUR, release binary). Only the channel name is sent.
  • Telemetry reports token savings and per-tool latency. The daily tool aggregate adds the day's total tool-output tokens before and after compression, and each built-in tool's summed latency. Counts only; no content.
  • Telemetry includes the daily usage record and why tools fail. The batch carries the last 90 days of the installation's own lean-ctx gain record (operations and tokens before/after compression per day, lifetime totals, month of first use), so usage through shell hooks and before telemetry is counted. Failed tool calls are reported by class (invalid input, not found, permission, policy, timeout, edit conflict, too large, unavailable), together with the five most frequent error messages per tool and day as templates: the client replaces every quoted text, path, file name, number, identifier, URL and e-mail address with a placeholder before anything is sent, and drops a message entirely when no safe wording remains. Shell commands that exit non-zero are now reported as command instead of internal.
  • Upgrades turn on telemetry that was only off by the old default. Before 3.11 telemetry was opt-in, so telemetry.enabled = false without a recorded choice is re-enabled once on upgrade, and the one-time notice explains it. An opt-out made since 3.11 (lean-ctx telemetry off, declining in setup, and now also lean-ctx config set telemetry.enabled false) is recorded as explicit and never overridden; DO_NOT_TRACK=1 and LEAN_CTX_TELEMETRY=off always win, and a read-only config is left untouched.
  • Telemetry counts which LeanCTX features are used. A daily feature_aggregate reports how often each CLI command runs (lean-ctx pack export → cli.pack.export, graph build, index build-full, telemetry off …) and every graph, BM25 and semantic index build with its failures. Commands and verbs come from a fixed registry; arguments, paths and queries never become part of a code, and hot-path commands (shell hooks, -c, read, grep, statusline) are not counted.
  • Telemetry names 21 more AI clients. Cline, Roo Code, Kilo Code, Continue, OpenCode, Goose, Amp, Augment, JetBrains, Warp, Trae, Qwen Code, Crush, Claude Desktop, ChatGPT, LM Studio, Copilot CLI, Visual Studio, Neovim, Emacs and Factory are reported as their own family, and none separates installations used only through the CLI and shell hooks from an unrecognised MCP client (other). The client's name is never sent, and what LeanCTX offers each client over MCP is unchanged.
  • Setup no longer asks about telemetry. Setup and the first interactive command after an install or update show a three-line notice instead: telemetry is on, how to turn it off (lean-ctx telemetry off, or enabled = false under [telemetry] in the config.toml it names) and where to see what is sent. The full list stays on lean-ctx telemetry on|off and the payload on lean-ctx telemetry show. An earlier explicit choice is kept.

Fixed

  • ctx_shell output capture works in your project. Redirects and tee (> build.log, >> notes.txt, | tee out.txt) were refused everywhere except /tmp, $TMPDIR and write_allow_paths; the project root stayed refused even when listed, and allow_paths / extra_roots were not consulted. Capture may now also go to the session's project and the jail's allow entries. /, ~, its ancestors and read_only_roots are never capture targets; downloads (curl -o, wget, dd of=) keep the scratch-only rule.
  • ctx_shell no longer relocates, queues or throttles your builds. Three multi-agent build settings were on by default: agents.shared_cargo_target pointed every cargo build/test run through ctx_shell at <data dir>/build-cache/cargo-target, so ./target kept a stale binary; agents.serialize_build_commands made each build wait for builds from other sessions on the machine; agents.cargo_build_jobs = 3 capped cargo at three jobs. All three are now opt-in (false, false, 0) and documented in the config reference under [agents]. Set them again in config.toml if you relied on the shared cache.
  • ctx_shell walk hint judges each invocation on its own (#2027). A scoped grep -r … tariff followed by a stdin-reading grep in the same command line (…; echo x | grep -c x, | grep -v _test) was treated as a recursive walk of the working directory, so the hint named .claude/worktrees/, node_modules/ or .venv/ although nothing entered them. Only invocations that walk (find, or a grep-like with its own -r/-R) now contribute search roots. With raw: true the hint is no longer appended, matching the verbatim promise.
  • lean-ctx update and enable-gpu no longer require a cosign binary. 3.11.0 verified release signatures by running cosign, so on machines without it every binary update and enable-gpu stopped with "cosign is unavailable; refusing unsigned release". The updater now verifies the keyless signature in-process: the certificate must chain to the embedded Sigstore Fulcio root, carry a valid SCT from the Sigstore CT log, name the release workflow at the exact release tag with the GitHub Actions OIDC issuer, and sign the file. When cosign is installed it still runs as an additional check (Rekor transparency log). 3.11.0 installations cannot self-update to this release unless cosign is on PATH (winget install -e --id Sigstore.Cosign, brew install cosign, or a binary from github.com/sigstore/cosign/releases); alternatively reinstall with the install script (macOS/Linux), npm, Homebrew or Cargo, or replace the binary from the release archive.
  • Semantic index builds keep their progress. Embeddings were written only after the last chunk, and lean-ctx index build-semantic gave up after 10 minutes, which ended the process and discarded the work — on CPU-only machines and with larger models the index was never built. Builds now save finished files every minute and on errors, Ctrl-C or memory aborts, the next run resumes where the last one stopped, and the CLI waits until the build finishes. index status and doctor report an interrupted build as partial with the resume command.
  • ctx_index builds the semantic index in the background. build-semantic and build-full no longer block the tool call, wait for the BM25 index instead of embedding an empty or stale one, and a per-project lock keeps two processes from building the same semantic index at once.
  • CLAUDE.md is read in full. Automatic ctx_read modes (and redirected native reads) returned a large CLAUDE.md as a headings-only map, because only SKILL.md, AGENTS.md and a few rule files were treated as instructions. CLAUDE.md, CLAUDE.local.md, GEMINI.md, copilot-instructions.md, .windsurfrules, and documents under .claude/agents/ and .claude/commands/ are now always delivered complete.
  • redirect_exclude works again. The key was loaded but never applied, so listing a file there changed nothing. Matching paths (globs on the trailing path components, e.g. CLAUDE.md, *.json, docs/**) now skip the native-read hook redirect and are returned in full by automatic ctx_read modes; LEAN_CTX_HOOK_EXCLUDE (comma-separated) takes precedence, as documented since 2.17.4.
  • lean-ctx index build / build-full no longer stop after 5 minutes while graph and BM25 are still building, which ended the process before the index was saved. A build worker that fails unexpectedly now always releases its slot, so the command reports the failure instead of waiting.

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.0...v3.11.1