thailint 0.1.5__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. src/__init__.py +7 -2
  2. src/analyzers/__init__.py +23 -0
  3. src/analyzers/typescript_base.py +148 -0
  4. src/api.py +1 -1
  5. src/cli.py +498 -141
  6. src/config.py +6 -31
  7. src/core/base.py +12 -0
  8. src/core/cli_utils.py +206 -0
  9. src/core/config_parser.py +99 -0
  10. src/core/linter_utils.py +168 -0
  11. src/core/registry.py +17 -92
  12. src/core/rule_discovery.py +132 -0
  13. src/core/violation_builder.py +122 -0
  14. src/linter_config/ignore.py +112 -40
  15. src/linter_config/loader.py +3 -13
  16. src/linters/dry/__init__.py +23 -0
  17. src/linters/dry/base_token_analyzer.py +76 -0
  18. src/linters/dry/block_filter.py +262 -0
  19. src/linters/dry/block_grouper.py +59 -0
  20. src/linters/dry/cache.py +218 -0
  21. src/linters/dry/cache_query.py +61 -0
  22. src/linters/dry/config.py +130 -0
  23. src/linters/dry/config_loader.py +44 -0
  24. src/linters/dry/deduplicator.py +120 -0
  25. src/linters/dry/duplicate_storage.py +126 -0
  26. src/linters/dry/file_analyzer.py +127 -0
  27. src/linters/dry/inline_ignore.py +140 -0
  28. src/linters/dry/linter.py +170 -0
  29. src/linters/dry/python_analyzer.py +517 -0
  30. src/linters/dry/storage_initializer.py +51 -0
  31. src/linters/dry/token_hasher.py +115 -0
  32. src/linters/dry/typescript_analyzer.py +590 -0
  33. src/linters/dry/violation_builder.py +74 -0
  34. src/linters/dry/violation_filter.py +91 -0
  35. src/linters/dry/violation_generator.py +174 -0
  36. src/linters/file_placement/config_loader.py +86 -0
  37. src/linters/file_placement/directory_matcher.py +80 -0
  38. src/linters/file_placement/linter.py +252 -472
  39. src/linters/file_placement/path_resolver.py +61 -0
  40. src/linters/file_placement/pattern_matcher.py +55 -0
  41. src/linters/file_placement/pattern_validator.py +106 -0
  42. src/linters/file_placement/rule_checker.py +229 -0
  43. src/linters/file_placement/violation_factory.py +177 -0
  44. src/linters/nesting/config.py +13 -3
  45. src/linters/nesting/linter.py +76 -152
  46. src/linters/nesting/typescript_analyzer.py +38 -102
  47. src/linters/nesting/typescript_function_extractor.py +130 -0
  48. src/linters/nesting/violation_builder.py +139 -0
  49. src/linters/srp/__init__.py +99 -0
  50. src/linters/srp/class_analyzer.py +113 -0
  51. src/linters/srp/config.py +76 -0
  52. src/linters/srp/heuristics.py +89 -0
  53. src/linters/srp/linter.py +225 -0
  54. src/linters/srp/metrics_evaluator.py +47 -0
  55. src/linters/srp/python_analyzer.py +72 -0
  56. src/linters/srp/typescript_analyzer.py +75 -0
  57. src/linters/srp/typescript_metrics_calculator.py +90 -0
  58. src/linters/srp/violation_builder.py +117 -0
  59. src/orchestrator/core.py +42 -7
  60. src/utils/__init__.py +4 -0
  61. src/utils/project_root.py +84 -0
  62. {thailint-0.1.5.dist-info → thailint-0.2.0.dist-info}/METADATA +414 -63
  63. thailint-0.2.0.dist-info/RECORD +75 -0
  64. src/.ai/layout.yaml +0 -48
  65. thailint-0.1.5.dist-info/RECORD +0 -28
  66. {thailint-0.1.5.dist-info → thailint-0.2.0.dist-info}/LICENSE +0 -0
  67. {thailint-0.1.5.dist-info → thailint-0.2.0.dist-info}/WHEEL +0 -0
  68. {thailint-0.1.5.dist-info → thailint-0.2.0.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: thailint
3
- Version: 0.1.5
3
+ Version: 0.2.0
4
4
  Summary: The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages
5
5
  License: MIT
6
6
  Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python
@@ -22,6 +22,7 @@ Classifier: Topic :: Software Development :: Testing
22
22
  Classifier: Topic :: Utilities
23
23
  Classifier: Typing :: Typed
24
24
  Requires-Dist: click (>=8.1.0,<9.0.0)
25
+ Requires-Dist: pyprojroot (>=0.3.0,<0.4.0)
25
26
  Requires-Dist: pyyaml (>=6.0,<7.0)
26
27
  Requires-Dist: tree-sitter (>=0.25.2,<0.26.0)
27
28
  Requires-Dist: tree-sitter-typescript (>=0.23.2,<0.24.0)
@@ -43,30 +44,40 @@ The AI Linter - Enterprise-ready linting and governance for AI-generated code ac
43
44
 
44
45
  thailint is a modern, enterprise-ready multi-language linter designed specifically for AI-generated code. It enforces project structure, file placement rules, and coding standards across Python, TypeScript, and other languages.
45
46
 
46
- ## Features
47
+ ## Features
47
48
 
48
49
  ### Core Capabilities
49
- - 🎯 **File Placement Linting** - Enforce project structure and organization
50
- - 🔄 **Nesting Depth Linting** - Detect excessive code nesting with AST analysis
50
+ - **File Placement Linting** - Enforce project structure and organization
51
+ - **Nesting Depth Linting** - Detect excessive code nesting with AST analysis
51
52
  - Python and TypeScript support with tree-sitter
52
53
  - Configurable max depth (default: 4, recommended: 3)
53
54
  - Helpful refactoring suggestions (guard clauses, extract method)
54
- - 🔌 **Pluggable Architecture** - Easy to extend with custom linters
55
- - 🌍 **Multi-Language Support** - Python, TypeScript, JavaScript, and more
56
- - ⚙️ **Flexible Configuration** - YAML/JSON configs with pattern matching
57
- - 🚫 **5-Level Ignore System** - Repo, directory, file, method, and line-level ignores
55
+ - **SRP Linting** - Detect Single Responsibility Principle violations
56
+ - Heuristic-based analysis (method count, LOC, keywords)
57
+ - Language-specific thresholds (Python, TypeScript, JavaScript)
58
+ - Refactoring patterns from real-world examples
59
+ - **DRY Linting** - Detect duplicate code across projects
60
+ - Token-based hash detection with SQLite caching
61
+ - Fast incremental scans (10-50x speedup with cache)
62
+ - Configurable thresholds (lines, tokens, occurrences)
63
+ - Language-specific detection (Python, TypeScript, JavaScript)
64
+ - False positive filtering (keyword args, imports)
65
+ - **Pluggable Architecture** - Easy to extend with custom linters
66
+ - **Multi-Language Support** - Python, TypeScript, JavaScript, and more
67
+ - **Flexible Configuration** - YAML/JSON configs with pattern matching
68
+ - **5-Level Ignore System** - Repo, directory, file, method, and line-level ignores
58
69
 
59
70
  ### Deployment Modes
60
- - 💻 **CLI Mode** - Full-featured command-line interface
61
- - 📚 **Library API** - Python library for programmatic integration
62
- - 🐳 **Docker Support** - Containerized deployment for CI/CD
71
+ - **CLI Mode** - Full-featured command-line interface
72
+ - **Library API** - Python library for programmatic integration
73
+ - **Docker Support** - Containerized deployment for CI/CD
63
74
 
64
75
  ### Enterprise Features
65
- - 📊 **Performance** - <100ms for single files, <5s for 1000 files
66
- - 🔒 **Type Safety** - Full type hints and MyPy strict mode
67
- - 🧪 **Test Coverage** - 90% coverage with 317 tests
68
- - 📈 **CI/CD Ready** - Proper exit codes and JSON output
69
- - 📝 **Comprehensive Docs** - Complete documentation and examples
76
+ - **Performance** - <100ms for single files, <5s for 1000 files
77
+ - **Type Safety** - Full type hints and MyPy strict mode
78
+ - **Test Coverage** - 90% coverage with 317 tests
79
+ - **CI/CD Ready** - Proper exit codes and JSON output
80
+ - **Comprehensive Docs** - Complete documentation and examples
70
81
 
71
82
  ## Installation
72
83
 
@@ -105,14 +116,20 @@ docker run --rm washad/thailint:latest --help
105
116
  # Check file placement
106
117
  thailint file-placement .
107
118
 
108
- # Check nesting depth
119
+ # Check multiple files
120
+ thailint nesting file1.py file2.py file3.py
121
+
122
+ # Check specific directory
109
123
  thailint nesting src/
110
124
 
125
+ # Check for duplicate code
126
+ thailint dry .
127
+
111
128
  # With config file
112
- thailint nesting --config .thailint.yaml src/
129
+ thailint dry --config .thailint.yaml src/
113
130
 
114
131
  # JSON output for CI/CD
115
- thailint nesting --format json src/
132
+ thailint dry --format json src/
116
133
  ```
117
134
 
118
135
  ### Library Mode
@@ -135,13 +152,21 @@ if violations:
135
152
  ### Docker Mode
136
153
 
137
154
  ```bash
138
- # Run with volume mount
155
+ # Lint directory (recommended - lints all files inside)
139
156
  docker run --rm -v $(pwd):/data \
140
157
  washad/thailint:latest file-placement /data
141
158
 
142
- # Check nesting depth
159
+ # Lint single file
160
+ docker run --rm -v $(pwd):/data \
161
+ washad/thailint:latest file-placement /data/src/app.py
162
+
163
+ # Lint multiple specific files
164
+ docker run --rm -v $(pwd):/data \
165
+ washad/thailint:latest nesting /data/src/file1.py /data/src/file2.py
166
+
167
+ # Check nesting depth in subdirectory
143
168
  docker run --rm -v $(pwd):/data \
144
- washad/thailint:latest nesting /data
169
+ washad/thailint:latest nesting /data/src
145
170
  ```
146
171
 
147
172
  ## Configuration
@@ -191,6 +216,26 @@ nesting:
191
216
  max_depth: 4
192
217
  javascript:
193
218
  max_depth: 4
219
+
220
+ # DRY linter configuration
221
+ dry:
222
+ enabled: true
223
+ min_duplicate_lines: 4 # Minimum lines to consider duplicate
224
+ min_duplicate_tokens: 30 # Minimum tokens to consider duplicate
225
+ min_occurrences: 2 # Report if appears 2+ times
226
+
227
+ # Language-specific thresholds
228
+ python:
229
+ min_occurrences: 3 # Python: require 3+ occurrences
230
+
231
+ # Cache settings (SQLite)
232
+ cache_enabled: true
233
+ cache_path: ".thailint-cache/dry.db"
234
+
235
+ # Ignore patterns
236
+ ignore:
237
+ - "tests/"
238
+ - "__init__.py"
194
239
  ```
195
240
 
196
241
  **JSON format also supported** (`.thailint.json`):
@@ -214,6 +259,18 @@ nesting:
214
259
  "python": { "max_depth": 4 },
215
260
  "typescript": { "max_depth": 4 }
216
261
  }
262
+ },
263
+ "dry": {
264
+ "enabled": true,
265
+ "min_duplicate_lines": 4,
266
+ "min_duplicate_tokens": 30,
267
+ "min_occurrences": 2,
268
+ "python": {
269
+ "min_occurrences": 3
270
+ },
271
+ "cache_enabled": true,
272
+ "cache_path": ".thailint-cache/dry.db",
273
+ "ignore": ["tests/", "__init__.py"]
217
274
  }
218
275
  }
219
276
  ```
@@ -280,7 +337,7 @@ def process_data(items):
280
337
 
281
338
  ### Refactoring Patterns
282
339
 
283
- Common patterns to reduce nesting (used to fix 23 violations in thai-lint):
340
+ Common patterns to reduce nesting:
284
341
 
285
342
  1. **Guard Clauses (Early Returns)**
286
343
  - Replace `if x: do_something()` with `if not x: return`
@@ -300,19 +357,300 @@ Common patterns to reduce nesting (used to fix 23 violations in thai-lint):
300
357
 
301
358
  ### Language Support
302
359
 
303
- - **Python**: Full support (if/for/while/with/try/match)
304
- - **TypeScript**: Full support (if/for/while/try/switch)
305
- - **JavaScript**: Supported via TypeScript parser
360
+ - **Python**: Full support (if/for/while/with/try/match)
361
+ - **TypeScript**: Full support (if/for/while/try/switch)
362
+ - **JavaScript**: Supported via TypeScript parser
306
363
 
307
- ### Refactoring Case Study
364
+ See [Nesting Linter Guide](docs/nesting-linter.md) for comprehensive documentation and refactoring patterns.
308
365
 
309
- The thai-lint codebase serves as a validation of the nesting linter:
310
- - Identified: 23 functions requiring refactoring (depth 4 → depth ≤3)
311
- - Refactored using documented patterns
312
- - Time estimate: ~10 minutes per function
313
- - Result: Zero violations, improved readability
366
+ ## Single Responsibility Principle (SRP) Linter
314
367
 
315
- See [Nesting Linter Guide](docs/nesting-linter.md) for comprehensive documentation and refactoring patterns.
368
+ ### Overview
369
+
370
+ The SRP linter detects classes that violate the Single Responsibility Principle by having too many methods, too many lines of code, or generic naming patterns. It uses AST analysis with configurable heuristics to identify classes that likely handle multiple responsibilities.
371
+
372
+ ### Quick Start
373
+
374
+ ```bash
375
+ # Check SRP violations in current directory
376
+ thailint srp .
377
+
378
+ # Use custom thresholds
379
+ thailint srp --max-methods 10 --max-loc 300 src/
380
+
381
+ # Get JSON output
382
+ thailint srp --format json src/
383
+ ```
384
+
385
+ ### Configuration
386
+
387
+ Add to `.thailint.yaml`:
388
+
389
+ ```yaml
390
+ srp:
391
+ enabled: true
392
+ max_methods: 7 # Maximum methods per class
393
+ max_loc: 200 # Maximum lines of code per class
394
+
395
+ # Language-specific thresholds
396
+ python:
397
+ max_methods: 8
398
+ max_loc: 200
399
+
400
+ typescript:
401
+ max_methods: 10 # TypeScript more verbose
402
+ max_loc: 250
403
+ ```
404
+
405
+ ### Detection Heuristics
406
+
407
+ The SRP linter uses three heuristics to detect violations:
408
+
409
+ 1. **Method Count**: Classes with >7 methods (default) likely have multiple responsibilities
410
+ 2. **Lines of Code**: Classes with >200 LOC (default) are often doing too much
411
+ 3. **Responsibility Keywords**: Names containing "Manager", "Handler", "Processor", etc.
412
+
413
+ ### Example Violation
414
+
415
+ **Code with SRP violation:**
416
+ ```python
417
+ class UserManager: # 8 methods, contains "Manager" keyword
418
+ def create_user(self): pass
419
+ def update_user(self): pass
420
+ def delete_user(self): pass
421
+ def send_email(self): pass # ← Different responsibility
422
+ def log_action(self): pass # ← Different responsibility
423
+ def validate_data(self): pass # ← Different responsibility
424
+ def generate_report(self): pass # ← Different responsibility
425
+ def export_data(self): pass # ← Violation at method 8
426
+ ```
427
+
428
+ **Refactored following SRP:**
429
+ ```python
430
+ class UserRepository: # 3 methods ✓
431
+ def create(self, user): pass
432
+ def update(self, user): pass
433
+ def delete(self, user): pass
434
+
435
+ class EmailService: # 1 method ✓
436
+ def send(self, user, template): pass
437
+
438
+ class UserAuditLog: # 1 method ✓
439
+ def log(self, action, user): pass
440
+
441
+ class UserValidator: # 1 method ✓
442
+ def validate(self, data): pass
443
+
444
+ class ReportGenerator: # 1 method ✓
445
+ def generate(self, users): pass
446
+ ```
447
+
448
+ ### Refactoring Patterns
449
+
450
+ Common patterns to fix SRP violations (discovered during dogfooding):
451
+
452
+ 1. **Extract Class**
453
+ - Split god classes into focused classes
454
+ - Each class handles one responsibility
455
+
456
+ 2. **Split Configuration and Logic**
457
+ - Separate config loading from business logic
458
+ - Create dedicated ConfigLoader classes
459
+
460
+ 3. **Extract Language-Specific Logic**
461
+ - Separate Python/TypeScript analysis
462
+ - Use analyzer classes per language
463
+
464
+ 4. **Utility Module Pattern**
465
+ - Group related helper methods
466
+ - Create focused utility classes
467
+
468
+ ### Language Support
469
+
470
+ - **Python**: Full support with method counting and LOC analysis
471
+ - **TypeScript**: Full support with tree-sitter parsing
472
+ - **JavaScript**: Supported via TypeScript parser
473
+
474
+ ### Real-World Example
475
+
476
+ **Large class refactoring:**
477
+ - **Before**: FilePlacementLinter (33 methods, 382 LOC) - single class handling config, patterns, validation
478
+ - **After**: Extract Class pattern applied - 5 focused classes (ConfigLoader, PatternValidator, RuleChecker, PathResolver, FilePlacementLinter)
479
+ - **Result**: Each class ≤8 methods, ≤150 LOC, single responsibility
480
+
481
+ See [SRP Linter Guide](docs/srp-linter.md) for comprehensive documentation and refactoring patterns.
482
+
483
+ ## DRY Linter (Don't Repeat Yourself)
484
+
485
+ ### Overview
486
+
487
+ The DRY linter detects duplicate code blocks across your entire project using token-based hashing with SQLite caching. It identifies identical or near-identical code that violates the Don't Repeat Yourself (DRY) principle, helping maintain code quality at scale.
488
+
489
+ ### Quick Start
490
+
491
+ ```bash
492
+ # Check for duplicate code in current directory
493
+ thailint dry .
494
+
495
+ # Use custom thresholds
496
+ thailint dry --min-lines 5 src/
497
+
498
+ # Clear cache and re-scan
499
+ thailint dry --clear-cache src/
500
+
501
+ # Get JSON output
502
+ thailint dry --format json src/
503
+ ```
504
+
505
+ ### Configuration
506
+
507
+ Add to `.thailint.yaml`:
508
+
509
+ ```yaml
510
+ dry:
511
+ enabled: true
512
+ min_duplicate_lines: 4 # Minimum lines to consider duplicate
513
+ min_duplicate_tokens: 30 # Minimum tokens to consider duplicate
514
+ min_occurrences: 2 # Report if appears 2+ times
515
+
516
+ # Language-specific thresholds
517
+ python:
518
+ min_occurrences: 3 # Python: require 3+ occurrences
519
+ typescript:
520
+ min_occurrences: 3 # TypeScript: require 3+ occurrences
521
+
522
+ # Cache settings (SQLite for fast incremental scans)
523
+ cache_enabled: true
524
+ cache_path: ".thailint-cache/dry.db"
525
+ cache_max_age_days: 30
526
+
527
+ # Ignore patterns
528
+ ignore:
529
+ - "tests/" # Test code often has acceptable duplication
530
+ - "__init__.py" # Import-only files exempt
531
+
532
+ # False positive filters
533
+ filters:
534
+ keyword_argument_filter: true # Filter function call kwargs
535
+ import_group_filter: true # Filter import groups
536
+ ```
537
+
538
+ ### How It Works
539
+
540
+ **Token-Based Detection:**
541
+ 1. Parse code into tokens (stripping comments, normalizing whitespace)
542
+ 2. Create rolling hash windows of N lines
543
+ 3. Store hashes in SQLite database with file locations
544
+ 4. Query for hashes appearing 2+ times across project
545
+
546
+ **SQLite Caching:**
547
+ - First scan: Hash all files (~1-3s for 1000 files)
548
+ - Subsequent scans: Load cached hashes for unchanged files (~0.1-0.5s)
549
+ - 10-50x speedup for incremental scans
550
+ - Mtime-based cache invalidation (automatic and safe)
551
+
552
+ ### Example Violation
553
+
554
+ **Code with duplication:**
555
+ ```python
556
+ # src/auth.py
557
+ def validate_user(user_data):
558
+ if not user_data:
559
+ return False
560
+ if not user_data.get('email'):
561
+ return False
562
+ if not user_data.get('password'):
563
+ return False
564
+ return True
565
+
566
+ # src/admin.py
567
+ def validate_admin(admin_data):
568
+ if not admin_data:
569
+ return False
570
+ if not admin_data.get('email'):
571
+ return False
572
+ if not admin_data.get('password'):
573
+ return False
574
+ return True
575
+ ```
576
+
577
+ **Violation message:**
578
+ ```
579
+ src/auth.py:3 - Duplicate code detected (4 lines, 2 occurrences)
580
+ Locations:
581
+ - src/auth.py:3-6
582
+ - src/admin.py:3-6
583
+ Consider extracting to shared function
584
+ ```
585
+
586
+ **Refactored (DRY):**
587
+ ```python
588
+ # src/validators.py
589
+ def validate_credentials(data):
590
+ if not data:
591
+ return False
592
+ if not data.get('email'):
593
+ return False
594
+ if not data.get('password'):
595
+ return False
596
+ return True
597
+
598
+ # src/auth.py & src/admin.py
599
+ from src.validators import validate_credentials
600
+
601
+ def validate_user(user_data):
602
+ return validate_credentials(user_data)
603
+
604
+ def validate_admin(admin_data):
605
+ return validate_credentials(admin_data)
606
+ ```
607
+
608
+ ### Cache Management
609
+
610
+ ```bash
611
+ # Normal cached run (default)
612
+ thailint dry src/
613
+
614
+ # Force re-analysis (ignore cache)
615
+ thailint dry --no-cache src/
616
+
617
+ # Clear cache before running
618
+ thailint dry --clear-cache src/
619
+
620
+ # Manual cache cleanup
621
+ rm -rf .thailint-cache/dry.db
622
+ ```
623
+
624
+ ### Performance
625
+
626
+ | Operation | Performance | Cache Status |
627
+ |-----------|-------------|--------------|
628
+ | First scan (1000 files) | 1-3s | Cache write |
629
+ | Unchanged files | 0.1-0.5s | Cache hit |
630
+ | 50 changed files | 0.5-1s | Partial cache |
631
+
632
+ **Speedup**: 3-10x for incremental scans with cache
633
+
634
+ ### Language Support
635
+
636
+ - **Python**: Full support with AST-based tokenization
637
+ - **TypeScript**: Full support with tree-sitter parsing
638
+ - **JavaScript**: Supported via TypeScript parser
639
+
640
+ ### False Positive Filtering
641
+
642
+ Built-in filters automatically exclude common non-duplication patterns:
643
+ - **keyword_argument_filter**: Excludes function calls with keyword arguments
644
+ - **import_group_filter**: Excludes import statement groups
645
+
646
+ ### Refactoring Patterns
647
+
648
+ 1. **Extract Function**: Move repeated logic to shared function
649
+ 2. **Extract Base Class**: Create base class for similar implementations
650
+ 3. **Extract Utility Module**: Move helper functions to shared utilities
651
+ 4. **Template Method**: Use function parameters for variations
652
+
653
+ See [DRY Linter Guide](docs/dry-linter.md) for comprehensive documentation, cache management, and refactoring patterns.
316
654
 
317
655
  ## Pre-commit Hooks
318
656
 
@@ -335,13 +673,13 @@ pre-commit run --all-files
335
673
  ### What You Get
336
674
 
337
675
  **On every commit:**
338
- - 🚫 Prevents commits to main/master branch
339
- - 🎨 Auto-fixes formatting issues
340
- - Runs thailint on changed files (fast)
676
+ - Prevents commits to main/master branch
677
+ - Auto-fixes formatting issues
678
+ - Runs thailint on changed files (fast, uses pass_filenames: true)
341
679
 
342
680
  **On every push:**
343
- - 🔍 Full linting on entire codebase
344
- - 🧪 Runs complete test suite
681
+ - Full linting on entire codebase
682
+ - Runs complete test suite
345
683
 
346
684
  ### Example Configuration
347
685
 
@@ -353,7 +691,7 @@ repos:
353
691
  # Prevent commits to protected branches
354
692
  - id: no-commit-to-main
355
693
  name: Prevent commits to main branch
356
- entry: bash -c 'branch=$(git rev-parse --abbrev-ref HEAD); if [ "$branch" = "main" ]; then echo " Use a feature branch!"; exit 1; fi'
694
+ entry: bash -c 'branch=$(git rev-parse --abbrev-ref HEAD); if [ "$branch" = "main" ]; then echo "ERROR: Use a feature branch!"; exit 1; fi'
357
695
  language: system
358
696
  pass_filenames: false
359
697
  always_run: true
@@ -361,16 +699,17 @@ repos:
361
699
  # Auto-format code
362
700
  - id: format
363
701
  name: Auto-fix formatting
364
- entry: make format
702
+ entry: just format
365
703
  language: system
366
704
  pass_filenames: false
367
705
 
368
- # Run thailint on changed files
369
- - id: lint-changed
706
+ # Run thailint on changed files (passes filenames directly)
707
+ - id: thailint-changed
370
708
  name: Lint changed files
371
- entry: make lint-full FILES=changed
709
+ entry: thailint nesting
372
710
  language: system
373
- pass_filenames: false
711
+ files: \.(py|ts|tsx|js|jsx)$
712
+ pass_filenames: true
374
713
  ```
375
714
 
376
715
  See **[Pre-commit Hooks Guide](docs/pre-commit-hooks.md)** for complete documentation, troubleshooting, and advanced configuration.
@@ -478,31 +817,43 @@ docker pull washad/thailint:latest
478
817
  # Run CLI help
479
818
  docker run --rm washad/thailint:latest --help
480
819
 
481
- # Run file-placement linter
820
+ # Lint entire directory (recommended)
482
821
  docker run --rm -v $(pwd):/data washad/thailint:latest file-placement /data
483
822
 
484
- # Run nesting linter
485
- docker run --rm -v $(pwd):/data washad/thailint:latest nesting /data
823
+ # Lint single file
824
+ docker run --rm -v $(pwd):/data washad/thailint:latest file-placement /data/src/app.py
825
+
826
+ # Lint multiple specific files
827
+ docker run --rm -v $(pwd):/data washad/thailint:latest nesting /data/src/file1.py /data/src/file2.py
828
+
829
+ # Lint specific subdirectory
830
+ docker run --rm -v $(pwd):/data washad/thailint:latest nesting /data/src
486
831
 
487
832
  # With custom config
488
833
  docker run --rm -v $(pwd):/data \
489
834
  washad/thailint:latest nesting --config /data/.thailint.yaml /data
