@legdev/tkxr 1.1.11

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 (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +477 -0
  3. package/dist/cli/commands/comments.d.ts +10 -0
  4. package/dist/cli/commands/comments.d.ts.map +1 -0
  5. package/dist/cli/commands/comments.js +81 -0
  6. package/dist/cli/commands/comments.js.map +1 -0
  7. package/dist/cli/commands/create.d.ts +11 -0
  8. package/dist/cli/commands/create.d.ts.map +1 -0
  9. package/dist/cli/commands/create.js +74 -0
  10. package/dist/cli/commands/create.js.map +1 -0
  11. package/dist/cli/commands/delete.d.ts +7 -0
  12. package/dist/cli/commands/delete.d.ts.map +1 -0
  13. package/dist/cli/commands/delete.js +61 -0
  14. package/dist/cli/commands/delete.js.map +1 -0
  15. package/dist/cli/commands/list.d.ts +16 -0
  16. package/dist/cli/commands/list.d.ts.map +1 -0
  17. package/dist/cli/commands/list.js +239 -0
  18. package/dist/cli/commands/list.js.map +1 -0
  19. package/dist/cli/commands/mcp.d.ts +8 -0
  20. package/dist/cli/commands/mcp.d.ts.map +1 -0
  21. package/dist/cli/commands/mcp.js +52 -0
  22. package/dist/cli/commands/mcp.js.map +1 -0
  23. package/dist/cli/commands/serve.d.ts +8 -0
  24. package/dist/cli/commands/serve.d.ts.map +1 -0
  25. package/dist/cli/commands/serve.js +505 -0
  26. package/dist/cli/commands/serve.js.map +1 -0
  27. package/dist/cli/commands/show.d.ts +7 -0
  28. package/dist/cli/commands/show.d.ts.map +1 -0
  29. package/dist/cli/commands/show.js +84 -0
  30. package/dist/cli/commands/show.js.map +1 -0
  31. package/dist/cli/commands/sprint.d.ts +11 -0
  32. package/dist/cli/commands/sprint.d.ts.map +1 -0
  33. package/dist/cli/commands/sprint.js +114 -0
  34. package/dist/cli/commands/sprint.js.map +1 -0
  35. package/dist/cli/commands/sprints.d.ts +10 -0
  36. package/dist/cli/commands/sprints.d.ts.map +1 -0
  37. package/dist/cli/commands/sprints.js +64 -0
  38. package/dist/cli/commands/sprints.js.map +1 -0
  39. package/dist/cli/commands/status.d.ts +6 -0
  40. package/dist/cli/commands/status.d.ts.map +1 -0
  41. package/dist/cli/commands/status.js +48 -0
  42. package/dist/cli/commands/status.js.map +1 -0
  43. package/dist/cli/commands/user.d.ts +8 -0
  44. package/dist/cli/commands/user.d.ts.map +1 -0
  45. package/dist/cli/commands/user.js +61 -0
  46. package/dist/cli/commands/user.js.map +1 -0
  47. package/dist/cli/commands/users.d.ts +7 -0
  48. package/dist/cli/commands/users.d.ts.map +1 -0
  49. package/dist/cli/commands/users.js +28 -0
  50. package/dist/cli/commands/users.js.map +1 -0
  51. package/dist/cli/commands/version.d.ts +7 -0
  52. package/dist/cli/commands/version.d.ts.map +1 -0
  53. package/dist/cli/commands/version.js +94 -0
  54. package/dist/cli/commands/version.js.map +1 -0
  55. package/dist/cli/index.d.ts +3 -0
  56. package/dist/cli/index.d.ts.map +1 -0
  57. package/dist/cli/index.js +146 -0
  58. package/dist/cli/index.js.map +1 -0
  59. package/dist/core/notifier.d.ts +51 -0
  60. package/dist/core/notifier.d.ts.map +1 -0
  61. package/dist/core/notifier.js +118 -0
  62. package/dist/core/notifier.js.map +1 -0
  63. package/dist/core/storage.d.ts +41 -0
  64. package/dist/core/storage.d.ts.map +1 -0
  65. package/dist/core/storage.js +383 -0
  66. package/dist/core/storage.js.map +1 -0
  67. package/dist/core/test_getAllTickets.d.ts +2 -0
  68. package/dist/core/test_getAllTickets.d.ts.map +1 -0
  69. package/dist/core/test_getAllTickets.js +7 -0
  70. package/dist/core/test_getAllTickets.js.map +1 -0
  71. package/dist/core/types.d.ts +67 -0
  72. package/dist/core/types.d.ts.map +1 -0
  73. package/dist/core/types.js +2 -0
  74. package/dist/core/types.js.map +1 -0
  75. package/dist/index.d.ts +3 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +3 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/mcp/server.d.ts +25 -0
  80. package/dist/mcp/server.d.ts.map +1 -0
  81. package/dist/mcp/server.js +489 -0
  82. package/dist/mcp/server.js.map +1 -0
  83. package/dist/web/_app/immutable/assets/0.47dd68fd.css +1 -0
  84. package/dist/web/_app/immutable/assets/2.3f11c9a4.css +1 -0
  85. package/dist/web/_app/immutable/assets/_layout.47e0a118.css +1 -0
  86. package/dist/web/_app/immutable/assets/_page.3f11c9a4.css +1 -0
  87. package/dist/web/_app/immutable/chunks/index.23b89654.js +1 -0
  88. package/dist/web/_app/immutable/chunks/index.f094d695.js +1 -0
  89. package/dist/web/_app/immutable/chunks/scheduler.81694808.js +1 -0
  90. package/dist/web/_app/immutable/chunks/singletons.9c246a72.js +1 -0
  91. package/dist/web/_app/immutable/chunks/stores.48058fce.js +1 -0
  92. package/dist/web/_app/immutable/entry/app.fea83d45.js +1 -0
  93. package/dist/web/_app/immutable/entry/start.3fd90366.js +3 -0
  94. package/dist/web/_app/immutable/nodes/0.e605bf9a.js +1 -0
  95. package/dist/web/_app/immutable/nodes/1.e3ce54f6.js +1 -0
  96. package/dist/web/_app/immutable/nodes/2.04dfac64.js +13 -0
  97. package/dist/web/_app/version.json +1 -0
  98. package/dist/web/favicon.png +3 -0
  99. package/dist/web/favicon.svg +10 -0
  100. package/dist/web/index.html +37 -0
  101. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andrew Hein
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,477 @@
1
+ # tkxr - In-Repo Ticket Management System
2
+
3
+ tkxr is a lightweight, file-based ticket management system with a modern web UI for human users, and CLI/MCP server interfaces for AI and automation. It uses chunked NDJSON for tickets/comments and JSON for sprints/users, ensuring scalable, fast, and version-controlled workflows. Ideal for small teams wanting Jira-like functionality without external dependencies.
4
+
5
+ ## Features
6
+
7
+ - 📁 **File-based Storage** - Tickets and comments stored as NDJSON chunks, sprints/users as JSON
8
+ - 🌐 **Web Dashboard** - The primary interface for humans to view, manage, and interact with tickets, sprints, users, and comments
9
+ - 🚀 **CLI Interface** - Designed for automation, scripting, and AI agents to manage tickets
10
+ - 🤖 **AI Integration** - MCP server enables AI assistants to interact with tickets, sprints, users, and comments
11
+ - 🔄 **Real-time Updates** - WebSocket-powered live updates
12
+ - 🏃 **Sprint Management** - Complete sprint lifecycle management
13
+ - 👥 **User Management** - Assign tickets to team members
14
+ - 💬 **Comment Support** - Add, list, and manage comments for tickets
15
+ - ⚡ **Zero Dependencies** - No external databases required
16
+
17
+ ## Installation
18
+
19
+ ### Run tkxr instantly with npx or pnpm dlx
20
+
21
+ You do not need to install tkxr globally. Run any command directly using pnpm dlx or npx:
22
+
23
+ ```bash
24
+ # Using pnpm dlx
25
+ pnpm dlx tkxr serve # Start the web interface
26
+ pnpm dlx tkxr mcp # Start the MCP server
27
+ pnpm dlx tkxr list # List tickets
28
+ pnpm dlx tkxr create task "Title" # Create a task
29
+ pnpm dlx tkxr comments <ticket-id> # Manage comments
30
+
31
+ # Using npx
32
+ npx tkxr serve # Start the web interface
33
+ npx tkxr mcp # Start the MCP server
34
+ npx tkxr list # List tickets
35
+ npx tkxr create task "Title" # Create a task
36
+ npx tkxr comments <ticket-id> # Manage comments
37
+ ```
38
+
39
+ Global install is optional:
40
+
41
+ ```bash
42
+ pnpm install -g tkxr
43
+ ```
44
+
45
+ ## Quick Start
46
+ > **Human users:** Use the web UI for all ticket management, sprint planning, and user interactions. Open http://localhost:8080 after running `pnpm dlx tkxr serve`.
47
+ > **AI/automation:** Use the CLI or MCP server for programmatic access, scripting, and integration with AI tools.
48
+
49
+ ### 1. Create your first tickets and comments
50
+
51
+ ```bash
52
+ tkxr create task "Implement user login"
53
+ tkxr create bug "Fix navigation menu"
54
+ tkxr sprint create "Sprint 1 - Authentication"
55
+ tkxr user create johndoe "John Doe" --email john@example.com
56
+ # Add a comment to a ticket
57
+ tkxr comments tas-AbCdEfGh --add --author johndoe --content "This is a comment"
58
+ ```
59
+
60
+ ### 2. List and manage entities
61
+
62
+ ```bash
63
+ tkxr list
64
+ tkxr users
65
+ tkxr sprints
66
+ tkxr sprint status spr-abc123 active
67
+ tkxr comments tas-AbCdEfGh # List comments for a ticket
68
+ ```
69
+
70
+ ### 3. Update ticket status
71
+
72
+ ```bash
73
+ # Mark ticket as in progress
74
+ tkxr status tas-AbCdEfGh progress
75
+
76
+ # Mark ticket as done
77
+ tkxr status tas-AbCdEfGh done
78
+ ```
79
+
80
+ ### 4. Start interfaces
81
+
82
+ ```bash
83
+ # Web interface (human-friendly)
84
+ tkxr serve
85
+
86
+ # MCP server (AI integration)
87
+ tkxr mcp
88
+ ```
89
+
90
+ Open http://localhost:8080 in your browser to access the web dashboard.
91
+
92
+ ## CLI Commands
93
+
94
+ ### Ticket & Comment Commands
95
+
96
+ ```bash
97
+ # Create tickets with options
98
+ tkxr create task "Task title" \
99
+ --description "Detailed description" \
100
+ --assignee usr-12345678 \
101
+ --sprint spr-12345678 \
102
+ --priority high \
103
+ --estimate 5
104
+
105
+ tkxr create bug "Bug title" \
106
+ --description "Bug description" \
107
+ --priority critical
108
+
109
+ # List tickets
110
+ tkxr list # All tickets
111
+ tkxr list tasks # Only tasks
112
+ tkxr list bugs # Only bugs
113
+
114
+ # Update status
115
+ tkxr status <ticket-id> <status>
116
+ # Valid statuses: todo, progress, done
117
+
118
+ tkxr delete <ticket-id>
119
+
120
+ # Comment management
121
+ tkxr comments <ticket-id> # List comments
122
+ tkxr comments <ticket-id> --add --author <user-id> --content "Comment text" # Add comment
123
+ ```
124
+
125
+ ### User Management
126
+
127
+ ```bash
128
+ # List all users
129
+ tkxr users
130
+
131
+ # Create a new user
132
+ tkxr user create <username> <displayName> [--email <email>]
133
+
134
+ # Examples
135
+ tkxr user create johndoe "John Doe"
136
+ tkxr user create alice "Alice Smith" --email alice@example.com
137
+ ```
138
+
139
+ ### Sprint Management
140
+
141
+ ```bash
142
+ # List all sprints
143
+ tkxr sprints
144
+
145
+ # List sprints by status
146
+ tkxr sprints --status active
147
+
148
+ # Create a new sprint
149
+ tkxr sprint create <name> [options]
150
+
151
+ # Sprint creation options
152
+ tkxr sprint create "Sprint 2" \
153
+ --description "Feature development sprint" \
154
+ --goal "Complete user authentication"
155
+
156
+ # Update sprint status
157
+ tkxr sprint status <sprint-id> <status>
158
+ # Valid statuses: planning, active, completed
159
+
160
+ # Examples
161
+ tkxr sprint status spr-abc123 active
162
+ tkxr sprint status spr-def456 completed
163
+ ```
164
+
165
+ ### Server Commands
166
+
167
+ ```bash
168
+ # Web interface server
169
+ tkxr serve # Start on localhost:8080
170
+ tkxr serve --port 3000 # Custom port
171
+ tkxr serve --host 0.0.0.0 # Custom host
172
+
173
+ # MCP server for AI integration
174
+ tkxr mcp # Start MCP server
175
+ ```
176
+
177
+ ## AI Integration (MCP Server)
178
+
179
+ tkxr includes a Model Context Protocol (MCP) server that enables AI assistants to manage tickets through standardized tool calls.
180
+
181
+ ### Starting the MCP Server
182
+
183
+ ```bash
184
+ npx tkxr mcp # If not installed globally
185
+ pnpm dlx tkxr mcp # Or use pnpm dlx
186
+ tkxr mcp # Only if installed globally
187
+ ```
188
+
189
+ ### Available MCP Tools
190
+
191
+ The MCP server provides these tools for AI assistants:
192
+
193
+ - `list_tickets` - List all tickets with optional filtering
194
+ - `create_ticket` - Create new tasks or bugs
195
+ - `update_ticket_status` - Change ticket status
196
+ - `delete_ticket` - Remove tickets
197
+ - `list_users` / `create_user` - User management
198
+ - `list_sprints` / `create_sprint` / `update_sprint_status` - Sprint management
199
+ - `list_comments` / `add_comment` - Comment management
200
+
201
+ ### AI Usage Examples
202
+
203
+ With the MCP server running, AI assistants can:
204
+
205
+ ```
206
+ "Show me all open tasks in the current sprint"
207
+ "Create a new bug for the login issue and assign it to John"
208
+ "Move all completed tickets from Sprint 1 to done status"
209
+ "Start Sprint 2 and create initial planning tasks"
210
+ ```
211
+
212
+ ### MCP Configuration
213
+
214
+ Configure your AI assistant to connect to the MCP server:
215
+
216
+ ```json
217
+ {
218
+ "mcpServers": {
219
+ "tkxr": {
220
+ "command": "tkxr-mcp",
221
+ "args": []
222
+ }
223
+ }
224
+ }
225
+ ```
226
+
227
+ ## Web Interface Features
228
+
229
+ ### Dashboard
230
+ - 📊 Overview statistics (sprint-aware)
231
+ - 🎯 **Sprint dropdown filter** - Filter by specific sprint or "No Sprint"
232
+ - 📋 Ticket cards with status indicators
233
+ - 💬 Comment modal for ticket conversations
234
+ - 🔄 Real-time updates via WebSocket
235
+ - 📈 Dynamic stats that update based on sprint selection
236
+
237
+ ### Sprint Filtering
238
+ - **All Tickets** - Show everything
239
+ - **No Sprint** - Show unassigned tickets
240
+ - **Active Sprints** - Filter by specific sprint (completed sprints hidden)
241
+ - Stats and tab counts update automatically based on selected sprint
242
+
243
+ ### Ticket Management
244
+ - ✅ Quick status updates
245
+ - 📝 Create new tickets with rich forms
246
+ - 🏷️ Priority and label management
247
+ - 👤 User assignment
248
+ - 🏃 Sprint assignment (only active/planning sprints shown)
249
+
250
+ ### Sprint Management
251
+ - 🏃 **Complete sprint lifecycle**: planning → active → completed
252
+ - 🎯 Sprint status buttons (Start, Complete, Reopen)
253
+ - 📋 Sprint creation with description and goals
254
+ - 🚫 Smart filtering (completed sprints hidden from ticket creation)
255
+
256
+ ### Visual Indicators
257
+ - 🟦 Tasks (blue)
258
+ - 🔴 Bugs (red)
259
+ - 🟡 In Progress (yellow)
260
+ - 🟢 Done (green)
261
+ - ⚪ Todo (gray)
262
+
263
+ ## File Structure
264
+
265
+ tkxr organizes tickets, comments, sprints, and users in your repository:
266
+
267
+ ```
268
+ tkxr/
269
+ ├── tickets/
270
+ │ ├── tickets-0001.ndjson
271
+ │ └── tickets-0002.ndjson
272
+ ├── comments/
273
+ │ ├── comments-0001.ndjson
274
+ │ └── comments-0002.ndjson
275
+ ├── sprints.json
276
+ ├── users.json
277
+ ```
278
+
279
+ ### Example Files
280
+
281
+ #### Ticket (NDJSON)
282
+ Each line is a JSON object:
283
+ {"id":"tas-12AbCdEfGh","type":"task","title":"Implement user authentication","description":"Add user authentication system...","status":"progress","assignee":"usr-98XyZaBc","sprint":"spr-45FgHiJk","estimate":8,"priority":"high","createdAt":"2026-02-19T10:30:00.000Z","updatedAt":"2026-02-19T14:15:00.000Z"}
284
+
285
+ #### Sprint (JSON)
286
+ {
287
+ "id": "spr-45FgHiJk",
288
+ "name": "Sprint 1 - Authentication",
289
+ "description": "Implement core authentication features",
290
+ "status": "active",
291
+ "goal": "Complete user login and registration",
292
+ "createdAt": "2026-02-19T09:00:00.000Z",
293
+ "updatedAt": "2026-02-19T11:00:00.000Z"
294
+ }
295
+
296
+ #### User (JSON)
297
+ {
298
+ "id": "usr-98XyZaBc",
299
+ "username": "johndoe",
300
+ "displayName": "John Doe",
301
+ "email": "john@example.com",
302
+ "createdAt": "2026-02-19T08:00:00.000Z",
303
+ "updatedAt": "2026-02-19T08:00:00.000Z"
304
+ }
305
+ #### Comment (NDJSON)
306
+ Each line is a JSON object:
307
+ {"id":"com-1a2b3c4d","ticketId":"tas-12AbCdEfGh","author":"usr-98XyZaBc","content":"This is a comment","createdAt":"2026-02-19T12:00:00.000Z"}
308
+
309
+ ## Advanced Usage
310
+ # Comment workflows
311
+ tkxr comments tas-12AbCdEf --add --author johndoe --content "Ready for review"
312
+ tkxr comments tas-12AbCdEf # List all comments for ticket
313
+
314
+ ### Sprint Workflow
315
+
316
+ ```bash
317
+ # Complete sprint lifecycle
318
+ tkxr sprint create "Sprint 1" --goal "Complete MVP"
319
+ tkxr sprint status spr-abc123 active
320
+ tkxr create task "Add login" --sprint spr-abc123
321
+ tkxr create task "Add dashboard" --sprint spr-abc123
322
+ # ... work on tickets ...
323
+ tkxr sprint status spr-abc123 completed
324
+
325
+ # Planning next sprint
326
+ tkxr sprint create "Sprint 2" --goal "User management"
327
+ # Only active/planning sprints appear in ticket creation
328
+ ```
329
+
330
+ ### Integration with Git
331
+
332
+ Since tickets are files, they integrate naturally with Git:
333
+
334
+ ```bash
335
+ # Track ticket changes
336
+ git add tickets/
337
+ git commit -m "Add feature tickets for sprint 1"
338
+
339
+ # Branch-specific tickets
340
+ git checkout feature/auth
341
+ tkxr create task "Add OAuth integration"
342
+
343
+ # Review ticket history
344
+ git log --follow tickets/tasks/tas-12345678.yaml
345
+ ```
346
+
347
+ ### AI-Powered Workflows
348
+
349
+ ```bash
350
+ # Start MCP server for AI integration
351
+ tkxr mcp
352
+
353
+ # AI can now:
354
+ # - Analyze ticket backlogs
355
+ # - Create tickets from requirements
356
+ # - Update sprint progress
357
+ # - Generate reports
358
+ # - Manage assignments
359
+ ```
360
+
361
+ ## API Reference
362
+ # Comments
363
+ GET /api/comments/:ticketId # List comments for ticket
364
+ POST /api/comments/:ticketId # Add comment to ticket
365
+
366
+ ### REST API
367
+
368
+ When running `tkxr serve`, the following API endpoints are available:
369
+
370
+ ```
371
+ # Tickets
372
+ GET /api/tickets # All tickets
373
+ GET /api/tickets/:type # Tickets by type (task/bug)
374
+ POST /api/tickets # Create ticket
375
+ PUT /api/tickets/:id/status # Update ticket status
376
+ DELETE /api/tickets/:id # Delete ticket
377
+
378
+ # Users
379
+ GET /api/users # All users
380
+ POST /api/users # Create user
381
+ DELETE /api/users/:id # Delete user
382
+
383
+ # Sprints
384
+ GET /api/sprints # All sprints
385
+ POST /api/sprints # Create sprint
386
+ PUT /api/sprints/:id/status # Update sprint status
387
+ DELETE /api/sprints/:id # Delete sprint
388
+ ```
389
+
390
+ ### WebSocket Events
391
+
392
+ ```javascript
393
+ // Connect to WebSocket
394
+ const ws = new WebSocket('ws://localhost:8080/ws');
395
+
396
+ // Listen for updates
397
+ ws.onmessage = (event) => {
398
+ const message = JSON.parse(event.data);
399
+ console.log('Update:', message.type, message.data);
400
+ };
401
+ ```
402
+
403
+ ## Configuration
404
+ # Server Configuration
405
+
406
+ The `.env.tkxr` file is dynamically created by the web UI server. It stores the host, port, and URL for the web interface (default: http://localhost:8080) in standard dotenv format:
407
+
408
+ ```
409
+ TKXR_HOST=localhost
410
+ TKXR_PORT=8080
411
+ ```
412
+
413
+ You can override the web UI port by editing `.env.tkxr`, using CLI flags:
414
+
415
+ ```bash
416
+ pnpm dlx tkxr serve --port 3000
417
+ ```
418
+ ### Development
419
+
420
+ ```bash
421
+ # Clone and develop
422
+ git clone <repo>
423
+ cd tkxr
424
+ npm install
425
+
426
+ # Build CLI and web interface
427
+ npm run build
428
+
429
+ # Develop web interface
430
+ cd src/web
431
+ npm install
432
+ npm run dev
433
+
434
+ # Test MCP server
435
+ npm run build
436
+ tkxr mcp
437
+ ```
438
+
439
+ ## Contributing
440
+
441
+ 1. Fork the repository
442
+ 2. Create your feature branch: `git checkout -b feature/amazing-feature`
443
+ 3. Commit your changes: `git commit -m 'Add amazing feature'`
444
+ 4. Push to the branch: `git push origin feature/amazing-feature`
445
+ 5. Open a Pull Request
446
+
447
+ ## License
448
+
449
+ MIT License - see LICENSE file for details.
450
+
451
+ ## Changelog
452
+
453
+ See [CHANGELOG.md](CHANGELOG.md) for a detailed history of all notable changes.
454
+
455
+ ### Recent Highlights
456
+ - Automated patch version bump and sync for root and web package.json on each build
457
+ - Version badge in web UI now reflects actual package version
458
+ - CLI command added for manual version bump and sync
459
+ - Changelog is updated automatically with each build
460
+ - Complete Sprint button bug fixed
461
+
462
+ ## Version Management
463
+
464
+ ### Automatic Patch Bump
465
+ Every build automatically bumps the patch version and syncs both root and web package.json files. This is handled by the `scripts/bump-version.js` script, which also updates the changelog.
466
+
467
+ ### Manual Version Control
468
+ You can manually bump the patch, minor, or major version using the CLI:
469
+
470
+ ```bash
471
+ node dist/cli/index.js version --bump patch # Patch bump
472
+ node dist/cli/index.js version --bump minor # Minor bump
473
+ node dist/cli/index.js version --bump major # Major bump
474
+ node dist/cli/index.js version # Show current version
475
+ ```
476
+
477
+ Both methods keep the root and web package.json files in sync.
@@ -0,0 +1,10 @@
1
+ import type minimist from 'minimist';
2
+ interface CommentsArgs extends minimist.ParsedArgs {
3
+ _: string[];
4
+ add?: boolean;
5
+ author?: string;
6
+ content?: string;
7
+ }
8
+ export declare function manageComments(args: CommentsArgs): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/comments.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAKrC,UAAU,YAAa,SAAQ,QAAQ,CAAC,UAAU;IAChD,CAAC,EAAE,MAAM,EAAE,CAAC;IACZ,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BtE"}
@@ -0,0 +1,81 @@
1
+ import chalk from 'chalk';
2
+ import { createStorage } from '../../core/storage.js';
3
+ import { notifier } from '../../core/notifier.js';
4
+ export async function manageComments(args) {
5
+ const [, ticketId] = args._;
6
+ if (!ticketId) {
7
+ console.log(chalk.red('Error: Please provide a ticket ID'));
8
+ console.log(chalk.dim('Usage: tkxr comments <ticket-id> [--add] [--author <author-id>] [--content <content>]'));
9
+ return;
10
+ }
11
+ const storage = await createStorage();
12
+ try {
13
+ // Verify ticket exists
14
+ const result = await storage.findTicket(ticketId);
15
+ if (!result) {
16
+ console.log(chalk.red(`Ticket '${ticketId}' not found`));
17
+ return;
18
+ }
19
+ if (args.add) {
20
+ await addComment(storage, ticketId, args);
21
+ }
22
+ else {
23
+ await listComments(storage, ticketId);
24
+ }
25
+ }
26
+ catch (error) {
27
+ console.log(chalk.red(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
28
+ }
29
+ }
30
+ async function listComments(storage, ticketId) {
31
+ const comments = await storage.getComments(ticketId);
32
+ const users = await storage.getUsers();
33
+ if (comments.length === 0) {
34
+ console.log(chalk.yellow(`No comments found for ticket '${ticketId}'`));
35
+ return;
36
+ }
37
+ console.log(chalk.bold(`\n💬 Comments for ticket ${ticketId} (${comments.length})\n`));
38
+ // Sort comments by creation date
39
+ const sortedComments = comments.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
40
+ for (const comment of sortedComments) {
41
+ const user = users.find((u) => u.id === comment.author);
42
+ const authorName = user?.displayName || user?.username || comment.author;
43
+ const createdAt = new Date(comment.createdAt).toLocaleString();
44
+ console.log(chalk.blue(`📝 ${comment.id}`));
45
+ console.log(chalk.dim(` Author: ${authorName}`));
46
+ console.log(chalk.dim(` Created: ${createdAt}`));
47
+ console.log(` ${comment.content}`);
48
+ console.log();
49
+ }
50
+ }
51
+ async function addComment(storage, ticketId, args) {
52
+ const { author, content } = args;
53
+ if (!author) {
54
+ console.log(chalk.red('Error: --author is required when adding a comment'));
55
+ console.log(chalk.dim('Usage: tkxr comments <ticket-id> --add --author <author-id> --content <content>'));
56
+ return;
57
+ }
58
+ if (!content) {
59
+ console.log(chalk.red('Error: --content is required when adding a comment'));
60
+ console.log(chalk.dim('Usage: tkxr comments <ticket-id> --add --author <author-id> --content <content>'));
61
+ return;
62
+ }
63
+ // Verify author exists
64
+ const users = await storage.getUsers();
65
+ const user = users.find((u) => u.id === author || u.username === author);
66
+ if (!user) {
67
+ console.log(chalk.red(`Error: User '${author}' not found`));
68
+ console.log(chalk.dim('Use: tkxr users - to see available users'));
69
+ return;
70
+ }
71
+ const comment = await storage.createComment(ticketId, user.id, content);
72
+ // Ensure the comment is fully saved before sending notification
73
+ // The createComment method should already call saveProject(), but let's be explicit
74
+ console.log(chalk.green('✓ Comment added successfully'));
75
+ console.log(chalk.dim(` ID: ${comment.id}`));
76
+ console.log(chalk.dim(` Author: ${user.displayName || user.username}`));
77
+ console.log(chalk.dim(` Content: ${content}`));
78
+ // Send notification after everything is saved
79
+ await notifier.notifyCommentCreated(comment);
80
+ }
81
+ //# sourceMappingURL=comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.js","sourceRoot":"","sources":["../../../src/cli/commands/comments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAUlD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAkB;IACrD,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAE5B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uFAAuF,CAAC,CAAC,CAAC;QAChH,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,EAAE,CAAC;IAEtC,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAElD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,QAAQ,aAAa,CAAC,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,MAAM,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,MAAM,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,OAAY,EAAE,QAAgB;IACxD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;IAEvC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,iCAAiC,QAAQ,GAAG,CAAC,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,QAAQ,KAAK,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAEvF,iCAAiC;IACjC,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,CAAM,EAAE,EAAE,CACtD,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAClE,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,IAAI,EAAE,WAAW,IAAI,IAAI,EAAE,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;QACzE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,CAAC;QAE/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,UAAU,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,SAAS,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAY,EAAE,QAAgB,EAAE,IAAkB;IAC1E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAEjC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC,CAAC;QAC1G,OAAO;IACT,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC,CAAC;QAC1G,OAAO;IACT,CAAC;IAED,uBAAuB;IACvB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;IAE9E,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,MAAM,aAAa,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAExE,gEAAgE;IAChE,oFAAoF;IACpF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC,CAAC;IAEhD,8CAA8C;IAC9C,MAAM,QAAQ,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type minimist from 'minimist';
2
+ interface CreateArgs extends minimist.ParsedArgs {
3
+ assignee?: string;
4
+ sprint?: string;
5
+ priority?: string;
6
+ estimate?: string;
7
+ description?: string;
8
+ }
9
+ export declare function createTicket(args: CreateArgs): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAKrC,UAAU,UAAW,SAAQ,QAAQ,CAAC,UAAU;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ElE"}
@@ -0,0 +1,74 @@
1
+ import chalk from 'chalk';
2
+ import { createStorage } from '../../core/storage.js';
3
+ import { notifier } from '../../core/notifier.js';
4
+ export async function createTicket(args) {
5
+ const [, entityType, title] = args._;
6
+ if (!entityType) {
7
+ console.log(chalk.red('Error: Entity type is required'));
8
+ console.log('Usage: tkxr create <type> <title> [options]');
9
+ console.log('Types: task, bug, sprint, user');
10
+ return;
11
+ }
12
+ if (!title) {
13
+ console.log(chalk.red('Error: Title is required'));
14
+ return;
15
+ }
16
+ const storage = await createStorage();
17
+ try {
18
+ switch (entityType) {
19
+ case 'task':
20
+ case 'bug': {
21
+ const ticket = await storage.createTicket(entityType, title, {
22
+ description: args.description,
23
+ assignee: args.assignee,
24
+ sprint: args.sprint,
25
+ priority: args.priority,
26
+ estimate: args.estimate ? parseInt(args.estimate) : undefined,
27
+ });
28
+ // Notify web UI
29
+ await notifier.notifyTicketCreated(ticket);
30
+ console.log(chalk.green(`✓ Created ${entityType}: ${ticket.id}`));
31
+ console.log(` Title: ${ticket.title}`);
32
+ console.log(` Status: ${ticket.status}`);
33
+ if (ticket.assignee)
34
+ console.log(` Assignee: ${ticket.assignee}`);
35
+ if (ticket.sprint)
36
+ console.log(` Sprint: ${ticket.sprint}`);
37
+ if (ticket.priority)
38
+ console.log(` Priority: ${ticket.priority}`);
39
+ break;
40
+ }
41
+ case 'sprint': {
42
+ const sprint = await storage.createSprint(title, {
43
+ description: args.description,
44
+ });
45
+ // Notify web UI
46
+ await notifier.notifySprintCreated(sprint);
47
+ console.log(chalk.green(`✓ Created sprint: ${sprint.id}`));
48
+ console.log(` Name: ${sprint.name}`);
49
+ console.log(` Status: ${sprint.status}`);
50
+ if (sprint.description)
51
+ console.log(` Description: ${sprint.description}`);
52
+ break;
53
+ }
54
+ case 'user': {
55
+ // For users, 'title' is the username
56
+ const displayName = args.description || title;
57
+ const user = await storage.createUser(title, displayName);
58
+ // Notify web UI
59
+ await notifier.notifyUserCreated(user);
60
+ console.log(chalk.green(`✓ Created user: ${user.id}`));
61
+ console.log(` Username: ${user.username}`);
62
+ console.log(` Display Name: ${user.displayName}`);
63
+ break;
64
+ }
65
+ default:
66
+ console.log(chalk.red(`Error: Unknown entity type "${entityType}"`));
67
+ console.log('Valid types: task, bug, sprint, user');
68
+ }
69
+ }
70
+ catch (error) {
71
+ console.log(chalk.red(`Error creating ${entityType}: ${error instanceof Error ? error.message : 'Unknown error'}`));
72
+ }
73
+ }
74
+ //# sourceMappingURL=create.js.map