linthis
A fast, cross-platform multi-language linter and formatter written in Rust.
Features
- 🚀 Single Command: Run both linting and formatting simultaneously
- 🌍 Multi-Language Support: Rust, Python, TypeScript, JavaScript, Go, Java, C++, Swift, Kotlin, Lua, and more
- 🎯 Auto-Detection: Automatically detect programming languages used in your project
- ⚙️ Flexible Configuration: Support for project config, global config, and CLI parameters
- 📦 Plugin System: Share and reuse configurations via Git repositories
- 🎨 Format Presets: Support for popular code styles like Google, Airbnb, Standard
- ⚡ Parallel Processing: Leverage multi-core CPU for faster file processing
Installation
Method 1: Install via PyPI (Recommended for Python users)
# Using pip
# Using uv (recommended)
# pip install uv
Method 2: Install via Cargo (Recommended for Rust users)
Method 3: Build from Source
Quick Start
Initialize Configuration (Optional)
# Create project configuration file
# Create global configuration file
# Create global git hook template (for all new repos)
# Initialize with pre-commit hooks (project-level)
# Force overwrite existing files
Basic Usage
# Check and format current directory (default behavior)
# Check and format specific directories
# Check only, no formatting
# Format only, no checking
# Check Git staged files (suitable for pre-commit hook)
Specify Languages
# Check specific language
# Check multiple languages
Exclude Files
# Exclude specific patterns
Plugin System
linthis supports Git-based configuration plugins for easy sharing of code standards across projects and teams.
Add Plugin
# Add plugin to project config (.linthis.toml)
# Example: Add a custom plugin
# Add to global config (~/.linthis/config.toml)
Use Plugin
# Use plugin configuration for linting and formatting
# Combine with other options
Remove Plugin
# Remove plugin from project config
# Remove plugin from global config
# Supports flexible parameter ordering
View and Manage Plugins
# View project config plugins
# View global config plugins
# Update plugin cache
# Initialize new plugin
# Validate plugin structure
# Clean plugin cache
Configuration Files
Project Configuration
Create .linthis.toml in your project root:
# Specify languages to check (omit for auto-detection)
= ["rust", "python", "javascript"]
# Exclude files and directories
= [
"target/**",
"node_modules/**",
"*.generated.rs",
"dist/**"
]
# Maximum cyclomatic complexity
= 20
# Format preset
= "google" # Options: google, airbnb, standard
# Configure plugins
[]
= [
{ = "official" },
{ = "myplugin", = "https://github.com/zhlinh/linthis-plugin.git", = "main" }
]
# Language-specific configuration
# [rust]
# max_complexity = 15
# [python]
# excludes = ["*_test.py"]
Global Configuration
Global configuration file is located at ~/.linthis/config.toml, with the same format as project config.
Configuration Priority
Configuration merge priority (from high to low):
- CLI Parameters:
--option value - Project Config:
.linthis.toml - Global Config:
~/.linthis/config.toml - Plugin Config: Plugins in sources array (later ones override earlier ones)
- Built-in Defaults
Configuration Management
linthis provides a config subcommand for convenient command-line configuration management without manual TOML editing.
Array Field Operations
Supported array fields: includes, excludes, languages
Add Values (add)
# Add to project config
# Add to global config (-g or --global)
# Add multiple values (automatically deduped)
Remove Values (remove)
# Remove from project config
# Remove from global config
Clear Field (clear)
# Clear project config field
# Clear global config field
Scalar Field Operations
Supported scalar fields: max_complexity, preset, verbose
Set Value (set)
# Set complexity limit
# Set format preset (google, standard, airbnb)
# Set verbose output
Unset Value (unset)
# Remove field from project config
# Remove field from global config
Query Operations
Get Single Field Value (get)
# View project config field
# View global config field
List All Configuration (list)
# List project config
# List global config
# Verbose mode (show all fields including empty values)
Configuration Management Examples
# Initialize project config
# View config
# Adjust config
# Set global defaults
Initialize Configuration File
Use the init subcommand to explicitly create configuration files:
# Create project config (.linthis.toml)
# Create global config (~/.linthis/config.toml)
# Backward compatible: can also use --init flag
Auto-Create Configuration Files
When using the config command, configuration files are automatically created if they don't exist:
- Project Config: Creates
.linthis.tomlin current directory - Global Config: Creates
config.tomlin~/.linthis/directory
All modifications preserve TOML file format and comments.
Command Line Options
Main Command Options
| Short | Long | Description | Example |
|---|---|---|---|
-i |
--include |
Specify files or directories to check | -i src -i lib |
-e |
--exclude |
Exclude patterns (can be used multiple times) | -e "*.test.js" |
-p |
--plugin |
Use plugin (alias or Git URL) | -p myplugin |
-c |
--check-only |
Check only, no formatting | -c |
-f |
--format-only |
Format only, no checking | -f |
-s |
--staged |
Check only Git staged files | -s |
-l |
--lang |
Specify languages (comma-separated) | -l python,rust |
-o |
--output |
Output format: human, json, github-actions | -o json |
-v |
--verbose |
Verbose output | -v |
-q |
--quiet |
Quiet mode (errors only) | -q |
--config |
Specify config file path | --config custom.toml |
|
--init |
Initialize .linthis.toml config file | --init |
|
--preset |
Format preset | --preset google |
|
--plugin-update |
Force update plugin cache | --plugin-update |
|
--no-default-excludes |
Disable default exclude rules | --no-default-excludes |
|
--no-gitignore |
Disable .gitignore rules | --no-gitignore |
Plugin Management Subcommands
| Command | Short | Long | Description |
|---|---|---|---|
plugin add <alias> <url> |
-g |
--global |
Add to global config |
--ref |
Specify Git reference | ||
plugin remove <alias> |
-g |
--global |
Remove from global config |
plugin list |
-g |
--global |
Show global config plugins |
-v |
--verbose |
Show detailed info | |
plugin clean |
--all |
Clean all caches | |
plugin init <name> |
Initialize new plugin | ||
plugin validate <path> |
Validate plugin structure |
Configuration Management Subcommands
| Command | Short | Long | Description |
|---|---|---|---|
config add <field> <value> |
-g |
--global |
Add value to array field |
config remove <field> <value> |
-g |
--global |
Remove value from array field |
config clear <field> |
-g |
--global |
Clear array field |
config set <field> <value> |
-g |
--global |
Set scalar field value |
config unset <field> |
-g |
--global |
Remove scalar field |
config get <field> |
-g |
--global |
Get field value |
config list |
-g |
--global |
List all configuration |
-v |
--verbose |
Show detailed info (including empty values) |
Supported array fields: includes, excludes, languages
Supported scalar fields: max_complexity, preset, verbose
Init Subcommand
| Command | Short | Long | Description |
|---|---|---|---|
init |
-g |
--global |
Create global config file |
--hook |
Initialize pre-commit hooks | ||
-i |
--interactive |
Interactive mode for hooks setup | |
-f |
--force |
Force overwrite existing files |
Created configuration files:
- Without
-g: Creates.linthis.toml(current directory) - With
-g: Creates~/.linthis/config.toml(global config)
Hook options:
prek: Rust-based pre-commit tool (faster)pre-commit: Python-based standard toolgit: Traditional git hook
Supported Languages
| Language | Linter | Formatter |
|---|---|---|
| Rust | clippy | rustfmt |
| Python | pylint, flake8, ruff | black, ruff |
| TypeScript | eslint | prettier |
| JavaScript | eslint | prettier |
| Go | golangci-lint | gofmt |
| Java | checkstyle | google-java-format |
| C++ | cpplint, cppcheck | clang-format |
| Swift | swiftlint | swift-format |
| Kotlin | detekt | ktlint |
| Lua | luacheck | stylua |
| Dart | dart analyze | dart format |
Usage Scenarios
Pre-commit Hook
Method 1: Global Hook Template (One-time Setup)
Set up a global Git hook template that applies to all new repositories:
# Create global hook template
# All new repos will automatically include the hook
# .git/hooks/pre-commit is already set up!
For existing repositories:
Features:
- 🎯 Smart Detection: Only runs if project has linthis config
- 🔗 Hook Chaining: Supports
.git/hooks/pre-commit.localfor project-specific hooks - 🚫 Zero Interference: Projects without linthis config are not affected
- ⚡ One-time Setup: Works for all your new repositories
Pros:
- One-time setup for all your projects
- No need to configure hooks per project
- Perfect for personal development
- Won't interfere with other projects or hook tools
Cons:
- Not shared with team members
- Requires manual setup on each machine
See Global Hooks Guide for details.
Method 2: Using prek (Recommended for Teams)
prek is a high-performance Git hooks manager written in Rust, fully compatible with pre-commit config format but much faster.
Install prek:
# Using cargo
# Or using pip
Create .pre-commit-config.yaml in your project:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: linthis
name: linthis
entry: linthis --staged --check-only
language: system
pass_filenames: false
Install hook:
Method 3: Traditional Git Hook (Project-level)
Add to .git/hooks/pre-commit:
#!/bin/sh
Or use linthis to create it automatically:
Method 4: Using pre-commit Framework
Using the pre-commit framework:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: linthis
name: linthis
entry: linthis --staged --check-only
language: system
pass_filenames: false
CI/CD Integration
GitHub Actions
name: Lint
on:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install linthis
run: pip install linthis
- name: Run linthis
run: linthis --check-only --output github-actions
GitLab CI
lint:
image: rust:latest
script:
- cargo install linthis
- linthis --check-only
Creating Custom Plugins
1. Initialize Plugin
2. Edit Plugin Configuration
Edit linthis-plugin.toml:
[]
= "my-company-standards"
= "1.0.0"
= "My company's coding standards"
[]
= 2
[]
= "P0"
= [".flake8"]
[]
= "P1"
= ["pyproject.toml"]
3. Add Configuration Files
# Add your config files to corresponding language directories
4. Publish to Git
5. Use Your Plugin
FAQ
Q: How to specify multiple paths?
Q: How to check only specific file types?
Q: Where is the plugin cache?
- macOS:
~/Library/Caches/linthis/plugins - Linux:
~/.cache/linthis/plugins - Windows:
%LOCALAPPDATA%\linthis\plugins
Q: How to update plugins?
Q: What is the plugin Git reference (ref) used for?
The ref can specify:
- Branch name:
--ref main - Tag:
--ref v1.0.0 - Commit hash:
--ref abc1234
This allows you to lock plugin versions or use development versions.
Documentation
- Plugin Auto-Sync - Automatic plugin synchronization (inspired by oh-my-zsh)
- Self Auto-Update - Automatic self-update functionality
Development
Build
Test
Release
Contributing
Issues and Pull Requests are welcome!
License
MIT License - See LICENSE file for details