Skip to content

Commit 1fc9f33

Browse files
Merge branch 'improve-desktop-onboarding-flow-swvs'
2 parents 2995991 + d755a7f commit 1fc9f33

34 files changed

Lines changed: 1483 additions & 403 deletions

CLAUDE.md

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Settings are stored in `.vibora/settings.json`. The vibora directory is resolved
123123
| Setting | Env Var | Default |
124124
|---------|---------|---------|
125125
| (base directory) | `VIBORA_DIR` | .vibora in CWD or ~/.vibora |
126-
| port | `PORT` | 3333 |
126+
| port | `PORT` | 7777 |
127127
| defaultGitReposDir | `VIBORA_GIT_REPOS_DIR` | ~ |
128128
| linearApiKey | `LINEAR_API_KEY` | null |
129129

@@ -226,19 +226,13 @@ mise run build:debug # Web build with debug logging
226226

227227
### Development vs Production
228228

229-
The `mise run dev` command defaults to `~/.vibora/dev` (port 3222) to keep development data separate from production:
229+
The `mise run dev` command requires explicit `PORT` and `VIBORA_DIR` environment variables to avoid accidentally running against production data:
230230

231231
```bash
232-
# Development (uses ~/.vibora/dev with port 3222)
233-
mise run dev
232+
# Development (explicitly set port and directory)
233+
PORT=3222 VIBORA_DIR=~/.vibora/dev mise run dev
234234

235-
# Development with custom port
236-
mise run dev 3333
237-
238-
# Development with custom directory
239-
mise run dev 3333 ~/.vibora/custom
240-
241-
# Production (uses ~/.vibora with port 3333)
235+
# Production (uses ~/.vibora with port 7777)
242236
mise run start
243237
```
244238

DEVELOPMENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mise install
1515
mise run dev
1616

1717
# Or run separately:
18-
mise run server # Backend (port 3333, with auto-reload)
18+
mise run server # Backend (uses PORT env var, with auto-reload)
1919
mise run client # Frontend (port 5173, proxies to backend)
2020
```
2121

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ claude plugin marketplace add knowsuchagency/vibora
5656
claude plugin install vibora@vibora --scope user
5757
```
5858

59-
Open http://localhost:3333 in your browser.
59+
Open http://localhost:7777 in your browser.
6060

6161
### Remote Server Setup
6262

@@ -76,11 +76,11 @@ Run the backend on a remote server and connect from the desktop app or browser:
7676
2. **Connect from desktop app:**
7777
- Launch the app
7878
- Click "Connect to Remote" (if local server not found)
79-
- Enter the server URL: `your-server.example.com:3333`
79+
- Enter the server URL: `your-server.example.com:7777`
8080
- Enter credentials when prompted
8181

8282
3. **Or access via browser:**
83-
Open `http://your-server.example.com:3333`
83+
Open `http://your-server.example.com:7777`
8484

8585
### Server Commands (Web Application)
8686

@@ -100,7 +100,7 @@ Settings are stored in `.vibora/settings.json`. The vibora directory is resolved
100100

101101
| Setting | Env Var | Default |
102102
|---------|---------|---------|
103-
| port | `PORT` | 3333 |
103+
| port | `PORT` | 7777 |
104104
| defaultGitReposDir | `VIBORA_GIT_REPOS_DIR` | ~ |
105105
| remoteHost | `VIBORA_REMOTE_HOST` | (empty) |
106106
| sshPort | `VIBORA_SSH_PORT` | 22 |
@@ -212,7 +212,7 @@ vibora notify <title> [message] # Send a notification to all enabled channels
212212
### Global Options
213213

214214
```bash
215-
--port=<port> # Server port (default: 3333)
215+
--port=<port> # Server port (default: 7777)
216216
--url=<url> # Override full server URL
217217
--pretty # Pretty-print JSON output
218218
```

