LLMScribe
LLMScribe is an open-source Python tool that exports an entire software project into a single readable text file. It generates a directory tree followed by the full contents of every supported source file, making it ideal for AI coding assistants, code reviews, documentation, debugging, and sharing codebases.
It ships with three interfaces so you can use whichever fits your workflow: a graphical desktop app, an interactive terminal menu, and a scriptable CLI.
Table of Contents
- Features
- Project Structure
- Requirements
- Installation
- Usage
- Output Format
- What Gets Included
- What Gets Ignored
- Core API Reference
- License
Features
- Directory tree — generates a visual
├──tree of your project structure. - Tree-only mode — export only the project directory tree without reading or including file contents, via the
--tree-onlyCLI flag or the "Tree only" checkbox in the GUI. - Full file content extraction — reads every supported text file and appends its complete, untruncated contents below the tree.
- Smart filtering — skips build outputs, dependency folders, IDE files, and OS noise out of the box.
.gitignoreaware — loads and respects the project's own.gitignoreautomatically.- Three interfaces — GUI desktop app, interactive terminal menu, and a fully scriptable CLI.
- Embeddable core — the
llmscribe.corepackage can be imported directly into other Python projects. - Cross-platform — runs on Windows, macOS, and Linux anywhere Python 3.10+ is available.
- Installable like any real CLI —
pip install llmscribegives you thellmscribe,llmscribe-gui, andllmscribe-cuicommands, usable from any terminal.
Project Structure
LLMScribe/
├── src/
│ └── llmscribe/ # Installable package (import as `llmscribe.*`)
│ ├── __init__.py # Package version
│ ├── core/ # All scanning and writing logic
│ │ ├── __init__.py # Public API surface
│ │ ├── file_reader.py # Extension allowlist + full file reading
│ │ ├── tree_builder.py # Directory tree + ignore rule engine
│ │ └── writer.py # Orchestrates tree + contents into output
│ ├── cli/ # Scriptable command-line interface
│ │ ├── __init__.py
│ │ └── main.py
│ ├── cui/ # Interactive terminal menu
│ │ ├── __init__.py
│ │ └── main.py
│ └── gui/ # Tkinter desktop application
│ ├── __init__.py
│ ├── __main__.py # `python -m llmscribe.gui` entrypoint
│ └── app.py
├── pyproject.toml
├── LICENSE
├── README.md
└── CONTRIBUTING.md
Requirements
-
Python 3.10 or higher
-
Tkinter (GUI only) — required only for
llmscribe-gui,llmscribe --gui, and the GUI picker in the CUI. The core library and non-GUI CLI work without Tkinter. It ships with most Python installers; on Linux it may need to be installed separately:# Debian / Ubuntu sudo apt install python3-tk # Fedora sudo dnf install python3-tkinter # Arch sudo pacman -S tk
No third-party Python packages are required — the standard library is sufficient.
Headless Linux servers can use the CLI and library integration without Tkinter. If GUI mode is requested without it, LLMScribe prints an installation hint.
Installation
From PyPI (once published):
pip install llmscribe
This installs three console commands anywhere on your system: llmscribe, llmscribe-gui, and llmscribe-cui.
From source (development):
git clone https://github.com/AMRITO-KUNDU/LLMScribe.git
cd LLMScribe
pip install -e .
pip install -e . (editable install) picks up local code changes immediately without reinstalling — use this while developing.
Publishing to PyPI yourself:
pip install build twine
python -m build
twine upload dist/*
For automated releases, configure PyPI Trusted Publishing for the GitHub
repository and create a tag such as v1.0.0. The workflow in
.github/workflows/publish.yml then builds and publishes the wheel and source
distribution without storing a PyPI token in GitHub secrets.
Usage
CLI
The CLI is designed for scripting, automation, and CI pipelines. All options are passed as flags.
Basic usage:
# Scan a project and write to the default output file
llmscribe --path /path/to/project
# Specify a custom output file
llmscribe --path /path/to/project --output ~/exports/my_project.txt
# Export only the directory tree
llmscribe --path /path/to/project --tree-only
# Open a GUI folder picker instead of typing a path
llmscribe --gui
# Run interactively (prompts for a path, then falls back to the GUI picker)
llmscribe
# Check the installed version
llmscribe --version
llmscribe-cui --version
All flags:
| Flag | Default | Description |
|---|---|---|
--path PATH |
(none) | Path to the project folder to scan. |
--output FILE |
project_overview.txt |
Where to write the output. Parent directories are created automatically. |
--tree-only |
false |
Export only the directory tree and skip file contents. |
--gui |
false |
Open a GUI folder picker dialog instead of reading --path. |
--version |
— | Print the installed LLMScribe version and exit. |
Getting help:
llmscribe --help
GUI App
The desktop app is the easiest way to use LLMScribe. It provides a two-panel layout: controls on the left, a live preview of the generated output on the right.
Launch:
llmscribe-gui
# or
llmscribe --gui
# or, without installing console scripts
python -m llmscribe.gui
Workflow:
- Click the folder icon next to Project Folder and select your project root, or type the path directly.
- The Output File field auto-populates to
<project>/project_overview.txt. Change it if needed. - Tick Tree only (skip file contents) if you just want the directory structure without reading any file contents.
- Click Generate. The preview pane fills with the output and the line count appears in the header.
- Use Copy output to copy the full text to the clipboard, or Open file to open the saved file in your system's default text editor.
The GUI runs the scan in a background thread so the window stays responsive on large projects.
Terminal Menu (CUI)
The CUI is an interactive numbered menu intended for terminal users and for embedding LLMScribe into other projects or scripts that call it as a subprocess.
Launch:
llmscribe-cui
Menu:
LLMScribe CUI
1) Enter project folder path
2) Open GUI folder picker
3) Quit
Choose an option [1-3]:
You can also pass flags to skip the menu entirely:
llmscribe-cui --path /path/to/project --output summary.txt
llmscribe-cui --gui --output summary.txt --tree-only
Python API
Import LLMScribe's core directly into your own Python scripts or tools.
Generate a summary string:
from pathlib import Path
from llmscribe.core.writer import build_project_summary
summary = build_project_summary(
Path("/path/to/project"),
tree_only=True,
)
Generate and save to a file:
from pathlib import Path
from llmscribe.core.writer import run
run(
project_path=Path("/path/to/project"),
output_file=Path("summary.txt"),
tree_only=True,
)
Use individual components:
from pathlib import Path
from llmscribe.core.tree_builder import DEFAULT_IGNORE, generate_tree, load_gitignore
from llmscribe.core.file_reader import extract_contents
from llmscribe import __version__
project = Path("/path/to/project")
ignore = [*DEFAULT_IGNORE, *load_gitignore(project)]
tree = generate_tree(project, ignore)
contents = extract_contents(project, ignore)
print(tree)
print(contents)
print(f"Using LLMScribe {__version__}")
Tree-only Output
When tree-only mode is used (--tree-only on the CLI/CUI, or the checkbox in the GUI), only the project directory structure is exported — no files are opened or read.
my-project/
├── src/
│ ├── main.py
│ └── utils.py
├── tests/
└── README.md
Output Format
The output is a plain UTF-8 text file with two sections:
Selected Files Directory Structure:
my-project/
├── src/
│ ├── main.py
│ └── utils.py
├── tests/
│ └── test_main.py
├── pyproject.toml
└── README.md
File Contents:
--- src/main.py ---
<full contents of main.py>
--- src/utils.py ---
<full contents of utils.py>
... (and so on for every included file)
Files are listed in sorted order, and each file's contents are included in full — nothing is cut off or truncated.
What Gets Included
LLMScribe reads files with the following extensions:
| Category | Extensions |
|---|---|
| Python | .py |
| JavaScript / TypeScript | .js .ts .jsx .tsx |
| Systems languages | .c .cpp .cc .cxx .h .hpp .rs .go .zig |
| JVM languages | .java .scala .kt .clj .cljs |
| Other languages | .rb .php .swift .dart .lua .pl .r .hs .ml .fs .vb .cs .ex .exs .nim .cr .d .elm .v |
| Web | .html .htm .css .scss .sass .less .vue .svelte .pug .ejs .hbs .mustache .twig .jsp .asp .aspx .erb .haml |
| Config & manifests | .json .xml .yaml .yml .toml .ini .cfg .conf .properties .env .dotenv .lock .sum .mod .gradle .pom .gitignore .gitattributes .editorconfig .prettierrc .eslintrc .babelrc |
| Shell & scripts | .sh .bash .zsh .fish .ps1 .bat .cmd .awk .sed |
| Documentation | .md .rst .adoc .tex .bib .txt |
| Data (text-based) | .csv .tsv .sql |
| Logs | .log |
Binary formats (.pdf, .docx, .epub, .db, .sqlite, .parquet, images, etc.) are intentionally excluded — they cannot be read as text.
What Gets Ignored
The following are skipped automatically regardless of the project being scanned:
Directories:
| Category | Names |
|---|---|
| Version control | .git .svn .hg |
| Dependencies | node_modules vendor packages |
| Python envs | venv __pycache__ .eggs *.egg-info |
| Build outputs | dist build target out bin obj |
| IDEs | .idea .vscode .vs |
| OS artifacts | .DS_Store Thumbs.db desktop.ini |
| Logs & temp | logs tmp temp .tmp .cache |
| Test coverage | .coverage coverage .nyc_output |
| Secrets | .env .env.* secrets |
Additionally: any pattern present in the project's .gitignore file is loaded and applied on top of the defaults above.
Core API Reference
llmscribe.core.writer
build_project_summary(project_path, tree_only=False) → str
Builds and returns the complete summary string for a project.
| Parameter | Type | Description |
|---|---|---|
project_path |
Path |
Resolved path to the project root. |
tree_only |
bool |
Export only the directory tree, skipping file contents. |
run(project_path, output_file, tree_only=False) → None
Generates the summary and writes it to output_file. Prints progress and the final line count to stdout. Creates parent directories of output_file if they do not exist.
llmscribe.core.file_reader
extract_contents(root, ignore_patterns) → str
Walks root recursively, reads every file whose extension is in TEXT_FILE_EXTENSIONS and which does not match ignore_patterns, and returns all contents concatenated with --- relative/path --- headers. Files are read in full.
is_text_file(path) → bool
Returns True if path.suffix.lower() is in TEXT_FILE_EXTENSIONS.
llmscribe.core.tree_builder
generate_tree(root, ignore_patterns) → str
Returns a multi-line string representing the directory tree rooted at root, skipping anything that matches ignore_patterns.
load_gitignore(root) → list[str]
Parses root/.gitignore and returns ordered non-comment, non-empty pattern strings. Common Git-style globs, anchored rules, and negation rules are supported. Returns an empty list if no .gitignore exists.
should_ignore(path, ignore_patterns) → bool
Returns True if path matches the supplied ignore rules.
License
LLMScribe is licensed under the Apache License 2.0.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llmscribe-1.0.0.tar.gz.
File metadata
- Download URL: llmscribe-1.0.0.tar.gz
- Upload date:
- Size: 25.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71650cae3abdb65a4931fb5e869ca6c690d66763fa7baaee35e1edf47740d20d
|
|
| MD5 |
0c1f6fabc63775e01255969b7fef96ca
|
|
| BLAKE2b-256 |
ee69e658b30924ffb7d80434f174cda835ce35f2b468b2c7abdfbabfd3866250
|
Provenance
The following attestation bundles were made for llmscribe-1.0.0.tar.gz:
Publisher:
publish.yml on AMRITO-KUNDU/llmscribe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llmscribe-1.0.0.tar.gz -
Subject digest:
71650cae3abdb65a4931fb5e869ca6c690d66763fa7baaee35e1edf47740d20d - Sigstore transparency entry: 2580165486
- Sigstore integration time:
-
Permalink:
AMRITO-KUNDU/llmscribe@f267a17cc733a106ba42f9700274b49e48630ac1 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/AMRITO-KUNDU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f267a17cc733a106ba42f9700274b49e48630ac1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file llmscribe-1.0.0-py3-none-any.whl.
File metadata
- Download URL: llmscribe-1.0.0-py3-none-any.whl
- Upload date:
- Size: 23.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e2f9f0ea2b8f840bf9aa43a4c683a6b5d32d4701aa70a34106c3578bb763c7a
|
|
| MD5 |
9e09b5d92fc3f637a7385f6c354abf05
|
|
| BLAKE2b-256 |
5267f703c75368c76082ff2739a736a1b15eab872b404178c77e2eb5f957cb51
|
Provenance
The following attestation bundles were made for llmscribe-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on AMRITO-KUNDU/llmscribe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llmscribe-1.0.0-py3-none-any.whl -
Subject digest:
7e2f9f0ea2b8f840bf9aa43a4c683a6b5d32d4701aa70a34106c3578bb763c7a - Sigstore transparency entry: 2580165501
- Sigstore integration time:
-
Permalink:
AMRITO-KUNDU/llmscribe@f267a17cc733a106ba42f9700274b49e48630ac1 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/AMRITO-KUNDU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f267a17cc733a106ba42f9700274b49e48630ac1 -
Trigger Event:
push
-
Statement type: