Metadata-Version: 2.4
Name: pylistall
Version: 2.1.0
Summary: Display directory context with a tree and Git history, or copy and export Markdown.
Author: urntt
License-Expression: MIT
Project-URL: Homepage, https://github.com/urntt/pylistall
Project-URL: Repository, https://github.com/urntt/pylistall
Project-URL: Issues, https://github.com/urntt/pylistall/issues
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyperclip>=1.8
Requires-Dist: rich>=15.0.0
Dynamic: license-file

# pylistall

[![PyPI version](https://img.shields.io/pypi/v/pylistall.svg)](https://pypi.org/project/pylistall/)
[![Python versions](https://img.shields.io/pypi/pyversions/pylistall.svg)](https://pypi.org/project/pylistall/)
[![License](https://img.shields.io/github/license/urntt/pylistall.svg)](https://github.com/urntt/pylistall)

[中文说明](README.zh-CN.md)

`pylistall` is a cross-platform command-line tool that collects file contents under
a directory and displays them in a structured format. It can also copy Markdown
to the system clipboard or export it to a single file.

It includes the absolute path and a tree-style directory structure. If the
directory contains a `.git` repository, it can optionally include the Git commit log.

This tool is designed for efficiently sharing project context with AI tools,
debugging, documentation, or code review.

---

## Features

* Display collected context in the terminal by default
* Copy Markdown to the clipboard or save it to a single file (optional)
* Tree-style directory structure and absolute root path
* Recursive traversal of subdirectories (optional, disabled by default)
* Include or omit files using glob patterns (optional, filters both the tree and Files)
* Expand binaries as Base64 and include Git logs (optional, disabled by default)
* Choose output parts, preview collection, and limit total output size
* Terminal headings, colors, code highlighting, and interactive paging
* Collection progress and current operations on interactive stderr
* Cross-platform support: macOS, Windows, and Linux

---

## Installation

Using PyPI:

```bash
python -m pip install pylistall
```

Or, from the project root (where `pyproject.toml` is located):

```bash
python -m pip install .
```

Verify installation:

```bash
pylistall --help
```

Uninstall:

```bash
python -m pip uninstall pylistall
```

---

## Usage

```bash
pylistall [path] [options]
```

If `[path]` is not provided, the current directory (`.`) is used.

By default, the result is displayed without changing the clipboard. Interactive
terminals use centered divider headings for the project name, Git log and Files,
plus colors and syntax highlighting. They omit Markdown fences and line numbers.
Pipes and redirection receive UTF-8/LF Markdown without added ANSI,
regardless of Python's locale encoding. A shell may decode or re-encode redirected
output; use `-f` for a file with guaranteed UTF-8/no BOM/LF, including in Windows
PowerShell 5.1.
Status messages and warnings go to stderr.

---

## Output Format

Example input for a directory containing `README.txt` and `src/main.py`:

```bash
cd /Users/example/project
pylistall . -r -o -c
```

Example clipboard text (file export and redirection use the same Markdown):

````markdown
# `project`

```bash
/Users/example/project
├── src/
│   └── main.py
└── README.txt
```

## Files

### `README.txt`

```text
Example project.
```

### `src/main.py`

```python
print("Hello World!")
```
````

Notes:

* The project title is always first; path and tree share one `bash` block,
  followed by optional Git groups and Files.
* `-i` filters file names in the tree and Files, keeping connecting directories.
  `-o` removes matching names and prunes completely omitted directories.
* `-r` controls directory expansion and `-l` controls link following.
* Directories end with `/`; links are marked `@` and skipped by default.
* Headings use inline code with dynamic backticks; control characters are shown
  as visible escapes. Known file types have language tags;
  unknown types use `text`. Fences grow to avoid backtick collisions.
* Content ordering and `[...TRUNCATED...]` markers remain visible.

---

## Options

### Recursive traversal

**Optional, disabled by default.**

```text
-r, --recursive
```

Recursively include subdirectories. When enabled:

* The tree includes nested files and directories.
* Content collection includes matching files in nested directories.
* Git discovery checks nested repositories when `-g` is also enabled.

---

### Copy output to clipboard

**Optional, disabled by default.**

```text
-c, --copy
```

Additionally copy the complete Markdown to the clipboard. The terminal still
displays the result unless `-f` is supplied. Only this option needs a working
clipboard backend.

---

### Save output to a file

**Optional, disabled by default.**

```text
-f, --file [DEST]
```

Save all enabled output parts to one file and suppress the terminal body.
Combine with `-c` to save and copy the same Markdown.

Destination rules:

* Bare `-f` saves in the **command's current directory** using local time:
  `pylistall-output-%Y-%m-%d-%H-%M-%S.md`.
* Relative paths use that same current directory, independently of the collection
  root. Absolute paths and `~` are supported.
* An existing directory or trailing platform separator selects a directory with
  the default filename. Otherwise `DEST` is the complete filename.
* Custom filenames do not receive an automatic extension.
* Missing parents are created after collection and budget validation succeed.
* Existing names and same-second collisions fail unless `-w` is provided.
* Files use UTF-8 without BOM and LF. Failed overwrites preserve the original.
* The active destination and its aliases are excluded from contents even without
  `-o`; existing names may still appear in the tree.

Failures return nonzero, and stderr reports each completed destination.

Examples:

```bash
pylistall -r -o -f
pylistall -r -o -f context.md
pylistall -r -o -f ../exports/context -c
```

---

### Overwrite an output file

**Optional, disabled by default; requires `-f`.**

```text
-w, --overwrite
```

Allow replacing an existing output file. A directory cannot be overwritten as a
file. Replacement occurs after a same-directory temporary file is fully written;
failure cleans the incomplete file and preserves the original.

```bash
pylistall -r -o -f context.md -w
```

---

### Disable output parts

**Optional, repeatable, disabled by default.**

```text
-d, --disable PARTS
```

Omit `path`, `tree`, `git`, or `files` from every destination. Repeat the option or
use comma-separated values. The project title cannot be disabled; all four parts
may be disabled to output only that title. `root` is no longer accepted.

Disabling `files` avoids sampling and reading file contents; disabling `git`
avoids Git queries. Copying, saving and display use the same enabled parts.

```bash
pylistall -r -g 3 -d files
pylistall -d path,tree -d git -c
```

---

### Include only specific files

**Optional, repeatable, disabled by default.**

```text
-i, --include PATTERN
```

Include only files matching glob patterns. Repeat the option or use comma-separated
patterns; surrounding whitespace, empty entries and duplicates are removed. Matching uses
`fnmatch` against the filename and logical relative path.

When `-i` is used:

* Only matching file names remain in the tree and Files, along with their ancestors.
* Parent directories need not match; `-i` does not prune the scan.
* Matching binary names remain visible but require `-b` to expand their contents.
* Matching omit rules still take precedence.

---

### Omit specific files

**Optional, repeatable, disabled by default.**

```text
-o, --omit [PATTERN]
```

Exclude matching names from the tree and Files. Entire omitted directories are
not scanned. Repeated and comma-separated values are trimmed and deduplicated. Omissions take precedence over `-i` and `-b`,
checking both logical and resolved paths when links are followed.

Bare `-o` enables the default set at the root and nested levels:

* Git metadata, Python environments/caches (including `.venv`), `build`, `dist`, `*.egg-info`,
  `node_modules`, `.idea`, `.vscode`, `.gitignore`, `.DS_Store`, `Thumbs.db`.
* Python/testing: `.nox`, `.hypothesis`, `.ipynb_checkpoints`, `__pypackages__`,
  `.eggs`, `htmlcov`, `.coverage`, `.coverage.*`.
* Frontend: `.next`, `.nuxt`, `.output`, `.svelte-kit`, `.turbo`, `.parcel-cache`,
  `.vite`, `coverage`, `.nyc_output`, `*.tsbuildinfo`, `.eslintcache`, `.stylelintcache`.
* Other generated files: `.cache`, `target`, `.gradle`, `.vs`, `*.swp`, `*.swo`,
  `*~`, `desktop.ini`, `pylistall-output-*.md`.
* Sensitive names: `.env`, `.env.*`, `.envrc`, `.pypirc`, `.netrc`, `id_rsa`,
  `id_dsa`, `id_ecdsa`, `id_ed25519`, `*.key`, `*.pem`, `*.p12`, `*.pfx`,
  `.aws/credentials`, `.streamlit/secrets.toml`.

The list also excludes some examples and public certificates. It cannot detect
arbitrary secrets and does not load `.gitignore`. Business logs and dependency
locks are retained. The explicitly selected root itself is exempt from filtering.
Directory rules match their name, relative path, or relative path ending in `/`:
`src`, `src/` and `src/**` prune `src`; `src/*.py` removes matching files without
pruning `src`. Include cannot restore an omitted subtree.

Default patterns beginning with `**/` also apply at the root. Custom patterns keep
ordinary `fnmatch` behavior and do not automatically enable defaults. `*.py` matches file names at every level;
`src/*.py` can also match deeper paths because `fnmatch` treats `/` as an ordinary
character. Custom `**/.venv/**` does not match root `.venv` automatically.
Platform case handling is preserved. To combine:

```bash
pylistall -o -o "README.md,test_cases/*"
```

---

### Include binary files

**Optional, disabled by default.**

```text
-b, --binary [PATTERN]
```

Controls expansion of already selected binary candidates, without adding file
names or changing the tree. `-o` removes names first, then `-i` selects names, and
`-b` grants binary content permission. Text files do not need `-b`.

* Not provided → retain a path heading and a binary placeholder, without a body.
* Bare `-b` → expand all candidate binaries.
* `-b PATTERN` → expand only binary candidates matching filename or logical path.

Authorized bytes use padded Base64 without inserted line breaks, labelled
`Encoding: Base64` in a `text` block. Base64 is neither compression nor file
interpretation. With `-m`, encode the raw prefix; its encoding remains decodable.
Binary `[...TRUNCATED...]` appears outside the code block, and only the prefix
can be restored. Read failures remain visible errors, never encoded error text.

```bash
pylistall -b
pylistall -i "*.png" -b
pylistall -i "*.py" -b "*.png"  # does not add PNG candidates
```

---

### Git log

**Optional, disabled by default.**

```text
-g, --git-log [N]
```

Include Git history. Bare `-g` includes all entries; `-g N` includes the last N
entries, where N must be positive.

Rules:

* Without `-r`, check only the root `.git` directory or worktree pointer file.
* With `-r`, discover nested repositories in unpruned directories.
* Discovery is independent of `-i`; explicitly requested logs remain available
  when `.git` metadata is omitted. Entire omitted parent directories are skipped.
* Without omissions, `.git` may also appear in the tree and Files as ordinary data.
* Groups are sorted by absolute `.git` path, case-insensitively.
* Logs use oneline and decorate; Markdown groups have path subheadings.
* Missing repositories, empty logs and Git failures have explicit markers.
* Git must be available on PATH. `-d git` suppresses Git queries and output.

---

### Limit file read size

**Optional, unlimited by default.**

```text
-m, --max-bytes N
```

Limit source bytes read per file. N must be nonnegative. Contents exceeding the
limit receive `[...TRUNCATED...]`. This does not limit the tree or Git logs.

---

### Follow links

**Optional, disabled by default.**

```text
-l, --follow-links
```

Follow file and directory links, including targets outside the root. Directory
expansion still requires `-r`. Contents use logical relative paths; omit rules
also check resolved targets and their omitted directory ancestors. Ancestor cycles and broken followed targets are
skipped with warnings, while repeated non-cyclic aliases remain separate.
An explicitly supplied root link is resolved even without this option.

---

### Preview collection

**Optional, disabled by default.**

```text
-D, --dry-run
```

Collect accurately and report Markdown UTF-8 bytes, Files entry count, successfully
collected bodies, discovered entries, skips and destinations on stderr. No body is displayed, nothing is copied, and
no directories or files are created. Combine with `-c` or `-f` to preview them.

```bash
pylistall -r -o -D -c -f context.md
```

---

### Limit total output size

**Optional, unlimited by default.**

```text
-M, --max-output-bytes N
```

Set a positive UTF-8 byte budget for the complete enabled Markdown, including
headings, encoding labels, fences and newlines. Colors, progress, summaries and
status messages do not count. This budget is not a total memory limit.
Exceeding the budget returns 1 and delivers no partial terminal body, clipboard
content or file. Dry-run reports the same size as actual Markdown.

---

### Disable terminal paging

**Optional; paging is automatic in interactive terminals.**

```text
-n, --no-pager
```

Paging requires both stdin and stdout to be terminals. `PAGER` takes priority;
otherwise pylistall looks for `less`, including Git for Windows' bundled executable,
then system `more`. Less defaults to `-FRX`: short output exits automatically,
Space advances, `/` searches and `q` quits. An empty `PAGER` also disables paging.
Configured commands use executable/arguments without shell expansion.

Missing or failed pagers display directly. More receives plain platform-encoded
text; characters unavailable in the current Windows codepage may be replaced.
Rich import failures silently fall back to Markdown. Clipboard and file outputs
always remain Markdown. See [Git's pager defaults](https://git-scm.com/docs/git-config#Documentation/git-config.txt-corepager).

---

### Disable progress feedback

**Optional; enabled on interactive stderr unless `TERM=dumb`.**

```text
-P, --no-progress
```

Shows scan, tree and Git operations with a spinner, then checked/candidate and
successfully collected file counts. Terminal formatting has a separate `render`
stage with the current path and rendered block count, before displaying or paging.
No percentage is claimed for unknown totals.
Paths are literal and clipped to terminal width; refresh is at most 10 times per
second. Output redirection, `-f`, `-c` and `-D` still allow progress when stderr is
interactive. Redirect stderr or use `-P` to suppress it. This is independent of
`-n`, which controls paging. Feedback is cleared before results or the pager.
Missing or failing progress components quietly disable feedback; Ctrl+C cleans
resources and returns 130.

---

### Version

```text
-v, --version
```

Print the installed version (for example, `pylistall 2.1.0`) and exit without
collecting context, copying or writing a file.

---

### Help

```text
-h, --help
```

Display the command's usage and available options.

---

## Examples

Basic usage:

```bash
pylistall
```

Recursively collect with default omissions and three recent Git commits:

```bash
pylistall -r -o -g 3
```

Copy context or save it to a file:

```bash
pylistall -r -o -c
pylistall -r -o -f context.md
```

Include only Python files, or omit test files:

```bash
pylistall -i "*.py"
pylistall -o "test/test_*"
```

Preview destinations with a total budget:

```bash
pylistall -r -o -D -M 100000 -c -f context.md
```

---

## Clipboard Support

Platform-specific clipboard backends:

| Platform | Backend |
| --- | --- |
| macOS | `pbcopy` |
| Windows | `clip` |
| Linux | `xclip` / `pyperclip` |

Only `-c` needs a working desktop clipboard. Display and file export work without
one. Review selected content before sharing; current boundaries are documented in
[architecture](docs/architecture.md#safety-boundaries-and-current-limitations).

---

## Requirements

Python 3.9 or higher. Git is required only when collecting Git history.

---

## Contributing

See the [development guide](docs/development.md) for setup, checks, builds, and
contribution steps. Product direction is in the [vision](VISION.md); module
responsibilities and data flow are in [architecture](docs/architecture.md).

## Releases

See the [changelog](CHANGELOG.md) for version changes and migration notes, and
[GitHub Releases](https://github.com/urntt/pylistall/releases) for published versions.
Maintainers use the [release guide](docs/releasing.md).

## License

MIT License
