claude-teammate 0.1.41 → 0.1.43

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.
package/README.md CHANGED
@@ -41,7 +41,9 @@ Assign it tickets. It ships.
41
41
  - ✅ You want Jira tickets to **turn into merged PRs** without manual handoff
42
42
  - ✅ You want **PR review comments acted on**, not just acknowledged
43
43
  - ✅ You need a reviewer that **always shows up** and leaves structured feedback
44
+ - ✅ You want **automated PR review** without adding another review subscription on top of Claude
44
45
  - ✅ You want an AI that **remembers** - which repo, what's shipped, what breaks, what to avoid
46
+ - ✅ You want the agent running in **its own working environment** so it can test code and verify real outputs
45
47
  - ✅ You want this running on **your own infrastructure**
46
48
 
47
49
  <br/>
@@ -72,10 +74,22 @@ Add it as a reviewer and it will show up - every time, with real feedback, never
72
74
 
73
75
  <br/>
74
76
 
77
+ ## Review Human PRs Too
78
+
79
+ Claude Teammate is not limited to tickets it implemented itself. Add it as a reviewer on a human-authored pull request and it will read the diff, inspect the repository, and leave structured review feedback. This can be an alternative to paid tools like CodeRabbit or GitHub Copilot code review.
80
+
81
+ <p align="center">
82
+ <img src="assets/PR_review.webp" alt="Claude Teammate reviewing a human pull request" width="760" style="border: 1px solid #d1d5db;" />
83
+ </p>
84
+
85
+ <br/>
86
+
75
87
  ## It Remembers
76
88
 
77
89
  Every epic has its own memory. The bot picks up exactly where it left off - no matter how much time has passed.
78
90
 
