Heredoc Support (GitHub Issue #140)
- Smart heredoc detection in
ctx_shell: Heredocs are no longer blanket-rejected. Only heredoc + file redirect combinations (cat <<EOF > file.txt) are blocked. Legitimate uses likepsql <<EOF,git commit -m "$(cat <<'EOF'...)", and input piping are now allowed through. - Hook passthrough for heredoc commands: The PreToolUse hook (Claude Code, Codex, Copilot) no longer wraps heredoc-containing commands in
lean-ctx -c '...'. Heredocs cannot survive the quoting round-trip (newlines get escaped to\\n), so they are passed through to the shell directly.
Headless MCP Mode
- New
LEAN_CTX_HEADLESS=1environment variable: When set, the MCP server skips all auto-setup duringinitialize()— no rules injection, no hook updates, no version check, no agent registry writes. Session management and all MCP tools remain fully functional. Designed for users who manage their own configuration (e.g. custom launchers with--append-system-prompt).
Cloud Auth Hardening
- Login and Register are now separate commands:
lean-ctx loginonly calls/api/auth/login.lean-ctx registeronly calls/api/auth/register. The previous behavior auto-fell back to registration on any non-specific login error (network, 500, DNS), which caused users to unknowingly create duplicate accounts. - Clear error messages: Specific guidance for wrong password, unverified email, non-existent account, and server errors.
Interactive Setup with Premium Features
- Setup wizard extended to 7 steps: New "Premium Features" step offers configuration of Terse Agent Mode (off/lite/full/ultra), Tool Result Archive (on/off), and Output Density (normal/terse/ultra) during
lean-ctx setup.
Dependency Updates
- Dependabot #12 resolved:
rand 0.8.5phantom dependency removed viacargo update(GHSA-cq8v-f236-94qc). - Updated:
tokio1.52.1,rustls0.23.39,rmcp1.5.0,uuid1.23.1, and 20+ other transitive dependencies.
Premium Features — Tool Result Archive, Terse Agent Mode, Compaction Survival
Tool Result Archive + ctx_expand (Zero-Loss Compression)
- Archive-on-disk: Large tool outputs (>4096 chars) are automatically archived to
~/.lean-ctx/archives/before density compression. The compressed response includes an[Archived: ... Retrieve: ctx_expand(id="...")]hint so the agent can retrieve the full original output at any time. - New MCP tool
ctx_expand: Retrieve archived tool output by ID. Supports full retrieval, line-range retrieval (start_line/end_line), pattern search (search), and listing all archives (action="list"). - Session-scoped archives: Each archive entry is tagged with the session ID, enabling per-session listing and cleanup.
- TTL-based cleanup: Archives older than
max_age_hours(default 48h) are automatically cleaned up. Configurable viaarchive.max_age_hoursinconfig.tomlorLEAN_CTX_ARCHIVE_TTLenv var. - Idempotent storage: Content-hash-based IDs ensure the same output is never stored twice.
- Config:
archive.enabled,archive.threshold_chars,archive.max_age_hours,archive.max_disk_mbinconfig.toml. Env overrides:LEAN_CTX_ARCHIVE,LEAN_CTX_ARCHIVE_THRESHOLD,LEAN_CTX_ARCHIVE_TTL.
Bidirectional Token Optimization (Terse Agent Mode)
- New
terse_agentconfig: Controls agent output verbosity via instructions injection. Levels:off(default),lite(concise, bullet points),full(max density, diff-only),ultra(expert pair-programmer, minimal narration). - Smart CRP interaction: Terse
lite/fullare skipped when CRP mode istdd(already maximally dense).ultraalways applies as an additional layer. - CLI toggle:
lean-ctx terse <off|lite|full|ultra>for instant switching. - Per-project override:
terse_agent = "full"in.lean-ctx.toml. - Env override:
LEAN_CTX_TERSE_AGENT=full.
Compaction Survival (Session-Resilience)
build_resume_block(): Generates a compact (~500 token) session resume containing task, decisions, modified files, next steps, archive references, and stats.- Automatic injection: The resume block is injected into MCP instructions whenever an active session with tool calls exists, ensuring context survives agent compaction events.
- New
ctx_session(action="resume")action: Explicit retrieval of the resume block for agents that need on-demand session state.
Bug Fixes
ctx_expand not registered in MCP tool listing
- Fixed:
ctx_expandwas implemented (dispatch handler, archive storage, tool definition inlist_all_tool_defs()) but was missing fromgranular_tool_defs()— the function that the MCP server actually uses to build thetools/listresponse. Agents could never discover or callctx_expanddespite the feature being fully coded. Now registered as tool #47.
TerseAgent::effective() ignores environment variable
- Fixed:
TerseAgent::effective()was supposed to letLEAN_CTX_TERSE_AGENToverride the config.toml value, but fell through to the config value when the env var was set to"off". Rewritten to explicitly check the env var first, then fall back to config.
CLI dispatch sync — terse, register, forgot-password not wired in main.rs
- Fixed:
lean-ctx terse,lean-ctx register, andlean-ctx forgot-passwordwere implemented incli/dispatch.rsbut the primary dispatch inmain.rswas missing the match arms. All three commands now work from the CLI. - New:
lean-ctx forgot-password <email>— sends a password reset email via the LeanCTX Cloud API. Previously referenced in help text but not implemented. - Help text: Updated in both
main.rsandcli/dispatch.rsto consistently listterse,register, andforgot-password.
lean-ctx doctor ignores LEAN_CTX_DATA_DIR (Discord: GlemSom)
- Fixed:
doctornow useslean_ctx_data_dir()instead of hardcoded~/.lean-ctxat all 4 locations: shell-hook checks, Docker env.sh path, data directory check, andcompact_score(). Users with customLEAN_CTX_DATA_DIRwill now see correct paths in doctor output.
Windows "path escapes project root" (GitHub Issue #139)
- Fixed:
pathjail.rsnow usessafe_canonicalize_or_self()(which strips the\\?\verbatim prefix) instead of rawstd::fs::canonicalize(). This resolves the mismatch where Windows canonicalized paths (\\?\C:\Users\...) didn't match normal paths (C:/Users/...), causing false "path escapes project root" errors on Windows with Codex. - Windows path normalization hardened:
is_under_prefix_windowsnow strips\\?\prefix before comparison, andallow_paths_from_envuses the safe canonicalization consistently.
Shell Quoting Hardening
Bug fixes — Argument preservation for complex shell commands
- Direct argv execution in
-tmode: Shell aliases (_lc gh,_lc find, etc.) now bypass the argv-to-string-to-argv round-trip entirely when multiple arguments are present.exec_argv()callsCommand::new().args()directly, preserving em-dashes (—),#signs, nested quotes, and all other special characters exactly as the user's shell parsed them. Single-string commands still usesh -cfor backward compatibility. - Single-quote wrapping for hook rewrites:
wrap_single_commandin hook handlers now uses POSIX single-quote escaping ('...'with'\''for embedded single quotes) instead of double-quote escaping. This protects$, backticks,!, and"from unintended expansion when commands are passed through Claude Code, Codex, or Copilot hooks. ghadded to full passthrough: AllghCLI commands (not justgh auth) are now excluded from compression and tracking. The GitHub CLI's output is typically short, and its complex argument patterns (multi-word--commentvalues, issue references with#) are prone to quoting issues.
Code quality
- 20+ new unit tests covering:
exec_direct/exec_argvdirect execution,quote_posixedge cases (em-dash,$, backtick, nested quotes),wrap_single_commandspecial characters ($HOME, backticks,findwith long exclude lists,!), andghfull passthrough verification. - All integration tests updated for new single-quote format.
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.3.4...v3.3.4