geekbot-cli 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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +517 -0
  3. package/package.json +50 -0
  4. package/scripts/postinstall.mjs +27 -0
  5. package/skills/geekbot/SKILL.md +281 -0
  6. package/skills/geekbot/check-cli.sh +36 -0
  7. package/skills/geekbot/cli-commands.md +382 -0
  8. package/skills/geekbot/error-recovery.md +95 -0
  9. package/skills/geekbot/manager-workflows.md +408 -0
  10. package/skills/geekbot/reporter-workflows.md +275 -0
  11. package/skills/geekbot/standup-templates.json +244 -0
  12. package/src/auth/keychain.ts +38 -0
  13. package/src/auth/resolver.ts +44 -0
  14. package/src/cli/commands/auth.ts +56 -0
  15. package/src/cli/commands/me.ts +34 -0
  16. package/src/cli/commands/poll.ts +91 -0
  17. package/src/cli/commands/report.ts +66 -0
  18. package/src/cli/commands/standup.ts +234 -0
  19. package/src/cli/commands/team.ts +40 -0
  20. package/src/cli/globals.ts +31 -0
  21. package/src/cli/index.ts +94 -0
  22. package/src/errors/cli-error.ts +16 -0
  23. package/src/errors/error-handler.ts +63 -0
  24. package/src/errors/exit-codes.ts +14 -0
  25. package/src/errors/not-found-helper.ts +86 -0
  26. package/src/handlers/auth-handlers.ts +152 -0
  27. package/src/handlers/me-handlers.ts +27 -0
  28. package/src/handlers/poll-handlers.ts +187 -0
  29. package/src/handlers/report-handlers.ts +87 -0
  30. package/src/handlers/standup-handlers.ts +534 -0
  31. package/src/handlers/team-handlers.ts +38 -0
  32. package/src/http/authenticated-client.ts +17 -0
  33. package/src/http/client.ts +138 -0
  34. package/src/http/errors.ts +134 -0
  35. package/src/output/envelope.ts +50 -0
  36. package/src/output/formatter.ts +12 -0
  37. package/src/schemas/common.ts +13 -0
  38. package/src/schemas/poll.ts +89 -0
  39. package/src/schemas/report.ts +124 -0
  40. package/src/schemas/standup.ts +64 -0
  41. package/src/schemas/team.ts +11 -0
  42. package/src/schemas/user.ts +70 -0
  43. package/src/types.ts +30 -0
  44. package/src/utils/constants.ts +24 -0
  45. package/src/utils/input-parsers.ts +234 -0
  46. package/src/utils/receipt.ts +94 -0
  47. package/src/utils/validation.ts +128 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Geekbot
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,517 @@
1
+ # geekbot-cli
2
+
3
+ A cross-platform CLI tool for interacting with the Geekbot API, designed for AI agents and humans. Built with Bun and TypeScript.
4
+
5
+ Manage standups, reports, polls, teams, and user profiles programmatically with structured JSON output, machine-readable exit codes, and actionable error messages.
6
+
7
+ ## Installation
8
+
9
+ ### Prerequisites
10
+
11
+ - [Bun](https://bun.sh/) runtime (v1.3.5 or later)
12
+
13
+ ### Install via npm
14
+
15
+ ```shell
16
+ npm install -g geekbot-cli
17
+ ```
18
+
19
+ This installs the `geekbot` binary globally. The postinstall script checks for Bun and prints a hint about skill registration.
20
+
21
+ > **Note:** `npx geekbot-cli` also requires Bun on PATH — the CLI uses a `#!/usr/bin/env bun` shebang, so it is not a Node.js fallback.
22
+
23
+ Verify the installation:
24
+
25
+ ```shell
26
+ geekbot --version
27
+ # 0.1.0
28
+ ```
29
+
30
+ ### Register the AI agent skill
31
+
32
+ To register the Geekbot skill with your AI coding agents (Claude Code, Cursor, Windsurf, Copilot, etc.):
33
+
34
+ ```shell
35
+ npx skills add geekbot-com/geekbot-cli
36
+ ```
37
+
38
+ This uses the [Vercel Skills](https://github.com/vercel-labs/skills) ecosystem to detect installed agents and register the skill with all of them.
39
+
40
+ <details>
41
+ <summary>Manual skill installation (without npx skills)</summary>
42
+
43
+ If you prefer not to use `npx skills`, copy the `skills/geekbot/` directory into your agent's skill directory:
44
+
45
+ ```shell
46
+ # Claude Code
47
+ cp -r node_modules/geekbot-cli/skills/geekbot ~/.claude/skills/geekbot
48
+
49
+ # Universal (.agents/skills/ — works with Cursor, Codex, Gemini CLI, etc.)
50
+ mkdir -p .agents/skills
51
+ cp -r node_modules/geekbot-cli/skills/geekbot .agents/skills/geekbot
52
+
53
+ # Windsurf
54
+ cp -r node_modules/geekbot-cli/skills/geekbot ~/.codeium/windsurf/skills/geekbot
55
+
56
+ # Roo Code
57
+ cp -r node_modules/geekbot-cli/skills/geekbot ~/.roo/skills/geekbot
58
+ ```
59
+
60
+ The skill directory must contain `SKILL.md` and its sibling reference files (`cli-commands.md`, `manager-workflows.md`, etc.) — they are loaded by relative path.
61
+
62
+ </details>
63
+
64
+ ### Install from source (for development)
65
+
66
+ ```shell
67
+ git clone https://github.com/geekbot-com/geekbot-cli.git
68
+ cd geekbot-cli
69
+ bun install
70
+ bun link
71
+ ```
72
+
73
+ ### Platform support
74
+
75
+ | Platform | Status |
76
+ |----------|--------|
77
+ | macOS (x64, ARM64) | Supported |
78
+ | Linux (x64, ARM64) | Supported |
79
+ | Windows (x64) | Supported (requires Bun >= 1.3.5) |
80
+ | Windows (ARM64) | Not supported (Bun does not yet ship ARM64 Windows binaries) |
81
+
82
+ ## Authentication
83
+
84
+ The CLI resolves API credentials using a three-level priority chain. The first source found wins:
85
+
86
+ 1. **`--api-key` flag** (highest priority) -- per-command override, useful for scripts and CI
87
+ 2. **`GEEKBOT_API_KEY` environment variable** -- session or shell-level credential
88
+ 3. **OS keychain** (lowest priority) -- persistent, secure storage via `geekbot auth setup`
89
+
90
+ ### OS Keychain Storage
91
+
92
+ The CLI uses [`@napi-rs/keyring`](https://github.com/nicola-nicolo/keyring) to store your API key in the platform-native credential store:
93
+
94
+ - **macOS**: Keychain
95
+ - **Windows**: Credential Vault
96
+ - **Linux**: Secret Service (GNOME Keyring / KDE Wallet)
97
+
98
+ Store a key interactively:
99
+
100
+ ```shell
101
+ geekbot auth setup
102
+ ```
103
+
104
+ Or non-interactively:
105
+
106
+ ```shell
107
+ geekbot auth setup --api-key YOUR_API_KEY
108
+ ```
109
+
110
+ The setup command validates the key against the Geekbot API before storing it.
111
+
112
+ ### Verify credentials
113
+
114
+ ```shell
115
+ geekbot auth status
116
+ ```
117
+
118
+ ### Remove stored key
119
+
120
+ ```shell
121
+ geekbot auth remove
122
+ ```
123
+
124
+ ## Global Options
125
+
126
+ These options apply to all commands:
127
+
128
+ | Option | Description | Default |
129
+ |--------|-------------|---------|
130
+ | `--api-key <key>` | Geekbot API key (overrides `GEEKBOT_API_KEY` env var) | -- |
131
+ | `--output <format>` | Output format (`json` only) | `json` |
132
+ | `--debug` | Show debug output on stderr | `false` |
133
+ | `-v, --version` | Print version number | -- |
134
+ | `--help` | Show help text | -- |
135
+
136
+ ## Commands
137
+
138
+ The CLI follows a noun-verb pattern: `geekbot <resource> <action> [options]`.
139
+
140
+ ### `standup` -- Manage standups
141
+
142
+ | Subcommand | Syntax | Description |
143
+ |------------|--------|-------------|
144
+ | `list` | `geekbot standup list [options]` | List standups you participate in |
145
+ | `get` | `geekbot standup get <id>` | Get a standup by ID |
146
+ | `create` | `geekbot standup create --name <name> --channel <channel> [options]` | Create a new standup |
147
+ | `update` | `geekbot standup update <id> [options]` | Partially update a standup (PATCH) |
148
+ | `replace` | `geekbot standup replace <id> --name <name> --channel <channel> [options]` | Fully replace a standup (PUT) |
149
+ | `delete` | `geekbot standup delete <id> --yes` | Delete a standup |
150
+ | `duplicate` | `geekbot standup duplicate <id> --name <name>` | Duplicate an existing standup |
151
+ | `start` | `geekbot standup start <id> [--users <ids>]` | Trigger a standup immediately |
152
+
153
+ #### `standup list` options
154
+
155
+ | Option | Default | Description |
156
+ |--------|---------|-------------|
157
+ | `--admin` | `false` | Include all team standups (admin only) |
158
+ | `--brief` | `false` | Return only id, name, channel, time, timezone, days |
159
+ | `--name <name>` | -- | Filter by name (case-insensitive substring match) |
160
+ | `--channel <channel>` | -- | Filter by channel (case-insensitive substring match) |
161
+ | `--mine` | `false` | Show only standups you are a member of |
162
+
163
+ #### `standup create` options
164
+
165
+ | Option | Required | Default | Description |
166
+ |--------|----------|---------|-------------|
167
+ | `--name <name>` | Yes | -- | Standup name |
168
+ | `--channel <channel>` | Yes | -- | Slack channel name |
169
+ | `--time <time>` | No | `10:00` | Time in HH:MM 24-hour format |
170
+ | `--timezone <tz>` | No | `UTC` | IANA timezone |
171
+ | `--days <days>` | No | `Mon,Tue,Wed,Thu,Fri` | Comma-separated days |
172
+ | `--questions <json>` | Yes | -- | Questions as JSON array |
173
+ | `--users <ids>` | No | -- | Comma-separated user IDs |
174
+ | `--wait-time <minutes>` | No | `0` | Minutes between users |
175
+
176
+ #### `standup update` options
177
+
178
+ | Option | Required | Description |
179
+ |--------|----------|-------------|
180
+ | `--name <name>` | No | New standup name |
181
+ | `--channel <channel>` | No | New channel |
182
+ | `--time <time>` | No | New time (HH:MM) |
183
+ | `--timezone <tz>` | No | New timezone |
184
+ | `--days <days>` | No | New days (comma-separated) |
185
+ | `--wait-time <minutes>` | No | New wait time in minutes |
186
+
187
+ #### `standup replace` options
188
+
189
+ Same options as `create`. `--name` and `--channel` are required; all other options have the same defaults as `create`.
190
+
191
+ #### `standup delete` options
192
+
193
+ | Option | Description |
194
+ |--------|-------------|
195
+ | `--yes` | Confirm deletion (required; deletion fails with an error if omitted) |
196
+
197
+ ### `report` -- Manage reports
198
+
199
+ | Subcommand | Syntax | Description |
200
+ |------------|--------|-------------|
201
+ | `list` | `geekbot report list [options]` | List reports with optional filters |
202
+ | `create` | `geekbot report create --standup-id <id> --answers <json>` | Submit a report for a standup |
203
+
204
+ #### `report list` options
205
+
206
+ | Option | Description |
207
+ |--------|-------------|
208
+ | `--standup-id <id>` | Filter by standup ID |
209
+ | `--user-id <id>` | Filter by user ID |
210
+ | `--before <date>` | Reports before date (ISO 8601 or unix timestamp) |
211
+ | `--after <date>` | Reports after date (ISO 8601 or unix timestamp) |
212
+ | `--limit <n>` | Max number of reports to return |
213
+
214
+ #### `report create` options
215
+
216
+ | Option | Required | Description |
217
+ |--------|----------|-------------|
218
+ | `--standup-id <id>` | Yes | Standup ID to report on |
219
+ | `--answers <json>` | Yes | Answers as JSON object: `{"question_id": "answer", ...}` |
220
+
221
+ ### `poll` -- Manage polls (Slack teams only)
222
+
223
+ Polls are only available for Slack-connected teams. Non-Slack teams will receive a platform error.
224
+
225
+ | Subcommand | Syntax | Description |
226
+ |------------|--------|-------------|
227
+ | `list` | `geekbot poll list` | List all polls |
228
+ | `get` | `geekbot poll get <id>` | Get a poll by ID |
229
+ | `create` | `geekbot poll create --name <name> --channel <channel> --question <text> --choices <json>` | Create a new poll |
230
+ | `votes` | `geekbot poll votes <id> [--after <date>] [--before <date>]` | Get voting results for a poll |
231
+
232
+ #### `poll create` options
233
+
234
+ | Option | Required | Description |
235
+ |--------|----------|-------------|
236
+ | `--name <name>` | Yes | Poll name |
237
+ | `--channel <channel>` | Yes | Slack channel |
238
+ | `--question <text>` | Yes | Poll question text |
239
+ | `--choices <json>` | Yes | Choices as JSON array of strings |
240
+
241
+ #### `poll votes` options
242
+
243
+ | Option | Description |
244
+ |--------|-------------|
245
+ | `--after <date>` | Votes after date |
246
+ | `--before <date>` | Votes before date |
247
+
248
+ ### `me` -- View your profile and teams
249
+
250
+ | Subcommand | Syntax | Description |
251
+ |------------|--------|-------------|
252
+ | `show` | `geekbot me show` | Show your Geekbot profile |
253
+ | `teams` | `geekbot me teams` | List teams you belong to |
254
+
255
+ ### `team` -- View team information
256
+
257
+ | Subcommand | Syntax | Description |
258
+ |------------|--------|-------------|
259
+ | `list` | `geekbot team list` | List all teams with members |
260
+
261
+ ### `auth` -- Manage authentication
262
+
263
+ | Subcommand | Syntax | Description |
264
+ |------------|--------|-------------|
265
+ | `setup` | `geekbot auth setup [--api-key <key>]` | Interactively configure and store API key |
266
+ | `status` | `geekbot auth status` | Verify stored credentials work |
267
+ | `remove` | `geekbot auth remove` | Remove stored API key from OS keychain |
268
+
269
+ ## Output Format
270
+
271
+ All command output is written to **stdout** as a JSON envelope. Diagnostic messages (debug output, Commander.js help/errors) go to **stderr**.
272
+
273
+ ### JSON Envelope
274
+
275
+ Every response follows this structure:
276
+
277
+ ```typescript
278
+ interface OutputEnvelope<T> {
279
+ ok: boolean;
280
+ data: T | null;
281
+ error: ErrorObject | null;
282
+ metadata: MetadataObject;
283
+ }
284
+ ```
285
+
286
+ ### Success Response
287
+
288
+ ```json
289
+ {
290
+ "ok": true,
291
+ "data": {
292
+ "id": 123,
293
+ "name": "Daily Standup",
294
+ "channel": "#engineering",
295
+ "time": "10:00",
296
+ "timezone": "America/New_York",
297
+ "days": ["Mon", "Tue", "Wed", "Thu", "Fri"],
298
+ "questions": [
299
+ { "id": 101, "text": "What did you do yesterday?" },
300
+ { "id": 102, "text": "What will you do today?" }
301
+ ]
302
+ },
303
+ "error": null,
304
+ "metadata": {
305
+ "timestamp": "2026-03-17T10:30:00.000Z"
306
+ }
307
+ }
308
+ ```
309
+
310
+ ### Error Response
311
+
312
+ ```json
313
+ {
314
+ "ok": false,
315
+ "data": null,
316
+ "error": {
317
+ "code": "standup_not_found",
318
+ "message": "Standup 999 not found",
319
+ "retryable": false,
320
+ "suggestion": "Available standups: 123 (Daily Standup), 456 (Weekly Sync). Run `geekbot standup list` to see all."
321
+ },
322
+ "metadata": {
323
+ "timestamp": "2026-03-17T10:30:00.000Z"
324
+ }
325
+ }
326
+ ```
327
+
328
+ ## Exit Codes
329
+
330
+ The CLI uses specific exit codes for programmatic error handling:
331
+
332
+ | Code | Name | Meaning |
333
+ |------|------|---------|
334
+ | 0 | `SUCCESS` | Operation completed successfully |
335
+ | 1 | `GENERAL` | Unexpected or unclassified error |
336
+ | 2 | `USAGE` | Invalid command syntax or missing required options |
337
+ | 3 | `NOT_FOUND` | Requested resource does not exist |
338
+ | 4 | `AUTH` | Authentication failed (missing or invalid API key) |
339
+ | 5 | `FORBIDDEN` | Insufficient permissions for the operation |
340
+ | 6 | `VALIDATION` | Input validation failed (bad format, invalid values) |
341
+ | 7 | `NETWORK` | Network error (DNS failure, timeout, connection refused) |
342
+ | 8 | `CONFLICT` | Resource conflict (duplicate name, concurrent modification) |
343
+ | 9 | `API_ERROR` | Geekbot API returned an unexpected error |
344
+
345
+ ## Error Handling
346
+
347
+ Errors include machine-readable fields designed for programmatic consumption:
348
+
349
+ ```typescript
350
+ interface ErrorObject {
351
+ code: string; // Machine-readable error code (e.g., "standup_not_found")
352
+ message: string; // Human-readable description
353
+ retryable: boolean; // Whether retrying may succeed (e.g., network errors)
354
+ suggestion: string | null; // Actionable next step
355
+ }
356
+ ```
357
+
358
+ Key behaviors:
359
+
360
+ - **Not-found errors suggest alternatives**: When a resource ID is not found, the CLI queries for valid IDs and includes them in the `suggestion` field.
361
+ - **Retryable flag**: Network errors and rate limits are marked `retryable: true`. Auth and validation errors are not.
362
+ - **Structured output on failure**: Even errors produce a valid JSON envelope on stdout, so parsers never encounter unexpected output.
363
+
364
+ ## Examples
365
+
366
+ ### List standups
367
+
368
+ ```shell
369
+ geekbot standup list --output json
370
+ ```
371
+
372
+ ```json
373
+ {
374
+ "ok": true,
375
+ "data": [
376
+ { "id": 123, "name": "Daily Standup", "channel": "#engineering", "time": "10:00", "timezone": "UTC" },
377
+ { "id": 456, "name": "Weekly Sync", "channel": "#team", "time": "09:00", "timezone": "America/New_York" }
378
+ ],
379
+ "error": null,
380
+ "metadata": { "timestamp": "2026-03-17T10:00:00.000Z" }
381
+ }
382
+ ```
383
+
384
+ ### Create a standup
385
+
386
+ ```shell
387
+ geekbot standup create \
388
+ --name "Sprint Retro" \
389
+ --channel "#engineering" \
390
+ --time "15:00" \
391
+ --timezone "America/Chicago" \
392
+ --days "Fri" \
393
+ --questions '[{"question": "What went well?"}, {"question": "What could improve?"}]'
394
+ ```
395
+
396
+ ```json
397
+ {
398
+ "ok": true,
399
+ "data": {
400
+ "id": 789,
401
+ "name": "Sprint Retro",
402
+ "channel": "#engineering",
403
+ "time": "15:00",
404
+ "timezone": "America/Chicago",
405
+ "days": ["Fri"]
406
+ },
407
+ "error": null,
408
+ "metadata": {
409
+ "timestamp": "2026-03-17T10:05:00.000Z",
410
+ "operation": "created",
411
+ "undo": "geekbot standup delete 789 --yes"
412
+ }
413
+ }
414
+ ```
415
+
416
+ ### Submit a report
417
+
418
+ ```shell
419
+ geekbot report create \
420
+ --standup-id 123 \
421
+ --answers '{"101": "Finished auth module", "102": "Starting API tests"}'
422
+ ```
423
+
424
+ ```json
425
+ {
426
+ "ok": true,
427
+ "data": {
428
+ "id": 5001,
429
+ "standup_id": 123,
430
+ "questions": [
431
+ { "id": 101, "text": "What did you do yesterday?", "answer": "Finished auth module" },
432
+ { "id": 102, "text": "What will you do today?", "answer": "Starting API tests" }
433
+ ]
434
+ },
435
+ "error": null,
436
+ "metadata": { "timestamp": "2026-03-17T10:10:00.000Z" }
437
+ }
438
+ ```
439
+
440
+ ### Handle a not-found error
441
+
442
+ ```shell
443
+ geekbot standup get 999
444
+ ```
445
+
446
+ ```json
447
+ {
448
+ "ok": false,
449
+ "data": null,
450
+ "error": {
451
+ "code": "standup_not_found",
452
+ "message": "Standup 999 not found",
453
+ "retryable": false,
454
+ "suggestion": "Available standups: 123 (Daily Standup), 456 (Weekly Sync). Run `geekbot standup list` to see all."
455
+ },
456
+ "metadata": { "timestamp": "2026-03-17T10:15:00.000Z" }
457
+ }
458
+ ```
459
+
460
+ Exit code: `3` (NOT_FOUND)
461
+
462
+ ### Create a poll (Slack only)
463
+
464
+ ```shell
465
+ geekbot poll create \
466
+ --name "Team Lunch" \
467
+ --channel "#general" \
468
+ --question "Where should we eat?" \
469
+ --choices '["Pizza", "Sushi", "Tacos"]'
470
+ ```
471
+
472
+ ### Use environment variable for auth
473
+
474
+ ```shell
475
+ export GEEKBOT_API_KEY=your-api-key
476
+ geekbot standup list
477
+ ```
478
+
479
+ ## Development
480
+
481
+ ### Run tests
482
+
483
+ ```shell
484
+ bun test
485
+ ```
486
+
487
+ ### Lint
488
+
489
+ ```shell
490
+ bun run lint
491
+ ```
492
+
493
+ ### Format
494
+
495
+ ```shell
496
+ bun run format
497
+ ```
498
+
499
+ ### Lint and auto-fix
500
+
501
+ ```shell
502
+ bun run check
503
+ ```
504
+
505
+ ### Integration tests
506
+
507
+ Integration tests run against the live Geekbot API and require a valid API key:
508
+
509
+ ```shell
510
+ GEEKBOT_INTEGRATION_TEST_API_KEY=your-key bun test:integration
511
+ ```
512
+
513
+ Tests are automatically skipped when `GEEKBOT_INTEGRATION_TEST_API_KEY` is not set. Tests that require a Slack channel (`#geekbot-skill-tests`) will gracefully skip with a warning if the channel does not exist in the workspace.
514
+
515
+ ## License
516
+
517
+ See LICENSE.
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "geekbot-cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/geekbot-com/geekbot-cli"
9
+ },
10
+ "bin": {
11
+ "geekbot": "./src/cli/index.ts"
12
+ },
13
+ "files": [
14
+ "src/",
15
+ "skills/",
16
+ "scripts/"
17
+ ],
18
+ "scripts": {
19
+ "postinstall": "node scripts/postinstall.mjs",
20
+ "dev": "bun run src/cli/index.ts",
21
+ "test": "bun test",
22
+ "test:integration": "bun test tests/integration/",
23
+ "lint": "bunx biome check .",
24
+ "format": "bunx biome format --write .",
25
+ "check": "bunx biome check --write ."
26
+ },
27
+ "publishConfig": {
28
+ "access": "public",
29
+ "provenance": true
30
+ },
31
+ "keywords": [
32
+ "geekbot",
33
+ "standup",
34
+ "cli",
35
+ "ai-agent",
36
+ "skill"
37
+ ],
38
+ "devDependencies": {
39
+ "@biomejs/biome": "^2.4.7",
40
+ "@types/bun": "^1.3.10"
41
+ },
42
+ "peerDependencies": {
43
+ "typescript": "^5"
44
+ },
45
+ "dependencies": {
46
+ "@napi-rs/keyring": "^1.2.0",
47
+ "commander": "^14.0.3",
48
+ "zod": "^4.3.6"
49
+ }
50
+ }
@@ -0,0 +1,27 @@
1
+ // Runs after npm install. Checks for Bun and hints about skill registration.
2
+ // Must work in plain Node.js (no Bun, no dependencies).
3
+
4
+ import { execSync } from "node:child_process";
5
+ import { platform } from "node:os";
6
+
7
+ // ── Bun availability check ──────────────────────────────────────────────────
8
+ // The geekbot CLI binary requires Bun. Warn early if it's missing.
9
+ try {
10
+ execSync("bun --version", { stdio: "ignore" });
11
+ } catch {
12
+ const installCmd =
13
+ platform() === "win32"
14
+ ? 'powershell -c "irm bun.sh/install.ps1 | iex"'
15
+ : "curl -fsSL https://bun.sh/install | bash";
16
+ console.warn(
17
+ "geekbot: warning: Bun runtime not found. The geekbot CLI requires Bun.\n" +
18
+ `geekbot: Install it: ${installCmd}\n` +
19
+ "geekbot: Then the `geekbot` command will work.",
20
+ );
21
+ }
22
+
23
+ // ── Skill registration hint ─────────────────────────────────────────────────
24
+ console.log(
25
+ "geekbot: to register the skill with your AI agents, run:\n" +
26
+ "geekbot: npx skills add geekbot-com/geekbot-cli",
27
+ );