@sunshinelife83/hearth 1.0.0 → 1.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/README.md +24 -24
- package/dist/cli.js +303 -102
- package/dist/config-schema.js +11 -10
- package/dist/config.js +13 -4
- package/dist/dashboard/app.js +1 -1
- package/dist/dashboard/landing.html +2 -2
- package/dist/logger.js +0 -3
- package/dist/server.js +18 -9
- package/dist/tunnel-ngrok.js +270 -0
- package/dist/user-config.js +28 -1
- package/docs/configuration.md +7 -0
- package/docs/gotchas.md +57 -17
- package/docs/security.md +26 -4
- package/docs/setup.md +52 -23
- package/package.json +1 -1
- package/schema/v1/hearth.schema.json +10 -27
package/docs/setup.md
CHANGED
|
@@ -11,10 +11,12 @@ This guide covers ChatGPT and Coding Agents using Hearth with local projects.
|
|
|
11
11
|
- a public HTTPS URL that forwards to the local Hearth server, only when
|
|
12
12
|
ChatGPT will connect
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`hearth
|
|
14
|
+
ChatGPT users need a public HTTPS URL forwarding to the local server. The
|
|
15
|
+
supported way is the managed ngrok tunnel:
|
|
16
|
+
|
|
17
|
+
1. **Managed per-PC tunnel (the only remote path):** `hearth ngrok setup`
|
|
18
|
+
saves this PC's static domain — see
|
|
19
|
+
[Managed Tunnel](#managed-tunnel-every-pc-is-server-url-and-tunnel).
|
|
18
20
|
|
|
19
21
|
## Install And Configure
|
|
20
22
|
|
|
@@ -71,28 +73,18 @@ These commands do not require `hearth serve`.
|
|
|
71
73
|
|
|
72
74
|
### Connect ChatGPT
|
|
73
75
|
|
|
74
|
-
Setup only asks for a public URL if you selected ChatGPT.
|
|
75
|
-
|
|
76
|
+
Setup only asks for a public URL if you selected ChatGPT. Enter your static
|
|
77
|
+
ngrok domain as the public origin without `/mcp` (run
|
|
78
|
+
`hearth ngrok setup` first if you have not saved one yet):
|
|
76
79
|
|
|
77
80
|
```text
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Proxy the whole Hearth server from the root path of your tunnel or reverse
|
|
82
|
-
proxy — never mount only `/mcp`. Hearth also serves OAuth discovery and
|
|
83
|
-
authorization routes outside `/mcp`, and a path-scoped mount can strip `/mcp`
|
|
84
|
-
before the request reaches Hearth (arriving as `/` and failing).
|
|
85
|
-
|
|
86
|
-
Enter the public origin without `/mcp`:
|
|
87
|
-
|
|
88
|
-
```text
|
|
89
|
-
https://your-tunnel-host.example.com
|
|
81
|
+
https://xxx.ngrok-free.dev
|
|
90
82
|
```
|
|
91
83
|
|
|
92
84
|
Configure the MCP client with the full MCP endpoint:
|
|
93
85
|
|
|
94
86
|
```text
|
|
95
|
-
https://
|
|
87
|
+
https://xxx.ngrok-free.dev/mcp
|
|
96
88
|
```
|
|
97
89
|
|
|
98
90
|
Protocol compatibility is automatic. Hearth serves MCP 2026-07-28 requests
|
|
@@ -106,19 +98,56 @@ A Coding Agents-only setup skips this section.
|
|
|
106
98
|
Run:
|
|
107
99
|
|
|
108
100
|
```bash
|
|
109
|
-
npx @sunshinelife83/hearth serve
|
|
101
|
+
npx @sunshinelife83/hearth serve --ngrok
|
|
110
102
|
```
|
|
111
103
|
|
|
112
|
-
|
|
104
|
+
The static domain never changes, so no URL resync is ever needed. If you
|
|
105
|
+
replace the domain, update the persisted value before starting:
|
|
113
106
|
|
|
114
107
|
```bash
|
|
115
|
-
npx @sunshinelife83/hearth
|
|
116
|
-
npx @sunshinelife83/hearth serve
|
|
108
|
+
npx @sunshinelife83/hearth ngrok setup --domain https://new-domain.ngrok-free.dev
|
|
109
|
+
npx @sunshinelife83/hearth serve --ngrok
|
|
117
110
|
```
|
|
118
111
|
|
|
119
112
|
Use the origin only — never append `/mcp` to `publicBaseUrl`. The client URL is
|
|
120
113
|
`<origin>/mcp`. `hearth doctor --fix` repairs a saved `/mcp` suffix.
|
|
121
114
|
|
|
115
|
+
## Managed Tunnel: Every PC Is Server, URL, And Tunnel
|
|
116
|
+
|
|
117
|
+
`hearth ngrok setup` binds this PC to its static ngrok domain, so
|
|
118
|
+
`hearth serve --ngrok` alone is server + stable public URL + tunnel. No
|
|
119
|
+
second terminal, no pasted tunnel URLs, no hostname churn on restart.
|
|
120
|
+
|
|
121
|
+
Prerequisites (once per PC):
|
|
122
|
+
|
|
123
|
+
- an ngrok account (free is enough — every account gets one stable dev
|
|
124
|
+
domain such as `xxx.ngrok-free.dev`)
|
|
125
|
+
- `ngrok` installed (`brew install ngrok`, the Linux package for your
|
|
126
|
+
distro, or `winget install --id Ngrok.ngrok`)
|
|
127
|
+
- `ngrok config add-authtoken <your-token>` completed once (token from
|
|
128
|
+
https://dashboard.ngrok.com/get-started/your-authtoken)
|
|
129
|
+
|
|
130
|
+
Then:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
hearth ngrok setup --domain xxx.ngrok-free.dev
|
|
134
|
+
hearth serve --ngrok
|
|
135
|
+
hearth ngrok status
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
What setup does: saves the static domain, syncs `server.publicBaseUrl`, and
|
|
139
|
+
enables `server.trustProxy` so rate limits see real client IPs. Your
|
|
140
|
+
authtoken stays in ngrok's own config — Hearth never stores it. Scripted
|
|
141
|
+
setups can pass `--yes` (requires `--domain`).
|
|
142
|
+
|
|
143
|
+
`hearth serve --ngrok` supervises the ngrok agent and fails fast if the live
|
|
144
|
+
domain drifts from the saved one, instead of serving locally-but-dark.
|
|
145
|
+
`hearth doctor` checks the binary, auth, domain match, and child liveness.
|
|
146
|
+
Plain `hearth serve` stays local-only.
|
|
147
|
+
|
|
148
|
+
Note: ngrok free shows a browser interstitial page on HTML traffic. API calls
|
|
149
|
+
are unaffected; the Owner approval page needs one click-through.
|
|
150
|
+
|
|
122
151
|
## Connect A Host (ChatGPT / Claude / Generic)
|
|
123
152
|
|
|
124
153
|
Run:
|
package/package.json
CHANGED
|
@@ -429,39 +429,22 @@
|
|
|
429
429
|
},
|
|
430
430
|
"additionalProperties": false
|
|
431
431
|
},
|
|
432
|
-
"
|
|
432
|
+
"tunnel": {
|
|
433
433
|
"default": {
|
|
434
|
-
"
|
|
435
|
-
"
|
|
436
|
-
"acmeDir": null
|
|
434
|
+
"provider": "none",
|
|
435
|
+
"domain": null
|
|
437
436
|
},
|
|
438
437
|
"type": "object",
|
|
439
438
|
"properties": {
|
|
440
|
-
"
|
|
441
|
-
"default":
|
|
442
|
-
"
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
"type": "null"
|
|
449
|
-
}
|
|
450
|
-
]
|
|
451
|
-
},
|
|
452
|
-
"keyFile": {
|
|
453
|
-
"default": null,
|
|
454
|
-
"anyOf": [
|
|
455
|
-
{
|
|
456
|
-
"type": "string",
|
|
457
|
-
"minLength": 1
|
|
458
|
-
},
|
|
459
|
-
{
|
|
460
|
-
"type": "null"
|
|
461
|
-
}
|
|
439
|
+
"provider": {
|
|
440
|
+
"default": "none",
|
|
441
|
+
"type": "string",
|
|
442
|
+
"enum": [
|
|
443
|
+
"none",
|
|
444
|
+
"ngrok"
|
|
462
445
|
]
|
|
463
446
|
},
|
|
464
|
-
"
|
|
447
|
+
"domain": {
|
|
465
448
|
"default": null,
|
|
466
449
|
"anyOf": [
|
|
467
450
|
{
|