@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.
- package/LICENSE +21 -0
- package/README.md +477 -0
- package/dist/cli/commands/comments.d.ts +10 -0
- package/dist/cli/commands/comments.d.ts.map +1 -0
- package/dist/cli/commands/comments.js +81 -0
- package/dist/cli/commands/comments.js.map +1 -0
- package/dist/cli/commands/create.d.ts +11 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +74 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +7 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +61 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/list.d.ts +16 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +239 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +8 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +52 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +8 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +505 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/show.d.ts +7 -0
- package/dist/cli/commands/show.d.ts.map +1 -0
- package/dist/cli/commands/show.js +84 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/sprint.d.ts +11 -0
- package/dist/cli/commands/sprint.d.ts.map +1 -0
- package/dist/cli/commands/sprint.js +114 -0
- package/dist/cli/commands/sprint.js.map +1 -0
- package/dist/cli/commands/sprints.d.ts +10 -0
- package/dist/cli/commands/sprints.d.ts.map +1 -0
- package/dist/cli/commands/sprints.js +64 -0
- package/dist/cli/commands/sprints.js.map +1 -0
- package/dist/cli/commands/status.d.ts +6 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +48 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/user.d.ts +8 -0
- package/dist/cli/commands/user.d.ts.map +1 -0
- package/dist/cli/commands/user.js +61 -0
- package/dist/cli/commands/user.js.map +1 -0
- package/dist/cli/commands/users.d.ts +7 -0
- package/dist/cli/commands/users.d.ts.map +1 -0
- package/dist/cli/commands/users.js +28 -0
- package/dist/cli/commands/users.js.map +1 -0
- package/dist/cli/commands/version.d.ts +7 -0
- package/dist/cli/commands/version.d.ts.map +1 -0
- package/dist/cli/commands/version.js +94 -0
- package/dist/cli/commands/version.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +146 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/notifier.d.ts +51 -0
- package/dist/core/notifier.d.ts.map +1 -0
- package/dist/core/notifier.js +118 -0
- package/dist/core/notifier.js.map +1 -0
- package/dist/core/storage.d.ts +41 -0
- package/dist/core/storage.d.ts.map +1 -0
- package/dist/core/storage.js +383 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/test_getAllTickets.d.ts +2 -0
- package/dist/core/test_getAllTickets.d.ts.map +1 -0
- package/dist/core/test_getAllTickets.js +7 -0
- package/dist/core/test_getAllTickets.js.map +1 -0
- package/dist/core/types.d.ts +67 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +25 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +489 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/web/_app/immutable/assets/0.47dd68fd.css +1 -0
- package/dist/web/_app/immutable/assets/2.3f11c9a4.css +1 -0
- package/dist/web/_app/immutable/assets/_layout.47e0a118.css +1 -0
- package/dist/web/_app/immutable/assets/_page.3f11c9a4.css +1 -0
- package/dist/web/_app/immutable/chunks/index.23b89654.js +1 -0
- package/dist/web/_app/immutable/chunks/index.f094d695.js +1 -0
- package/dist/web/_app/immutable/chunks/scheduler.81694808.js +1 -0
- package/dist/web/_app/immutable/chunks/singletons.9c246a72.js +1 -0
- package/dist/web/_app/immutable/chunks/stores.48058fce.js +1 -0
- package/dist/web/_app/immutable/entry/app.fea83d45.js +1 -0
- package/dist/web/_app/immutable/entry/start.3fd90366.js +3 -0
- package/dist/web/_app/immutable/nodes/0.e605bf9a.js +1 -0
- package/dist/web/_app/immutable/nodes/1.e3ce54f6.js +1 -0
- package/dist/web/_app/immutable/nodes/2.04dfac64.js +13 -0
- package/dist/web/_app/version.json +1 -0
- package/dist/web/favicon.png +3 -0
- package/dist/web/favicon.svg +10 -0
- package/dist/web/index.html +37 -0
- 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":"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"}
|
|
@@ -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
|