pm-slack-standup 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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-05-26
4
+
5
+ ### Other
6
+
7
+ - Release readiness hardening for pm-slack-standup ([pm-slack-standup-i5h1](https://github.com/unbraind/pm-slack-standup/blob/main/.agents/pm/tasks/pm-slack-standup-i5h1.toon))
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # pm-slack-standup
2
+
3
+ A [pm-cli](https://github.com/unbraind/pm-cli) extension that posts your current project context as a formatted Slack standup message.
4
+
5
+ ## Features
6
+
7
+ - Posts WIP, Blocked, and Up Next items to a Slack channel via incoming webhook
8
+ - Optional Done Today section (`--include-done`)
9
+ - Dry-run mode to preview the message without posting
10
+ - Slack mrkdwn formatting or plain text output
11
+ - Channel prefix support
12
+ - Webhook URL configurable via flag or environment variable
13
+
14
+ ## Installation
15
+
16
+ Place the built extension in your pm-cli extensions directory, or install via npm (when published):
17
+
18
+ ```bash
19
+ npm install pm-slack-standup
20
+ ```
21
+
22
+ Then register it in your pm-cli config.
23
+
24
+ ## Setup
25
+
26
+ ### 1. Create a Slack Incoming Webhook
27
+
28
+ 1. Go to [api.slack.com/apps](https://api.slack.com/apps) and create (or select) an app.
29
+ 2. Under **Incoming Webhooks**, activate and add a new webhook to your workspace.
30
+ 3. Copy the webhook URL into your shell environment.
31
+
32
+ ### 2. Configure the webhook
33
+
34
+ Either pass it directly as a flag:
35
+
36
+ ```bash
37
+ pm standup --webhook <slack-webhook-url>
38
+ ```
39
+
40
+ Or set the environment variable (recommended — add to `.env` or shell profile):
41
+
42
+ ```bash
43
+ export PM_SLACK_WEBHOOK=<slack-webhook-url>
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ ```
49
+ pm standup [flags]
50
+ ```
51
+
52
+ ### Flags
53
+
54
+ | Flag | Type | Default | Description |
55
+ |------|------|---------|-------------|
56
+ | `--webhook <url>` | string | — | Slack incoming webhook URL (overrides `PM_SLACK_WEBHOOK`) |
57
+ | `--channel <name>` | string | — | Channel name to prepend to the message (e.g. `#team-eng`) |
58
+ | `--dry-run` | boolean | `false` | Print the message without posting to Slack |
59
+ | `--include-done` | boolean | `false` | Include items with `done` status in a Done Today section |
60
+ | `--format <slack\|text>` | string | `slack` | Output format: `slack` uses mrkdwn, `text` is plain |
61
+
62
+ ### Examples
63
+
64
+ **Basic standup (webhook from env):**
65
+ ```bash
66
+ pm standup
67
+ ```
68
+
69
+ **Post to a specific channel with dry-run preview:**
70
+ ```bash
71
+ pm standup --channel '#team-eng' --dry-run
72
+ ```
73
+
74
+ **Include done items and use plain text format:**
75
+ ```bash
76
+ pm standup --include-done --format text
77
+ ```
78
+
79
+ **Full explicit invocation:**
80
+ ```bash
81
+ pm standup \
82
+ --webhook <slack-webhook-url> \
83
+ --channel '#standups' \
84
+ --include-done
85
+ ```
86
+
87
+ ## Message Format
88
+
89
+ ### Slack (mrkdwn)
90
+
91
+ ```
92
+ > Channel: #team-eng
93
+
94
+ 📊 *pm standup* — 2026-05-09
95
+
96
+ 🏃 *In Progress* (2)
97
+ • [Epic] Dashboard redesign
98
+ • [Feature] User auth flow
99
+
100
+ 🚫 *Blocked* (1)
101
+ • [Issue] Login redirect bug
102
+
103
+ ✅ *Done Today* (1)
104
+ • [Task] Write unit tests
105
+
106
+ 📋 *Up Next* (3)
107
+ • [Feature] Email notifications (priority 1)
108
+ • [Task] Write API tests (priority 2)
109
+ • [Chore] Update dependencies (priority 3)
110
+ ```
111
+
112
+ ### Plain Text (`--format text`)
113
+
114
+ ```
115
+ 📊 pm standup — 2026-05-09
116
+
117
+ 🏃 In Progress (2)
118
+ • [Epic] Dashboard redesign
119
+ • [Feature] User auth flow
120
+
121
+ 🚫 Blocked (1)
122
+ • [Issue] Login redirect bug
123
+
124
+ 📋 Up Next (3)
125
+ • [Feature] Email notifications (priority 1)
126
+ • [Task] Write API tests (priority 2)
127
+ • [Chore] Update dependencies (priority 3)
128
+ ```
129
+
130
+ ## Environment Variables
131
+
132
+ | Variable | Description |
133
+ |----------|-------------|
134
+ | `PM_SLACK_WEBHOOK` | Slack incoming webhook URL (used when `--webhook` flag is not provided) |
135
+
136
+ ## Building
137
+
138
+ ```bash
139
+ npm install
140
+ npm run build
141
+ ```
142
+
143
+ This compiles `index.ts` to `dist/index.js`.
144
+
145
+ ## Development
146
+
147
+ ```bash
148
+ npm run dev # watch mode
149
+ ```
150
+
151
+ ## How It Works
152
+
153
+ 1. Fetches items from pm-cli with statuses `wip`, `blocked`, `todo`, and optionally `done`.
154
+ 2. Sorts `todo` items by priority (ascending) and takes the top 3 as "Up Next".
155
+ 3. Formats a message using either Slack mrkdwn or plain text.
156
+ 4. Posts the message to the configured Slack webhook using Node.js native `https`.
157
+
158
+ ## License
159
+
160
+ MIT
161
+
162
+ ## Release Automation
163
+
164
+ This package is release-ready for GitHub, npm, and Bun-compatible installs. CI runs type checking, build, production dependency audit, package packing, Bun install verification, and pm-changelog validation. The daily release workflow publishes only when commits exist after the latest release tag and uses pm-changelog to generate CHANGELOG.md and GitHub release notes.
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ name: string;
3
+ version: string;
4
+ activate(api: import("@unbrained/pm-cli/sdk").ExtensionApi): void;
5
+ };
6
+ export default _default;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;AAgLA,wBA4GG"}
package/dist/index.js ADDED
@@ -0,0 +1,230 @@
1
+ import https from "node:https";
2
+ import { spawnSync } from "node:child_process";
3
+ const defineExtension = ((extension) => extension);
4
+ // ---------------------------------------------------------------------------
5
+ // Helpers
6
+ // ---------------------------------------------------------------------------
7
+ function fetchItemsByStatus(pmRoot, subcommand) {
8
+ const result = spawnSync("pm", ["--path", pmRoot, subcommand, "--json"], { encoding: "utf-8" });
9
+ if (result.error || result.status !== 0) {
10
+ console.error(`pm ${subcommand} failed: ${result.stderr}`);
11
+ return [];
12
+ }
13
+ return (JSON.parse(result.stdout).items ?? []);
14
+ }
15
+ function typeLabel(item) {
16
+ if (!item.type)
17
+ return "";
18
+ const label = item.type.charAt(0).toUpperCase() + item.type.slice(1);
19
+ return `[${label}]`;
20
+ }
21
+ function itemLine(item, format) {
22
+ const label = typeLabel(item);
23
+ const title = label ? `${label} ${item.title}` : item.title;
24
+ return format === "slack" ? `• ${title}` : `• ${title}`;
25
+ }
26
+ function todayISO() {
27
+ return new Date().toISOString().slice(0, 10);
28
+ }
29
+ function buildMessage(wip, blocked, done, upNext, opts) {
30
+ const { format } = opts;
31
+ const lines = [];
32
+ // Header
33
+ const dateStr = todayISO();
34
+ if (format === "slack") {
35
+ lines.push(`📊 *pm standup* — ${dateStr}`);
36
+ }
37
+ else {
38
+ lines.push(`📊 pm standup — ${dateStr}`);
39
+ }
40
+ // Channel prefix (prepended at the very top when posting to Slack)
41
+ // It's added to the message body so dry-run also shows it.
42
+ if (opts.channel) {
43
+ lines.unshift(`> Channel: ${opts.channel}`);
44
+ }
45
+ lines.push("");
46
+ // In Progress
47
+ if (format === "slack") {
48
+ lines.push(`🏃 *In Progress* (${wip.length})`);
49
+ }
50
+ else {
51
+ lines.push(`🏃 In Progress (${wip.length})`);
52
+ }
53
+ if (wip.length === 0) {
54
+ lines.push("• _nothing in progress_");
55
+ }
56
+ else {
57
+ for (const item of wip)
58
+ lines.push(itemLine(item, format));
59
+ }
60
+ lines.push("");
61
+ // Blocked
62
+ if (format === "slack") {
63
+ lines.push(`🚫 *Blocked* (${blocked.length})`);
64
+ }
65
+ else {
66
+ lines.push(`🚫 Blocked (${blocked.length})`);
67
+ }
68
+ if (blocked.length === 0) {
69
+ lines.push("• _nothing blocked_");
70
+ }
71
+ else {
72
+ for (const item of blocked)
73
+ lines.push(itemLine(item, format));
74
+ }
75
+ // Done Today (optional)
76
+ if (done.length > 0) {
77
+ lines.push("");
78
+ if (format === "slack") {
79
+ lines.push(`✅ *Done Today* (${done.length})`);
80
+ }
81
+ else {
82
+ lines.push(`✅ Done Today (${done.length})`);
83
+ }
84
+ for (const item of done)
85
+ lines.push(itemLine(item, format));
86
+ }
87
+ // Up Next
88
+ if (upNext.length > 0) {
89
+ lines.push("");
90
+ if (format === "slack") {
91
+ lines.push(`📋 *Up Next* (${upNext.length})`);
92
+ }
93
+ else {
94
+ lines.push(`📋 Up Next (${upNext.length})`);
95
+ }
96
+ upNext.forEach((item) => {
97
+ const label = typeLabel(item);
98
+ const title = label ? `${label} ${item.title}` : item.title;
99
+ const prio = item.priority != null ? ` (priority ${item.priority})` : "";
100
+ lines.push(`• ${title}${prio}`);
101
+ });
102
+ }
103
+ return lines.join("\n");
104
+ }
105
+ function postToSlack(webhookUrl, text) {
106
+ return new Promise((resolve, reject) => {
107
+ const payload = JSON.stringify({ text, mrkdwn: true });
108
+ const url = new URL(webhookUrl);
109
+ const options = {
110
+ hostname: url.hostname,
111
+ path: url.pathname + url.search,
112
+ method: "POST",
113
+ headers: {
114
+ "Content-Type": "application/json",
115
+ "Content-Length": Buffer.byteLength(payload),
116
+ },
117
+ };
118
+ const req = https.request(options, (res) => {
119
+ let body = "";
120
+ res.on("data", (chunk) => (body += chunk.toString()));
121
+ res.on("end", () => {
122
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
123
+ resolve();
124
+ }
125
+ else {
126
+ reject(new Error(`Slack webhook returned HTTP ${res.statusCode ?? "unknown"}: ${body}`));
127
+ }
128
+ });
129
+ });
130
+ req.on("error", reject);
131
+ req.write(payload);
132
+ req.end();
133
+ });
134
+ }
135
+ // ---------------------------------------------------------------------------
136
+ // Extension
137
+ // ---------------------------------------------------------------------------
138
+ export default defineExtension({
139
+ name: "pm-slack-standup",
140
+ version: "0.1.0",
141
+ activate(api) {
142
+ api.registerCommand({
143
+ name: "standup",
144
+ description: "Post pm context as a Slack standup message",
145
+ intent: "Share current work status (in-progress, blocked, up-next) to a Slack channel via webhook",
146
+ examples: [
147
+ "pm standup --webhook https://hooks.slack.com/services/...",
148
+ "pm standup --channel '#team-eng' --dry-run",
149
+ "pm standup --include-done --format text",
150
+ "PM_SLACK_WEBHOOK=https://... pm standup --channel '#standups'",
151
+ ],
152
+ flags: [
153
+ {
154
+ long: "--webhook",
155
+ value_name: "url",
156
+ description: "Slack incoming webhook URL (overrides PM_SLACK_WEBHOOK env var)",
157
+ },
158
+ {
159
+ long: "--channel",
160
+ value_name: "name",
161
+ description: "Channel name to prepend to the standup message (e.g. #team-eng)",
162
+ },
163
+ {
164
+ long: "--dry-run",
165
+ description: "Print the message without posting to Slack",
166
+ },
167
+ {
168
+ long: "--include-done",
169
+ description: "Include items with 'closed' status in a Done Today section",
170
+ },
171
+ {
172
+ long: "--format",
173
+ value_name: "fmt",
174
+ description: "Output format: 'slack' uses mrkdwn bold/italic, 'text' is plain (default: slack)",
175
+ },
176
+ ],
177
+ async run(ctx) {
178
+ // Resolve options
179
+ const webhookUrl = ctx.options["webhook"] ?? process.env["PM_SLACK_WEBHOOK"] ?? "";
180
+ const dryRun = Boolean(ctx.options["dry-run"]);
181
+ const includeDone = Boolean(ctx.options["include-done"]);
182
+ const rawFormat = ctx.options["format"];
183
+ const format = rawFormat === "text" ? "text" : "slack";
184
+ const channel = ctx.options["channel"];
185
+ if (!dryRun && !webhookUrl) {
186
+ return {
187
+ error: "missing_webhook",
188
+ message: "No webhook URL provided. Set --webhook or PM_SLACK_WEBHOOK env var, or use --dry-run.",
189
+ };
190
+ }
191
+ // Fetch items using pm subcommands
192
+ const wipItems = fetchItemsByStatus(ctx.pm_root, "list-in-progress");
193
+ const blockedItems = fetchItemsByStatus(ctx.pm_root, "list-blocked");
194
+ const todoItems = fetchItemsByStatus(ctx.pm_root, "list-open");
195
+ const doneItems = includeDone ? fetchItemsByStatus(ctx.pm_root, "list-closed") : [];
196
+ // Sort todo by priority (lower number = higher priority), take top 3
197
+ const upNext = [...todoItems]
198
+ .sort((a, b) => {
199
+ const pa = a.priority ?? 9999;
200
+ const pb = b.priority ?? 9999;
201
+ return pa - pb;
202
+ })
203
+ .slice(0, 3);
204
+ const message = buildMessage(wipItems, blockedItems, doneItems, upNext, { channel, format, includeDate: true });
205
+ if (dryRun) {
206
+ console.error("--- DRY RUN (message not posted) ---");
207
+ process.stdout.write(message + "\n");
208
+ console.error("--- END ---");
209
+ return {
210
+ dryRun: true,
211
+ message,
212
+ wip: wipItems.length,
213
+ blocked: blockedItems.length,
214
+ done: doneItems.length,
215
+ upNext: upNext.length,
216
+ };
217
+ }
218
+ await postToSlack(webhookUrl, message);
219
+ return {
220
+ posted: true,
221
+ wip: wipItems.length,
222
+ blocked: blockedItems.length,
223
+ done: doneItems.length,
224
+ upNext: upNext.length,
225
+ };
226
+ },
227
+ });
228
+ },
229
+ });
230
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/manifest.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "pm-slack-standup",
3
+ "version": "0.1.0",
4
+ "description": "Post pm context as a Slack standup message",
5
+ "author": "@unbraind",
6
+ "entry": "./dist/index.js",
7
+ "priority": 50,
8
+ "capabilities": [
9
+ "commands",
10
+ "schema"
11
+ ],
12
+ "pm": {
13
+ "compatibility": "v2"
14
+ }
15
+ }
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "pm-slack-standup",
3
+ "version": "0.1.0",
4
+ "description": "Post pm context as a Slack standup message",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/unbraind/pm-slack-standup.git"
8
+ },
9
+ "bugs": {
10
+ "url": "https://github.com/unbraind/pm-slack-standup/issues"
11
+ },
12
+ "homepage": "https://github.com/unbraind/pm-slack-standup#readme",
13
+ "type": "module",
14
+ "main": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "files": [
17
+ "dist/",
18
+ "manifest.json",
19
+ "README.md",
20
+ "CHANGELOG.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "tsc --watch",
25
+ "prepack": "npm run build",
26
+ "typecheck": "tsc --noEmit",
27
+ "check": "npm run typecheck",
28
+ "audit:prod": "npm audit --omit=dev",
29
+ "pack:dry-run": "npm pack --dry-run",
30
+ "changelog": "pm-changelog --pm-root .agents/pm --mode prepend --output CHANGELOG.md --release-version-from-package --since-previous-tag --until-release-tag --item-url-base https://github.com/unbraind/pm-slack-standup/blob/main/.agents/pm",
31
+ "changelog:full": "pm-changelog --pm-root .agents/pm --mode replace --output CHANGELOG.md --all-release-tags --release-version-from-package --item-url-base https://github.com/unbraind/pm-slack-standup/blob/main/.agents/pm",
32
+ "changelog:check": "pm-changelog --pm-root .agents/pm --mode replace --output CHANGELOG.md --all-release-tags --release-version-from-package --item-url-base https://github.com/unbraind/pm-slack-standup/blob/main/.agents/pm --check",
33
+ "release:check": "npm run typecheck && npm run build && npm run audit:prod && npm run pack:dry-run && npm run changelog:check"
34
+ },
35
+ "peerDependencies": {
36
+ "@unbrained/pm-cli": ">=2026.5.24"
37
+ },
38
+ "devDependencies": {
39
+ "@unbrained/pm-cli": "^2026.5.24",
40
+ "typescript": "^6.0.3",
41
+ "pm-changelog": "^2026.5.25",
42
+ "@types/node": "^25.9.1"
43
+ },
44
+ "keywords": [
45
+ "pm-cli",
46
+ "pm-cli-extension",
47
+ "pm-extension",
48
+ "pm-package",
49
+ "slack",
50
+ "standup"
51
+ ],
52
+ "license": "MIT",
53
+ "engines": {
54
+ "node": ">=20.0.0"
55
+ },
56
+ "author": "@unbraind",
57
+ "pm": {
58
+ "aliases": [
59
+ "slack-standup"
60
+ ],
61
+ "extensions": [
62
+ "."
63
+ ],
64
+ "catalog": {
65
+ "display_name": "Slack Standup",
66
+ "category": "reporting",
67
+ "summary": "Post pm context as a Slack standup message",
68
+ "tags": [
69
+ "slack",
70
+ "standup",
71
+ "reporting"
72
+ ],
73
+ "links": {
74
+ "docs": "https://github.com/unbraind/pm-slack-standup#readme",
75
+ "npm": "https://www.npmjs.com/package/pm-slack-standup",
76
+ "repository": "https://github.com/unbraind/pm-slack-standup",
77
+ "report": "https://github.com/unbraind/pm-slack-standup/issues"
78
+ }
79
+ },
80
+ "docs": [
81
+ "README.md",
82
+ "CHANGELOG.md"
83
+ ],
84
+ "examples": [
85
+ "README.md"
86
+ ]
87
+ }
88
+ }