devdaily-ai 0.1.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/LICENSE +21 -0
- package/README.md +112 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +638 -0
- package/dist/index.js.map +1 -0
- package/package.json +93 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DevDaily AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# DevDaily AI
|
|
2
|
+
|
|
3
|
+
> Your AI memory for developer work
|
|
4
|
+
|
|
5
|
+
Never forget what you did. Auto-generate PR descriptions, standup notes, and work summaries from your git history.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Standup Generator** - Yesterday's work in 30 seconds
|
|
10
|
+
- **PR Descriptions** - AI-generated from your commits
|
|
11
|
+
- **Weekly Summaries** - Track your impact over time
|
|
12
|
+
- **Smart Context** - Remember what you were working on
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g devdaily-ai
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Generate standup notes
|
|
24
|
+
devdaily standup
|
|
25
|
+
|
|
26
|
+
# Create PR description
|
|
27
|
+
devdaily pr
|
|
28
|
+
|
|
29
|
+
# Weekly summary
|
|
30
|
+
devdaily week
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Commands
|
|
34
|
+
|
|
35
|
+
### `devdaily standup`
|
|
36
|
+
|
|
37
|
+
Generate standup notes from your recent commits.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
devdaily standup # Yesterday's work
|
|
41
|
+
devdaily standup --days=3 # Last 3 days
|
|
42
|
+
devdaily standup --format=slack
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### `devdaily pr`
|
|
46
|
+
|
|
47
|
+
Generate comprehensive PR descriptions.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
devdaily pr # Generate description
|
|
51
|
+
devdaily pr --create # Create PR on GitHub
|
|
52
|
+
devdaily pr --draft # Create as draft
|
|
53
|
+
devdaily pr --base=develop # Compare to develop
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### `devdaily week`
|
|
57
|
+
|
|
58
|
+
Get a weekly summary of your work.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
devdaily week # Current week
|
|
62
|
+
devdaily week --last # Last week
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Requirements
|
|
66
|
+
|
|
67
|
+
- Node.js >= 18
|
|
68
|
+
- Git repository
|
|
69
|
+
- GitHub CLI (`gh`) with Copilot extension
|
|
70
|
+
|
|
71
|
+
## Setup
|
|
72
|
+
|
|
73
|
+
1. Install GitHub CLI:
|
|
74
|
+
```bash
|
|
75
|
+
brew install gh # macOS
|
|
76
|
+
# or visit https://cli.github.com
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
2. Install Copilot extension:
|
|
80
|
+
```bash
|
|
81
|
+
gh extension install github/gh-copilot
|
|
82
|
+
gh auth login
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
3. Install DevDaily:
|
|
86
|
+
```bash
|
|
87
|
+
npm install -g devdaily-ai
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Clone repo
|
|
94
|
+
git clone https://github.com/yourusername/devdaily-ai
|
|
95
|
+
cd devdaily-ai
|
|
96
|
+
|
|
97
|
+
# Install dependencies
|
|
98
|
+
npm install
|
|
99
|
+
|
|
100
|
+
# Run in dev mode
|
|
101
|
+
npm run dev
|
|
102
|
+
|
|
103
|
+
# Build
|
|
104
|
+
npm run build
|
|
105
|
+
|
|
106
|
+
# Run tests
|
|
107
|
+
npm test
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
import { Command as Command5 } from "commander";
|
|
6
|
+
|
|
7
|
+
// src/commands/standup.ts
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
|
|
10
|
+
// src/core/git-analyzer.ts
|
|
11
|
+
import simpleGit from "simple-git";
|
|
12
|
+
var GitAnalyzer = class {
|
|
13
|
+
git;
|
|
14
|
+
constructor(repoPath) {
|
|
15
|
+
this.git = simpleGit(repoPath || process.cwd());
|
|
16
|
+
}
|
|
17
|
+
async isRepository() {
|
|
18
|
+
try {
|
|
19
|
+
await this.git.revparse(["--is-inside-work-tree"]);
|
|
20
|
+
return true;
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async getCurrentBranch() {
|
|
26
|
+
const branch = await this.git.revparse(["--abbrev-ref", "HEAD"]);
|
|
27
|
+
return branch.trim();
|
|
28
|
+
}
|
|
29
|
+
async getCommits(options = {}) {
|
|
30
|
+
const logOptions = {
|
|
31
|
+
format: {
|
|
32
|
+
hash: "%H",
|
|
33
|
+
message: "%s",
|
|
34
|
+
body: "%b",
|
|
35
|
+
author: "%an",
|
|
36
|
+
date: "%ai"
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
if (options.since) {
|
|
40
|
+
logOptions.from = options.since.toISOString();
|
|
41
|
+
}
|
|
42
|
+
if (options.until) {
|
|
43
|
+
logOptions.to = options.until.toISOString();
|
|
44
|
+
}
|
|
45
|
+
if (options.author) {
|
|
46
|
+
logOptions.author = options.author;
|
|
47
|
+
}
|
|
48
|
+
const log = await this.git.log(logOptions);
|
|
49
|
+
return log.all.map((commit) => ({
|
|
50
|
+
hash: commit.hash,
|
|
51
|
+
message: commit.message,
|
|
52
|
+
author: commit.author,
|
|
53
|
+
date: new Date(commit.date),
|
|
54
|
+
body: commit.body
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
async getDiff(base = "main", head = "HEAD") {
|
|
58
|
+
const diff = await this.git.diff([`${base}...${head}`]);
|
|
59
|
+
return diff;
|
|
60
|
+
}
|
|
61
|
+
async getDiffStats(base = "main", head = "HEAD") {
|
|
62
|
+
const diffSummary = await this.git.diffSummary([`${base}...${head}`]);
|
|
63
|
+
return {
|
|
64
|
+
filesChanged: diffSummary.files.length,
|
|
65
|
+
insertions: diffSummary.insertions,
|
|
66
|
+
deletions: diffSummary.deletions
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async getChangedFiles(base = "main", head = "HEAD") {
|
|
70
|
+
const diff = await this.git.diff([`${base}...${head}`, "--name-only"]);
|
|
71
|
+
return diff.split("\n").filter(Boolean);
|
|
72
|
+
}
|
|
73
|
+
async getCurrentUser() {
|
|
74
|
+
const name = await this.git.getConfig("user.name");
|
|
75
|
+
const email = await this.git.getConfig("user.email");
|
|
76
|
+
return {
|
|
77
|
+
name: name.value || "",
|
|
78
|
+
email: email.value || ""
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async getStatus() {
|
|
82
|
+
const status = await this.git.status();
|
|
83
|
+
return {
|
|
84
|
+
modified: status.modified,
|
|
85
|
+
untracked: status.not_added
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async hasUncommittedChanges() {
|
|
89
|
+
const status = await this.git.status();
|
|
90
|
+
return !status.isClean();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// src/core/copilot.ts
|
|
95
|
+
import { execa } from "execa";
|
|
96
|
+
var CopilotClient = class {
|
|
97
|
+
async isInstalled() {
|
|
98
|
+
try {
|
|
99
|
+
await execa("gh", ["copilot", "--version"]);
|
|
100
|
+
return true;
|
|
101
|
+
} catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async suggest(prompt) {
|
|
106
|
+
try {
|
|
107
|
+
const { stdout } = await execa("gh", ["copilot", "suggest", "-t", "shell", prompt]);
|
|
108
|
+
return this.parseOutput(stdout);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
throw new Error(`Copilot CLI error: ${error}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async explain(code) {
|
|
114
|
+
try {
|
|
115
|
+
const { stdout } = await execa("gh", ["copilot", "explain", code]);
|
|
116
|
+
return this.parseOutput(stdout);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
throw new Error(`Copilot CLI error: ${error}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
parseOutput(raw) {
|
|
122
|
+
const cleaned = raw.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
|
|
123
|
+
const lines = cleaned.split("\n");
|
|
124
|
+
const relevantLines = lines.filter(
|
|
125
|
+
(line) => line.trim() && !line.includes("Suggestion:") && !line.includes("Explain command:") && !line.includes("?")
|
|
126
|
+
);
|
|
127
|
+
return relevantLines.join("\n").trim();
|
|
128
|
+
}
|
|
129
|
+
async summarizeCommits(commits) {
|
|
130
|
+
const prompt = `
|
|
131
|
+
You are helping a developer write their standup notes.
|
|
132
|
+
|
|
133
|
+
Here are their git commits from yesterday:
|
|
134
|
+
${commits.map((c, i) => `${i + 1}. ${c}`).join("\n")}
|
|
135
|
+
|
|
136
|
+
Generate a professional standup update following this format:
|
|
137
|
+
|
|
138
|
+
Yesterday I:
|
|
139
|
+
- [achievement 1 with impact]
|
|
140
|
+
- [achievement 2 with impact]
|
|
141
|
+
- [achievement 3 with impact]
|
|
142
|
+
|
|
143
|
+
Today I'm working on:
|
|
144
|
+
- [planned work based on commits]
|
|
145
|
+
|
|
146
|
+
Blockers: None
|
|
147
|
+
|
|
148
|
+
Requirements:
|
|
149
|
+
- Make it sound natural and professional
|
|
150
|
+
- Focus on WHAT was accomplished, not HOW
|
|
151
|
+
- Highlight business impact when possible
|
|
152
|
+
- Keep it concise (3-5 bullet points max)
|
|
153
|
+
- No emojis
|
|
154
|
+
`;
|
|
155
|
+
return this.suggest(prompt);
|
|
156
|
+
}
|
|
157
|
+
async generatePRDescription(data) {
|
|
158
|
+
const prompt = `
|
|
159
|
+
You are helping a developer create a Pull Request description.
|
|
160
|
+
|
|
161
|
+
Branch: ${data.branch}
|
|
162
|
+
|
|
163
|
+
Commits:
|
|
164
|
+
${data.commits.map((c, i) => `${i + 1}. ${c}`).join("\n")}
|
|
165
|
+
|
|
166
|
+
Files changed:
|
|
167
|
+
${data.files.join("\n")}
|
|
168
|
+
|
|
169
|
+
Related issues: ${data.issues.length > 0 ? data.issues.join(", ") : "None"}
|
|
170
|
+
|
|
171
|
+
Generate a comprehensive PR description following this template:
|
|
172
|
+
|
|
173
|
+
## What Changed
|
|
174
|
+
- [bullet point 1]
|
|
175
|
+
- [bullet point 2]
|
|
176
|
+
- [bullet point 3]
|
|
177
|
+
|
|
178
|
+
## Why
|
|
179
|
+
[Business or technical reason for these changes]
|
|
180
|
+
${data.issues.length > 0 ? `Closes ${data.issues.join(", ")}` : ""}
|
|
181
|
+
|
|
182
|
+
## How to Test
|
|
183
|
+
1. [testing step 1]
|
|
184
|
+
2. [testing step 2]
|
|
185
|
+
3. [testing step 3]
|
|
186
|
+
|
|
187
|
+
Requirements:
|
|
188
|
+
- Be specific and technical where appropriate
|
|
189
|
+
- Focus on value for code reviewers
|
|
190
|
+
- Keep it clear and concise
|
|
191
|
+
- No emojis
|
|
192
|
+
`;
|
|
193
|
+
return this.suggest(prompt);
|
|
194
|
+
}
|
|
195
|
+
async generateWeeklySummary(data) {
|
|
196
|
+
const prompt = `
|
|
197
|
+
You are helping a developer create their weekly work summary.
|
|
198
|
+
|
|
199
|
+
This week's commits:
|
|
200
|
+
${data.commits.map((c, i) => `${i + 1}. ${c}`).join("\n")}
|
|
201
|
+
|
|
202
|
+
Statistics:
|
|
203
|
+
- ${data.stats.commits} commits
|
|
204
|
+
- ${data.stats.linesAdded} lines added
|
|
205
|
+
- ${data.stats.linesRemoved} lines removed
|
|
206
|
+
|
|
207
|
+
Generate a professional weekly summary following this format:
|
|
208
|
+
|
|
209
|
+
Key Accomplishments:
|
|
210
|
+
1. [Major accomplishment with impact]
|
|
211
|
+
2. [Second accomplishment]
|
|
212
|
+
3. [Third accomplishment]
|
|
213
|
+
4. [Fourth accomplishment]
|
|
214
|
+
5. [Fifth accomplishment]
|
|
215
|
+
|
|
216
|
+
Top Achievement:
|
|
217
|
+
[Single sentence highlighting the most impactful work]
|
|
218
|
+
|
|
219
|
+
Requirements:
|
|
220
|
+
- Focus on business value and impact
|
|
221
|
+
- Be suitable for sharing with manager or team
|
|
222
|
+
- Highlight 3-5 key accomplishments
|
|
223
|
+
- Keep it professional
|
|
224
|
+
- No emojis
|
|
225
|
+
`;
|
|
226
|
+
return this.suggest(prompt);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// src/utils/ui.ts
|
|
231
|
+
import chalk from "chalk";
|
|
232
|
+
import boxen from "boxen";
|
|
233
|
+
var UI = class {
|
|
234
|
+
static colors = {
|
|
235
|
+
primary: chalk.blue,
|
|
236
|
+
success: chalk.green,
|
|
237
|
+
warning: chalk.yellow,
|
|
238
|
+
error: chalk.red,
|
|
239
|
+
dim: chalk.gray,
|
|
240
|
+
bold: chalk.bold
|
|
241
|
+
};
|
|
242
|
+
static header(title) {
|
|
243
|
+
return this.colors.bold(title);
|
|
244
|
+
}
|
|
245
|
+
static section(title, content) {
|
|
246
|
+
return `
|
|
247
|
+
${this.colors.primary(title)}
|
|
248
|
+
${content}`;
|
|
249
|
+
}
|
|
250
|
+
static box(content, title) {
|
|
251
|
+
return boxen(content, {
|
|
252
|
+
padding: 1,
|
|
253
|
+
margin: 1,
|
|
254
|
+
borderStyle: "round",
|
|
255
|
+
borderColor: "blue",
|
|
256
|
+
title,
|
|
257
|
+
titleAlignment: "left"
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
static list(items) {
|
|
261
|
+
return items.map((item) => ` ${this.colors.dim(">")} ${item}`).join("\n");
|
|
262
|
+
}
|
|
263
|
+
static success(message) {
|
|
264
|
+
return this.colors.success(`\u2713 ${message}`);
|
|
265
|
+
}
|
|
266
|
+
static error(message) {
|
|
267
|
+
return this.colors.error(`\u2717 ${message}`);
|
|
268
|
+
}
|
|
269
|
+
static warning(message) {
|
|
270
|
+
return this.colors.warning(`! ${message}`);
|
|
271
|
+
}
|
|
272
|
+
static info(message) {
|
|
273
|
+
return this.colors.dim(`i ${message}`);
|
|
274
|
+
}
|
|
275
|
+
static divider() {
|
|
276
|
+
return this.colors.dim("\u2500".repeat(50));
|
|
277
|
+
}
|
|
278
|
+
static dim(text) {
|
|
279
|
+
return this.colors.dim(text);
|
|
280
|
+
}
|
|
281
|
+
static table(headers, rows) {
|
|
282
|
+
const colWidths = headers.map((h, i) => {
|
|
283
|
+
const maxRowWidth = Math.max(...rows.map((r) => r[i]?.length || 0));
|
|
284
|
+
return Math.max(h.length, maxRowWidth);
|
|
285
|
+
});
|
|
286
|
+
const headerRow = headers.map((h, i) => h.padEnd(colWidths[i])).join(" ");
|
|
287
|
+
const separator = colWidths.map((w) => "\u2500".repeat(w)).join(" ");
|
|
288
|
+
const dataRows = rows.map((row) => row.map((cell, i) => cell.padEnd(colWidths[i])).join(" ")).join("\n");
|
|
289
|
+
return `${this.colors.bold(headerRow)}
|
|
290
|
+
${this.colors.dim(separator)}
|
|
291
|
+
${dataRows}`;
|
|
292
|
+
}
|
|
293
|
+
static progress(current, total, label) {
|
|
294
|
+
const percentage = Math.round(current / total * 100);
|
|
295
|
+
const barLength = 30;
|
|
296
|
+
const filled = Math.round(barLength * current / total);
|
|
297
|
+
const bar = "\u2588".repeat(filled) + "\u2591".repeat(barLength - filled);
|
|
298
|
+
return `${label} ${this.colors.primary(bar)} ${percentage}%`;
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// src/utils/helpers.ts
|
|
303
|
+
import ora from "ora";
|
|
304
|
+
import clipboard from "clipboardy";
|
|
305
|
+
async function copyToClipboard(text) {
|
|
306
|
+
try {
|
|
307
|
+
await clipboard.write(text);
|
|
308
|
+
console.log(UI.success("Copied to clipboard"));
|
|
309
|
+
} catch {
|
|
310
|
+
console.log(UI.warning("Failed to copy to clipboard"));
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function spinner(text) {
|
|
314
|
+
return ora({
|
|
315
|
+
text,
|
|
316
|
+
spinner: "dots",
|
|
317
|
+
color: "blue"
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function formatDate(date) {
|
|
321
|
+
return date.toLocaleDateString("en-US", {
|
|
322
|
+
month: "short",
|
|
323
|
+
day: "numeric",
|
|
324
|
+
year: "numeric"
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function formatDateRange(start, end) {
|
|
328
|
+
return `${formatDate(start)} - ${formatDate(end)}`;
|
|
329
|
+
}
|
|
330
|
+
function getWeekStart(weeksAgo = 0) {
|
|
331
|
+
const now = /* @__PURE__ */ new Date();
|
|
332
|
+
const dayOfWeek = now.getDay();
|
|
333
|
+
const monday = new Date(now);
|
|
334
|
+
monday.setDate(now.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1));
|
|
335
|
+
monday.setDate(monday.getDate() - weeksAgo * 7);
|
|
336
|
+
monday.setHours(0, 0, 0, 0);
|
|
337
|
+
return monday;
|
|
338
|
+
}
|
|
339
|
+
function getWeekEnd(weeksAgo = 0) {
|
|
340
|
+
const start = getWeekStart(weeksAgo);
|
|
341
|
+
const end = new Date(start);
|
|
342
|
+
end.setDate(start.getDate() + 6);
|
|
343
|
+
end.setHours(23, 59, 59, 999);
|
|
344
|
+
return end;
|
|
345
|
+
}
|
|
346
|
+
function getDaysAgo(days) {
|
|
347
|
+
const date = /* @__PURE__ */ new Date();
|
|
348
|
+
date.setDate(date.getDate() - days);
|
|
349
|
+
date.setHours(0, 0, 0, 0);
|
|
350
|
+
return date;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/commands/standup.ts
|
|
354
|
+
var standupCommand = new Command("standup").description("Generate standup notes from your recent commits").option("-d, --days <number>", "Number of days to look back", "1").option("-f, --format <type>", "Output format (markdown|slack|plain)", "markdown").option("--no-copy", "Do not copy to clipboard").action(async (options) => {
|
|
355
|
+
const git = new GitAnalyzer();
|
|
356
|
+
const copilot = new CopilotClient();
|
|
357
|
+
if (!await git.isRepository()) {
|
|
358
|
+
console.log(UI.error("Not a git repository"));
|
|
359
|
+
console.log(UI.info("Run this command inside a git repository"));
|
|
360
|
+
process.exit(1);
|
|
361
|
+
}
|
|
362
|
+
if (!await copilot.isInstalled()) {
|
|
363
|
+
console.log(UI.error("GitHub Copilot CLI not found"));
|
|
364
|
+
console.log(UI.info("Install with: gh extension install github/gh-copilot"));
|
|
365
|
+
process.exit(1);
|
|
366
|
+
}
|
|
367
|
+
const load = spinner("Analyzing your work...").start();
|
|
368
|
+
try {
|
|
369
|
+
const user = await git.getCurrentUser();
|
|
370
|
+
const days = parseInt(options.days, 10);
|
|
371
|
+
const since = getDaysAgo(days);
|
|
372
|
+
const commits = await git.getCommits({
|
|
373
|
+
since,
|
|
374
|
+
author: user.email
|
|
375
|
+
});
|
|
376
|
+
if (commits.length === 0) {
|
|
377
|
+
load.stop();
|
|
378
|
+
console.log(UI.warning(`No commits found in the last ${days} day(s)`));
|
|
379
|
+
console.log(UI.info(`Try: devdaily standup --days=${days + 1}`));
|
|
380
|
+
process.exit(0);
|
|
381
|
+
}
|
|
382
|
+
load.text = "Generating standup notes with Copilot CLI...";
|
|
383
|
+
const commitMessages = commits.map((c) => c.message);
|
|
384
|
+
const standup = await copilot.summarizeCommits(commitMessages);
|
|
385
|
+
load.stop();
|
|
386
|
+
const title = days === 1 ? "Your Standup" : `Your Work (Last ${days} Days)`;
|
|
387
|
+
const content = `${standup}
|
|
388
|
+
|
|
389
|
+
${UI.divider()}
|
|
390
|
+
${UI.dim(`${commits.length} commits analyzed`)}`;
|
|
391
|
+
console.log(UI.box(content, title));
|
|
392
|
+
if (options.copy) {
|
|
393
|
+
await copyToClipboard(standup);
|
|
394
|
+
}
|
|
395
|
+
} catch (error) {
|
|
396
|
+
load.stop();
|
|
397
|
+
console.log(UI.error("Failed to generate standup"));
|
|
398
|
+
console.log(UI.dim(error.message));
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// src/commands/pr.ts
|
|
404
|
+
import { Command as Command2 } from "commander";
|
|
405
|
+
import inquirer from "inquirer";
|
|
406
|
+
import { execa as execa2 } from "execa";
|
|
407
|
+
import open from "open";
|
|
408
|
+
|
|
409
|
+
// src/utils/commitlint.ts
|
|
410
|
+
var COMMIT_PATTERN = (
|
|
411
|
+
// eslint-disable-next-line no-useless-escape
|
|
412
|
+
/^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\([^\)]+\))?(!)?:\s*(.+)$/
|
|
413
|
+
);
|
|
414
|
+
function parseConventionalCommit(message) {
|
|
415
|
+
const match = message.match(COMMIT_PATTERN);
|
|
416
|
+
if (!match) {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
const [, type, scope, breaking, subject] = match;
|
|
420
|
+
return {
|
|
421
|
+
type,
|
|
422
|
+
scope: scope?.replace(/[()]/g, ""),
|
|
423
|
+
subject: subject.trim(),
|
|
424
|
+
breaking: breaking === "!"
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function extractIssueNumbers(text) {
|
|
428
|
+
const issuePattern = /#(\d+)/g;
|
|
429
|
+
const matches = text.matchAll(issuePattern);
|
|
430
|
+
return Array.from(matches, (m) => `#${m[1]}`);
|
|
431
|
+
}
|
|
432
|
+
function generatePRTitle(commits) {
|
|
433
|
+
const parsed = commits.map(parseConventionalCommit).filter((c) => c !== null);
|
|
434
|
+
if (parsed.length === 0) {
|
|
435
|
+
return commits[0] || "Update";
|
|
436
|
+
}
|
|
437
|
+
const features = parsed.filter((c) => c.type === "feat");
|
|
438
|
+
const fixes = parsed.filter((c) => c.type === "fix");
|
|
439
|
+
if (features.length > 0) {
|
|
440
|
+
return features[0].subject;
|
|
441
|
+
}
|
|
442
|
+
if (fixes.length > 0) {
|
|
443
|
+
return `Fix: ${fixes[0].subject}`;
|
|
444
|
+
}
|
|
445
|
+
return parsed[0].subject;
|
|
446
|
+
}
|
|
447
|
+
function categorizePRType(commits) {
|
|
448
|
+
const parsed = commits.map(parseConventionalCommit).filter((c) => c !== null);
|
|
449
|
+
const hasFeatures = parsed.some((c) => c.type === "feat");
|
|
450
|
+
const hasFixes = parsed.some((c) => c.type === "fix");
|
|
451
|
+
const hasBreaking = parsed.some((c) => c.breaking);
|
|
452
|
+
if (hasBreaking) return "breaking";
|
|
453
|
+
if (hasFeatures) return "feature";
|
|
454
|
+
if (hasFixes) return "bugfix";
|
|
455
|
+
return "chore";
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/commands/pr.ts
|
|
459
|
+
var prCommand = new Command2("pr").description("Generate PR description from current branch").option("-b, --base <branch>", "Base branch to compare against", "main").option("-c, --create", "Create PR on GitHub").option("-d, --draft", "Create as draft PR").option("-e, --edit", "Edit description before creating").action(async (options) => {
|
|
460
|
+
const git = new GitAnalyzer();
|
|
461
|
+
const copilot = new CopilotClient();
|
|
462
|
+
if (!await git.isRepository()) {
|
|
463
|
+
console.log(UI.error("Not a git repository"));
|
|
464
|
+
process.exit(1);
|
|
465
|
+
}
|
|
466
|
+
if (!await copilot.isInstalled()) {
|
|
467
|
+
console.log(UI.error("GitHub Copilot CLI not found"));
|
|
468
|
+
console.log(UI.info("Install with: gh extension install github/gh-copilot"));
|
|
469
|
+
process.exit(1);
|
|
470
|
+
}
|
|
471
|
+
const load = spinner("Analyzing branch...").start();
|
|
472
|
+
try {
|
|
473
|
+
const currentBranch = await git.getCurrentBranch();
|
|
474
|
+
if (currentBranch === options.base) {
|
|
475
|
+
load.stop();
|
|
476
|
+
console.log(UI.error(`Cannot create PR from ${options.base} branch`));
|
|
477
|
+
console.log(UI.info("Switch to a feature branch first"));
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
const commits = await git.getCommits();
|
|
481
|
+
if (commits.length === 0) {
|
|
482
|
+
load.stop();
|
|
483
|
+
console.log(UI.warning("No commits on this branch"));
|
|
484
|
+
process.exit(0);
|
|
485
|
+
}
|
|
486
|
+
const files = await git.getChangedFiles(options.base);
|
|
487
|
+
const commitMessages = commits.map((c) => c.message);
|
|
488
|
+
const allText = commitMessages.join(" ");
|
|
489
|
+
const issues = extractIssueNumbers(allText);
|
|
490
|
+
const suggestedTitle = generatePRTitle(commitMessages);
|
|
491
|
+
const prType = categorizePRType(commitMessages);
|
|
492
|
+
load.text = "Generating PR description with Copilot CLI...";
|
|
493
|
+
const description = await copilot.generatePRDescription({
|
|
494
|
+
branch: currentBranch,
|
|
495
|
+
commits: commitMessages,
|
|
496
|
+
files,
|
|
497
|
+
issues
|
|
498
|
+
});
|
|
499
|
+
load.stop();
|
|
500
|
+
console.log(
|
|
501
|
+
UI.box(
|
|
502
|
+
`${UI.colors.bold(suggestedTitle)}
|
|
503
|
+
|
|
504
|
+
${description}
|
|
505
|
+
|
|
506
|
+
${UI.divider()}
|
|
507
|
+
${UI.dim(`${commits.length} commits \u2022 ${files.length} files changed \u2022 ${prType}`)}`,
|
|
508
|
+
`PR Description for ${currentBranch}`
|
|
509
|
+
)
|
|
510
|
+
);
|
|
511
|
+
const { action } = await inquirer.prompt([
|
|
512
|
+
{
|
|
513
|
+
type: "list",
|
|
514
|
+
name: "action",
|
|
515
|
+
message: "What would you like to do?",
|
|
516
|
+
choices: [
|
|
517
|
+
{ name: "Preview in browser (render markdown)", value: "preview" },
|
|
518
|
+
{ name: "Copy to clipboard", value: "copy" },
|
|
519
|
+
{ name: "Create PR on GitHub", value: "create" },
|
|
520
|
+
{ name: "Create draft PR", value: "draft" },
|
|
521
|
+
{ name: "Exit", value: "exit" }
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
]);
|
|
525
|
+
if (action === "copy") {
|
|
526
|
+
await copyToClipboard(description);
|
|
527
|
+
} else if (action === "preview") {
|
|
528
|
+
console.log(UI.info("Opening preview in browser..."));
|
|
529
|
+
await open(`https://github.com`);
|
|
530
|
+
} else if (action === "create" || action === "draft") {
|
|
531
|
+
const isDraft = action === "draft" || options.draft;
|
|
532
|
+
const createSpinner = spinner(`Creating ${isDraft ? "draft " : ""}PR...`).start();
|
|
533
|
+
try {
|
|
534
|
+
const args = [
|
|
535
|
+
"pr",
|
|
536
|
+
"create",
|
|
537
|
+
"--title",
|
|
538
|
+
suggestedTitle,
|
|
539
|
+
"--body",
|
|
540
|
+
description,
|
|
541
|
+
"--base",
|
|
542
|
+
options.base
|
|
543
|
+
];
|
|
544
|
+
if (isDraft) {
|
|
545
|
+
args.push("--draft");
|
|
546
|
+
}
|
|
547
|
+
const { stdout } = await execa2("gh", args);
|
|
548
|
+
createSpinner.stop();
|
|
549
|
+
console.log(UI.success("PR created successfully"));
|
|
550
|
+
console.log(UI.dim(stdout));
|
|
551
|
+
} catch (error) {
|
|
552
|
+
createSpinner.stop();
|
|
553
|
+
console.log(UI.error("Failed to create PR"));
|
|
554
|
+
console.log(UI.dim(error.message));
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
} catch (error) {
|
|
558
|
+
load.stop();
|
|
559
|
+
console.log(UI.error("Failed to generate PR description"));
|
|
560
|
+
console.log(UI.dim(error.message));
|
|
561
|
+
process.exit(1);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// src/commands/week.ts
|
|
566
|
+
import { Command as Command3 } from "commander";
|
|
567
|
+
var weekCommand = new Command3("week").description("Generate weekly work summary").option("-l, --last", "Last week instead of current week").option("--no-copy", "Do not copy to clipboard").action(async (options) => {
|
|
568
|
+
const git = new GitAnalyzer();
|
|
569
|
+
const copilot = new CopilotClient();
|
|
570
|
+
if (!await git.isRepository()) {
|
|
571
|
+
console.log(UI.error("Not a git repository"));
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
574
|
+
if (!await copilot.isInstalled()) {
|
|
575
|
+
console.log(UI.error("GitHub Copilot CLI not found"));
|
|
576
|
+
process.exit(1);
|
|
577
|
+
}
|
|
578
|
+
const load = spinner("Analyzing your week...").start();
|
|
579
|
+
try {
|
|
580
|
+
const weeksAgo = options.last ? 1 : 0;
|
|
581
|
+
const start = getWeekStart(weeksAgo);
|
|
582
|
+
const end = getWeekEnd(weeksAgo);
|
|
583
|
+
const user = await git.getCurrentUser();
|
|
584
|
+
const commits = await git.getCommits({
|
|
585
|
+
since: start,
|
|
586
|
+
until: end,
|
|
587
|
+
author: user.email
|
|
588
|
+
});
|
|
589
|
+
if (commits.length === 0) {
|
|
590
|
+
load.stop();
|
|
591
|
+
console.log(UI.warning("No commits found this week"));
|
|
592
|
+
process.exit(0);
|
|
593
|
+
}
|
|
594
|
+
const stats = await git.getDiffStats();
|
|
595
|
+
load.text = "Generating summary with Copilot CLI...";
|
|
596
|
+
const commitMessages = commits.map((c) => c.message);
|
|
597
|
+
const summary = await copilot.generateWeeklySummary({
|
|
598
|
+
commits: commitMessages,
|
|
599
|
+
stats: {
|
|
600
|
+
commits: commits.length,
|
|
601
|
+
linesAdded: stats.insertions,
|
|
602
|
+
linesRemoved: stats.deletions
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
load.stop();
|
|
606
|
+
const title = `Week in Review (${formatDateRange(start, end)})`;
|
|
607
|
+
const content = `${summary}
|
|
608
|
+
|
|
609
|
+
${UI.divider()}
|
|
610
|
+
${UI.dim(`${commits.length} commits \u2022 ${stats.insertions}+ ${stats.deletions}- lines`)}`;
|
|
611
|
+
console.log(UI.box(content, title));
|
|
612
|
+
if (options.copy) {
|
|
613
|
+
await copyToClipboard(summary);
|
|
614
|
+
}
|
|
615
|
+
} catch (error) {
|
|
616
|
+
load.stop();
|
|
617
|
+
console.log(UI.error("Failed to generate weekly summary"));
|
|
618
|
+
console.log(UI.dim(error.message));
|
|
619
|
+
process.exit(1);
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// src/commands/context.ts
|
|
624
|
+
import { Command as Command4 } from "commander";
|
|
625
|
+
var contextCommand = new Command4("context").description("Recover what you were working on (coming soon)").action(async () => {
|
|
626
|
+
console.log(UI.info("Context recovery feature coming soon!"));
|
|
627
|
+
console.log(UI.dim("This will help you remember what you were working on after interruptions"));
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// src/index.ts
|
|
631
|
+
var program = new Command5();
|
|
632
|
+
program.name("devdaily").description("Your AI memory for developer work").version("1.0.0");
|
|
633
|
+
program.addCommand(standupCommand);
|
|
634
|
+
program.addCommand(prCommand);
|
|
635
|
+
program.addCommand(weekCommand);
|
|
636
|
+
program.addCommand(contextCommand);
|
|
637
|
+
program.parse();
|
|
638
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/standup.ts","../src/core/git-analyzer.ts","../src/core/copilot.ts","../src/utils/ui.ts","../src/utils/helpers.ts","../src/commands/pr.ts","../src/utils/commitlint.ts","../src/commands/week.ts","../src/commands/context.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { standupCommand } from './commands/standup.js';\nimport { prCommand } from './commands/pr.js';\nimport { weekCommand } from './commands/week.js';\nimport { contextCommand } from './commands/context.js';\n\nconst program = new Command();\n\nprogram.name('devdaily').description('Your AI memory for developer work').version('1.0.0');\n\n// Register commands\nprogram.addCommand(standupCommand);\nprogram.addCommand(prCommand);\nprogram.addCommand(weekCommand);\nprogram.addCommand(contextCommand);\n\n// Parse and execute\nprogram.parse();\n","import { Command } from 'commander';\nimport { GitAnalyzer } from '../core/git-analyzer.js';\nimport { CopilotClient } from '../core/copilot.js';\nimport { UI } from '../utils/ui.js';\nimport { spinner, copyToClipboard, getDaysAgo } from '../utils/helpers.js';\n\nexport const standupCommand = new Command('standup')\n .description('Generate standup notes from your recent commits')\n .option('-d, --days <number>', 'Number of days to look back', '1')\n .option('-f, --format <type>', 'Output format (markdown|slack|plain)', 'markdown')\n .option('--no-copy', 'Do not copy to clipboard')\n .action(async (options) => {\n const git = new GitAnalyzer();\n const copilot = new CopilotClient();\n\n // Check if in git repo\n if (!(await git.isRepository())) {\n console.log(UI.error('Not a git repository'));\n console.log(UI.info('Run this command inside a git repository'));\n process.exit(1);\n }\n\n // Check if Copilot CLI is installed\n if (!(await copilot.isInstalled())) {\n console.log(UI.error('GitHub Copilot CLI not found'));\n console.log(UI.info('Install with: gh extension install github/gh-copilot'));\n process.exit(1);\n }\n\n const load = spinner('Analyzing your work...').start();\n\n try {\n // Get user info\n const user = await git.getCurrentUser();\n\n // Get commits\n const days = parseInt(options.days, 10);\n const since = getDaysAgo(days);\n const commits = await git.getCommits({\n since,\n author: user.email,\n });\n\n if (commits.length === 0) {\n load.stop();\n console.log(UI.warning(`No commits found in the last ${days} day(s)`));\n console.log(UI.info(`Try: devdaily standup --days=${days + 1}`));\n process.exit(0);\n }\n\n load.text = 'Generating standup notes with Copilot CLI...';\n\n // Generate standup using Copilot\n const commitMessages = commits.map((c) => c.message);\n const standup = await copilot.summarizeCommits(commitMessages);\n\n load.stop();\n\n // Format output\n const title = days === 1 ? 'Your Standup' : `Your Work (Last ${days} Days)`;\n const content = `${standup}\\n\\n${UI.divider()}\\n${UI.dim(`${commits.length} commits analyzed`)}`;\n\n console.log(UI.box(content, title));\n\n // Copy to clipboard\n if (options.copy) {\n await copyToClipboard(standup);\n }\n } catch (error) {\n load.stop();\n console.log(UI.error('Failed to generate standup'));\n console.log(UI.dim((error as Error).message));\n process.exit(1);\n }\n });\n","import simpleGit, { SimpleGit, LogResult } from 'simple-git';\nimport type { Commit, CommitOptions, DiffStats } from '../types/index.js';\n\nexport class GitAnalyzer {\n private git: SimpleGit;\n\n constructor(repoPath?: string) {\n this.git = simpleGit(repoPath || process.cwd());\n }\n\n async isRepository(): Promise<boolean> {\n try {\n await this.git.revparse(['--is-inside-work-tree']);\n return true;\n } catch {\n return false;\n }\n }\n\n async getCurrentBranch(): Promise<string> {\n const branch = await this.git.revparse(['--abbrev-ref', 'HEAD']);\n return branch.trim();\n }\n\n async getCommits(options: CommitOptions = {}): Promise<Commit[]> {\n const logOptions: any = {\n format: {\n hash: '%H',\n message: '%s',\n body: '%b',\n author: '%an',\n date: '%ai',\n },\n };\n\n if (options.since) {\n logOptions.from = options.since.toISOString();\n }\n\n if (options.until) {\n logOptions.to = options.until.toISOString();\n }\n\n if (options.author) {\n logOptions.author = options.author;\n }\n\n const log: LogResult = await this.git.log(logOptions);\n\n return log.all.map((commit: any) => ({\n hash: commit.hash,\n message: commit.message,\n author: commit.author,\n date: new Date(commit.date),\n body: commit.body,\n }));\n }\n\n async getDiff(base: string = 'main', head: string = 'HEAD'): Promise<string> {\n const diff = await this.git.diff([`${base}...${head}`]);\n return diff;\n }\n\n async getDiffStats(base: string = 'main', head: string = 'HEAD'): Promise<DiffStats> {\n const diffSummary = await this.git.diffSummary([`${base}...${head}`]);\n\n return {\n filesChanged: diffSummary.files.length,\n insertions: diffSummary.insertions,\n deletions: diffSummary.deletions,\n };\n }\n\n async getChangedFiles(base: string = 'main', head: string = 'HEAD'): Promise<string[]> {\n const diff = await this.git.diff([`${base}...${head}`, '--name-only']);\n return diff.split('\\n').filter(Boolean);\n }\n\n async getCurrentUser(): Promise<{ name: string; email: string }> {\n const name = await this.git.getConfig('user.name');\n const email = await this.git.getConfig('user.email');\n\n return {\n name: name.value || '',\n email: email.value || '',\n };\n }\n\n async getStatus(): Promise<{ modified: string[]; untracked: string[] }> {\n const status = await this.git.status();\n\n return {\n modified: status.modified,\n untracked: status.not_added,\n };\n }\n\n async hasUncommittedChanges(): Promise<boolean> {\n const status = await this.git.status();\n return !status.isClean();\n }\n}\n","import { execa } from 'execa';\n\nexport class CopilotClient {\n async isInstalled(): Promise<boolean> {\n try {\n await execa('gh', ['copilot', '--version']);\n return true;\n } catch {\n return false;\n }\n }\n\n async suggest(prompt: string): Promise<string> {\n try {\n const { stdout } = await execa('gh', ['copilot', 'suggest', '-t', 'shell', prompt]);\n\n return this.parseOutput(stdout);\n } catch (error) {\n throw new Error(`Copilot CLI error: ${error}`);\n }\n }\n\n async explain(code: string): Promise<string> {\n try {\n const { stdout } = await execa('gh', ['copilot', 'explain', code]);\n return this.parseOutput(stdout);\n } catch (error) {\n throw new Error(`Copilot CLI error: ${error}`);\n }\n }\n\n private parseOutput(raw: string): string {\n // The gh copilot CLI wraps output in UI elements\n // We need to extract just the AI response\n\n // Remove ANSI codes\n // eslint-disable-next-line no-control-regex\n const cleaned = raw.replace(/\\x1B\\[[0-9;]*[a-zA-Z]/g, '');\n\n // Extract the actual suggestion (between prompts)\n const lines = cleaned.split('\\n');\n const relevantLines = lines.filter(\n (line) =>\n line.trim() &&\n !line.includes('Suggestion:') &&\n !line.includes('Explain command:') &&\n !line.includes('?')\n );\n\n return relevantLines.join('\\n').trim();\n }\n\n async summarizeCommits(commits: string[]): Promise<string> {\n const prompt = `\nYou are helping a developer write their standup notes.\n\nHere are their git commits from yesterday:\n${commits.map((c, i) => `${i + 1}. ${c}`).join('\\n')}\n\nGenerate a professional standup update following this format:\n\nYesterday I:\n- [achievement 1 with impact]\n- [achievement 2 with impact]\n- [achievement 3 with impact]\n\nToday I'm working on:\n- [planned work based on commits]\n\nBlockers: None\n\nRequirements:\n- Make it sound natural and professional\n- Focus on WHAT was accomplished, not HOW\n- Highlight business impact when possible\n- Keep it concise (3-5 bullet points max)\n- No emojis\n`;\n\n return this.suggest(prompt);\n }\n\n async generatePRDescription(data: {\n branch: string;\n commits: string[];\n files: string[];\n issues: string[];\n }): Promise<string> {\n const prompt = `\nYou are helping a developer create a Pull Request description.\n\nBranch: ${data.branch}\n\nCommits:\n${data.commits.map((c, i) => `${i + 1}. ${c}`).join('\\n')}\n\nFiles changed:\n${data.files.join('\\n')}\n\nRelated issues: ${data.issues.length > 0 ? data.issues.join(', ') : 'None'}\n\nGenerate a comprehensive PR description following this template:\n\n## What Changed\n- [bullet point 1]\n- [bullet point 2]\n- [bullet point 3]\n\n## Why\n[Business or technical reason for these changes]\n${data.issues.length > 0 ? `Closes ${data.issues.join(', ')}` : ''}\n\n## How to Test\n1. [testing step 1]\n2. [testing step 2]\n3. [testing step 3]\n\nRequirements:\n- Be specific and technical where appropriate\n- Focus on value for code reviewers\n- Keep it clear and concise\n- No emojis\n`;\n\n return this.suggest(prompt);\n }\n\n async generateWeeklySummary(data: {\n commits: string[];\n stats: {\n commits: number;\n linesAdded: number;\n linesRemoved: number;\n };\n }): Promise<string> {\n const prompt = `\nYou are helping a developer create their weekly work summary.\n\nThis week's commits:\n${data.commits.map((c, i) => `${i + 1}. ${c}`).join('\\n')}\n\nStatistics:\n- ${data.stats.commits} commits\n- ${data.stats.linesAdded} lines added\n- ${data.stats.linesRemoved} lines removed\n\nGenerate a professional weekly summary following this format:\n\nKey Accomplishments:\n1. [Major accomplishment with impact]\n2. [Second accomplishment]\n3. [Third accomplishment]\n4. [Fourth accomplishment]\n5. [Fifth accomplishment]\n\nTop Achievement:\n[Single sentence highlighting the most impactful work]\n\nRequirements:\n- Focus on business value and impact\n- Be suitable for sharing with manager or team\n- Highlight 3-5 key accomplishments\n- Keep it professional\n- No emojis\n`;\n\n return this.suggest(prompt);\n }\n}\n","import chalk from 'chalk';\nimport boxen from 'boxen';\n\n// Clean, minimal UI inspired by terminal.shop\n// No emojis, professional output\n\nexport class UI {\n static readonly colors = {\n primary: chalk.blue,\n success: chalk.green,\n warning: chalk.yellow,\n error: chalk.red,\n dim: chalk.gray,\n bold: chalk.bold,\n };\n\n static header(title: string): string {\n return this.colors.bold(title);\n }\n\n static section(title: string, content: string): string {\n return `\\n${this.colors.primary(title)}\\n${content}`;\n }\n\n static box(content: string, title?: string): string {\n return boxen(content, {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'blue',\n title: title,\n titleAlignment: 'left',\n });\n }\n\n static list(items: string[]): string {\n return items.map((item) => ` ${this.colors.dim('>')} ${item}`).join('\\n');\n }\n\n static success(message: string): string {\n return this.colors.success(`✓ ${message}`);\n }\n\n static error(message: string): string {\n return this.colors.error(`✗ ${message}`);\n }\n\n static warning(message: string): string {\n return this.colors.warning(`! ${message}`);\n }\n\n static info(message: string): string {\n return this.colors.dim(`i ${message}`);\n }\n\n static divider(): string {\n return this.colors.dim('─'.repeat(50));\n }\n\n static dim(text: string): string {\n return this.colors.dim(text);\n }\n\n static table(headers: string[], rows: string[][]): string {\n const colWidths = headers.map((h, i) => {\n const maxRowWidth = Math.max(...rows.map((r) => r[i]?.length || 0));\n return Math.max(h.length, maxRowWidth);\n });\n\n const headerRow = headers.map((h, i) => h.padEnd(colWidths[i])).join(' ');\n\n const separator = colWidths.map((w) => '─'.repeat(w)).join(' ');\n\n const dataRows = rows\n .map((row) => row.map((cell, i) => cell.padEnd(colWidths[i])).join(' '))\n .join('\\n');\n\n return `${this.colors.bold(headerRow)}\\n${this.colors.dim(separator)}\\n${dataRows}`;\n }\n\n static progress(current: number, total: number, label: string): string {\n const percentage = Math.round((current / total) * 100);\n const barLength = 30;\n const filled = Math.round((barLength * current) / total);\n const bar = '█'.repeat(filled) + '░'.repeat(barLength - filled);\n\n return `${label} ${this.colors.primary(bar)} ${percentage}%`;\n }\n}\n","import ora from 'ora';\nimport clipboard from 'clipboardy';\nimport { UI } from './ui.js';\n\nexport async function copyToClipboard(text: string): Promise<void> {\n try {\n await clipboard.write(text);\n console.log(UI.success('Copied to clipboard'));\n } catch {\n console.log(UI.warning('Failed to copy to clipboard'));\n }\n}\n\nexport function spinner(text: string) {\n return ora({\n text,\n spinner: 'dots',\n color: 'blue',\n });\n}\n\nexport function formatDate(date: Date): string {\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n}\n\nexport function formatDateRange(start: Date, end: Date): string {\n return `${formatDate(start)} - ${formatDate(end)}`;\n}\n\nexport function getWeekStart(weeksAgo: number = 0): Date {\n const now = new Date();\n const dayOfWeek = now.getDay();\n const monday = new Date(now);\n monday.setDate(now.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1));\n monday.setDate(monday.getDate() - weeksAgo * 7);\n monday.setHours(0, 0, 0, 0);\n return monday;\n}\n\nexport function getWeekEnd(weeksAgo: number = 0): Date {\n const start = getWeekStart(weeksAgo);\n const end = new Date(start);\n end.setDate(start.getDate() + 6);\n end.setHours(23, 59, 59, 999);\n return end;\n}\n\nexport function getDaysAgo(days: number): Date {\n const date = new Date();\n date.setDate(date.getDate() - days);\n date.setHours(0, 0, 0, 0);\n return date;\n}\n","import { Command } from 'commander';\nimport inquirer from 'inquirer';\nimport { execa } from 'execa';\nimport open from 'open';\nimport { GitAnalyzer } from '../core/git-analyzer.js';\nimport { CopilotClient } from '../core/copilot.js';\nimport { UI } from '../utils/ui.js';\nimport { spinner, copyToClipboard } from '../utils/helpers.js';\nimport { extractIssueNumbers, generatePRTitle, categorizePRType } from '../utils/commitlint.js';\n\nexport const prCommand = new Command('pr')\n .description('Generate PR description from current branch')\n .option('-b, --base <branch>', 'Base branch to compare against', 'main')\n .option('-c, --create', 'Create PR on GitHub')\n .option('-d, --draft', 'Create as draft PR')\n .option('-e, --edit', 'Edit description before creating')\n .action(async (options) => {\n const git = new GitAnalyzer();\n const copilot = new CopilotClient();\n\n // Check if in git repo\n if (!(await git.isRepository())) {\n console.log(UI.error('Not a git repository'));\n process.exit(1);\n }\n\n // Check if Copilot CLI is installed\n if (!(await copilot.isInstalled())) {\n console.log(UI.error('GitHub Copilot CLI not found'));\n console.log(UI.info('Install with: gh extension install github/gh-copilot'));\n process.exit(1);\n }\n\n const load = spinner('Analyzing branch...').start();\n\n try {\n // Get current branch\n const currentBranch = await git.getCurrentBranch();\n\n if (currentBranch === options.base) {\n load.stop();\n console.log(UI.error(`Cannot create PR from ${options.base} branch`));\n console.log(UI.info('Switch to a feature branch first'));\n process.exit(1);\n }\n\n // Get commits on this branch\n const commits = await git.getCommits();\n\n if (commits.length === 0) {\n load.stop();\n console.log(UI.warning('No commits on this branch'));\n process.exit(0);\n }\n\n // Get changed files\n const files = await git.getChangedFiles(options.base);\n\n // Extract issue numbers\n const commitMessages = commits.map((c) => c.message);\n const allText = commitMessages.join(' ');\n const issues = extractIssueNumbers(allText);\n\n // Generate PR title from commits\n const suggestedTitle = generatePRTitle(commitMessages);\n const prType = categorizePRType(commitMessages);\n\n load.text = 'Generating PR description with Copilot CLI...';\n\n // Generate description\n const description = await copilot.generatePRDescription({\n branch: currentBranch,\n commits: commitMessages,\n files,\n issues,\n });\n\n load.stop();\n\n // Display\n console.log(\n UI.box(\n `${UI.colors.bold(suggestedTitle)}\\n\\n${description}\\n\\n${UI.divider()}\\n${UI.dim(`${commits.length} commits • ${files.length} files changed • ${prType}`)}`,\n `PR Description for ${currentBranch}`\n )\n );\n\n // Interactive options\n const { action } = await inquirer.prompt([\n {\n type: 'list',\n name: 'action',\n message: 'What would you like to do?',\n choices: [\n { name: 'Preview in browser (render markdown)', value: 'preview' },\n { name: 'Copy to clipboard', value: 'copy' },\n { name: 'Create PR on GitHub', value: 'create' },\n { name: 'Create draft PR', value: 'draft' },\n { name: 'Exit', value: 'exit' },\n ],\n },\n ]);\n\n if (action === 'copy') {\n await copyToClipboard(description);\n } else if (action === 'preview') {\n // Create temporary markdown file and open in browser\n console.log(UI.info('Opening preview in browser...'));\n // TODO: Implement preview (save to temp file, open with `open` package)\n await open(`https://github.com`);\n } else if (action === 'create' || action === 'draft') {\n const isDraft = action === 'draft' || options.draft;\n\n const createSpinner = spinner(`Creating ${isDraft ? 'draft ' : ''}PR...`).start();\n\n try {\n const args = [\n 'pr',\n 'create',\n '--title',\n suggestedTitle,\n '--body',\n description,\n '--base',\n options.base,\n ];\n\n if (isDraft) {\n args.push('--draft');\n }\n\n const { stdout } = await execa('gh', args);\n\n createSpinner.stop();\n console.log(UI.success('PR created successfully'));\n console.log(UI.dim(stdout));\n } catch (error) {\n createSpinner.stop();\n console.log(UI.error('Failed to create PR'));\n console.log(UI.dim((error as Error).message));\n }\n }\n } catch (error) {\n load.stop();\n console.log(UI.error('Failed to generate PR description'));\n console.log(UI.dim((error as Error).message));\n process.exit(1);\n }\n });\n","import type { ConventionalCommit } from '../types/index.js';\n\nconst COMMIT_PATTERN =\n // eslint-disable-next-line no-useless-escape\n /^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\\([^\\)]+\\))?(!)?:\\s*(.+)$/;\n\nexport function parseConventionalCommit(message: string): ConventionalCommit | null {\n const match = message.match(COMMIT_PATTERN);\n\n if (!match) {\n return null;\n }\n\n const [, type, scope, breaking, subject] = match;\n\n return {\n type: type as ConventionalCommit['type'],\n scope: scope?.replace(/[()]/g, ''),\n subject: subject.trim(),\n breaking: breaking === '!',\n };\n}\n\nexport function extractIssueNumbers(text: string): string[] {\n const issuePattern = /#(\\d+)/g;\n const matches = text.matchAll(issuePattern);\n return Array.from(matches, (m) => `#${m[1]}`);\n}\n\nexport function generatePRTitle(commits: string[]): string {\n // Try to parse conventional commits\n const parsed = commits\n .map(parseConventionalCommit)\n .filter((c): c is ConventionalCommit => c !== null);\n\n if (parsed.length === 0) {\n // Fallback: use first commit message\n return commits[0] || 'Update';\n }\n\n // Group by type\n const features = parsed.filter((c) => c.type === 'feat');\n const fixes = parsed.filter((c) => c.type === 'fix');\n\n if (features.length > 0) {\n return features[0].subject;\n }\n\n if (fixes.length > 0) {\n return `Fix: ${fixes[0].subject}`;\n }\n\n return parsed[0].subject;\n}\n\nexport function categorizePRType(commits: string[]): string {\n const parsed = commits\n .map(parseConventionalCommit)\n .filter((c): c is ConventionalCommit => c !== null);\n\n const hasFeatures = parsed.some((c) => c.type === 'feat');\n const hasFixes = parsed.some((c) => c.type === 'fix');\n const hasBreaking = parsed.some((c) => c.breaking);\n\n if (hasBreaking) return 'breaking';\n if (hasFeatures) return 'feature';\n if (hasFixes) return 'bugfix';\n return 'chore';\n}\n","import { Command } from 'commander';\nimport { GitAnalyzer } from '../core/git-analyzer.js';\nimport { CopilotClient } from '../core/copilot.js';\nimport { UI } from '../utils/ui.js';\nimport {\n spinner,\n copyToClipboard,\n getWeekStart,\n getWeekEnd,\n formatDateRange,\n} from '../utils/helpers.js';\n\nexport const weekCommand = new Command('week')\n .description('Generate weekly work summary')\n .option('-l, --last', 'Last week instead of current week')\n .option('--no-copy', 'Do not copy to clipboard')\n .action(async (options) => {\n const git = new GitAnalyzer();\n const copilot = new CopilotClient();\n\n // Check if in git repo\n if (!(await git.isRepository())) {\n console.log(UI.error('Not a git repository'));\n process.exit(1);\n }\n\n // Check if Copilot CLI is installed\n if (!(await copilot.isInstalled())) {\n console.log(UI.error('GitHub Copilot CLI not found'));\n process.exit(1);\n }\n\n const load = spinner('Analyzing your week...').start();\n\n try {\n const weeksAgo = options.last ? 1 : 0;\n const start = getWeekStart(weeksAgo);\n const end = getWeekEnd(weeksAgo);\n\n // Get user info\n const user = await git.getCurrentUser();\n\n // Get commits\n const commits = await git.getCommits({\n since: start,\n until: end,\n author: user.email,\n });\n\n if (commits.length === 0) {\n load.stop();\n console.log(UI.warning('No commits found this week'));\n process.exit(0);\n }\n\n // Get stats\n const stats = await git.getDiffStats();\n\n load.text = 'Generating summary with Copilot CLI...';\n\n // Generate summary\n const commitMessages = commits.map((c) => c.message);\n const summary = await copilot.generateWeeklySummary({\n commits: commitMessages,\n stats: {\n commits: commits.length,\n linesAdded: stats.insertions,\n linesRemoved: stats.deletions,\n },\n });\n\n load.stop();\n\n // Display\n const title = `Week in Review (${formatDateRange(start, end)})`;\n const content = `${summary}\\n\\n${UI.divider()}\\n${UI.dim(`${commits.length} commits • ${stats.insertions}+ ${stats.deletions}- lines`)}`;\n\n console.log(UI.box(content, title));\n\n // Copy to clipboard\n if (options.copy) {\n await copyToClipboard(summary);\n }\n } catch (error) {\n load.stop();\n console.log(UI.error('Failed to generate weekly summary'));\n console.log(UI.dim((error as Error).message));\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { UI } from '../utils/ui.js';\n\nexport const contextCommand = new Command('context')\n .description('Recover what you were working on (coming soon)')\n .action(async () => {\n console.log(UI.info('Context recovery feature coming soon!'));\n console.log(UI.dim('This will help you remember what you were working on after interruptions'));\n });\n"],"mappings":";;;;AACA,SAAS,WAAAA,gBAAe;;;ACDxB,SAAS,eAAe;;;ACAxB,OAAO,eAAyC;AAGzC,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EAER,YAAY,UAAmB;AAC7B,SAAK,MAAM,UAAU,YAAY,QAAQ,IAAI,CAAC;AAAA,EAChD;AAAA,EAEA,MAAM,eAAiC;AACrC,QAAI;AACF,YAAM,KAAK,IAAI,SAAS,CAAC,uBAAuB,CAAC;AACjD,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,mBAAoC;AACxC,UAAM,SAAS,MAAM,KAAK,IAAI,SAAS,CAAC,gBAAgB,MAAM,CAAC;AAC/D,WAAO,OAAO,KAAK;AAAA,EACrB;AAAA,EAEA,MAAM,WAAW,UAAyB,CAAC,GAAsB;AAC/D,UAAM,aAAkB;AAAA,MACtB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,QAAQ,OAAO;AACjB,iBAAW,OAAO,QAAQ,MAAM,YAAY;AAAA,IAC9C;AAEA,QAAI,QAAQ,OAAO;AACjB,iBAAW,KAAK,QAAQ,MAAM,YAAY;AAAA,IAC5C;AAEA,QAAI,QAAQ,QAAQ;AAClB,iBAAW,SAAS,QAAQ;AAAA,IAC9B;AAEA,UAAM,MAAiB,MAAM,KAAK,IAAI,IAAI,UAAU;AAEpD,WAAO,IAAI,IAAI,IAAI,CAAC,YAAiB;AAAA,MACnC,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,MAChB,QAAQ,OAAO;AAAA,MACf,MAAM,IAAI,KAAK,OAAO,IAAI;AAAA,MAC1B,MAAM,OAAO;AAAA,IACf,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,OAAe,QAAQ,OAAe,QAAyB;AAC3E,UAAM,OAAO,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC;AACtD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,OAAe,QAAQ,OAAe,QAA4B;AACnF,UAAM,cAAc,MAAM,KAAK,IAAI,YAAY,CAAC,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC;AAEpE,WAAO;AAAA,MACL,cAAc,YAAY,MAAM;AAAA,MAChC,YAAY,YAAY;AAAA,MACxB,WAAW,YAAY;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,OAAe,QAAQ,OAAe,QAA2B;AACrF,UAAM,OAAO,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG,IAAI,MAAM,IAAI,IAAI,aAAa,CAAC;AACrE,WAAO,KAAK,MAAM,IAAI,EAAE,OAAO,OAAO;AAAA,EACxC;AAAA,EAEA,MAAM,iBAA2D;AAC/D,UAAM,OAAO,MAAM,KAAK,IAAI,UAAU,WAAW;AACjD,UAAM,QAAQ,MAAM,KAAK,IAAI,UAAU,YAAY;AAEnD,WAAO;AAAA,MACL,MAAM,KAAK,SAAS;AAAA,MACpB,OAAO,MAAM,SAAS;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAM,YAAkE;AACtE,UAAM,SAAS,MAAM,KAAK,IAAI,OAAO;AAErC,WAAO;AAAA,MACL,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAM,wBAA0C;AAC9C,UAAM,SAAS,MAAM,KAAK,IAAI,OAAO;AACrC,WAAO,CAAC,OAAO,QAAQ;AAAA,EACzB;AACF;;;ACrGA,SAAS,aAAa;AAEf,IAAM,gBAAN,MAAoB;AAAA,EACzB,MAAM,cAAgC;AACpC,QAAI;AACF,YAAM,MAAM,MAAM,CAAC,WAAW,WAAW,CAAC;AAC1C,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,QAAiC;AAC7C,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM,MAAM,MAAM,CAAC,WAAW,WAAW,MAAM,SAAS,MAAM,CAAC;AAElF,aAAO,KAAK,YAAY,MAAM;AAAA,IAChC,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,sBAAsB,KAAK,EAAE;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,MAA+B;AAC3C,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM,MAAM,MAAM,CAAC,WAAW,WAAW,IAAI,CAAC;AACjE,aAAO,KAAK,YAAY,MAAM;AAAA,IAChC,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,sBAAsB,KAAK,EAAE;AAAA,IAC/C;AAAA,EACF;AAAA,EAEQ,YAAY,KAAqB;AAMvC,UAAM,UAAU,IAAI,QAAQ,0BAA0B,EAAE;AAGxD,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,UAAM,gBAAgB,MAAM;AAAA,MAC1B,CAAC,SACC,KAAK,KAAK,KACV,CAAC,KAAK,SAAS,aAAa,KAC5B,CAAC,KAAK,SAAS,kBAAkB,KACjC,CAAC,KAAK,SAAS,GAAG;AAAA,IACtB;AAEA,WAAO,cAAc,KAAK,IAAI,EAAE,KAAK;AAAA,EACvC;AAAA,EAEA,MAAM,iBAAiB,SAAoC;AACzD,UAAM,SAAS;AAAA;AAAA;AAAA;AAAA,EAIjB,QAAQ,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBhD,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EAEA,MAAM,sBAAsB,MAKR;AAClB,UAAM,SAAS;AAAA;AAAA;AAAA,UAGT,KAAK,MAAM;AAAA;AAAA;AAAA,EAGnB,KAAK,QAAQ,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,EAGvD,KAAK,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,kBAEL,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,IAAI,IAAI,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWxE,KAAK,OAAO,SAAS,IAAI,UAAU,KAAK,OAAO,KAAK,IAAI,CAAC,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAc9D,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EAEA,MAAM,sBAAsB,MAOR;AAClB,UAAM,SAAS;AAAA;AAAA;AAAA;AAAA,EAIjB,KAAK,QAAQ,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,IAGrD,KAAK,MAAM,OAAO;AAAA,IAClB,KAAK,MAAM,UAAU;AAAA,IACrB,KAAK,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBvB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AACF;;;ACxKA,OAAO,WAAW;AAClB,OAAO,WAAW;AAKX,IAAM,KAAN,MAAS;AAAA,EACd,OAAgB,SAAS;AAAA,IACvB,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,KAAK,MAAM;AAAA,IACX,MAAM,MAAM;AAAA,EACd;AAAA,EAEA,OAAO,OAAO,OAAuB;AACnC,WAAO,KAAK,OAAO,KAAK,KAAK;AAAA,EAC/B;AAAA,EAEA,OAAO,QAAQ,OAAe,SAAyB;AACrD,WAAO;AAAA,EAAK,KAAK,OAAO,QAAQ,KAAK,CAAC;AAAA,EAAK,OAAO;AAAA,EACpD;AAAA,EAEA,OAAO,IAAI,SAAiB,OAAwB;AAClD,WAAO,MAAM,SAAS;AAAA,MACpB,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,aAAa;AAAA,MACb;AAAA,MACA,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,KAAK,OAAyB;AACnC,WAAO,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,IAAI;AAAA,EAC3E;AAAA,EAEA,OAAO,QAAQ,SAAyB;AACtC,WAAO,KAAK,OAAO,QAAQ,UAAK,OAAO,EAAE;AAAA,EAC3C;AAAA,EAEA,OAAO,MAAM,SAAyB;AACpC,WAAO,KAAK,OAAO,MAAM,UAAK,OAAO,EAAE;AAAA,EACzC;AAAA,EAEA,OAAO,QAAQ,SAAyB;AACtC,WAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,EAAE;AAAA,EAC3C;AAAA,EAEA,OAAO,KAAK,SAAyB;AACnC,WAAO,KAAK,OAAO,IAAI,KAAK,OAAO,EAAE;AAAA,EACvC;AAAA,EAEA,OAAO,UAAkB;AACvB,WAAO,KAAK,OAAO,IAAI,SAAI,OAAO,EAAE,CAAC;AAAA,EACvC;AAAA,EAEA,OAAO,IAAI,MAAsB;AAC/B,WAAO,KAAK,OAAO,IAAI,IAAI;AAAA,EAC7B;AAAA,EAEA,OAAO,MAAM,SAAmB,MAA0B;AACxD,UAAM,YAAY,QAAQ,IAAI,CAAC,GAAG,MAAM;AACtC,YAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;AAClE,aAAO,KAAK,IAAI,EAAE,QAAQ,WAAW;AAAA,IACvC,CAAC;AAED,UAAM,YAAY,QAAQ,IAAI,CAAC,GAAG,MAAM,EAAE,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI;AAEzE,UAAM,YAAY,UAAU,IAAI,CAAC,MAAM,SAAI,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI;AAE/D,UAAM,WAAW,KACd,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,MAAM,KAAK,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EACvE,KAAK,IAAI;AAEZ,WAAO,GAAG,KAAK,OAAO,KAAK,SAAS,CAAC;AAAA,EAAK,KAAK,OAAO,IAAI,SAAS,CAAC;AAAA,EAAK,QAAQ;AAAA,EACnF;AAAA,EAEA,OAAO,SAAS,SAAiB,OAAe,OAAuB;AACrE,UAAM,aAAa,KAAK,MAAO,UAAU,QAAS,GAAG;AACrD,UAAM,YAAY;AAClB,UAAM,SAAS,KAAK,MAAO,YAAY,UAAW,KAAK;AACvD,UAAM,MAAM,SAAI,OAAO,MAAM,IAAI,SAAI,OAAO,YAAY,MAAM;AAE9D,WAAO,GAAG,KAAK,IAAI,KAAK,OAAO,QAAQ,GAAG,CAAC,IAAI,UAAU;AAAA,EAC3D;AACF;;;ACxFA,OAAO,SAAS;AAChB,OAAO,eAAe;AAGtB,eAAsB,gBAAgB,MAA6B;AACjE,MAAI;AACF,UAAM,UAAU,MAAM,IAAI;AAC1B,YAAQ,IAAI,GAAG,QAAQ,qBAAqB,CAAC;AAAA,EAC/C,QAAQ;AACN,YAAQ,IAAI,GAAG,QAAQ,6BAA6B,CAAC;AAAA,EACvD;AACF;AAEO,SAAS,QAAQ,MAAc;AACpC,SAAO,IAAI;AAAA,IACT;AAAA,IACA,SAAS;AAAA,IACT,OAAO;AAAA,EACT,CAAC;AACH;AAEO,SAAS,WAAW,MAAoB;AAC7C,SAAO,KAAK,mBAAmB,SAAS;AAAA,IACtC,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,EACR,CAAC;AACH;AAEO,SAAS,gBAAgB,OAAa,KAAmB;AAC9D,SAAO,GAAG,WAAW,KAAK,CAAC,MAAM,WAAW,GAAG,CAAC;AAClD;AAEO,SAAS,aAAa,WAAmB,GAAS;AACvD,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,YAAY,IAAI,OAAO;AAC7B,QAAM,SAAS,IAAI,KAAK,GAAG;AAC3B,SAAO,QAAQ,IAAI,QAAQ,IAAI,aAAa,cAAc,IAAI,KAAK,EAAE;AACrE,SAAO,QAAQ,OAAO,QAAQ,IAAI,WAAW,CAAC;AAC9C,SAAO,SAAS,GAAG,GAAG,GAAG,CAAC;AAC1B,SAAO;AACT;AAEO,SAAS,WAAW,WAAmB,GAAS;AACrD,QAAM,QAAQ,aAAa,QAAQ;AACnC,QAAM,MAAM,IAAI,KAAK,KAAK;AAC1B,MAAI,QAAQ,MAAM,QAAQ,IAAI,CAAC;AAC/B,MAAI,SAAS,IAAI,IAAI,IAAI,GAAG;AAC5B,SAAO;AACT;AAEO,SAAS,WAAW,MAAoB;AAC7C,QAAM,OAAO,oBAAI,KAAK;AACtB,OAAK,QAAQ,KAAK,QAAQ,IAAI,IAAI;AAClC,OAAK,SAAS,GAAG,GAAG,GAAG,CAAC;AACxB,SAAO;AACT;;;AJlDO,IAAM,iBAAiB,IAAI,QAAQ,SAAS,EAChD,YAAY,iDAAiD,EAC7D,OAAO,uBAAuB,+BAA+B,GAAG,EAChE,OAAO,uBAAuB,wCAAwC,UAAU,EAChF,OAAO,aAAa,0BAA0B,EAC9C,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,YAAY;AAC5B,QAAM,UAAU,IAAI,cAAc;AAGlC,MAAI,CAAE,MAAM,IAAI,aAAa,GAAI;AAC/B,YAAQ,IAAI,GAAG,MAAM,sBAAsB,CAAC;AAC5C,YAAQ,IAAI,GAAG,KAAK,0CAA0C,CAAC;AAC/D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,CAAE,MAAM,QAAQ,YAAY,GAAI;AAClC,YAAQ,IAAI,GAAG,MAAM,8BAA8B,CAAC;AACpD,YAAQ,IAAI,GAAG,KAAK,sDAAsD,CAAC;AAC3E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,QAAQ,wBAAwB,EAAE,MAAM;AAErD,MAAI;AAEF,UAAM,OAAO,MAAM,IAAI,eAAe;AAGtC,UAAM,OAAO,SAAS,QAAQ,MAAM,EAAE;AACtC,UAAM,QAAQ,WAAW,IAAI;AAC7B,UAAM,UAAU,MAAM,IAAI,WAAW;AAAA,MACnC;AAAA,MACA,QAAQ,KAAK;AAAA,IACf,CAAC;AAED,QAAI,QAAQ,WAAW,GAAG;AACxB,WAAK,KAAK;AACV,cAAQ,IAAI,GAAG,QAAQ,gCAAgC,IAAI,SAAS,CAAC;AACrE,cAAQ,IAAI,GAAG,KAAK,gCAAgC,OAAO,CAAC,EAAE,CAAC;AAC/D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,SAAK,OAAO;AAGZ,UAAM,iBAAiB,QAAQ,IAAI,CAAC,MAAM,EAAE,OAAO;AACnD,UAAM,UAAU,MAAM,QAAQ,iBAAiB,cAAc;AAE7D,SAAK,KAAK;AAGV,UAAM,QAAQ,SAAS,IAAI,iBAAiB,mBAAmB,IAAI;AACnE,UAAM,UAAU,GAAG,OAAO;AAAA;AAAA,EAAO,GAAG,QAAQ,CAAC;AAAA,EAAK,GAAG,IAAI,GAAG,QAAQ,MAAM,mBAAmB,CAAC;AAE9F,YAAQ,IAAI,GAAG,IAAI,SAAS,KAAK,CAAC;AAGlC,QAAI,QAAQ,MAAM;AAChB,YAAM,gBAAgB,OAAO;AAAA,IAC/B;AAAA,EACF,SAAS,OAAO;AACd,SAAK,KAAK;AACV,YAAQ,IAAI,GAAG,MAAM,4BAA4B,CAAC;AAClD,YAAQ,IAAI,GAAG,IAAK,MAAgB,OAAO,CAAC;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;;;AK1EH,SAAS,WAAAC,gBAAe;AACxB,OAAO,cAAc;AACrB,SAAS,SAAAC,cAAa;AACtB,OAAO,UAAU;;;ACDjB,IAAM;AAAA;AAAA,EAEJ;AAAA;AAEK,SAAS,wBAAwB,SAA4C;AAClF,QAAM,QAAQ,QAAQ,MAAM,cAAc;AAE1C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,EAAE,MAAM,OAAO,UAAU,OAAO,IAAI;AAE3C,SAAO;AAAA,IACL;AAAA,IACA,OAAO,OAAO,QAAQ,SAAS,EAAE;AAAA,IACjC,SAAS,QAAQ,KAAK;AAAA,IACtB,UAAU,aAAa;AAAA,EACzB;AACF;AAEO,SAAS,oBAAoB,MAAwB;AAC1D,QAAM,eAAe;AACrB,QAAM,UAAU,KAAK,SAAS,YAAY;AAC1C,SAAO,MAAM,KAAK,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE;AAC9C;AAEO,SAAS,gBAAgB,SAA2B;AAEzD,QAAM,SAAS,QACZ,IAAI,uBAAuB,EAC3B,OAAO,CAAC,MAA+B,MAAM,IAAI;AAEpD,MAAI,OAAO,WAAW,GAAG;AAEvB,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AAGA,QAAM,WAAW,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AACvD,QAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK;AAEnD,MAAI,SAAS,SAAS,GAAG;AACvB,WAAO,SAAS,CAAC,EAAE;AAAA,EACrB;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,QAAQ,MAAM,CAAC,EAAE,OAAO;AAAA,EACjC;AAEA,SAAO,OAAO,CAAC,EAAE;AACnB;AAEO,SAAS,iBAAiB,SAA2B;AAC1D,QAAM,SAAS,QACZ,IAAI,uBAAuB,EAC3B,OAAO,CAAC,MAA+B,MAAM,IAAI;AAEpD,QAAM,cAAc,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACxD,QAAM,WAAW,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK;AACpD,QAAM,cAAc,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ;AAEjD,MAAI,YAAa,QAAO;AACxB,MAAI,YAAa,QAAO;AACxB,MAAI,SAAU,QAAO;AACrB,SAAO;AACT;;;AD1DO,IAAM,YAAY,IAAIC,SAAQ,IAAI,EACtC,YAAY,6CAA6C,EACzD,OAAO,uBAAuB,kCAAkC,MAAM,EACtE,OAAO,gBAAgB,qBAAqB,EAC5C,OAAO,eAAe,oBAAoB,EAC1C,OAAO,cAAc,kCAAkC,EACvD,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,YAAY;AAC5B,QAAM,UAAU,IAAI,cAAc;AAGlC,MAAI,CAAE,MAAM,IAAI,aAAa,GAAI;AAC/B,YAAQ,IAAI,GAAG,MAAM,sBAAsB,CAAC;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,CAAE,MAAM,QAAQ,YAAY,GAAI;AAClC,YAAQ,IAAI,GAAG,MAAM,8BAA8B,CAAC;AACpD,YAAQ,IAAI,GAAG,KAAK,sDAAsD,CAAC;AAC3E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,QAAQ,qBAAqB,EAAE,MAAM;AAElD,MAAI;AAEF,UAAM,gBAAgB,MAAM,IAAI,iBAAiB;AAEjD,QAAI,kBAAkB,QAAQ,MAAM;AAClC,WAAK,KAAK;AACV,cAAQ,IAAI,GAAG,MAAM,yBAAyB,QAAQ,IAAI,SAAS,CAAC;AACpE,cAAQ,IAAI,GAAG,KAAK,kCAAkC,CAAC;AACvD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,UAAU,MAAM,IAAI,WAAW;AAErC,QAAI,QAAQ,WAAW,GAAG;AACxB,WAAK,KAAK;AACV,cAAQ,IAAI,GAAG,QAAQ,2BAA2B,CAAC;AACnD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,QAAQ,MAAM,IAAI,gBAAgB,QAAQ,IAAI;AAGpD,UAAM,iBAAiB,QAAQ,IAAI,CAAC,MAAM,EAAE,OAAO;AACnD,UAAM,UAAU,eAAe,KAAK,GAAG;AACvC,UAAM,SAAS,oBAAoB,OAAO;AAG1C,UAAM,iBAAiB,gBAAgB,cAAc;AACrD,UAAM,SAAS,iBAAiB,cAAc;AAE9C,SAAK,OAAO;AAGZ,UAAM,cAAc,MAAM,QAAQ,sBAAsB;AAAA,MACtD,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AAED,SAAK,KAAK;AAGV,YAAQ;AAAA,MACN,GAAG;AAAA,QACD,GAAG,GAAG,OAAO,KAAK,cAAc,CAAC;AAAA;AAAA,EAAO,WAAW;AAAA;AAAA,EAAO,GAAG,QAAQ,CAAC;AAAA,EAAK,GAAG,IAAI,GAAG,QAAQ,MAAM,mBAAc,MAAM,MAAM,yBAAoB,MAAM,EAAE,CAAC;AAAA,QAC1J,sBAAsB,aAAa;AAAA,MACrC;AAAA,IACF;AAGA,UAAM,EAAE,OAAO,IAAI,MAAM,SAAS,OAAO;AAAA,MACvC;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,UACP,EAAE,MAAM,wCAAwC,OAAO,UAAU;AAAA,UACjE,EAAE,MAAM,qBAAqB,OAAO,OAAO;AAAA,UAC3C,EAAE,MAAM,uBAAuB,OAAO,SAAS;AAAA,UAC/C,EAAE,MAAM,mBAAmB,OAAO,QAAQ;AAAA,UAC1C,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA,QAChC;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,WAAW,QAAQ;AACrB,YAAM,gBAAgB,WAAW;AAAA,IACnC,WAAW,WAAW,WAAW;AAE/B,cAAQ,IAAI,GAAG,KAAK,+BAA+B,CAAC;AAEpD,YAAM,KAAK,oBAAoB;AAAA,IACjC,WAAW,WAAW,YAAY,WAAW,SAAS;AACpD,YAAM,UAAU,WAAW,WAAW,QAAQ;AAE9C,YAAM,gBAAgB,QAAQ,YAAY,UAAU,WAAW,EAAE,OAAO,EAAE,MAAM;AAEhF,UAAI;AACF,cAAM,OAAO;AAAA,UACX;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AAEA,YAAI,SAAS;AACX,eAAK,KAAK,SAAS;AAAA,QACrB;AAEA,cAAM,EAAE,OAAO,IAAI,MAAMC,OAAM,MAAM,IAAI;AAEzC,sBAAc,KAAK;AACnB,gBAAQ,IAAI,GAAG,QAAQ,yBAAyB,CAAC;AACjD,gBAAQ,IAAI,GAAG,IAAI,MAAM,CAAC;AAAA,MAC5B,SAAS,OAAO;AACd,sBAAc,KAAK;AACnB,gBAAQ,IAAI,GAAG,MAAM,qBAAqB,CAAC;AAC3C,gBAAQ,IAAI,GAAG,IAAK,MAAgB,OAAO,CAAC;AAAA,MAC9C;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,SAAK,KAAK;AACV,YAAQ,IAAI,GAAG,MAAM,mCAAmC,CAAC;AACzD,YAAQ,IAAI,GAAG,IAAK,MAAgB,OAAO,CAAC;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;;;AEpJH,SAAS,WAAAC,gBAAe;AAYjB,IAAM,cAAc,IAAIC,SAAQ,MAAM,EAC1C,YAAY,8BAA8B,EAC1C,OAAO,cAAc,mCAAmC,EACxD,OAAO,aAAa,0BAA0B,EAC9C,OAAO,OAAO,YAAY;AACzB,QAAM,MAAM,IAAI,YAAY;AAC5B,QAAM,UAAU,IAAI,cAAc;AAGlC,MAAI,CAAE,MAAM,IAAI,aAAa,GAAI;AAC/B,YAAQ,IAAI,GAAG,MAAM,sBAAsB,CAAC;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,CAAE,MAAM,QAAQ,YAAY,GAAI;AAClC,YAAQ,IAAI,GAAG,MAAM,8BAA8B,CAAC;AACpD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,QAAQ,wBAAwB,EAAE,MAAM;AAErD,MAAI;AACF,UAAM,WAAW,QAAQ,OAAO,IAAI;AACpC,UAAM,QAAQ,aAAa,QAAQ;AACnC,UAAM,MAAM,WAAW,QAAQ;AAG/B,UAAM,OAAO,MAAM,IAAI,eAAe;AAGtC,UAAM,UAAU,MAAM,IAAI,WAAW;AAAA,MACnC,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ,KAAK;AAAA,IACf,CAAC;AAED,QAAI,QAAQ,WAAW,GAAG;AACxB,WAAK,KAAK;AACV,cAAQ,IAAI,GAAG,QAAQ,4BAA4B,CAAC;AACpD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,QAAQ,MAAM,IAAI,aAAa;AAErC,SAAK,OAAO;AAGZ,UAAM,iBAAiB,QAAQ,IAAI,CAAC,MAAM,EAAE,OAAO;AACnD,UAAM,UAAU,MAAM,QAAQ,sBAAsB;AAAA,MAClD,SAAS;AAAA,MACT,OAAO;AAAA,QACL,SAAS,QAAQ;AAAA,QACjB,YAAY,MAAM;AAAA,QAClB,cAAc,MAAM;AAAA,MACtB;AAAA,IACF,CAAC;AAED,SAAK,KAAK;AAGV,UAAM,QAAQ,mBAAmB,gBAAgB,OAAO,GAAG,CAAC;AAC5D,UAAM,UAAU,GAAG,OAAO;AAAA;AAAA,EAAO,GAAG,QAAQ,CAAC;AAAA,EAAK,GAAG,IAAI,GAAG,QAAQ,MAAM,mBAAc,MAAM,UAAU,KAAK,MAAM,SAAS,SAAS,CAAC;AAEtI,YAAQ,IAAI,GAAG,IAAI,SAAS,KAAK,CAAC;AAGlC,QAAI,QAAQ,MAAM;AAChB,YAAM,gBAAgB,OAAO;AAAA,IAC/B;AAAA,EACF,SAAS,OAAO;AACd,SAAK,KAAK;AACV,YAAQ,IAAI,GAAG,MAAM,mCAAmC,CAAC;AACzD,YAAQ,IAAI,GAAG,IAAK,MAAgB,OAAO,CAAC;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;;;ACzFH,SAAS,WAAAC,gBAAe;AAGjB,IAAM,iBAAiB,IAAIC,SAAQ,SAAS,EAChD,YAAY,gDAAgD,EAC5D,OAAO,YAAY;AAClB,UAAQ,IAAI,GAAG,KAAK,uCAAuC,CAAC;AAC5D,UAAQ,IAAI,GAAG,IAAI,0EAA0E,CAAC;AAChG,CAAC;;;ATDH,IAAM,UAAU,IAAIC,SAAQ;AAE5B,QAAQ,KAAK,UAAU,EAAE,YAAY,mCAAmC,EAAE,QAAQ,OAAO;AAGzF,QAAQ,WAAW,cAAc;AACjC,QAAQ,WAAW,SAAS;AAC5B,QAAQ,WAAW,WAAW;AAC9B,QAAQ,WAAW,cAAc;AAGjC,QAAQ,MAAM;","names":["Command","Command","execa","Command","execa","Command","Command","Command","Command","Command"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devdaily-ai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Your AI memory for developer work - auto-generate PR descriptions, standup notes, and work summaries",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"devdaily": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "tsx watch src/index.ts",
|
|
11
|
+
"build": "tsup",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"lint": "eslint src",
|
|
15
|
+
"lint:fix": "eslint src --fix",
|
|
16
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
17
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"test:coverage": "vitest run --coverage",
|
|
21
|
+
"prepare": "husky",
|
|
22
|
+
"prepublishOnly": "npm run build && npm run test"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"cli",
|
|
26
|
+
"git",
|
|
27
|
+
"pr",
|
|
28
|
+
"standup",
|
|
29
|
+
"copilot",
|
|
30
|
+
"ai",
|
|
31
|
+
"developer-tools"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/yourusername/devdaily-ai.git"
|
|
38
|
+
},
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/yourusername/devdaily-ai/issues"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/yourusername/devdaily-ai#readme",
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"boxen": "^8.0.1",
|
|
50
|
+
"chalk": "^5.3.0",
|
|
51
|
+
"clipboardy": "^4.0.0",
|
|
52
|
+
"commander": "^12.1.0",
|
|
53
|
+
"dotenv": "^16.4.7",
|
|
54
|
+
"execa": "^9.5.2",
|
|
55
|
+
"inquirer": "^12.2.0",
|
|
56
|
+
"open": "^10.1.0",
|
|
57
|
+
"ora": "^8.1.1",
|
|
58
|
+
"picocolors": "^1.1.1",
|
|
59
|
+
"simple-git": "^3.27.0",
|
|
60
|
+
"zod": "^3.23.8"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@commitlint/cli": "^20.4.1",
|
|
64
|
+
"@commitlint/config-conventional": "^20.4.1",
|
|
65
|
+
"@types/inquirer": "^9.0.7",
|
|
66
|
+
"@types/node": "^22.10.2",
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^8.18.2",
|
|
68
|
+
"@typescript-eslint/parser": "^8.18.2",
|
|
69
|
+
"eslint": "^9.17.0",
|
|
70
|
+
"eslint-config-prettier": "^10.1.8",
|
|
71
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
72
|
+
"globals": "^17.3.0",
|
|
73
|
+
"husky": "^9.1.7",
|
|
74
|
+
"lint-staged": "^16.2.7",
|
|
75
|
+
"prettier": "^3.8.1",
|
|
76
|
+
"tsup": "^8.3.5",
|
|
77
|
+
"tsx": "^4.19.2",
|
|
78
|
+
"typescript": "^5.7.2",
|
|
79
|
+
"vitest": "^2.1.8"
|
|
80
|
+
},
|
|
81
|
+
"engines": {
|
|
82
|
+
"node": ">=18.0.0"
|
|
83
|
+
},
|
|
84
|
+
"lint-staged": {
|
|
85
|
+
"*.ts": [
|
|
86
|
+
"eslint --fix",
|
|
87
|
+
"prettier --write"
|
|
88
|
+
],
|
|
89
|
+
"*.{json,md}": [
|
|
90
|
+
"prettier --write"
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
}
|