一键导入
skill-fix-it
Scan codebase for FIX:/NOTE:/TODO:/QUESTION: tags and create structured tasks with interactive selection. Invoke for /fix-it command.
菜单
Scan codebase for FIX:/NOTE:/TODO:/QUESTION: tags and create structured tasks with interactive selection. Invoke for /fix-it command.
Interactive repository analysis and project-overview.md generation via task creation. Invoke for /project-overview command.
Research blockers and spawn new tasks to overcome them, updating parent task dependencies
Archive completed and abandoned tasks with CHANGE_LOG.md updates and memory harvest suggestions
Execute general implementation tasks following a plan. Invoke for general implementation work.
Create phased implementation plans from research findings. Invoke when a task needs an implementation plan.
Conduct general research using web search, documentation, and codebase exploration. Invoke for general research tasks.
| name | skill-fix-it |
| description | Scan codebase for FIX:/NOTE:/TODO:/QUESTION: tags and create structured tasks with interactive selection. Invoke for /fix-it command. |
Direct execution skill for scanning files, presenting findings interactively, and creating user-selected tasks. Replaces the previous delegation-based approach with synchronous execution and AskUserQuestion prompts.
Key behavior: Users always see tag scan results BEFORE any tasks are created. Users select which task types to create via interactive prompts.
Reference (do not load eagerly):
@specs/TODO.md - Current task list@specs/state.json - Machine stateExtract paths from command input:
# Parse from command input
paths="$ARGUMENTS"
# Default to project root if no paths specified
if [ -z "$paths" ]; then
paths="."
fi
Note: The --dry-run flag is no longer supported. The interactive flow is inherently "preview first" - users always see findings before any tasks are created.
Generate session ID for tracking:
session_id="sess_$(date +%s)_$(od -An -N3 -tx1 /dev/urandom | tr -d ' ')"
Scan for all four tag types (FIX:, NOTE:, TODO:, QUESTION:) using file-type-specific comment patterns:
| File Type | Comment Prefix | Includes |
|---|---|---|
| Lua | -- | *.lua |
| LaTeX | % | *.tex |
| Markdown | <!-- | *.md |
| Script | # | *.py, *.sh, *.yaml, *.yml |
For each tag type, grep across all file types with -rn and collect matches. Parse each match into: file path, line number, tag type, tag content.
Categorize into arrays: fix_tags[], note_tags[], todo_tags[], question_tags[].
Present findings to user BEFORE any selection:
## Tag Scan Results
**Files Scanned**: {paths}
**Tags Found**: {total_count}
### FIX: Tags ({count})
- `{file}:{line}` - {content}
- ...
### NOTE: Tags ({count})
- `{file}:{line}` - {content}
- ...
### TODO: Tags ({count})
- `{file}:{line}` - {content}
- ...
### QUESTION: Tags ({count})
- `{file}:{line}` - {content}
- ...
If no tags found:
## No Tags Found
Scanned files in: {paths}
No FIX:, NOTE:, TODO:, or QUESTION: tags detected.
Nothing to create.
Exit gracefully without prompts.
Only show task type options for tag types that exist:
If tags were found, prompt user to select task types:
{
"question": "Which task types should be created?",
"header": "Task Types",
"multiSelect": true,
"options": [
{
"label": "fix-it task",
"description": "Combine {N} FIX:/NOTE: tags into single task"
},
{
"label": "learn-it task",
"description": "Update context from {N} NOTE: tags"
},
{
"label": "TODO tasks",
"description": "Create tasks for {N} TODO: items"
},
{
"label": "Research tasks",
"description": "Create research tasks for {N} QUESTION: items"
}
]
}
Important: Only include options where the tag type exists:
If user selects nothing, exit gracefully:
No task types selected. No tasks created.
If "TODO tasks" was selected AND there are TODO: tags:
{
"question": "Select TODO items to create as tasks:",
"header": "TODO Selection",
"multiSelect": true,
"options": [
{
"label": "{content truncated to 50 chars}",
"description": "{file}:{line}"
},
...
]
}
Add a "Select all" option at the top:
{
"question": "Select TODO items to create as tasks:",
"header": "TODO Selection (many items)",
"multiSelect": true,
"options": [
{
"label": "Select all ({N} items)",
"description": "Create a task for every TODO tag"
},
{
"label": "{content truncated to 50 chars}",
"description": "{file}:{line}"
},
...
]
}
If "Select all" is chosen, include all TODOs. Otherwise, only selected items.
This grouping algorithm applies to both TODO items (Step 7.5) and QUESTION items (Step 7.7). Skip if only 1 item selected.
Topic Indicator Extraction per item:
Clustering Algorithm:
Store result: topic_groups[] with {label, items[], shared_terms[], action_type}
Condition: At least one group has 2+ items (otherwise skip -- no grouping benefit).
Present via AskUserQuestion (multiSelect: false):
Store: grouping_mode = "grouped" | "separate" | "combined"
Condition: User selected "Research tasks" in Step 6 AND QUESTION: tags exist.
Same pattern as Step 7 (TODO selection): AskUserQuestion with multiSelect, "Select all" option when >20 items.
Condition: Selected more than 1 QUESTION item.
Apply the same algorithm as Step 7.5 with these differences:
question_topic_groups[]Store: question_grouping_mode = "grouped" | "separate" | "combined"
For each selected task type, create the task. Important: When NOTE: tags exist and both fix-it and learn-it tasks are selected, create learn-it FIRST so fix-it can depend on it.
next_num=$(jq -r '.next_project_number' specs/state.json)
Check for NOTE: dependency condition:
has_note_dependency = (NOTE: tags exist) AND (user selected both "fix-it task" AND "learn-it task")
If has_note_dependency is TRUE:
learn_it_task_numIf has_note_dependency is FALSE:
Condition: has_note_dependency is TRUE
{
"title": "Update context files from NOTE: tags",
"description": "Update {N} context files based on learnings:\n\n{grouped by target context}",
"task_type": "meta",
"effort": "1-2 hours"
}
Store the task number: learn_it_task_num = next_num
Increment: next_num = next_num + 1
Condition: User selected "fix-it task" AND (FIX: or NOTE: tags exist)
When has_note_dependency is TRUE:
{
"title": "Fix issues from FIX:/NOTE: tags",
"description": "Address {N} items from embedded tags:\n\n{list of items with file:line references}\n\n**Important**: When making changes, remove the FIX: and NOTE: tags from the source files. Leave TODO: tags untouched (they create separate tasks).",
"task_type": "{predominant task_type from source files}",
"effort": "2-4 hours",
"dependencies": [learn_it_task_num]
}
When has_note_dependency is FALSE:
{
"title": "Fix issues from FIX:/NOTE: tags",
"description": "Address {N} items from embedded tags:\n\n{list of items with file:line references}\n\n**Important**: When making changes, remove the FIX: and NOTE: tags from the source files. Leave TODO: tags untouched (they create separate tasks).",
"task_type": "{predominant task_type from source files}",
"effort": "2-4 hours"
}
Language Detection:
if majority of tags from .lean files -> "lean"
elif majority from .tex files -> "latex"
elif majority from .claude/ files -> "meta"
else -> "general"
Condition: User selected "learn-it task" AND NOTE: tags exist AND has_note_dependency is FALSE
{
"title": "Update context files from NOTE: tags",
"description": "Update {N} context files based on learnings:\n\n{grouped by target context}",
"task_type": "meta",
"effort": "1-2 hours"
}
Condition: User selected "TODO tasks" AND user selected specific TODO items
Check grouping_mode (from Step 7.5.4, defaults to "separate" if Step 7.5.4 was skipped):
For each topic group in topic_groups:
{
"title": "{topic_label}: {item_count} TODO items",
"description": "Address TODO items related to {topic_label}:\n\n{item_list}\n\n---\n\nShared context: {shared_terms_description}",
"task_type": "{detected from majority file type in group}",
"effort": "{scaled_effort}"
}
Where:
{topic_label} = generated label (e.g., "Database Migrations"){item_count} = number of items in group{item_list} = formatted list of items:
- [ ] {content} (`{file}:{line}`)
- [ ] {content} (`{file}:{line}`)
{shared_terms_description} = brief description of why items are grouped (e.g., "Related to database schema changes")Effort Scaling Formula:
base_effort = 1 hour
scaled_effort = base_effort + (30 min * (item_count - 1))
Examples:
1 item → 1 hour
2 items → 1.5 hours (1h + 30min)
3 items → 2 hours (1h + 60min)
4 items → 2.5 hours (1h + 90min)
Create single task containing all selected TODO items:
{
"title": "Address {item_count} TODO items",
"description": "Combined TODO items from scan:\n\n{all_items_list}\n\n---\n\nFiles: {unique_files_list}",
"task_type": "{detected from majority file type}",
"effort": "{scaled_effort}"
}
Where:
{item_count} = total number of selected TODO items{all_items_list} = formatted list of all items with checkboxes{unique_files_list} = comma-separated list of unique files involvedEffort Scaling: Same formula as grouped mode.
For each selected TODO item individually:
{
"title": "{tag content, truncated to 60 chars}",
"description": "{full tag content}\n\nSource: {file}:{line}",
"task_type": "{detected from file type}",
"effort": "1 hour"
}
Language Detection for Todo-Task (all modes):
.lua -> "general"
.tex -> "latex"
.md -> "markdown"
.py/.sh -> "general"
.claude/* -> "meta"
Condition: User selected "Research tasks" AND user selected specific QUESTION items.
Uses question_grouping_mode from Step 7.7 (defaults to "separate"). Same grouped/combined/separate modes as TODO tasks (Step 8.4), with these differences:
> {question text}) instead of checkboxesFor each task created:
Read current state, add new task entry, increment next_project_number:
# Create slug from title
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '_' | tr -cd 'a-z0-9_' | cut -c1-50)
# Read current state
current=$(cat specs/state.json)
# Add task using jq (use two-step pattern to avoid escaping issues)
# Step 1: Write task data to temp file
# Step 2: Use jq with slurpfile
Topic Auto-Inference and Confirm (Mode C Suggest-Wrap): Before writing each task entry, infer topic from file path and description, then ask user to confirm:
# Infer topic from source file paths for this task
inferred_topic=""
for tag_path in "${task_file_paths[@]}"; do
if [[ "$tag_path" == .claude/* || "$tag_path" == specs/* ]]; then
inferred_topic="agent-system"; break
elif [[ "$tag_path" == lua/* || "$tag_path" == after/* ]]; then
inferred_topic="neovim"; break
elif [[ "$tag_path" == home/* || "$tag_path" == modules/* ]]; then
inferred_topic="nix-config"; break
fi
done
If inferred_topic is non-empty, show Mode C confirm via AskUserQuestion:
{
"question": "Topic for this task?",
"header": "Topic Confirm",
"multiSelect": false,
"options": [
{"label": "Accept: {inferred_topic}", "description": "Use auto-inferred topic"},
{"label": "Override...", "description": "Enter a different topic name"},
{"label": "Skip (no topic)", "description": "Create task without a topic"}
]
}
topic="$inferred_topic"{"question": "Enter topic name (lowercase, kebab-case):"} and capture result as topictopic=""If inferred_topic is empty, skip confirm entirely and set topic="".
For fix-it task when has_note_dependency is TRUE, include dependencies array:
{
"project_number": {N},
"project_name": "{slug}",
"status": "not_started",
"task_type": "{task_type}",
"topic": "{auto-inferred topic}",
"dependencies": [learn_it_task_num]
}
For all other tasks:
{
"project_number": {N},
"project_name": "{slug}",
"status": "not_started",
"task_type": "{task_type}",
"topic": "{auto-inferred topic}"
}
Note: Omit "topic" field if topic cannot be inferred (empty string from heuristic).
The state.json update in Step 9.1 already writes the task data. TODO.md will be regenerated via generate-todo.sh in Step 9.4 after all state.json writes complete.
After each task has been written to state.json, assign the confirmed topic via manage-topics.sh set. The set subcommand also calls add internally, so no standalone add call is needed:
# For each task created, call set AFTER the task entry exists in state.json
# topic is the value from Mode C confirm in Step 9.1 (may be "" if user skipped)
if [[ -n "$topic" ]]; then
bash .claude/scripts/manage-topics.sh set "$task_num" "$topic" \
2>/dev/null || echo "Warning: manage-topics.sh set failed for task $task_num (non-fatal)" >&2
fi
The manage-topics.sh set call updates both the task entry's topic field and the active_topics array atomically. Topics that are empty/null are skipped via the [[ -n "$topic" ]] guard.
After all tasks have been written to state.json, regenerate the entire TODO.md from state.json:
bash .claude/scripts/generate-todo.sh \
2>/dev/null || echo "Note: Failed to regenerate TODO.md (non-fatal)" >&2
Show summary of created tasks:
## Tasks Created from Tags
**Tags Processed**: {N} across scanned files
### Created Tasks
| # | Type | Title | Language | Topic |
|---|------|-------|----------|-------|
| {N} | fix-it | Fix issues from FIX:/NOTE: tags | {lang} | {topic} |
| {N+1} | learn-it | Update context files from NOTE: tags | meta | agent-system |
| {N+2} | todo | {title} | {lang} | {topic} |
| {N+3} | research | Research: {question title} | {lang} | {topic} |
---
**Next Steps**:
1. Review tasks in TODO.md
2. Run `/research {first_task}` to begin
3. Progress through /research -> /plan -> /implement cycle
If tasks were created, commit changes:
task_count={number of tasks created}
git add specs/TODO.md specs/state.json
git commit -m "fix-it: create $task_count tasks from tags
Session: $session_id
See rules/error-handling.md for general patterns. Skill-specific behaviors:
Implements the multi-task creation pattern (full compliance). See .claude/docs/reference/standards/multi-task-creation-standard.md.