uplink-cli 0.1.38 → 0.2.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/AGENTS.md +177 -0
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +72 -52
- package/cli/src/index.ts +16 -3
- package/cli/src/registrars/cloudflare.ts +148 -0
- package/cli/src/registrars/dreamhost.ts +129 -0
- package/cli/src/registrars/godaddy.ts +105 -0
- package/cli/src/registrars/hostinger.ts +106 -0
- package/cli/src/registrars/http.ts +18 -0
- package/cli/src/registrars/index.ts +32 -0
- package/cli/src/registrars/namecheap.ts +163 -0
- package/cli/src/registrars/secret.ts +66 -0
- package/cli/src/registrars/store.ts +55 -0
- package/cli/src/registrars/types.ts +42 -0
- package/cli/src/subcommands/admin.ts +17 -30
- package/cli/src/subcommands/db.ts +63 -57
- package/cli/src/subcommands/dev.ts +23 -25
- package/cli/src/subcommands/domains.ts +295 -0
- package/cli/src/subcommands/host-domains.ts +148 -0
- package/cli/src/subcommands/host.ts +3 -0
- package/cli/src/subcommands/login.ts +85 -0
- package/cli/src/subcommands/menu/colors.ts +1 -1
- package/cli/src/subcommands/menu/effects/tunnel-clients.ts +87 -14
- package/cli/src/subcommands/menu/inline-tree-select.ts +6 -5
- package/cli/src/subcommands/menu/io.ts +27 -5
- package/cli/src/subcommands/menu/menus/domain-check.ts +34 -0
- package/cli/src/subcommands/menu/menus/domains.ts +197 -0
- package/cli/src/subcommands/menu/menus/hosting.ts +14 -46
- package/cli/src/subcommands/menu/menus/index.ts +1 -0
- package/cli/src/subcommands/menu/menus/tunnels.ts +25 -67
- package/cli/src/subcommands/menu/render.ts +2 -2
- package/cli/src/subcommands/menu/requests.ts +9 -2
- package/cli/src/subcommands/menu/tests.ts +1 -1
- package/cli/src/subcommands/menu/tunnels.ts +10 -99
- package/cli/src/subcommands/menu/types.ts +8 -0
- package/cli/src/subcommands/menu.ts +32 -524
- package/cli/src/subcommands/signup.ts +2 -2
- package/cli/src/subcommands/system.ts +58 -36
- package/cli/src/subcommands/tunnel.ts +126 -33
- package/cli/src/templates/index.ts +3 -3
- package/cli/src/tui/App.tsx +202 -0
- package/cli/src/tui/AppInspector.tsx +114 -0
- package/cli/src/tui/HomeStatus.tsx +92 -0
- package/cli/src/tui/brand.tsx +20 -0
- package/cli/src/tui/format.ts +22 -0
- package/cli/src/tui/index.mts +6 -0
- package/cli/src/tui/liveTree.ts +40 -0
- package/cli/src/tui/package.json +3 -0
- package/cli/src/tui/runMenu.tsx +57 -0
- package/cli/src/tui/session.mts +267 -0
- package/cli/src/tui/snapshot.ts +175 -0
- package/cli/src/utils/api-base.ts +11 -0
- package/cli/src/utils/credentials.ts +58 -0
- package/cli/src/utils/domain-availability.ts +56 -0
- package/cli/src/utils/guest-access.ts +38 -0
- package/cli/src/utils/launchDomainking.ts +64 -0
- package/cli/src/utils/login-flow.ts +57 -0
- package/docs/AGENTS.md +130 -148
- package/docs/HOSTING.md +55 -0
- package/docs/MENU_STRUCTURE.md +60 -288
- package/docs/PRODUCT.md +64 -0
- package/docs/README.md +11 -7
- package/package.json +22 -36
- package/scripts/tunnel/client-improved.js +127 -38
- package/scripts/tunnel/client.js +118 -0
- package/assets/cli-screenshot.png +0 -0
package/docs/MENU_STRUCTURE.md
CHANGED
|
@@ -1,337 +1,109 @@
|
|
|
1
1
|
# Uplink CLI Menu Structure
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
> Last updated:
|
|
3
|
+
> Interactive menu hierarchy for `uplink` / `uplink menu`.
|
|
4
|
+
> Last updated: August 2026
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
## Overview
|
|
9
|
-
|
|
10
|
-
The Uplink CLI (`uplink menu`) provides an interactive terminal interface for managing tunnels, databases, and system administration. The menu adapts based on authentication status and user role.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Menu States
|
|
15
|
-
|
|
16
|
-
| State | Condition | Available Options |
|
|
17
|
-
|-------|-----------|-------------------|
|
|
18
|
-
| Unauthenticated | No `AGENTCLOUD_TOKEN` or invalid token | Get Started, Exit |
|
|
19
|
-
| User | Valid token with `role: user` | Tunnels, Exit |
|
|
20
|
-
| Admin | Valid token with `role: admin` | Tunnels, Usage (all tunnels/dbs), System Status, Manage Tokens, Stop All, Exit |
|
|
6
|
+
Agents should prefer non-interactive commands in [AGENTS.md](../AGENTS.md).
|
|
21
7
|
|
|
22
8
|
---
|
|
23
9
|
|
|
24
|
-
##
|
|
10
|
+
## Overview
|
|
25
11
|
|
|
26
|
-
|
|
12
|
+
The menu adapts by auth and role. Arrow keys + Enter (no numeric entry).
|
|
27
13
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
| State | Condition | Main options |
|
|
15
|
+
|-------|-----------|--------------|
|
|
16
|
+
| Guest | No / invalid token → guest access is created silently on menu open | Share, Check domain availability, Continue with email, About, Exit |
|
|
17
|
+
| Verified user | Email-verified token | Share, Hosting, Domains, About, Exit |
|
|
18
|
+
| Admin | `role: admin` | Same as user + Usage, System Status, Manage Tokens |
|
|
19
|
+
| Offline | API unreachable | Connection details, About, Exit |
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
→ Creates a user token via the API (`POST /v1/signup`)
|
|
34
|
-
→ Optionally saves `AGENTCLOUD_TOKEN` into your shell rc file
|
|
35
|
-
|
|
36
|
-
Exit
|
|
37
|
-
```
|
|
21
|
+
There is no separate "unauthenticated" menu: opening the menu without a usable token mints a guest token (1 active tunnel, 24-hour expiry) and shows the same Share menu everyone gets — including port scanning and tunnel management.
|
|
38
22
|
|
|
39
23
|
---
|
|
40
24
|
|
|
41
|
-
|
|
25
|
+
## Guest
|
|
42
26
|
|
|
43
27
|
```
|
|
44
28
|
UPLINK
|
|
45
29
|
● connected
|
|
46
|
-
├─ Active 2 tunnels
|
|
47
|
-
|
|
48
|
-
Manage Tunnels
|
|
49
|
-
├── Start Tunnel
|
|
50
|
-
│ └── [Port Selection]
|
|
51
|
-
│ ├── Port 3000 → Creates tunnel & starts client
|
|
52
|
-
│ ├── Port 8080 → Creates tunnel & starts client
|
|
53
|
-
│ ├── Enter custom port → Prompt → Creates tunnel
|
|
54
|
-
│ └── ← Back
|
|
55
|
-
│
|
|
56
|
-
├── Stop Tunnel
|
|
57
|
-
│ └── [Running Tunnels Selection]
|
|
58
|
-
│ ├── Port 3000 (abc123...) → Stops tunnel client
|
|
59
|
-
│ ├── Port 8080 (def456...) → Stops tunnel client
|
|
60
|
-
│ ├── Stop all tunnels → Stops all clients
|
|
61
|
-
│ └── ← Back
|
|
62
|
-
│
|
|
63
|
-
├── View Tunnel Stats
|
|
64
|
-
│ └── [Running Tunnel Selection]
|
|
65
|
-
│ ├── abc123... Port 3000
|
|
66
|
-
│ └── ← Back
|
|
67
|
-
│
|
|
68
|
-
│ → Displays:
|
|
69
|
-
│ - Permanent URL (if set)
|
|
70
|
-
│ - Connection status (verified via relay)
|
|
71
|
-
│ - Total stats (requests, bytes in/out)
|
|
72
|
-
│ - Current run stats
|
|
73
|
-
│
|
|
74
|
-
└── Active Tunnels
|
|
75
|
-
└── Displays table (only shows tunnels connected to relay):
|
|
76
|
-
Token Port Status Permanent URL
|
|
77
|
-
────────────────────────────────────────────────
|
|
78
|
-
abc123... 3000 connected myapp.uplink.spot
|
|
79
|
-
def456... 8080 connected -
|
|
80
|
-
|
|
81
|
-
Manage Aliases (Premium)
|
|
82
|
-
├── My Aliases
|
|
83
|
-
│ └── Displays table:
|
|
84
|
-
│ Alias Port Status
|
|
85
|
-
│ ────────────────────────────────
|
|
86
|
-
│ myapp 3000 active
|
|
87
|
-
│ api 8080 inactive
|
|
88
|
-
│
|
|
89
|
-
│ (active = tunnel running on that port)
|
|
90
|
-
│
|
|
91
|
-
├── Create Alias
|
|
92
|
-
│ └── [Port Selection]
|
|
93
|
-
│ ├── Port 3000 (tunnel running) → Prompt alias name
|
|
94
|
-
│ ├── Enter custom port → Prompt port → Prompt alias
|
|
95
|
-
│ └── ← Back
|
|
96
|
-
│
|
|
97
|
-
│ → Creates permanent URL at {alias}.uplink.spot
|
|
98
|
-
│ → Alias is port-based (persists across tunnel restarts)
|
|
99
|
-
│
|
|
100
|
-
├── Reassign Alias
|
|
101
|
-
│ └── [Alias Selection]
|
|
102
|
-
│ ├── myapp → Port 3000
|
|
103
|
-
│ └── ← Back
|
|
104
|
-
│
|
|
105
|
-
│ → Select new port for alias
|
|
106
|
-
│
|
|
107
|
-
└── Delete Alias
|
|
108
|
-
└── [Alias Selection]
|
|
109
|
-
├── myapp
|
|
110
|
-
└── ← Back
|
|
111
|
-
|
|
112
|
-
→ Removes permanent URL
|
|
113
30
|
|
|
31
|
+
Share → same full Share menu as verified users (no Aliases)
|
|
32
|
+
Check domain availability → Domainking TUI if bundled, else inline `domains check` (public DNS/RDAP)
|
|
33
|
+
Continue with email → preserve guest tunnel; unlock Hosting + Domains
|
|
34
|
+
About
|
|
114
35
|
Exit
|
|
115
36
|
```
|
|
116
37
|
|
|
117
|
-
> **Note:**
|
|
118
|
-
> - Database features are admin-only. Regular users do not see database options.
|
|
119
|
-
> - Aliases are port-based: they persist even when tunnels restart. The same alias always points to the same port.
|
|
120
|
-
> - "Active Tunnels" verifies connection status with the relay server (not just local processes).
|
|
121
|
-
|
|
122
38
|
---
|
|
123
39
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
Usage (admin-only)
|
|
128
|
-
├── List All Tunnels
|
|
129
|
-
│ └── Shows all tunnels across all users
|
|
130
|
-
│
|
|
131
|
-
└── List All Databases
|
|
132
|
-
└── Shows all databases across all users
|
|
133
|
-
|
|
134
|
-
System Status
|
|
135
|
-
├── View Status
|
|
136
|
-
│ └── Displays:
|
|
137
|
-
│ - API health
|
|
138
|
-
│ - Relay status (online/offline)
|
|
139
|
-
│ - Connected tunnels count
|
|
140
|
-
│ - Active databases count
|
|
141
|
-
│
|
|
142
|
-
├── View Connected Tunnels
|
|
143
|
-
│ └── Displays table:
|
|
144
|
-
│ Token Client IP Port Uptime Connected At
|
|
145
|
-
│ ─────────────────────────────────────────────────────────────
|
|
146
|
-
│ abc123... 192.168.1.5 3000 2h 15m 2024-12-31T10:00:00
|
|
147
|
-
│
|
|
148
|
-
└── View Traffic Stats
|
|
149
|
-
└── Displays table:
|
|
150
|
-
Alias Requests In Out Sts Last Seen
|
|
151
|
-
─────────────────────────────────────────────────────────────────────────
|
|
152
|
-
chat 1,234 45.2 MB 12.8 MB 200 2024-12-31...
|
|
153
|
-
|
|
154
|
-
Manage Tokens
|
|
155
|
-
├── List Tokens
|
|
156
|
-
│ └── Displays table:
|
|
157
|
-
│ ID Prefix Role Label Created
|
|
158
|
-
│ ──────────────────────────────────────────────────────────────────────
|
|
159
|
-
│ tok_abc... sk-abc... admin Production 2024-12-01...
|
|
160
|
-
│
|
|
161
|
-
├── Create Token
|
|
162
|
-
│ ├── Prompt: "Role (admin/user, default user):"
|
|
163
|
-
│ ├── Prompt: "Label (optional):"
|
|
164
|
-
│ ├── Prompt: "Expires in days (optional):"
|
|
165
|
-
│ └── Displays created token (save immediately!)
|
|
166
|
-
│
|
|
167
|
-
└── Revoke Token
|
|
168
|
-
├── Prompt: "Token ID to revoke:"
|
|
169
|
-
└── Confirms revocation
|
|
170
|
-
|
|
171
|
-
⚠️ Stop All Tunnel Clients
|
|
172
|
-
└── Emergency kill switch for all local tunnel processes
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## Result Displays
|
|
178
|
-
|
|
179
|
-
### Tunnel Created Successfully
|
|
180
|
-
|
|
181
|
-
```
|
|
182
|
-
✓ Tunnel created and client started
|
|
183
|
-
|
|
184
|
-
→ Public URL https://abc123.x.uplink.spot
|
|
185
|
-
→ Token abc123
|
|
186
|
-
→ Local port 3000
|
|
40
|
+
## Authenticated — Share
|
|
187
41
|
|
|
188
|
-
|
|
189
|
-
Use "Stop Tunnel" to disconnect.
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Alias Created
|
|
193
|
-
|
|
194
|
-
```
|
|
195
|
-
✓ Alias created
|
|
42
|
+
Creates tunnels **and** starts the local client (same as `uplink tunnel create`).
|
|
196
43
|
|
|
197
|
-
→ Alias my-app
|
|
198
|
-
→ Port 3000
|
|
199
|
-
→ URL https://my-app.uplink.spot
|
|
200
|
-
|
|
201
|
-
Your tunnel will now be accessible at this permanent URL.
|
|
202
|
-
Alias is port-based - it will persist across tunnel restarts.
|
|
203
44
|
```
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
45
|
+
Share
|
|
46
|
+
├── Start tunnel → scan ports / enter port → create + start client
|
|
47
|
+
├── Stop tunnel → kill local client + delete API record
|
|
48
|
+
├── View tunnel stats
|
|
49
|
+
├── Active tunnels → connected tunnels table
|
|
50
|
+
└── Aliases → list / create permanent URLs (premium)
|
|
207
51
|
```
|
|
208
|
-
❌ Permanent URLs are a premium feature
|
|
209
52
|
|
|
210
|
-
|
|
211
|
-
```
|
|
53
|
+
Admins also get **Stop ALL Tunnel Clients** under Share.
|
|
212
54
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
```
|
|
216
|
-
❌ URL limit reached
|
|
217
|
-
|
|
218
|
-
You've reached your URL limit. Contact us to increase it.
|
|
219
|
-
```
|
|
55
|
+
---
|
|
220
56
|
|
|
221
|
-
|
|
57
|
+
## Authenticated — Hosting
|
|
222
58
|
|
|
223
59
|
```
|
|
224
|
-
|
|
60
|
+
Hosting
|
|
61
|
+
├── Setup wizard → analyze + create + deploy
|
|
62
|
+
├── Deploy → deploy to existing app
|
|
63
|
+
├── List apps
|
|
64
|
+
├── Analyze project
|
|
65
|
+
├── Delete app
|
|
66
|
+
└── (Apps subtree may show live apps + logs in the Ink TUI)
|
|
225
67
|
```
|
|
226
68
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
## Navigation Controls
|
|
230
|
-
|
|
231
|
-
| Key | Action |
|
|
232
|
-
|-----|--------|
|
|
233
|
-
| `↑` / `↓` | Navigate menu items |
|
|
234
|
-
| `Enter` | Select item |
|
|
235
|
-
| `←` | Go back to parent menu |
|
|
236
|
-
| `Ctrl+C` | Exit immediately |
|
|
237
|
-
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
## Environment Variables
|
|
241
|
-
|
|
242
|
-
| Variable | Description | Default |
|
|
243
|
-
|----------|-------------|---------|
|
|
244
|
-
| `AGENTCLOUD_TOKEN` | API authentication token | (required) |
|
|
245
|
-
| `AGENTCLOUD_API_BASE` | API base URL | `https://api.uplink.spot` |
|
|
246
|
-
| `TUNNEL_CTRL` | Tunnel relay control endpoint | `tunnel.uplink.spot:7071` |
|
|
247
|
-
| `TUNNEL_DOMAIN` | Tunnel URL domain | `x.uplink.spot` |
|
|
248
|
-
| `RELAY_HEALTH_URL` | Optional: show API/relay banner in menu | (unset) |
|
|
69
|
+
CLI equivalents: `uplink host setup|deploy|list|status|logs|delete|analyze|preflight`.
|
|
249
70
|
|
|
250
71
|
---
|
|
251
72
|
|
|
252
|
-
##
|
|
253
|
-
|
|
254
|
-
### Current Structure Rationale
|
|
255
|
-
|
|
256
|
-
**Regular users** see a focused menu:
|
|
257
|
-
- All tunnel operations in one place ("Manage Tunnels")
|
|
258
|
-
- "My Tunnels" listing included in the same menu
|
|
259
|
-
- No database options (admin feature only)
|
|
260
|
-
|
|
261
|
-
**Admin users** get additional sections:
|
|
262
|
-
- "Usage" for cross-user visibility (all tunnels, all databases)
|
|
263
|
-
- "System Status" for monitoring
|
|
264
|
-
- "Manage Tokens" for access control
|
|
265
|
-
- Emergency kill switch
|
|
266
|
-
|
|
267
|
-
### Future Improvements
|
|
268
|
-
|
|
269
|
-
Consider consolidating admin sections:
|
|
73
|
+
## Authenticated — Domains
|
|
270
74
|
|
|
271
75
|
```
|
|
272
|
-
|
|
273
|
-
├──
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
├──
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
│ ├── List / Create / Revoke
|
|
282
|
-
└── Stop All Clients
|
|
76
|
+
Domains
|
|
77
|
+
├── My domains → uplink domains list
|
|
78
|
+
├── Connect registrar → providers connect (token via env)
|
|
79
|
+
├── Check availability → domains check
|
|
80
|
+
├── Attach to app → host domains add
|
|
81
|
+
├── Verify → host domains verify
|
|
82
|
+
├── List attached → host domains list
|
|
83
|
+
├── Detach → host domains remove
|
|
84
|
+
└── Search (optional TUI) → Domainking if DOMAINKING_ENTRY / sibling repo exists
|
|
283
85
|
```
|
|
284
86
|
|
|
285
|
-
|
|
87
|
+
Bare `uplink domains` opens the search TUI when available; otherwise it prints agent-friendly command hints.
|
|
286
88
|
|
|
287
89
|
---
|
|
288
90
|
|
|
289
|
-
##
|
|
290
|
-
|
|
291
|
-
This section is a **single source of truth** for how the interactive menu is implemented and how it should evolve. It intentionally stays high-level and avoids security-sensitive details.
|
|
292
|
-
|
|
293
|
-
### Goals
|
|
294
|
-
- **Deterministic**: UI output is a function of state (no hidden UI state).
|
|
295
|
-
- **Maintainable**: Separate **rendering**, **input/events**, and **side-effects** (API calls, spawning clients).
|
|
296
|
-
- **Safe defaults**: Avoid leaking secrets; avoid printing raw tokens except in the explicit signup/token-creation flows.
|
|
297
|
-
|
|
298
|
-
### Proposed refactor shape (Textual-inspired, Node/TS)
|
|
299
|
-
|
|
300
|
-
Current `cli/src/subcommands/menu.ts` mixes rendering + input handling + actions in one file. The refactor splits into a tiny internal “menu framework”:
|
|
301
|
-
|
|
302
|
-
- `cli/src/subcommands/menu/state.ts`
|
|
303
|
-
- Exports `MenuState`, `MenuRole`, `MenuAuthStatus`
|
|
304
|
-
- Single state object drives all rendering
|
|
305
|
-
- `cli/src/subcommands/menu/events.ts`
|
|
306
|
-
- Exports `MenuEvent` (key presses, navigation, action results)
|
|
307
|
-
- `cli/src/subcommands/menu/reducer.ts`
|
|
308
|
-
- Pure reducer: `(state, event) => { state, effect? }`
|
|
309
|
-
- `cli/src/subcommands/menu/effects.ts`
|
|
310
|
-
- Side-effects runner (API calls, spawn/kill tunnel clients)
|
|
311
|
-
- Dispatches `MenuEvent` results back into the reducer
|
|
312
|
-
- `cli/src/subcommands/menu/render.ts`
|
|
313
|
-
- `render(state): string[]` (or a single string) composing widget renderers
|
|
314
|
-
- `cli/src/subcommands/menu/widgets.ts`
|
|
315
|
-
- Small, testable “views”: header, breadcrumbs, menu list, message area, footer, active tunnel panel
|
|
316
|
-
- `cli/src/subcommands/menu/menu-tree.ts`
|
|
317
|
-
- Build `MenuChoice[]` based on auth status + role (unauth/user/admin)
|
|
91
|
+
## Admin extras
|
|
318
92
|
|
|
319
|
-
|
|
320
|
-
-
|
|
321
|
-
-
|
|
322
|
-
- `cli/src/subcommands/menu/inline-select.ts` (arrow-key selector)
|
|
323
|
-
- `cli/src/subcommands/menu/requests.ts` (unauthenticated API requests)
|
|
93
|
+
- **Usage** — cross-user tunnels / databases visibility
|
|
94
|
+
- **System Status** — API health + stats (+ smoke where configured)
|
|
95
|
+
- **Manage Tokens** — create / list / revoke
|
|
324
96
|
|
|
325
|
-
|
|
326
|
-
1. Remove duplicate palette + selector from `menu.ts` and use `menu/colors.ts`, `menu/io.ts`, `menu/inline-select.ts`.
|
|
327
|
-
2. Extract a pure `render(state)` and keep current behavior.
|
|
328
|
-
3. Introduce `MenuState` and move mutable globals into state.
|
|
329
|
-
4. Introduce `MenuEvent` + reducer loop (keypress → event → state update → render).
|
|
330
|
-
5. Move actions (API/spawn) into `effects.ts` and keep render side-effect free.
|
|
97
|
+
CLI: `uplink admin status|tunnels|databases|tokens …`
|
|
331
98
|
|
|
332
99
|
---
|
|
333
100
|
|
|
334
|
-
##
|
|
101
|
+
## Environment
|
|
335
102
|
|
|
336
|
-
|
|
337
|
-
|
|
103
|
+
| Variable | Purpose | Default |
|
|
104
|
+
|----------|---------|---------|
|
|
105
|
+
| `AGENTCLOUD_TOKEN` | Auth bearer | — |
|
|
106
|
+
| `AGENTCLOUD_API_BASE` | API host | `https://api.uplink.spot` |
|
|
107
|
+
| `TUNNEL_CTRL` | Relay | `tunnel.uplink.spot:7071` |
|
|
108
|
+
| `TUNNEL_DOMAIN` | Tunnel DNS suffix | `x.uplink.spot` |
|
|
109
|
+
| `DOMAINKING_ENTRY` | Optional search TUI entry | — |
|
package/docs/PRODUCT.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Uplink
|
|
2
|
+
|
|
3
|
+
**Software for agents** — share localhost, host apps, and attach domains from the terminal. No dashboard required.
|
|
4
|
+
|
|
5
|
+
Website: [uplink.spot](https://uplink.spot) · CLI: [`uplink-cli`](https://www.npmjs.com/package/uplink-cli) · Agents: [AGENTS.md](../AGENTS.md)
|
|
6
|
+
|
|
7
|
+
## What it is
|
|
8
|
+
|
|
9
|
+
Three surfaces, one CLI (`uplink`):
|
|
10
|
+
|
|
11
|
+
1. **Share** — expose `localhost:<port>` as HTTPS (`https://<token>.x.uplink.spot`).
|
|
12
|
+
2. **Hosting** — deploy a project to `https://<app_id>.host.uplink.spot` (email-verified accounts).
|
|
13
|
+
3. **Domains** — check availability, list registrar inventory, attach a hostname to a hosted app.
|
|
14
|
+
|
|
15
|
+
Humans use `uplink` (keyboard menu). Agents use subcommands with `--json` and `--token-stdin`.
|
|
16
|
+
|
|
17
|
+
## Accounts
|
|
18
|
+
|
|
19
|
+
| Kind | How you get it | Can do | Cannot do |
|
|
20
|
+
|------|----------------|--------|-----------|
|
|
21
|
+
| **Guest** | Automatic on `tunnel create` or menu open | 1 tunnel (24h), public `domains check` | Hosting, databases, aliases, custom domains |
|
|
22
|
+
| **Verified** | `uplink login --email` then OTP | Guest plus hosting / DBs / registrars | Plan-gated extras (aliases, custom domains) |
|
|
23
|
+
| **Admin** | Operator token in the control plane | Everything + Usage / System Status / Manage Tokens | — |
|
|
24
|
+
|
|
25
|
+
Guest → verified **merges**: the existing tunnel stays; credentials land in `~/.uplink/credentials` (mode 600). Gate error for locked features: `ACCOUNT_VERIFICATION_REQUIRED`.
|
|
26
|
+
|
|
27
|
+
## URLs
|
|
28
|
+
|
|
29
|
+
| Kind | Format |
|
|
30
|
+
|------|--------|
|
|
31
|
+
| Tunnel | `https://<token>.x.uplink.spot` |
|
|
32
|
+
| Alias (plan) | `https://<alias>.uplink.spot` |
|
|
33
|
+
| Hosted app | `https://<app_id>.host.uplink.spot` |
|
|
34
|
+
| Custom domain | hostname attached + verified on an app |
|
|
35
|
+
|
|
36
|
+
Reserved alias labels include `www`, `api`, `x`, `host`, `docs`, `status`.
|
|
37
|
+
|
|
38
|
+
## Architecture (high level)
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
localhost --tunnel client--> relay (*.x.uplink.spot)
|
|
42
|
+
control plane API (api.uplink.spot)
|
|
43
|
+
hosted app --container------> runner + router (*.host.uplink.spot)
|
|
44
|
+
Caddy terminates TLS (Cloudflare DNS-01 wildcards).
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The CLI repo is public. The control plane, builder, runner, router, and relay live in a private runtime repo.
|
|
48
|
+
|
|
49
|
+
## Hosting behavior
|
|
50
|
+
|
|
51
|
+
Free apps **sleep after 30 minutes idle**. A request wakes them (first hit is slower). See [HOSTING.md](./HOSTING.md).
|
|
52
|
+
|
|
53
|
+
## vs a typical tunnel SaaS
|
|
54
|
+
|
|
55
|
+
| | Uplink | Typical tunnel dashboard |
|
|
56
|
+
|--|--------|--------------------------|
|
|
57
|
+
| Signup to share localhost | Guest token, no email | Account + browser |
|
|
58
|
+
| Agent install | `npx uplink-cli` + `--json` | Scraping a UI |
|
|
59
|
+
| Hosting | Same CLI | Separate product |
|
|
60
|
+
| Custom domains | Attach to a hosted app | Often a paid add-on |
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
CLI: MIT. Runtime: private.
|
package/docs/README.md
CHANGED
|
@@ -3,19 +3,23 @@
|
|
|
3
3
|
## Quick Start
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
#
|
|
7
|
-
npm install -g uplink
|
|
8
|
-
|
|
9
|
-
#
|
|
10
|
-
uplink menu
|
|
6
|
+
# 0.2.0 (guest login, public domain check) — GitHub tag until npm org auth lands
|
|
7
|
+
npm install -g github:firstprinciplecode/uplink#v0.2.0
|
|
8
|
+
uplink menu # interactive
|
|
9
|
+
uplink --help # commands
|
|
11
10
|
```
|
|
12
11
|
|
|
13
12
|
## Documentation
|
|
14
13
|
|
|
15
|
-
- **[AGENTS.md](
|
|
16
|
-
- **[
|
|
14
|
+
- **[AGENTS.md](../AGENTS.md)** (also mirrored here) — programmatic CLI for AI agents
|
|
15
|
+
- **[PRODUCT.md](./PRODUCT.md)** — what Uplink is, account types, URLs
|
|
16
|
+
- **[HOSTING.md](./HOSTING.md)** — deploy, quotas, sleep/wake
|
|
17
|
+
- **[MENU_STRUCTURE.md](./MENU_STRUCTURE.md)** — interactive menu reference
|
|
18
|
+
- **[CHANGELOG.md](../CHANGELOG.md)** — releases
|
|
17
19
|
|
|
18
20
|
## Links
|
|
19
21
|
|
|
20
22
|
- Website: [uplink.spot](https://uplink.spot)
|
|
23
|
+
- npm: [uplink-cli](https://www.npmjs.com/package/uplink-cli) (0.1.39 until 0.2.0 publishes)
|
|
24
|
+
- Source: [github.com/firstprinciplecode/uplink](https://github.com/firstprinciplecode/uplink)
|
|
21
25
|
- API: `https://api.uplink.spot`
|
package/package.json
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uplink-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Software for agents — share localhost, host apps, and attach domains from the terminal. JSON-first CLI for Cursor, Claude, Codex, and Windsurf.",
|
|
5
5
|
"keywords": [
|
|
6
|
+
"ai-agents",
|
|
7
|
+
"agents",
|
|
8
|
+
"cursor",
|
|
9
|
+
"claude-code",
|
|
6
10
|
"tunnel",
|
|
7
11
|
"localhost",
|
|
8
|
-
"
|
|
9
|
-
"ngrok-alternative",
|
|
10
|
-
"expose",
|
|
12
|
+
"hosting",
|
|
11
13
|
"cli",
|
|
12
14
|
"dev-tools",
|
|
13
|
-
"webhook",
|
|
14
15
|
"public-url",
|
|
15
|
-
"port-forwarding",
|
|
16
|
-
"reverse-proxy",
|
|
17
|
-
"tunneling",
|
|
18
|
-
"local-development",
|
|
19
16
|
"https-tunnel",
|
|
20
|
-
"custom-domain"
|
|
17
|
+
"custom-domain",
|
|
18
|
+
"agent-cli"
|
|
21
19
|
],
|
|
22
20
|
"homepage": "https://uplink.spot",
|
|
23
21
|
"repository": {
|
|
@@ -38,45 +36,33 @@
|
|
|
38
36
|
"files": [
|
|
39
37
|
"cli/",
|
|
40
38
|
"scripts/tunnel/client-improved.js",
|
|
39
|
+
"scripts/tunnel/client.js",
|
|
41
40
|
"README.md",
|
|
42
|
-
"
|
|
41
|
+
"LICENSE",
|
|
42
|
+
"AGENTS.md",
|
|
43
43
|
"docs/README.md",
|
|
44
44
|
"docs/AGENTS.md",
|
|
45
|
-
"docs/MENU_STRUCTURE.md"
|
|
45
|
+
"docs/MENU_STRUCTURE.md",
|
|
46
|
+
"docs/HOSTING.md",
|
|
47
|
+
"docs/PRODUCT.md",
|
|
48
|
+
"CHANGELOG.md"
|
|
46
49
|
],
|
|
47
50
|
"scripts": {
|
|
48
|
-
"dev:relay": "node scripts/tunnel/relay.js",
|
|
49
|
-
"dev:stub": "PORT=4100 AGENTCLOUD_TOKEN_DEV=dev-token node scripts/dev/stub-control-plane.js",
|
|
50
51
|
"dev:cli": "tsx cli/src/index.ts",
|
|
51
|
-
"
|
|
52
|
-
"smoke:db": "bash scripts/db-api-smoke.sh",
|
|
53
|
-
"smoke:all": "bash scripts/smoke-all.sh",
|
|
54
|
-
"test:features": "bash scripts/test-new-features.sh",
|
|
55
|
-
"test:comprehensive": "bash scripts/test-comprehensive.sh"
|
|
52
|
+
"pack:check": "npm pack --dry-run"
|
|
56
53
|
},
|
|
57
54
|
"dependencies": {
|
|
58
|
-
"@sendgrid/mail": "^8.1.6",
|
|
59
|
-
"better-sqlite3": "^11.10.0",
|
|
60
|
-
"body-parser": "^1.20.3",
|
|
61
55
|
"commander": "^12.1.0",
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"express": "^4.19.2",
|
|
65
|
-
"express-rate-limit": "^8.2.1",
|
|
66
|
-
"helmet": "^8.1.0",
|
|
56
|
+
"ink": "^6.8.0",
|
|
57
|
+
"ink-text-input": "^6.0.0",
|
|
67
58
|
"node-fetch": "^2.7.0",
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"pino-pretty": "^13.1.3",
|
|
71
|
-
"tsx": "^4.21.0",
|
|
72
|
-
"zod": "^4.2.1"
|
|
59
|
+
"react": "^19.2.8",
|
|
60
|
+
"tsx": "^4.21.0"
|
|
73
61
|
},
|
|
74
62
|
"devDependencies": {
|
|
75
|
-
"@types/compression": "^1.7.5",
|
|
76
|
-
"@types/express": "^4.17.21",
|
|
77
|
-
"@types/express-rate-limit": "^5.1.3",
|
|
78
63
|
"@types/node": "^22.7.4",
|
|
79
64
|
"@types/node-fetch": "^2.6.11",
|
|
65
|
+
"@types/react": "^19.2.18",
|
|
80
66
|
"typescript": "^5.6.2"
|
|
81
67
|
}
|
|
82
68
|
}
|