claude-task-master 0.2.0
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.
- checksums.yaml +7 -0
- data/CLAUDE.md +192 -0
- data/README.md +231 -0
- data/bin/claude-task-master +6 -0
- data/lib/claude_task_master/claude.rb +305 -0
- data/lib/claude_task_master/cli.rb +537 -0
- data/lib/claude_task_master/github.rb +345 -0
- data/lib/claude_task_master/loop.rb +250 -0
- data/lib/claude_task_master/pr_comment.rb +170 -0
- data/lib/claude_task_master/state.rb +183 -0
- data/lib/claude_task_master/version.rb +5 -0
- data/lib/claude_task_master.rb +17 -0
- metadata +141 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
require 'timeout'
|
|
5
|
+
|
|
6
|
+
module ClaudeTaskMaster
|
|
7
|
+
# Wrapper around the Claude Code CLI
|
|
8
|
+
# Handles invocation, output capture, and error handling
|
|
9
|
+
class Claude
|
|
10
|
+
DEFAULT_TIMEOUT = 3600 # 1 hour max per invocation
|
|
11
|
+
CLAUDE_BINARY = 'claude'
|
|
12
|
+
|
|
13
|
+
attr_reader :model, :timeout
|
|
14
|
+
|
|
15
|
+
def initialize(model: 'sonnet', timeout: DEFAULT_TIMEOUT)
|
|
16
|
+
@model = model
|
|
17
|
+
@timeout = timeout
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Check if Claude CLI is available
|
|
21
|
+
def self.available?
|
|
22
|
+
system('which claude > /dev/null 2>&1')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Get Claude version
|
|
26
|
+
def self.version
|
|
27
|
+
`claude --version 2>&1`.strip
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Invoke Claude with a prompt (non-interactive mode)
|
|
31
|
+
# Returns [success, output, exit_code]
|
|
32
|
+
def invoke(prompt, allowed_tools: nil, working_dir: nil)
|
|
33
|
+
args = build_args(allowed_tools)
|
|
34
|
+
cmd = [CLAUDE_BINARY, *args, prompt]
|
|
35
|
+
|
|
36
|
+
output = +''
|
|
37
|
+
success = false
|
|
38
|
+
exit_code = nil
|
|
39
|
+
|
|
40
|
+
Dir.chdir(working_dir || Dir.pwd) do
|
|
41
|
+
Timeout.timeout(timeout) do
|
|
42
|
+
Open3.popen2e(*cmd) do |stdin, stdout_err, wait_thr|
|
|
43
|
+
stdin.close
|
|
44
|
+
|
|
45
|
+
# Stream output in real-time
|
|
46
|
+
stdout_err.each_line do |line|
|
|
47
|
+
output << line
|
|
48
|
+
# Minimal progress indicator
|
|
49
|
+
$stdout.print '.' if line.include?('[Tool:')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
exit_code = wait_thr.value.exitstatus
|
|
53
|
+
success = exit_code.zero?
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
$stdout.puts if output.include?('[Tool:') # Newline after dots
|
|
59
|
+
|
|
60
|
+
[success, output, exit_code]
|
|
61
|
+
rescue Timeout::Error
|
|
62
|
+
[false, "#{output}\n\n[TIMEOUT after #{timeout}s]", -1]
|
|
63
|
+
rescue StandardError => e
|
|
64
|
+
[false, "#{output}\n\n[ERROR: #{e.message}]", -1]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Build the planning prompt
|
|
68
|
+
def self.planning_prompt(goal, existing_claude_md: nil, no_merge: false)
|
|
69
|
+
claude_md_section = if existing_claude_md
|
|
70
|
+
<<~SECTION
|
|
71
|
+
## Existing Project Context (CLAUDE.md)
|
|
72
|
+
The project already has a CLAUDE.md file. Read and follow its conventions:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
#{existing_claude_md[0..2000]}#{'...' if existing_claude_md.length > 2000}
|
|
76
|
+
```
|
|
77
|
+
SECTION
|
|
78
|
+
else
|
|
79
|
+
''
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
<<~PROMPT
|
|
83
|
+
# Claude Task Master - Planning Phase
|
|
84
|
+
|
|
85
|
+
You are an autonomous software engineer starting a new project. Your job is to:
|
|
86
|
+
1. **Analyze the codebase** - Understand what exists, patterns, tech stack
|
|
87
|
+
2. **Create a detailed plan** - Break the goal into PRs, each PR into tasks
|
|
88
|
+
3. **Save the plan** - Write to .claude-task-master/plan.md
|
|
89
|
+
|
|
90
|
+
#{claude_md_section}
|
|
91
|
+
|
|
92
|
+
## Goal
|
|
93
|
+
#{goal}
|
|
94
|
+
|
|
95
|
+
## Planning Instructions
|
|
96
|
+
|
|
97
|
+
### Step 1: Explore the Codebase
|
|
98
|
+
- Read key files: README.md, CLAUDE.md, package.json/Gemfile/Cargo.toml/CMakeLists.txt
|
|
99
|
+
- Understand the project structure and directory layout
|
|
100
|
+
- Identify existing patterns, coding style, and conventions
|
|
101
|
+
- Note the tech stack, dependencies, and build system
|
|
102
|
+
- Check for existing CI/CD configuration (.github/workflows, etc.)
|
|
103
|
+
|
|
104
|
+
### Step 2: Design the Plan
|
|
105
|
+
Create a plan structured as multiple PRs. Each PR should be:
|
|
106
|
+
- **Atomic**: A logical chunk of work that makes sense on its own
|
|
107
|
+
- **Reviewable**: Small enough for meaningful code review
|
|
108
|
+
- **Testable**: Includes tests or can be verified independently
|
|
109
|
+
|
|
110
|
+
Structure your plan like this:
|
|
111
|
+
```markdown
|
|
112
|
+
# Plan for: [Goal Summary]
|
|
113
|
+
|
|
114
|
+
## PR 1: [Title - e.g., "Project Foundation"]
|
|
115
|
+
- [ ] Task 1.1: Description
|
|
116
|
+
- [ ] Task 1.2: Description
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
## PR 2: [Title - e.g., "Core Implementation"]
|
|
120
|
+
- [ ] Task 2.1: Description
|
|
121
|
+
...
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Guidelines:
|
|
125
|
+
- 3-10 PRs typically, depending on scope
|
|
126
|
+
- 3-15 tasks per PR
|
|
127
|
+
- First PR often includes: project setup, CI, basic structure
|
|
128
|
+
- Order tasks by dependency (what must be done first)
|
|
129
|
+
- Include test tasks where appropriate
|
|
130
|
+
- Include documentation where appropriate
|
|
131
|
+
|
|
132
|
+
### Step 3: Write State Files
|
|
133
|
+
1. Write plan to `.claude-task-master/plan.md`
|
|
134
|
+
2. Update `.claude-task-master/state.json`:
|
|
135
|
+
- Set `status` to `"ready"`
|
|
136
|
+
- Set `current_task` to first task description
|
|
137
|
+
- Set `current_pr` to `1`
|
|
138
|
+
3. Write context to `.claude-task-master/context.md`:
|
|
139
|
+
- Key files discovered
|
|
140
|
+
- Patterns to follow
|
|
141
|
+
- Decisions made
|
|
142
|
+
|
|
143
|
+
Be thorough but practical. Each PR should deliver value.
|
|
144
|
+
PROMPT
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Build the work prompt
|
|
148
|
+
def self.work_prompt(context, no_merge: false)
|
|
149
|
+
merge_instructions = if no_merge
|
|
150
|
+
<<~MERGE
|
|
151
|
+
**IMPORTANT: DO NOT MERGE PRs**
|
|
152
|
+
- Create PRs but do not merge them
|
|
153
|
+
- Wait for manual review and merge
|
|
154
|
+
- Once PR is ready (CI green, no unresolved comments), move to next PR
|
|
155
|
+
- Set `pr_ready` to `true` in state.json when ready for merge
|
|
156
|
+
MERGE
|
|
157
|
+
else
|
|
158
|
+
<<~MERGE
|
|
159
|
+
**Auto-merge is enabled**
|
|
160
|
+
- Once PR is approved (CI green, no unresolved comments), merge it:
|
|
161
|
+
`gh pr merge --squash --delete-branch`
|
|
162
|
+
- After merge, pull main and start next PR
|
|
163
|
+
MERGE
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
<<~PROMPT
|
|
167
|
+
# Claude Task Master - Work Session
|
|
168
|
+
|
|
169
|
+
You are an autonomous software engineer continuing work on a project.
|
|
170
|
+
|
|
171
|
+
## Current State
|
|
172
|
+
#{context}
|
|
173
|
+
|
|
174
|
+
## Work Loop Instructions
|
|
175
|
+
|
|
176
|
+
### Step 1: Understand Current State
|
|
177
|
+
- Read `.claude-task-master/plan.md` to see all tasks
|
|
178
|
+
- Read `.claude-task-master/state.json` for current task and status
|
|
179
|
+
- Identify what needs to be done next
|
|
180
|
+
|
|
181
|
+
### Step 2: Execute the Work
|
|
182
|
+
|
|
183
|
+
**If working on a task:**
|
|
184
|
+
1. Implement the task (write code, create files)
|
|
185
|
+
2. Run tests/linters if available
|
|
186
|
+
3. Commit with a clear message
|
|
187
|
+
4. Check off task in plan.md: `- [x] Task`
|
|
188
|
+
5. Update state.json with next task
|
|
189
|
+
6. Continue to next task in same PR
|
|
190
|
+
|
|
191
|
+
**If PR is ready (all tasks for this PR done):**
|
|
192
|
+
1. Create the PR if not already created:
|
|
193
|
+
```bash
|
|
194
|
+
gh pr create --title "PR Title" --body "Description
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
Built with [claude-task-master](https://github.com/sebyx07/claude-task-master) + [Claude Code](https://claude.ai/code)"
|
|
198
|
+
```
|
|
199
|
+
2. Store PR number in state.json: `pr_number`
|
|
200
|
+
|
|
201
|
+
**If PR exists, check its status:**
|
|
202
|
+
1. Check CI status:
|
|
203
|
+
```bash
|
|
204
|
+
gh pr checks
|
|
205
|
+
```
|
|
206
|
+
2. Check for review comments (CodeRabbit, Copilot, human reviewers):
|
|
207
|
+
```bash
|
|
208
|
+
gh pr view --json comments,reviews
|
|
209
|
+
gh api repos/{owner}/{repo}/pulls/{pr}/comments
|
|
210
|
+
```
|
|
211
|
+
3. **CRITICAL: Address ALL review comments before proceeding**
|
|
212
|
+
- Read each comment carefully
|
|
213
|
+
- Make the requested changes
|
|
214
|
+
- Commit and push: `git push`
|
|
215
|
+
- Wait for CI to pass again
|
|
216
|
+
|
|
217
|
+
**If CI fails:**
|
|
218
|
+
1. Read the error output: `gh pr checks`
|
|
219
|
+
2. Fix the issues
|
|
220
|
+
3. Commit and push
|
|
221
|
+
4. Repeat until green
|
|
222
|
+
|
|
223
|
+
**If review comments exist:**
|
|
224
|
+
1. Address each comment
|
|
225
|
+
2. Push fixes
|
|
226
|
+
3. Comments from bots (CodeRabbit, Copilot) often auto-resolve
|
|
227
|
+
4. Check again: `gh api repos/{owner}/{repo}/pulls/{pr}/comments`
|
|
228
|
+
|
|
229
|
+
#{merge_instructions}
|
|
230
|
+
|
|
231
|
+
### Step 3: Track Progress
|
|
232
|
+
|
|
233
|
+
Always update state files after significant progress:
|
|
234
|
+
|
|
235
|
+
**plan.md:**
|
|
236
|
+
- Check off completed tasks: `- [x] Task done`
|
|
237
|
+
- Keep unchecked tasks: `- [ ] Task pending`
|
|
238
|
+
|
|
239
|
+
**state.json:**
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"status": "working|ready|blocked|success",
|
|
243
|
+
"current_task": "Current task description",
|
|
244
|
+
"current_pr": 1,
|
|
245
|
+
"pr_number": 123,
|
|
246
|
+
"pr_ready": false,
|
|
247
|
+
"session_count": N,
|
|
248
|
+
"updated_at": "ISO timestamp"
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**progress.md:**
|
|
253
|
+
- Append notes about what was done
|
|
254
|
+
- Document any issues encountered
|
|
255
|
+
- Note decisions made
|
|
256
|
+
|
|
257
|
+
**context.md:**
|
|
258
|
+
- Add newly discovered patterns
|
|
259
|
+
- Document learnings about the codebase
|
|
260
|
+
|
|
261
|
+
### Step 4: Handle Completion
|
|
262
|
+
|
|
263
|
+
**When current PR is complete (merged or ready):**
|
|
264
|
+
1. Update state.json: increment `current_pr`
|
|
265
|
+
2. Create new branch from main: `git checkout main && git pull && git checkout -b pr-N-description`
|
|
266
|
+
3. Reset `pr_number` to null in state.json
|
|
267
|
+
4. Continue with next PR's tasks
|
|
268
|
+
|
|
269
|
+
**When ALL PRs are done:**
|
|
270
|
+
1. Set status to `"success"` in state.json
|
|
271
|
+
2. Write completion summary to progress.md
|
|
272
|
+
|
|
273
|
+
**If stuck or blocked:**
|
|
274
|
+
1. Set status to `"blocked"` in state.json
|
|
275
|
+
2. Explain the blocker clearly in progress.md
|
|
276
|
+
3. Do NOT retry the same failing approach repeatedly
|
|
277
|
+
|
|
278
|
+
### Guidelines
|
|
279
|
+
- Work autonomously - make decisions
|
|
280
|
+
- Ship working code - don't over-engineer
|
|
281
|
+
- Follow existing patterns in the codebase
|
|
282
|
+
- Write tests where appropriate
|
|
283
|
+
- Keep commits focused and well-described
|
|
284
|
+
- Don't leave commented-out code
|
|
285
|
+
- Fix issues properly, don't hack around them
|
|
286
|
+
PROMPT
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
private
|
|
290
|
+
|
|
291
|
+
def build_args(allowed_tools)
|
|
292
|
+
args = [
|
|
293
|
+
'-p',
|
|
294
|
+
'--dangerously-skip-permissions',
|
|
295
|
+
'--model', model
|
|
296
|
+
]
|
|
297
|
+
|
|
298
|
+
if allowed_tools
|
|
299
|
+
args += ['--allowedTools', allowed_tools.join(',')]
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
args
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|