Skip to content
This repository was archived by the owner on Jan 11, 2026. It is now read-only.

Commit bac950b

Browse files
rmurpheyclaude
andcommitted
feat: migrate from ACTIVE_WORK.md to GitHub Issues
- Create todo-github.js script for GitHub issue management - Update /todo command to use GitHub Issues API - Add npm scripts for issue operations (list, add, done, comment, stats) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 42fe0c1 commit bac950b

File tree

3 files changed

+279
-19
lines changed

3 files changed

+279
-19
lines changed

.claude/commands/todo.md

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
---
22
allowed-tools: [Bash, Read, Write]
3-
description: Task management and tracking system with ACTIVE_WORK.md integration
3+
description: Task management using GitHub Issues for better collaboration and tracking
44
---
55

66
# Todo Management Command
77

8-
Manage tasks efficiently using ACTIVE_WORK.md.
8+
Manage tasks efficiently using GitHub Issues.
99

1010
## Your Task
11-
Handle todo operations:
11+
Handle todo operations via GitHub Issues:
1212

1313
**IMPORTANT**: If adding dates, always use `date "+%Y-%m-%d"` to get the current date. Never guess or assume dates.
1414

@@ -21,30 +21,56 @@ ARGS="$*"
2121

2222
case "$COMMAND" in
2323
"list"|"show")
24-
echo "📋 Current Tasks:"
24+
echo "📋 GitHub Issues:"
2525
npm run todo:list --silent
26-
echo ""
27-
npm run todo:count --silent
2826
;;
2927

30-
"add")
31-
echo "➕ Adding task: $ARGS"
32-
echo "- [ ] $ARGS" >> ACTIVE_WORK.md
33-
echo "✅ Task added"
28+
"add"|"create")
29+
if [ -z "$ARGS" ]; then
30+
echo "❌ Error: Title required"
31+
exit 1
32+
fi
33+
echo "➕ Creating issue: $ARGS"
34+
npm run todo:add --silent -- "$ARGS"
3435
;;
3536

36-
"done")
37-
LINE_NUM="$1"
38-
echo "✅ Completing task #$LINE_NUM"
39-
sed -i.bak "${LINE_NUM}s/\\[ \\]/[x]/" ACTIVE_WORK.md && rm ACTIVE_WORK.md.bak
37+
"done"|"close")
38+
ISSUE_NUM="$1"
39+
if [ -z "$ISSUE_NUM" ]; then
40+
echo "❌ Error: Issue number required"
41+
exit 1
42+
fi
43+
echo "✅ Closing issue #$ISSUE_NUM"
44+
npm run todo:done --silent -- "$ISSUE_NUM"
45+
;;
46+
47+
"comment")
48+
ISSUE_NUM="$1"
49+
shift
50+
COMMENT="$*"
51+
if [ -z "$ISSUE_NUM" ] || [ -z "$COMMENT" ]; then
52+
echo "❌ Error: Issue number and comment required"
53+
exit 1
54+
fi
55+
npm run todo:comment --silent -- "$ISSUE_NUM" "$COMMENT"
56+
;;
57+
58+
"stats")
59+
echo "📊 Issue Statistics:"
60+
npm run todo:stats --silent
4061
;;
4162

