Added
- Addon ecosystem —
lean-ctx addon(#858). A package manager for community
extensions: an addon wraps an external MCP server behind a small
lean-ctx-addon.tomlmanifest and plugs into the MCP gateway with one
lean-ctx addon add— no fork, no recompile.list/search/infobrowse
a curated registry (bundledrust/data/addon_registry.json, overridable per
entry via<data_dir>/addon_registry.json);addresolves a registry name or
a local manifest path, discloses the exact transport/command/args/env it will
run, then — after confirmation (--yesto skip; refuses non-interactively
without it) — wires a[[gateway.servers]]entry via the safe global-only
Config::update_globalpath and records it in<data_dir>/addons/installed.json;
removeunwinds exactly what it wired. Registry entries without a runnable
[mcp]block are listed (directory + homepage link), never installed with
fabricated wiring. Reuses the gateway trust model (global-only, opt-in) and the
cli::promptconfirmation gate; no new config section, so schema parity is
untouched. Manifest, registry and install logic live in small, unit-tested
core::addons::{manifest,registry,store,install}modules. Spec:
addon-manifest-v1· guide:
docs/guides/addons.md. - Repo-stack-aware profile recommendation —
lean-ctx profile suggest(#851).
Scans the current repo for deterministic, local signals (languages + source-file
count, monorepo layout viapathutil::has_multi_repo_children+ workspace
markers, build/CI markers, configured LLM providers) and recommends a context
profile plus key settings (profile,output_density,proxy.history_mode;
proxy.effortis left off — it is never inferred from a repo). Prints the exact
export/config setcommands to apply it, plus task-oriented alternatives
(ci-debugfirst when CI is detected, thenhotfix/bugfix/review). Strictly
read-only — it never writes config.--jsonfor scripting. The mapping
(core::profile_suggest::suggest) is a pure, unit-tested function separated from
the gitignore-aware scan, so the suggestion is a deterministic function of the
repo + environment (no network, no telemetry). - Review-before-overwrite for consequential CLI writes (#852). State-mutating
writes that could clobber existing state now print a before→after diff plus a
risk note and require confirmation (or--yes) — mirroring theyolo/secure
pattern, and refusing to run non-interactively without--yes. Covers
lean-ctx config setfor security/egress-relevant keys (path_jail,
shell_security,sandbox_level,secret_detection.*,boundary_policy,
proxy.*_upstream) andlean-ctx knowledge rememberwhen it would overwrite an
existing fact with a materially different value (the prior value is archived).
The knowledge gate reuses the exact overwrite predicate the write path applies
(check_contradiction), so additive, identical, near-identical (>0.8 similarity)
and no-op writes stay frictionless. The shared prompt/confirm helper is now a
singlecli::promptmodule (extracted fromsecurity_cmd), and config-key risk
classification lives incore::config::risk— deterministic and local-only. The
MCPctx_knowledgetool path is unchanged (agent writes stay versioned and
contradiction-warned without an interactive gate). - Tool & rule budget —
lean-ctx tools health(#848). A deterministic,
local-only "rot" report answering whether every always-on token earns its
place. Cross-references the fixed cost of each advertised MCP tool schema,
the MCP instructions, and every auto-loaded rules file with recorded usage
(the post-dispatch cost ledger) to flag: tools that cost schema tokens every
session but are never called (unused), heavy-schema tools used for <1% of
calls (low-use), rules files that bill the same guidance to a client more
than once, and stale knowledge facts (>30d, never retrieved). Reuses existing
telemetry and adds no new hot-path cost — per-toollast_usedrides the
cost-attribution write that already happens. Text (rot candidates only;--all
for the full list),--jsonfor scripting, and a Tool Budget panel in the
dashboard health view (/api/tools-health). Never auto-applies: every finding
is a suggestion (lean-ctx tools lean,lean-ctx rules dedup --apply). - Cache-safe cross-provider reasoning-effort control —
proxy.effort(#834).
One opt-in setting (off|minimal|low|medium|high) pins a single
reasoning-effort level across all three providers without breaking the provider
prompt cache. lean-ctx translates the constant level to each provider's native
parameter — OpenAIreasoning_effort/reasoning.effort, Anthropic
output_config.effort, and GeminithinkingConfig(thinkingLevelon 3.x,
thinkingBudgeton 2.5 pro/flash) — only on models that accept it and only when the
client didn't set its own value. Unlike per-turn "effort routing" (which flips
effort between turns and invalidates the cache — OpenAI lists effort changes as a
cache-invalidation cause; Anthropic breaks its message-cache breakpoints), the level
is a constant, so the cached prefix stays byte-stable (#448/#498) and only the
model's reasoning depth changes. Conservative by design:offis a strict no-op, it
never overrides a client value, never enables reasoning the client didn't ask for
(Anthropic adaptive-only; Gemini skips 2.5 flash-lite and never sends both thinking
fields), is model-gated (never turns a working200into a400) and deterministic.
lean-ctx proxy statussurfaces the active level plus per-provider steer counts. Set
viaproxy.effortor theLEAN_CTX_PROXY_EFFORTenv (env wins). - Unified security posture +
lean-ctx yolo/securemaster switches (#507).
Decouples lean-ctx's two independent security planes and makes them discoverable:
containment (path jail + shell gating — protects the machine from the agent)
vs secret defense (.env/credential redaction — protects secrets from the LLM
provider).lean-ctx security statusprints a posture board (and a coarse
STRICT / RELAXED / OPEN label) reused bylean-ctx doctor, which now also shows a
dedicated Secret redaction line.lean-ctx yolo(aliassecurity open) drops
containment in one step — writespath_jail = false+shell_security = "off",
takes effect immediately, and deliberately keeps secret redaction on;
lean-ctx secure(aliassecurity strict/lockdown) restores the secure
defaults. The standalone.envswitch islean-ctx security secrets <on|off>.
path_jailis now a first-class, schema-documented config key (the blanket
"any path" opt-out, equivalent toallow_paths = ["/"]), so granular re-enabling
vialean-ctx config set …/lean-ctx allow <cmd>composes cleanly after a
yolo. Disabling either plane requires a confirmation (or--yes) and refuses to
run non-interactively, so an agent can never silently weaken security. - Observation tier — synthesized, recall-prioritized entity summaries (GL #802).
A 9th cognition-loop step distils clusters of related facts into compact,
per-entity observations (Hindsight-inspired). Synthesis is deterministic by
default — facts are grouped by an entity anchor (file path in key/value, else
category) and each cluster of ≥cognition_synthesis_min_cluster(default 3)
facts is written through the normalremember()path, so versioning, persistence
and idempotency come for free and the value stays byte-stable (#498). An optional
LLM refinement sits behindllm.enabledwith the deterministic digest as
fallback. Recall gives a balanced boost to relevant synthesized observations
(above incidental matches, below an exact key hit). Facts are now epistemically
typed on write (evidence vs. inference) viainfer_from_category, feeding
salience and — opt-in viaarchetype_aware_decay— slower decay for structural
evidence. Gated bycognition_loop_max_steps >= 9(the new default; set 8 to
disable); visible asobservation_synthesisinlean-ctx introspect cognition. - Configurable shell-security mode —
enforce|warn|off(GL #788). One
switch now governs all command gating (the allowlist and the hard blocks:
eval/exec/source,$()/backticks at command position, interpreter-c),
applied at a single chokepoint so MCPctx_shelland the CLI (lean-ctx -c/-t)
behave identically.enforcestays the secure default;warnruns every check
but only logs violations;offis a deliberate opt-out that skips gating entirely
while compression stays fully active. Set viashell_securityin config or
theLEAN_CTX_SHELL_SECURITYenv (env wins; unknown values fall back to
enforce, never fail open).offdoes not lift the read-only-output doctrine
(no>/tee/heredoc writes via shell).lean-ctx doctorsurfaces the active
mode whenever it is notenforce. Supersedes the CLI-only
LEAN_CTX_ALLOWLIST_WARN_ONLY(kept for backward compatibility). /v1contract clients published under one name —lean-ctx-client. The thin,
engine-independent clients now ship on every registry under a single consistent
name: PyPI (import module stays
leanctx), npm, and
crates.io. Replaces docs that pointed
at an unrelated third-partyleanctx/ unpublished@leanctx/sdk(GL #783). A
dedicated, idempotentpublish-clients.ymlworkflow ships the family independently
of the engine.- Cognition v2 — science-grounded context engineering, deterministic by default,
provably active. Ten neuroscience/physics-motivated mechanisms are wired to
real hot-path call sites and made inspectable vialean-ctx introspect cognition
(each subsystem reports wired/active/last-run/count; also surfaced inlean-ctx doctor). All decision layers are deterministic by default (Rule #498 / prompt
cache intact); stochastic exploration is gated behindLEAN_CTX_STOCHASTIC.- Time-variant Φ (attention). Context salience is recomputed and EMA-blended
on every re-read instead of being frozen on first sight (context_ledger). - Ebbinghaus forgetting + spacing effect. Knowledge confidence decays as
R = exp(-Δt/S)with stabilitySgrowing per retrieval, replacing linear
decay. Configurable viaforgetting_model(ebbinghaus|linear),
base_stability_days, andLEAN_CTX_LIFECYCLE_FORGETTING(memory_lifecycle). - Hebbian eviction. Co-accessed cache entries protect each other from
eviction ("fire together, wire together") via a deterministic association bonus
(cache,hebbian_cache). - Complementary-learning-systems consolidation. Idle/loop replay lifts the
confidence of related, frequently-retrieved facts (cognition_loop). - Integration-aware Φ (IIT non-redundancy / MMR). The context compiler now
selects via greedy Maximal-Marginal-Relevance and deduplicates on content
(fixes a bug that compared file paths), so near-duplicate items collapse to
one (context_compiler,context_field). - Global-workspace ignition. High-salience Φ-outliers (z-score > θ, default
LEAN_CTX_GWT_IGNITION_Z) are broadcast/pinned and resist reinjection
downgrades (context_ledger,context_gate). - Learned field weights (bandit). Φ field weights are chosen by a Thompson
bandit — deterministic argmax-of-posterior-mean by default, sampling only under
LEAN_CTX_STOCHASTIC(bandit,context_field,adaptive_thresholds). - Sharp-wave-ripple idle replay. A quiet gap (default 300 s,
LEAN_CTX_COGNITION_IDLE_SECS) triggers a deeper replay-consolidation pass in
the background (cognition_scheduler,cognition_loop). - FEP prefetch (active inference). After a read, likely-next files from the
co-access graph are surfaced as a deterministic warmup hint — never an automatic
read (fep_prefetch,context_gate). - Immune detector (artificial immune system). External provider data is
screened for prompt-injection/poisoning before it can become a fact, edge or
cache entry; untrusted workspaces get a stricter screen (coupled to Workspace
Trust) (immune_detector,consolidation,ctx_provider).
- Time-variant Φ (attention). Context salience is recomputed and EMA-blended
lean-ctx introspect cognition/introspect qubo. New CLI to prove which
cognition subsystems are wired and active, and to run the experimental
QUBO-vs-greedy selection benchmark.- QUBO selection spike (research only). A deterministic simulated-annealing
QUBO solver and benchmark harness for redundancy-aware context selection, gated
behindLEAN_CTX_EXPERIMENTAL_QUBO. On clean problems it reaches parity with the
greedy knapsack (no measurable win), so greedy remains the default; promotion
is conditional on a future measurable gain (qubo_select). - Opt-in debug log —
LEAN_CTX_DEBUG_LOG/lean-ctx debug-log(#520). A
human-readable, off-by-default trace of every MCP tool call (tool, arguments,
outcome) and every shell-hook routing decision (compress / track / pass-through
and why), for diagnosing "why did lean-ctx do X?" without attaching a debugger.
Enable via theLEAN_CTX_DEBUG_LOGenv (truthy) orlean-ctx config set debug_log true; read or clear it withlean-ctx debug-log(--clear). Writes
to a single rolling file under the state dir; never on the hot path when
disabled, and the body carries no secrets (arguments are redaction-screened). - In-band remote-proxy expansion marker —
<lc_expand:HASH>(#493). Lets the
cold-prefix/CCR retrieval layer work through a remote proxy with no shared
filesystem: the model can emit a<lc_expand:HASH>marker in its output and the
proxy splices the referenced content back in band, across all three providers
(OpenAI chat + responses, Anthropic, Gemini). Opt-in and cache-safe by
construction (the marker is deterministic), follow-up to #482.
Security
- Shell allowlist now enforced on the
-t/ track path (external audit, finding 1).
exec_argv(used by the default shell hook_lc() { lean-ctx -t "$@" }for
multi-arg commands) never calledcheck_shell_allowlist, so every aliased
invocation like_lc git statusbypassed the restriction thatlean-ctx -c
enforces. Both paths now share a singleallowlist_gate, so the track path
blocks non-allowlisted commands (exit 126) exactly like the compress path. - Agent API keys are no longer captured or forwarded to
ctx_shellchildren
(external audit, finding 2). The agent-runtime-env bridge forwarded every
CODEX_*/CLAUDE_*/OPENCODE_*/GEMINI_*… var — including*_API_KEY,
*_TOKEN,*_SECRET,*_PASSWORD— into the env of every command the agent
ran, where output redaction can't stop network exfiltration.is_forwardable
now excludes credential-shaped names (only session/thread identifiers cross the
bridge), andloadretroactively scrubs such vars from any capture file
written by an older build, removing the plaintext secret at rest. - Path-jail relaxations are now surfaced loudly (external audit, finding 3).
path_jail = false, theno-jailbuild feature and the env channels
(LEAN_CTX_ALLOW_PATH,LEAN_CTX_EXTRA_ROOTS,LEAN_CTX_ALLOW_IDE_DIRS) that
widen or disable the jail are inherited from the IDE/launchd env and previously
loosened the boundary with no in-band signal. The MCP and HTTP servers now emit
a[SECURITY]warning at startup for each active relaxation, andlean-ctx doctorreports env-channel relaxations alongside the config-level ones. - Workspace Trust for project-local
.lean-ctx.tomloverrides (external audit,
finding 4). A cloned repo's.lean-ctx.tomlis merged over the global config
and could raise security-sensitive settings — replace the shell allowlist, widen
the path jail (allow_paths/extra_roots), repoint the proxy upstream, define
command aliases, changerules_scope/rules_injection. For an untrusted
workspace those overrides are now withheld (comfort knobs like
compression/themestill apply) with a[SECURITY]warning;lean-ctx doctor
shows the state. Grant trust withlean-ctx trust(andlean-ctx untrust/
lean-ctx trust status/--list); trust is pinned to the workspace path and
a content hash of.lean-ctx.toml, so editing the file re-gates it. Headless use
can opt in viaLEAN_CTX_TRUST_WORKSPACE=1orLEAN_CTX_TRUSTED_ROOTS.
Changed
- Change-aware pre-push gate + no-test advisory (#850/#849).
scripts/preflight.sh
now classifies the diff againstorigin/main: a docs-only push (README, CHANGELOG,
*.md, website, scripts) skips the Rust gates (fmt/clippy/rustdoc/Windows
cross-compile) and the pre-push hook finishes in ~0.1 s instead of ~140 s.
gen_docs --checkstill runs whenever Rust or a committed file under
docs/reference/generated/**changed. CI is unchanged and remains the source of
truth (a docs-only diff cannot turn a Rust gate red, so the local skip can never
cause a local-green / CI-red split);make preflightforces the full gate. A change
to contract code (proxy/,tools/,config/schema/) with no test signal in the
diff prints a no-test advisory — blocking underLEAN_CTX_PREFLIGHT_STRICT_TESTS=1. - Faster semantic search on a native ONNX Runtime (#497). The
embedding/index stack moves from the pure-Rustrtenbackend to nativeort
(ONNX Runtime 2.0), with a rebuilt indexing pipeline (int8-quantized vectors,
tighter HNSW, a compact postcard on-disk format). ONNX Runtime is loaded at
runtime (ort'sload-dynamic), resolved across platforms fromORT_DYLIB_PATH,
Nix profiles, and well-known system locations — so it is provided once by the
platformonnxruntimepackage (declared as a dependency in the Arch/Homebrew
packages),pip install onnxruntime, or a manualORT_DYLIB_PATH. Theort
crate is exact-pinned (=2.0.0-rc.12) until a stable 2.0 ships. One-time
re-index: the new index format is not backward-compatible; the first semantic
search after upgrade rebuilds the index automatically (a load-time version guard
removes any stale index rather than risk mis-decoding it). Thejina-code-v2
built-in (pre-existing broken) is removed; code-specialized embeddings remain
available through thehf:org/repo[@rev]custom scheme
(hf:jinaai/jina-embeddings-v2-base-code), which auto-probes the model's
ONNX I/O signature. Thanks to @omar-mohamed-khallaf for the optimization work. lean-ctx bypassrenamed tolean-ctx raw(external audit, finding 5).
The "bypass" wording read to a model like a security bypass, but it only
skips output compression — the shell allowlist and path jail still apply.
lean-ctx bypassstays as a back-compat alias; model-visible hints now use
rawand state that the allowlist still holds.- Fewer, less-duplicated MCP read tools (#509 Phase 1+2 / #527, #528, #532).
The read-variant cluster (ctx_smart_read,ctx_multi_read) folds into a
singlectx_read(multi-path + auto mode); the former tool names stay as
deprecated aliases that still work but no longer cost schema tokens in
tools/list, shrinking the always-on surface. Internally,ctx_readmodes are
now a type-safeReadModevocabulary (parsed once,FromStr/Display) instead
of ad-hoc strings, with behavioural-equivalence tests and the eval A/B gate
guarding zero output regression.SessionCacheis retained (the decoupling
thesis was evaluated and rejected as net-negative). - Configurable
ctx_shelltimeouts + opt-in writes (#526 / #523, #529). The
hard-coded 2-min / 10-min shell ceilings are now tunable viashell_timeout_secs
andshell_heavy_timeout_secs(envLEAN_CTX_SHELL_TIMEOUT*), and the read-only
output doctrine can be relaxed deliberately withshell_allow_writes(env
LEAN_CTX_SHELL_ALLOW_WRITES) so a trusted operator can permit>/tee/heredoc
writes throughctx_shell— off by default, part of making prohibitive security
opt-in rather than absolute (#526). - Leaner always-on tool & rules schema (#510/#517, #505/#508). Power-tier tool
descriptions are reworked workflow-first and de-duplicated, and the optimized
tools schema + canonical rules consolidation land, trimming the fixed
per-session token cost of advertised tools and auto-loaded rules without
changing behaviour (eval-gated).
Fixed
config setnow accepts every validOptionconfig key (persona,
bypass_hints) instead of rejecting them as "Unknown config key" (#856).
config setresolves keys via the hand-written schema (ConfigSchema::lookup)
only. AnOption<_>scalar field defaults toNone, so serde omits it from
Config::default()and it never appears inconfig_derived_keys()(which feeds
onlyconfig validate/apply). Any such field that wasn't hand-registered was
therefore accepted fromconfig.tomlbut rejected byconfig setand flagged
"unknown" byconfig validate— the class behind thepath_jailreport (fixed
earlier in #507). Auditing all 17 root-levelOptionfields found two more:
personaandbypass_hintsare now registered in the root schema (persona
as an openstringso custom<name>.tomlpersonas stay valid;bypass_hints
asenum(on|off|aggressive)soconfig setvalidates the value). A new
regression test (option_scalar_keys_are_cli_settable) asserts the
Option-scalar knobs resolve via schema lookup, guarding the whole class.lean-ctx -cno longer kills hook-runninggit commit/git pushat the
2-minute default (#854). The shell wrapper enforcesDEFAULT_TIMEOUT(2 min)
on ordinary commands andHEAVY_TIMEOUT(10 min) on build/test commands, but
git commit/git pushwere treated as ordinary — even though, in a repo with
hooks,git commitfans out intocargo clippy(pre-commit) andgit push
into the fullscripts/preflight.sh(pre-push), each of which routinely runs
3–10 min. The wrapper SIGKILLed git mid-hook, leaving the tree
staged-but-uncommitted or the push half-done.is_heavy_commandnow classifies
git commitandgit pushas heavy (10-min ceiling, 32 MB buffer); read-only
verbs (git status/log/diff) stay on the default ceiling because matching
is on the fullgit <verb>prefix.- Hybrid/dense cold-start no longer re-embeds the whole corpus inline (#512).
On a large repo, the firstctx_semantic_search mode=hybrid(ordense) call on
an MCP server that started before the on-disk dense index existed would embed the
entire corpus under the 120s per-request watchdog. The watchdog abandons the response
but cannot cancel the spawned compute, so the embed kept running — observed as a 500%+
CPU child for >10 min after the call "returned". A new cold-start guard counts the
chunks a re-embed would touch (EmbeddingIndex::pending_chunk_count) and, above a
budget (default 2000 chunks, tunable viaLEAN_CTX_HYBRID_INLINE_EMBED_MAX;0
disables — the pre-#512 behavior), refuses the inline embed across all four search
entry points (hybrid/dense × the MCP tool and the CLI/editorsearch_hitspath):
hybrid degrades to the coherent BM25(+graph) ranking (the same fallback used when
dense is disabled) and dense fails fast — both with a one-line hint to build the
index once, out of band (lean-ctx index build-semantic). Warm and incremental paths
(a few changed chunks on an existing index) are untouched and still embed inline. - Shell-output compression can no longer inflate token counts (Windows CI
flake). The VCS branch ofcompress_output(git/jj/gh/glab/hg) returned its
authoritative compressor's result even when it was not strictly shorter — so a
compactgit log --onelinestays verbatim — but it skipped the token guard the
other paths use. A tiny adversarialgit statusbody could reshape into a
one-token-larger summary, breaking thecompress_output_never_inflates_tokens
property on Windows. The VCS path now allows equal (verbatim) output but
rejects any growth, restoring the never-inflate invariant deterministically.
Pinned with a regression unit test for the exact failing input. - Cold-prefix repack is now sticky, persistent, and marker-stable (#499). Three
fixes to the opt-in big-gap repack (#480): (1) once a resumed conversation is judged
cold and repacked, the decision latches so every warm follow-up keeps the same
deterministic prefix compression and hits the cache written at the cold turn — the
previous one-shot repack re-sent the uncompressed prefix on the very next turn and
busted its own fresh cache (net-negative for the common resume-then-continue case);
(2) per-conversation baselines now persist to disk (cold_prefix_touch.json,
atomic write) and reload on proxy startup, so a long idle gap that straddles a daemon
restart is still detected; (3) the conversation key ignores the volatile
cache_controlmarker, so a moving cache breakpoint no longer flips the key into a
permanent first-sighting that never repacks. All three are cache-safe by construction
(deterministic re-compression) and covered by new N→N+1, restart, and marker-stability
tests. Thanks to @phawrylak for the precise analysis. gainno longer reports0saved when MCP tools wrote to a different data
dir (#500). The savings headline, gain score, cost view and net-of-injection
line now sum stats across every auto-resolved data dir that holds a
stats.json. When an agent host launches the lean-ctx MCP server with a
differentHOME/XDG_*than the user's shell (e.g. a containerised Hermes
Agent) the savings landed in a sibling tree while the CLI read an empty primary
dir and showed a false zero. Aggregation is a no-op without a split and is
skipped entirely whenLEAN_CTX_DATA_DIRpins one dir, so non-split users are
unaffected. The empty-state screen now also cross-checks the tamper-evident
savings ledger and, when it holds events thatstats.jsondoes not, names the
data-dir split outright (lean-ctx savings/lean-ctx doctor). Finally, the
proxy "bridge OFF — savings cannot be measured" caveat is suppressed whenever
there are real (MCP-measured) savings to show, sincegainmeasures MCP-tool
savings directly and needs no proxy. Thanks to the reporter for the detailed
Hermes + OpenRouter writeup.- Billing edge no longer downgrades a paying account on a billing-service blip
(GL #785). Entitlement resolution at the cloud edge now caches each user's
last known plan (in-memory, short TTL) and, when the upstream billing service
is unreachable or returns a bad response, serves that cached plan instead of
silently falling back to Free. Successful lookups refresh the cache; only
never-seen accounts fall to Free. A transient upstream outage can no longer
lock a Pro subscriber out of paid features mid-session. - Windows PowerShell/cmd no longer rewrites the
lean-ctxpath (#518 / #521).
The terminal-integration shell hook used a Unix-style/c/...path that
PowerShell and cmd can't execute, solean-ctxinvocations failed on Windows.
The hook now emits the native binary path on PowerShell/cmd, restoring terminal
integration there. - No more flaky ORT SIGSEGV on process exit (#519 / #522). Short-lived
processes that loaded the ONNX Runtime model could crash with a ~30% flaky
SIGSEGV/EXC_BAD_ACCESSduring staticOpSchemateardown at exit (arm64
macOS). lean-ctx now skips the detached ORT model load in short-lived processes
that won't use it, removing the teardown crash without affecting real search. - Inherited
LEAN_CTX_ACTIVEno longer silently disables compression (#533 /
#537).LEAN_CTX_ACTIVEserved double duty as both a shell-hook re-entrancy
guard and a compression bypass; when an agent (e.g. Codex) inherited it into the
MCP server's environment, every tool output came back uncompressed. Re-entrancy
ownership now rides a dedicatedLEAN_CTX_WRAPPEDmarker, so an inherited
LEAN_CTX_ACTIVEno longer turns compression off. ctx_read raw:true/mode=rawnow honored and documented (#513 / #514).
The verbatim escape hatch was silently ignored on theraw:trueargument and
undocumented formode=raw, so non-Opus models (GLM 5.2 report) fought the
compression by retrying reads. Both forms now reliably return uncompressed,
un-elided bytes and are documented as the way to get exact file content.allow_paths/shell_allowlist_extrafailures are no longer silent (#540 /
#541, #542). Two invisible-over-MCP failure modes are surfaced at the point of
the block: (1) a project-local.lean-ctx.tomlwhose security-sensitive
overrides are withheld because the workspace is untrusted now names the
ignored keys and thelean-ctx trust/ global-config remedies; (2) when the
runtime resolves a globalconfig.tomlthat doesn't exist (an edit that
landed in a different dir — XDG vs legacy~/.lean-ctx, or a sandboxed/container
$HOME), both the allowlist and path-jail block messages now say so and name
the path actually read. The stderr-onlytracing::warnwas invisible to MCP
clients (OpenCode), making these read as "the setting does nothing".
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.8.12...v3.8.12