Fixed
- Linux:
ctx_*tools broke for projects under/c/…and other
single-letter roots (#397): the MSYS2/Git-Bash drive mapping
(/c/Users/…→C:/Users/…) in the MCP path normalizer ran
unconditionally — on Linux/macOS, where/c/…is a literal directory,
every file-addressing tool then failed withfile not foundon a
nonexistentC:/…path (and absolute arguments were re-joined under the
already-translated root, doubling it). The mapping is now gated on Windows
hosts (cfg!(windows)) — that is the only platform where MSYS2/Git-Bash
clients hand POSIX drive paths to a native Windows binary. On other hosts,
/c/…passes through untouched; regression tests cover both sides. lean-ctx doctorreported "no rules file found" right afterlean-ctx setup
(#396): the 3.8 layout (GL #555) intentionally replaced the always-loaded
~/.claude/rules/lean-ctx.mdwith a CLAUDE.md block + on-demand skill — setup
even removes the legacy file — but the doctor check still demanded it, so a
clean install could never reach a full pass and the suggested fix
(init --agent claude) couldn't recreate the file either. Both doctor views
(doctoranddoctor integrations) now share one layout detector
(claude_instructions_state) that accepts every state setup can produce:
CLAUDE.md block (+ skill), dedicated injection (SessionStart hook + skill),
legacy rules file, project scope, andrules_injection=off. Docs that still
described the retired rules file were updated as well.- macOS still prompted "lean-ctx would like to access files in your Documents
folder" on every upgrade (#356, reopened): the first fix (3.8.0) removed the
scan-heuristic probes, but the prompt actually came from the launchd
daemon's boot path — a process that is its own TCC identity, and whose
grant is invalidated by every update (binary swap → new cdhash → re-prompt).
Traced empirically with a deny-sandbox + crash-stack bisection; two
independent boot-time offenders fixed:servebooted with cwd/and walked every stored session, stat-ing
each session'sproject_root/shell_cwd(project-marker probes +
canonicalize) — paths that usually live under~/Documents. Broad
roots ("/", HOME, agent sandboxes) now bail out before the scan — they
can never own a session (this also stopsshell_cwd.starts_with("/")
from leaking an arbitrary project's session into the daemon default).ContextLedger::load → pruneranrealpathover every persisted ledger
entry at boot for its dedupe key; the key is now lexical-only.
Defense in depth: launchd-owned processes (ppid 1) are detected as
TCC-standalone and never stat/canonicalize paths under
~/Documents/Desktop/Downloadsin heuristics (has_project_marker,
session-root matching,normalize_tool_path); editor/CLI children inherit
their host's TCC grant and keep full behavior. Verified with a
SIGKILL-on-Documents-access sandbox: daemon boot (30 s soak), proxy boot,
and the fulllean-ctx updaterewire now run clean against a real data dir
with 600+ sessions rooted under~/Documents.
- Pi:
ctx_grep/ctx_find/ctx_lssilently searched the wrong directory
(#395):pathwas optional and fell back to the extension's cwd, so an
agent working elsewhere got results from the wrong tree and was derailed;
the calls also rendered without their arguments.pathis now required
(schema + description make the scope explicit), and the three tools reuse
Pi's native call renderers so every invocation shows its pattern and
directory in the transcript. - OpenCode × ChatGPT-OAuth broke behind the proxy (#366):
proxy enable
exportedOPENAI_BASE_URLwithout the/v1suffix the OpenAI SDK convention
expects (default ishttps://api.openai.com/v1). OpenCode therefore sent
Responses-API calls to…:4444/responses— a path its ChatGPT-OAuth plugin
does not recognize (it matches/v1/responses), so subscription traffic
leaked through the proxy to the platform API with the wrong credential:
"Missing scopes: api.responses.write". The shell exports and the Codex CLI
config now advertisehttp://127.0.0.1:<port>/v1; with that base, OpenCode's
OAuth plugin correctly routes ChatGPT-subscription requests directly to
chatgpt.com(analogous to the Claude Pro/Max guard), while API-key traffic
keeps flowing through the proxy. Stale/v1-less entries in Codex
config.tomlare migrated on the nextproxy enable; the proxy also
collapses accidental/v1/v1/…double prefixes from clients that append
/v1themselves. Verified end-to-end against OpenCode 1.2.15. - Dashboard token race:
lean-ctx dashboardpersisted its fresh auth token
before binding the port. Two racing starts both wrotedashboard.token;
the bind loser exited, leaving a token on disk the surviving server never
accepted — every "already running" browser open then hit silent 401s. The
token is now saved only after a successful bind. - Live Activity feed masked errors as "No events recorded yet": a failed
/api/eventspoll (daemon restart, expired token, timeout) was rendered as
an empty feed. The dashboard now keeps the last known events and shows the
actual error with a recovery hint instead. - Status bar showed "No session" while agents were active:
/api/session
matched sessions against the dashboard process's own cwd (usually HOME — a
broad root that rightly matches nothing). It now falls back to the most
recently updated session rooted in a real project.
Performance
/api/eventsno longer re-parses the event log on every poll: the
file-backed event load is cached on (path, mtime, length) — the 3-second
dashboard poll now costs astat()instead of reading and parsing up to
10k JSONL lines.
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.2...v3.8.2