@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/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
- Hearth does not create the public tunnel for you. ChatGPT users need a public
15
- HTTPS URL forwarding to the local server: their own reverse proxy or tunnel,
16
- or Hearth's relay-free direct exposure (own domain + TLS, see
17
- `hearth expose`).
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. Start your tunnel or
75
- reverse proxy first and point it at:
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
- http://127.0.0.1:7176
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://your-tunnel-host.example.com/mcp
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
- If your tunnel URL changes, update the persisted value before starting:
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 config set publicBaseUrl https://hearth.example.com
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunshinelife83/hearth",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Expose a secure local coding workspace through an MCP server.",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/Waishnav/hearth#readme",
@@ -429,39 +429,22 @@
429
429
  },
430
430
  "additionalProperties": false
431
431
  },
432
- "tls": {
432
+ "tunnel": {
433
433
  "default": {
434
- "certFile": null,
435
- "keyFile": null,
436
- "acmeDir": null
434
+ "provider": "none",
435
+ "domain": null
437
436
  },
438
437
  "type": "object",
439
438
  "properties": {
440
- "certFile": {
441
- "default": null,
442
- "anyOf": [
443
- {
444
- "type": "string",
445
- "minLength": 1
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
- "acmeDir": {
447
+ "domain": {
465
448
  "default": null,
466
449
  "anyOf": [
467
450
  {