91
+ That memory is built from more than the original Jira description. Claude Teammate updates it from planning, implementation, review comments, and recurring human feedback so future tickets inherit the durable parts of the work instead of starting from scratch.
92
+
79
93
  ```
80
94
  memory/
81
95
  └── {domain}/
@@ -87,7 +101,9 @@ memory/
87
101
  |---|---|
88
102
  | `jira_key` / `jira_url` | Canonical epic identity |
89
103
  | `repos` | Shared target GitHub repositories for the epic |
90
- | `summary` / `guardrails` | Reusable lessons, build quirks, verification workflows, and what-not-to-do notes for the epic |
104
+ | `facts` / `guardrails` | Reusable lessons, build quirks, verification workflows, recurring human feedback, and what-not-to-do notes for the epic |
105
+
106
+ The memory stays compact on purpose. It is cleaned up, deduplicated, and summarized over time so later tickets can reuse the important context without dragging an ever-growing prompt window behind them.
91
107
 
92
108
  <br/>
93
109
 
@@ -162,6 +178,9 @@ Yes. Each epic is scoped to its own Jira domain and workspace, and can map to on
162
178
  **Does it understand the codebase or just generate generic code?**
163
179
  It reads the actual repository before writing anything - structure, conventions, existing patterns. The plan it proposes is specific to your code, not a template.
164
180
 
181
+ **Can it test code and verify UI changes?**
182
+ Yes. It works in its own cloned working environment, can run the repo's test and build commands, and can use Playwright to take screenshots and verify frontend changes instead of relying only on the diff.
183
+
165
184
  **Can I use Claude skills or MCP, and does it respect `CLAUDE.md`?**
166
185
  Yes. Claude skills, configured MCP servers, and repo instructions in `CLAUDE.md` are available and respected just like they are in a normal Claude-driven workflow. Playwright MCP is built in and enabled by default so challenging frontend tasks can be verified in-browser.
167
186
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-teammate",
3
- "version": "0.1.41",
3
+ "version": "0.1.43",
4
4
  "description": "CLI bootstrapper for Claude Teammate.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/claude.js CHANGED
@@ -1037,7 +1037,7 @@ function buildGitHubPRReviewSystemPrompt() {
1037
1037
  "Skip trivial style-only issues unless they introduce a real risk.",
1038
1038
  "Classify each suggestion as Minor (non-blocking) or Major (should be addressed before merge).",
1039
1039
  "Where possible, produce a committable suggestion with the corrected code.",
1040
- "Return a summary paragraph describing what the PR does, followed by a summary of all suggestions.",
1040
+ "Return a summary with the following structure: Short overview (1–3 sentences), Key changes (bullet points), Summary of all suggestions (1-2 sentences).",
1041
1041
  "Return only structured output matching the provided schema."
1042
1042
  ].join(" ");
1043
1043
  }
@@ -1200,13 +1200,16 @@ Pull request number: ${input.pr?.number ?? ""}
1200
1200
  Pull request title:
1201
1201
  ${input.pr?.title ?? ""}
1202
1202
 
1203
+ Pull request description:
1204
+ ${input.pr?.body ?? "(empty)"}
1205
+
1203
1206
  Repository path:
1204
1207
  ${input.repoPath}
1205
1208
 
1206
1209
  Unified diff:
1207
1210
  ${input.diff || "(empty)"}
1208
1211
 
1209
- Review the diff carefully. Read related code files with Read, Grep, or Glob only when the diff alone is insufficient to judge correctness. Return a summary describing the PR and its suggestions.`;
1212
+ Return a concise PR summary in the schema summary field, plus any review suggestions in the schema suggestions field.`;
1210
1213
  }
1211
1214
 
1212
1215
  function buildEpicMemoryCleanupUserPrompt(input) {
@@ -377,28 +377,13 @@ export async function runWorkerCommand({ projectRoot }) {
377
377
  }
378
378
 
379
379
  try {
380
- const repoPath = await ensureReviewRepo(pr.repoUrl, runtimePaths.reviewReposDir);
381
- const prDetail = await github.fetchPullRequest(pr.repoUrl, pr.number);
382
- await checkoutPullRequestBranch(repoPath, prDetail.headRef, prDetail.headRepoCloneUrl);
383
-
384
- const diff = await github.fetchPullRequestDiff(pr.repoUrl, pr.number);
385
- const result = await runClaudePrReview({
386
- diff,
387
- repoPath,
388
- pr: prDetail,
380
+ const { prDetail, result } = await processReviewPullRequest({
381
+ pr,
382
+ github,
383
+ reviewReposDir: runtimePaths.reviewReposDir,
389
384
  timeoutMs: parseOptionalInt(values.CLAUDE_TIMEOUT_MS)
390
385
  });
391
386
 
392
- await github.createPullRequestReview(
393
- pr.repoUrl,
394
- pr.number,
395
- result.summary,
396
- result.suggestions,
397
- "COMMENT"
398
- );
399
-
400
- await github.addLabelsToPullRequest(pr.repoUrl, pr.number, ["AI-reviewed"]);
401
-
402
387
  processedPrs.push({
403
388
  repoUrl: pr.repoUrl,
404
389
  pullRequestNumber: String(pr.number),
@@ -455,6 +440,45 @@ export async function runWorkerCommand({ projectRoot }) {
455
440
  }, POLL_INTERVAL_MS);
456
441
  }
457
442
 
443
+ export async function processReviewPullRequest({
444
+ pr,
445
+ github,
446
+ reviewReposDir,
447
+ timeoutMs,
448
+ ensureReviewRepoFn = ensureReviewRepo,
449
+ fetchPullRequestFn = (repoUrl, prNumber) => github.fetchPullRequest(repoUrl, prNumber),
450
+ checkoutPullRequestBranchFn = checkoutPullRequestBranch,
451
+ fetchPullRequestDiffFn = (repoUrl, prNumber) => github.fetchPullRequestDiff(repoUrl, prNumber),
452
+ runClaudePrReviewFn = runClaudePrReview,
453
+ createPullRequestReviewFn = (repoUrl, prNumber, body, suggestions, event) =>
454
+ github.createPullRequestReview(repoUrl, prNumber, body, suggestions, event)
455
+ }) {
456
+ await github.addLabelsToPullRequest(pr.repoUrl, pr.number, ["AI-reviewed"]);
457
+ await github.postIssueComment(pr.repoUrl, pr.number, "I am reviewing the PR.");
458
+
459
+ const repoPath = await ensureReviewRepoFn(pr.repoUrl, reviewReposDir);
460
+ const prDetail = await fetchPullRequestFn(pr.repoUrl, pr.number);
461
+ await checkoutPullRequestBranchFn(repoPath, prDetail.headRef, prDetail.headRepoCloneUrl);
462
+
463
+ const diff = await fetchPullRequestDiffFn(pr.repoUrl, pr.number);
464
+ const result = await runClaudePrReviewFn({
465
+ diff,
466
+ repoPath,
467
+ pr: prDetail,
468
+ timeoutMs
469
+ });
470
+
471
+ await createPullRequestReviewFn(
472
+ pr.repoUrl,
473
+ pr.number,
474
+ result.summary,
475
+ result.suggestions,
476
+ "COMMENT"
477
+ );
478
+
479
+ return { prDetail, result };
480
+ }
481
+
458
482
  async function processJiraIssue({ issue, jira, github, botUser, config, projectRoot, runtimePaths, logger }) {
459
483
  const detail = await jira.fetchIssueDetails(issue.key);
460
484