Remove comments and docstrings from Python source files
Project description
Pystrip
Python tool to safely remove comments, docstrings, and type annotations from source files using libcst.
Features
- Removes comments (inline and standalone)
- Removes docstrings (module, class, function)
- Removes type annotations (parameter hints, return types, variable annotations)
- Keeps regular string literals untouched
- Supports output formats:
text,json,sarif,gitlab,github - Works in CI with
--check - Supports config discovery and parallel processing
What pystrip will not remove
- String literals that are not docstrings. A string only counts as a docstring when it is the first statement in a module, class, or function body.
- String literals that merely look like comments, such as
"value # not a comment". - Arbitrary strings later in a body, even if they are standalone expression statements.
- Shebang lines like
#!/usr/bin/env python3unless--remove-shebangis set. - Files that fail to parse as Python. By default the run stops on the first such error; with
--continue-on-error, pystrip reports the failure and keeps processing other files.
Docstring detection is syntax-based, not text-based. That means pystrip does not try to guess intent from quote style or wording; it only removes a literal string expression in the docstring position.
Installation
pip install pystrip
Usage
# Check mode (CI)
pystrip . --check
# Apply changes in place
pystrip ./src/ --in-place
# Read from stdin and write stripped code to stdout
pystrip - < input.py > output.py
usage: pystrip [-h] [--exclude PATH] [--exclude-glob PATTERN] [--keep-docstrings] [--keep-comments] [--keep-type-annotations] [--keep-blank] [--remove-shebang] [--use-pass] [--check]
[--diff] [--in-place] [--output-dir DIR] [--no-recursive] [--jobs N] [--config PATH] [--format {text,json,sarif,gitlab,github}] [--quiet] [--verbose]
[--continue-on-error]
[paths ...]
Remove comments and docstrings from Python source files.
positional arguments:
paths Files or directories to process (default: ['.'])
options:
-h, --help show this help message and exit
--exclude PATH Exclude a file or directory path (repeatable) (default: None)
--exclude-glob PATTERN
Exclude paths by glob pattern (repeatable) (default: None)
--keep-docstrings Keep docstrings and only strip comments (default: None)
--keep-comments Keep comments and only strip docstrings (default: None)
--keep-type-annotations
Keep type annotations and only strip comments/docstrings (default: None)
--keep-blank Keep blank lines introduced by comment removal (default: None)
--remove-shebang Remove shebang lines (#!/...) from files (kept by default) (default: None)
--use-pass Use 'pass' instead of '...' for empty body placeholders (default: None)
--check Do not write files; exit with code 1 if any file would change (default: False)
--diff Print unified diffs for changed files (default: False)
--in-place Write stripped output back to each input file (default: False)
--output-dir DIR Write changed files into DIR instead of modifying inputs (default: None)
--no-recursive Process only direct child files of each directory path (default: True)
--jobs N Number of worker processes to use (default: None)
--config PATH Load configuration from a specific TOML file (default: None)
--format {text,json,sarif,gitlab,github}
Output format for violations (default: None)
--quiet Suppress progress and summary output (default: False)
--verbose Print detailed removal diagnostics (default: False)
--continue-on-error Continue processing remaining files when a file fails to parse/process (default: False)
Output example:
⠇ Processing 10 file(s)...
src/pystrip/__init__.py:1:0: DOCSTRING_REMOVED Module docstring removed
src/pystrip/__main__.py:1:0: DOCSTRING_REMOVED Module docstring removed
...
src/pystrip/visitor.py:1:0: DOCSTRING_REMOVED Module docstring removed
Changed 10 file(s), 63 violation(s), 26 docstring(s), 37 comment(s), 0 annotation(s).
When using - as the sole input path, pystrip reads source from stdin. In normal mode it writes stripped code to stdout; in --check mode it emits violations instead. --in-place, --output-dir, and --diff are not available with stdin input.
Configuration
Use either pyproject.toml ([tool.pystrip]) or .pystrip.toml ([pystrip]).
pyproject.toml is recommended when pystrip is part of a project; .pystrip.toml is useful for standalone usage.
Invalid config values (for example jobs = "4") fail fast with exit code 2 and a clear error message.
[tool.pystrip]
remove_comments = true
remove_docstrings = true
remove_blank_lines = true
remove_type_annotations = true
exclude = ["tests/"]
exclude_glob = ["*.generated.py"]
jobs = 4
Output and CI
# GitHub annotations
pystrip . --check --format github
# GitLab code-quality report
pystrip . --check --format gitlab > gl-code-quality-report.json
Development
Developer setup, quality checks, and contribution workflow are documented in docs/development.md.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Clean (no changes needed) |
| 1 | Changes would be made in --check mode |
| 2 | Runtime or CLI error |
Project details
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 pystrip-1.2.0.tar.gz.
File metadata
- Download URL: pystrip-1.2.0.tar.gz
- Upload date:
- Size: 609.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee9ee37b7e8db00a993ef682e71a16e1cfe09ddc7f6389be1a7fe7d913c7cbf8
|
|
| MD5 |
ffe407caffe1d3a0c74bc4f64473baa1
|
|
| BLAKE2b-256 |
3b699a0222b616ceccb411e82e7f5829767b55d5993a3b0585fb6e9bdfad668a
|
Provenance
The following attestation bundles were made for pystrip-1.2.0.tar.gz:
Publisher:
publish.yml on pystrip/pystrip
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pystrip-1.2.0.tar.gz -
Subject digest:
ee9ee37b7e8db00a993ef682e71a16e1cfe09ddc7f6389be1a7fe7d913c7cbf8 - Sigstore transparency entry: 1102083814
- Sigstore integration time:
-
Permalink:
pystrip/pystrip@24e79841f175dda12ef4177c17d8de6f9d1c1bc9 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/pystrip
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@24e79841f175dda12ef4177c17d8de6f9d1c1bc9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pystrip-1.2.0-py3-none-any.whl.
File metadata
- Download URL: pystrip-1.2.0-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ad948751ad586f9bf07392673c26c61fcb1371acb2746cda71ec3723da2ca42
|
|
| MD5 |
4c06cc0a3ede59ea5e35ea528780ee1b
|
|
| BLAKE2b-256 |
784a1e4611b9448462040040903d979c2e66b84d2dfd1dc7ebaab51e9e8ac41a
|
Provenance
The following attestation bundles were made for pystrip-1.2.0-py3-none-any.whl:
Publisher:
publish.yml on pystrip/pystrip
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pystrip-1.2.0-py3-none-any.whl -
Subject digest:
8ad948751ad586f9bf07392673c26c61fcb1371acb2746cda71ec3723da2ca42 - Sigstore transparency entry: 1102083918
- Sigstore integration time:
-
Permalink:
pystrip/pystrip@24e79841f175dda12ef4177c17d8de6f9d1c1bc9 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/pystrip
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@24e79841f175dda12ef4177c17d8de6f9d1c1bc9 -
Trigger Event:
release
-
Statement type: