13 KiB
Appendix — Paths, Env Vars & Config
Where lean-ctx stores everything, every environment variable that changes its
behavior, and every config section. Source: rust/src/core/data_dir.rs,
rust/src/core/config/.
1. Directories (XDG Base Directory layout)
Since GH #408 lean-ctx separates its files into the standard XDG categories so
the config dir can be mounted read-only. Typed resolvers live in
rust/src/core/paths.rs (config_dir(), data_dir(), state_dir(),
cache_dir(), runtime_dir()).
| Category | Default | Override | Contents |
|---|---|---|---|
| Config | $XDG_CONFIG_HOME/lean-ctx (~/.config/lean-ctx) |
LEAN_CTX_CONFIG_DIR |
config.toml, env.sh, shell-hook.* — RO-safe |
| Data | $XDG_DATA_HOME/lean-ctx (~/.local/share/lean-ctx) |
LEAN_CTX_DATA_DIR |
sessions/, vectors/, graphs/, knowledge/, archives/, memory/, packages/, agents/, stats.json, client-id.json |
| State | $XDG_STATE_HOME/lean-ctx (~/.local/state/lean-ctx) |
LEAN_CTX_STATE_DIR |
events.jsonl, journal.md, *.log, mcp-live.json, heatmap.json, pipeline_stats.json, cost_attribution.json, context_ledger.json, cooccurrence/, tee/, dashboard.token, agent_runtime_env.json (0600) |
| Cache | $XDG_CACHE_HOME/lean-ctx (~/.cache/lean-ctx) |
LEAN_CTX_CACHE_DIR |
semantic_cache/, models/, anomaly_detector.json, *_learned.json, litm_calibration.json, context_ir_v1.json, latest-version.json, .first_run_wow_done |
| Runtime | dirs::data_local_dir()/lean-ctx |
— | daemon.pid, daemon.sock, daemon-*.log, *.lock |
Unix dir permissions: 0700. The Runtime dir is the OS data-local dir
(~/.local/share/lean-ctx on Linux, ~/Library/Application Support/lean-ctx on
macOS); it holds only daemon IPC and is intentionally separate from the data dir.
Resolution order (per category)
Each resolver applies the same three steps:
- Explicit override —
LEAN_CTX_<CATEGORY>_DIRset & non-empty → wins. - Single-dir backward-compat — existing installs never split silently. If
LEAN_CTX_DATA_DIRpoints at a non-standard path, or legacy~/.lean-ctxholds data, or mixed$XDG_CONFIG_HOME/lean-ctxholds data (the pre-#408 layout), then all categories collapse onto that one directory — byte-for-byte the old behavior. - XDG split default — a fresh install uses the per-category default above.
"Holds data" = contains a data marker (stats.json, sessions/, vectors/,
graphs/, knowledge/). config.toml/hooks alone do not count, so a
config-only dir does not pin the other categories back onto it.
Data-only pin (GH #594). A
LEAN_CTX_DATA_DIRequal to the standard data dir ($XDG_DATA_HOME/lean-ctx) is treated as a data pin only and does not collapse config/state/cache. Older versions baked exactly that value into editor MCPenvblocks; honoring it as single-dir made the MCP server readconfig.tomlfrom the data dir while the CLI read it from the config dir. Now both keep the XDG split, so they always read the same config.
Don't hardcode
LEAN_CTX_DATA_DIRin editor MCP configs — a custom path still forces the legacy single-dir layout. Leave it unset for the clean XDG split; existing installs are auto-detected and keep working, andsetup/updatestrip any stale pin a previous version may have written.
Migrate an existing install to the split (opt-in)
Legacy/mixed installs keep working in single-dir mode. To adopt the four-dir layout on demand:
| Command | Effect |
|---|---|
lean-ctx doctor |
Reports XDG layout: N item(s) in single dir when a split is available |
lean-ctx doctor --fix |
Moves data/state/cache out of the config dir into their XDG homes |
The migration is all-or-nothing (partial moves would re-collapse via
back-compat), idempotent/resumable (existing destinations are skipped, never
clobbered) and crash-safe (atomic rename, copy+remove fallback across
filesystems; the source is removed only after a successful copy). An explicit
LEAN_CTX_DATA_DIR is treated as a deliberate single-dir choice and is never
auto-split; runtime files are left in place.
Read-only config sandbox (the #408 goal)
Once split, the config dir holds only config.toml + hooks, so it can be mounted
read-only while the writable categories live elsewhere:
--ro $XDG_CONFIG_HOME/lean-ctx # config.toml, shell hooks
--rw $XDG_DATA_HOME/lean-ctx # sessions, vectors, graphs, knowledge
--rw $XDG_STATE_HOME/lean-ctx # events, journals, logs, ledgers
--tmpfs $XDG_CACHE_HOME/lean-ctx # semantic cache, models (regenerable)
# runtime (daemon.pid/sock) lives in the OS data-local dir
Project-local lean-ctx data (in the repo, not these dirs): .lean-ctx.toml
(project config override), .lean-ctx-id, .lean-ctx/.
2. Environment variables
There are ~120 env vars; the ones you'll actually touch are below. The full list
is in rust/src/core/config/. Most have a matching config.toml key — the env
var always wins.
The ones you'll use
| Variable | Purpose | Default |
|---|---|---|
LEAN_CTX_DISABLED=1 |
Bypass ALL compression + disable shell hook | unset |
LEAN_CTX_RAW=1 |
Uncompressed output for one command | unset |
LEAN_CTX_DATA_DIR |
Explicit data dir; a custom path also forces legacy single-dir mode (a standard-path pin is data-only, see §1) | $XDG_DATA_HOME/lean-ctx |
LEAN_CTX_CONFIG_DIR |
Explicit config dir (config.toml, hooks) |
$XDG_CONFIG_HOME/lean-ctx |
LEAN_CTX_STATE_DIR |
Explicit state dir (events, logs, ledgers) | $XDG_STATE_HOME/lean-ctx |
LEAN_CTX_CACHE_DIR |
Explicit cache dir (semantic cache, models) | $XDG_CACHE_HOME/lean-ctx |
LEAN_CTX_PROJECT_ROOT |
Explicit project root | auto-detected |
LEAN_CTX_TOOL_PROFILE |
minimal|standard|power |
config / power |
LEAN_CTX_PROFILE |
Active context profile | config / coder |
LEAN_CTX_COMPRESSION |
off|lite|standard|max |
config / lite |
LEAN_CTX_RESEARCH_PROSE_CAP |
Proxy research prose squeeze cap in bytes | 20000 |
LEAN_CTX_MEMORY_PROFILE |
low|balanced|performance |
performance |
LEAN_CTX_PROXY_PORT |
Proxy port | 4444 |
LEAN_CTX_NO_UPDATE_CHECK=1 |
Disable update check | unset |
LEAN_CTX_ALLOW_PATH |
Extra PathJail roots (path list; see §5) | unset |
LEAN_CTX_EXTRA_ROOTS |
Multi-root workspace roots (path list; see §5) | unset |
Provider tokens (for ctx_provider)
GITHUB_TOKEN / GH_TOKEN, GITLAB_TOKEN / CI_JOB_TOKEN, JIRA_URL +
JIRA_EMAIL + JIRA_TOKEN, DATABASE_URL. Optional LLM enhance:
OPENROUTER_API_KEY, ANTHROPIC_API_KEY.
Internal (set by lean-ctx itself — don't set these)
LEAN_CTX_MCP_SERVER, LEAN_CTX_ACTIVE, LEAN_CTX_HOOK_CHILD,
LEAN_CTX_HEADLESS, LEAN_CTX_PLUGIN_DIR, etc.
3. Config file (config.toml)
Global at <CONFIG_DIR>/config.toml ($XDG_CONFIG_HOME/lean-ctx/config.toml,
or the single dir for legacy/mixed installs — see §1); per-project override at
<repo>/.lean-ctx.toml (merged, project wins). Manage with lean-ctx config
(set, schema, validate, show).
Sections
| Section | What it controls |
|---|---|
| (root keys) | compression, cache, shell hook, profiles, memory caps, savings footer, proxy tri-state |
[tools] |
profile (minimal/standard/power), explicit enabled list |
[setup] |
auto_inject_rules, auto_inject_skills, auto_update_mcp |
[archive] |
Zero-loss tool-output archive: enabled, threshold_chars (800), max_age_hours (48), max_disk_mb (500) |
[search] |
BM25/dense/splade weights + candidate counts |
[autonomy] |
Auto preload/dedup/consolidate, cognition loop |
[providers] |
GitHub/GitLab/Jira/Postgres + MCP bridges |
[loop_detection] |
Per-tool call limits to prevent agent loops |
[updates] |
auto_update, check_interval_hours (6), notify_only |
[boundary_policy] |
Cross-project search/import + universal gotchas |
[secret_detection] |
Secret redaction in output |
[cloud] |
contribute_enabled + sync timestamps |
[proxy] |
Upstream URLs for Anthropic/OpenAI/Gemini |
[memory.*] |
Knowledge/episodic/procedural/lifecycle/gotcha/embeddings caps |
[llm] |
Optional local LLM enhance (Ollama) |
Key defaults worth knowing:
compression_level = "lite"(root) — light compression on by default.savings_footer = "always"config default, but theSavingsFooterenum default isNeverso no inline footer tokens are emitted unless enabled.memory_profile = "performance",memory_cleanup = "aggressive".[memory.knowledge] max_facts = 200— the source of doctor's "facts at capacity" warning.
4. Files written outside the lean-ctx dirs
| Category | Examples | Written by |
|---|---|---|
| Shell hook | ~/.zshenv, ~/.bashenv, fish, PowerShell profile |
setup step 1 / init --global |
| Agent aliases | ~/.zshrc, ~/.bashrc (lean-ctx-on/off/mode/status) |
setup / init --global |
| MCP configs | ~/.cursor/mcp.json, ~/.claude.json, ~30 editors |
setup step 3 / init --agent |
| Agent rules (opt-in) | ~/.cursor/rules/lean-ctx.mdc, AGENTS.md blocks |
setup step 4 |
| Skills (opt-in) | ~/.claude/skills/lean-ctx/, … |
setup step 6 |
| Proxy env (opt-in) | RC exports, ~/.claude/settings.json, Codex config.toml |
proxy enable |
| Autostart | ~/Library/LaunchAgents/com.leanctx.{proxy,daemon,autoupdate}.plist; systemd user units on Linux |
setup steps 5/9 |
| Binary | ~/.local/bin/lean-ctx |
installer / dev-install |
Every edit to an existing file goes through config_io::write_atomic, which
writes a *.lean-ctx.bak backup first. Rules injection only rewrites content
between <!-- lean-ctx --> markers — your own content is preserved.
lean-ctx uninstall reverses all of the above.
5. Filesystem boundary — path_jail, allow_paths, extra_roots (GH #392)
All tool file access (ctx_read, ctx_edit, ctx_tree, …) is jailed under the
current project_root (PathJail). Three knobs widen or remove that boundary —
they overlap, so here is exactly what each one does:
| Knob | Effect | Use when |
|---|---|---|
allow_paths = ["…"] (root key) |
Adds directories to PathJail's whitelist. Tools may read/edit under them, but ctx_tree/ctx_search do not scan them. |
One extra directory needs to be readable/editable (e.g. a shared skills folder). |
extra_roots = ["…"] (root key) |
Same whitelist effect as allow_paths plus multi-root scanning: ctx_tree, ctx_search, overview treat them as additional project roots. |
Multi-repo workspaces. |
path_jail = false (root key) |
Disables PathJail entirely — every absolute path is allowed. | Sandboxed environments (bwrap, containers, VMs) where the OS is the boundary. |
allow_ide_config_dirs = true (root key) |
Adds every supported editor's config dir to the read whitelist — registry-derived (~/.cursor, VS Code, Cline/Roo, JetBrains, …). Opt-in; exposes other agents' sessions/credentials. |
Letting the agent manage MCP setup across editors. |
Env equivalents (path-list syntax, : on Unix / ; on Windows):
LEAN_CTX_ALLOW_PATH (= allow_paths), LEAN_CTX_EXTRA_ROOTS (= extra_roots).
Notes that save debugging time:
~,$VARand${VAR}are expanded inallow_paths/extra_roots/ the env vars (since v3.8.1). On older versions"$HOME/code"was matched literally and silently never applied.allow_paths = ["/"]technically whitelists everything; prefer the explicitpath_jail = false—lean-ctx doctorflags the"/"pattern.- Config changes are picked up on the next tool call (mtime-based reload); no
MCP server restart needed. If a change appears to do nothing, run
lean-ctx doctor: it reports config parse errors (a brokenconfig.tomlsilently falls back to defaults) and deadallow_pathsentries (unset$VAR, missing directory), plus the effective jail state. - Compile-time off-switch: building with the
no-jailcargo feature removes the jail entirely (for trusted single-user builds). - Removed: the
LEAN_CTX_NO_JAIL=1env var (≤ 3.7.3). It was replaced by thepath_jail = falseconfig key and theno-jailcompile feature; setting the old env var has no effect on current versions. - Home-level IDE config dirs are excluded from the jail's whitelist by default.
Opt in with
allow_ide_config_dirs = true(orLEAN_CTX_ALLOW_IDE_DIRS=1): the allow-list is derived from the editor registry, so it covers every supported editor — including non-dotfile layouts like VS Code (~/Library/Application Support/Code/User), Cline/Roo and JetBrains — and never drifts as editors are added.~/.lean-ctxis always allowed, and a config file that lives directly in$HOMEnever widens the jail to the whole home directory.lean-ctx setupasks once (informed consent) and the relaxation is audited bylean-ctx doctor. These dirs expose other agents' sessions and credentials.