{"id":51438291,"url":"https://github.com/Goldziher/uncomment","last_synced_at":"2026-07-15T16:01:33.559Z","repository":{"id":281308398,"uuid":"943078746","full_name":"Goldziher/uncomment","owner":"Goldziher","description":"Blazingly fast CLI to remove comments from code using tree-sitter grammers","archived":false,"fork":false,"pushed_at":"2026-07-09T07:13:28.000Z","size":3245,"stargazers_count":50,"open_issues_count":0,"forks_count":10,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-09T08:17:20.222Z","etag":null,"topics":["ai","cli","comments","python","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Goldziher.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-05T06:11:12.000Z","updated_at":"2026-07-09T07:13:32.000Z","dependencies_parsed_at":"2025-03-08T08:15:21.737Z","dependency_job_id":"85ac3d79-5b15-4a3f-9ee3-e330b25b6dbf","html_url":"https://github.com/Goldziher/uncomment","commit_stats":null,"previous_names":["goldziher/uncomment"],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/Goldziher/uncomment","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goldziher%2Funcomment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goldziher%2Funcomment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goldziher%2Funcomment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goldziher%2Funcomment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Goldziher","download_url":"https://codeload.github.com/Goldziher/uncomment/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Goldziher%2Funcomment/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35511400,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-15T02:00:06.706Z","response_time":131,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","cli","comments","python","rust"],"created_at":"2026-07-05T09:00:30.716Z","updated_at":"2026-07-15T16:01:33.552Z","avatar_url":"https://github.com/Goldziher.png","language":"Rust","funding_links":["https://github.com/sponsors/Goldziher"],"categories":["Applications"],"sub_categories":["Text processing"],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"assets/banner.svg\" alt=\"uncomment — strip the noise, keep the code\" width=\"820\"\u003e\n\n**Strip the noise. Keep the code.**\n\nuncomment removes comments from source code using tree-sitter's AST — so it is 100% accurate and\n**never** touches comment-like text inside strings. It keeps what matters by default (TODO/FIXME,\ndocs, and linting directives) across **300+ languages**, with parallel processing and a safe dry-run\nmode.\n\nAST-accurate\u0026nbsp;·\u0026nbsp;306 languages\u0026nbsp;·\u0026nbsp;zero false positives\u0026nbsp;·\u0026nbsp;smart preservation\u0026nbsp;·\u0026nbsp;parallel\u0026nbsp;·\u0026nbsp;dry-run\n\n[![crates.io](https://img.shields.io/crates/v/uncomment?style=flat-square\u0026color=2dd4bf)](https://crates.io/crates/uncomment)\n[![npm](https://img.shields.io/npm/v/uncomment-cli?style=flat-square\u0026color=2dd4bf\u0026label=npm)](https://www.npmjs.com/package/uncomment-cli)\n[![PyPI](https://img.shields.io/pypi/v/uncomment?style=flat-square\u0026color=2dd4bf)](https://pypi.org/project/uncomment/)\n[![CI](https://img.shields.io/github/actions/workflow/status/Goldziher/uncomment/ci.yml?style=flat-square\u0026label=CI)](https://github.com/Goldziher/uncomment/actions)\n[![License: MIT](https://img.shields.io/badge/License-MIT-2dd4bf?style=flat-square)](./LICENSE)\n[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-2dd4bf?style=flat-square\u0026logo=github-sponsors)](https://github.com/sponsors/Goldziher)\n\n[Install](#installation)\u0026nbsp;·\u0026nbsp;[Features](#features)\u0026nbsp;·\u0026nbsp;[Usage](#usage)\u0026nbsp;·\u0026nbsp;[Configuration](#configuration)\u0026nbsp;·\u0026nbsp;[How it works](#how-it-works)\u0026nbsp;·\u0026nbsp;[Contributing](#contributing)\n\n\u003c/div\u003e\n\n---\n\n## Why uncomment\n\nRegex-based comment strippers guess. They delete a `//` inside a string literal, mangle a URL in a\ndocstring, or leave a linting directive your CI depends on. uncomment doesn't guess: it parses your\ncode into a real syntax tree and removes only the nodes that are genuinely comments.\n\nOriginally built to clean up AI-generated code drowning in explanatory comments, it now works on\nanything with a tree-sitter grammar.\n\n## Features\n\n- **100% accurate** — tree-sitter AST parsing identifies comments structurally, not by pattern matching\n- **No false positives** — never removes comment-like content from strings\n- **Smart preservation** — keeps TODO/FIXME, docs, and language-specific linting directives by default\n- **306 languages** — powered by [tree-sitter-language-pack](https://github.com/kreuzberg-dev/tree-sitter-language-pack), grammars downloaded on demand\n- **Parallel** — multi-threaded processing that scales across cores\n- **Safe** — dry-run mode with line-by-line diffs previews every change before you write\n- **Configurable** — hierarchical TOML config with a smart `init` command\n- **Built-in benchmarking** — optional performance analysis and profiling tools\n\n## Installation\n\n| Channel | Command |\n| ------- | ------- |\n| Homebrew (macOS/Linux) | `brew tap goldziher/tap \u0026\u0026 brew install uncomment` |\n| Cargo (Rust) | `cargo install uncomment` |\n| npm (Node.js) | `npm install -g uncomment-cli` |\n| pip (Python) | `pip install uncomment` |\n\nRun without installing:\n\n```bash\nnpx -y uncomment-cli@latest .\nuvx uncomment .\n```\n\nAdd `--dry-run` to preview changes before writing.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eBuild from source\u003c/b\u003e\u003c/summary\u003e\n\n```bash\ngit clone https://github.com/Goldziher/uncomment.git\ncd uncomment\ncargo install --path .\n```\n\nRequires Rust 1.70+. npm and pip packages download pre-built binaries automatically.\n\n\u003c/details\u003e\n\n## Quick Start\n\n```bash\n# Generate a configuration file tuned to your project\nuncomment init\n\n# Remove comments from a directory\nuncomment src/\n\n# Preview changes as a diff, write nothing\nuncomment src/ --dry-run --diff\n```\n\n## Usage\n\n```bash\n# Single file\nuncomment file.py\n\n# Multiple files / globs\nuncomment src/*.py\n\n# Also strip doc comments and docstrings\nuncomment --remove-doc file.py\n\n# Also remove TODO and FIXME comments (preserved by default)\nuncomment --remove-todo --remove-fixme file.py\n\n# Add custom patterns to preserve\nuncomment --ignore \"HACK\" --ignore \"WARNING\" file.py\n\n# Process an entire tree with all CPU cores\nuncomment . -j 0\n```\n\nRun `uncomment --help` for the full, grouped list of options.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eConfiguring with \u003ccode\u003einit\u003c/code\u003e\u003c/b\u003e\u003c/summary\u003e\n\nThe `init` command detects the languages in your project and writes a matching `.uncommentrc.toml`:\n\n```bash\n# Smart detection — includes only the languages it finds\nuncomment init\n\n# All 49 built-in languages\nuncomment init --comprehensive\n\n# Interactive selection\nuncomment init --interactive\n\n# Custom output location / overwrite\nuncomment init --output config/uncomment.toml --force\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eOptional benchmarking tools\u003c/b\u003e\u003c/summary\u003e\n\nDevelopment binaries for benchmarking and profiling are gated behind the `bench-tools` feature so\nthey are not installed for regular users:\n\n```bash\n# Install with extras\ncargo install uncomment --features bench-tools\n\n# Or run locally\ncargo run --release --features bench-tools --bin benchmark -- --target /path/to/repo --iterations 3\ncargo run --release --features bench-tools --bin profile -- /path/to/repo\n```\n\n\u003c/details\u003e\n\n## Supported Languages\n\nuncomment ships with 49 built-in language configurations and can process any of the **306 languages**\nin [tree-sitter-language-pack](https://github.com/kreuzberg-dev/tree-sitter-language-pack) — grammars\nare downloaded automatically on first use, and any language can be added via configuration.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e49 built-in languages\u003c/b\u003e\u003c/summary\u003e\n\nPython (`.py`, `.pyw`, `.pyi`, `.pyx`, `.pxd`) · JavaScript (`.js`, `.jsx`, `.mjs`, `.cjs`) ·\nTypeScript (`.ts`, `.tsx`, `.mts`, `.cts`, `.d.ts`) · Rust (`.rs`) · Go (`.go`) · Java (`.java`) ·\nC (`.c`, `.h`) · C++ (`.cpp`, `.cc`, `.cxx`, `.hpp`, `.hxx`) · C# (`.cs`) ·\nRuby (`.rb`, `.rake`, `.gemspec`) · PHP (`.php`, `.phtml`) · Elixir (`.ex`, `.exs`) · TOML (`.toml`) ·\nJSON (`.json`) · JSON with Comments (`.jsonc`) · YAML (`.yml`, `.yaml`) ·\nHCL/Terraform (`.hcl`, `.tf`, `.tfvars`) · Makefile (`Makefile`, `.mk`) ·\nShell/Bash (`.sh`, `.bash`, `.zsh`) · Haskell (`.hs`, `.lhs`) · HTML (`.html`, `.htm`, `.xhtml`) ·\nCSS (`.css`) · XML (`.xml`, `.xsd`, `.xsl`, `.xslt`, `.svg`) · SQL (`.sql`) · Kotlin (`.kt`, `.kts`) ·\nSwift (`.swift`) · Lua (`.lua`) · Nix (`.nix`) · PowerShell (`.ps1`, `.psm1`, `.psd1`) ·\nProtobuf (`.proto`) · INI-like configs (`.ini`, `.cfg`, `.conf`) · Dockerfile (`Dockerfile`) ·\nScala (`.scala`, `.sc`) · Dart (`.dart`) · R (`.r`, `.R`) · Julia (`.jl`) · Zig (`.zig`) ·\nClojure (`.clj`, `.cljs`, `.cljc`, `.edn`) · Elm (`.elm`) · Erlang (`.erl`, `.hrl`) · Vue (`.vue`) ·\nSvelte (`.svelte`) · SCSS (`.scss`) · LaTeX (`.tex`, `.sty`, `.cls`) · Fish (`.fish`) ·\nPerl (`.pl`, `.pm`) · Groovy (`.groovy`, `.gradle`) · OCaml (`.ml`, `.mli`) ·\nFortran (`.f90`, `.f95`, `.f03`, `.f08`)\n\n\u003c/details\u003e\n\n## Preservation Rules\n\nCertain comments are **never removed by default** — uncomment protects the ones your tooling and\nteammates rely on.\n\n**Always preserved:**\n\n- Comments containing `~keep`\n- `TODO` (unless `--remove-todo`), `FIXME` (unless `--remove-fixme`)\n- Documentation comments (unless `--remove-doc`)\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eLinting \u0026amp; formatter directives (always preserved)\u003c/b\u003e\u003c/summary\u003e\n\n| Language | Directives |\n| -------- | ---------- |\n| Go | `//nolint`, `//golangci-lint`, `//staticcheck`, `//go:generate` |\n| Python | `# noqa`, `# type: ignore`, `# mypy:`, `# pyright:`, `# ruff:`, `# pylint:`, `# flake8:`, `# fmt: off/on`, `# black:`, `# isort:`, `# bandit:`, `# pyre-ignore` |\n| JS/TS | `eslint-disable*`, `@ts-ignore`, `@ts-expect-error`, `@ts-nocheck`, `/// \u003creference`, `prettier-ignore`, `biome-ignore`, `deno-lint-ignore`, `v8/c8/istanbul ignore` |\n| Rust | `#[allow]`, `#[deny]`, `#[warn]`, `#[forbid]`, `#[cfg]`, `clippy::`, `#[rustfmt::skip]` |\n| Java | `@SuppressWarnings`, `@SuppressFBWarnings`, `//noinspection`, `// checkstyle:` |\n| C/C++ | `// NOLINT`, `// NOLINTNEXTLINE`, `#pragma`, `// clang-format off/on` |\n| Shell | `# shellcheck disable`, `# hadolint ignore` |\n| YAML | `# yamllint disable/enable` |\n| HCL/Terraform | `# tfsec:ignore`, `# checkov:skip`, `# trivy:ignore`, `# tflint-ignore` |\n| Ruby | `# rubocop:disable/enable`, `# reek:`, `# standard:disable/enable` |\n\n\u003c/details\u003e\n\n## Configuration\n\nuncomment reads a hierarchical TOML configuration, merged highest-to-lowest precedence:\n\n1. Command-line flags\n2. Local `.uncommentrc.toml` (closest to the file being processed wins)\n3. Global `~/.config/uncomment/config.toml`\n4. Built-in defaults\n\n```toml\n[global]\nremove_todos = false\nremove_fixme = false\nremove_docs = false\npreserve_patterns = [\"IMPORTANT\", \"NOTE\", \"WARNING\"]\nuse_default_ignores = true\nrespect_gitignore = true\n\n[languages.python]\nextensions = [\"py\", \"pyw\", \"pyi\"]\npreserve_patterns = [\"noqa\", \"type:\", \"pragma:\", \"pylint:\"]\n\n[patterns.\"tests/**/*.py\"]\n# Keep all comments in test files\nremove_todos = false\nremove_fixme = false\nremove_docs = false\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAdding a language via configuration\u003c/b\u003e\u003c/summary\u003e\n\nAny of the 306 tree-sitter-language-pack languages works — grammars download automatically on first\nuse, no manual grammar setup:\n\n```toml\n[languages.hare]\nname = \"Hare\"\nextensions = [\"ha\"]\ncomment_nodes = [\"comment\"]\npreserve_patterns = [\"TODO\", \"FIXME\"]\n```\n\n\u003c/details\u003e\n\n## How It Works\n\nUnlike regex-based tools, uncomment builds a proper Abstract Syntax Tree of your code with\ntree-sitter, so it distinguishes:\n\n- Real comments vs comment-like content in strings\n- Documentation comments vs regular comments\n- Inline comments vs standalone comments\n- Language-specific metadata that must be preserved\n\nThe pipeline is modular: a **language registry** (49 built-ins + on-demand grammars) feeds an\n**AST visitor** that finds comment nodes, a **preservation engine** decides what to keep, and an\n**output generator** emits clean code.\n\n## Git Hooks\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003epre-commit\u003c/b\u003e\u003c/summary\u003e\n\n```yaml\nrepos:\n  - repo: https://github.com/Goldziher/uncomment\n    rev: v3.4.0\n    hooks:\n      - id: uncomment\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eLefthook\u003c/b\u003e\u003c/summary\u003e\n\n```yaml\npre-commit:\n  commands:\n    uncomment:\n      run: uncomment {staged_files}\n      stage_fixed: true\n```\n\n\u003c/details\u003e\n\n## Performance\n\nAST parsing costs a little more than regex, but the tool is fast and scales well with threads.\n\n- Small files (\u003c1000 lines): ~20-30ms\n- Large files (\u003e10000 lines): ~100-200ms\n\n| Threads | Files/second | Speedup |\n| ------- | ------------ | ------- |\n| 1 | 1,500 | 1.0× |\n| 4 | 3,900 | 2.6× |\n| 8 | 5,100 | 3.4× |\n\n_Benchmarked on a large enterprise codebase of ~5,000 mixed-language files._ Measure your own with\nthe built-in `benchmark` and `profile` tools (see [optional benchmarking tools](#usage)).\n\n## Development\n\n```bash\ncargo build              # Debug build\ncargo test               # Run the test suite\ncargo test -- --ignored  # Include network-dependent tests\ncargo clippy             # Lint\ncargo fmt --all          # Format\n```\n\nSee [`CONTRIBUTING.md`](./CONTRIBUTING.md) for local development, automation hooks, and release\nprocedures.\n\n## Contributing\n\nIssues and pull requests are welcome. If uncomment is useful to you, consider\n[sponsoring development](https://github.com/sponsors/Goldziher) — it helps keep the project\nmaintained for the community.\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGoldziher%2Funcomment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGoldziher%2Funcomment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGoldziher%2Funcomment/lists"}