4263
*)
43-
echo "Usage: /todo [list|add|done] [args]"
64+
echo "Usage: /todo [list|add|done|comment|stats] [args]"
65+
echo " list - Show open issues"
66+
echo " add <title> - Create new issue"
67+
echo " done <#> - Close issue"
68+
echo " comment <#> - Add comment to issue"
69+
echo " stats - Show issue statistics"
4470
;;
4571
esac
4672
```
4773

4874
## Notes
4975

50-
This command delegates to npm scripts for token efficiency.
76+
This command uses GitHub Issues via the GitHub CLI for better collaboration and tracking.

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
"hygiene": "npm run hygiene:quick --silent",
1010
"hygiene:quick": "npm run lint:check && npm run test:check && npm run git:status:summary",
1111
"hygiene:full": "npm run lint:check && npm run test:check && npm run deps:check && npm run git:status:full && npm run maintain:summary",
12-
"todo:list": "grep -n '^- \\[ \\]' ACTIVE_WORK.md 2>/dev/null || echo 'No pending tasks'",
13-
"todo:count": "echo \"Pending: $(grep -c '^- \\[ \\]' ACTIVE_WORK.md 2>/dev/null || echo '0') | Completed: $(grep -c '^- \\[x\\]' ACTIVE_WORK.md 2>/dev/null || echo '0')\"",
12+
"todo:list": "node scripts/todo-github.js list",
13+
"todo:add": "node scripts/todo-github.js add",
14+
"todo:done": "node scripts/todo-github.js done",
15+
"todo:comment": "node scripts/todo-github.js comment",
16+
"todo:stats": "node scripts/todo-github.js stats",
1417
"commit": "npm run commit:check",
1518
"commit:check": "npm run lint:check --silent && npm run test:check --silent",
1619
"// Quality Checks": "=== Quality and testing ===",
@@ -98,7 +101,6 @@
98101
"scripts/",
99102
"CLAUDE.md",
100103
"AGENTS.md",
101-
"ACTIVE_WORK.md",
102104
"README.md",
103105
"LICENSE"
104106
],

scripts/todo-github.js

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* GitHub Issue Management for Todo System
5+
* Replaces ACTIVE_WORK.md with GitHub Issues
6+
*/
7+
8+
const { execSync } = require('child_process');
9+
10+
const LABELS = {
11+
priority: ['high', 'medium', 'low'],
12+
type: ['bug', 'feature', 'docs', 'refactor', 'test'],
13+
status: ['blocked', 'in-progress'],
14+
area: ['commands', 'scripts', 'docs', 'ci', 'setup']
15+
};
16+
17+
function exec(command) {
18+
try {
19+
return execSync(command, { encoding: 'utf8', stdio: 'pipe' }).trim();
20+
} catch (error) {
21+
console.error(`Error: ${error.message}`);
22+
process.exit(1);
23+
}
24+
}
25+
26+
function formatIssue(issue) {
27+
const parts = issue.split('\t');
28+
const number = parts[0];
29+
const state = parts[1];
30+
const title = parts[2];
31+
const labels = parts[3] || '';
32+
const updated = parts[4] || '';
33+
34+
const stateIcon = state === 'OPEN' ? '🔵' : '✅';
35+
const labelStr = labels ? ` [${labels}]` : '';
36+
37+
return `${stateIcon} #${number}: ${title}${labelStr}`;
38+
}
39+
40+
function listIssues(filter = 'open') {
41+
console.log(`\n📋 GitHub Issues (${filter}):`);
42+
console.log('─'.repeat(50));
43+
44+
const stateFlag = filter === 'all' ? '' : `--state ${filter}`;
45+
const command = `gh issue list ${stateFlag} --limit 30 --json number,state,title,labels,updatedAt --template '{{range .}}{{.number}}\t{{.state}}\t{{.title}}\t{{range .labels}}{{.name}} {{end}}\t{{.updatedAt}}{{println}}{{end}}'`;
46+
47+
const output = exec(command);
48+
49+
if (!output) {
50+
console.log('No issues found');
51+
return;
52+
}
53+
54+
const issues = output.split('\n').filter(Boolean);
55+
issues.forEach(issue => {
56+
console.log(formatIssue(issue));
57+
});
58+
59+
console.log('─'.repeat(50));
60+
console.log(`Total: ${issues.length} issues`);
61+
}
62+
63+
function createIssue(title, body = '', labels = []) {
64+
console.log(`\n➕ Creating issue: "${title}"`);
65+
66+
const labelFlag = labels.length > 0 ? `--label "${labels.join(',')}"` : '';
67+
const bodyFlag = body ? `--body "${body}"` : '';
68+
69+
const command = `gh issue create --title "${title}" ${bodyFlag} ${labelFlag}`;
70+
const result = exec(command);
71+
72+
console.log(`✅ Issue created: ${result}`);
73+
return result;
74+
}
75+
76+
function closeIssue(number, comment = '') {
77+
console.log(`\n✅ Closing issue #${number}`);
78+
79+
if (comment) {
80+
exec(`gh issue comment ${number} --body "${comment}"`);
81+
}
82+
83+
exec(`gh issue close ${number}`);
84+
console.log(`Issue #${number} closed`);
85+
}
86+
87+
function reopenIssue(number, comment = '') {
88+
console.log(`\n🔄 Reopening issue #${number}`);
89+
90+
if (comment) {
91+
exec(`gh issue comment ${number} --body "${comment}"`);
92+
}
93+
94+
exec(`gh issue reopen ${number}`);
95+
console.log(`Issue #${number} reopened`);
96+
}
97+
98+
function addComment(number, comment) {
99+
console.log(`\n💬 Adding comment to issue #${number}`);
100+
exec(`gh issue comment ${number} --body "${comment}"`);
101+
console.log(`Comment added to issue #${number}`);
102+
}
103+
104+
function showIssue(number) {
105+
console.log(`\n📄 Issue #${number} Details:`);
106+
console.log('─'.repeat(50));
107+
108+
const issue = exec(`gh issue view ${number}`);
109+
console.log(issue);
110+
}
111+
112+
function showStats() {
113+
console.log('\n📊 Issue Statistics:');
114+
console.log('─'.repeat(50));
115+
116+
const openCount = exec('gh issue list --state open --limit 999 --json number --jq "length"');
117+
const closedCount = exec('gh issue list --state closed --limit 999 --json number --jq "length"');
118+
119+
console.log(`🔵 Open: ${openCount}`);
120+
console.log(`✅ Closed: ${closedCount}`);
121+
console.log(`📈 Total: ${parseInt(openCount) + parseInt(closedCount)}`);
122+
123+
// Get label distribution
124+
console.log('\n🏷️ Label Distribution:');
125+
const labels = exec('gh issue list --state open --limit 999 --json labels --jq "[.[].labels[].name] | group_by(.) | map({label: .[0], count: length})"');
126+
127+
if (labels && labels !== '[]') {
128+
const labelData = JSON.parse(labels);
129+
labelData.forEach(item => {
130+
console.log(` ${item.label}: ${item.count}`);
131+
});
132+
}
133+
}
134+
135+
function showHelp() {
136+
console.log(`
137+
📋 GitHub Issue Todo Management
138+
139+
Usage: node scripts/todo-github.js <command> [options]
140+
141+
Commands:
142+
list [filter] List issues (open/closed/all, default: open)
143+
add <title> [body] Create new issue
144+
done <number> Close an issue
145+
reopen <number> Reopen an issue
146+
comment <number> Add comment to issue
147+
show <number> Show issue details
148+
stats Show issue statistics
149+
help Show this help
150+
151+
Examples:
152+
node scripts/todo-github.js list
153+
node scripts/todo-github.js add "Fix login bug"
154+
node scripts/todo-github.js done 42
155+
node scripts/todo-github.js comment 42 "Working on this"
156+
157+
Labels:
158+
Priority: ${LABELS.priority.join(', ')}
159+
Type: ${LABELS.type.join(', ')}
160+
Status: ${LABELS.status.join(', ')}
161+
Area: ${LABELS.area.join(', ')}
162+
`);
163+
}
164+
165+
// Main execution
166+
const command = process.argv[2] || 'list';
167+
const args = process.argv.slice(3);
168+
169+
switch (command) {
170+
case 'list':
171+
listIssues(args[0] || 'open');
172+
break;
173+
174+
case 'add':
175+
case 'create':
176+
if (!args[0]) {
177+
console.error('Error: Title required');
178+
process.exit(1);
179+
}
180+
createIssue(args[0], args[1] || '');
181+
break;
182+
183+
case 'done':
184+
case 'close':
185+
if (!args[0]) {
186+
console.error('Error: Issue number required');
187+
process.exit(1);
188+
}
189+
closeIssue(args[0], args[1]);
190+
break;
191+
192+
case 'reopen':
193+
if (!args[0]) {
194+
console.error('Error: Issue number required');
195+
process.exit(1);
196+
}
197+
reopenIssue(args[0], args[1]);
198+
break;
199+
200+
case 'comment':
201+
if (!args[0] || !args[1]) {
202+
console.error('Error: Issue number and comment required');
203+
process.exit(1);
204+
}
205+
addComment(args[0], args.slice(1).join(' '));
206+
break;
207+
208+
case 'show':
209+
case 'view':
210+
if (!args[0]) {
211+
console.error('Error: Issue number required');
212+
process.exit(1);
213+
}
214+
showIssue(args[0]);
215+
break;
216+
217+
case 'stats':
218+
case 'status':
219+
showStats();
220+
break;
221+
222+
case 'help':
223+
case '--help':
224+
case '-h':
225+
showHelp();
226+
break;
227+
228+
default:
229+
console.error(`Unknown command: ${command}`);
230+
showHelp();
231+
process.exit(1);
232+
}

0 commit comments

Comments
 (0)