hotsheet 0.4.0 → 0.5.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/README.md +45 -19
- package/dist/channel.js +97 -0
- package/dist/cli.js +482 -190
- package/dist/client/app.global.js +38 -38
- package/dist/client/styles.css +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -74,10 +74,10 @@ The loop stays tight because the AI always knows what to work on next.
|
|
|
74
74
|
<img src="docs/demo-2.png" alt="Quick ticket entry with the bullet-list input row" width="900">
|
|
75
75
|
</p>
|
|
76
76
|
|
|
77
|
-
**
|
|
77
|
+
**Customizable categories** — defaults to a software development set (Issue, Bug, Feature, Req Change, Task, Investigation), with built-in presets for Design, Product Management, Marketing, and Personal workflows. Each category has a color, badge label, and keyboard shortcut — all configurable in Settings.
|
|
78
78
|
|
|
79
79
|
<p align="center">
|
|
80
|
-
<img src="docs/demo-3.png" alt="Sidebar
|
|
80
|
+
<img src="docs/demo-3.png" alt="Sidebar with custom views and category filtering" width="900">
|
|
81
81
|
</p>
|
|
82
82
|
|
|
83
83
|
**Column view** — switch to a kanban-style board grouped by status. Drag tickets between columns to change status, or drag onto sidebar items to set category, priority, or view.
|
|
@@ -86,26 +86,38 @@ The loop stays tight because the AI always knows what to work on next.
|
|
|
86
86
|
<img src="docs/demo-7.png" alt="Column view showing tickets organized by status in a kanban board" width="900">
|
|
87
87
|
</p>
|
|
88
88
|
|
|
89
|
-
**Batch operations** — select multiple tickets to bulk-update category, priority, status, or Up Next.
|
|
89
|
+
**Batch operations** — select multiple tickets to bulk-update category, priority, status, or Up Next. The overflow menu (⋯) provides duplicate, tags, move to backlog, and archive actions. Right-click any ticket for a full context menu with submenus.
|
|
90
90
|
|
|
91
91
|
<p align="center">
|
|
92
|
-
<img src="docs/demo-5.png" alt="Multiple tickets selected with the batch toolbar
|
|
92
|
+
<img src="docs/demo-5.png" alt="Multiple tickets selected with the batch toolbar and context menu" width="900">
|
|
93
93
|
</p>
|
|
94
94
|
|
|
95
|
-
**Detail panel** — side or bottom orientation (toggle in the toolbar), resizable,
|
|
95
|
+
**Detail panel** — side or bottom orientation (toggle in the toolbar), resizable. Shows category, priority, status, and Up Next in a compact grid, plus title, details, tags, attachments, and editable notes. Click a note to edit inline; right-click to delete.
|
|
96
96
|
|
|
97
97
|
<p align="center">
|
|
98
|
-
<img src="docs/demo-6.png" alt="Detail panel in bottom orientation showing ticket details and notes" width="900">
|
|
98
|
+
<img src="docs/demo-6.png" alt="Detail panel in bottom orientation showing ticket details, tags, and notes" width="900">
|
|
99
|
+
</p>
|
|
100
|
+
|
|
101
|
+
**Stats dashboard** — click the sidebar widget to open a full analytics page with throughput charts, created-vs-completed trends, cumulative flow diagram, category breakdown, and cycle time scatter plot. Hover any chart for detailed tooltips.
|
|
102
|
+
|
|
103
|
+
<p align="center">
|
|
104
|
+
<img src="docs/demo-8.png" alt="Stats dashboard showing throughput, flow, and cycle time charts" width="900">
|
|
99
105
|
</p>
|
|
100
106
|
|
|
101
107
|
**Also includes:**
|
|
108
|
+
- **Tags** — free-form tags on tickets, with autocomplete and a batch tag dialog for multi-select
|
|
109
|
+
- **Custom views** — create filtered views with an interactive query builder (field + operator + value conditions, AND/OR logic)
|
|
102
110
|
- **Five priority levels** — Highest to Lowest, sortable and filterable
|
|
103
111
|
- **Up Next flag** — star tickets to add them to the AI worklist
|
|
104
|
-
- **Drag and drop** — drag tickets onto sidebar views to change category, priority, or status
|
|
105
|
-
- **
|
|
106
|
-
- **
|
|
107
|
-
- **
|
|
108
|
-
- **
|
|
112
|
+
- **Drag and drop** — drag tickets onto sidebar views to change category, priority, or status; reorder custom views
|
|
113
|
+
- **Right-click context menus** — full context menu on tickets with category/priority/status submenus, tags, duplicate, delete
|
|
114
|
+
- **Search** — full-text search across ticket titles, details, and ticket numbers
|
|
115
|
+
- **Print** — print the dashboard, all tickets, selected tickets, or individual tickets in checklist, summary, or full-detail format
|
|
116
|
+
- **Keyboard-driven** — `Enter` to create, `Cmd+I/B/F/R/K/G` for categories, `Alt+1-5` for priority, `Cmd+D` for Up Next, `Delete` to trash, `Cmd+P` to print, `Cmd+Z/Shift+Z` for undo/redo
|
|
117
|
+
- **Undo/redo** — `Cmd+Z` and `Cmd+Shift+Z` for all operations including notes, batch changes, and deletions
|
|
118
|
+
- **Animated transitions** — smooth FLIP animations when tickets reorder after property changes
|
|
119
|
+
- **Copy for commits** — `Cmd+C` copies selected ticket info (number + title + details + notes) for use in commit messages
|
|
120
|
+
- **File attachments** — attach files to any ticket, reveal in file manager
|
|
109
121
|
- **Markdown sync** — `worklist.md` and `open-tickets.md` auto-generated on every change
|
|
110
122
|
- **Automatic backups** — tiered snapshots (every 5 min, hourly, daily) with preview-before-restore recovery
|
|
111
123
|
- **Auto-cleanup** — configurable auto-deletion of old trash and verified items
|
|
@@ -137,6 +149,18 @@ Or add it to your `CLAUDE.md`:
|
|
|
137
149
|
Read .hotsheet/worklist.md for current work items.
|
|
138
150
|
```
|
|
139
151
|
|
|
152
|
+
Hot Sheet automatically generates skill files for Claude Code (as well as Cursor, GitHub Copilot, and Windsurf) so your AI tool can create tickets directly. Run `/hotsheet` in Claude Code to process the worklist.
|
|
153
|
+
|
|
154
|
+
### Claude Channel Integration (Experimental)
|
|
155
|
+
|
|
156
|
+
Hot Sheet can push events directly to a running Claude Code session via MCP channels. Enable it in Settings → General → Experimental:
|
|
157
|
+
|
|
158
|
+
- **Play button** — appears in the sidebar. Single-click sends the worklist to Claude on demand.
|
|
159
|
+
- **Auto mode** — double-click the play button to enable automatic mode. When you star a ticket for Up Next, Claude is notified after a 5-second debounce and picks up the work automatically.
|
|
160
|
+
- **Status indicator** — shows "Claude working" / "Claude idle" in the footer.
|
|
161
|
+
|
|
162
|
+
Requires Claude Code v2.1.80+ with channel support. See [docs/12-claude-channel.md](docs/12-claude-channel.md) for setup details.
|
|
163
|
+
|
|
140
164
|
### Other AI Tools
|
|
141
165
|
|
|
142
166
|
The worklist works with any AI tool that reads files — Cursor, Copilot, Aider, etc. Each ticket includes its number, type, priority, status, title, and details.
|
|
@@ -290,17 +314,18 @@ Both settings can also be changed from the settings panel UI.
|
|
|
290
314
|
| Shortcut | Action |
|
|
291
315
|
|----------|--------|
|
|
292
316
|
| `Enter` | Create new ticket |
|
|
293
|
-
| `Cmd+I` | Set category
|
|
294
|
-
| `Cmd+B` | Set category: Bug |
|
|
295
|
-
| `Cmd+F` | Set category: Feature |
|
|
296
|
-
| `Cmd+R` | Set category: Req Change |
|
|
297
|
-
| `Cmd+K` | Set category: Task |
|
|
298
|
-
| `Cmd+G` | Set category: Investigation |
|
|
317
|
+
| `Cmd+I/B/F/R/K/G` | Set category (customizable) |
|
|
299
318
|
| `Alt+1-5` | Set priority (Highest to Lowest) |
|
|
300
319
|
| `Cmd+D` | Toggle Up Next |
|
|
301
|
-
| `
|
|
320
|
+
| `Delete` / `Backspace` | Delete selected tickets |
|
|
321
|
+
| `Cmd+C` | Copy ticket info |
|
|
302
322
|
| `Cmd+A` | Select all |
|
|
303
|
-
| `
|
|
323
|
+
| `Cmd+Z` | Undo |
|
|
324
|
+
| `Cmd+Shift+Z` | Redo |
|
|
325
|
+
| `Cmd+P` | Print |
|
|
326
|
+
| `Cmd+F` | Focus search |
|
|
327
|
+
| `Cmd+N` / `N` | Focus new ticket input |
|
|
328
|
+
| `Escape` | Blur field / clear selection / close |
|
|
304
329
|
|
|
305
330
|
---
|
|
306
331
|
|
|
@@ -313,6 +338,7 @@ Both settings can also be changed from the settings panel UI.
|
|
|
313
338
|
| Server | Hono |
|
|
314
339
|
| Database | PGLite (embedded PostgreSQL) |
|
|
315
340
|
| UI | Custom server-side JSX (no React), vanilla client JS |
|
|
341
|
+
| Charts | Inline SVG (no external chart library) |
|
|
316
342
|
| Build | tsup (single-file bundle) |
|
|
317
343
|
| Storage | `.hotsheet/` in your project directory |
|
|
318
344
|
|
package/dist/channel.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
|
|
4
|
+
// src/channel.ts
|
|
5
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { createServer } from "http";
|
|
8
|
+
import { writeFileSync, unlinkSync } from "fs";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
var dataDir = ".hotsheet";
|
|
11
|
+
var args = process.argv.slice(2);
|
|
12
|
+
for (let i = 0; i < args.length; i++) {
|
|
13
|
+
if (args[i] === "--data-dir" && args[i + 1]) {
|
|
14
|
+
dataDir = args[i + 1];
|
|
15
|
+
i++;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
var portFile = join(dataDir, "channel-port");
|
|
19
|
+
var mcp = new Server(
|
|
20
|
+
{ name: "hotsheet-channel", version: "0.1.0" },
|
|
21
|
+
{
|
|
22
|
+
capabilities: {
|
|
23
|
+
experimental: { "claude/channel": {} }
|
|
24
|
+
},
|
|
25
|
+
instructions: [
|
|
26
|
+
'Events from the hotsheet-channel arrive as <channel source="hotsheet-channel">.',
|
|
27
|
+
"When you receive a channel event from hotsheet-channel, follow the instructions in the event content.",
|
|
28
|
+
"Typically this means running /hotsheet to process the current Up Next work items.",
|
|
29
|
+
"Do not ask for confirmation \u2014 just execute the requested action.",
|
|
30
|
+
"IMPORTANT: When you finish processing (or if there was nothing to process), you MUST run the curl command provided in the event to signal completion."
|
|
31
|
+
].join(" ")
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
await mcp.connect(new StdioServerTransport());
|
|
35
|
+
var httpServer = createServer(async (req, res) => {
|
|
36
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
37
|
+
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
|
|
38
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
39
|
+
if (req.method === "OPTIONS") {
|
|
40
|
+
res.writeHead(200);
|
|
41
|
+
res.end();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (req.method === "GET" && req.url === "/health") {
|
|
45
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
46
|
+
res.end(JSON.stringify({ ok: true }));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (req.method === "POST" && req.url === "/trigger") {
|
|
50
|
+
let body = "";
|
|
51
|
+
for await (const chunk of req) body += chunk;
|
|
52
|
+
try {
|
|
53
|
+
await mcp.notification({
|
|
54
|
+
method: "notifications/claude/channel",
|
|
55
|
+
params: {
|
|
56
|
+
content: body || "Process the Hot Sheet worklist. Run /hotsheet to work through the current Up Next items.",
|
|
57
|
+
meta: { type: "worklist" }
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
61
|
+
res.end(JSON.stringify({ ok: true }));
|
|
62
|
+
} catch (err) {
|
|
63
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
64
|
+
res.end(JSON.stringify({ error: String(err) }));
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
res.writeHead(404);
|
|
69
|
+
res.end("not found");
|
|
70
|
+
});
|
|
71
|
+
httpServer.listen(0, "127.0.0.1", () => {
|
|
72
|
+
const addr = httpServer.address();
|
|
73
|
+
if (addr && typeof addr !== "string") {
|
|
74
|
+
const port = addr.port;
|
|
75
|
+
try {
|
|
76
|
+
writeFileSync(portFile, String(port), "utf-8");
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
process.stderr.write(`hotsheet-channel listening on port ${port}
|
|
80
|
+
`);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
function cleanup() {
|
|
84
|
+
try {
|
|
85
|
+
unlinkSync(portFile);
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
process.on("SIGTERM", cleanup);
|
|
91
|
+
process.on("SIGINT", cleanup);
|
|
92
|
+
process.on("exit", () => {
|
|
93
|
+
try {
|
|
94
|
+
unlinkSync(portFile);
|
|
95
|
+
} catch {
|
|
96
|
+
}
|
|
97
|
+
});
|