claude-code-hub 0.37.0 → 0.39.0-rc.1

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 CHANGED
@@ -4,85 +4,155 @@
4
4
  [![license](https://img.shields.io/npm/l/claude-code-hub)](LICENSE)
5
5
  [![npm downloads](https://img.shields.io/npm/dm/claude-code-hub)](https://www.npmjs.com/package/claude-code-hub)
6
6
 
7
- Unified launcher for Claude Code tools — browse plugins in **Marketplace**, track tasks in **Kanban**, monitor costs in **Cost**, and explore memory in **Memory Diagnoser**, all from a single chromeless PWA.
7
+ One window for your Claude Code tools: Kanban, Marketplace, Cost, and Memory Diagnoser, in a single chromeless PWA that you drive from the keyboard.
8
8
 
9
- ## Kanban:
9
+ Website: [nikiforovall.blog/claude-code-hub](https://nikiforovall.blog/claude-code-hub/)
10
10
 
11
- ![Kanban Screenshot](./assets/cck.png)
11
+ ## The tools
12
12
 
13
- ## Marketplace:
14
- ![Marketplace Screenshot](./assets/marketplace.png)
13
+ ### Kanban
15
14
 
16
- ## Cost:
17
- ![Cost Screenshot](./assets/cost.png)
15
+ See tasks, sessions, and live agent activity as a board. Open a Claude Code session in the embedded terminal.
18
16
 
19
- ## Memory Diagnoser:
20
- ![Memory Diagnoser Screenshot](./assets/memory.png)
17
+ <picture>
18
+ <source media="(prefers-color-scheme: dark)" srcset="assets/kanban-dark.webp">
19
+ <img alt="Kanban board with sessions and tasks" src="assets/kanban-light.webp">
20
+ </picture>
21
21
 
22
- ## Quick Start
22
+ ### Marketplace
23
+
24
+ Browse and manage Claude Code marketplace plugins.
25
+
26
+ <picture>
27
+ <source media="(prefers-color-scheme: dark)" srcset="assets/marketplace-dark.webp">
28
+ <img alt="Marketplace with the plugin list" src="assets/marketplace-light.webp">
29
+ </picture>
30
+
31
+ ### Cost
32
+
33
+ See what your Claude Code usage costs, per session and per project.
34
+
35
+ <picture>
36
+ <source media="(prefers-color-scheme: dark)" srcset="assets/cost-dark.webp">
37
+ <img alt="Cost dashboard with usage charts" src="assets/cost-light.webp">
38
+ </picture>
39
+
40
+ ### Memory Diagnoser
41
+
42
+ Explore the memory files that Claude Code loads for a project.
43
+
44
+ <picture>
45
+ <source media="(prefers-color-scheme: dark)" srcset="assets/memory-dark.webp">
46
+ <img alt="Memory Diagnoser with loaded memory files" src="assets/memory-light.webp">
47
+ </picture>
48
+
49
+ ## Quick start
23
50
 
24
51
  ```bash
25
52
  npx claude-code-hub --open
26
53
  ```
27
54
 
28
- ### From Source
55
+ The hub starts on `http://localhost:3540` and opens the browser. To get a window with no browser UI, install the page as an app from the browser menu.
56
+
57
+ ### From source
29
58
 
30
59
  ```bash
31
60
  git clone --recurse-submodules https://github.com/NikiforovAll/claude-code-hub.git
32
61
  cd claude-code-hub
33
- npm install && npm install --prefix marketplace && npm install --prefix cck && npm install --prefix memory
62
+ npm install && npm install --prefix marketplace && npm install --prefix cck && npm install --prefix cost && npm install --prefix memory
34
63
  npm start # http://localhost:3540
35
64
  ```
36
65
 
37
- ## Agent Observability (one-time setup)
66
+ ## Agent observability (one-time setup)
38
67
 
39
- For the full Kanban experience — agent log, live subagent tracking, waiting-for-user indicators, and context window monitoring — install the hooks:
68
+ For the full Kanban view (agent log, live subagent tracking, waiting-for-user indicators, and context window use), install the hooks:
40
69
 
41
70
  ```bash
42
71
  npx claude-code-kanban --install
43
72
  ```
44
73
 
45
- Without hooks you still get the task board, but no agent activity or live indicators. See the [Kanban README](https://github.com/NikiforovAll/claude-task-viewer#getting-started) for details.
74
+ Without the hooks you still get the task board and sessions, but no live agent activity. The hooks and status line are installed per Claude config dir, so run the command again for each dir you use. See the [Kanban docs](https://nikiforovall.blog/claude-code-kanban/) for details.
75
+
76
+ ## Hub token
77
+
78
+ The hub page and its API need a token. Any local account can reach a loopback port, and the API carries the terminal token.
79
+
80
+ - The token is in `~/.claude-hub/token`. The hub creates it on the first run and keeps it across restarts.
81
+ - The startup banner prints the URL with the token, `http://localhost:3540/?token=…`, and `--open` uses that URL. The hub sets a cookie and then removes the token from the address bar, so later visits and the installed app need no token.
82
+ - Without the token, the page shows a locked screen.
83
+ - To change the token, delete the file and restart the hub.
46
84
 
47
- ## Keyboard Shortcuts
85
+ ## Config dirs
48
86
 
49
- | Shortcut | Action |
50
- | ---------------- | ----------------------- |
51
- | `Alt+1` | Switch to Kanban |
52
- | `Alt+2` | Switch to Marketplace |
53
- | `Alt+3` | Switch to Cost |
54
- | `Alt+4` | Switch to Memory Diagnoser |
55
- | `Ctrl+M` | Open Memory Diagnoser for current session (Kanban) |
56
- | `Ctrl+Alt+Right` | Switch to next tool |
57
- | `Ctrl+Alt+Left` | Switch to previous tool |
58
- | `Ctrl+Alt+P` | Switch project |
59
- | `Ctrl+Alt+W` | Switch Claude config dir (`CLAUDE_CONFIG_DIR`); restarts the sub-apps |
87
+ The hub can run the tools against more than one Claude config dir (`CLAUDE_CONFIG_DIR`), for example a work dir and a personal dir.
60
88
 
61
- ## How It Works
89
+ - Press <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>W</kbd> to open the config-dir palette. Pick a dir to switch to it, or type a path to add a new one. <kbd>Ctrl</kbd>+<kbd>D</kbd> removes the selected dir.
90
+ - Each dir gets its own set of the four tools. When you switch, the hub keeps the old set running, so switching back is instant. `--pool-size` sets how many sets stay alive (default 3). When the pool is full, the hub stops the least recently used set, but not a set whose Kanban has open terminals.
91
+ - The list and the active dir are saved in `~/.claude-hub/config.json`.
62
92
 
63
- The hub server spawns both sub-apps as child processes, each on its own port. A minimal shell page embeds them in iframes and switches visibility on tab change — zero UI chrome, just keyboard shortcuts.
93
+ ## Embedded terminal
64
94
 
65
- ## Included Tools
95
+ Under the hub, Kanban has an embedded terminal, on by default, so you can start or resume Claude Code sessions from the board. While a terminal is attached, the hub asks before it closes the window, because <kbd>Ctrl</kbd>+<kbd>W</kbd> meant for the terminal would close it.
66
96
 
67
- | Tool | Submodule | Default Port |
68
- | ---------------------------------------------------------------------- | -------------- | ------------ |
69
- | [Marketplace](https://github.com/NikiforovAll/claude-code-marketplace) | `marketplace/` | 3542 |
70
- | [Kanban](https://github.com/NikiforovAll/claude-task-viewer) | `cck/` | 3541 |
71
- | [Cost](https://github.com/NikiforovAll/claude-code-cost) | `cost/` | 3543 |
72
- | [Memory Diagnoser](https://github.com/NikiforovAll/claude-code-memory) | `memory/` | 3544 |
97
+ To turn the terminal off, start the hub with `--disable-terminal`, or add this to `~/.claude-hub/config.json`:
73
98
 
74
- ## CLI Flags
99
+ ```json
100
+ {
101
+ "terminal": { "enabled": false }
102
+ }
103
+ ```
104
+
105
+ ## Keyboard shortcuts
106
+
107
+ The hub has no visible UI of its own. Use these shortcuts:
108
+
109
+ | Shortcut | Action |
110
+ | --- | --- |
111
+ | <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>→</kbd> | Next tool |
112
+ | <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>←</kbd> | Previous tool |
113
+ | <kbd>Alt</kbd>+<kbd>1</kbd> | Kanban |
114
+ | <kbd>Alt</kbd>+<kbd>2</kbd> | Marketplace |
115
+ | <kbd>Alt</kbd>+<kbd>3</kbd> | Cost |
116
+ | <kbd>Alt</kbd>+<kbd>4</kbd> | Memory Diagnoser |
117
+ | <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>P</kbd> | Project palette: set the project for all tools |
118
+ | <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>W</kbd> | Config-dir palette: switch, add, or remove a config dir |
119
+
120
+ In a palette, use <kbd>↑</kbd>/<kbd>↓</kbd> or <kbd>Tab</kbd> to move, <kbd>Enter</kbd> to select, and <kbd>Esc</kbd> to close.
121
+
122
+ The shortcuts also work when focus is inside a tool. Kanban keeps <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>N</kbd> (new session), <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>R</kbd> (resume session), and <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>S</kbd> (previous session) for itself. From Kanban you can also jump to another tool for the selected session:
123
+
124
+ | Shortcut | Action |
125
+ | --- | --- |
126
+ | <kbd>M</kbd> | Open Marketplace for the session's project |
127
+ | <kbd>$</kbd> | Open Cost for the session |
128
+ | <kbd>Ctrl</kbd>+<kbd>M</kbd> | Open Memory Diagnoser for the session's project |
129
+
130
+ ## CLI flags
75
131
 
76
132
  ```
77
133
  --port <n> Hub port (default: 3540)
78
- --marketplace-port <n> Marketplace port (default: 3542)
79
134
  --kanban-port <n> Kanban port (default: 3541)
135
+ --marketplace-port <n> Marketplace port (default: 3542)
80
136
  --cost-port <n> Cost port (default: 3543)
81
137
  --memory-port <n> Memory Diagnoser port (default: 3544)
82
- --pool-size <n> Config dirs kept running after a switch (default: 3)
83
- --open Auto-open browser
138
+ --pool-size <n> Config-dir sets kept running after a switch (default: 3)
139
+ --disable-terminal Turn off the embedded terminal in Kanban
140
+ --host <addr> Bind address (default: 127.0.0.1)
141
+ --allowed-hosts <list> Extra host names to accept, comma-separated
142
+ --open Open the browser on start
84
143
  ```
85
144
 
145
+ If a port is busy, the hub uses a free port and reports it.
146
+
147
+ ## Included tools
148
+
149
+ | Tool | Docs | Repo | Submodule | Default port |
150
+ | --- | --- | --- | --- | --- |
151
+ | Kanban | [Docs](https://nikiforovall.blog/claude-code-kanban/) | [claude-code-kanban](https://github.com/NikiforovAll/claude-code-kanban) | `cck/` | 3541 |
152
+ | Marketplace | [Docs](https://nikiforovall.blog/claude-code-marketplace/) | [claude-code-marketplace](https://github.com/NikiforovAll/claude-code-marketplace) | `marketplace/` | 3542 |
153
+ | Cost | [Docs](https://nikiforovall.blog/claude-code-cost/) | [claude-code-cost](https://github.com/NikiforovAll/claude-code-cost) | `cost/` | 3543 |
154
+ | Memory Diagnoser | [Docs](https://nikiforovall.blog/claude-code-memory/) | [claude-code-memory](https://github.com/NikiforovAll/claude-code-memory) | `memory/` | 3544 |
155
+
86
156
  ## License
87
157
 
88
158
  MIT
package/lib/net-guard.js CHANGED
@@ -181,6 +181,16 @@ function createNetGuard(config = {}) {
181
181
  return next();
182
182
  }
183
183
 
184
+ // For a WebSocket upgrade, which originGuard must not judge: the handshake is a
185
+ // GET, and WebSocket has no CORS, so any page can open one. Browsers always send
186
+ // Origin on the handshake, so a missing or `null` one is refused, not trusted.
187
+ // Returns null when allowed, or the reason it was refused.
188
+ function upgradeVerdict(req) {
189
+ if (!hostAllowed(parseHostHeader(req.headers.host))) return 'unrecognized Host header';
190
+ if (originVerdict(req.headers.origin) !== true) return 'cross-origin or missing Origin';
191
+ return null;
192
+ }
193
+
184
194
  // Constant for the life of the process, and frameGuard runs ahead of
185
195
  // express.static — so this is built once rather than per asset fetch.
186
196
  //
@@ -229,12 +239,19 @@ function createNetGuard(config = {}) {
229
239
  * @param {any} app express app (or any http request handler)
230
240
  * @param {number} port 0 selects a free port
231
241
  * @param {(port: number) => void} [onReady]
232
- * @param {{maxHeaderSize?: number}} [opts]
242
+ * `onUpgrade` is attached to both servers; a caller that attached it to the
243
+ * returned one alone would drop every WebSocket that arrives over the other family.
244
+ *
245
+ * @param {{maxHeaderSize?: number, onUpgrade?: (req: any, socket: any, head: Buffer) => void}} [opts]
233
246
  */
234
247
  function listenLoopback(app, port, onReady, opts = {}) {
235
248
  const http = require('http');
236
249
  const serverOpts = opts.maxHeaderSize ? { maxHeaderSize: opts.maxHeaderSize } : {};
237
- const makeServer = (handler) => http.createServer(serverOpts, handler);
250
+ const makeServer = (handler) => {
251
+ const s = http.createServer(serverOpts, handler);
252
+ if (opts.onUpgrade) s.on('upgrade', opts.onUpgrade);
253
+ return s;
254
+ };
238
255
  const server = makeServer(app);
239
256
  let secondary = null;
240
257
 
@@ -261,7 +278,7 @@ function createNetGuard(config = {}) {
261
278
  return `WARNING: listening on ${BIND_HOST} - reachable from your network, with no authentication.`;
262
279
  }
263
280
 
264
- return { BIND_HOST, ALLOWED_HOSTS, hostGuard, originGuard, frameGuard, listenLoopback, exposureWarning };
281
+ return { BIND_HOST, ALLOWED_HOSTS, EXPOSED, hostGuard, originGuard, upgradeVerdict, frameGuard, listenLoopback, exposureWarning };
265
282
  }
266
283
 
267
284
  module.exports = { createNetGuard, parseHostHeader, isLoopbackAddress };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-hub",
3
- "version": "0.37.0",
3
+ "version": "0.39.0-rc.1",
4
4
  "description": "Unified hub for Claude Code tools — Marketplace + Kanban in one PWA",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -9,6 +9,8 @@
9
9
  "scripts": {
10
10
  "start": "node server.js",
11
11
  "dev": "node server.js --open",
12
+ "update": "bash scripts/update-submodules.sh",
13
+ "update:check": "bash scripts/update-submodules.sh --check",
12
14
  "lint": "npx @biomejs/biome check public/app.js server.js && npm run check:escaping && npm run check:security-lib",
13
15
  "lint:fix": "npx @biomejs/biome check --fix public/app.js server.js",
14
16
  "prepare": "husky",
@@ -37,10 +39,10 @@
37
39
  },
38
40
  "homepage": "https://github.com/NikiforovAll/claude-code-hub#readme",
39
41
  "dependencies": {
40
- "claude-code-cost": "^0.23.0",
41
- "claude-code-kanban": "^4.26.0",
42
- "claude-code-marketplace": "^0.18.0",
43
- "claude-code-memory-explorer": "^0.14.0",
42
+ "claude-code-cost": "^0.24.0-rc.1",
43
+ "claude-code-kanban": "^4.28.0-rc.1",
44
+ "claude-code-marketplace": "^0.20.0-rc.1",
45
+ "claude-code-memory-explorer": "^0.15.0-rc.1",
44
46
  "express": "^4.21.0",
45
47
  "open": "^10.1.0"
46
48
  },