Uncomment: Tree-sitter Based Comment Removal Tool
A fast, accurate, and extensible comment removal tool that uses tree-sitter for parsing, ensuring 100% accuracy in comment identification. Originally created to clean up AI-generated code with excessive comments, it now supports any language with a tree-sitter grammar through its flexible configuration system.
Support This Project
If you find uncomment helpful, please consider sponsoring the development:
Your support helps maintain and improve this tool for the community! 🚀
Features
- 100% Accurate: Uses tree-sitter AST parsing to correctly identify comments
- No False Positives: Never removes comment-like content from strings
- Smart Preservation: Keeps important metadata, TODOs, FIXMEs, and language-specific patterns
- Parallel Processing: Multi-threaded processing for improved performance
- 306 Languages: Powered by tree-sitter-language-pack with automatic grammar downloading
- Configuration System: TOML-based configuration for project-specific settings
- Smart Init Command: Automatically generate configuration based on your project
- Fast: Leverages tree-sitter's optimized parsing
- Safe: Dry-run mode to preview changes
- Built-in Benchmarking: Performance analysis and profiling tools
Supported Languages
Built-in Languages
- Python (.py, .pyw, .pyi, .pyx, .pxd)
- JavaScript (.js, .jsx, .mjs, .cjs)
- TypeScript (.ts, .tsx, .mts, .cts, .d.ts, .d.mts, .d.cts)
- Rust (.rs)
- Go (.go)
- Java (.java)
- C (.c, .h)
- C++ (.cpp, .cc, .cxx, .hpp, .hxx)
- C# (.cs)
- Ruby (.rb, .rake, .gemspec)
- PHP (.php, .phtml)
- Elixir (.ex, .exs)
- TOML (.toml)
- JSON (.json)
- JSON with Comments (.jsonc)
- YAML (.yml, .yaml)
- HCL/Terraform (.hcl, .tf, .tfvars)
- Makefile (Makefile, .mk)
- Shell/Bash (.sh, .bash, .zsh, .bashrc, .zshrc)
- Haskell (.hs, .lhs)
- HTML (.html, .htm, .xhtml)
- CSS (.css)
- XML (.xml, .xsd, .xsl, .xslt, .svg)
- SQL (.sql)
- Kotlin (.kt, .kts)
- Swift (.swift)
- Lua (.lua)
- Nix (.nix)
- PowerShell (.ps1, .psm1, .psd1)
- Protobuf (.proto)
- INI-like configs (.ini, .cfg, .conf)
- Dockerfile (Dockerfile, Dockerfile.*)
- Scala (.scala, .sc)
- Dart (.dart)
- R (.r, .R)
- Julia (.jl)
- Zig (.zig)
- Clojure (.clj, .cljs, .cljc, .edn)
- Elm (.elm)
- Erlang (.erl, .hrl)
- Vue (.vue)
- Svelte (.svelte)
- SCSS (.scss)
- LaTeX (.tex, .sty, .cls)
- Fish (.fish)
- Perl (.pl, .pm)
- Groovy (.groovy, .gradle)
- OCaml (.ml, .mli)
- Fortran (.f90, .f95, .f03, .f08)
306 Languages Available
Powered by tree-sitter-language-pack, uncomment can process any of 306 supported languages. Languages not listed above can be added via configuration — grammars are downloaded automatically on first use.
Installation
Via Package Managers
Homebrew (macOS/Linux)
Cargo (Rust)
npm (Node.js)
pip (Python)
From source
Requirements
- For building from source: Rust 1.70+
- For npm/pip packages: Pre-built binaries are downloaded automatically
Quick Start
Run Without Installing
Add --dry-run to either command to preview changes before writing.
Install Locally
# Generate a configuration file for your project
# Remove comments from files
# Preview changes without modifying files
Usage
Configuration
# Generate a smart configuration based on your project
# Generate a comprehensive configuration with all supported languages
# Interactive configuration setup
# Use a custom configuration file
Init Command Examples
The init command intelligently detects languages in your project:
# Smart detection - analyzes your project and includes only detected languages
# Comprehensive mode - includes configurations for 49 built-in languages
# Specify output location
# Force overwrite existing configuration
Basic Usage
# Remove comments from a single file
# Preview changes without modifying files
# Process multiple files
# Remove documentation comments/docstrings
# Remove TODO and FIXME comments
# Add custom patterns to preserve
# Process entire directory recursively
# Use parallel processing with 8 threads
Optional Benchmarking Tools
The crate ships development binaries for benchmarking and profiling, but they are gated behind the bench-tools feature so they are not installed for regular users.
-
Install from crates.io with the extras:
-
Run locally without installing:
Contributing
See CONTRIBUTING.md for local development, automation hooks, and release procedures.
Default Preservation Rules
Always Preserved
- Comments containing
~keep - TODO comments (unless
--remove-todo) - FIXME comments (unless
--remove-fixme) - Documentation comments (unless
--remove-doc)
Linting Tool Directives (Always Preserved)
The tool preserves all linting and formatting directives to ensure your CI/CD pipelines and development workflows remain intact:
Go:
//nolint,//nolint:gosec,//golangci-lint,//staticcheck,//go:generate
Python:
# noqa,# type: ignore,# mypy:,# pyright:,# ruff:,# pylint:,# flake8:# fmt: off/on,# black:,# isort:,# bandit:,# pyre-ignore
JavaScript/TypeScript:
- ESLint:
eslint-disable,eslint-enable,eslint-disable-next-line - TypeScript:
@ts-ignore,@ts-expect-error,@ts-nocheck,@ts-check - Triple-slash:
/// <reference,/// <amd-module,/// <amd-dependency - Formatters:
prettier-ignore,biome-ignore,deno-lint-ignore - Coverage:
v8 ignore,c8 ignore,istanbul ignore
Rust:
- Attributes:
#[allow],#[deny],#[warn],#[forbid],#[cfg] - Clippy:
clippy::,#[rustfmt::skip]
Java:
@SuppressWarnings,@SuppressFBWarnings,//noinspection,// checkstyle:
C/C++:
// NOLINT,// NOLINTNEXTLINE,#pragma,// clang-format off/on
Shell/Bash:
# shellcheck disable,# hadolint ignore
YAML:
# yamllint disable/enable
HCL/Terraform:
# tfsec:ignore,# checkov:skip,# trivy:ignore,# tflint-ignore
Ruby:
# rubocop:disable/enable,# reek:,# standard:disable/enable
Configuration
Uncomment uses a flexible TOML-based configuration system that allows you to customize behavior for your project.
Configuration File Discovery
Uncomment searches for configuration files in the following order:
- Command-line specified config:
--config path/to/config.toml .uncommentrc.tomlin the current directory.uncommentrc.tomlin parent directories (up to git root or filesystem root)~/.config/uncomment/config.toml(global configuration)- Built-in defaults
Basic Configuration Example
[]
= false
= false
= false
= ["IMPORTANT", "NOTE", "WARNING"]
= true
= true
[]
= ["py", "pyw", "pyi"]
= ["noqa", "type:", "pragma:", "pylint:"]
[]
# Keep all comments in test files
= false
= false
= false
Adding Languages via Configuration
Uncomment supports 306 languages through tree-sitter-language-pack. To add a language not in the built-in list, define it in your .uncommentrc.toml:
[]
= "Hare"
= ["ha"]
= ["comment"]
= ["TODO", "FIXME"]
The grammar is downloaded automatically on first use. No manual grammar configuration needed.
Configuration Merging
When multiple configuration files are found, they are merged with the following precedence (highest to lowest):
- Command-line flags
- Local
.uncommentrc.tomlfiles (closer to the file being processed wins) - Global configuration (
~/.config/uncomment/config.toml) - Built-in defaults
Pattern-specific configurations override language configurations for matching files.
How It Works
Unlike regex-based tools, uncomment uses tree-sitter to build a proper Abstract Syntax Tree (AST) of your code. This means it understands the difference between:
- Real comments vs comment-like content in strings
- Documentation comments vs regular comments
- Inline comments vs standalone comments
- Language-specific metadata that should be preserved
Architecture
The tool is built with a modular, extensible architecture:
- Language Registry: Manages 49 built-in languages with extensible configuration
- tree-sitter-language-pack: Provides 306 language grammars with automatic downloading
- Configuration System: TOML-based hierarchical configuration with merging
- AST Visitor: Traverses the tree-sitter AST to find comments
- Preservation Engine: Applies rules to determine what to keep
- Output Generator: Produces clean code with comments removed
Adding New Languages
Add to your .uncommentrc.toml:
[]
= "My Language"
= ["ml", "mli"]
= ["comment"]
= ["TODO", "FIXME"]
Any of the 306 languages supported by tree-sitter-language-pack will work — grammars are downloaded automatically on first use.
Git Hooks
Pre-commit
Add to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/Goldziher/uncomment
rev: v2.9.0
hooks:
- id: uncomment
Lefthook
Add to your lefthook.yml:
pre-commit:
commands:
uncomment:
run: uncomment {staged_files}
stage_fixed: true
For both hooks, install uncomment via pip:
Performance
While slightly slower than regex-based approaches due to parsing overhead, the tool is very fast and scales well with parallel processing:
Single-threaded Performance
- Small files (<1000 lines): ~20-30ms
- Large files (>10000 lines): ~100-200ms
Parallel Processing Benchmarks
Performance scales excellently with multiple threads:
| Thread Count | Files/Second | Speedup |
|---|---|---|
| 1 thread | 1,500 | 1.0x |
| 4 threads | 3,900 | 2.6x |
| 8 threads | 5,100 | 3.4x |
Benchmarks run on a large enterprise codebase with 5,000 mixed language files
Built-in Benchmarking
Use the built-in tools to measure performance on your specific codebase:
# Basic benchmark
# Detailed benchmark with multiple iterations
# Memory and performance profiling
The accuracy gained through AST parsing is worth the small performance cost, and parallel processing makes it suitable for even the largest codebases.
Development
Project Structure
uncomment/
├── src/ # Source code
├── tests/ # Integration tests
├── fixtures/ # Test fixtures
│ ├── languages/ # Language-specific test files
│ └── repos/ # Repository test configurations
├── test-repos/ # Manual testing scripts
└── scripts/ # Build and release scripts
Benchmarking
The project includes optional benchmarking and profiling binaries (gated behind the bench-tools feature):
- Run
benchmark(real-world throughput on a codebase) - Run
profile(repeatable timing runs + basic analysis)
Testing
# Run all tests
# Run tests with output
# Run integration tests (including network-dependent)
License
MIT