patholog 1.0.0

Diagnose, explain, clean, and safely repair PATH behavior.
Documentation
# patholog

Diagnose and fix PATH problems across macOS, Linux, and Windows.

[![GitHub Release](https://img.shields.io/github/v/release/techouse/patholog?logo=github)](https://github.com/techouse/patholog/releases/latest)
[![Crates.io Version](https://img.shields.io/crates/v/patholog?logo=rust)](https://crates.io/crates/patholog)
[![Crates.io MSRV](https://img.shields.io/crates/msrv/patholog?logo=rust)](https://crates.io/crates/patholog)
[![Test](https://github.com/techouse/patholog/actions/workflows/test.yml/badge.svg)](https://github.com/techouse/patholog/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/techouse/patholog/graph/badge.svg?token=qsdPHsjKcq)](https://codecov.io/gh/techouse/patholog)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/44b97859730f460c82a22c72ee21f8ed)](https://app.codacy.com/gh/techouse/patholog/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[![GitHub](https://img.shields.io/github/license/techouse/patholog)](https://github.com/techouse/patholog/blob/main/LICENSE)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/techouse?logo=github)](https://github.com/sponsors/techouse)
[![GitHub Repo stars](https://img.shields.io/github/stars/techouse/patholog)](https://github.com/techouse/patholog/stargazers)

`patholog` explains why a command resolves to a particular executable, shows competing matches, diagnoses common PATH problems, scans shell startup files read-only, prints cleaned PATH proposals, and applies tightly scoped shell profile repairs through a managed block.

## Installation

Install the CLI from crates.io:

```sh
cargo install patholog
```

Prebuilt release archives are available from the
[GitHub releases page](https://github.com/techouse/patholog/releases). Archives include the `patholog` binary,
shell completions, the README, the project license, and third-party license notices.

## Quick Examples

```sh
patholog doctor
patholog health --json
patholog doctor --command python
patholog why python
patholog why-not poetry
patholog conflicts cargo
patholog scan
patholog clean --stdout
patholog clean --stdout --drop /sw/bin
patholog clean --export --var manpath --shell zsh
patholog clean --export --shell zsh
patholog apply --dry-run --shell zsh
patholog apply --shell zsh --yes
patholog config check --config patholog.toml
patholog completions zsh
```

## Why It Exists

PATH problems are usually invisible until the wrong tool runs. `patholog` is built for cases like:

- `python`, `node`, or `cargo` resolving to an unexpected executable.
- duplicate PATH entries hiding the real search order.
- missing directories left behind by old installers.
- unreadable PATH entries or shadowed command candidates.
- Cargo, Homebrew, pyenv, nvm, or system directories appearing in surprising order.
- shell config drift between machines.

The goal is to explain before changing anything.

## Command Surface

```sh
patholog print [--json] [--platform auto|posix|windows] [--var path|manpath]
patholog doctor [--json] [--platform auto|posix|windows] [--var path|manpath] [--drop <entry>] [--preset homebrew|cargo|pyenv|fink] [--fail-on=missing,duplicate,...] [--command <command>] [--config <file|auto>]
patholog health [--json] [--platform auto|posix|windows] [--var path|manpath] [--drop <entry>] [--preset homebrew|cargo|pyenv|fink] [--config <file|auto>]
patholog why <command> [--json] [--platform auto|posix|windows]
patholog why-not <command> [--json] [--platform auto|posix|windows]
patholog conflicts <command> [--json] [--platform auto|posix|windows]
patholog scan [--json] [--platform auto|posix|windows] [--home <dir>]
patholog clean --stdout [--platform auto|posix|windows] [--var path|manpath] [--drop <entry>] [--preset homebrew|cargo|pyenv|fink] [--config <file|auto>]
patholog clean --export --shell zsh|bash|fish|pwsh [--platform auto|posix|windows] [--var path|manpath] [--drop <entry>] [--preset homebrew|cargo|pyenv|fink] [--config <file|auto>]
patholog apply --dry-run --shell zsh|bash|fish|pwsh [--json] [--platform auto|posix|windows] [--home <dir>] [--profile <file>] [--drop <entry>] [--preset homebrew|cargo|pyenv|fink] [--config <file|auto>]
patholog apply --shell zsh|bash|fish|pwsh --yes [--no-backup] [--json] [--platform auto|posix|windows] [--home <dir>] [--profile <file>] [--drop <entry>] [--preset homebrew|cargo|pyenv|fink] [--config <file|auto>]
patholog config check --config <file|auto>
patholog config print --config <file|auto> [--json]
patholog completions zsh|bash|fish|pwsh
```

`patholog` mutates files only for `apply --yes`. Other commands do not edit shell profiles, environment variables, or files.

## Read-Only Diagnostics

`doctor` reports duplicate, missing, non-directory, unreadable, empty, explicitly unwanted, and suspiciously ordered PATH entries. With `--command`, it also reports executable candidates shadowed by an earlier winner:

```sh
patholog doctor --command python
patholog doctor --drop /sw/bin --fail-on=unwanted
```

`health` summarizes those diagnostics as an advisory deterministic score, issue counts, worst severity, and the diagnostics used to compute the score:

```sh
patholog health --json
patholog health --var manpath
```

Example JSON excerpt:

```json
{
  "score": 85,
  "healthy": false,
  "worst_severity": "error",
  "counts": {
    "missing": 1
  }
}
```

Use `doctor --fail-on` when you need a CI gate; `health` always exits `0` when the summary is calculated successfully.

`--var manpath` switches `print`, `doctor`, `health`, and `clean` to `MANPATH`. Command resolution and profile planning stay PATH-only. `clean --var manpath` preserves empty MANPATH components because common man implementations use them to include the system default manpath.

`scan` reads known shell startup profiles under the home directory and reports likely PATH mutation lines. It does not source or edit those files:

```sh
patholog scan
patholog scan --home /tmp/example-home
```

## Output Modes

Human output is the default. JSON output is available for `print`, `doctor`, `health`, `why`, `why-not`, `conflicts`, `scan`, and `apply`:

```sh
patholog doctor --json
patholog health --json
patholog why python --json
patholog why-not poetry --json
patholog scan --json
```

`why-not` explains missing-command cases by combining exact PATH lookup, related executable hints, PATH health diagnostics, and safe advisory next checks. It is read-only and does not run package managers or edit shell configuration.

`clean --stdout` prints a raw PATH or MANPATH string suitable for review or manual export. `clean --export` prints a shell-ready assignment snippet for `zsh`, `bash`, `fish`, or `pwsh`:

```sh
patholog clean --export --shell zsh
patholog clean --export --var manpath --shell zsh
```

`completions` prints shell completion scripts to stdout:

```sh
patholog completions zsh
```

`apply --dry-run` plans a shell profile edit without writing files. `apply --yes` writes the same managed block, creates backups for existing profiles by default, and never rewrites arbitrary PATH lines outside the patholog block:

```sh
patholog apply --dry-run --shell zsh
patholog apply --dry-run --shell zsh --json
patholog apply --dry-run --shell zsh --drop /sw/bin
patholog apply --shell zsh --yes
patholog apply --shell zsh --yes --no-backup
```

`--preset fink` marks `/sw/bin` and `/sw/sbin` as unwanted for PATH, and `/sw/share/man` as unwanted for MANPATH. `homebrew`, `cargo`, and `pyenv` presets enable ecosystem policy checks without automatically reordering entries.

## Config Files

`--config <file>` lets `doctor`, `health`, `clean`, and `apply` load declarative policy defaults. CLI flags append after config values:

```toml
version = 1

[path]
drop = ["/sw/bin"]
preset = ["homebrew", "cargo"]
fail_on = ["duplicate", "unwanted"]

[manpath]
drop = ["/sw/share/man"]
preset = ["fink"]
fail_on = ["duplicate"]
```

Use `patholog config check --config patholog.toml` to validate a file, or `patholog config print --config patholog.toml --json` to inspect normalized policy. `--config auto` searches only the current working directory for `patholog.toml`, then `.patholog.toml`.

`health` uses config `drop` and `preset` policy for scoring, but `fail_on` remains specific to `doctor`.

## Exit Codes

- `0`: success
- `1`: usage or runtime error
- `2`: `doctor --fail-on` matched selected diagnostics
- `3`: command not found for `why`, `why-not`, or `conflicts`

## Platform Model

- `auto` uses host platform rules.
- `posix` uses `:` separators and case-sensitive comparison keys.
- `windows` uses `;` separators, case-insensitive comparison keys, and PATHEXT modeling.

Windows command resolution differs from POSIX lookup because file extensions and `PATHEXT` affect which executable wins. `patholog --platform windows` models that behavior for tests and cross-platform inspection.

PATH values are handled as UTF-8 strings to preserve v0.1 parity. Symlinks, inode identity, and canonical-file identity are not analyzed.

## Safety

All commands are read-only except `apply --yes`, which writes only the patholog-managed block in the selected shell
profile. When the selected target is `~/.zshrc`, `~/.bashrc`, `~/.profile`, or a PowerShell profile, `patholog` may
create, append, or replace that managed block, but it does not rewrite arbitrary profile content outside the block or
edit system environment configuration.

`clean --stdout`, `clean --export`, `apply --dry-run`, and `completions` only print generated text. Mutating `apply` requires `--yes` and backs up existing profiles unless `--no-backup` is passed.

## Development

```sh
make ci
make install-smoke
make v1-contract-check
make pre-release
```

Use `make ci` for normal local checks, `make install-smoke` to test the packaged crate in a temporary install root,
`make v1-contract-check` for the v1 contract audit, and `make pre-release` as the full gate before tagging a
release.

Golden parity fixtures are vendored in `tests/fixtures/golden`.