@bragduck/cli 1.0.3 → 2.0.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.
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # Bragduck CLI
2
2
 
3
- > Transform your git commits into polished achievements with AI-powered refinement
3
+ > Transform your GitHub Pull Requests into polished achievements with AI-powered refinement
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/@bragduck%2Fcli.svg)](https://www.npmjs.com/package/@bragduck/cli)
6
6
  [![Node.js Version](https://img.shields.io/node/v/@bragduck/cli)](https://nodejs.org)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
- [![Tests](https://img.shields.io/badge/tests-122%20passing-brightgreen)](https://github.com/medhatdawoud/bragduck-cli)
8
+ [![Tests](https://img.shields.io/badge/tests-126%20passing-brightgreen)](https://github.com/medhatdawoud/bragduck-cli)
9
9
 
10
10
  ## Overview
11
11
 
12
- Bragduck CLI is a powerful command-line tool that helps developers track and showcase their achievements by transforming git commits into polished "brags" using AI-powered refinement. Perfect for updating your portfolio, preparing for performance reviews, or simply keeping track of your accomplishments.
12
+ Bragduck CLI is a powerful command-line tool that helps developers track and showcase their achievements by transforming GitHub Pull Requests into polished "brags" using AI-powered refinement. Perfect for updating your portfolio, preparing for performance reviews, or simply keeping track of your accomplishments.
13
13
 
14
14
  ### Why Bragduck?
15
15
 
@@ -20,6 +20,33 @@ Bragduck CLI is a powerful command-line tool that helps developers track and sho
20
20
  - 🚀 **Fast**: Optimized build size (69KB) for quick installation and execution
21
21
  - 🌐 **Cross-Platform**: Works on macOS, Windows, and Linux
22
22
 
23
+ ## Prerequisites
24
+
25
+ Before installing Bragduck CLI, you need:
26
+
27
+ 1. **Node.js ≥18.0.0**
28
+ ```bash
29
+ node --version # Should be v18.0.0 or higher
30
+ ```
31
+
32
+ 2. **GitHub CLI (gh)**
33
+ ```bash
34
+ # macOS
35
+ brew install gh
36
+
37
+ # Windows
38
+ winget install --id GitHub.cli
39
+
40
+ # Linux
41
+ # See https://github.com/cli/cli#installation
42
+ ```
43
+
44
+ 3. **Authenticate with GitHub CLI**
45
+ ```bash
46
+ gh auth login
47
+ ```
48
+ Follow the prompts to authenticate with your GitHub account.
49
+
23
50
  ## Installation
24
51
 
25
52
  ```bash
@@ -30,25 +57,34 @@ npm install -g @bragduck/cli
30
57
 
31
58
  ### Quick Start
32
59
 
33
- 1. **Install globally:**
60
+ 1. **Install GitHub CLI and authenticate:**
61
+ ```bash
62
+ # Install GitHub CLI (if not already installed)
63
+ brew install gh # macOS
64
+
65
+ # Authenticate with GitHub
66
+ gh auth login
67
+ ```
68
+
69
+ 2. **Install Bragduck CLI globally:**
34
70
  ```bash
35
71
  npm install -g @bragduck/cli
36
72
  ```
37
73
 
38
- 2. **Initialize and authenticate:**
74
+ 3. **Initialize and authenticate:**
39
75
  ```bash
40
76
  bragduck init
41
77
  ```
42
78
  This opens your browser for OAuth authentication. Once completed, your credentials are securely stored.
43
79
 
44
- 3. **Scan your commits:**
80
+ 4. **Scan your merged PRs:**
45
81
  ```bash
46
- cd /path/to/your/git/repo
82
+ cd /path/to/your/github/repo
47
83
  bragduck scan
48
84
  ```
49
- Select commits interactively, preview AI-refined brags, and create them.
85
+ Select PRs interactively, preview AI-refined brags, and create them.
50
86
 
51
- 4. **View your brags:**
87
+ 5. **View your brags:**
52
88
  ```bash
53
89
  bragduck list
54
90
  ```
@@ -65,16 +101,16 @@ bragduck init
65
101
 
66
102
  #### `bragduck scan`
67
103
 
68
- Scan git commits and create brags with AI-powered refinement.
104
+ Scan merged GitHub Pull Requests and create brags with AI-powered refinement.
69
105
 
70
106
  ```bash
71
- # Scan last 30 days (default)
107
+ # Scan last 30 days (default, your PRs only)
72
108
  bragduck scan
73
109
 
74
110
  # Scan last 60 days
75
111
  bragduck scan --days 60
76
112
 
77
- # Include all commits (not just yours)
113
+ # Include all PRs (not just yours)
78
114
  bragduck scan --all
79
115
 
80
116
  # Combine options
@@ -83,15 +119,28 @@ bragduck scan --days 90 --all
83
119
 
84
120
  **Options:**
85
121
  - `-d, --days <number>` - Number of days to scan (default: 30)
86
- - `-a, --all` - Include all commits, not just current user's
122
+ - `-a, --all` - Include all PRs, not just current user's
87
123
 
88
124
  **Workflow:**
89
- 1. Detects git repository
90
- 2. Fetches recent commits
91
- 3. Interactive checkbox selection
92
- 4. AI refines selected commits
93
- 5. Preview refined brags in table format
94
- 6. Confirm and create brags
125
+ 1. Validates GitHub repository
126
+ 2. Fetches merged PRs in timeframe (filtered by author unless --all)
127
+ 3. Displays PRs in format: `#123 PR Title [stats]`
128
+ 4. Interactive checkbox selection
129
+ 5. AI refines selected PRs (using title + description)
130
+ 6. Preview refined brags in table format
131
+ 7. Confirm and create brags
132
+
133
+ **What gets scanned:**
134
+ - ✅ Merged Pull Requests only
135
+ - ✅ PR title and description used for context
136
+ - ✅ Aggregate PR statistics (files changed, insertions, deletions)
137
+ - ✅ Filtered by PR author (person who created the PR)
138
+ - ❌ Draft or closed-without-merge PRs excluded
139
+ - ❌ Individual commits not scanned
140
+
141
+ **Requirements:**
142
+ - Must be in a GitHub repository (GitLab/Bitbucket not supported)
143
+ - GitHub CLI must be installed and authenticated (`gh auth login`)
95
144
 
96
145
  #### `bragduck list`
97
146
 
@@ -196,6 +245,7 @@ bragduck --help
196
245
  - ✅ Windows (Compatible)
197
246
  - ✅ Linux (Compatible)
198
247
  - ✅ Node.js ≥18.0.0
248
+ - ✅ GitHub repositories only (GitLab/Bitbucket not supported)
199
249
 
200
250
  ## Configuration
201
251
 
@@ -241,17 +291,62 @@ git status # Verify it's a git repo
241
291
  bragduck scan
242
292
  ```
243
293
 
244
- ### No Commits Found
294
+ ### GitHub CLI Not Authenticated
245
295
 
246
- **Problem**: "No commits found in the last X days"
296
+ **Problem**: "Not authenticated with GitHub" error
297
+
298
+ **Solution**:
299
+ ```bash
300
+ # Authenticate with GitHub CLI
301
+ gh auth login
302
+
303
+ # Verify authentication
304
+ gh auth status
305
+ ```
306
+
307
+ ### Not a GitHub Repository
308
+
309
+ **Problem**: "This repository is not hosted on GitHub" error
310
+
311
+ **Solution**:
312
+ - Bragduck CLI currently only supports GitHub repositories
313
+ - Make sure you're in a repository with a GitHub remote:
314
+ ```bash
315
+ git remote -v # Should show github.com URL
316
+ ```
317
+
318
+ ### No Merged PRs Found
319
+
320
+ **Problem**: "No merged PRs found in the last X days"
247
321
 
248
322
  **Solution**:
249
323
  ```bash
250
324
  # Increase the scan days
251
325
  bragduck scan --days 90
252
326
 
253
- # Or include all commits (not just yours)
327
+ # Or include all PRs (not just yours)
254
328
  bragduck scan --all
329
+
330
+ # Check if you have merged PRs on GitHub
331
+ gh pr list --state merged --limit 10
332
+ ```
333
+
334
+ ### GitHub CLI Not Installed
335
+
336
+ **Problem**: "GitHub CLI (gh) is not installed" error
337
+
338
+ **Solution**:
339
+ ```bash
340
+ # macOS
341
+ brew install gh
342
+
343
+ # Windows
344
+ winget install --id GitHub.cli
345
+
346
+ # Linux - see https://github.com/cli/cli#installation
347
+
348
+ # Verify installation
349
+ gh --version
255
350
  ```
256
351
 
257
352
  ### API Connection Issues
@@ -377,10 +472,10 @@ npx vitest
377
472
  ```
378
473
 
379
474
  **Test Stats:**
380
- - ✅ 122 tests passing
475
+ - ✅ 126 tests passing
381
476
  - 📊 50% code coverage (focused on core logic)
382
- - 🧪 7 test suites covering:
383
- - Services (Storage, Git, API)
477
+ - 🧪 8 test suites covering:
478
+ - Services (Storage, Git, API, GitHub)
384
479
  - Commands (Config, List)
385
480
  - Utilities (Version, Errors)
386
481
 
@@ -398,6 +493,7 @@ src/
398
493
  │ ├── auth.service.ts # Authentication & token management
399
494
  │ ├── api.service.ts # Backend API client (ofetch)
400
495
  │ ├── git.service.ts # Git operations (simple-git)
496
+ │ ├── github.service.ts # GitHub PR fetching (gh CLI)
401
497
  │ └── storage.service.ts # Encrypted credential storage
402
498
  ├── ui/ # Terminal UI components
403
499
  │ ├── prompts.ts # Interactive prompts (Inquirer)
@@ -432,6 +528,9 @@ src/
432
528
  - chalk, ora, cli-table3, boxen (terminal styling)
433
529
  - conf (configuration management)
434
530
 
531
+ **External Tools:**
532
+ - GitHub CLI (gh) - Required for PR scanning
533
+
435
534
  ## Contributing
436
535
 
437
536
  Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
@@ -457,7 +556,7 @@ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for gui
457
556
 
458
557
  ### Getting Help
459
558
 
460
- - 📖 **Documentation**: Read this README and [PLAN.md](PLAN.md)
559
+ - 📖 **Documentation**: Read this README and [TESTING_GUIDE.md](TESTING_GUIDE.md)
461
560
  - 🐛 **Issues**: [GitHub Issues](https://github.com/medhatdawoud/bragduck-cli/issues)
462
561
  - 💬 **Discussions**: [GitHub Discussions](https://github.com/medhatdawoud/bragduck-cli/discussions)
463
562
 
@@ -308,7 +308,7 @@ var init_storage_service = __esm({
308
308
  });
309
309
 
310
310
  // src/utils/errors.ts
311
- var BragduckError, AuthenticationError, GitError, ApiError, NetworkError, ValidationError, OAuthError, TokenExpiredError;
311
+ var BragduckError, AuthenticationError, GitError, ApiError, NetworkError, ValidationError, OAuthError, TokenExpiredError, GitHubError;
312
312
  var init_errors = __esm({
313
313
  "src/utils/errors.ts"() {
314
314
  "use strict";
@@ -366,6 +366,12 @@ var init_errors = __esm({
366
366
  this.code = "TOKEN_EXPIRED";
367
367
  }
368
368
  };
369
+ GitHubError = class extends BragduckError {
370
+ constructor(message, details) {
371
+ super(message, "GITHUB_ERROR", details);
372
+ this.name = "GitHubError";
373
+ }
374
+ };
369
375
  }
370
376
  });
371
377
 
@@ -1399,6 +1405,13 @@ init_esm_shims();
1399
1405
  import boxen4 from "boxen";
1400
1406
  import chalk7 from "chalk";
1401
1407
 
1408
+ // src/services/github.service.ts
1409
+ init_esm_shims();
1410
+ init_errors();
1411
+ init_logger();
1412
+ import { exec as exec2 } from "child_process";
1413
+ import { promisify as promisify2 } from "util";
1414
+
1402
1415
  // src/services/git.service.ts
1403
1416
  init_esm_shims();
1404
1417
  import simpleGit from "simple-git";
@@ -1481,7 +1494,7 @@ var GitService = class {
1481
1494
  * Fetch recent commits
1482
1495
  */
1483
1496
  async getRecentCommits(options = {}) {
1484
- const { days = 30, limit, author, branch } = options;
1497
+ const { days = 30, limit, author } = options;
1485
1498
  try {
1486
1499
  await this.validateRepository();
1487
1500
  logger.debug(`Fetching commits from last ${days} days`);
@@ -1619,6 +1632,203 @@ var GitService = class {
1619
1632
  };
1620
1633
  var gitService = new GitService();
1621
1634
 
1635
+ // src/services/github.service.ts
1636
+ var execAsync2 = promisify2(exec2);
1637
+ var GitHubService = class {
1638
+ MAX_BODY_LENGTH = 5e3;
1639
+ PR_SEARCH_FIELDS = "number,title,body,author,mergedAt,additions,deletions,changedFiles,url,labels";
1640
+ /**
1641
+ * Check if GitHub CLI is installed and available
1642
+ */
1643
+ async checkGitHubCLI() {
1644
+ try {
1645
+ await execAsync2("command gh --version");
1646
+ return true;
1647
+ } catch (_error) {
1648
+ return false;
1649
+ }
1650
+ }
1651
+ /**
1652
+ * Validate that GitHub CLI is installed
1653
+ */
1654
+ async ensureGitHubCLI() {
1655
+ const isInstalled = await this.checkGitHubCLI();
1656
+ if (!isInstalled) {
1657
+ throw new GitHubError("GitHub CLI (gh) is not installed", {
1658
+ hint: "Install from https://cli.github.com/"
1659
+ });
1660
+ }
1661
+ }
1662
+ /**
1663
+ * Check if user is authenticated with GitHub CLI
1664
+ */
1665
+ async checkAuthentication() {
1666
+ try {
1667
+ await execAsync2("command gh auth status");
1668
+ return true;
1669
+ } catch (_error) {
1670
+ return false;
1671
+ }
1672
+ }
1673
+ /**
1674
+ * Ensure user is authenticated with GitHub CLI
1675
+ */
1676
+ async ensureAuthentication() {
1677
+ const isAuthenticated = await this.checkAuthentication();
1678
+ if (!isAuthenticated) {
1679
+ throw new GitHubError("Not authenticated with GitHub", {
1680
+ hint: 'Run "gh auth login" to authenticate'
1681
+ });
1682
+ }
1683
+ }
1684
+ /**
1685
+ * Validate that the current repository is hosted on GitHub
1686
+ */
1687
+ async validateGitHubRepository() {
1688
+ try {
1689
+ await this.ensureGitHubCLI();
1690
+ await this.ensureAuthentication();
1691
+ await gitService.validateRepository();
1692
+ const { stdout } = await execAsync2("command gh repo view --json url");
1693
+ const data = JSON.parse(stdout);
1694
+ if (!data.url) {
1695
+ throw new GitHubError("This repository is not hosted on GitHub", {
1696
+ hint: "Only GitHub repositories are currently supported for PR scanning"
1697
+ });
1698
+ }
1699
+ } catch (error) {
1700
+ if (error instanceof GitHubError || error instanceof GitError) {
1701
+ throw error;
1702
+ }
1703
+ if (error.message?.includes("not a git repository")) {
1704
+ throw new GitHubError("Not a git repository", {
1705
+ hint: "Navigate to a git repository directory"
1706
+ });
1707
+ }
1708
+ if (error.message?.includes("Could not resolve to a Repository")) {
1709
+ throw new GitHubError("This repository is not hosted on GitHub", {
1710
+ hint: "Only GitHub repositories are currently supported for PR scanning"
1711
+ });
1712
+ }
1713
+ throw new GitHubError("Failed to validate GitHub repository", {
1714
+ originalError: error.message
1715
+ });
1716
+ }
1717
+ }
1718
+ /**
1719
+ * Get GitHub repository information
1720
+ */
1721
+ async getRepositoryInfo() {
1722
+ try {
1723
+ await this.ensureGitHubCLI();
1724
+ const { stdout } = await execAsync2(
1725
+ "command gh repo view --json owner,name,url,nameWithOwner"
1726
+ );
1727
+ const data = JSON.parse(stdout);
1728
+ return {
1729
+ owner: data.owner.login,
1730
+ name: data.name,
1731
+ fullName: data.nameWithOwner,
1732
+ url: data.url,
1733
+ isGitHub: true
1734
+ };
1735
+ } catch (error) {
1736
+ if (error instanceof GitHubError || error instanceof GitError) {
1737
+ throw error;
1738
+ }
1739
+ throw new GitHubError("Failed to get GitHub repository information", {
1740
+ originalError: error.message
1741
+ });
1742
+ }
1743
+ }
1744
+ /**
1745
+ * Get the current authenticated GitHub user
1746
+ */
1747
+ async getCurrentGitHubUser() {
1748
+ try {
1749
+ const { stdout } = await execAsync2("command gh api user --jq .login");
1750
+ return stdout.trim() || null;
1751
+ } catch (_error) {
1752
+ logger.debug("Failed to get GitHub user");
1753
+ return null;
1754
+ }
1755
+ }
1756
+ /**
1757
+ * Fetch merged PRs from GitHub
1758
+ */
1759
+ async getMergedPRs(options = {}) {
1760
+ const { days = 30, limit, author } = options;
1761
+ try {
1762
+ await this.ensureGitHubCLI();
1763
+ await this.ensureAuthentication();
1764
+ logger.debug(`Fetching merged PRs from the last ${days} days`);
1765
+ const since = /* @__PURE__ */ new Date();
1766
+ since.setDate(since.getDate() - days);
1767
+ const sinceDate = since.toISOString().split("T")[0];
1768
+ let searchQuery = `merged:>=${sinceDate}`;
1769
+ if (author) {
1770
+ searchQuery += ` author:${author}`;
1771
+ }
1772
+ const limitArg = limit ? `--limit ${limit}` : "";
1773
+ const command = `command gh pr list --state merged --json ${this.PR_SEARCH_FIELDS} --search "${searchQuery}" ${limitArg}`;
1774
+ logger.debug(`Running: ${command}`);
1775
+ const { stdout } = await execAsync2(command);
1776
+ const prs = JSON.parse(stdout);
1777
+ logger.debug(`Found ${prs.length} merged PRs`);
1778
+ return prs;
1779
+ } catch (error) {
1780
+ if (error instanceof GitHubError || error instanceof GitError) {
1781
+ throw error;
1782
+ }
1783
+ throw new GitHubError("Failed to fetch PRs from GitHub", {
1784
+ originalError: error.message,
1785
+ days
1786
+ });
1787
+ }
1788
+ }
1789
+ /**
1790
+ * Get merged PRs by current user (PRs authored by the current user)
1791
+ */
1792
+ async getPRsByCurrentUser(options = {}) {
1793
+ const currentUser = await this.getCurrentGitHubUser();
1794
+ if (!currentUser) {
1795
+ logger.warning("Could not determine GitHub user, returning all PRs");
1796
+ return this.getMergedPRs(options);
1797
+ }
1798
+ logger.debug(`Filtering PRs by author: ${currentUser}`);
1799
+ return this.getMergedPRs({
1800
+ ...options,
1801
+ author: currentUser
1802
+ });
1803
+ }
1804
+ /**
1805
+ * Transform a GitHub PR into a GitCommit structure
1806
+ * This allows PR data to work with existing commit-based UI and API
1807
+ */
1808
+ transformPRToCommit(pr) {
1809
+ const title = pr.title;
1810
+ const body = pr.body || "";
1811
+ const truncatedBody = body.length > this.MAX_BODY_LENGTH ? body.substring(0, this.MAX_BODY_LENGTH) + "...[truncated]" : body;
1812
+ const message = truncatedBody ? `${title}
1813
+
1814
+ ${truncatedBody}` : title;
1815
+ return {
1816
+ sha: `pr-${pr.number}`,
1817
+ message,
1818
+ author: pr.author.login,
1819
+ authorEmail: "",
1820
+ // Not available from gh PR API
1821
+ date: pr.mergedAt,
1822
+ diffStats: {
1823
+ filesChanged: pr.changedFiles,
1824
+ insertions: pr.additions,
1825
+ deletions: pr.deletions
1826
+ }
1827
+ };
1828
+ }
1829
+ };
1830
+ var githubService = new GitHubService();
1831
+
1622
1832
  // src/commands/scan.ts
1623
1833
  init_api_service();
1624
1834
  init_auth_service();
@@ -1635,7 +1845,13 @@ import chalk5 from "chalk";
1635
1845
  import Table from "cli-table3";
1636
1846
  import terminalLink from "terminal-link";
1637
1847
  function formatCommitChoice(commit) {
1638
- const sha = chalk5.yellow(commit.sha.substring(0, 7));
1848
+ let displaySha;
1849
+ if (commit.sha.startsWith("pr-")) {
1850
+ const prNumber = commit.sha.replace("pr-", "#");
1851
+ displaySha = chalk5.yellow(prNumber);
1852
+ } else {
1853
+ displaySha = chalk5.yellow(commit.sha.substring(0, 7));
1854
+ }
1639
1855
  const message = commit.message.split("\n")[0];
1640
1856
  const author = chalk5.gray(`by ${commit.author}`);
1641
1857
  const date = chalk5.gray(new Date(commit.date).toLocaleDateString());
@@ -1646,7 +1862,7 @@ function formatCommitChoice(commit) {
1646
1862
  ` [${filesChanged} files, ${chalk5.green(`+${insertions}`)} ${chalk5.red(`-${deletions}`)}]`
1647
1863
  );
1648
1864
  }
1649
- return `${sha} ${message}${stats}
1865
+ return `${displaySha} ${message}${stats}
1650
1866
  ${author} \u2022 ${date}`;
1651
1867
  }
1652
1868
  function formatRefinedCommitsTable(commits) {
@@ -1721,7 +1937,7 @@ async function promptSelectCommits(commits) {
1721
1937
  checked: false
1722
1938
  }));
1723
1939
  const selected = await checkbox({
1724
- message: "Select commits to brag about (use space to select, enter to confirm):",
1940
+ message: "Select PRs to brag about (use space to select, enter to confirm):",
1725
1941
  choices,
1726
1942
  pageSize: 10,
1727
1943
  loop: false
@@ -1743,7 +1959,7 @@ async function promptDaysToScan(defaultDays = 30) {
1743
1959
  { name: "Custom", value: "custom", description: "Enter custom number of days" }
1744
1960
  ];
1745
1961
  const selected = await select({
1746
- message: "How many days back should we scan for commits?",
1962
+ message: "How many days back should we scan for PRs?",
1747
1963
  choices,
1748
1964
  default: "30"
1749
1965
  });
@@ -1775,8 +1991,8 @@ function createSpinner(text) {
1775
1991
  spinner: "dots"
1776
1992
  });
1777
1993
  }
1778
- function fetchingCommitsSpinner(days) {
1779
- return createSpinner(`Fetching commits from the last ${days} days...`);
1994
+ function fetchingPRsSpinner(days) {
1995
+ return createSpinner(`Fetching merged PRs from the last ${days} days...`);
1780
1996
  }
1781
1997
  function refiningCommitsSpinner(count) {
1782
1998
  return createSpinner(`Refining ${count} commit${count > 1 ? "s" : ""} with AI...`);
@@ -1823,9 +2039,9 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1823
2039
  );
1824
2040
  process.exit(1);
1825
2041
  }
1826
- await gitService.validateRepository();
1827
- const repoInfo = await gitService.getRepositoryInfo();
1828
- logger.info(`Repository: ${chalk7.cyan(repoInfo.currentBranch)} branch`);
2042
+ await githubService.validateGitHubRepository();
2043
+ const repoInfo = await githubService.getRepositoryInfo();
2044
+ logger.info(`Repository: ${chalk7.cyan(repoInfo.fullName)} on GitHub`);
1829
2045
  logger.log("");
1830
2046
  let days = options.days;
1831
2047
  if (!days) {
@@ -1833,21 +2049,22 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1833
2049
  days = await promptDaysToScan(defaultDays);
1834
2050
  logger.log("");
1835
2051
  }
1836
- const spinner = fetchingCommitsSpinner(days);
2052
+ const spinner = fetchingPRsSpinner(days);
1837
2053
  spinner.start();
1838
- let commits;
2054
+ let prs;
1839
2055
  if (options.all) {
1840
- commits = await gitService.getCommitsWithStats({ days });
2056
+ prs = await githubService.getMergedPRs({ days });
1841
2057
  } else {
1842
- commits = await gitService.getCommitsByCurrentUser({ days });
2058
+ prs = await githubService.getPRsByCurrentUser({ days });
1843
2059
  }
2060
+ const commits = prs.map((pr) => githubService.transformPRToCommit(pr));
1844
2061
  if (commits.length === 0) {
1845
- failSpinner(spinner, `No commits found in the last ${days} days`);
2062
+ failSpinner(spinner, `No merged PRs found in the last ${days} days`);
1846
2063
  logger.log("");
1847
- logger.info("Try increasing the number of days or check your git configuration");
2064
+ logger.info("Try increasing the number of days or check your GitHub activity");
1848
2065
  return;
1849
2066
  }
1850
- succeedSpinner(spinner, `Found ${commits.length} commit${commits.length > 1 ? "s" : ""}`);
2067
+ succeedSpinner(spinner, `Found ${commits.length} PR${commits.length > 1 ? "s" : ""}`);
1851
2068
  logger.log("");
1852
2069
  logger.log(formatCommitStats(commits));
1853
2070
  logger.log("");
@@ -1858,9 +2075,7 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1858
2075
  }
1859
2076
  const selectedCommits = commits.filter((c) => selectedShas.includes(c.sha));
1860
2077
  logger.log("");
1861
- logger.success(
1862
- `Selected ${selectedCommits.length} commit${selectedCommits.length > 1 ? "s" : ""}`
1863
- );
2078
+ logger.success(`Selected ${selectedCommits.length} PR${selectedCommits.length > 1 ? "s" : ""}`);
1864
2079
  logger.log("");
1865
2080
  const refineSpinner = refiningCommitsSpinner(selectedCommits.length);
1866
2081
  refineSpinner.start();
@@ -1879,7 +2094,7 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1879
2094
  };
1880
2095
  const refineResponse = await apiService.refineCommits(refineRequest);
1881
2096
  const refinedCommits = refineResponse.refined_commits;
1882
- succeedSpinner(refineSpinner, "Commits refined successfully");
2097
+ succeedSpinner(refineSpinner, "PRs refined successfully");
1883
2098
  logger.log("");
1884
2099
  logger.info("Preview of refined brags:");
1885
2100
  logger.log("");
@@ -1901,7 +2116,7 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1901
2116
  title: refined.refined_title,
1902
2117
  description: refined.refined_description,
1903
2118
  tags: refined.suggested_tags,
1904
- repository: repoInfo.remoteUrl,
2119
+ repository: repoInfo.url,
1905
2120
  date: originalCommit?.date || (/* @__PURE__ */ new Date()).toISOString(),
1906
2121
  commit_url: refined.commit_url,
1907
2122
  impact_score: refined.impact_score,
@@ -1935,8 +2150,11 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1935
2150
  }
1936
2151
  }
1937
2152
  function getErrorHint2(error) {
2153
+ if (error.name === "GitHubError") {
2154
+ return 'Make sure you are in a GitHub repository and have authenticated with "gh auth login"';
2155
+ }
1938
2156
  if (error.name === "GitError") {
1939
- return "Make sure you are in a git repository with commits";
2157
+ return "Make sure you are in a git repository. Note: Only GitHub repositories are supported for PR scanning.";
1940
2158
  }
1941
2159
  if (error.name === "TokenExpiredError" || error.name === "AuthenticationError") {
1942
2160
  return 'Run "bragduck init" to login again';