work-chronicler 0.2.0 → 0.2.2
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/.agent/skills/release-notes/skill.md +129 -0
- package/README.md +24 -49
- package/dist/cli/commands/init/index.js +10 -7
- package/dist/cli/index.js +4 -1
- package/package.json +1 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release-notes
|
|
3
|
+
description: Use when releasing a new version, after tagging, or when the user asks to update release notes. Generates meaningful release notes from git history and updates the GitHub release.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Generate Release Notes
|
|
8
|
+
|
|
9
|
+
Generate meaningful release notes from git history between two tags and update the corresponding GitHub release.
|
|
10
|
+
|
|
11
|
+
## User Input
|
|
12
|
+
|
|
13
|
+
**Optional:**
|
|
14
|
+
- **Tag**: The tag to generate notes for (e.g., "v0.2.0")
|
|
15
|
+
- If omitted, uses the latest tag
|
|
16
|
+
- **Previous tag**: The starting point for the diff
|
|
17
|
+
- If omitted, uses the tag immediately before the target tag
|
|
18
|
+
|
|
19
|
+
**Example invocations:**
|
|
20
|
+
- `/release-notes` (latest tag vs its predecessor)
|
|
21
|
+
- `/release-notes v0.2.0` (specific tag)
|
|
22
|
+
- `/release-notes v0.3.0 v0.1.1` (explicit range)
|
|
23
|
+
|
|
24
|
+
## Instructions
|
|
25
|
+
|
|
26
|
+
### 1. Determine the tag range
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# If no tag specified, get the latest
|
|
30
|
+
git tag --sort=-v:refname | head -1
|
|
31
|
+
|
|
32
|
+
# Get the previous tag
|
|
33
|
+
git tag --sort=-v:refname | head -2 | tail -1
|
|
34
|
+
|
|
35
|
+
# Check when the tag was created (to detect stale releases)
|
|
36
|
+
git log -1 --format="%ci" <latest-tag>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Staleness check:** If no tag was explicitly provided, compare the tag's date to today. If the tag is older than 7 days, ask the user to confirm this is the intended release before proceeding — they may have forgotten to specify a tag, or may need to create a new one first.
|
|
40
|
+
|
|
41
|
+
Confirm the two tags with the user before proceeding.
|
|
42
|
+
|
|
43
|
+
### 2. Gather commit data
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# All commits in the range
|
|
47
|
+
git log --oneline <previous-tag>..<target-tag>
|
|
48
|
+
|
|
49
|
+
# Merged PRs (first-parent view)
|
|
50
|
+
git log --oneline --first-parent <previous-tag>..<target-tag>
|
|
51
|
+
|
|
52
|
+
# Full commit messages for context
|
|
53
|
+
git log --format="%h %s%n%b" <previous-tag>..<target-tag>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 3. Gather PR details (if available)
|
|
57
|
+
|
|
58
|
+
For each merged PR number found in commit messages:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
gh pr view <number> --json title,body,labels
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 4. Categorize changes
|
|
65
|
+
|
|
66
|
+
Group commits into categories based on conventional commit prefixes:
|
|
67
|
+
|
|
68
|
+
| Prefix | Category |
|
|
69
|
+
|--------|----------|
|
|
70
|
+
| `feat` | New Features |
|
|
71
|
+
| `fix` | Bug Fixes |
|
|
72
|
+
| `perf` | Performance |
|
|
73
|
+
| `refactor` | Refactoring |
|
|
74
|
+
| `test` | Testing |
|
|
75
|
+
| `docs` | Documentation |
|
|
76
|
+
| `chore` | Maintenance |
|
|
77
|
+
|
|
78
|
+
Within each category, group related commits together and summarize them as a single item rather than listing every commit individually. Focus on **what changed for the user**, not implementation details.
|
|
79
|
+
|
|
80
|
+
### 5. Write release notes
|
|
81
|
+
|
|
82
|
+
Structure:
|
|
83
|
+
|
|
84
|
+
```markdown
|
|
85
|
+
## Highlights
|
|
86
|
+
|
|
87
|
+
[1-3 sentence summary of the most important changes in this release]
|
|
88
|
+
|
|
89
|
+
## What's New
|
|
90
|
+
|
|
91
|
+
### [Category Name]
|
|
92
|
+
- **[Feature/change name]** — [Description of what it does and why it matters]
|
|
93
|
+
- **[Feature/change name]** — [Description]
|
|
94
|
+
|
|
95
|
+
### [Category Name]
|
|
96
|
+
- **[Fix/change name]** — [Description]
|
|
97
|
+
|
|
98
|
+
## Installation
|
|
99
|
+
|
|
100
|
+
\`\`\`bash
|
|
101
|
+
npm install -g work-chronicler@<version>
|
|
102
|
+
\`\`\`
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 6. Update the GitHub release
|
|
106
|
+
|
|
107
|
+
First, show the user the generated notes and get their approval. Then:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
gh release edit <tag> --notes "<approved notes>"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Use a heredoc for the notes body to preserve formatting:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
gh release edit <tag> --notes "$(cat <<'NOTES'
|
|
117
|
+
<release notes content>
|
|
118
|
+
NOTES
|
|
119
|
+
)"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Guidelines
|
|
123
|
+
|
|
124
|
+
- **Summarize, don't list** — "Added manager mode with report management, per-report analysis, and team aggregations" is better than listing 15 individual commits
|
|
125
|
+
- **User-facing language** — Describe what users can do now, not what files changed
|
|
126
|
+
- **Group by feature, not by commit** — Multiple commits that build one feature should be a single bullet point
|
|
127
|
+
- **Skip noise** — Formatting fixes, import cleanup, and file moves don't need to be mentioned unless they affect users
|
|
128
|
+
- **Keep it scannable** — Someone should understand the release in 30 seconds
|
|
129
|
+
- **Preserve the installation section** — The CI workflow includes this; keep it consistent
|
package/README.md
CHANGED
|
@@ -21,68 +21,37 @@ Manager mode extends work-chronicler for people managers tracking multiple direc
|
|
|
21
21
|
|
|
22
22
|
## Quick Start
|
|
23
23
|
|
|
24
|
-
### Local Development (this repo)
|
|
25
|
-
|
|
26
|
-
Use `pnpm cli` instead of `work-chronicler`:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
pnpm install
|
|
30
|
-
pnpm cli init
|
|
31
|
-
pnpm cli fetch all
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Published Package Usage
|
|
35
|
-
|
|
36
|
-
After the package is published to npm:
|
|
37
|
-
|
|
38
24
|
```bash
|
|
39
25
|
# Install globally
|
|
40
26
|
npm install -g work-chronicler
|
|
41
27
|
|
|
42
|
-
# Initialize
|
|
28
|
+
# 1. Initialize — interactive wizard guides you through setup
|
|
43
29
|
work-chronicler init
|
|
44
30
|
|
|
45
|
-
#
|
|
46
|
-
work-chronicler init --mode manager
|
|
47
|
-
|
|
48
|
-
# Fetch your work history
|
|
31
|
+
# 2. Fetch your work history from GitHub and JIRA
|
|
49
32
|
work-chronicler fetch all
|
|
50
33
|
|
|
51
|
-
#
|
|
52
|
-
work-chronicler analyze --projects --timeline
|
|
53
|
-
|
|
54
|
-
# Check what you have
|
|
34
|
+
# 3. Review what was fetched
|
|
55
35
|
work-chronicler status
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Data is stored in `~/.work-chronicler/profiles/<profile-name>/` with isolated configs, tokens, and work logs per profile.
|
|
59
36
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
work-chronicler uses a portable workspace at `~/.work-chronicler/` with support for multiple profiles. Each profile has its own config, tokens, and work log.
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
# Initialize with interactive wizard (creates profile)
|
|
66
|
-
work-chronicler init
|
|
37
|
+
# 4. Filter to relevant work (exclude minor PRs, personal repos, etc.)
|
|
38
|
+
work-chronicler filter
|
|
67
39
|
|
|
68
|
-
#
|
|
69
|
-
work-chronicler
|
|
40
|
+
# 5. Run analysis on the filtered data
|
|
41
|
+
work-chronicler analyze --all
|
|
70
42
|
|
|
71
|
-
#
|
|
72
|
-
work-chronicler
|
|
43
|
+
# 6. Install AI skills to your coding assistant
|
|
44
|
+
work-chronicler skills install
|
|
73
45
|
|
|
74
|
-
#
|
|
75
|
-
work-chronicler
|
|
46
|
+
# 7. Use a skill in Claude Code, Cursor, etc.
|
|
47
|
+
# /work-chronicler-summarize-work
|
|
48
|
+
```
|
|
76
49
|
|
|
77
|
-
|
|
78
|
-
work-chronicler status
|
|
50
|
+
> Skills are slash commands for AI coding assistants — they won't work in a regular terminal. Run them from Claude Code, Cursor, Codex, or Gemini after running `skills install`.
|
|
79
51
|
|
|
80
|
-
|
|
81
|
-
work-chronicler fetch all --profile work
|
|
82
|
-
work-chronicler status --profile personal
|
|
83
|
-
```
|
|
52
|
+
Data is stored in `~/.work-chronicler/profiles/<profile-name>/` with isolated configs, tokens, and work logs per profile.
|
|
84
53
|
|
|
85
|
-
> **
|
|
54
|
+
> **Local development:** Use `pnpm cli` instead of `work-chronicler` (e.g., `pnpm cli init`).
|
|
86
55
|
|
|
87
56
|
### Profiles
|
|
88
57
|
|
|
@@ -319,9 +288,13 @@ Create an API token at https://id.atlassian.com/manage-profile/security/api-toke
|
|
|
319
288
|
| `WORK_CHRONICLER_DIR` | Legacy: directory containing config (for MCP server) |
|
|
320
289
|
| `WORK_CHRONICLER_CONFIG` | Legacy: full path to config file |
|
|
321
290
|
|
|
322
|
-
## AI Skills
|
|
291
|
+
## AI Skills
|
|
292
|
+
|
|
293
|
+
work-chronicler includes AI skills that can be installed to your preferred coding assistant. Skills are **stateless** — they don't embed any file paths. At runtime, each skill shells out to `work-chronicler workspace work-log` (and similar commands) to resolve the active profile's data directory. This means:
|
|
323
294
|
|
|
324
|
-
|
|
295
|
+
- Skills work regardless of where they're installed (`~/.claude/skills/`, `~/.cursor/skills/`, etc.)
|
|
296
|
+
- Switching profiles with `work-chronicler profile switch` changes what data skills read
|
|
297
|
+
- No reinstallation is needed when you change profiles
|
|
325
298
|
|
|
326
299
|
```bash
|
|
327
300
|
# Install skills to Claude Code, Cursor, etc.
|
|
@@ -336,7 +309,7 @@ work-chronicler skills uninstall
|
|
|
336
309
|
|
|
337
310
|
### Available Skills
|
|
338
311
|
|
|
339
|
-
After installation, these skills are available as slash commands:
|
|
312
|
+
After installation, these skills are available as slash commands in your AI coding assistant:
|
|
340
313
|
|
|
341
314
|
**Individual Contributor (IC) Mode:**
|
|
342
315
|
|
|
@@ -470,6 +443,8 @@ work-chronicler includes an MCP (Model Context Protocol) server that exposes you
|
|
|
470
443
|
|
|
471
444
|
3. Restart your AI assistant to load the MCP server.
|
|
472
445
|
|
|
446
|
+
> **Profile resolution:** The MCP server resolves the active profile **once at startup**. If you switch profiles with `work-chronicler profile switch`, you need to restart the MCP server (i.e., restart your AI assistant) for the change to take effect. Alternatively, set `WORK_CHRONICLER_PROFILE` in the MCP config to pin to a specific profile.
|
|
447
|
+
|
|
473
448
|
**Environment Variables:**
|
|
474
449
|
- `WORK_CHRONICLER_HOME` - Workspace root (default: `~/.work-chronicler`)
|
|
475
450
|
- `WORK_CHRONICLER_PROFILE` - Profile name (default: active profile in `~/.work-chronicler/config.json`)
|
|
@@ -364,17 +364,20 @@ async function runInitialFetch(config, outputDir) {
|
|
|
364
364
|
*/
|
|
365
365
|
function showNextSteps(profileName, tokens) {
|
|
366
366
|
console.log(chalk.cyan('\nNext steps:\n'));
|
|
367
|
+
let step = 1;
|
|
367
368
|
if (!tokens.githubToken && !tokens.jiraToken) {
|
|
368
369
|
const envPath = getProfileEnvPath(profileName);
|
|
369
|
-
console.log(`
|
|
370
|
-
|
|
370
|
+
console.log(` ${step}. Add your API tokens to: ${envPath}`);
|
|
371
|
+
step++;
|
|
371
372
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
console.log(
|
|
376
|
-
console.log(
|
|
373
|
+
console.log(` ${step}. Fetch your work history: work-chronicler fetch all`);
|
|
374
|
+
console.log(` ${step + 1}. Review what was fetched: work-chronicler status`);
|
|
375
|
+
console.log(` ${step + 2}. Filter for relevant work: work-chronicler filter`);
|
|
376
|
+
console.log(` ${step + 3}. Run analysis on filtered data: work-chronicler analyze --all`);
|
|
377
|
+
console.log(` ${step + 4}. Install AI skills: work-chronicler skills install`);
|
|
378
|
+
console.log(` ${step + 5}. Use a skill in your AI editor: /work-chronicler-summarize-work`);
|
|
377
379
|
console.log();
|
|
380
|
+
console.log(chalk.dim('Skills are slash commands for AI coding assistants (Claude Code, Cursor, etc.).'));
|
|
378
381
|
console.log(chalk.dim('Switch profiles: work-chronicler profile switch <name>'));
|
|
379
382
|
console.log(chalk.dim('List profiles: work-chronicler profile list'));
|
|
380
383
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
3
4
|
import { dirname, resolve } from 'node:path';
|
|
4
5
|
import { analyzeCommand } from './commands/analyze.js';
|
|
5
6
|
import { fetchCommand } from './commands/fetch/index.js';
|
|
@@ -44,11 +45,13 @@ function loadEnvFile(override = false) {
|
|
|
44
45
|
// Initial .env load (before --profile is parsed)
|
|
45
46
|
// Use override:false so real env vars take precedence over .env
|
|
46
47
|
loadEnvFile(false);
|
|
48
|
+
const require = createRequire(import.meta.url);
|
|
49
|
+
const { version } = require('../../package.json');
|
|
47
50
|
const program = new Command();
|
|
48
51
|
program
|
|
49
52
|
.name('work-chronicler')
|
|
50
53
|
.description('Gather, analyze, and summarize your work history from GitHub PRs and JIRA tickets')
|
|
51
|
-
.version(
|
|
54
|
+
.version(version)
|
|
52
55
|
.option('--profile <name>', 'Use a specific profile (overrides active profile)')
|
|
53
56
|
.hook('preAction', (thisCommand) => {
|
|
54
57
|
const opts = thisCommand.opts();
|
package/package.json
CHANGED