gh-tldr 1.1.2 → 1.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.
- package/README.md +18 -2
- package/dist/index.js +107 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,10 +25,13 @@ That's it. Follow the prompts.
|
|
|
25
25
|
## Features
|
|
26
26
|
|
|
27
27
|
- 📊 Summarizes PRs, reviews, commits, and issues
|
|
28
|
+
- 📈 Tracks lines of code changed (additions/deletions)
|
|
28
29
|
- 🤖 Powered by Claude AI for natural language summaries
|
|
30
|
+
- 🎯 Custom prompt support for focused summaries
|
|
29
31
|
- 🔄 Interactive or scripted mode
|
|
30
32
|
- 📝 Multiple output formats (plain text, markdown, slack)
|
|
31
33
|
- 🔒 Private repository support
|
|
34
|
+
- 🏢 Organization/scope filtering
|
|
32
35
|
- 🌍 English and German output
|
|
33
36
|
|
|
34
37
|
## Prerequisites
|
|
@@ -100,9 +103,12 @@ gh-tldr
|
|
|
100
103
|
? GitHub username (leave empty for authenticated user)
|
|
101
104
|
? Time period › Last 24 hours / Last 7 days / Last 30 days
|
|
102
105
|
? Language › English / German
|
|
106
|
+
? Summary verbosity › Brief / Normal / Detailed
|
|
103
107
|
? Output format › Plain text / Markdown / Slack
|
|
104
108
|
? Include private repos? (y/N)
|
|
109
|
+
? Filter by scope › All / org-name / username
|
|
105
110
|
? Claude model (leave empty for default)
|
|
111
|
+
? Any specific focus for the summary? (optional)
|
|
106
112
|
```
|
|
107
113
|
|
|
108
114
|
### Direct Mode
|
|
@@ -116,8 +122,11 @@ gh-tldr [username] [options]
|
|
|
116
122
|
| `-d, --days <n>` | Time period in days (default: 1) |
|
|
117
123
|
| `-e, --english` | Output in English (default: German) |
|
|
118
124
|
| `-f, --format <type>` | Output: `plain` \| `markdown` \| `slack` |
|
|
125
|
+
| `-v, --verbosity <level>` | Summary length: `brief` \| `normal` \| `detailed` |
|
|
119
126
|
| `-p, --public-only` | Exclude private repositories |
|
|
127
|
+
| `-o, --orgs <orgs>` | Filter by organizations/accounts (comma-separated) |
|
|
120
128
|
| `-m, --model <model>` | Claude model (e.g., haiku, sonnet, opus) |
|
|
129
|
+
| `-P, --prompt <text>` | Custom instructions for Claude |
|
|
121
130
|
| `-i, --interactive` | Force interactive mode |
|
|
122
131
|
| `-h, --help` | Show help |
|
|
123
132
|
|
|
@@ -130,8 +139,14 @@ gh-tldr --days 7 --english
|
|
|
130
139
|
# Specific user, public repos only
|
|
131
140
|
gh-tldr yungweng --public-only
|
|
132
141
|
|
|
133
|
-
#
|
|
134
|
-
gh-tldr --
|
|
142
|
+
# Filter by organization
|
|
143
|
+
gh-tldr --orgs my-company,my-org
|
|
144
|
+
|
|
145
|
+
# Custom focus for standup
|
|
146
|
+
gh-tldr -P "Focus on bug fixes and blockers"
|
|
147
|
+
|
|
148
|
+
# Brief summary with Haiku model
|
|
149
|
+
gh-tldr --verbosity brief --model haiku
|
|
135
150
|
|
|
136
151
|
# Markdown output for documentation
|
|
137
152
|
gh-tldr --days 30 --format markdown
|
|
@@ -147,6 +162,7 @@ tl;dr 28.12.2025
|
|
|
147
162
|
• 2 PRs merged (repo-a)
|
|
148
163
|
• 1 issue closed (repo-d)
|
|
149
164
|
• 12 commits (repo-a, repo-b)
|
|
165
|
+
• +1,234 / -567 lines changed (15 files)
|
|
150
166
|
|
|
151
167
|
Repos: org/repo-a, org/repo-b, org/repo-c, org/repo-d
|
|
152
168
|
|
package/dist/index.js
CHANGED
|
@@ -12,19 +12,24 @@ var wordLimits = {
|
|
|
12
12
|
normal: { en: "50-80 word", de: "50-80 W\xF6rter" },
|
|
13
13
|
detailed: { en: "150-200 word", de: "150-200 W\xF6rter" }
|
|
14
14
|
};
|
|
15
|
-
function buildPrompt(lang, verbosity) {
|
|
15
|
+
function buildPrompt(lang, verbosity, customPrompt) {
|
|
16
16
|
const limit = wordLimits[verbosity][lang];
|
|
17
|
+
const customSection = customPrompt?.trim() ? lang === "en" ? `
|
|
18
|
+
|
|
19
|
+
Additional focus: ${customPrompt}` : `
|
|
20
|
+
|
|
21
|
+
Zus\xE4tzlicher Fokus: ${customPrompt}` : "";
|
|
17
22
|
if (lang === "en") {
|
|
18
|
-
return `Based on this GitHub activity data, write a summary of what was accomplished. STRICT LIMIT: ${limit}. Mention specific PR/issue titles. Casual tone, no bullet points, no emojis
|
|
23
|
+
return `Based on this GitHub activity data, write a summary of what was accomplished. STRICT LIMIT: ${limit}. Mention specific PR/issue titles. If stats are available, include the lines of code changed (additions/deletions) as a brief mention. Casual tone, no bullet points, no emojis.${customSection}
|
|
19
24
|
|
|
20
25
|
GitHub Activity Data:`;
|
|
21
26
|
}
|
|
22
|
-
return `Basierend auf diesen GitHub-Aktivit\xE4tsdaten, schreibe eine Zusammenfassung was gemacht wurde. STRIKTES LIMIT: ${limit}. Erw\xE4hne konkret die PR/Issue-Titel. Lockerer Ton, keine Aufz\xE4hlungen, keine Emojis
|
|
27
|
+
return `Basierend auf diesen GitHub-Aktivit\xE4tsdaten, schreibe eine Zusammenfassung was gemacht wurde. STRIKTES LIMIT: ${limit}. Erw\xE4hne konkret die PR/Issue-Titel. Falls Stats verf\xFCgbar sind, erw\xE4hne kurz die ge\xE4nderten Codezeilen (Additions/Deletions). Lockerer Ton, keine Aufz\xE4hlungen, keine Emojis.${customSection}
|
|
23
28
|
|
|
24
29
|
GitHub-Aktivit\xE4tsdaten:`;
|
|
25
30
|
}
|
|
26
|
-
async function generateSummaryText(activity, lang, verbosity = "normal", model) {
|
|
27
|
-
const prompt = buildPrompt(lang, verbosity);
|
|
31
|
+
async function generateSummaryText(activity, lang, verbosity = "normal", model, customPrompt) {
|
|
32
|
+
const prompt = buildPrompt(lang, verbosity, customPrompt);
|
|
28
33
|
const fullPrompt = `${prompt}
|
|
29
34
|
${JSON.stringify(activity, null, 2)}`;
|
|
30
35
|
const args = ["-p", "-", "--output-format", "text"];
|
|
@@ -111,6 +116,59 @@ function parseCommit(item) {
|
|
|
111
116
|
date: item.commit.author.date
|
|
112
117
|
};
|
|
113
118
|
}
|
|
119
|
+
async function fetchPRDetails(org, repo, number) {
|
|
120
|
+
const { stdout } = await execa2("gh", [
|
|
121
|
+
"api",
|
|
122
|
+
`repos/${org}/${repo}/pulls/${number}`
|
|
123
|
+
]);
|
|
124
|
+
const data = JSON.parse(stdout);
|
|
125
|
+
return {
|
|
126
|
+
additions: data.additions,
|
|
127
|
+
deletions: data.deletions,
|
|
128
|
+
changedFiles: data.changed_files
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
async function enrichPRsWithStats(prs) {
|
|
132
|
+
const results = await Promise.allSettled(
|
|
133
|
+
prs.map(async (pr) => {
|
|
134
|
+
const stats = await fetchPRDetails(pr.org, pr.repo, pr.number);
|
|
135
|
+
return { ...pr, ...stats };
|
|
136
|
+
})
|
|
137
|
+
);
|
|
138
|
+
return results.map((result, index) => {
|
|
139
|
+
if (result.status === "fulfilled") {
|
|
140
|
+
return result.value;
|
|
141
|
+
}
|
|
142
|
+
return prs[index];
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function calculateStats(prs) {
|
|
146
|
+
const seen = /* @__PURE__ */ new Set();
|
|
147
|
+
const uniquePRs = prs.filter((pr) => {
|
|
148
|
+
const key = `${pr.org}/${pr.repo}#${pr.number}`;
|
|
149
|
+
if (seen.has(key)) return false;
|
|
150
|
+
seen.add(key);
|
|
151
|
+
return true;
|
|
152
|
+
});
|
|
153
|
+
const totalAdditions = uniquePRs.reduce(
|
|
154
|
+
(sum, pr) => sum + (pr.additions ?? 0),
|
|
155
|
+
0
|
|
156
|
+
);
|
|
157
|
+
const totalDeletions = uniquePRs.reduce(
|
|
158
|
+
(sum, pr) => sum + (pr.deletions ?? 0),
|
|
159
|
+
0
|
|
160
|
+
);
|
|
161
|
+
const totalChangedFiles = uniquePRs.reduce(
|
|
162
|
+
(sum, pr) => sum + (pr.changedFiles ?? 0),
|
|
163
|
+
0
|
|
164
|
+
);
|
|
165
|
+
return {
|
|
166
|
+
totalAdditions,
|
|
167
|
+
totalDeletions,
|
|
168
|
+
totalChangedFiles,
|
|
169
|
+
netLines: totalAdditions - totalDeletions
|
|
170
|
+
};
|
|
171
|
+
}
|
|
114
172
|
async function getAuthenticatedUser() {
|
|
115
173
|
const { stdout } = await execa2("gh", ["api", "user", "--jq", ".login"]);
|
|
116
174
|
return stdout.trim();
|
|
@@ -200,12 +258,17 @@ async function fetchGitHubActivity(username, days, publicOnly, filterOrgs = null
|
|
|
200
258
|
}),
|
|
201
259
|
fetchReposCreatedSince(username, since, publicOnly, filterOrgs)
|
|
202
260
|
]);
|
|
203
|
-
const
|
|
204
|
-
const
|
|
261
|
+
const prs_created_raw = prsCreatedItems.map(parsePR);
|
|
262
|
+
const prs_merged_raw = prsMergedItems.map(parsePR);
|
|
205
263
|
const prs_reviewed = prsReviewedItems.map(parsePR);
|
|
206
264
|
const issues_created = issuesCreatedItems.map(parseIssue);
|
|
207
265
|
const issues_closed = issuesClosedItems.map(parseIssue);
|
|
208
266
|
const commits = commitsItems.map(parseCommit);
|
|
267
|
+
const [prs_created, prs_merged] = await Promise.all([
|
|
268
|
+
enrichPRsWithStats(prs_created_raw),
|
|
269
|
+
enrichPRsWithStats(prs_merged_raw)
|
|
270
|
+
]);
|
|
271
|
+
const stats = calculateStats([...prs_created, ...prs_merged]);
|
|
209
272
|
const allRepos = [
|
|
210
273
|
...prs_created,
|
|
211
274
|
...prs_merged,
|
|
@@ -227,7 +290,8 @@ async function fetchGitHubActivity(username, days, publicOnly, filterOrgs = null
|
|
|
227
290
|
issues_closed,
|
|
228
291
|
commits,
|
|
229
292
|
repos_created,
|
|
230
|
-
repos_touched
|
|
293
|
+
repos_touched,
|
|
294
|
+
stats
|
|
231
295
|
};
|
|
232
296
|
}
|
|
233
297
|
|
|
@@ -295,6 +359,10 @@ async function runInteractive() {
|
|
|
295
359
|
message: "Claude model (leave empty for default)",
|
|
296
360
|
default: ""
|
|
297
361
|
});
|
|
362
|
+
const customPrompt = await input({
|
|
363
|
+
message: "Any specific focus for the summary? (optional)",
|
|
364
|
+
default: ""
|
|
365
|
+
});
|
|
298
366
|
return {
|
|
299
367
|
username,
|
|
300
368
|
days,
|
|
@@ -303,7 +371,8 @@ async function runInteractive() {
|
|
|
303
371
|
format,
|
|
304
372
|
includePrivate,
|
|
305
373
|
selectedOrgs,
|
|
306
|
-
model
|
|
374
|
+
model,
|
|
375
|
+
customPrompt
|
|
307
376
|
};
|
|
308
377
|
}
|
|
309
378
|
|
|
@@ -344,6 +413,23 @@ function getRepoNames(items) {
|
|
|
344
413
|
const repos = [...new Set(items.map((i) => i.repo))];
|
|
345
414
|
return repos.join(", ");
|
|
346
415
|
}
|
|
416
|
+
function formatNumber(n) {
|
|
417
|
+
return n.toLocaleString("en-US");
|
|
418
|
+
}
|
|
419
|
+
function formatLinesChanged(stats, lang, format) {
|
|
420
|
+
if (!stats || stats.totalAdditions === 0 && stats.totalDeletions === 0) {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
const additions = formatNumber(stats.totalAdditions);
|
|
424
|
+
const deletions = formatNumber(stats.totalDeletions);
|
|
425
|
+
const files = formatNumber(stats.totalChangedFiles);
|
|
426
|
+
const filesLabel = lang === "en" ? "files" : "Dateien";
|
|
427
|
+
const text = `+${additions} / -${deletions} lines (${files} ${filesLabel})`;
|
|
428
|
+
if (format === "markdown") {
|
|
429
|
+
return `- **${text}**`;
|
|
430
|
+
}
|
|
431
|
+
return `\u2022 ${text}`;
|
|
432
|
+
}
|
|
347
433
|
function formatActivityLine(count, labelEn, labelDe, repos, lang, format) {
|
|
348
434
|
if (count === 0) return null;
|
|
349
435
|
const label = lang === "en" ? labelEn : labelDe;
|
|
@@ -414,7 +500,8 @@ function formatActivity(activity, format, lang) {
|
|
|
414
500
|
activity.repos_created.map((r) => r.name).join(", "),
|
|
415
501
|
lang,
|
|
416
502
|
format
|
|
417
|
-
)
|
|
503
|
+
),
|
|
504
|
+
formatLinesChanged(activity.stats, lang, format)
|
|
418
505
|
].filter(Boolean);
|
|
419
506
|
if (activityLines.length === 0) {
|
|
420
507
|
const noActivity = lang === "en" ? `No GitHub activity in the ${activity.period}.` : `Keine GitHub-Aktivit\xE4t in den ${activity.period}.`;
|
|
@@ -478,7 +565,7 @@ function validateVerbosity(value) {
|
|
|
478
565
|
const valid = ["brief", "normal", "detailed"];
|
|
479
566
|
return valid.includes(value) ? value : "normal";
|
|
480
567
|
}
|
|
481
|
-
async function execute(username, days, lang, format, publicOnly, verbosity, filterOrgs, model) {
|
|
568
|
+
async function execute(username, days, lang, format, publicOnly, verbosity, filterOrgs, model, customPrompt) {
|
|
482
569
|
const resolvedUsername = username || await getAuthenticatedUser();
|
|
483
570
|
const scopeInfo = filterOrgs ? ` in ${filterOrgs.join(", ")}` : "";
|
|
484
571
|
console.error(
|
|
@@ -506,7 +593,8 @@ async function execute(username, days, lang, format, publicOnly, verbosity, filt
|
|
|
506
593
|
activity,
|
|
507
594
|
lang,
|
|
508
595
|
verbosity,
|
|
509
|
-
model
|
|
596
|
+
model,
|
|
597
|
+
customPrompt
|
|
510
598
|
);
|
|
511
599
|
console.log("");
|
|
512
600
|
console.log(stats);
|
|
@@ -530,6 +618,9 @@ async function run() {
|
|
|
530
618
|
).option(
|
|
531
619
|
"-m, --model <model>",
|
|
532
620
|
"Claude model to use (e.g., sonnet, opus, haiku)"
|
|
621
|
+
).option(
|
|
622
|
+
"-P, --prompt <text>",
|
|
623
|
+
"Custom instructions for Claude to consider when summarizing"
|
|
533
624
|
).action(async (username, options) => {
|
|
534
625
|
try {
|
|
535
626
|
await checkDependencies();
|
|
@@ -545,7 +636,8 @@ async function run() {
|
|
|
545
636
|
!answers.includePrivate,
|
|
546
637
|
answers.verbosity,
|
|
547
638
|
answers.selectedOrgs,
|
|
548
|
-
answers.model || void 0
|
|
639
|
+
answers.model || void 0,
|
|
640
|
+
answers.customPrompt || void 0
|
|
549
641
|
);
|
|
550
642
|
} else {
|
|
551
643
|
const days = parseInt(options.days, 10);
|
|
@@ -560,7 +652,8 @@ async function run() {
|
|
|
560
652
|
options.publicOnly,
|
|
561
653
|
validateVerbosity(options.verbosity),
|
|
562
654
|
filterOrgs && filterOrgs.length > 0 ? filterOrgs : null,
|
|
563
|
-
options.model
|
|
655
|
+
options.model,
|
|
656
|
+
options.prompt
|
|
564
657
|
);
|
|
565
658
|
}
|
|
566
659
|
} catch (error) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/claude.ts","../src/github.ts","../src/interactive.ts","../src/output.ts","../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport { generateSummaryText } from \"./claude.js\";\nimport { fetchGitHubActivity, getAuthenticatedUser } from \"./github.js\";\nimport { runInteractive } from \"./interactive.js\";\nimport { formatActivity, hasActivity } from \"./output.js\";\nimport type { Language, OutputFormat, Verbosity } from \"./types.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nasync function checkDependencies(): Promise<void> {\n\tconst { execa } = await import(\"execa\");\n\n\tconst deps = [\n\t\t{ cmd: \"gh\", name: \"GitHub CLI\", installHint: \"brew install gh\" },\n\t\t{\n\t\t\tcmd: \"claude\",\n\t\t\tname: \"Claude Code CLI\",\n\t\t\tinstallHint: \"npm install -g @anthropic-ai/claude-code\",\n\t\t},\n\t];\n\n\tconst missing: string[] = [];\n\n\tfor (const dep of deps) {\n\t\ttry {\n\t\t\tawait execa(\"which\", [dep.cmd]);\n\t\t} catch {\n\t\t\tmissing.push(`${dep.name} (${dep.installHint})`);\n\t\t}\n\t}\n\n\tif (missing.length > 0) {\n\t\tconsole.error(chalk.red(\"Missing dependencies:\"));\n\t\tfor (const m of missing) {\n\t\t\tconsole.error(` - ${m}`);\n\t\t}\n\t\tprocess.exit(1);\n\t}\n\n\t// Check gh auth\n\ttry {\n\t\tawait execa(\"gh\", [\"auth\", \"status\"]);\n\t} catch {\n\t\tconsole.error(\n\t\t\tchalk.red(\"GitHub CLI not authenticated. Run 'gh auth login'.\"),\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n\ninterface CliOptions {\n\tdays: string;\n\tenglish: boolean;\n\tformat: OutputFormat;\n\tpublicOnly: boolean;\n\tinteractive: boolean;\n\tverbosity: string;\n\torgs?: string;\n\tmodel?: string;\n}\n\nfunction validateVerbosity(value: string): Verbosity {\n\tconst valid: Verbosity[] = [\"brief\", \"normal\", \"detailed\"];\n\treturn valid.includes(value as Verbosity) ? (value as Verbosity) : \"normal\";\n}\n\nasync function execute(\n\tusername: string,\n\tdays: number,\n\tlang: Language,\n\tformat: OutputFormat,\n\tpublicOnly: boolean,\n\tverbosity: Verbosity,\n\tfilterOrgs: string[] | null,\n\tmodel?: string,\n): Promise<void> {\n\t// Resolve username\n\tconst resolvedUsername = username || (await getAuthenticatedUser());\n\n\tconst scopeInfo = filterOrgs ? ` in ${filterOrgs.join(\", \")}` : \"\";\n\tconsole.error(\n\t\tchalk.yellow(\n\t\t\t`Fetching GitHub activity for ${resolvedUsername}${scopeInfo}...`,\n\t\t),\n\t);\n\n\tconst activity = await fetchGitHubActivity(\n\t\tresolvedUsername,\n\t\tdays,\n\t\tpublicOnly,\n\t\tfilterOrgs,\n\t);\n\n\tif (!hasActivity(activity)) {\n\t\tconsole.log(\"\");\n\t\tconsole.log(`tl;dr ${activity.date}`);\n\t\tconsole.log(\"\");\n\t\tconst noActivity =\n\t\t\tlang === \"en\"\n\t\t\t\t? `No GitHub activity in the ${activity.period}.`\n\t\t\t\t: `Keine GitHub-Aktivität in den ${activity.period}.`;\n\t\tconsole.log(noActivity);\n\t\treturn;\n\t}\n\n\t// Format stats locally\n\tconst stats = formatActivity(activity, format, lang);\n\n\tconsole.error(chalk.yellow(\"Generating summary with Claude...\"));\n\n\t// Only ask Claude for the summary paragraph\n\tconst summaryText = await generateSummaryText(\n\t\tactivity,\n\t\tlang,\n\t\tverbosity,\n\t\tmodel,\n\t);\n\n\tconsole.log(\"\");\n\tconsole.log(stats);\n\tconsole.log(\"\");\n\tconsole.log(\"---\");\n\tconsole.log(summaryText);\n}\n\nexport async function run(): Promise<void> {\n\tconst program = new Command();\n\n\tprogram\n\t\t.name(\"gh-tldr\")\n\t\t.description(\"Generate a TL;DR summary of your GitHub activity\")\n\t\t.version(version)\n\t\t.argument(\"[username]\", \"GitHub username (defaults to authenticated user)\")\n\t\t.option(\"-d, --days <n>\", \"Time period in days\", \"1\")\n\t\t.option(\"-e, --english\", \"Output in English (default: German)\", false)\n\t\t.option(\n\t\t\t\"-f, --format <type>\",\n\t\t\t\"Output format: slack|markdown|plain\",\n\t\t\t\"slack\",\n\t\t)\n\t\t.option(\"-p, --public-only\", \"Exclude private repositories\", false)\n\t\t.option(\"-i, --interactive\", \"Force interactive mode\", false)\n\t\t.option(\n\t\t\t\"-v, --verbosity <level>\",\n\t\t\t\"Summary verbosity: brief|normal|detailed\",\n\t\t\t\"normal\",\n\t\t)\n\t\t.option(\n\t\t\t\"-o, --orgs <orgs>\",\n\t\t\t\"Filter by organizations/accounts (comma-separated)\",\n\t\t)\n\t\t.option(\n\t\t\t\"-m, --model <model>\",\n\t\t\t\"Claude model to use (e.g., sonnet, opus, haiku)\",\n\t\t)\n\t\t.action(async (username: string | undefined, options: CliOptions) => {\n\t\t\ttry {\n\t\t\t\tawait checkDependencies();\n\n\t\t\t\t// Determine if we should run interactive mode\n\t\t\t\tconst hasArgs = process.argv.length > 2;\n\t\t\t\tconst forceInteractive = options.interactive;\n\n\t\t\t\tif (!hasArgs || forceInteractive) {\n\t\t\t\t\t// Interactive mode\n\t\t\t\t\tconst answers = await runInteractive();\n\t\t\t\t\tawait execute(\n\t\t\t\t\t\tanswers.username,\n\t\t\t\t\t\tanswers.days,\n\t\t\t\t\t\tanswers.language,\n\t\t\t\t\t\tanswers.format,\n\t\t\t\t\t\t!answers.includePrivate,\n\t\t\t\t\t\tanswers.verbosity,\n\t\t\t\t\t\tanswers.selectedOrgs,\n\t\t\t\t\t\tanswers.model || undefined,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Direct mode\n\t\t\t\t\tconst days = parseInt(options.days, 10);\n\t\t\t\t\tconst lang: Language = options.english ? \"en\" : \"de\";\n\t\t\t\t\tconst format = options.format as OutputFormat;\n\n\t\t\t\t\t// Parse orgs flag\n\t\t\t\t\tconst filterOrgs = options.orgs\n\t\t\t\t\t\t? options.orgs\n\t\t\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t\t\t.map((o) => o.trim())\n\t\t\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t: null;\n\n\t\t\t\t\tawait execute(\n\t\t\t\t\t\tusername || \"\",\n\t\t\t\t\t\tdays,\n\t\t\t\t\t\tlang,\n\t\t\t\t\t\tformat,\n\t\t\t\t\t\toptions.publicOnly,\n\t\t\t\t\t\tvalidateVerbosity(options.verbosity),\n\t\t\t\t\t\tfilterOrgs && filterOrgs.length > 0 ? filterOrgs : null,\n\t\t\t\t\t\toptions.model,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconsole.error(chalk.red(`Error: ${error.message}`));\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t});\n\n\tawait program.parseAsync();\n}\n","import { execa } from \"execa\";\nimport type { GitHubActivity, Language, Verbosity } from \"./types.js\";\n\nconst wordLimits: Record<Verbosity, Record<Language, string>> = {\n\tbrief: { en: \"20-40 word\", de: \"20-40 Wörter\" },\n\tnormal: { en: \"50-80 word\", de: \"50-80 Wörter\" },\n\tdetailed: { en: \"150-200 word\", de: \"150-200 Wörter\" },\n};\n\nfunction buildPrompt(lang: Language, verbosity: Verbosity): string {\n\tconst limit = wordLimits[verbosity][lang];\n\n\tif (lang === \"en\") {\n\t\treturn `Based on this GitHub activity data, write a summary of what was accomplished. STRICT LIMIT: ${limit}. Mention specific PR/issue titles. Casual tone, no bullet points, no emojis.\n\nGitHub Activity Data:`;\n\t}\n\n\treturn `Basierend auf diesen GitHub-Aktivitätsdaten, schreibe eine Zusammenfassung was gemacht wurde. STRIKTES LIMIT: ${limit}. Erwähne konkret die PR/Issue-Titel. Lockerer Ton, keine Aufzählungen, keine Emojis.\n\nGitHub-Aktivitätsdaten:`;\n}\n\nexport async function generateSummaryText(\n\tactivity: GitHubActivity,\n\tlang: Language,\n\tverbosity: Verbosity = \"normal\",\n\tmodel?: string,\n): Promise<string> {\n\tconst prompt = buildPrompt(lang, verbosity);\n\tconst fullPrompt = `${prompt}\\n${JSON.stringify(activity, null, 2)}`;\n\n\tconst args = [\"-p\", \"-\", \"--output-format\", \"text\"];\n\tif (model) {\n\t\targs.push(\"--model\", model);\n\t}\n\n\tconst { stdout } = await execa(\"claude\", args, {\n\t\tinput: fullPrompt,\n\t});\n\n\treturn stdout.trim();\n}\n","import { execa } from \"execa\";\nimport type {\n\tCommit,\n\tGitHubActivity,\n\tIssue,\n\tPullRequest,\n\tRepoInfo,\n} from \"./types.js\";\n\nfunction getSinceDate(days: number): string {\n\tconst date = new Date();\n\tdate.setDate(date.getDate() - days);\n\treturn date.toISOString();\n}\n\nfunction formatDate(date: Date): string {\n\tconst day = date.getDate().toString().padStart(2, \"0\");\n\tconst month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n\tconst year = date.getFullYear();\n\treturn `${day}.${month}.${year}`;\n}\n\nasync function ghApi<T>(\n\tendpoint: string,\n\tparams: Record<string, string>,\n): Promise<T> {\n\tconst args = [\n\t\t\"api\",\n\t\t\"-X\",\n\t\t\"GET\",\n\t\tendpoint,\n\t\t...Object.entries(params).flatMap(([key, value]) => [\n\t\t\t\"-f\",\n\t\t\t`${key}=${value}`,\n\t\t]),\n\t];\n\n\tconst { stdout } = await execa(\"gh\", args);\n\treturn JSON.parse(stdout) as T;\n}\n\nasync function ghApiPaginated<T>(\n\tendpoint: string,\n\tparams: Record<string, string>,\n\tmaxPages: number = 10,\n): Promise<T[]> {\n\tconst allItems: T[] = [];\n\tlet page = 1;\n\n\twhile (page <= maxPages) {\n\t\tconst result = await ghApi<SearchResult<T>>(endpoint, {\n\t\t\t...params,\n\t\t\tpage: String(page),\n\t\t\tper_page: \"100\",\n\t\t});\n\n\t\tallItems.push(...result.items);\n\n\t\tif (result.items.length < 100) {\n\t\t\tbreak;\n\t\t}\n\t\tpage++;\n\t}\n\n\treturn allItems;\n}\n\ninterface SearchResult<T> {\n\ttotal_count?: number;\n\titems: T[];\n}\n\ninterface RawPR {\n\trepository_url: string;\n\ttitle: string;\n\tnumber: number;\n\tstate: string;\n\thtml_url: string;\n}\n\ninterface RawCommit {\n\trepository: {\n\t\tname: string;\n\t\towner: { login: string };\n\t};\n\tcommit: {\n\t\tmessage: string;\n\t\tauthor: { date: string };\n\t};\n\thtml_url: string;\n}\n\ninterface RawRepo {\n\tname: string;\n\towner: { login: string };\n\tcreated_at: string;\n\thtml_url: string;\n}\n\nfunction parsePR(item: RawPR): PullRequest {\n\tconst urlParts = item.repository_url.split(\"/\");\n\treturn {\n\t\trepo: urlParts[urlParts.length - 1],\n\t\torg: urlParts[urlParts.length - 2],\n\t\ttitle: item.title,\n\t\tnumber: item.number,\n\t\tstate: item.state,\n\t\turl: item.html_url,\n\t};\n}\n\nfunction parseIssue(item: RawPR): Issue {\n\tconst urlParts = item.repository_url.split(\"/\");\n\treturn {\n\t\trepo: urlParts[urlParts.length - 1],\n\t\torg: urlParts[urlParts.length - 2],\n\t\ttitle: item.title,\n\t\tnumber: item.number,\n\t\turl: item.html_url,\n\t};\n}\n\nfunction parseCommit(item: RawCommit): Commit {\n\treturn {\n\t\trepo: item.repository.name,\n\t\torg: item.repository.owner.login,\n\t\tmessage: item.commit.message.split(\"\\n\")[0],\n\t\turl: item.html_url,\n\t\tdate: item.commit.author.date,\n\t};\n}\n\nexport async function getAuthenticatedUser(): Promise<string> {\n\tconst { stdout } = await execa(\"gh\", [\"api\", \"user\", \"--jq\", \".login\"]);\n\treturn stdout.trim();\n}\n\nexport async function fetchUserOrgs(username: string): Promise<string[]> {\n\t// First try authenticated user's orgs (includes private memberships)\n\ttry {\n\t\tconst authUser = await getAuthenticatedUser();\n\t\tif (authUser === username) {\n\t\t\tconst { stdout } = await execa(\"gh\", [\n\t\t\t\t\"api\",\n\t\t\t\t\"user/orgs\",\n\t\t\t\t\"--jq\",\n\t\t\t\t\".[].login\",\n\t\t\t]);\n\t\t\treturn stdout.trim().split(\"\\n\").filter(Boolean);\n\t\t}\n\t} catch {\n\t\t// Fall through to public orgs\n\t}\n\n\t// Fallback to public orgs for other users\n\ttry {\n\t\tconst { stdout } = await execa(\"gh\", [\n\t\t\t\"api\",\n\t\t\t`users/${username}/orgs`,\n\t\t\t\"--jq\",\n\t\t\t\".[].login\",\n\t\t]);\n\t\treturn stdout.trim().split(\"\\n\").filter(Boolean);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nasync function fetchReposCreatedSince(\n\tusername: string,\n\tsince: string,\n\tpublicOnly: boolean,\n\tfilterOrgs: string[] | null,\n): Promise<RepoInfo[]> {\n\tconst sinceDate = new Date(since);\n\tconst repos: RepoInfo[] = [];\n\n\t// Determine which orgs to check\n\tconst orgsToCheck = filterOrgs ?? [\n\t\tusername,\n\t\t...(await fetchUserOrgs(username)),\n\t];\n\n\tfor (const org of orgsToCheck) {\n\t\ttry {\n\t\t\tconst isUser = org === username;\n\t\t\tconst endpoint = isUser\n\t\t\t\t? `users/${username}/repos?type=${publicOnly ? \"public\" : \"all\"}&sort=created&direction=desc&per_page=100`\n\t\t\t\t: `orgs/${org}/repos?sort=created&direction=desc&per_page=100`;\n\n\t\t\tconst { stdout } = await execa(\"gh\", [\"api\", endpoint]);\n\t\t\tconst orgRepos = JSON.parse(stdout) as RawRepo[];\n\t\t\tfor (const repo of orgRepos) {\n\t\t\t\tif (new Date(repo.created_at) >= sinceDate) {\n\t\t\t\t\trepos.push({ name: repo.name, org: repo.owner.login });\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore errors for individual orgs\n\t\t}\n\t}\n\n\t// Deduplicate\n\treturn repos.filter(\n\t\t(repo, index, self) =>\n\t\t\tself.findIndex((r) => r.name === repo.name && r.org === repo.org) ===\n\t\t\tindex,\n\t);\n}\n\nexport async function fetchGitHubActivity(\n\tusername: string,\n\tdays: number,\n\tpublicOnly: boolean,\n\tfilterOrgs: string[] | null = null,\n): Promise<GitHubActivity> {\n\tconst since = getSinceDate(days);\n\tconst today = formatDate(new Date());\n\tconst visibilityFilter = publicOnly ? \" is:public\" : \"\";\n\n\t// Build org filter string: \"org:X org:Y\" (implicit OR)\n\tconst orgFilter = filterOrgs\n\t\t? ` ${filterOrgs.map((o) => `org:${o}`).join(\" \")}`\n\t\t: \"\";\n\n\t// Fetch all data in parallel with pagination\n\tconst [\n\t\tprsCreatedItems,\n\t\tprsMergedItems,\n\t\tprsReviewedItems,\n\t\tissuesCreatedItems,\n\t\tissuesClosedItems,\n\t\tcommitsItems,\n\t\trepos_created,\n\t] = await Promise.all([\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:pr created:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:pr merged:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `reviewed-by:${username} type:pr created:>=${since} -author:${username}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:issue created:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:issue closed:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawCommit>(\"search/commits\", {\n\t\t\tq: `author:${username} committer-date:>=${since}${orgFilter}`,\n\t\t}),\n\t\tfetchReposCreatedSince(username, since, publicOnly, filterOrgs),\n\t]);\n\n\tconst prs_created = prsCreatedItems.map(parsePR);\n\tconst prs_merged = prsMergedItems.map(parsePR);\n\tconst prs_reviewed = prsReviewedItems.map(parsePR);\n\tconst issues_created = issuesCreatedItems.map(parseIssue);\n\tconst issues_closed = issuesClosedItems.map(parseIssue);\n\tconst commits = commitsItems.map(parseCommit);\n\n\t// Extract unique repos touched\n\tconst allRepos = [\n\t\t...prs_created,\n\t\t...prs_merged,\n\t\t...prs_reviewed,\n\t\t...issues_created,\n\t\t...issues_closed,\n\t\t...commits,\n\t].map((item) => `${item.org}/${item.repo}`);\n\n\tconst repos_touched = [...new Set(allRepos)];\n\n\tconst periodText =\n\t\tdays === 1\n\t\t\t? \"last 24 hours\"\n\t\t\t: days === 7\n\t\t\t\t? \"last 7 days\"\n\t\t\t\t: days === 30\n\t\t\t\t\t? \"last 30 days\"\n\t\t\t\t\t: `last ${days} days`;\n\n\treturn {\n\t\tuser: username,\n\t\tdate: today,\n\t\tperiod: periodText,\n\t\tprs_created,\n\t\tprs_merged,\n\t\tprs_reviewed,\n\t\tissues_created,\n\t\tissues_closed,\n\t\tcommits,\n\t\trepos_created,\n\t\trepos_touched,\n\t};\n}\n","import { confirm, input, select } from \"@inquirer/prompts\";\nimport { fetchUserOrgs, getAuthenticatedUser } from \"./github.js\";\nimport type { Language, OutputFormat, Verbosity } from \"./types.js\";\n\ninterface InteractiveOptions {\n\tusername: string;\n\tdays: number;\n\tlanguage: Language;\n\tverbosity: Verbosity;\n\tformat: OutputFormat;\n\tincludePrivate: boolean;\n\tselectedOrgs: string[] | null;\n\tmodel: string;\n}\n\nexport async function runInteractive(): Promise<InteractiveOptions> {\n\tconst username = await input({\n\t\tmessage: \"GitHub username (leave empty for authenticated user)\",\n\t\tdefault: \"\",\n\t});\n\n\tconst days = await select({\n\t\tmessage: \"Time period\",\n\t\tchoices: [\n\t\t\t{ name: \"Last 24 hours\", value: 1 },\n\t\t\t{ name: \"Last 7 days\", value: 7 },\n\t\t\t{ name: \"Last 30 days\", value: 30 },\n\t\t],\n\t\tdefault: 1,\n\t});\n\n\tconst language = await select({\n\t\tmessage: \"Language\",\n\t\tchoices: [\n\t\t\t{ name: \"English\", value: \"en\" as Language },\n\t\t\t{ name: \"German\", value: \"de\" as Language },\n\t\t],\n\t\tdefault: \"en\" as Language,\n\t});\n\n\tconst verbosity = await select({\n\t\tmessage: \"Summary verbosity\",\n\t\tchoices: [\n\t\t\t{ name: \"Brief (~30 words)\", value: \"brief\" as Verbosity },\n\t\t\t{ name: \"Normal (~60 words)\", value: \"normal\" as Verbosity },\n\t\t\t{ name: \"Detailed (~175 words)\", value: \"detailed\" as Verbosity },\n\t\t],\n\t\tdefault: \"normal\" as Verbosity,\n\t});\n\n\tconst format = await select({\n\t\tmessage: \"Output format\",\n\t\tchoices: [\n\t\t\t{ name: \"Plain text\", value: \"plain\" as OutputFormat },\n\t\t\t{ name: \"Markdown\", value: \"markdown\" as OutputFormat },\n\t\t\t{ name: \"Slack\", value: \"slack\" as OutputFormat },\n\t\t],\n\t\tdefault: \"plain\" as OutputFormat,\n\t});\n\n\tconst includePrivate = await confirm({\n\t\tmessage: \"Include private repos?\",\n\t\tdefault: true,\n\t});\n\n\t// Fetch available orgs for the user\n\tconst resolvedUsername = username || (await getAuthenticatedUser());\n\tconst userOrgs = await fetchUserOrgs(resolvedUsername);\n\tconst allScopes = [resolvedUsername, ...userOrgs];\n\n\t// Build choices with \"All\" as first option\n\tconst ALL_VALUE = \"__ALL__\";\n\tconst scopeChoices = [\n\t\t{ name: \"All (no filter)\", value: ALL_VALUE },\n\t\t...allScopes.map((org) => ({ name: org, value: org })),\n\t];\n\n\tconst scopeSelection = await select({\n\t\tmessage: \"Filter by scope\",\n\t\tchoices: scopeChoices,\n\t\tdefault: ALL_VALUE,\n\t});\n\n\t// If \"All\" selected, no filtering; otherwise filter to that single org\n\t// For multi-org selection, user can use CLI --orgs flag\n\tconst selectedOrgs = scopeSelection === ALL_VALUE ? null : [scopeSelection];\n\n\tconst model = await input({\n\t\tmessage: \"Claude model (leave empty for default)\",\n\t\tdefault: \"\",\n\t});\n\n\treturn {\n\t\tusername,\n\t\tdays,\n\t\tlanguage,\n\t\tverbosity,\n\t\tformat,\n\t\tincludePrivate,\n\t\tselectedOrgs,\n\t\tmodel,\n\t};\n}\n","import type {\n\tCommit,\n\tGitHubActivity,\n\tLanguage,\n\tOutputFormat,\n} from \"./types.js\";\n\n// Gap threshold: if gap between commits > 3 hours, treat as separate session\nconst GAP_THRESHOLD_MS = 3 * 60 * 60 * 1000;\n// Minimum time to count for a single-commit session (15 minutes)\nconst SINGLE_COMMIT_HOURS = 0.25;\n\nfunction calculateWorkSession(\n\tcommits: Commit[],\n\tlang: Language,\n): string | null {\n\tif (commits.length < 2) return null;\n\n\t// Sort timestamps chronologically\n\tconst timestamps = commits\n\t\t.map((c) => new Date(c.date).getTime())\n\t\t.sort((a, b) => a - b);\n\n\t// Group commits into sessions based on gap threshold\n\tconst sessions: number[][] = [];\n\tlet currentSession = [timestamps[0]];\n\n\tfor (let i = 1; i < timestamps.length; i++) {\n\t\tconst gap = timestamps[i] - timestamps[i - 1];\n\t\tif (gap > GAP_THRESHOLD_MS) {\n\t\t\tsessions.push(currentSession);\n\t\t\tcurrentSession = [timestamps[i]];\n\t\t} else {\n\t\t\tcurrentSession.push(timestamps[i]);\n\t\t}\n\t}\n\tsessions.push(currentSession);\n\n\t// Calculate total hours across all sessions\n\tlet totalHours = 0;\n\tfor (const session of sessions) {\n\t\tif (session.length === 1) {\n\t\t\ttotalHours += SINGLE_COMMIT_HOURS;\n\t\t} else {\n\t\t\tconst duration = session[session.length - 1] - session[0];\n\t\t\ttotalHours += duration / (1000 * 60 * 60);\n\t\t}\n\t}\n\n\t// Round to nearest 0.5 hours\n\tconst rounded = Math.round(totalHours * 2) / 2;\n\n\tif (rounded < 0.5) return null;\n\n\tconst label = lang === \"en\" ? \"Work session\" : \"Arbeitszeit\";\n\tconst hoursLabel =\n\t\trounded === 1\n\t\t\t? lang === \"en\"\n\t\t\t\t? \"hour\"\n\t\t\t\t: \"Stunde\"\n\t\t\t: lang === \"en\"\n\t\t\t\t? \"hours\"\n\t\t\t\t: \"Stunden\";\n\n\treturn `${label}: ~${rounded} ${hoursLabel}`;\n}\n\nfunction getRepoNames(items: { repo: string }[]): string {\n\tconst repos = [...new Set(items.map((i) => i.repo))];\n\treturn repos.join(\", \");\n}\n\nfunction formatActivityLine(\n\tcount: number,\n\tlabelEn: string,\n\tlabelDe: string,\n\trepos: string,\n\tlang: Language,\n\tformat: OutputFormat,\n): string | null {\n\tif (count === 0) return null;\n\n\tconst label = lang === \"en\" ? labelEn : labelDe;\n\tconst repoSuffix = repos ? ` (${repos})` : \"\";\n\n\tif (format === \"markdown\") {\n\t\treturn `- **${count}** ${label}${repoSuffix}`;\n\t}\n\treturn `• ${count} ${label}${repoSuffix}`;\n}\n\nexport function formatActivity(\n\tactivity: GitHubActivity,\n\tformat: OutputFormat,\n\tlang: Language,\n): string {\n\tconst lines: string[] = [];\n\n\t// Header\n\tconst headerPrefix = format === \"markdown\" ? \"## \" : \"\";\n\tlines.push(`${headerPrefix}tl;dr ${activity.date}`);\n\tlines.push(\"\");\n\n\tconst activityLines = [\n\t\tformatActivityLine(\n\t\t\tactivity.prs_created.length,\n\t\t\t\"PRs created\",\n\t\t\t\"PRs erstellt\",\n\t\t\tgetRepoNames(activity.prs_created),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.prs_reviewed.length,\n\t\t\t\"PRs reviewed\",\n\t\t\t\"PRs reviewed/approved\",\n\t\t\tgetRepoNames(activity.prs_reviewed),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.prs_merged.length,\n\t\t\t\"PRs merged\",\n\t\t\t\"PRs gemerged\",\n\t\t\tgetRepoNames(activity.prs_merged),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.issues_created.length,\n\t\t\t\"issues created\",\n\t\t\t\"Issues erstellt\",\n\t\t\tgetRepoNames(activity.issues_created),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.issues_closed.length,\n\t\t\t\"issues closed\",\n\t\t\t\"Issues geschlossen\",\n\t\t\tgetRepoNames(activity.issues_closed),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.commits.length,\n\t\t\t\"commits\",\n\t\t\t\"Commits\",\n\t\t\tgetRepoNames(activity.commits),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.repos_created.length,\n\t\t\t\"new repos created\",\n\t\t\t\"neue Repos erstellt\",\n\t\t\tactivity.repos_created.map((r) => r.name).join(\", \"),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t].filter(Boolean) as string[];\n\n\tif (activityLines.length === 0) {\n\t\tconst noActivity =\n\t\t\tlang === \"en\"\n\t\t\t\t? `No GitHub activity in the ${activity.period}.`\n\t\t\t\t: `Keine GitHub-Aktivität in den ${activity.period}.`;\n\t\tlines.push(noActivity);\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\tlines.push(...activityLines);\n\n\t// Work session duration\n\tconst workSession = calculateWorkSession(activity.commits, lang);\n\tif (workSession) {\n\t\tlines.push(format === \"markdown\" ? `- ${workSession}` : `• ${workSession}`);\n\t}\n\n\tlines.push(\"\");\n\n\t// Repos touched\n\tif (activity.repos_touched.length > 0) {\n\t\tconst reposLabel = lang === \"en\" ? \"Repos\" : \"Repos\";\n\t\tlines.push(`${reposLabel}: ${activity.repos_touched.join(\", \")}`);\n\t}\n\n\treturn lines.join(\"\\n\");\n}\n\nexport function hasActivity(activity: GitHubActivity): boolean {\n\treturn (\n\t\tactivity.prs_created.length +\n\t\t\tactivity.prs_merged.length +\n\t\t\tactivity.prs_reviewed.length +\n\t\t\tactivity.issues_created.length +\n\t\t\tactivity.issues_closed.length >\n\t\t0\n\t);\n}\n","// gh-tldr - Generate a TL;DR summary of your GitHub activity\n// Entry point: detects mode (interactive vs direct) and runs CLI\n\nimport { run } from \"./cli.js\";\n\nrun();\n"],"mappings":"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","names":["execa","require","execa"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/claude.ts","../src/github.ts","../src/interactive.ts","../src/output.ts","../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport { generateSummaryText } from \"./claude.js\";\nimport { fetchGitHubActivity, getAuthenticatedUser } from \"./github.js\";\nimport { runInteractive } from \"./interactive.js\";\nimport { formatActivity, hasActivity } from \"./output.js\";\nimport type { Language, OutputFormat, Verbosity } from \"./types.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nasync function checkDependencies(): Promise<void> {\n\tconst { execa } = await import(\"execa\");\n\n\tconst deps = [\n\t\t{ cmd: \"gh\", name: \"GitHub CLI\", installHint: \"brew install gh\" },\n\t\t{\n\t\t\tcmd: \"claude\",\n\t\t\tname: \"Claude Code CLI\",\n\t\t\tinstallHint: \"npm install -g @anthropic-ai/claude-code\",\n\t\t},\n\t];\n\n\tconst missing: string[] = [];\n\n\tfor (const dep of deps) {\n\t\ttry {\n\t\t\tawait execa(\"which\", [dep.cmd]);\n\t\t} catch {\n\t\t\tmissing.push(`${dep.name} (${dep.installHint})`);\n\t\t}\n\t}\n\n\tif (missing.length > 0) {\n\t\tconsole.error(chalk.red(\"Missing dependencies:\"));\n\t\tfor (const m of missing) {\n\t\t\tconsole.error(` - ${m}`);\n\t\t}\n\t\tprocess.exit(1);\n\t}\n\n\t// Check gh auth\n\ttry {\n\t\tawait execa(\"gh\", [\"auth\", \"status\"]);\n\t} catch {\n\t\tconsole.error(\n\t\t\tchalk.red(\"GitHub CLI not authenticated. Run 'gh auth login'.\"),\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n\ninterface CliOptions {\n\tdays: string;\n\tenglish: boolean;\n\tformat: OutputFormat;\n\tpublicOnly: boolean;\n\tinteractive: boolean;\n\tverbosity: string;\n\torgs?: string;\n\tmodel?: string;\n\tprompt?: string;\n}\n\nfunction validateVerbosity(value: string): Verbosity {\n\tconst valid: Verbosity[] = [\"brief\", \"normal\", \"detailed\"];\n\treturn valid.includes(value as Verbosity) ? (value as Verbosity) : \"normal\";\n}\n\nasync function execute(\n\tusername: string,\n\tdays: number,\n\tlang: Language,\n\tformat: OutputFormat,\n\tpublicOnly: boolean,\n\tverbosity: Verbosity,\n\tfilterOrgs: string[] | null,\n\tmodel?: string,\n\tcustomPrompt?: string,\n): Promise<void> {\n\t// Resolve username\n\tconst resolvedUsername = username || (await getAuthenticatedUser());\n\n\tconst scopeInfo = filterOrgs ? ` in ${filterOrgs.join(\", \")}` : \"\";\n\tconsole.error(\n\t\tchalk.yellow(\n\t\t\t`Fetching GitHub activity for ${resolvedUsername}${scopeInfo}...`,\n\t\t),\n\t);\n\n\tconst activity = await fetchGitHubActivity(\n\t\tresolvedUsername,\n\t\tdays,\n\t\tpublicOnly,\n\t\tfilterOrgs,\n\t);\n\n\tif (!hasActivity(activity)) {\n\t\tconsole.log(\"\");\n\t\tconsole.log(`tl;dr ${activity.date}`);\n\t\tconsole.log(\"\");\n\t\tconst noActivity =\n\t\t\tlang === \"en\"\n\t\t\t\t? `No GitHub activity in the ${activity.period}.`\n\t\t\t\t: `Keine GitHub-Aktivität in den ${activity.period}.`;\n\t\tconsole.log(noActivity);\n\t\treturn;\n\t}\n\n\t// Format stats locally\n\tconst stats = formatActivity(activity, format, lang);\n\n\tconsole.error(chalk.yellow(\"Generating summary with Claude...\"));\n\n\t// Only ask Claude for the summary paragraph\n\tconst summaryText = await generateSummaryText(\n\t\tactivity,\n\t\tlang,\n\t\tverbosity,\n\t\tmodel,\n\t\tcustomPrompt,\n\t);\n\n\tconsole.log(\"\");\n\tconsole.log(stats);\n\tconsole.log(\"\");\n\tconsole.log(\"---\");\n\tconsole.log(summaryText);\n}\n\nexport async function run(): Promise<void> {\n\tconst program = new Command();\n\n\tprogram\n\t\t.name(\"gh-tldr\")\n\t\t.description(\"Generate a TL;DR summary of your GitHub activity\")\n\t\t.version(version)\n\t\t.argument(\"[username]\", \"GitHub username (defaults to authenticated user)\")\n\t\t.option(\"-d, --days <n>\", \"Time period in days\", \"1\")\n\t\t.option(\"-e, --english\", \"Output in English (default: German)\", false)\n\t\t.option(\n\t\t\t\"-f, --format <type>\",\n\t\t\t\"Output format: slack|markdown|plain\",\n\t\t\t\"slack\",\n\t\t)\n\t\t.option(\"-p, --public-only\", \"Exclude private repositories\", false)\n\t\t.option(\"-i, --interactive\", \"Force interactive mode\", false)\n\t\t.option(\n\t\t\t\"-v, --verbosity <level>\",\n\t\t\t\"Summary verbosity: brief|normal|detailed\",\n\t\t\t\"normal\",\n\t\t)\n\t\t.option(\n\t\t\t\"-o, --orgs <orgs>\",\n\t\t\t\"Filter by organizations/accounts (comma-separated)\",\n\t\t)\n\t\t.option(\n\t\t\t\"-m, --model <model>\",\n\t\t\t\"Claude model to use (e.g., sonnet, opus, haiku)\",\n\t\t)\n\t\t.option(\n\t\t\t\"-P, --prompt <text>\",\n\t\t\t\"Custom instructions for Claude to consider when summarizing\",\n\t\t)\n\t\t.action(async (username: string | undefined, options: CliOptions) => {\n\t\t\ttry {\n\t\t\t\tawait checkDependencies();\n\n\t\t\t\t// Determine if we should run interactive mode\n\t\t\t\tconst hasArgs = process.argv.length > 2;\n\t\t\t\tconst forceInteractive = options.interactive;\n\n\t\t\t\tif (!hasArgs || forceInteractive) {\n\t\t\t\t\t// Interactive mode\n\t\t\t\t\tconst answers = await runInteractive();\n\t\t\t\t\tawait execute(\n\t\t\t\t\t\tanswers.username,\n\t\t\t\t\t\tanswers.days,\n\t\t\t\t\t\tanswers.language,\n\t\t\t\t\t\tanswers.format,\n\t\t\t\t\t\t!answers.includePrivate,\n\t\t\t\t\t\tanswers.verbosity,\n\t\t\t\t\t\tanswers.selectedOrgs,\n\t\t\t\t\t\tanswers.model || undefined,\n\t\t\t\t\t\tanswers.customPrompt || undefined,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Direct mode\n\t\t\t\t\tconst days = parseInt(options.days, 10);\n\t\t\t\t\tconst lang: Language = options.english ? \"en\" : \"de\";\n\t\t\t\t\tconst format = options.format as OutputFormat;\n\n\t\t\t\t\t// Parse orgs flag\n\t\t\t\t\tconst filterOrgs = options.orgs\n\t\t\t\t\t\t? options.orgs\n\t\t\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t\t\t.map((o) => o.trim())\n\t\t\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t: null;\n\n\t\t\t\t\tawait execute(\n\t\t\t\t\t\tusername || \"\",\n\t\t\t\t\t\tdays,\n\t\t\t\t\t\tlang,\n\t\t\t\t\t\tformat,\n\t\t\t\t\t\toptions.publicOnly,\n\t\t\t\t\t\tvalidateVerbosity(options.verbosity),\n\t\t\t\t\t\tfilterOrgs && filterOrgs.length > 0 ? filterOrgs : null,\n\t\t\t\t\t\toptions.model,\n\t\t\t\t\t\toptions.prompt,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconsole.error(chalk.red(`Error: ${error.message}`));\n\t\t\t\t}\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t});\n\n\tawait program.parseAsync();\n}\n","import { execa } from \"execa\";\nimport type { GitHubActivity, Language, Verbosity } from \"./types.js\";\n\nconst wordLimits: Record<Verbosity, Record<Language, string>> = {\n\tbrief: { en: \"20-40 word\", de: \"20-40 Wörter\" },\n\tnormal: { en: \"50-80 word\", de: \"50-80 Wörter\" },\n\tdetailed: { en: \"150-200 word\", de: \"150-200 Wörter\" },\n};\n\nfunction buildPrompt(\n\tlang: Language,\n\tverbosity: Verbosity,\n\tcustomPrompt?: string,\n): string {\n\tconst limit = wordLimits[verbosity][lang];\n\n\tconst customSection = customPrompt?.trim()\n\t\t? lang === \"en\"\n\t\t\t? `\\n\\nAdditional focus: ${customPrompt}`\n\t\t\t: `\\n\\nZusätzlicher Fokus: ${customPrompt}`\n\t\t: \"\";\n\n\tif (lang === \"en\") {\n\t\treturn `Based on this GitHub activity data, write a summary of what was accomplished. STRICT LIMIT: ${limit}. Mention specific PR/issue titles. If stats are available, include the lines of code changed (additions/deletions) as a brief mention. Casual tone, no bullet points, no emojis.${customSection}\n\nGitHub Activity Data:`;\n\t}\n\n\treturn `Basierend auf diesen GitHub-Aktivitätsdaten, schreibe eine Zusammenfassung was gemacht wurde. STRIKTES LIMIT: ${limit}. Erwähne konkret die PR/Issue-Titel. Falls Stats verfügbar sind, erwähne kurz die geänderten Codezeilen (Additions/Deletions). Lockerer Ton, keine Aufzählungen, keine Emojis.${customSection}\n\nGitHub-Aktivitätsdaten:`;\n}\n\nexport async function generateSummaryText(\n\tactivity: GitHubActivity,\n\tlang: Language,\n\tverbosity: Verbosity = \"normal\",\n\tmodel?: string,\n\tcustomPrompt?: string,\n): Promise<string> {\n\tconst prompt = buildPrompt(lang, verbosity, customPrompt);\n\tconst fullPrompt = `${prompt}\\n${JSON.stringify(activity, null, 2)}`;\n\n\tconst args = [\"-p\", \"-\", \"--output-format\", \"text\"];\n\tif (model) {\n\t\targs.push(\"--model\", model);\n\t}\n\n\tconst { stdout } = await execa(\"claude\", args, {\n\t\tinput: fullPrompt,\n\t});\n\n\treturn stdout.trim();\n}\n","import { execa } from \"execa\";\nimport type {\n\tCodeStats,\n\tCommit,\n\tGitHubActivity,\n\tIssue,\n\tPullRequest,\n\tRepoInfo,\n} from \"./types.js\";\n\nfunction getSinceDate(days: number): string {\n\tconst date = new Date();\n\tdate.setDate(date.getDate() - days);\n\treturn date.toISOString();\n}\n\nfunction formatDate(date: Date): string {\n\tconst day = date.getDate().toString().padStart(2, \"0\");\n\tconst month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n\tconst year = date.getFullYear();\n\treturn `${day}.${month}.${year}`;\n}\n\nasync function ghApi<T>(\n\tendpoint: string,\n\tparams: Record<string, string>,\n): Promise<T> {\n\tconst args = [\n\t\t\"api\",\n\t\t\"-X\",\n\t\t\"GET\",\n\t\tendpoint,\n\t\t...Object.entries(params).flatMap(([key, value]) => [\n\t\t\t\"-f\",\n\t\t\t`${key}=${value}`,\n\t\t]),\n\t];\n\n\tconst { stdout } = await execa(\"gh\", args);\n\treturn JSON.parse(stdout) as T;\n}\n\nasync function ghApiPaginated<T>(\n\tendpoint: string,\n\tparams: Record<string, string>,\n\tmaxPages: number = 10,\n): Promise<T[]> {\n\tconst allItems: T[] = [];\n\tlet page = 1;\n\n\twhile (page <= maxPages) {\n\t\tconst result = await ghApi<SearchResult<T>>(endpoint, {\n\t\t\t...params,\n\t\t\tpage: String(page),\n\t\t\tper_page: \"100\",\n\t\t});\n\n\t\tallItems.push(...result.items);\n\n\t\tif (result.items.length < 100) {\n\t\t\tbreak;\n\t\t}\n\t\tpage++;\n\t}\n\n\treturn allItems;\n}\n\ninterface SearchResult<T> {\n\ttotal_count?: number;\n\titems: T[];\n}\n\ninterface RawPR {\n\trepository_url: string;\n\ttitle: string;\n\tnumber: number;\n\tstate: string;\n\thtml_url: string;\n}\n\ninterface RawCommit {\n\trepository: {\n\t\tname: string;\n\t\towner: { login: string };\n\t};\n\tcommit: {\n\t\tmessage: string;\n\t\tauthor: { date: string };\n\t};\n\thtml_url: string;\n}\n\ninterface RawRepo {\n\tname: string;\n\towner: { login: string };\n\tcreated_at: string;\n\thtml_url: string;\n}\n\ninterface RawPRDetails {\n\tadditions: number;\n\tdeletions: number;\n\tchanged_files: number;\n}\n\nfunction parsePR(item: RawPR): PullRequest {\n\tconst urlParts = item.repository_url.split(\"/\");\n\treturn {\n\t\trepo: urlParts[urlParts.length - 1],\n\t\torg: urlParts[urlParts.length - 2],\n\t\ttitle: item.title,\n\t\tnumber: item.number,\n\t\tstate: item.state,\n\t\turl: item.html_url,\n\t};\n}\n\nfunction parseIssue(item: RawPR): Issue {\n\tconst urlParts = item.repository_url.split(\"/\");\n\treturn {\n\t\trepo: urlParts[urlParts.length - 1],\n\t\torg: urlParts[urlParts.length - 2],\n\t\ttitle: item.title,\n\t\tnumber: item.number,\n\t\turl: item.html_url,\n\t};\n}\n\nfunction parseCommit(item: RawCommit): Commit {\n\treturn {\n\t\trepo: item.repository.name,\n\t\torg: item.repository.owner.login,\n\t\tmessage: item.commit.message.split(\"\\n\")[0],\n\t\turl: item.html_url,\n\t\tdate: item.commit.author.date,\n\t};\n}\n\nasync function fetchPRDetails(\n\torg: string,\n\trepo: string,\n\tnumber: number,\n): Promise<{ additions: number; deletions: number; changedFiles: number }> {\n\tconst { stdout } = await execa(\"gh\", [\n\t\t\"api\",\n\t\t`repos/${org}/${repo}/pulls/${number}`,\n\t]);\n\tconst data = JSON.parse(stdout) as RawPRDetails;\n\treturn {\n\t\tadditions: data.additions,\n\t\tdeletions: data.deletions,\n\t\tchangedFiles: data.changed_files,\n\t};\n}\n\nasync function enrichPRsWithStats(prs: PullRequest[]): Promise<PullRequest[]> {\n\tconst results = await Promise.allSettled(\n\t\tprs.map(async (pr) => {\n\t\t\tconst stats = await fetchPRDetails(pr.org, pr.repo, pr.number);\n\t\t\treturn { ...pr, ...stats };\n\t\t}),\n\t);\n\n\treturn results.map((result, index) => {\n\t\tif (result.status === \"fulfilled\") {\n\t\t\treturn result.value;\n\t\t}\n\t\t// On failure, return original PR without stats\n\t\treturn prs[index];\n\t});\n}\n\nfunction calculateStats(prs: PullRequest[]): CodeStats {\n\t// Deduplicate PRs by org/repo/number to avoid double-counting\n\tconst seen = new Set<string>();\n\tconst uniquePRs = prs.filter((pr) => {\n\t\tconst key = `${pr.org}/${pr.repo}#${pr.number}`;\n\t\tif (seen.has(key)) return false;\n\t\tseen.add(key);\n\t\treturn true;\n\t});\n\n\tconst totalAdditions = uniquePRs.reduce(\n\t\t(sum, pr) => sum + (pr.additions ?? 0),\n\t\t0,\n\t);\n\tconst totalDeletions = uniquePRs.reduce(\n\t\t(sum, pr) => sum + (pr.deletions ?? 0),\n\t\t0,\n\t);\n\tconst totalChangedFiles = uniquePRs.reduce(\n\t\t(sum, pr) => sum + (pr.changedFiles ?? 0),\n\t\t0,\n\t);\n\n\treturn {\n\t\ttotalAdditions,\n\t\ttotalDeletions,\n\t\ttotalChangedFiles,\n\t\tnetLines: totalAdditions - totalDeletions,\n\t};\n}\n\nexport async function getAuthenticatedUser(): Promise<string> {\n\tconst { stdout } = await execa(\"gh\", [\"api\", \"user\", \"--jq\", \".login\"]);\n\treturn stdout.trim();\n}\n\nexport async function fetchUserOrgs(username: string): Promise<string[]> {\n\t// First try authenticated user's orgs (includes private memberships)\n\ttry {\n\t\tconst authUser = await getAuthenticatedUser();\n\t\tif (authUser === username) {\n\t\t\tconst { stdout } = await execa(\"gh\", [\n\t\t\t\t\"api\",\n\t\t\t\t\"user/orgs\",\n\t\t\t\t\"--jq\",\n\t\t\t\t\".[].login\",\n\t\t\t]);\n\t\t\treturn stdout.trim().split(\"\\n\").filter(Boolean);\n\t\t}\n\t} catch {\n\t\t// Fall through to public orgs\n\t}\n\n\t// Fallback to public orgs for other users\n\ttry {\n\t\tconst { stdout } = await execa(\"gh\", [\n\t\t\t\"api\",\n\t\t\t`users/${username}/orgs`,\n\t\t\t\"--jq\",\n\t\t\t\".[].login\",\n\t\t]);\n\t\treturn stdout.trim().split(\"\\n\").filter(Boolean);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nasync function fetchReposCreatedSince(\n\tusername: string,\n\tsince: string,\n\tpublicOnly: boolean,\n\tfilterOrgs: string[] | null,\n): Promise<RepoInfo[]> {\n\tconst sinceDate = new Date(since);\n\tconst repos: RepoInfo[] = [];\n\n\t// Determine which orgs to check\n\tconst orgsToCheck = filterOrgs ?? [\n\t\tusername,\n\t\t...(await fetchUserOrgs(username)),\n\t];\n\n\tfor (const org of orgsToCheck) {\n\t\ttry {\n\t\t\tconst isUser = org === username;\n\t\t\tconst endpoint = isUser\n\t\t\t\t? `users/${username}/repos?type=${publicOnly ? \"public\" : \"all\"}&sort=created&direction=desc&per_page=100`\n\t\t\t\t: `orgs/${org}/repos?sort=created&direction=desc&per_page=100`;\n\n\t\t\tconst { stdout } = await execa(\"gh\", [\"api\", endpoint]);\n\t\t\tconst orgRepos = JSON.parse(stdout) as RawRepo[];\n\t\t\tfor (const repo of orgRepos) {\n\t\t\t\tif (new Date(repo.created_at) >= sinceDate) {\n\t\t\t\t\trepos.push({ name: repo.name, org: repo.owner.login });\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore errors for individual orgs\n\t\t}\n\t}\n\n\t// Deduplicate\n\treturn repos.filter(\n\t\t(repo, index, self) =>\n\t\t\tself.findIndex((r) => r.name === repo.name && r.org === repo.org) ===\n\t\t\tindex,\n\t);\n}\n\nexport async function fetchGitHubActivity(\n\tusername: string,\n\tdays: number,\n\tpublicOnly: boolean,\n\tfilterOrgs: string[] | null = null,\n): Promise<GitHubActivity> {\n\tconst since = getSinceDate(days);\n\tconst today = formatDate(new Date());\n\tconst visibilityFilter = publicOnly ? \" is:public\" : \"\";\n\n\t// Build org filter string: \"org:X org:Y\" (implicit OR)\n\tconst orgFilter = filterOrgs\n\t\t? ` ${filterOrgs.map((o) => `org:${o}`).join(\" \")}`\n\t\t: \"\";\n\n\t// Fetch all data in parallel with pagination\n\tconst [\n\t\tprsCreatedItems,\n\t\tprsMergedItems,\n\t\tprsReviewedItems,\n\t\tissuesCreatedItems,\n\t\tissuesClosedItems,\n\t\tcommitsItems,\n\t\trepos_created,\n\t] = await Promise.all([\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:pr created:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:pr merged:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `reviewed-by:${username} type:pr created:>=${since} -author:${username}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:issue created:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawPR>(\"search/issues\", {\n\t\t\tq: `author:${username} type:issue closed:>=${since}${visibilityFilter}${orgFilter}`,\n\t\t}),\n\t\tghApiPaginated<RawCommit>(\"search/commits\", {\n\t\t\tq: `author:${username} committer-date:>=${since}${orgFilter}`,\n\t\t}),\n\t\tfetchReposCreatedSince(username, since, publicOnly, filterOrgs),\n\t]);\n\n\tconst prs_created_raw = prsCreatedItems.map(parsePR);\n\tconst prs_merged_raw = prsMergedItems.map(parsePR);\n\tconst prs_reviewed = prsReviewedItems.map(parsePR);\n\tconst issues_created = issuesCreatedItems.map(parseIssue);\n\tconst issues_closed = issuesClosedItems.map(parseIssue);\n\tconst commits = commitsItems.map(parseCommit);\n\n\t// Enrich PRs with LOC stats (created and merged, in parallel)\n\tconst [prs_created, prs_merged] = await Promise.all([\n\t\tenrichPRsWithStats(prs_created_raw),\n\t\tenrichPRsWithStats(prs_merged_raw),\n\t]);\n\n\t// Calculate aggregate stats from all authored PRs (deduplicated)\n\tconst stats = calculateStats([...prs_created, ...prs_merged]);\n\n\t// Extract unique repos touched\n\tconst allRepos = [\n\t\t...prs_created,\n\t\t...prs_merged,\n\t\t...prs_reviewed,\n\t\t...issues_created,\n\t\t...issues_closed,\n\t\t...commits,\n\t].map((item) => `${item.org}/${item.repo}`);\n\n\tconst repos_touched = [...new Set(allRepos)];\n\n\tconst periodText =\n\t\tdays === 1\n\t\t\t? \"last 24 hours\"\n\t\t\t: days === 7\n\t\t\t\t? \"last 7 days\"\n\t\t\t\t: days === 30\n\t\t\t\t\t? \"last 30 days\"\n\t\t\t\t\t: `last ${days} days`;\n\n\treturn {\n\t\tuser: username,\n\t\tdate: today,\n\t\tperiod: periodText,\n\t\tprs_created,\n\t\tprs_merged,\n\t\tprs_reviewed,\n\t\tissues_created,\n\t\tissues_closed,\n\t\tcommits,\n\t\trepos_created,\n\t\trepos_touched,\n\t\tstats,\n\t};\n}\n","import { confirm, input, select } from \"@inquirer/prompts\";\nimport { fetchUserOrgs, getAuthenticatedUser } from \"./github.js\";\nimport type { Language, OutputFormat, Verbosity } from \"./types.js\";\n\ninterface InteractiveOptions {\n\tusername: string;\n\tdays: number;\n\tlanguage: Language;\n\tverbosity: Verbosity;\n\tformat: OutputFormat;\n\tincludePrivate: boolean;\n\tselectedOrgs: string[] | null;\n\tmodel: string;\n\tcustomPrompt: string;\n}\n\nexport async function runInteractive(): Promise<InteractiveOptions> {\n\tconst username = await input({\n\t\tmessage: \"GitHub username (leave empty for authenticated user)\",\n\t\tdefault: \"\",\n\t});\n\n\tconst days = await select({\n\t\tmessage: \"Time period\",\n\t\tchoices: [\n\t\t\t{ name: \"Last 24 hours\", value: 1 },\n\t\t\t{ name: \"Last 7 days\", value: 7 },\n\t\t\t{ name: \"Last 30 days\", value: 30 },\n\t\t],\n\t\tdefault: 1,\n\t});\n\n\tconst language = await select({\n\t\tmessage: \"Language\",\n\t\tchoices: [\n\t\t\t{ name: \"English\", value: \"en\" as Language },\n\t\t\t{ name: \"German\", value: \"de\" as Language },\n\t\t],\n\t\tdefault: \"en\" as Language,\n\t});\n\n\tconst verbosity = await select({\n\t\tmessage: \"Summary verbosity\",\n\t\tchoices: [\n\t\t\t{ name: \"Brief (~30 words)\", value: \"brief\" as Verbosity },\n\t\t\t{ name: \"Normal (~60 words)\", value: \"normal\" as Verbosity },\n\t\t\t{ name: \"Detailed (~175 words)\", value: \"detailed\" as Verbosity },\n\t\t],\n\t\tdefault: \"normal\" as Verbosity,\n\t});\n\n\tconst format = await select({\n\t\tmessage: \"Output format\",\n\t\tchoices: [\n\t\t\t{ name: \"Plain text\", value: \"plain\" as OutputFormat },\n\t\t\t{ name: \"Markdown\", value: \"markdown\" as OutputFormat },\n\t\t\t{ name: \"Slack\", value: \"slack\" as OutputFormat },\n\t\t],\n\t\tdefault: \"plain\" as OutputFormat,\n\t});\n\n\tconst includePrivate = await confirm({\n\t\tmessage: \"Include private repos?\",\n\t\tdefault: true,\n\t});\n\n\t// Fetch available orgs for the user\n\tconst resolvedUsername = username || (await getAuthenticatedUser());\n\tconst userOrgs = await fetchUserOrgs(resolvedUsername);\n\tconst allScopes = [resolvedUsername, ...userOrgs];\n\n\t// Build choices with \"All\" as first option\n\tconst ALL_VALUE = \"__ALL__\";\n\tconst scopeChoices = [\n\t\t{ name: \"All (no filter)\", value: ALL_VALUE },\n\t\t...allScopes.map((org) => ({ name: org, value: org })),\n\t];\n\n\tconst scopeSelection = await select({\n\t\tmessage: \"Filter by scope\",\n\t\tchoices: scopeChoices,\n\t\tdefault: ALL_VALUE,\n\t});\n\n\t// If \"All\" selected, no filtering; otherwise filter to that single org\n\t// For multi-org selection, user can use CLI --orgs flag\n\tconst selectedOrgs = scopeSelection === ALL_VALUE ? null : [scopeSelection];\n\n\tconst model = await input({\n\t\tmessage: \"Claude model (leave empty for default)\",\n\t\tdefault: \"\",\n\t});\n\n\tconst customPrompt = await input({\n\t\tmessage: \"Any specific focus for the summary? (optional)\",\n\t\tdefault: \"\",\n\t});\n\n\treturn {\n\t\tusername,\n\t\tdays,\n\t\tlanguage,\n\t\tverbosity,\n\t\tformat,\n\t\tincludePrivate,\n\t\tselectedOrgs,\n\t\tmodel,\n\t\tcustomPrompt,\n\t};\n}\n","import type {\n\tCodeStats,\n\tCommit,\n\tGitHubActivity,\n\tLanguage,\n\tOutputFormat,\n} from \"./types.js\";\n\n// Gap threshold: if gap between commits > 3 hours, treat as separate session\nconst GAP_THRESHOLD_MS = 3 * 60 * 60 * 1000;\n// Minimum time to count for a single-commit session (15 minutes)\nconst SINGLE_COMMIT_HOURS = 0.25;\n\nfunction calculateWorkSession(\n\tcommits: Commit[],\n\tlang: Language,\n): string | null {\n\tif (commits.length < 2) return null;\n\n\t// Sort timestamps chronologically\n\tconst timestamps = commits\n\t\t.map((c) => new Date(c.date).getTime())\n\t\t.sort((a, b) => a - b);\n\n\t// Group commits into sessions based on gap threshold\n\tconst sessions: number[][] = [];\n\tlet currentSession = [timestamps[0]];\n\n\tfor (let i = 1; i < timestamps.length; i++) {\n\t\tconst gap = timestamps[i] - timestamps[i - 1];\n\t\tif (gap > GAP_THRESHOLD_MS) {\n\t\t\tsessions.push(currentSession);\n\t\t\tcurrentSession = [timestamps[i]];\n\t\t} else {\n\t\t\tcurrentSession.push(timestamps[i]);\n\t\t}\n\t}\n\tsessions.push(currentSession);\n\n\t// Calculate total hours across all sessions\n\tlet totalHours = 0;\n\tfor (const session of sessions) {\n\t\tif (session.length === 1) {\n\t\t\ttotalHours += SINGLE_COMMIT_HOURS;\n\t\t} else {\n\t\t\tconst duration = session[session.length - 1] - session[0];\n\t\t\ttotalHours += duration / (1000 * 60 * 60);\n\t\t}\n\t}\n\n\t// Round to nearest 0.5 hours\n\tconst rounded = Math.round(totalHours * 2) / 2;\n\n\tif (rounded < 0.5) return null;\n\n\tconst label = lang === \"en\" ? \"Work session\" : \"Arbeitszeit\";\n\tconst hoursLabel =\n\t\trounded === 1\n\t\t\t? lang === \"en\"\n\t\t\t\t? \"hour\"\n\t\t\t\t: \"Stunde\"\n\t\t\t: lang === \"en\"\n\t\t\t\t? \"hours\"\n\t\t\t\t: \"Stunden\";\n\n\treturn `${label}: ~${rounded} ${hoursLabel}`;\n}\n\nfunction getRepoNames(items: { repo: string }[]): string {\n\tconst repos = [...new Set(items.map((i) => i.repo))];\n\treturn repos.join(\", \");\n}\n\nfunction formatNumber(n: number): string {\n\treturn n.toLocaleString(\"en-US\");\n}\n\nfunction formatLinesChanged(\n\tstats: CodeStats | undefined,\n\tlang: Language,\n\tformat: OutputFormat,\n): string | null {\n\tif (!stats || (stats.totalAdditions === 0 && stats.totalDeletions === 0)) {\n\t\treturn null;\n\t}\n\n\tconst additions = formatNumber(stats.totalAdditions);\n\tconst deletions = formatNumber(stats.totalDeletions);\n\tconst files = formatNumber(stats.totalChangedFiles);\n\tconst filesLabel = lang === \"en\" ? \"files\" : \"Dateien\";\n\n\tconst text = `+${additions} / -${deletions} lines (${files} ${filesLabel})`;\n\n\tif (format === \"markdown\") {\n\t\treturn `- **${text}**`;\n\t}\n\treturn `• ${text}`;\n}\n\nfunction formatActivityLine(\n\tcount: number,\n\tlabelEn: string,\n\tlabelDe: string,\n\trepos: string,\n\tlang: Language,\n\tformat: OutputFormat,\n): string | null {\n\tif (count === 0) return null;\n\n\tconst label = lang === \"en\" ? labelEn : labelDe;\n\tconst repoSuffix = repos ? ` (${repos})` : \"\";\n\n\tif (format === \"markdown\") {\n\t\treturn `- **${count}** ${label}${repoSuffix}`;\n\t}\n\treturn `• ${count} ${label}${repoSuffix}`;\n}\n\nexport function formatActivity(\n\tactivity: GitHubActivity,\n\tformat: OutputFormat,\n\tlang: Language,\n): string {\n\tconst lines: string[] = [];\n\n\t// Header\n\tconst headerPrefix = format === \"markdown\" ? \"## \" : \"\";\n\tlines.push(`${headerPrefix}tl;dr ${activity.date}`);\n\tlines.push(\"\");\n\n\tconst activityLines = [\n\t\tformatActivityLine(\n\t\t\tactivity.prs_created.length,\n\t\t\t\"PRs created\",\n\t\t\t\"PRs erstellt\",\n\t\t\tgetRepoNames(activity.prs_created),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.prs_reviewed.length,\n\t\t\t\"PRs reviewed\",\n\t\t\t\"PRs reviewed/approved\",\n\t\t\tgetRepoNames(activity.prs_reviewed),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.prs_merged.length,\n\t\t\t\"PRs merged\",\n\t\t\t\"PRs gemerged\",\n\t\t\tgetRepoNames(activity.prs_merged),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.issues_created.length,\n\t\t\t\"issues created\",\n\t\t\t\"Issues erstellt\",\n\t\t\tgetRepoNames(activity.issues_created),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.issues_closed.length,\n\t\t\t\"issues closed\",\n\t\t\t\"Issues geschlossen\",\n\t\t\tgetRepoNames(activity.issues_closed),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.commits.length,\n\t\t\t\"commits\",\n\t\t\t\"Commits\",\n\t\t\tgetRepoNames(activity.commits),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatActivityLine(\n\t\t\tactivity.repos_created.length,\n\t\t\t\"new repos created\",\n\t\t\t\"neue Repos erstellt\",\n\t\t\tactivity.repos_created.map((r) => r.name).join(\", \"),\n\t\t\tlang,\n\t\t\tformat,\n\t\t),\n\t\tformatLinesChanged(activity.stats, lang, format),\n\t].filter(Boolean) as string[];\n\n\tif (activityLines.length === 0) {\n\t\tconst noActivity =\n\t\t\tlang === \"en\"\n\t\t\t\t? `No GitHub activity in the ${activity.period}.`\n\t\t\t\t: `Keine GitHub-Aktivität in den ${activity.period}.`;\n\t\tlines.push(noActivity);\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\tlines.push(...activityLines);\n\n\t// Work session duration\n\tconst workSession = calculateWorkSession(activity.commits, lang);\n\tif (workSession) {\n\t\tlines.push(format === \"markdown\" ? `- ${workSession}` : `• ${workSession}`);\n\t}\n\n\tlines.push(\"\");\n\n\t// Repos touched\n\tif (activity.repos_touched.length > 0) {\n\t\tconst reposLabel = lang === \"en\" ? \"Repos\" : \"Repos\";\n\t\tlines.push(`${reposLabel}: ${activity.repos_touched.join(\", \")}`);\n\t}\n\n\treturn lines.join(\"\\n\");\n}\n\nexport function hasActivity(activity: GitHubActivity): boolean {\n\treturn (\n\t\tactivity.prs_created.length +\n\t\t\tactivity.prs_merged.length +\n\t\t\tactivity.prs_reviewed.length +\n\t\t\tactivity.issues_created.length +\n\t\t\tactivity.issues_closed.length >\n\t\t0\n\t);\n}\n","// gh-tldr - Generate a TL;DR summary of your GitHub activity\n// Entry point: detects mode (interactive vs direct) and runs CLI\n\nimport { run } from \"./cli.js\";\n\nrun();\n"],"mappings":"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","names":["execa","require","execa"]}
|