835
+
836
+ # JSON output for CI/CD
837
+ docker run --rm -v $(pwd):/data \
838
+ washad/thailint:latest file-placement --format json /data
490
839
  ```
491
840
 
492
841
  ## Documentation
493
842
 
494
843
  ### Comprehensive Guides
495
844
 
496
- - 📖 **[Getting Started](docs/getting-started.md)** - Installation, first lint, basic config
497
- - ⚙️ **[Configuration Reference](docs/configuration.md)** - Complete config options (YAML/JSON)
498
- - 📚 **[API Reference](docs/api-reference.md)** - Library API documentation
499
- - 💻 **[CLI Reference](docs/cli-reference.md)** - All CLI commands and options
500
- - 🚀 **[Deployment Modes](docs/deployment-modes.md)** - CLI, Library, and Docker usage
501
- - 📁 **[File Placement Linter](docs/file-placement-linter.md)** - Detailed linter guide
502
- - 🔄 **[Nesting Depth Linter](docs/nesting-linter.md)** - Nesting depth analysis guide
503
- - 🪝 **[Pre-commit Hooks](docs/pre-commit-hooks.md)** - Automated quality checks
504
- - 📦 **[Publishing Guide](docs/releasing.md)** - Release and publishing workflow
505
- - **[Publishing Checklist](docs/publishing-checklist.md)** - Post-publication validation
845
+ - **[Getting Started](docs/getting-started.md)** - Installation, first lint, basic config
846
+ - **[Configuration Reference](docs/configuration.md)** - Complete config options (YAML/JSON)
847
+ - **[API Reference](docs/api-reference.md)** - Library API documentation
848
+ - **[CLI Reference](docs/cli-reference.md)** - All CLI commands and options
849
+ - **[Deployment Modes](docs/deployment-modes.md)** - CLI, Library, and Docker usage
850
+ - **[File Placement Linter](docs/file-placement-linter.md)** - Detailed linter guide
851
+ - **[Nesting Depth Linter](docs/nesting-linter.md)** - Nesting depth analysis guide
852
+ - **[SRP Linter](docs/srp-linter.md)** - Single Responsibility Principle guide
853
+ - **[DRY Linter](docs/dry-linter.md)** - Duplicate code detection guide
854
+ - **[Pre-commit Hooks](docs/pre-commit-hooks.md)** - Automated quality checks
855
+ - **[Publishing Guide](docs/releasing.md)** - Release and publishing workflow
856
+ - **[Publishing Checklist](docs/publishing-checklist.md)** - Post-publication validation
506
857
 
507
858
  ### Examples
508
859
 
@@ -578,10 +929,10 @@ thailint is designed for speed and efficiency:
578
929
 
579
930
  | Operation | Performance | Target |
580
931
  |-----------|-------------|--------|
581
- | Single file lint | ~20ms | <100ms |
582
- | 100 files | ~300ms | <1s |
583
- | 1000 files | ~900ms | <5s |
584
- | Config loading | ~10ms | <100ms |
932
+ | Single file lint | ~20ms | <100ms |
933
+ | 100 files | ~300ms | <1s |
934
+ | 1000 files | ~900ms | <5s |
935
+ | Config loading | ~10ms | <100ms |
585
936
 
586
937
  *Performance benchmarks run on standard hardware, your results may vary.*
587
938
 
@@ -596,9 +947,9 @@ thailint uses standard exit codes for CI/CD integration:
596
947
  ```bash
597
948
  thailint file-placement .
598
949
  if [ $? -eq 0 ]; then
599
- echo "Linting passed"
950
+ echo "Linting passed"
600
951
  else
601
- echo "Linting failed"
952
+ echo "Linting failed"
602
953
  fi
603
954
  ```
604
955