todo-scan 0.1.1

Track TODO/FIXME/HACK comments with git-aware diff and CI gate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
# todo-scan

[![Crates.io](https://img.shields.io/crates/v/todo-scan.svg)](https://crates.io/crates/todo-scan)
[![CI](https://github.com/sotayamashita/todo-scan/actions/workflows/ci.yml/badge.svg)](https://github.com/sotayamashita/todo-scan/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/sotayamashita/todo-scan/graph/badge.svg)](https://codecov.io/gh/sotayamashita/todo-scan)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/sotayamashita/todo-scan)

A CI gate that fails your build when TODO comments exceed thresholds, so technical debt stays visible and under control.

### Why not `grep -r TODO .`?

- **No CI enforcement** — grep finds TODOs but can't fail a build when the count crosses a limit
- **No git awareness** — grep can't show which TODOs were added in a branch or since a specific commit
- **No structure** — grep gives raw text; todo-scan extracts tags, authors, priorities, issue refs, and deadlines
- **No format enforcement** — grep can't reject malformed TODOs like `todo fix this` in a pre-merge check

### Quick start

```sh
cargo install todo-scan

# See what you have
todo-scan list

# Set a ceiling and enforce it in CI
todo-scan check --max 100
```

### Key commands

| Command | What it does |
|---|---|
| `todo-scan check --max 100` | CI gate — fails the build when TODO count exceeds the threshold |
| `todo-scan diff main` | Shows TODOs added/removed since a git ref — useful in PR review |
| `todo-scan lint` | Enforces consistent TODO formatting (uppercase, colon, author) |

## Features

1. **Discover**
     - [Scan & List TODOs]#scan--list-todos
     - [Search TODOs]#search-todos
     - [Inline Code Context]#inline-code-context
     - [Progressive Detail Levels]#progressive-detail-levels
2. **Analyze**
     - [Diff Against Git Refs]#diff-against-git-refs
     - [Dashboard & Statistics]#dashboard--statistics
     - [Git Blame Integration]#git-blame-integration
     - [Discover TODO Relationships]#discover-todo-relationships
3. **Enforce**
     - [Inline Suppression]#inline-suppression
     - [Lint TODO Format]#lint-todo-format
     - [Clean Stale & Duplicate TODOs]#clean-stale--duplicate-todos
     - [CI Quality Gate]#ci-quality-gate
4. **Scale**
     - [Workspace-Aware Scanning]#workspace-aware-scanning
     - [Per-Package CI Gate]#per-package-ci-gate
     - [Single Package Scope]#single-package-scope
5. **Report & Integrate**
     - [HTML Report Generation]#html-report-generation
     - [CI Output Formats]#ci-output-formats
     - [Claude Code Task Export]#claude-code-task-export
6. **Productivity**
     - [Real-time File Watching]#real-time-file-watching
     - [Interactive Setup]#interactive-setup
     - [Shell Completions]#shell-completions

### Scan & List TODOs

🔥 **Problem**

TODO comments scatter across hundreds of files, making it hard to know what's outstanding.

🌱 **Solution**

`todo-scan list` scans your entire codebase and displays every TODO, FIXME, HACK, XXX, BUG, and NOTE comment with color-coded tags, flexible grouping (`--group-by file|tag|priority|author|dir`), and filtering by priority, author, path glob, and result limit.

🎁 **Outcome**

One command gives you a complete, filterable inventory of all technical debt markers in your project.

```sh
todo-scan list --group-by tag --priority high
```

### Search TODOs

🔥 **Problem**

Scrolling through `todo-scan list` output or manually grepping to find specific TODOs is impractical in large codebases with hundreds of items.

🌱 **Solution**

`todo-scan search` filters TODO comments by message text or issue reference using case-insensitive substring matching, with `--exact` for case-sensitive searches and `-C` for context lines.

🎁 **Outcome**

You can instantly find relevant TODOs without scrolling through hundreds of items.

```sh
todo-scan search "migration" --author alice
```

### Inline Code Context

🔥 **Problem**

TODO lists show file:line references but lack surrounding code, forcing you to open files to understand what each TODO refers to.

🌱 **Solution**

`todo-scan context` displays the code around a specific line with related TODOs in the same file, and the `-C N` flag on `list` and `diff` adds inline context to every item.

🎁 **Outcome**

You understand what each TODO refers to without leaving the terminal.

```sh
todo-scan context src/main.rs:25 -C 3
```

### Progressive Detail Levels

🔥 **Problem**

Humans scanning a terminal need compact output, while AI agents need full metadata — but every command outputs the same level of detail regardless of the consumer.

🌱 **Solution**

`--detail minimal|normal|full` controls information density across `list`, `diff`, and `search`: `minimal` shows only file, line, tag, and message; `normal` (default) preserves current behavior; `full` injects `match_key` and auto-collects surrounding source context.

🎁 **Outcome**

One flag adapts todo-scan output from quick human glances to rich machine-readable payloads without separate commands.

```sh
todo-scan list --detail minimal
todo-scan search "migration" --detail full --format json
```

### Diff Against Git Refs

🔥 **Problem**

New TODOs slip into pull requests unnoticed while resolved ones go unrecognized.

🌱 **Solution**

`todo-scan diff` compares the current working tree against any git ref and shows exactly which TODOs were added or removed.

🎁 **Outcome**

Every PR review shows precisely what TODO debt changed, making it impossible to sneak in untracked work.

```sh
todo-scan diff main
```

### Dashboard & Statistics

🔥 **Problem**

A flat list of TODOs makes it hard to see the big picture — whether tech debt is growing, who owns the most items, and which files are hotspots.

🌱 **Solution**

`todo-scan stats` provides a dashboard summary with tag and author breakdowns, priority distribution, and top files by TODO count, with `--since <ref>` for trend analysis.

🎁 **Outcome**

You get an at-a-glance view of your project's technical debt health and trends.

```sh
todo-scan stats --since main
```

### Compressed Brief Summary

🔥 **Problem**

AI agents and developers working in token-constrained environments need a quick TODO landscape overview without consuming excessive context window or screen space.

🌱 **Solution**

`todo-scan brief` produces a compressed 2-4 line summary showing total counts, priority breakdown, and the single most urgent item, with optional `--since <ref>` for trend info and `--budget N` to cap output lines.

🎁 **Outcome**

You get the essential TODO health signal in minimal output, ideal for CI summaries and AI agent context.

```sh
todo-scan brief --since main --budget 2
```

### Git Blame Integration

🔥 **Problem**

TODO comments lack accountability — you can't tell who wrote them or when without manually running `git blame`.

🌱 **Solution**

`todo-scan blame` enriches each TODO with git blame metadata including author, commit date, and age in days, and flags items older than a configurable threshold as stale.

🎁 **Outcome**

Every TODO has clear ownership and age, making it easy to prioritize and assign cleanup work.

```sh
todo-scan blame --sort age --min-age 90d
```

### Discover TODO Relationships

🔥 **Problem**

TODOs in large codebases form implicit dependency chains, but existing tools treat each item in isolation.

🌱 **Solution**

`todo-scan relate` discovers relationships between TODO comments using same-file proximity, shared keywords, cross-references (same issue or author), and tag similarity, scoring each pair on a 0–1 scale.

🎁 **Outcome**

Related TODOs surface as actionable clusters, revealing hidden patterns in your technical debt.

```sh
todo-scan relate --cluster
```

### Inline Suppression

🔥 **Problem**

Some TODO comments are intentional or false positives, but the only way to exclude them is file-level patterns in `.todo-scan.toml`, which is too coarse.

🌱 **Solution**

Add `todo-scan:ignore` at the end of a TODO line to suppress that specific item, or place `todo-scan:ignore-next-line` on the line above to suppress the following TODO. Suppressed items are excluded from counts, checks, and output by default. Use `--show-ignored` to reveal them.

🎁 **Outcome**

You get fine-grained, inline control over false positives without maintaining exclusion lists in config files.

```
// TODO: this is tracked normally
// TODO: known false positive todo-scan:ignore
// todo-scan:ignore-next-line
// FIXME: suppressed item
```

### Lint TODO Format

🔥 **Problem**

TODO comments in team codebases drift in format — inconsistent casing, missing colons, missing authors — degrading scanner reliability and code hygiene.

🌱 **Solution**

`todo-scan lint` enforces configurable formatting rules (uppercase tags, colons, author attribution, issue references, message length) and exits with code 1 on violations, making it CI-ready out of the box.

🎁 **Outcome**

Every TODO in your codebase follows consistent formatting, improving both machine parseability and human readability.

```sh
todo-scan lint --require-author TODO,FIXME
```

### Clean Stale & Duplicate TODOs

🔥 **Problem**

TODOs accumulate faster than they resolve, and no amount of listing or linting reduces the pile.

🌱 **Solution**

`todo-scan clean` identifies TODOs referencing closed GitHub issues (stale) and those with identical messages across files (duplicates).

🎁 **Outcome**

You get an actionable cleanup list that targets the lowest-hanging fruit first.

```sh
todo-scan clean --check
```

### CI Quality Gate

🔥 **Problem**

Without enforcement, TODO debt grows silently until it becomes unmanageable.

🌱 **Solution**

`todo-scan check` acts as a CI gate that fails the build when TODO counts exceed a threshold, forbidden tags appear, too many new TODOs are introduced, or deadlines have expired.

🎁 **Outcome**

Your CI pipeline automatically prevents TODO debt from spiraling out of control.

```sh
todo-scan check --max 100 --block-tags BUG
```

### Workspace-Aware Scanning

🔥 **Problem**

Monorepos lack per-package TODO visibility — you can't tell which packages are accumulating debt without manually scanning each one.

🌱 **Solution**

`todo-scan workspace list` auto-detects your workspace format (Cargo, npm, pnpm, Nx, Go workspaces), scans each package independently, and displays a summary table with TODO counts, configured thresholds, and pass/fail status.

🎁 **Outcome**

Every package's TODO health is visible at a glance, making it easy to spot where debt concentrates.

```sh
todo-scan workspace list
```

### Per-Package CI Gate

🔥 **Problem**

A single global `--max` threshold doesn't work for monorepos where packages have different maturity levels.

🌱 **Solution**

`todo-scan check --workspace` evaluates per-package thresholds defined in `[workspace.packages.<name>]` config sections, failing the build if any package exceeds its individual limit or uses forbidden tags.

🎁 **Outcome**

Each package enforces its own TODO budget, matching reality instead of a one-size-fits-all limit.

```sh
todo-scan check --workspace
```

### Single Package Scope

🔥 **Problem**

Sometimes you only need to see TODOs in one package without the noise from the rest of the monorepo.

🌱 **Solution**

The `--package` flag on `list`, `check`, and `diff` scopes the scan to a single workspace package.

🎁 **Outcome**

You get focused results for just the package you're working on.

```sh
todo-scan list --package core
```

### HTML Report Generation

🔥 **Problem**

Presenting TODO metrics to stakeholders requires manual data collection and slide preparation.

🌱 **Solution**

`todo-scan report` generates a self-contained HTML dashboard with summary cards, trend charts from git history, tag/priority/age distribution, author breakdowns, and a sortable items table — zero external dependencies.

🎁 **Outcome**

You get a shareable, presentation-ready report droppable into any CI pipeline as an artifact.

```sh
todo-scan report --output debt.html --history 20
```

### CI Output Formats

🔥 **Problem**

Plain text output requires extra tooling to integrate with CI dashboards and PR workflows.

🌱 **Solution**

todo-scan supports `--format github-actions` for inline PR annotations, `--format sarif` for GitHub's [Code Scanning](https://docs.github.com/en/code-security/code-scanning) tab via SARIF, and `--format markdown` for PR comment bot tables.

🎁 **Outcome**

todo-scan integrates natively with your CI pipeline without any glue scripts.

```sh
todo-scan list --format github-actions
```

### Claude Code Task Export

🔥 **Problem**

Bridging TODO scanning with AI task orchestration requires manually parsing `todo-scan list --format json` output and constructing TaskCreate calls.

🌱 **Solution**

`todo-scan tasks` exports scanned TODOs as Claude Code Task-compatible JSON with action-verb subjects, code context in descriptions, and priority-based ordering.

🎁 **Outcome**

Your TODOs become AI-assignable tasks with a single command.

```sh
todo-scan tasks --dry-run
```

### Real-time File Watching

🔥 **Problem**

Re-running `todo-scan list` after every edit breaks flow when actively cleaning up TODO debt.

🌱 **Solution**

`todo-scan watch` monitors the filesystem and shows real-time TODO additions and removals as files change, with optional `--max` threshold warnings.

🎁 **Outcome**

You see the impact of your cleanup work instantly without switching context.

```sh
todo-scan watch
```

### Interactive Setup

🔥 **Problem**

New users must manually create `.todo-scan.toml` from documentation, slowing onboarding.

🌱 **Solution**

`todo-scan init` walks you through an interactive setup that detects your project type (Rust, Node, Go, Python), suggests appropriate exclude directories, and lets you choose which tags to track.

🎁 **Outcome**

You go from zero to a working configuration in seconds, not minutes of documentation reading.

```sh
todo-scan init
```

### Shell Completions

🔥 **Problem**

Shell completions are table stakes for CLI tools but require manual setup.

🌱 **Solution**

`todo-scan completions` generates completion scripts for bash, zsh, fish, elvish, and PowerShell and outputs them to stdout for easy installation.

🎁 **Outcome**

Tab completion works out of the box for every major shell.

```sh
todo-scan completions fish > ~/.config/fish/completions/todo-scan.fish
```

### What it detects

Tags: `TODO`, `FIXME`, `HACK`, `XXX`, `BUG`, `NOTE` (case-insensitive)

```
// TODO: basic task
// FIXME(alice): broken parsing logic
// BUG: !! crashes on empty input       ← priority: urgent
// TODO: fix layout issue #123          ← issue ref extracted
// HACK(bob): workaround for JIRA-456   ← author + issue ref
// TODO(2025-06-01): migrate to v2 API   ← deadline (YYYY-MM-DD)
// TODO(alice, 2025-Q2): refactor auth   ← author + deadline (quarter)
// TODO: false positive todo-scan:ignore     ← suppressed from output
// todo-scan:ignore-next-line                ← suppresses the line below
// FIXME: suppressed item
```

### Supported comment syntax

The scanner uses line-based heuristic comment detection, not a language parser. The following comment prefixes are recognized:

| Prefix | Languages |
|--------|-----------|
| `//`   | Rust, C/C++, Java, Go, JavaScript, TypeScript, Swift, Kotlin, C# |
| `#`    | Python, Ruby, Shell, YAML, TOML, Perl, R |
| `/* `  | C/C++, Java, JavaScript, CSS (block comment start) |
| ` * `  | Block comment continuation lines |
| `--`   | SQL, Haskell, Lua, Ada |
| `<!--` | HTML, XML, Markdown |
| `;`    | Lisp, Clojure, Assembly, INI |
| `(*`   | OCaml, Pascal, F# |
| `{-`   | Haskell (block) |
| `%`    | LaTeX, Erlang, MATLAB |

> **Note:** Detection is line-based. Multi-line constructs (Python docstrings, heredocs) are not supported. Tags must appear as standalone words — `todo-scan` and `TODOS` will not match `TODO`.

### Supported workspace formats

todo-scan auto-detects monorepo/workspace layouts by checking for these manifest files in order:

| Format | Manifest File | Member Field |
|--------|--------------|--------------|
| Cargo  | `Cargo.toml` | `[workspace] members` |
| npm    | `package.json` | `"workspaces"` array |
| pnpm   | `pnpm-workspace.yaml` | `packages` list |
| Nx     | `workspace.json` | `"projects"` map |
| Go     | `go.work` | `use` directives |

Glob patterns in member lists (e.g., `packages/*`, `crates/*`) are expanded automatically. You can also define packages manually in `.todo-scan.toml` with `[workspace]` configuration.

## Installation

### Prebuilt binaries (macOS / Linux)

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/sotayamashita/todo-scan/releases/latest/download/todo-scan-installer.sh | sh
```

### Prebuilt binaries (Windows)

```powershell
powershell -ExecutionPolicy ByPass -c "irm https://github.com/sotayamashita/todo-scan/releases/latest/download/todo-scan-installer.ps1 | iex"
```

### From source

```bash
cargo install todo-scan
```

## Usage

### List TODOs

```bash
# List all TODOs in current directory
todo-scan list

# Short alias
todo-scan ls

# Filter by tag
todo-scan list --tag FIXME
todo-scan list --tag TODO --tag BUG

# Filter by priority, author, or path
todo-scan list --priority urgent
todo-scan list --author alice
todo-scan list --path "src/**"

# Combine filters
todo-scan list --priority urgent --author alice --path "src/**"

# Limit results
todo-scan list --limit 10

# Group by tag, priority, author, or directory (default: file)
todo-scan list --group-by tag
todo-scan list --group-by priority
todo-scan list --group-by author
todo-scan list --group-by dir

# Sort by priority or tag severity
todo-scan list --sort priority
todo-scan list --sort tag

# JSON output
todo-scan list --format json
```

### Search TODOs

```bash
# Search by message text (case-insensitive)
todo-scan search "migration"

# Short alias
todo-scan s "migration"

# Case-sensitive exact match
todo-scan search "TODO" --exact

# Search by issue reference
todo-scan search "#123"

# Combine with filters
todo-scan search "fix" --author alice --tag FIXME --path "src/**"

# Show context lines around matches
todo-scan search "bug" -C 3

# JSON output with query metadata
todo-scan search "fix" --format json
```

### Show context around TODOs

```bash
# Show code context around a specific line (default: 5 lines)
todo-scan context src/main.rs:25

# Custom context window
todo-scan context src/main.rs:25 -C 3

# JSON output with related TODOs
todo-scan context src/main.rs:25 --format json

# Add context lines to list output
todo-scan list -C 3
todo-scan list -C 2 --format json

# Add context lines to diff output
todo-scan diff main -C 2
```

### Diff against a git ref

```bash
# Compare against main branch
todo-scan diff main

# Compare against recent commits
todo-scan diff HEAD~3

# Filter diff by tag
todo-scan diff main --tag FIXME

# JSON output
todo-scan diff main --format json
```

### Blame — TODO age and ownership

```bash
# Show all TODOs with git blame metadata
todo-scan blame

# Sort by age (oldest first)
todo-scan blame --sort age

# Filter by author (substring match)
todo-scan blame --author alice

# Filter by minimum age
todo-scan blame --min-age 90d

# Set stale threshold (default: 365 days)
todo-scan blame --stale-threshold 180d

# Filter by tag or path
todo-scan blame --tag TODO
todo-scan blame --path "src/**"

# JSON output
todo-scan blame --format json
```

### Stats dashboard

```bash
# Show tag/priority/author/hotspot summary
todo-scan stats

# Show trend compared to a git ref
todo-scan stats --since main

# JSON output
todo-scan stats --format json
```

### Brief summary

```bash
# Compressed summary (2-4 lines)
todo-scan brief

# With trend info compared to a git ref
todo-scan brief --since main

# Limit output to N lines
todo-scan brief --budget 1

# JSON output
todo-scan brief --format json
```

### Lint TODO formatting

```bash
# Check formatting with sensible defaults (uppercase, colon, no bare tags)
todo-scan lint

# Require author for specific tags
todo-scan lint --require-author TODO,FIXME

# Require issue reference for BUG tags
todo-scan lint --require-issue-ref BUG

# Enforce max message length
todo-scan lint --max-message-length 120

# Combine rules
todo-scan lint --require-author TODO --require-issue-ref BUG --max-message-length 120

# JSON output
todo-scan lint --format json
```

Exit codes: `0` = pass, `1` = fail, `2` = error.

### Clean — stale issues and duplicates

```bash
# Dry-run: show stale and duplicate TODOs (always exit 0)
todo-scan clean

# CI gate: exit 1 if any violations found
todo-scan clean --check

# Only flag issues closed more than 30 days ago
todo-scan clean --since 30d

# JSON output
todo-scan clean --format json
```

Exit codes (with `--check`): `0` = pass, `1` = fail, `2` = error. Without `--check`, always exits `0`.

### HTML report

```bash
# Generate report with default settings (todo-scan-report.html)
todo-scan report

# Custom output path
todo-scan report --output debt-report.html

# Sample more commits for trend chart
todo-scan report --history 20

# Skip history analysis (faster)
todo-scan report --history 0

# Set stale threshold
todo-scan report --stale-threshold 180d
```

### CI gate

```bash
# Fail if total TODOs exceed 100
todo-scan check --max 100

# Fail if any FIXME or BUG tags exist
todo-scan check --block-tags FIXME,BUG

# Fail if new TODOs were added since main
todo-scan check --max-new 0 --since main

# Fail if any TODOs have expired deadlines
todo-scan check --expired

# Combine rules
todo-scan check --max 50 --block-tags BUG --max-new 0 --since main --expired
```

Exit codes: `0` = pass, `1` = fail, `2` = error.

### Workspace — monorepo support

```bash
# List all packages with TODO counts
todo-scan workspace list

# Short aliases
todo-scan ws ls

# JSON output
todo-scan workspace list --format json

# Scope any command to a single package
todo-scan list --package core
todo-scan check --max 50 --package cli
todo-scan diff main --package core

# Per-package CI gate (uses [workspace.packages.*] config)
todo-scan check --workspace
```

### Relate — TODO relationships and clusters

```bash
# Discover all relationships (text output)
todo-scan relate

# JSON output
todo-scan relate --format json

# Group related TODOs into clusters
todo-scan relate --cluster

# Show TODOs related to a specific item
todo-scan relate --for src/auth.rs:42

# Set minimum relationship score (default: 0.3)
todo-scan relate --min-score 0.5

# Adjust proximity threshold (default: 10 lines)
todo-scan relate --proximity 20

# Combine options
todo-scan relate --cluster --min-score 0.4 --format json
```

### Export as Claude Code Tasks

```bash
# Preview tasks as JSON to stdout
todo-scan tasks --dry-run

# Write individual task files to a directory
todo-scan tasks --output ~/.claude/tasks/my-sprint/

# Filter by tag, priority, author, or path
todo-scan tasks --dry-run --tag BUG --priority urgent
todo-scan tasks --dry-run --author alice --path "src/**"

# Only TODOs added since a git ref
todo-scan tasks --dry-run --since main

# Control context lines in task descriptions (default: 3)
todo-scan tasks --dry-run -C 5

# JSON output
todo-scan tasks --dry-run --format json
```

### Global flags

| Flag | Description |
|---|---|
| `--root <path>` | Set the project root directory (default: current directory) |
| `--format <format>` | Output format: `text`, `json`, `github-actions`, `sarif`, `markdown` (default: text) |
| `--config <path>` | Path to config file (default: auto-discover `.todo-scan.toml`) |
| `--show-ignored` | Show items suppressed by `todo-scan:ignore` markers |

### Output formats

```bash
# GitHub Actions annotations — inline warnings/errors in PR diffs
todo-scan list --format github-actions
todo-scan check --max 100 --format github-actions

# SARIF — upload to GitHub Code Scanning / Security tab
todo-scan list --format sarif > results.sarif

# Markdown — tables for PR comment bots
todo-scan diff main --format markdown
```

### Quick start

```bash
# Interactive setup — generates .todo-scan.toml
todo-scan init

# Non-interactive with defaults
todo-scan init --yes
```

### Shell completions

```bash
# Bash
todo-scan completions bash > ~/.local/share/bash-completion/completions/todo-scan

# Zsh
todo-scan completions zsh > ~/.zfunc/_todo-scan

# Fish
todo-scan completions fish > ~/.config/fish/completions/todo-scan.fish
```

## Configuration

Create a `.todo-scan.toml` in your project root (or run `todo-scan init`). The file is discovered by searching upward from the current directory.

```toml
# Tags to scan for (default: all supported tags)
tags = ["TODO", "FIXME", "HACK", "XXX", "BUG", "NOTE"]

# Directories to exclude from scanning
exclude_dirs = ["vendor", "third_party"]

# Regex patterns to exclude files
exclude_patterns = [".*\\.min\\.js$", ".*generated.*"]

[check]
# Maximum total TODOs allowed
max = 100

# Maximum new TODOs allowed (requires --since)
max_new = 0

# Tags that cause check to fail immediately
block_tags = ["BUG"]

# Fail if any TODOs have expired deadlines
expired = true

[blame]
# Days threshold for marking TODOs as stale (default: 365d)
stale_threshold = "180d"

[clean]
# Enable stale issue detection (default: true)
stale_issues = true

# Enable duplicate detection (default: true)
duplicates = true

# Only flag issues closed longer than this duration (default: disabled)
# since = "30d"

[workspace]
# Disable automatic workspace detection (default: true)
# auto_detect = false

# Per-package check thresholds
[workspace.packages.core]
max = 50
block_tags = ["BUG"]

[workspace.packages.cli]
max = 20

[lint]
# Reject TODOs with empty message (default: true)
no_bare_tags = true

# Enforce uppercase tag names (default: true)
uppercase_tag = true

# Enforce colon after tag (default: true)
require_colon = true

# Enforce max message character count (default: disabled)
# max_message_length = 120

# Require (author) for specified tags (default: disabled)
# require_author = ["TODO", "FIXME"]

# Require issue ref for specified tags (default: disabled)
# require_issue_ref = ["BUG"]
```

All fields are optional. Unspecified values use sensible defaults.

A machine-readable JSON Schema is available at [`schema/todo-scan.schema.json`](schema/todo-scan.schema.json) for editor validation and autocompletion (e.g., [Taplo](https://taplo.tamasfe.dev/), [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml)).

### Configuration Reference

#### Top-level fields

| Field | Type | Default | Description |
|---|---|---|---|
| `tags` | `string[]` | `["TODO","FIXME","HACK","XXX","BUG","NOTE"]` | Tag keywords to scan for |
| `exclude_dirs` | `string[]` | `[]` | Directory names to skip during scanning |
| `exclude_patterns` | `string[]` | `[]` | Regex patterns; matching file paths are excluded |

#### `[check]` section

| Field | Type | Default | Description |
|---|---|---|---|
| `max` | `integer` | _(none)_ | Maximum total TODOs allowed |
| `max_new` | `integer` | _(none)_ | Maximum new TODOs allowed (requires `--since`) |
| `block_tags` | `string[]` | `[]` | Tags that cause `check` to fail immediately |
| `expired` | `boolean` | _(none)_ | Fail if any TODOs have expired deadlines |

#### `[blame]` section

| Field | Type | Default | Description |
|---|---|---|---|
| `stale_threshold` | `string` | `"365d"` | Duration threshold for marking TODOs as stale |

#### `[clean]` section

| Field | Type | Default | Description |
|---|---|---|---|
| `stale_issues` | `boolean` | `true` | Enable stale issue detection via `gh` CLI |
| `duplicates` | `boolean` | `true` | Enable duplicate TODO detection |
| `since` | `string` | _(none)_ | Only flag issues closed longer than this duration (e.g., `"30d"`) |

#### `[lint]` section

| Field | Type | Default | Description |
|---|---|---|---|
| `no_bare_tags` | `boolean` | `true` | Reject TODOs with empty message |
| `uppercase_tag` | `boolean` | `true` | Enforce uppercase tag names |
| `require_colon` | `boolean` | `true` | Enforce colon after tag |
| `max_message_length` | `integer` | _(none)_ | Enforce max message character count |
| `require_author` | `string[]` | _(none)_ | Require `(author)` for specified tags |
| `require_issue_ref` | `string[]` | _(none)_ | Require issue ref for specified tags |

#### `[workspace]` section

| Field | Type | Default | Description |
|---|---|---|---|
| `auto_detect` | `boolean` | `true` | Enable automatic workspace detection |

#### `[workspace.packages.<name>]` section

Per-package check thresholds for `todo-scan check --workspace`.

| Field | Type | Default | Description |
|---|---|---|---|
| `max` | `integer` | _(none)_ | Maximum TODOs allowed for this package |
| `block_tags` | `string[]` | `[]` | Tags that cause check to fail for this package |

## Agent Skill

todo-scan provides a [Claude Code plugin](https://docs.anthropic.com/en/docs/claude-code/skills) that enables AI coding agents to automatically use todo-scan commands for TODO tracking, CI gate configuration, and code quality checks.

### Install from plugin marketplace (recommended)

```bash
/plugin marketplace add sotayamashita/todo-scan
```

### Install with [skills CLI]https://github.com/vercel-labs/skills

```bash
npx skills add sotayamashita/todo-scan
```

### Manual install

```bash
cp -r skills/todo-scan ~/.claude/skills/
```

## CI Integration

### GitHub Action

The easiest way to add todo-scan to your CI pipeline. No binary installation or workflow boilerplate needed.

**Minimal usage:**

```yaml
- uses: sotayamashita/todo-scan@v1
  with:
    max: '100'
```

**Full example with SARIF and diff:**

```yaml
- uses: actions/checkout@v6
  with:
    fetch-depth: 0  # Required for base-ref diff

- uses: sotayamashita/todo-scan@v1
  with:
    max: '100'
    block-tags: 'BUG,FIXME'
    max-new: '0'
    base-ref: 'origin/main'
    sarif: 'true'
```

#### Inputs

| Input | Default | Description |
|-------|---------|-------------|
| `version` | `latest` | todo-scan version to install (e.g. `0.1.0`) |
| `max` | | Maximum total TODOs allowed |
| `block-tags` | | Comma-separated tags that cause check to fail |
| `max-new` | | Maximum new TODOs allowed (requires `base-ref`) |
| `base-ref` | | Git ref to diff against (requires `fetch-depth: 0`) |
| `expired` | `false` | Fail if any TODOs have expired deadlines |
| `sarif` | `false` | Generate and upload SARIF to GitHub Code Scanning |
| `root` | | Project root directory |
| `config` | | Path to `.todo-scan.toml` config file |
| `token` | `github.token` | GitHub token for SARIF upload |

#### Outputs

| Output | Description |
|--------|-------------|
| `total-count` | Total number of TODOs found |
| `passed` | Whether the check passed (`true`/`false`) |
| `sarif-file` | Path to generated SARIF file (if `sarif: true`) |

### GitHub Actions (manual setup)

```yaml
- name: Check TODOs
  run: |
    todo-scan check --max 100 --block-tags BUG,FIXME
```

### GitHub Actions with inline annotations

```yaml
- name: Check TODOs with annotations
  run: |
    todo-scan check --max 100 --format github-actions
```

### SARIF upload to Code Scanning

```yaml
- name: Scan TODOs
  run: todo-scan list --format sarif > todo-scan.sarif

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: todo-scan.sarif
```

### HTML report artifact

```yaml
- name: Generate TODO report
  run: todo-scan report --output todo-scan-report.html

- name: Upload TODO report
  uses: actions/upload-artifact@v4
  with:
    name: todo-scan-report
    path: todo-scan-report.html
```

### PR review with diff

> **Note:** `todo-scan diff` and `todo-scan check --since` need access to the base ref's git history.
> `actions/checkout@v4` uses `fetch-depth: 1` (shallow clone) by default, which means the base
> SHA is not available. Set `fetch-depth: 0` to fetch the full history.

```yaml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # Required for todo-scan to access the base ref

- name: Check new TODOs
  run: |
    todo-scan check --max-new 0 --since origin/main
```

## Release Workflow

Releases are fully automated via [release-please](https://github.com/googleapis/release-please) and [cargo-dist](https://github.com/axodotdev/cargo-dist).

### How to release

1. Merge PRs with [Conventional Commits](https://www.conventionalcommits.org/) into `main`
2. release-please automatically opens (or updates) a Release PR that bumps the version and updates the changelog
3. Merge the Release PR — this creates a git tag and GitHub Release
4. cargo-dist builds platform binaries and uploads them to the GitHub Release

```mermaid
sequenceDiagram
    participant M as main branch
    participant RP as release-please
    participant CD as cargo-dist
    participant GH as GitHub Release

    M->>RP: push with conventional commits
    RP->>M: open/update Release PR (bump version + changelog)
    M->>RP: merge Release PR
    RP->>GH: create git tag + draft release
    GH->>CD: tag push triggers release workflow
    CD->>GH: upload binaries, installers, checksums
```

### Commit conventions

| Prefix | Version bump | Example |
|--------|-------------|---------|
| `fix:` | patch (0.0.x) | `fix(scanner): handle empty files` |
| `feat:` | minor (0.x.0) | `feat(cli): add --verbose flag` |
| `feat!:` or `BREAKING CHANGE:` | major (x.0.0) | `feat!: remove deprecated --count flag` |

### Supported targets

| Target | OS | Arch |
|--------|----|------|
| `aarch64-apple-darwin` | macOS | Apple Silicon |
| `x86_64-apple-darwin` | macOS | Intel |
| `x86_64-unknown-linux-gnu` | Linux | x86_64 |
| `x86_64-pc-windows-msvc` | Windows | x86_64 |

### Release artifacts

Each release includes:

- Platform-specific binary archives (`.tar.xz` / `.zip`)
- Shell installer (`todo-scan-installer.sh`) for macOS and Linux
- PowerShell installer (`todo-scan-installer.ps1`) for Windows
- Checksums for verification

## Development

```bash
# Build
cargo build

# Run tests
cargo test

# Run against a project
cargo run -- list --root /path/to/project
```