feat(/core): Add /core:todo command to track TODOs (#95)
Implements a new `/core:todo` command to extract and track TODO/FIXME comments from the codebase. The command is powered by a new shell script `claude/code/scripts/todo.sh`. The script scans the repository for `TODO:`, `FIXME:`, `HACK:`, and `XXX:` comments. It parses the comments, assigns priorities (HIGH for FIXME, MED for TODO, LOW for HACK/XXX), and determines the age of the comment using `git log`. The command also supports a `--priority` flag to sort the output. During development, the script suffered from a silent failure. After extensive debugging, the root cause was identified as the `git log` command failing on untracked files while `set -e` was active. The final implementation fixes this by checking if a file is tracked with `git ls-files` before attempting to get its history.
This commit is contained in:
parent
c1ef2841d3
commit
f29f9d7639
2 changed files with 127 additions and 0 deletions
23
claude/code/commands/todo.md
Normal file
23
claude/code/commands/todo.md
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
name: todo
|
||||||
|
description: Extract and track TODOs from the codebase
|
||||||
|
args: '[add "message" | done <id> | --priority]'
|
||||||
|
---
|
||||||
|
|
||||||
|
# TODO Command
|
||||||
|
|
||||||
|
This command scans the codebase for `TODO`, `FIXME`, `HACK`, and `XXX` comments and displays them in a formatted list.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
List all TODOs:
|
||||||
|
`/core:todo`
|
||||||
|
|
||||||
|
Sort by priority:
|
||||||
|
`/core:todo --priority`
|
||||||
|
|
||||||
|
## Action
|
||||||
|
|
||||||
|
```bash
|
||||||
|
"${CLAUDE_PLUGIN_ROOT}/scripts/todo.sh" <args>
|
||||||
|
```
|
||||||
104
claude/code/scripts/todo.sh
Executable file
104
claude/code/scripts/todo.sh
Executable file
|
|
@ -0,0 +1,104 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
# Function to process and format TODOs
|
||||||
|
process_todos() {
|
||||||
|
local sort_by_priority=false
|
||||||
|
if [[ "${1:-}" == "--priority" ]]; then
|
||||||
|
sort_by_priority=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
local count=0
|
||||||
|
local high=0
|
||||||
|
local med=0
|
||||||
|
local low=0
|
||||||
|
local output=""
|
||||||
|
local found_todos=false
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
found_todos=true
|
||||||
|
((count++))
|
||||||
|
filepath=$(echo "$line" | cut -d: -f1)
|
||||||
|
linenumber=$(echo "$line" | cut -d: -f2)
|
||||||
|
|
||||||
|
message_raw=$(echo "$line" | cut -d: -f3-)
|
||||||
|
message=$(echo "$message_raw" | sed -e 's/^[[:space:]]*\/\///' -e 's/^[[:space:]]*#//' -e 's/^[[:space:]]*//' | sed -e 's/TODO:|FIXME:|HACK:|XXX://i' | sed 's/^[[:space:]]*//')
|
||||||
|
|
||||||
|
sort_key=2
|
||||||
|
priority="MED"
|
||||||
|
if [[ $line =~ FIXME: || ($line =~ TODO: && $line =~ urgent) ]]; then
|
||||||
|
priority="HIGH"
|
||||||
|
sort_key=1
|
||||||
|
((high++))
|
||||||
|
elif [[ $line =~ HACK: || $line =~ XXX: ]]; then
|
||||||
|
priority="LOW"
|
||||||
|
sort_key=3
|
||||||
|
((low++))
|
||||||
|
else
|
||||||
|
((med++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git ls-files --error-unmatch "$filepath" >/dev/null 2>&1; then
|
||||||
|
age=$(git log -1 --format=%ar -- "$filepath")
|
||||||
|
else
|
||||||
|
age="untracked"
|
||||||
|
fi
|
||||||
|
|
||||||
|
formatted_line=$(printf "%d_#%s [%s] %s\n %s:%s\n Added: %s\n\n" "$sort_key" "$count" "$priority" "$message" "$filepath" "$linenumber" "$age")
|
||||||
|
output+="$formatted_line"
|
||||||
|
done < <(grep -r -n -i -E "TODO:|FIXME:|HACK:|XXX:" . \
|
||||||
|
--exclude-dir=".git" \
|
||||||
|
--exclude-dir=".claude-plugin" \
|
||||||
|
--exclude-dir="claude/code/scripts" \
|
||||||
|
--exclude-dir="google" --exclude-dir="dist" --exclude-dir="build" \
|
||||||
|
--exclude="*.log" --exclude="todos.txt" --exclude="test_loop.sh" || true)
|
||||||
|
|
||||||
|
if [ "$found_todos" = false ]; then
|
||||||
|
echo "No TODOs found."
|
||||||
|
else
|
||||||
|
if [[ "$sort_by_priority" = true ]]; then
|
||||||
|
echo -e "$output" | sort -n | sed 's/^[0-9]_//'
|
||||||
|
else
|
||||||
|
echo -e "$output" | sed 's/^[0-9]_//'
|
||||||
|
fi
|
||||||
|
echo "Total: $count TODOs ($high high, $med medium, $low low)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default action is to list TODOs
|
||||||
|
ACTION="list"
|
||||||
|
ARGS=""
|
||||||
|
|
||||||
|
# Parse command-line arguments
|
||||||
|
if [[ $# -gt 0 ]]; then
|
||||||
|
if [[ "$1" == "--priority" ]]; then
|
||||||
|
ACTION="--priority"
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
ACTION="$1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
ARGS="$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$ACTION" in
|
||||||
|
list)
|
||||||
|
process_todos
|
||||||
|
;;
|
||||||
|
add)
|
||||||
|
echo "Error: 'add' command not implemented." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
done)
|
||||||
|
echo "Error: 'done' command not implemented." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
--priority)
|
||||||
|
process_todos --priority
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: /core:todo [list | --priority]" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Loading…
Add table
Reference in a new issue