clauder-hub 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/README.md +310 -2
- package/bin/clauder-hub.mjs +61 -0
- package/logo.svg +1 -0
- package/package.json +54 -4
- package/server/dist/index.js +750 -0
- package/web/dist/assets/MonacoEditor-BbYsqB7V.css +1 -0
- package/web/dist/assets/MonacoEditor-Bdblyy-v.js +1007 -0
- package/web/dist/assets/abap-DLDM7-KI.js +1 -0
- package/web/dist/assets/apex-DNDY2TF8.js +1 -0
- package/web/dist/assets/azcli-Y6nb8tq_.js +1 -0
- package/web/dist/assets/babel-Dw5Eu3O9.js +16 -0
- package/web/dist/assets/bat-BwHxbl9M.js +1 -0
- package/web/dist/assets/bicep-CFznDFnq.js +2 -0
- package/web/dist/assets/cameligo-Bf6VGUru.js +1 -0
- package/web/dist/assets/clojure-Dnu-v4kV.js +1 -0
- package/web/dist/assets/codicon-DF1abBS2.ttf +0 -0
- package/web/dist/assets/coffee-Bd8akH9Z.js +1 -0
- package/web/dist/assets/cpp-BbWJElDN.js +1 -0
- package/web/dist/assets/csharp-Co3qMtFm.js +1 -0
- package/web/dist/assets/csp-D-4FJmMZ.js +1 -0
- package/web/dist/assets/css-DdJfP1eB.js +3 -0
- package/web/dist/assets/css.worker-CH7Os8C2.js +97 -0
- package/web/dist/assets/cssMode-DOakqY50.js +1 -0
- package/web/dist/assets/cypher-cTPe9QuQ.js +1 -0
- package/web/dist/assets/dart-BOtBlQCF.js +1 -0
- package/web/dist/assets/dockerfile-BG73LgW2.js +1 -0
- package/web/dist/assets/ecl-BEgZUVRK.js +1 -0
- package/web/dist/assets/editor.worker-BytiCuzy.js +30 -0
- package/web/dist/assets/elixir-BkW5O-1t.js +1 -0
- package/web/dist/assets/estree-DlGR-zBs.js +44 -0
- package/web/dist/assets/flow9-BeJ5waoc.js +1 -0
- package/web/dist/assets/freemarker2-WsMzPf-p.js +3 -0
- package/web/dist/assets/fsharp-PahG7c26.js +1 -0
- package/web/dist/assets/go-acbASCJo.js +1 -0
- package/web/dist/assets/graphql-BxJiqAUM.js +1 -0
- package/web/dist/assets/graphql-Houc-vhO.js +17 -0
- package/web/dist/assets/handlebars-CFf3afIj.js +1 -0
- package/web/dist/assets/hcl-DtV1sZF8.js +1 -0
- package/web/dist/assets/html-Cdlyoy-I.js +25 -0
- package/web/dist/assets/html-Duk6L3Ci.js +1 -0
- package/web/dist/assets/html.worker-DTgyLzoY.js +474 -0
- package/web/dist/assets/htmlMode-CuaMCYCU.js +1 -0
- package/web/dist/assets/index-CGbzqzmX.js +19 -0
- package/web/dist/assets/index-DI4uTQnz.css +32 -0
- package/web/dist/assets/index-DpS67tuQ.js +522 -0
- package/web/dist/assets/ini-Kd9XrMLS.js +1 -0
- package/web/dist/assets/java-CXBNlu9o.js +1 -0
- package/web/dist/assets/javascript-57wNn1QZ.js +1 -0
- package/web/dist/assets/json.worker-Dgwax7hT.js +62 -0
- package/web/dist/assets/jsonMode-DPgMOUkd.js +7 -0
- package/web/dist/assets/julia-cl7-CwDS.js +1 -0
- package/web/dist/assets/kotlin-s7OhZKlX.js +1 -0
- package/web/dist/assets/less-9HpZscsL.js +2 -0
- package/web/dist/assets/lexon-OrD6JF1K.js +1 -0
- package/web/dist/assets/liquid-DHlnUOel.js +1 -0
- package/web/dist/assets/lspLanguageFeatures-BIy_BVAi.js +4 -0
- package/web/dist/assets/lua-Cyyb5UIc.js +1 -0
- package/web/dist/assets/m3-B8OfTtLu.js +1 -0
- package/web/dist/assets/markdown-BFxVWTOG.js +1 -0
- package/web/dist/assets/markdown-Da4luf4E.js +70 -0
- package/web/dist/assets/mdx-SCDblWWe.js +1 -0
- package/web/dist/assets/mips-CiqrrVzr.js +1 -0
- package/web/dist/assets/msdax-DmeGPVcC.js +1 -0
- package/web/dist/assets/mysql-C_tMU-Nz.js +1 -0
- package/web/dist/assets/objective-c-BDtDVThU.js +1 -0
- package/web/dist/assets/pascal-vHIfCaH5.js +1 -0
- package/web/dist/assets/pascaligo-DtZ0uQbO.js +1 -0
- package/web/dist/assets/perl-Ub6l9XKa.js +1 -0
- package/web/dist/assets/pgsql-BlNEE0v7.js +1 -0
- package/web/dist/assets/php-BBUBE1dy.js +1 -0
- package/web/dist/assets/pla-DSh2-awV.js +1 -0
- package/web/dist/assets/postcss-2VMvKpSM.js +62 -0
- package/web/dist/assets/postiats-CocnycG-.js +1 -0
- package/web/dist/assets/powerquery-tScXyioY.js +1 -0
- package/web/dist/assets/powershell-COWaemsV.js +1 -0
- package/web/dist/assets/protobuf-Brw8urJB.js +2 -0
- package/web/dist/assets/pug-8SOpv6rk.js +1 -0
- package/web/dist/assets/python-DcjgL-6k.js +1 -0
- package/web/dist/assets/qsharp-Bw9ernYp.js +1 -0
- package/web/dist/assets/r-j7ic8hl3.js +1 -0
- package/web/dist/assets/razor-q_Zkc8t3.js +1 -0
- package/web/dist/assets/redis-Bu5POkcn.js +1 -0
- package/web/dist/assets/redshift-Bs9aos_-.js +1 -0
- package/web/dist/assets/restructuredtext-CqXO7rUv.js +1 -0
- package/web/dist/assets/ruby-zBfavPgS.js +1 -0
- package/web/dist/assets/rust-BzKRNQWT.js +1 -0
- package/web/dist/assets/sb-BBc9UKZt.js +1 -0
- package/web/dist/assets/scala-D9hQfWCl.js +1 -0
- package/web/dist/assets/scheme-BPhDTwHR.js +1 -0
- package/web/dist/assets/scss-CBJaRo0y.js +3 -0
- package/web/dist/assets/shell-DiJ1NA_G.js +1 -0
- package/web/dist/assets/solidity-Db0IVjzk.js +1 -0
- package/web/dist/assets/sophia-CnS9iZB_.js +1 -0
- package/web/dist/assets/sparql-CJmd_6j2.js +1 -0
- package/web/dist/assets/sql-ClhHkBeG.js +1 -0
- package/web/dist/assets/st-CHwy0fLd.js +1 -0
- package/web/dist/assets/standalone-fOeV0Vsa.js +29 -0
- package/web/dist/assets/swift-Bqt4WxQ4.js +3 -0
- package/web/dist/assets/systemverilog-Bs9z6M-B.js +1 -0
- package/web/dist/assets/tcl-Dm6ycUr_.js +1 -0
- package/web/dist/assets/ts.worker-CE_y865M.js +67735 -0
- package/web/dist/assets/tsMode-N3PGleJF.js +11 -0
- package/web/dist/assets/twig-Csy3S7wG.js +1 -0
- package/web/dist/assets/typescript-CpwMS6-X.js +22 -0
- package/web/dist/assets/typescript-UQxkBsMs.js +1 -0
- package/web/dist/assets/typespec-Btyra-wh.js +1 -0
- package/web/dist/assets/vb-Db0cS2oM.js +1 -0
- package/web/dist/assets/wgsl-BTesnYfV.js +298 -0
- package/web/dist/assets/workers-BVzxuZVI.js +1 -0
- package/web/dist/assets/xml-BDNQC6ch.js +1 -0
- package/web/dist/assets/yaml-CwaMJBxz.js +154 -0
- package/web/dist/assets/yaml-FyKAiCgl.js +1 -0
- package/web/dist/favicon.svg +1 -0
- package/web/dist/index.html +20 -0
- package/web/dist/logo-small.svg +1 -0
- package/web/dist/logo.svg +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Clauder Hub License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 goldyndevs. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Clauder Hub is free to use. You may install it from the npm registry and run
|
|
6
|
+
it on any number of your own machines, for personal or commercial work.
|
|
7
|
+
|
|
8
|
+
You may not, in whole or in part:
|
|
9
|
+
|
|
10
|
+
- copy, modify, merge, translate or create derivative works of it;
|
|
11
|
+
- redistribute, sublicense, sell, rent or publish it, or offer it as a hosted
|
|
12
|
+
service;
|
|
13
|
+
- decompile, reverse engineer or extract its source code, except where the law
|
|
14
|
+
explicitly permits it regardless of this restriction;
|
|
15
|
+
- remove or alter this license or any copyright notice.
|
|
16
|
+
|
|
17
|
+
All rights not expressly granted here are reserved by goldyndevs.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Contact: goldyndevs@gmail.com
|
package/README.md
CHANGED
|
@@ -1,3 +1,311 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Clauder Hub
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**A handy ADE (agentic development environment) for Claude Code: one local dashboard over every Claude Code session on your machine.**
|
|
4
|
+
|
|
5
|
+
Clauder Hub is a wrapper around Claude Code. It starts real `claude` processes
|
|
6
|
+
in real terminals, shows them in your browser, and adds what a single terminal
|
|
7
|
+
window cannot give you: every project's sessions in one place, an inbox of
|
|
8
|
+
everything Claude is waiting on, answers from your phone, scheduled and
|
|
9
|
+
webhook-triggered runs, and stats read straight from the transcripts.
|
|
10
|
+
|
|
11
|
+
Nothing is reimplemented and nothing is installed into Claude Code. The
|
|
12
|
+
terminal you see *is* the `claude` CLI you already use, with your login, your
|
|
13
|
+
settings and your plugins.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Why
|
|
18
|
+
|
|
19
|
+
Claude Code is great in one terminal. It gets messy with five:
|
|
20
|
+
|
|
21
|
+
- 😵 **Too many windows.** Sessions in several repos, each in its own tab, and
|
|
22
|
+
no way to see at a glance which ones are working, done, or stuck.
|
|
23
|
+
- ⏳ **Silent waits.** A session asks for permission or asks a question, and
|
|
24
|
+
sits there for an hour because you were in another window (or away from
|
|
25
|
+
your desk).
|
|
26
|
+
- 🔁 **Repeated chores.** Nightly test runs, dependency checks, triage on an
|
|
27
|
+
incoming webhook: you either babysit them or script around the CLI yourself.
|
|
28
|
+
- 🧰 **Context bloat.** Every agent, skill, MCP server and plugin you ever
|
|
29
|
+
installed loads into every session, even when the task needs three of them.
|
|
30
|
+
- 📊 **No overview.** Where did the tokens go? Which tools, subagents and MCP
|
|
31
|
+
servers did a session actually use?
|
|
32
|
+
|
|
33
|
+
Clauder Hub keeps all of that in one browser tab, and lets you answer from
|
|
34
|
+
Slack or Telegram when you are not at the machine.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Feature tour
|
|
39
|
+
|
|
40
|
+
### 🖥️ Sessions and terminals
|
|
41
|
+
|
|
42
|
+
- Every session of a project, read from `~/.claude/projects/...`, including the
|
|
43
|
+
ones you started in a plain terminal.
|
|
44
|
+
- **New session** opens a plain `claude` straight in an embedded terminal
|
|
45
|
+
(xterm.js over a pty on the hub). Resume any past session the same way.
|
|
46
|
+
- Closing the browser only detaches: the process keeps running in the hub.
|
|
47
|
+
Pop a session out into a window of its own (`#/w/...`) if you like.
|
|
48
|
+
- Sessions started outside the hub are visible but have no hooks; resume one
|
|
49
|
+
in the hub to bring it in.
|
|
50
|
+
|
|
51
|
+
### 🌐 The global page: many projects, one view
|
|
52
|
+
|
|
53
|
+
- One hub runs per machine and remembers every project you gave it.
|
|
54
|
+
- The global page (`#/global`) shows a card per project, **one inbox across all
|
|
55
|
+
of them**, and the global channels.
|
|
56
|
+
- Each project keeps its own database, queue, cron jobs, channels, presets and
|
|
57
|
+
categories, and they all keep running while you look at another project.
|
|
58
|
+
|
|
59
|
+
### 📥 Inbox: everything Claude is waiting on
|
|
60
|
+
|
|
61
|
+
- Permission requests, `AskUserQuestion` questions, ends of turns, MCP
|
|
62
|
+
suggestions and finished tasks land in the inbox as cards with buttons.
|
|
63
|
+
- Answer from the dashboard or from any channel. **The first answer from
|
|
64
|
+
anywhere wins**, and the others are told who answered.
|
|
65
|
+
- An answer is delivered by *typing into the pty*, exactly as you would.
|
|
66
|
+
Hooks never approve, deny or delay anything on their own.
|
|
67
|
+
|
|
68
|
+
### 💬 Channels: Telegram, Slack and webhooks
|
|
69
|
+
|
|
70
|
+
| Channel | How it connects | Two-way |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| Telegram | Bot API, long polling (no public URL needed) | Yes, inline buttons and replies |
|
|
73
|
+
| Slack | Socket Mode (no public URL needed) | Yes, blocks, buttons and threads |
|
|
74
|
+
| Webhook | JSON, plain text, Discord or Teams (Adaptive Card) | JSON carries a `replyUrl`; chat formats are one-way |
|
|
75
|
+
|
|
76
|
+
**BotFather-style commands** (on Slack use `!` instead of `/`, since Slack keeps `/` for itself):
|
|
77
|
+
|
|
78
|
+
| Command | What it does |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `/new <prompt>` | Start a session (alone, it asks for the prompt) |
|
|
81
|
+
| `/run <prompt>` | Queue an unattended run |
|
|
82
|
+
| `/sessions` | Pick a session; your plain messages then go to it |
|
|
83
|
+
| `/summary` | What a session did, read from its transcript (no tokens spent) |
|
|
84
|
+
| `/stop` | Stop a running session (asks first) |
|
|
85
|
+
| `/queue` | The run queue, with cancel buttons |
|
|
86
|
+
| `/cancel`, `/help` | Drop a pending question, or show the menu |
|
|
87
|
+
|
|
88
|
+
A **global bot** also has `/projects`, `/use <name>` and `/addproject`, and
|
|
89
|
+
relays every project's questions labelled with the project name.
|
|
90
|
+
|
|
91
|
+
**Natural-language fallbacks.** Misspell a command, describe a session instead
|
|
92
|
+
of naming it ("the one fixing the login bug"), or describe a folder for
|
|
93
|
+
`/addproject` ("my calendar app"), and the hub asks a small Claude model
|
|
94
|
+
(Haiku, no tools) for its best guesses. They come back as buttons; **nothing
|
|
95
|
+
runs until you press one**. Plain chat on Slack is never guessed at, since
|
|
96
|
+
people talk there.
|
|
97
|
+
|
|
98
|
+
### ⏰ Automation: cron, webhooks and a queue per project
|
|
99
|
+
|
|
100
|
+
- **Cron jobs** and **webhook triggers** start unattended sessions.
|
|
101
|
+
- A webhook is `POST /api/trigger/<job id>` with the job's token in the
|
|
102
|
+
`x-clauder-token` header. `{{payload.field}}` in the job's prompt pulls a
|
|
103
|
+
value from the request body (`{{payload}}` is the whole body, `{{now}}` the time).
|
|
104
|
+
- Every run goes through **one queue per project**: runs in a project go one at
|
|
105
|
+
a time, different projects run side by side.
|
|
106
|
+
- **Task categories** define what "done" means for a kind of task (a PR, an RCA,
|
|
107
|
+
test evidence...). A session with a category is closed only when Claude
|
|
108
|
+
reports every required deliverable; if something is missing, the hub types
|
|
109
|
+
back what is missing.
|
|
110
|
+
|
|
111
|
+
### 🧰 Toolsets and presets
|
|
112
|
+
|
|
113
|
+
- Turn agents, skills, MCP servers and plugins **off** for one session (its
|
|
114
|
+
Toolset tab), or save the choice as a **preset** for jobs and as the default
|
|
115
|
+
for new sessions.
|
|
116
|
+
- Applied only through that session's own `--settings` file. Changing a live
|
|
117
|
+
session restarts it on the same conversation.
|
|
118
|
+
|
|
119
|
+
### 📊 Stats from the transcripts
|
|
120
|
+
|
|
121
|
+
- Tokens (input, output, cache) by model and by day.
|
|
122
|
+
- Tool calls grouped as built-in, MCP (by server), skills and subagents, plus
|
|
123
|
+
each subagent's own tokens and calls.
|
|
124
|
+
- All parsed from the JSONL transcripts Claude Code already writes. Nothing
|
|
125
|
+
extra is collected.
|
|
126
|
+
|
|
127
|
+
### 📁 Files and editor
|
|
128
|
+
|
|
129
|
+
- A file tree in the sidebar (create, rename, move, delete) and a **Monaco**
|
|
130
|
+
editor with tabs.
|
|
131
|
+
- GitLens-style **blame** annotations from `git blame` (read-only, git is only
|
|
132
|
+
asked, never told).
|
|
133
|
+
|
|
134
|
+
### 📝 Prompts, memory and inventory
|
|
135
|
+
|
|
136
|
+
- Every word the hub adds to a session or sends to a channel is a prompt you
|
|
137
|
+
can edit and restore (Hub prompts).
|
|
138
|
+
- `CLAUDE.md` files, rules, auto memory, agents, skills and commands can be
|
|
139
|
+
edited in place after reviewing a diff.
|
|
140
|
+
- Inventory of agents, skills, commands, MCP servers, hooks and plugins by
|
|
141
|
+
scope (user, project, local, plugin).
|
|
142
|
+
- **MCP suggestions:** when a session is blocked on a missing integration it
|
|
143
|
+
says so and stops. The `claude mcp add --scope project ...` command runs only
|
|
144
|
+
when you approve it, then the session resumes so the server loads.
|
|
145
|
+
|
|
146
|
+
### 🤖 No forms: configuration is a conversation
|
|
147
|
+
|
|
148
|
+
Creating a cron job, a run, a category, a preset or a channel opens a Claude
|
|
149
|
+
session with that purpose. Claude asks what it needs, shows the final JSON,
|
|
150
|
+
and saves it through the hub API after you say yes.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Use cases
|
|
155
|
+
|
|
156
|
+
**Approve a permission from your phone.** You step away while Claude refactors
|
|
157
|
+
a module. It hits a `Bash` permission prompt; the request arrives in Telegram
|
|
158
|
+
with buttons. Tap *Allow*, and the hub types the answer into the terminal.
|
|
159
|
+
|
|
160
|
+
**Reply late, safely.** You reply to a question an hour later by replying to
|
|
161
|
+
its Telegram message. If it was already answered, or the session has moved
|
|
162
|
+
on, the hub tells you so (and points at the newer question) instead of
|
|
163
|
+
applying your old "yes" to whatever dialog is showing now.
|
|
164
|
+
|
|
165
|
+
**Nightly jobs with a summary.** A cron job runs `npm test` and triages
|
|
166
|
+
failures every night at 2:00. Each run waits its turn in the project's queue,
|
|
167
|
+
and its end of turn (or its done report, if the job has a category) lands in
|
|
168
|
+
the inbox and your channels. In the morning, `/summary` shows what it did.
|
|
169
|
+
|
|
170
|
+
**Juggle five projects from one page.** Add each repo once. The global page
|
|
171
|
+
shows every project, a single inbox, and one global bot that tags each
|
|
172
|
+
message with its project. `/use api-server` then `/new fix the flaky test`
|
|
173
|
+
starts work there from chat.
|
|
174
|
+
|
|
175
|
+
**Add a project by describing it.** Tell the global bot `/addproject my
|
|
176
|
+
calendar app`. It looks through your usual code folders and offers matching
|
|
177
|
+
folders as buttons; press one and the project is in the hub.
|
|
178
|
+
|
|
179
|
+
**Trigger Claude from another system.** Point a GitHub, n8n or monitoring
|
|
180
|
+
webhook at `POST /api/trigger/<job id>`; the job's prompt picks fields out of
|
|
181
|
+
the payload with `{{payload.issue.title}}` and queues a run.
|
|
182
|
+
|
|
183
|
+
**Lean sessions for focused work.** Make a "frontend" preset that turns off the
|
|
184
|
+
database MCP servers and backend agents, and use it for UI jobs and new
|
|
185
|
+
sessions.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Quick start
|
|
190
|
+
|
|
191
|
+
**Requirements**
|
|
192
|
+
|
|
193
|
+
- Node.js 22 or newer
|
|
194
|
+
- [Claude Code](https://docs.claude.com/en/docs/claude-code) installed and
|
|
195
|
+
logged in (`claude` on your PATH)
|
|
196
|
+
|
|
197
|
+
**Install and run**
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
npx clauder-hub "/path/to/your/project"
|
|
201
|
+
# or keep it installed:
|
|
202
|
+
npm i -g clauder-hub
|
|
203
|
+
clauder-hub "/path/to/your/project" # 'clauder-hub .' for the current folder
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Open **http://localhost:4329**. The port moves up if it is taken (`--port <n>`
|
|
207
|
+
to pick one); the hub prints the one it chose. It remembers its projects, so
|
|
208
|
+
later runs can be just `clauder-hub`, and running it again with another path
|
|
209
|
+
while the hub is up adds that folder to the running hub. `clauder-hub --help`
|
|
210
|
+
lists the options.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## How it works
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
Browser (React + xterm.js) Telegram / Slack / webhooks
|
|
218
|
+
| ^ | ^
|
|
219
|
+
REST + WebSocket | answers | | questions
|
|
220
|
+
v | v |
|
|
221
|
+
+-----------------------------------------------------------------------+
|
|
222
|
+
| Clauder Hub server (Express + ws, 127.0.0.1, one per machine) |
|
|
223
|
+
| |
|
|
224
|
+
| inbox / channels / queue + cron / stats / files / prompts |
|
|
225
|
+
+-----------------------------------------------------------------------+
|
|
226
|
+
| spawns in a pty, types answers ^ HTTP hooks (answered {} at once)
|
|
227
|
+
v |
|
|
228
|
+
+--------------------------+ writes +--------------------------+
|
|
229
|
+
| real `claude` process | -------------> | ~/.claude/projects/... |
|
|
230
|
+
| --settings (hooks) | | JSONL transcripts |
|
|
231
|
+
| --append-system-prompt | +--------------------------+
|
|
232
|
+
+--------------------------+ | read for stats
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
| Need | How |
|
|
236
|
+
| --- | --- |
|
|
237
|
+
| Show the terminal | `claude` runs in a pty on the hub; the page attaches over a WebSocket |
|
|
238
|
+
| Know a session is waiting | HTTP hooks passed per process with `--settings` (SessionStart, UserPromptSubmit, PermissionRequest, PreToolUse for AskUserQuestion, Notification, Stop, SessionEnd). The hub answers each with `{}` immediately, so hooks never decide or delay anything |
|
|
239
|
+
| Answer from anywhere | The answer is typed into the pty, as a person would |
|
|
240
|
+
| Done reports, MCP suggestions | `--append-system-prompt-file`, read back from the last message by the Stop hook |
|
|
241
|
+
| Toolsets | Settings keys merged into the session's own `--settings` file |
|
|
242
|
+
| Stats | The JSONL transcripts Claude Code writes anyway |
|
|
243
|
+
|
|
244
|
+
**Data layout** (`CLAUDER_HUB_HOME` moves it):
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
~/.clauder-hub/
|
|
248
|
+
hub.db project list and hub prompts
|
|
249
|
+
hub.lock one hub per machine; a second start hands its folder over
|
|
250
|
+
global/ the global context (global channels, hub tasks)
|
|
251
|
+
projects/<id>/ hub.db per project: sessions, inbox, jobs, channels, presets
|
|
252
|
+
run/ per-terminal --settings files and appended system prompts
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Safety and privacy
|
|
258
|
+
|
|
259
|
+
- 🔒 **Local only.** The server listens on `127.0.0.1`, never on your network.
|
|
260
|
+
It runs a shell-capable agent, so keep it that way.
|
|
261
|
+
- 🧼 **Nothing installed into Claude Code.** No MCP server, skill, plugin or
|
|
262
|
+
settings file is written. Hooks and the extra prompt are passed per process
|
|
263
|
+
on the command line. The only exceptions are ones you ask for by name:
|
|
264
|
+
running a suggested `claude mcp add --scope project`, or saving an
|
|
265
|
+
instruction file after reviewing its diff.
|
|
266
|
+
- 🙅 **Hooks never decide.** Every hook is answered `{}` before the hub does
|
|
267
|
+
anything with it, so the hub cannot approve or block a tool call by itself.
|
|
268
|
+
- ✋ **Confirm before acting.** Stopping, deleting, running commands and
|
|
269
|
+
starting unattended runs ask first in the dashboard. Channel guesses are
|
|
270
|
+
buttons that do nothing until pressed.
|
|
271
|
+
- 📡 **What leaves the machine:** only what you configure. Channel messages go
|
|
272
|
+
to the Slack, Telegram or webhook you set up, and natural-language guesses
|
|
273
|
+
use your own Claude Code login (a small Haiku call).
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## FAQ
|
|
278
|
+
|
|
279
|
+
**Does it replace Claude Code?**
|
|
280
|
+
No. It runs the `claude` you already have, in a real terminal. Everything you
|
|
281
|
+
can do in Claude Code you still do in that terminal.
|
|
282
|
+
|
|
283
|
+
**Do I need a server or a public URL for Telegram or Slack?**
|
|
284
|
+
No. Telegram uses long polling and Slack uses Socket Mode, both outgoing
|
|
285
|
+
connections from your machine.
|
|
286
|
+
|
|
287
|
+
**What happens to sessions when I close the browser?**
|
|
288
|
+
They keep running in the hub. Reopen the page and attach again.
|
|
289
|
+
|
|
290
|
+
**Can it see sessions I started in a normal terminal?**
|
|
291
|
+
Yes, they are listed with their stats. To answer them from the inbox or a
|
|
292
|
+
channel, resume them in the hub so they get its hooks.
|
|
293
|
+
|
|
294
|
+
**Does it cost extra tokens?**
|
|
295
|
+
Stats and `/summary` are read from transcripts and cost nothing. Only the
|
|
296
|
+
natural-language fallbacks in channels make a small Haiku call.
|
|
297
|
+
|
|
298
|
+
**Can two hubs run at once?**
|
|
299
|
+
One hub runs per machine. Starting another hands its project folder to the
|
|
300
|
+
running one.
|
|
301
|
+
|
|
302
|
+
**Where is my data?**
|
|
303
|
+
In `~/.clauder-hub` (or `CLAUDER_HUB_HOME`), plus the transcripts Claude Code
|
|
304
|
+
keeps in `~/.claude`.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
Free to use, not open source: see [LICENSE](LICENSE). © 2026 goldyndevs.
|
|
311
|
+
Questions and ideas: goldyndevs@gmail.com
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
|
|
6
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const serverEntry = path.join(here, "..", "server", "dist", "index.js");
|
|
8
|
+
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
|
|
11
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
12
|
+
console.log(`
|
|
13
|
+
clauder-hub [project path] [--port <n>]
|
|
14
|
+
|
|
15
|
+
Opens the dashboard for the Claude Code sessions of your projects. One hub
|
|
16
|
+
runs per machine and keeps every project it was given: their sessions, cron
|
|
17
|
+
jobs and webhooks run as long as it does. A path adds that project and opens
|
|
18
|
+
it ('clauder-hub .' for the current folder); when a hub is already running,
|
|
19
|
+
the path is handed to it.
|
|
20
|
+
|
|
21
|
+
--port <n> Preferred port (default 4329). If it is taken, the next free
|
|
22
|
+
one is used.
|
|
23
|
+
version Print the version.
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
npx clauder-hub "C:\\Source code\\your-repo"
|
|
27
|
+
cd your-repo && npx clauder-hub .
|
|
28
|
+
npx clauder-hub
|
|
29
|
+
`);
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (args[0] === "version") {
|
|
34
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(here, "..", "package.json"), "utf8"));
|
|
35
|
+
console.log(pkg.version);
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function flag(name) {
|
|
40
|
+
const index = args.indexOf(name);
|
|
41
|
+
return index === -1 ? undefined : args[index + 1];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const positional = args.find((arg, index) => !arg.startsWith("-") && args[index - 1] !== "--port");
|
|
45
|
+
const target = positional ? path.resolve(positional) : "";
|
|
46
|
+
|
|
47
|
+
if (target && (!fs.existsSync(target) || !fs.statSync(target).isDirectory())) {
|
|
48
|
+
console.error(`\n ${target} is not a folder.\n`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!fs.existsSync(serverEntry)) {
|
|
53
|
+
console.error(`\n The hub has not been built yet.\n Run 'npm run build' in ${path.join(here, "..")}\n`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const port = flag("--port");
|
|
58
|
+
if (port) process.env.PORT = port;
|
|
59
|
+
if (target) process.env.CLAUDER_HUB_PROJECT = target;
|
|
60
|
+
|
|
61
|
+
await import(pathToFileURL(serverEntry).href);
|
package/logo.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 18 48 30" width="480px" height="300px" baseProfile="basic"><rect width="36" height="24" x="6" y="18" fill="#d77757"/><rect width="3" height="9" x="9" y="39" fill="#d77757"/><rect width="3" height="9" x="15" y="39" fill="#d77757"/><rect width="3" height="9" x="30" y="39" fill="#d77757"/><rect width="3" height="9" x="36" y="39" fill="#d77757"/><rect width="7.5" height="6" y="33" fill="#d77757"/><rect width="7.5" height="6" x="40.5" y="33" fill="#d77757"/><rect width="9" height="9" x="12" y="24"/><rect width="9" height="9" x="27" y="24"/><rect width="3" height="6" x="22.5" y="22.5" transform="rotate(90 24 25.5)"/><rect width="3" height="7" x="37" y="22" transform="rotate(90 38.5 25.5)"/><rect width="3" height="7" x="8" y="22" transform="rotate(90 9.5 25.5)"/></svg>
|
package/package.json
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clauder-hub",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A local dashboard that runs, watches and automates the Claude Code sessions of every project on the machine",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"author": "goldyndevs <goldyndevs@gmail.com>",
|
|
7
|
+
"homepage": "https://www.npmjs.com/package/clauder-hub",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=22"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"claude",
|
|
14
|
+
"claude-code",
|
|
15
|
+
"dashboard",
|
|
16
|
+
"terminal",
|
|
17
|
+
"automation"
|
|
18
|
+
],
|
|
19
|
+
"workspaces": [
|
|
20
|
+
"server",
|
|
21
|
+
"web"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"clauder-hub": "bin/clauder-hub.mjs"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"LICENSE",
|
|
28
|
+
"logo.svg",
|
|
29
|
+
"bin",
|
|
30
|
+
"server/dist",
|
|
31
|
+
"web/dist"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"dev": "node scripts/dev.mjs",
|
|
35
|
+
"build": "npm run build:server && npm -w web run build",
|
|
36
|
+
"typecheck": "npm -w server run typecheck && npm -w web run typecheck",
|
|
37
|
+
"prepare": "npm run build",
|
|
38
|
+
"build:server": "esbuild server/src/index.ts --bundle --platform=node --format=esm --target=node22 --minify --outfile=server/dist/index.js --external:better-sqlite3 --external:@lydell/node-pty --banner:js=\"import{createRequire}from'node:module';const require=createRequire(import.meta.url);\""
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@lydell/node-pty": "1.2.0-beta.18",
|
|
42
|
+
"better-sqlite3": "^13.0.3",
|
|
43
|
+
"material-icon-theme": "^5.40.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"cors": "^2.8.5",
|
|
47
|
+
"croner": "^9.1.0",
|
|
48
|
+
"esbuild": "^0.28.2",
|
|
49
|
+
"express": "^4.21.2",
|
|
50
|
+
"ignore": "^7.0.14",
|
|
51
|
+
"nanoid": "^5.0.9",
|
|
52
|
+
"tsx": "^4.19.2",
|
|
53
|
+
"ws": "^8.18.0",
|
|
54
|
+
"zod": "^4.1.13"
|
|
55
|
+
}
|
|
56
|
+
}
|