CodeToTxt
CodeToTxt is a small Python tool that flattens a codebase into a single text file. It's built for feeding code into LLMs, but it works just as well for code review, documentation, or just having a searchable snapshot of a project.
Features
- Convert an entire directory of code into one text file
- Optional directory tree at the top of the output
- Respects
.gitignoreautomatically (including parent directories) - Filter files by extension or glob pattern
- Custom separators and output formatting
- Copy straight to the clipboard instead of (or in addition to) writing a file
- Dry-run and stats modes to see what you're about to process before you commit to it
- Config file support so you don't have to repeat the same flags every time
- Token estimate in the output, since that's usually what people actually care about
Installation
pip install code-to-txt
Or with Poetry:
poetry add code-to-txt
Quick start
# Show version
code-to-txt --version
# Convert everything in the current directory, with a timestamped filename
code-to-txt -t
# See what would be processed without writing anything
code-to-txt --dry-run
# Get a quick summary of the codebase
code-to-txt --stats
# Convert a specific directory
code-to-txt ./my-project -o project.txt
# Skip the file and just copy the result to the clipboard
code-to-txt --clipboard-only
Choosing file types
# Multiple extensions (space or comma separated, both work)
code-to-txt -e ".py .js .ts"
code-to-txt -e ".py,.js,.ts"
# Or use glob patterns instead
code-to-txt -g "*.py" -g "src/**/*.js"
More options
# Skip files above a certain size (handy for staying under token limits)
code-to-txt --max-file-size 500
# Exclude specific patterns
code-to-txt -x "tests/*" -x "*.test.js"
# Ignore .gitignore entirely
code-to-txt --no-gitignore
# Leave out the directory tree
code-to-txt --no-tree
# Use a different separator between files
code-to-txt --separator "---"
# Combine whatever you need
code-to-txt -t -c -e ".py .js" -x "tests/*"
Configuration file
Rather than typing the same flags every time, you can generate a config file:
code-to-txt --init-config
This creates .code-to-txt.yml:
# Output file name
output: code-to-txt.txt
# File extensions to include (null = use defaults)
extensions: null
# Patterns to exclude
exclude:
- "tests/*"
- "*.test.js"
- "*.test.ts"
- "*.spec.js"
- "*.spec.ts"
- "node_modules/*"
- "__pycache__/*"
- "*.pyc"
# Glob patterns (alternative to extensions)
glob: []
# Options
no_gitignore: false
no_tree: false
separator: "================"
clipboard: false
clipboard_only: false
timestamp: true
max_file_size: null
Then point the CLI at it:
code-to-txt --config .code-to-txt.yml
Any CLI flag you pass will override the matching setting in the config file.
A few example configs
Python project:
extensions: [ .py ]
exclude: [ "tests/*", "*.pyc", "__pycache__/*", "venv/*", ".venv/*" ]
timestamp: true
max_file_size: 500
JavaScript/TypeScript project:
extensions: [ .js, .ts, .jsx, .tsx ]
exclude: [ "node_modules/*", "dist/*", "build/*", "*.test.js", "*.spec.ts" ]
no_tree: false
max_file_size: 1000
Tuned for LLM input:
extensions: [ .py, .js, .md ]
exclude: [ "tests/*", "*.test.*", "node_modules/*", "dist/*", "build/*" ]
timestamp: true
clipboard: true
max_file_size: 200
no_tree: false
Command line options
Usage: code-to-txt [OPTIONS] [PATH]
Arguments:
PATH Directory to scan (default: current directory)
Options:
-o, --output PATH Output file path (default: codetotxt_YYYYMMDD_HHMMSS.txt)
-e, --extensions TEXT File extensions to include (space or comma separated)
-x, --exclude TEXT Patterns to exclude (can be used multiple times)
-g, --glob TEXT Glob patterns to include (can be used multiple times)
--no-gitignore Don't respect .gitignore files
--no-tree Don't include directory tree in output
--separator TEXT Separator between files
-c, --clipboard Copy output to clipboard in addition to file
--clipboard-only Copy to clipboard only (don't save file)
--config PATH Path to config file (.yml or .yaml)
--init-config Create default configuration file
-t, --timestamp Add timestamp to output filename
-v, --version Show version and exit
--dry-run Show which files would be processed
--stats Show detailed statistics
--max-file-size INT Skip files larger than N KB
--help Show this message and exit
Using it as a library
You don't need the CLI. Everything is available directly from the CodeToText class.
Basic conversion
from code_to_txt import CodeToText
code_to_txt = CodeToText(
root_path="./my-project",
output_file="output.txt",
include_extensions={".py", ".js"},
)
num_files = code_to_txt.convert(add_tree=True)
print(f"Processed {num_files} files")
Generating content without writing to disk
from code_to_txt import CodeToText
import pyperclip
code_to_txt = CodeToText(
root_path="./my-project",
output_file=None,
include_extensions={".py"},
)
content = code_to_txt.generate_content(add_tree=True)
pyperclip.copy(content)
Getting statistics
from code_to_txt import CodeToText
code_to_txt = CodeToText(
root_path="./my-project",
output_file=None,
max_file_size_kb=500,
)
stats = code_to_txt.calculate_statistics()
print(f"Total files: {stats['total_files']}")
print(f"Total size: {stats['total_size_bytes'] / 1024 / 1024:.2f} MB")
print(f"Total lines: {stats['total_lines']:,}")
Using glob patterns
from code_to_txt import CodeToText
code_to_txt = CodeToText(
root_path="./my-project",
output_file="output.txt",
glob_patterns=["*.py", "src/**/*.js", "**/*.md"],
)
num_files = code_to_txt.convert()
Default file extensions
If you don't specify extensions or glob patterns, CodeToTxt includes these by default:
- Python:
.py - JavaScript/TypeScript:
.js,.ts,.jsx,.tsx - Systems languages:
.c,.cpp,.h,.hpp,.java,.cs,.go,.rs - Web:
.html,.css,.scss - Config:
.yaml,.yml,.json,.toml,.xml - Docs:
.md,.txt,.rst - Scripts:
.sh,.bash,.zsh - Other:
.rb,.php,.swift,.kt,.scala,.r,.sql
Default ignore patterns
These are excluded automatically, on top of whatever's in your .gitignore (parent directories included, up to five
levels up):
__pycache__,*.pyc,*.pyo,*.pyd.git,.svn,.hgnode_modules.venv,venv,.env*.egg-info,dist,build.pytest_cache,.mypy_cache,.ruff_cache*.so,*.dylib,*.dll
Output format
The generated file has three parts:
- A header with the source directory and total file count
- An optional directory tree
- Each file's contents, labeled with its relative path
For example:
Code Export from: /path/to/project
Total files: 4
================================================================================
DIRECTORY TREE:
================================================================================
my-project/
├── src/
│ ├── main.py
│ └── utils.py
├── tests/
│ └── test_main.py
└── README.md
================================================================================
FILE 1/4: src/main.py
================================================================================
def main():
print("Hello, World!")
if __name__ == "__main__":
main()
================================================================================
...
Where this is useful
- Sharing a whole codebase with someone in one file, for review
- Feeding a project into ChatGPT, Claude, or another AI assistant
- Generating a quick reference document for a project
- Doing plain-text search across an entire codebase at once
- Producing input for other code analysis tools
- Keeping a simple, flat backup of a project's source
Tips
Preparing input for an LLM
# See what you're dealing with first
code-to-txt --stats
# Preview with a size cap
code-to-txt --dry-run --max-file-size 200
# Then copy it straight to the clipboard
code-to-txt --clipboard-only --max-file-size 200 -e ".py .md"
Working with large projects
# Narrow it down to the extensions you actually care about
code-to-txt -e ".py" -t --max-file-size 500
# Cut out the usual heavy directories
code-to-txt -x "node_modules/*" -x "venv/*" -x "dist/*"
# Check the size before generating anything
code-to-txt --stats --max-file-size 300
Debugging what's being skipped
# See exactly which files are excluded and why
code-to-txt --dry-run
# Compare with .gitignore turned off
code-to-txt --dry-run --no-gitignore
Requirements
- Python 3.10+
- Dependencies:
click,gitpython,pathspec,pyperclip,pyyaml
Development
# Clone the repository
git clone https://github.com/AndriiSonsiadlo/code-to-txt.git
cd code-to-txt
# Install with Poetry
poetry install
# Run tests
poetry run pytest
# Run linting
poetry run ruff check .
poetry run mypy src/
Contributing
Contributions are welcome. Feel free to open a pull request.
License
MIT License. See the LICENSE file for details.
Changelog
See CHANGELOG.md for the full history of changes.
Author
Created by Andrii Sonsiadlo.
Metadata
Release files for code-to-txt 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| code_to_txt-0.3.1.tar.gz | 14.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| code_to_txt-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.1 kB
Release files / code_to_txt-0.3.1.tar.gz
| Download URL | code_to_txt-0.3.1.tar.gz |
|---|---|
| Size | 14.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dcd561cd919fc8413204aadb4d2acf56226faa0f3aeca18b8c24c38a82c199bc
|
|
BLAKE2b-256 checksum How to use checksums |
2702e10c7889916a10fdb49186fd57d3f82535209d73d81b336755d56f96dd9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.10.20 Linux/6.17.0-1020-azure
|
Release files / code_to_txt-0.3.1-py3-none-any.whl
| Download URL | code_to_txt-0.3.1-py3-none-any.whl |
|---|---|
| Size | 14.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
50ff008d37ec69bb3b81e08d2bbdde3c4cdc6f60484608c4436c25ff8d79f61e
|
|
BLAKE2b-256 checksum How to use checksums |
4440eeefe8847459e2a458f38b02d58804bc83cc677e5ff42dc813d987c60480
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.10.20 Linux/6.17.0-1020-azure
|