Metadata-Version: 2.4
Name: sarand-cli
Version: 0.6.20
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Requires-Dist: filelock>=3.14,<4
Requires-Dist: rich>=13.0
Requires-Dist: tomli>=2.0 ; python_full_version < '3.11'
Requires-Dist: pyyaml>=6.0
Requires-Dist: pytest>=8.0 ; extra == 'dev'
Requires-Dist: ruff>=0.16 ; extra == 'dev'
Requires-Dist: mypy>=1.10 ; extra == 'dev'
Requires-Dist: bandit>=1.9 ; extra == 'dev'
Requires-Dist: pip-audit>=2.10 ; extra == 'dev'
Requires-Dist: types-pyyaml ; extra == 'dev'
Provides-Extra: dev
License-File: LICENSE
Summary: Cross-platform CLI that scans any project, detects its architecture, runs its tests, and generates an AI-ready intelligence report.
Keywords: cli,project-analysis,ai-context,code-intelligence,static-analysis
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/msoleimani62/sarand/blob/main/CHANGELOG.md
Project-URL: Homepage, https://github.com/msoleimani62/sarand
Project-URL: Issues, https://github.com/msoleimani62/sarand/issues
Project-URL: Repository, https://github.com/msoleimani62/sarand

<h1 align="center"><img src="https://raw.githubusercontent.com/msoleimani62/sarand/main/assets/banner.svg" alt="sarand" width="100%"></h1>

<p align="center">
  <b>English</b> · <a href="https://github.com/msoleimani62/sarand/blob/main/README.fa.md">فارسی</a>
</p>

<p align="center">
  <a href="https://github.com/msoleimani62/sarand/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/msoleimani62/sarand/actions/workflows/ci.yml/badge.svg"></a>
  <a href="https://github.com/msoleimani62/sarand/tags"><img alt="Version" src="https://img.shields.io/github/v/tag/msoleimani62/sarand?label=version&color=2dd4bf"></a>
  <img alt="Python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-3776ab?logo=python&logoColor=white">
  <img alt="Rust core" src="https://img.shields.io/badge/core-Rust%20%2B%20PyO3-dea584?logo=rust&logoColor=white">
  <img alt="Platforms" src="https://img.shields.io/badge/platforms-Linux%20%C2%B7%20macOS%20%C2%B7%20Windows%20%C2%B7%20Termux-a78bfa">
  <a href="https://github.com/msoleimani62/sarand/blob/main/LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-22c55e"></a>
</p>

<p align="center">
  <b>Point it at any codebase. Get one report an AI assistant can actually use.</b>
</p>

<p align="center">
  <a href="#quick-start">Quick start</a> ·
  <a href="#install">Install</a> ·
  <a href="#usage">Usage</a> ·
  <a href="#whats-in-the-report">The report</a> ·
  <a href="#more-tools">More tools</a> ·
  <a href="#uninstall">Uninstall</a>
</p>

---

> **Not to be confused with** [Sarand](https://github.com/beiko-lab/sarand), a
> bioinformatics tool for antimicrobial-resistance gene neighbourhoods. This is an
> unrelated developer tool.

sarand scans a project, works out what it is, runs its tests, linters and security checks, and writes **one file** with everything an AI coding assistant needs: the project tree, the full source, the results, a health score and a written summary. Run it *before* you hand a codebase to an assistant, so the assistant starts with facts instead of guesses.

## Why sarand

<table>
  <tr>
    <td width="50%" valign="top"><b>One command, one file</b><br>Tree, source, test results, lint output, security findings and a health score, in a single Markdown, JSON, text, HTML, PDF or SARIF file.</td>
    <td width="50%" valign="top"><b>Written for AI</b><br>Includes an AI summary and a suggested reading order, so a model knows where to look first.</td>
  </tr>
  <tr>
    <td valign="top"><b>41 language and format analyzers</b><br>Python, Rust, Go, Node.js, TypeScript, C/C++, Java, Kotlin, Android, C#, Swift, PHP, Ruby, Lua, Dart, Zig, Haskell, Elixir, Erlang, Scala, shell, SQL, Nix, assembly (with its dialect) and more, plus Dockerfile, Kubernetes (Helm and Kustomize), GitHub Actions, Terraform, Protobuf, YAML, JSON, TOML, XML and Markdown. See the <a href="https://github.com/msoleimani62/sarand/blob/main/docs/COVERAGE.md">coverage matrix</a>.</td>
    <td valign="top"><b>Safe by default</b><br>Files that contain secrets, and credential-shaped files, are left out of the report. With <code>--security</code> the git history is scanned too.</td>
  </tr>
  <tr>
    <td valign="top"><b>Fast, and never blocked</b><br>The heavy scanning runs in a Rust core. If it is not available, an equivalent pure-Python scanner takes over. A missing tool is skipped with a hint, never a crash.</td>
    <td valign="top"><b>Cross-platform by design</b><br>Meant to behave the same on Linux, macOS, Windows and Android (Termux). CI runs on all three desktop systems.</td>
  </tr>
</table>

## Quick start

Install it once with [pipx](https://pipx.pypa.io) (Python 3.10+; no Rust needed, the wheels are prebuilt):

```bash
pipx install sarand-cli
sarand --version
```

Other ways (from source, Arch, development) are under [Install](#install).

Then run it inside any project:

```bash
cd ~/my-project
sarand --full
```

The last lines tell you where the report went (by default the `Downloads` folder). Example output:

```text
→ Detected: Rust, Python (cargo)
→ Scan engine: Rust core
→ Running tests (Python, Rust, Shell, JSON, TOML, Markdown)...
→ Running quality checks (Python, Rust, Shell, JSON, TOML, Markdown)...
→ Running security checks (Python, Rust, Shell, JSON, TOML, Markdown)...
→ Rendering Markdown report...
✓ Report completed

============================================================
Project: /home/you/my-project
Detected: Rust, Python
Engine  : Rust core
Output  : /home/you/Downloads/sarand-my-project-report.md
Files   : 163 included / 0 skipped / 1 excluded (secrets)
Health  : 76.0/100 (C)
============================================================
```

> [!TIP]
> Run `sarand --doctor` first if you want to see which tools are installed and how to add the missing ones.

## How it works

```mermaid
flowchart LR
    P[("Your project")] --> D["Detect languages<br/>and layout"]
    D --> S["Rust core scan<br/>tree, stats, hashes"]
    D --> A["Language analyzers<br/>tests, quality, security"]
    D --> G["Git, environment,<br/>TODOs, secrets"]
    S --> H["Health score<br/>and AI summary"]
    A --> H
    G --> H
    H --> R{"Renderer"}
    R --> O1["Markdown"]
    R --> O2["JSON, text, HTML"]
    R --> O3["PDF, SARIF"]
    O1 --> AI(["Your AI assistant"])
```

The CPU-heavy part (walking the tree, counting lines, hashing files to find duplicates) is a Rust crate exposed to Python through [PyO3](https://pyo3.rs) and [maturin](https://www.maturin.rs). Everything that changes often, the analyzers, renderers, health score and CLI, is plain Python. If the Rust extension cannot be built or loaded on your platform, sarand falls back to a pure-Python scanner that produces the same report, only slower.

## What's in the report

| Section | What it tells you |
|---|---|
| Detected project | Languages, build tools and entry points |
| Environment | OS, CPU, memory and toolchain versions |
| Git | Branch, dirty state and recent history |
| Health score | 0–100 with a grade and concrete recommendations |
| AI summary | A written overview and a suggested reading order |
| Project statistics | Files, lines and language breakdown |
| TODO / FIXME markers | Every marker, with its location |
| Test results | Pass or fail per language, with output |
| Quality checks | Linters, formatters and type checkers (`--quality`) |
| Security checks | Vulnerability, secret and supply-chain checks (`--security`) |
| Known issues | Problems sarand recognised in the tool output |
| Project tree and files | The tree and, unless you pass `--no-source`, every included file |

<details>
<summary><b>Which tools does sarand use for each language?</b></summary>

<br>

sarand drives the standard tools of each ecosystem. Nothing here is required: a tool that is not installed is skipped and `sarand --doctor` tells you how to install it.

| Ecosystem | Tools sarand can drive |
|---|---|
| Python | tests: `pytest` · quality: `ruff`, `mypy` · security: `pip-audit`, `bandit` |
| Rust | tests: `cargo` · quality: `rustfmt`, `cargo-clippy` · security: `cargo-audit`, `cargo-deny` |
| Go | tests: `go` · quality: `staticcheck` · security: `govulncheck` |
| Node.js | tests: `npm` · quality: `eslint` |
| TypeScript | quality: `tsc` |
| CSS | quality: `stylelint` |
| Zig | tests: `zig` |
| Assembly | built in: names the dialect of every assembly file, no external tool needed |
| Swift | tests: `swift`, `xcodebuild` · quality: `swift-format`, `swiftlint` |
| SQL | quality: `sqlfluff` |
| C/C++ | detection: `cmake` · quality: `clang-tidy` · security: `cppcheck` |
| Java / Kotlin / Android | tests: `mvn`, `gradle` (uses `./gradlew` when present) · quality: checkstyle and spotbugs |
| Lua | tests: `busted` · quality: `luacheck` |
| Ruby | tests: `bundle` |
| PHP | security: `composer` |
| Dart / Flutter | tests: `dart` |
| Kotlin | quality: `ktlint`, `detekt` |
| C# | tests: `dotnet` |
| Shell | tests: `bats` · quality: `shellcheck`, `shfmt` |
| YAML | quality: `yamllint` |
| Markdown | quality: `markdownlint` |
| JSON | quality: `jsonlint` |
| TOML | quality: `taplo` |
| XML | quality: `xmllint` |
| R | tests: `Rscript` |
| Perl | tests: `prove` · quality: `perlcritic` |
| Julia | tests: `julia` |
| Objective-C | tests: `xcodebuild` |
| Groovy | quality: `codenarc` |
| PowerShell | tests: `pwsh` |
| Nix | tests: `nix` · quality: `nixpkgs-fmt` |
| Haskell | tests: `stack`, `cabal` · quality: `hlint` |
| Elixir | tests, quality, security: `mix` (Credo and MixAudit only when the project depends on them) |
| Erlang | tests, quality: `rebar3` (EUnit, xref) |
| Scala | tests: `sbt` · quality: scalafmt through `sbt`, when the project uses it |
| Dockerfile | quality: `hadolint` |
| Kubernetes | quality: `helm lint` per chart, `kustomize build` per overlay (never applies anything; remote bases and unbuilt dependencies are skipped) |
| GitHub Actions | quality: `actionlint` |
| Terraform | quality: `terraform fmt`, `tflint` (never init, plan or apply) |
| Protobuf | quality: `buf lint` |

**Assembly** needs no external tool. sarand recognises `.asm`, `.s`/`.S`, `.nasm`, `.yasm`, `.masm`, `.fasm`, `.a51`, `.a65`, `.a86` and `.z80` files in the project root and in the first-level `src/`, `asm/`, `boot/`, `kernel/` and `firmware/` folders, and names the *dialect* of each file in the "Detected project" section: x86 (NASM, GNU as with AT&T or Intel syntax, MASM/TASM, FASM; 16, 32 or 64-bit), ARM (A32/T32), AArch64, RISC-V, MIPS, PowerPC, 6502, Z80, AVR, Motorola 68000 and 8051. It is a transparent heuristic, not a parser: a file it cannot place is reported as `Unidentified` instead of a guess, and nothing is ever assembled or run.

Project-wide checks that run with `--security`: `gitleaks` (secrets, including git history) and `syft` (software bill of materials with a license summary). PDF output needs an HTML-to-PDF engine: `wkhtmltopdf` (upstream archived it in 2023, so some distributions no longer ship it) or WeasyPrint (`pip install weasyprint`, or `pipx inject sarand-cli weasyprint` for a pipx install; it also needs the Pango system library). If no engine works, sarand says why, writes the same report as Markdown next to the intended PDF path and exits non-zero. On Termux and Android neither engine has been verified; use `--format html` and print from a browser there.

</details>

## Install

### Requirements

| Needed | For |
|---|---|
| Python 3.10 or newer | Running sarand |
| A Rust toolchain ([rustup.rs](https://rustup.rs)) | Only to build from source; the PyPI wheels need none |
| [pipx](https://pipx.pypa.io) | Recommended installer |
| Per-language tools | Optional, see `sarand --doctor` |

### From PyPI (no Rust needed)

```bash
pipx install sarand-cli
sarand --version
```

The package is called `sarand-cli` on PyPI (the name `sarand` there belongs to an unrelated project); the command it installs is `sarand`. Prebuilt wheels cover Linux (glibc) on x86_64 and aarch64, macOS on Intel and Apple silicon, and Windows on x64, for every Python from 3.10 on. Other systems build from source, as below. To upgrade: `pipx upgrade sarand-cli`.

### From source with pipx

pipx builds sarand in its own isolated environment and puts the `sarand` command on your `PATH`.

```bash
pipx install ~/sarand
sarand --version
```

To upgrade after pulling new source, use the installer script instead of a plain `pipx install`, which does not refresh an existing copy. It builds the current source first and only then replaces the old installation; if the build fails (no network, no Rust toolchain) your previous installation is restored, and it retries slow network failures on its own:

```bash
./install.sh
```

It finishes by printing the version it installed and tells you if a different `sarand` earlier on your `PATH` would still run instead of it.

If pipx itself is missing, install it with your package manager (`sudo pacman -S python-pipx`, `brew install pipx`, `sudo apt install pipx`) or with pip, then reload your shell:

```bash
python3 -m pip install --user pipx
pipx ensurepath
```

> [!NOTE]
> On systems that protect the system Python (PEP 668) add `--break-system-packages` to the pip command.

### Arch Linux (AUR)

The AUR package is drafted but not published yet, so `yay -S sarand` does not work today. Use pipx.

### Development install

```bash
pip install maturin
cd sarand
maturin develop --release
```

Building the package needs a Rust toolchain: the build backend is maturin, and `pip install -e .` fails without one (it tries to download Rust and gives up when it cannot). If the extension will not build on your platform (possible on some Termux/aarch64 toolchains), run sarand straight from the source tree instead. With no compiled core importable it uses the pure-Python scanner, and the report says `Scan engine: pure-Python fallback`:

```bash
python3 -m venv .venv && . .venv/bin/activate
pip install rich PyYAML filelock   # plus tomli on Python 3.10
PYTHONPATH=python python -m sarand --help
```

Point it at a project with `-p`, for example `PYTHONPATH=/path/to/sarand/python python -m sarand -p .`.

<details>
<summary><b>Platform notes: Windows, macOS, Android/Termux</b></summary>

<br>

- **Windows.** `install.sh` is a Bash script. In PowerShell run `pipx install .` from the repository instead.
- **macOS.** Nothing special: install pipx with Homebrew and follow the steps above.
- **Android / Termux.** Everything works in the terminal. The paste helper (`sarand.rc`) copies to the clipboard through the OSC 52 terminal sequence, so it needs no clipboard tool and no graphical session.

</details>

## Usage

| I want to… | Command |
|---|---|
| Analyse the current directory | `sarand` |
| Analyse another project and lint it | `sarand --project ~/my-project --quality` |
| Get the most complete report possible | `sarand --full` |
| Run security checks | `sarand --security` |
| Skip the slow vulnerability lookups | `sarand --security --skip-audit` |
| Write JSON without running tests | `sarand --skip-tests --format json -o report.json` |
| Export a PDF | `sarand --format pdf` |
| Feed code-scanning tools | `sarand --security --format sarif` |
| Leave the source out of the report | `sarand --no-source` |
| Choose the output folder once | `sarand --set-output-dir ~/ai-reports` |
| Cap the size of each embedded file | `sarand --full --max-file-size 1M` |
| Speed up repeat runs | `sarand --cache` |
| Check the environment | `sarand --doctor` |

`--full` is shorthand for "give me everything": it turns on `--quality` and `--security` and removes the limits on file size, tree depth and tree entries. A `--max-depth`, `--max-entries` or `--max-file-size` you pass yourself still wins.

### Large projects and small devices

Before it renders anything, sarand tells you how much source it is about to embed (`Embedding about 12.4 MiB of source from 163 file(s)`) and warns when that looks too large for the memory this machine has free. A complete `--full` report of a big project can be slow, or run out of memory, on a phone or a 2 GB laptop; the warning never blocks the run. To get a lighter report, use `--no-source`, lower `--max-file-size` (the default is 2M; `--full` removes it), or leave `--full` out.

Running sarand again on the same project replaces its previous report at that path and says so, so reports never pile up under one filename.

<details>
<summary><b>All options</b></summary>

<br>

| Option | Meaning |
|---|---|
| `-p, --project PATH` | Project root (default: current directory) |
| `-d, --output-dir PATH` | Folder for the report |
| `-o, --output-name NAME` | Report file name (default: `sarand-<project>-report.<ext>`) |
| `--set-output-dir PATH` | Save PATH as the default output folder and exit |
| `-f, --format FORMAT` | `markdown` (default), `json`, `text`, `html`, `pdf` or `sarif` |
| `--skip-tests` | Do not run tests |
| `--quality` | Run lint, format and type checks for each detected language |
| `--security` | Run security and vulnerability checks for each detected language |
| `--skip-audit` | Skip `pip-audit` and `cargo-audit`, whose database lookups can take tens of seconds |
| `--full` | `--quality` + `--security` + no truncation limits |
| `--max-depth N` | Maximum project tree depth |
| `--max-entries N` | Maximum entries per tree level |
| `--max-file-size SIZE` | Largest source file to embed, for example `512K`, `2M` or `1G` (default `2M`; larger files are listed as skipped). Overrides the no-limit behaviour of `--full` |
| `--no-source` | Do not embed file contents |
| `--no-health` | Skip the health score |
| `--cache` | Skip re-scanning TODOs and secrets in files unchanged since the last `--cache` run |
| `--clear-cache` | Delete this project's scan cache and exit |
| `--doctor` | Diagnose the environment and exit |
| `-v, --verbose` / `--debug` | More logging |
| `--version` | Print the version and exit; warns when the running copy is a stale editable install |

</details>

## Security checks

`--security` adds the security tools of every detected language (for example `bandit` and `pip-audit` for Python, `cargo-audit` and `cargo-deny` for Rust, `govulncheck` for Go) and three project-wide checks:

| Check | What it does |
|---|---|
| Secret scan | `gitleaks` looks for credentials in the working tree and the whole git history. Findings are redacted. |
| SBOM and licenses | `syft` lists every dependency per ecosystem and summarises licenses. Copyleft is advice only, unless you add a [license policy](#license-policy). |
| Lockfile check | Confirms that the manifest has a lockfile and that the lockfile is not git-ignored. |

Independently of this flag, sarand never copies a file that contains a detected secret into the report, and reports how many files it left out.

### Check results and TODO markers

Each check ends as `PASS`, `FAIL`, `SKIP` (tool missing or not applicable) or `INCONCLUSIVE`. `INCONCLUSIVE` is for dependency-audit tools (`cargo audit`, `pip-audit`, `npm audit`, `govulncheck`, ...) that exited 0 but reported that they could not finish, usually because the network was unreachable. It lowers the report's confidence instead of earning a green `PASS`, and a failing exit is never downgraded. The errors listed in a report come only from checks that failed.

The TODO scan skips golden, fixture and snapshot directories and Markdown or reStructuredText prose by default, and the report states how many markers it suppressed. Add project-specific exclusions in `.sarand.toml`:

```toml
[todo]
exclude_globs = ["vendor/*"]
```

### Secret handling

Files whose *name* looks like a credential (`.env*`, `*.pem`, `secrets.yaml`, `kubeconfig`, `.docker/config.json`, `*.tfvars`, ...) are left out before their content is read, and so is any file in which the built-in scan finds a credential-shaped value. With `--security`, a file that `gitleaks` flags is left out too. If your project keeps deliberately fake credentials in its own tests, list those files so they stop lowering the health score:

```toml
[secrets]
fixture_paths = ["tests/test_secrets.py"]
```

Entries are `fnmatch` globs on the project-relative path (case-sensitive; `*` also matches `/`). The default is an empty list, so every finding counts. A listed file is still never copied into the report and its findings are still listed. A glob that would match every file is rejected, and so is any mistake in the table: sarand warns and counts every finding instead.

### License policy

By default sarand only *advises* about copyleft licenses, because whether one matters depends on your project. If you know your rules, write them in a `.sarand.toml` at the project root and `--security` enforces them against the SBOM:

```toml
[licenses]
allow   = ["MIT", "Apache-2.0", "BSD-*", "ISC", "PSF-2.0"]
deny    = ["AGPL-*", "GPL-*"]
warn    = ["MPL-2.0"]
unknown = "allow"

[[licenses.exceptions]]
package = "somelib"
reason  = "GPL-3.0, used only as a build tool and never shipped"
```

| Key | Meaning |
|---|---|
| `allow` | If set, every license must match one of these (or `warn`). Patterns are case-insensitive and support `*`. |
| `deny` | A match is a violation and fails the check. `deny` always wins. |
| `warn` | Acceptable, but reported for review. |
| `unknown` | What to do with a package that reports no license: `allow` (default), `warn` or `deny`. |
| `exceptions` | Per-package exceptions. A written `reason` is required, a `version` is optional. |

- `A OR B` lets you choose, so a package is judged by its best alternative; `A AND B` needs every part to pass.
- Common non-SPDX spellings such as `Apache 2.0` or `PSFL` are mapped to their SPDX ids. Any other unrecognised string must be listed in `allow` exactly as it is reported.
- A mistake in the file (a typo like `alow`, a wrong type, invalid TOML) is an error, never silently ignored.
- `syft` reads no license for Rust crates because `Cargo.lock` carries none, so keep `unknown = "allow"` there and let `cargo deny` cover Rust.

## Health score

The score is transparent and adds up to 100:

| Part | Points |
|---|---|
| Tests pass | 25 |
| No critical errors in quality or security | 20 |
| Test and quality tooling present | 15 |
| Reasonable TODO count and code hygiene | 15 |
| Security tooling run and clean | 15 |
| Clean git state | 10 |

Grades: **A** 90 and above, **B** 80, **C** 70, **D** 60, **F** below 60.

A score is only as trustworthy as the checks behind it, so the report also says how many checks actually ran. A check whose tool is not installed is skipped, and a skipped check proves nothing: when any were skipped, the Health section lists how many ran and how many did not, gives a **confidence** percentage, and names the tools to install. A security run in which every check was skipped no longer earns the full security points.

## Configuration

The report folder is chosen in this order:

1. `--output-dir` on the command line
2. The `SARAND_OUTPUT_DIR` environment variable
3. The folder saved with `--set-output-dir`
4. `~/Downloads`

The saved setting lives in a per-user config file:

| System | Location |
|---|---|
| Linux | `$XDG_CONFIG_HOME/sarand/config.json` or `~/.config/sarand/config.json` |
| macOS | `~/Library/Application Support/sarand/config.json` |
| Windows | `%APPDATA%\sarand\config.json` |

The `--cache` data is stored in the output folder under `.sarand-cache`.

## More tools

### Paste a large report into a chat

Some chats take no file upload. `python3 -m sarand.rc.command` splits any file, typically a `sarand --full` report, into paste-sized chunks. Every chunk sits inside an integrity-checked envelope (session id, per-chunk hash and a final report hash) that an AI receiver can verify. It walks you through the chunks one at a time and remembers where you stopped, and on terminals that support OSC 52 (Termux included) it copies each chunk straight to the clipboard.

```bash
sarand --full -d ~/reports
python3 -m sarand.rc.command --source ~/reports/sarand-my-project-report.md
```

Run the second command again with no options for the next chunk. State is kept in `.sarand-rc/`. See [docs/RC-AI-RECEIVER.md](https://github.com/msoleimani62/sarand/blob/main/docs/RC-AI-RECEIVER.md) for the protocol as the receiving AI sees it.

| Option | Effect |
|---|---|
| `--source FILE` | File to split (default: `README.md`, or the `SARAND_RC_SOURCE` variable) |
| *(none)* | Send the next unsent chunk |
| `-i, --info` | Show session and progress |
| `-b, --back` | Send the previous block again |
| `-br, --back-run` | Send the last history entry again |
| `-n N` | Jump to block N |
| `-c, --chunk N` | Send chunk N of the current block |
| `--verify` | Check that the saved chunks rebuild the source byte for byte; sends nothing |
| `--reset`, `--clean` | Delete the state and start a new session |

### Device storage and environment audit

`python3 -m sarand.device_report.command` is a separate, **read-only** tool. It scans a whole device, not one project, for space hogs, duplicate and stale files, build caches, package-manager footprints and Android/Termux environment details, and writes one Markdown report as evidence for a cleanup decision. It never deletes, moves, changes or installs anything.

```bash
python3 -m sarand.device_report.command --full -o ~/device-report.md
```

<details>
<summary><b>Device audit options</b></summary>

<br>

| Option | Effect |
|---|---|
| `-o, --output PATH` | Report path |
| `-r, --root DIR` | Extra scan root, repeatable (default: `$HOME`, plus `/sdcard` if present) |
| `-x, --exclude PATH` | Exclude a path from every scan, repeatable |
| `-q, --quick` | Skip the duplicate and stale-file scans, the two slowest |
| `--full` | Always run those scans and remove the `--top` row cap |
| `-n, --top N` | Rows per top-space table (default 30) |
| `-d, --old-days N` | Age in days for a stale file (default 180) |
| `-m, --min-file-size MB` | Minimum size for the large-files section (default 50) |
| `-u, --dup-min-size MB` | Minimum size considered for duplicate scanning (default 5) |
| `-D, --max-depth N` | Maximum scan depth, 0 for unlimited (default) |
| `--min-top-space MB` | Minimum size for a row in the summary's top-space table (default 1.0) |
| `--expand-aggregates` | List every cache directory instead of one line per pattern |
| `--summary-only` | Render only the executive summary; excludes `--full` |

</details>

### Built-in diagnostics

`sarand --doctor` checks the Rust core, your Python version, every per-language tool and the PDF engines. Each line says whether the tool is present and, if it is not, the exact command that installs it. A missing tool is informational; only an unsupported Python version fails the command. `sarand --doctor` also shows which copy of sarand is running (its version, where it lives, whether it is an editable development install) and warns when a second copy on your `PATH` shadows it or when an editable install lags behind its source tree. Every command above also answers to `--help`.

### Add a language with a plugin

Implement the `LanguageAnalyzer` protocol (`matches`, `entry_points`, `run_tests`, `run_quality`, and optionally `run_security`) in your own package and register it in your `pyproject.toml`:

```toml
[project.entry-points."sarand.analyzers"]
zig = "sarand_zig_plugin:ZigAnalyzer"
```

sarand finds it and runs it alongside the built-in analyzers. A plugin that raises, returns the wrong type or cannot be loaded is skipped with a reported reason; it never crashes a scan. The full contract, version compatibility rules and author workflow are in [docs/PLUGINS.md](https://github.com/msoleimani62/sarand/blob/main/docs/PLUGINS.md), with a working example in [`examples/sarand-plugin-justfile`](https://github.com/msoleimani62/sarand/tree/main/examples/sarand-plugin-justfile).

### Monorepos and workspaces

sarand detects Cargo workspaces and npm, Yarn and pnpm workspaces and lists their members. For Node workspaces it runs tests and lint inside each member (labelled `packages/api: npm test`) and skips whatever the root script already fans out, so nothing is reported twice. What is and is not supported, and how the health score treats members, is in [docs/WORKSPACES.md](https://github.com/msoleimani62/sarand/blob/main/docs/WORKSPACES.md).

## Troubleshooting

<details>
<summary><b><code>sarand --version</code> shows an old version right after installing</b></summary>

<br>

Another copy of sarand comes first on your `PATH`, typically a development virtualenv that is still active, and it shadows the one pipx just installed. `./install.sh` names both copies when this happens, and `sarand --doctor` lists them. Run `deactivate` (or remove the old copy) and then `hash -r`. If it is a development install whose recorded version lags the source, `maturin develop --release` refreshes it.

</details>

<details>
<summary><b><code>sarand: command not found</code></b></summary>

<br>

Run `pipx ensurepath`, then open a new terminal. On Windows, also check that the pipx bin folder is on `PATH`.

</details>

<details>
<summary><b>The build fails with a Rust error</b></summary>

<br>

Install a Rust toolchain from [rustup.rs](https://rustup.rs) and try again, or run sarand from the source tree on the pure-Python scanner, which needs no build (see the development install section).

</details>

<details>
<summary><b>A check shows as skipped</b></summary>

<br>

The tool behind it is not installed. `sarand --doctor` lists it with the install command.

</details>

<details>
<summary><b>The security checks are slow</b></summary>

<br>

Vulnerability databases are queried over the network. Add `--skip-audit` to skip `pip-audit` and `cargo-audit`; the static checks still run.

</details>

<details>
<summary><b>The report says files were excluded because of secrets</b></summary>

<br>

That is intended. Files that contain a detected secret are never written into the report. Remove or rotate the secret, then run again.

</details>

## Uninstall

Installed with pipx:

```bash
pipx uninstall sarand-cli
```

Installed as a development install:

```bash
pip uninstall sarand
```

sarand keeps a few things outside the package. Delete them if you want a clean removal:

| What | Where |
|---|---|
| Saved settings | The config file listed under [Configuration](#configuration) |
| Reports | Your output folder, `~/Downloads` by default |
| Scan cache | `.sarand-cache` inside the output folder (or run `sarand --clear-cache` first) |
| Paste-helper state | `.sarand-rc/` in the directory where you ran it |

## Contributing

[AGENTS.md](https://github.com/msoleimani62/sarand/blob/main/AGENTS.md) is the source of truth for architecture, conventions and the roadmap. Before opening a pull request, run:

```bash
ruff format .
ruff check .
mypy python
pytest -q
```

Continuous integration runs the same checks on Linux, macOS and Windows.

## License

Released under the [MIT License](https://github.com/msoleimani62/sarand/blob/main/LICENSE).

