Skip to main content

Module pathutil

Module pathutil 

Source

Constants§

AGENT_CONFIG_DIRS
Agent/IDE CLI config or sandbox directories some clients launch their MCP server from, but which are never a user’s project root. Adopting one as the project root jails every real repository path out — the root cause of #580 (GitHub Copilot CLI launches from ~/.copilot; Cursor, Windsurf, Gemini CLI and LM Studio behave similarly). This is the canonical set: every “is this an agent dir?” check across the codebase delegates here so the list never drifts.
PROJECT_MARKERS
Well-known project markers used to identify project roots.

Functions§

canonicalize_secure
SECURITY canonicalize: always resolves symlinks, even under ~/Documents in a launchd-standalone process. PathJail relies on this to detect symlink jail escapes (#356 must never weaken the security boundary). A standalone process only reaches here for a path the client explicitly asked to access, where a one-time TCC prompt is legitimate — unlike the self-initiated heuristic probes that safe_canonicalize suppresses.
canonicalize_secure_bounded
SECURITY variant of safe_canonicalize_bounded — bypasses the #356 TCC guard so PathJail keeps resolving symlinks to detect jail escapes. See canonicalize_secure for why a prompt here (explicit request) is legitimate.
canonicalize_secure_or_self
Like canonicalize_secure but returns the original path on failure.
has_multi_repo_children
Returns true if dir is a multi-repo workspace parent — i.e. it has at least 2 immediate child directories that each contain a project marker.
has_project_marker
Returns true if dir contains at least one known project marker.
home_dirs
Every spelling of the user’s home directory a root guard must refuse: the profile folder (dirs::home_dir, which on Windows ignores the environment) and the override-friendly home (HOME/USERPROFILE, crate::core::home::resolve_home_dir). On Unix both are $HOME and one entry remains.
is_agent_config_dir
Returns true if dir is — or lies inside — a known agent/IDE config dir (AGENT_CONFIG_DIRS). Separator-agnostic so Windows backslash paths (C:\Users\me\.copilot) match too; #580 is a Windows Copilot report.
is_broad_or_unsafe_root
Returns true if the directory is too broad to be a valid project root. Rejects home directories (including WSL-mounted Windows profiles), filesystem root, . (bare CWD), agent/IDE config directories (AGENT_CONFIG_DIRS) and LeanCTX’s own stores (is_lean_ctx_store_dir). Used to prevent adopting a bogus project root and writing project-scoped data into the global ~/.lean-ctx/ data directory.
is_data_dir_collision
Returns true if project_root collides with the lean-ctx data directory. This prevents project-scoped files (overlays.json, policies.json) from being written into ~/.lean-ctx/ or ~/.config/lean-ctx/.
is_lean_ctx_store_dir
dir is LeanCTX’s data, state, config or cache directory itself. A CLI started there without a project (the Cockpit’s fallback working directory) must never adopt it as a project. Folders inside a store stay allowed: setups and fixtures with LEAN_CTX_DATA_DIR in a temp dir keep their projects there. Resolved read-only: nothing is created. Both sides are compared as given and canonical, so another spelling of the same folder (a symlink, macOS /var → /private/var) matches too.
is_suspicious_root
A startup root the server must not adopt as a jail root: too broad (is_broad_or_unsafe_root) or an agent/IDE config directory.
is_symlink_or_reparse
Returns true if the (lstat) metadata describes a symlink — or, on Windows, any reparse point (junctions, mount points, app-exec links).
is_tcc_sensitive_home_dir
Returns true if dir is the home directory or one of the macOS “magic” home subdirectories (Documents, Desktop, Downloads).
is_under_tcc_protected_dir
Returns true if path lies inside (or is) one of the macOS TCC-protected home folders (~/Documents, ~/Desktop, ~/Downloads). Pure string/path comparison — performs no filesystem access itself.
is_windows_absolute_path
A Windows absolute path (C:\…, C:/…) or UNC path (\\server, //server), recognised lexically on every platform.
may_probe_path
Returns true when this process may stat/read_dir/canonicalize path without risking a macOS TCC privacy prompt in lean-ctx’s name.
normalize_tool_path
normalize_tool_path_lexical
Lexical (string-only) part of normalize_tool_path: MSYS2 drive prefix (Windows hosts only), separators, double slashes, trailing slash. Performs no filesystem access, so it is safe on persisted paths in TCC-standalone processes (launchd daemon, #356) and as a dedupe key where symlink resolution is not worth a realpath per entry.
process_is_tcc_standalone
Returns true when this process is its own TCC identity on macOS — i.e. it was started (or re-parented) by launchd rather than by a TCC-granted host like a terminal or an editor.
safe_canonicalize
Canonicalize a path and strip the Windows verbatim/extended-length prefix (\\?\) that std::fs::canonicalize adds on Windows. This prefix breaks many tools and string-based path comparisons.
safe_canonicalize_bounded
Canonicalize with a timeout guard. Protects against hangs on WSL2 DrvFS, Windows reparse points, NFS, FUSE, sshfs, and other slow filesystems. Falls back to the original path if canonicalize doesn’t complete within the timeout. Self-healing: after a timeout, subsequent calls to slow mounts skip the thread entirely.
safe_canonicalize_or_self
Like safe_canonicalize but returns the original path on failure.
safe_project_data_dir
Returns the project-scoped .lean-ctx/ directory if the project root is safe. Returns Err if the project root collides with the global data directory.
same_project
Normalize paths from any client format to a consistent OS-native form. Handles MSYS2/Git Bash drive prefixes on Windows hosts (/c/Users/... -> C:/Users/...), mixed separators, double slashes, and trailing slashes. Uses forward slashes for consistency. On non-Windows hosts /c/... is a literal directory and passes through unchanged (#397). Whether two recorded project roots name the same project: equal after separator and trailing-slash normalization, or after resolving symlinks. The one comparison for project-scoped records (agents, messages, shares): a raw string comparison split one project into several by spelling.
strip_verbatim
Remove the \\?\ / //?/ verbatim prefix from a PathBuf. Handles both regular verbatim (\\?\C:\...) and UNC verbatim (\\?\UNC\...).
strip_verbatim_str
Remove the \\?\ / //?/ verbatim prefix from a path string. Returns Some(cleaned) if a prefix was found, None otherwise.