cli/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ Commands:
125125
dev status Check if developer mode is enabled
126126
127127
Global Options:
128-
--port=<port> Server port (default: 3333)
128+
--port=<port> Server port (default: 7777)
129129
--url=<url> Override full server URL
130130
--pretty Pretty-print JSON output
131131
--version Show version

cli/src/utils/process.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,5 @@ export function getPort(portOverride?: string): number {
8181
if (!isNaN(port)) return port
8282
}
8383

84-
return 3333
84+
return 7777
8585
}

cli/src/utils/server.ts

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,58 @@ import { existsSync, readFileSync } from 'node:fs'
22
import { join } from 'node:path'
33
import { homedir } from 'node:os'
44

5+
// Settings interface supporting both nested (v2) and flat (legacy) formats
56
interface Settings {
7+
_schemaVersion?: number
8+
// Nested format (v2)
9+
server?: { port?: number }
10+
authentication?: { username?: string | null; password?: string | null }
11+
// Legacy flat format
612
port?: number
713
basicAuthUsername?: string
814
basicAuthPassword?: string
915
}
1016

17+
const DEFAULT_PORT = 7777
18+
19+
/**
20+
* Get port from settings (supports nested and flat formats)
21+
*/
22+
function getPortFromSettings(settings: Settings | null): number | null {
23+
if (!settings) return null
24+
// Try nested format first (v2)
25+
if (settings.server?.port) {
26+
return settings.server.port
27+
}
28+
// Fall back to flat format (legacy)
29+
if (settings.port) {
30+
return settings.port
31+
}
32+
return null
33+
}
34+
35+
/**
36+
* Get auth credentials from settings (supports nested and flat formats)
37+
*/
38+
function getAuthFromSettings(settings: Settings | null): { username: string; password: string } | null {
39+
if (!settings) return null
40+
// Try nested format first (v2)
41+
if (settings.authentication?.username && settings.authentication?.password) {
42+
return {
43+
username: settings.authentication.username,
44+
password: settings.authentication.password,
45+
}
46+
}
47+
// Fall back to flat format (legacy)
48+
if (settings.basicAuthUsername && settings.basicAuthPassword) {
49+
return {
50+
username: settings.basicAuthUsername,
51+
password: settings.basicAuthPassword,
52+
}
53+
}
54+
return null
55+
}
56+
1157
function expandPath(p: string): string {
1258
if (p.startsWith('~/')) {
1359
return join(homedir(), p.slice(2))
@@ -36,7 +82,7 @@ function readSettingsFile(path: string): Settings | null {
3682
* 4. VIBORA_DIR settings.json (read port)
3783
* 5. .vibora/settings.json in CWD (read port)
3884
* 6. ~/.vibora/settings.json (read port)
39-
* 7. Default: http://localhost:3333
85+
* 7. Default: http://localhost:7777
4086
*/
4187
export function discoverServerUrl(urlOverride?: string, portOverride?: string): string {
4288
// 1. Explicit URL override
@@ -58,27 +104,30 @@ export function discoverServerUrl(urlOverride?: string, portOverride?: string):
58104
if (process.env.VIBORA_DIR) {
59105
const viboraDirSettings = join(expandPath(process.env.VIBORA_DIR), 'settings.json')
60106
const settings = readSettingsFile(viboraDirSettings)
61-
if (settings?.port) {
62-
return `http://localhost:${settings.port}`
107+
const port = getPortFromSettings(settings)
108+
if (port) {
109+
return `http://localhost:${port}`
63110
}
64111
}
65112

66113
// 5. Local .vibora/settings.json
67114
const cwdSettings = join(process.cwd(), '.vibora', 'settings.json')
68115
const localSettings = readSettingsFile(cwdSettings)
69-
if (localSettings?.port) {
70-
return `http://localhost:${localSettings.port}`
116+
const localPort = getPortFromSettings(localSettings)
117+
if (localPort) {
118+
return `http://localhost:${localPort}`
71119
}
72120

73121
// 6. Global ~/.vibora/settings.json
74122
const globalSettings = join(homedir(), '.vibora', 'settings.json')
75123
const homeSettings = readSettingsFile(globalSettings)
76-
if (homeSettings?.port) {
77-
return `http://localhost:${homeSettings.port}`
124+
const homePort = getPortFromSettings(homeSettings)
125+
if (homePort) {
126+
return `http://localhost:${homePort}`
78127
}
79128

80129
// 7. Default
81-
return 'http://localhost:3333'
130+
return `http://localhost:${DEFAULT_PORT}`
82131
}
83132

84133
/**
@@ -101,6 +150,7 @@ export function getViboraDir(): string {
101150

102151
/**
103152
* Gets auth credentials from settings.json.
153+
* Supports both nested (v2) and flat (legacy) formats.
104154
* Priority: VIBORA_DIR → CWD .vibora → ~/.vibora
105155
* Returns null if no credentials are configured.
106156
*/
@@ -113,11 +163,9 @@ export function getAuthCredentials(): { username: string; password: string } | n
113163

114164
for (const path of settingsPaths) {
115165
const settings = readSettingsFile(path)
116-
if (settings?.basicAuthUsername && settings?.basicAuthPassword) {
117-
return {
118-
username: settings.basicAuthUsername,
119-
password: settings.basicAuthPassword,
120-
}
166+
const auth = getAuthFromSettings(settings)
167+
if (auth) {
168+
return auth
121169
}
122170
}
123171

desktop/README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,12 @@ Desktop-specific settings are saved to `~/.vibora/settings.json`:
6060

6161
```json
6262
{
63-
"port": 3333,
64-
"remoteHost": "my-server.tailnet.ts.net",
65-
"remotePort": 3333,
63+
"_schemaVersion": 2,
64+
"server": { "port": 7777 },
65+
"remoteVibora": {
66+
"host": "my-server.tailnet.ts.net",
67+
"port": 7777
68+
},
6669
"lastConnectedHost": "my-server.tailnet.ts.net"
6770
}
6871
```
@@ -157,12 +160,14 @@ To use the desktop app with a remote Vibora server:
157160

158161
2. **Ensure the server is accessible**:
159162
- Via Tailscale: Use your machine's Tailscale hostname (e.g., `my-server.tailnet.ts.net`)
160-
- Via direct IP: Ensure port 3333 (or your configured port) is accessible
163+
- Via direct IP: Ensure port 7777 (or your configured port) is accessible
161164

162165
3. **Configure the remote host** in your local `~/.vibora/settings.json`:
163166
```json
164167
{
165-
"remoteHost": "my-server.tailnet.ts.net"
168+
"remoteVibora": {
169+
"host": "my-server.tailnet.ts.net"
170+
}
166171
}
167172
```
168173

desktop/resources/index.html

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@
150150
margin-top: 8px;
151151
}
152152

153+
.button-group.vertical {
154+
flex-direction: column;
155+
gap: 12px;
156+
}
157+
153158
.primary-btn, .secondary-btn, .retry-btn {
154159
flex: 1;
155160
padding: 10px 16px;
@@ -161,6 +166,38 @@
161166
border: none;
162167
}
163168

169+
.primary-btn.large, .secondary-btn.large {
170+
display: flex;
171+
align-items: center;
172+
gap: 16px;
173+
padding: 16px 20px;
174+
border-radius: 10px;
175+
text-align: left;
176+
}
177+
178+
.btn-icon {
179+
font-size: 24px;
180+
flex-shrink: 0;
181+
}
182+
183+
.btn-content {
184+
display: flex;
185+
flex-direction: column;
186+
gap: 4px;
187+
}
188+
189+
.btn-title {
190+
font-size: 15px;
191+
font-weight: 600;
192+
color: inherit;
193+
}
194+
195+
.btn-desc {
196+
font-size: 12px;
197+
opacity: 0.7;
198+
font-weight: 400;
199+
}
200+
164201
.primary-btn {
165202
background: #3b82f6;
166203
color: white;

0 commit comments

Comments
 (0)