vibelet 1.2.92 → 1.2.96

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.
@@ -1,2 +1,2 @@
1
- var c=require("node:fs"),n=require("node:path"),p="@vibelet/cli";function i(r){try{let e=JSON.parse((0,c.readFileSync)(r,"utf8"));if(e.name===p&&typeof e.version=="string"&&e.version.length>0)return e.version}catch{}return null}function l(){return"1.2.92"}var a=l();process.stdout.write(`${a}
1
+ var c=require("node:fs"),n=require("node:path"),p="@vibelet/cli";function i(r){try{let e=JSON.parse((0,c.readFileSync)(r,"utf8"));if(e.name===p&&typeof e.version=="string"&&e.version.length>0)return e.version}catch{}return null}function l(){return"1.2.96"}var a=l();process.stdout.write(`${a}
2
2
  `);
package/dist/vibelet.mjs CHANGED
@@ -12862,10 +12862,12 @@ async function runManagedNativeTerminal({
12862
12862
 
12863
12863
  /* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
12864
12864
  /* harmony export */ AW: () => (/* binding */ readNpmConfigFlag),
12865
+ /* harmony export */ NT: () => (/* binding */ hasLegacyAccessArgs),
12865
12866
  /* harmony export */ PC: () => (/* binding */ consumeFlag),
12866
- /* harmony export */ nE: () => (/* binding */ parseNamedArg)
12867
+ /* harmony export */ nE: () => (/* binding */ parseNamedArg),
12868
+ /* harmony export */ tY: () => (/* binding */ parseAccessTargetArg)
12867
12869
  /* harmony export */ });
12868
- /* unused harmony export readNpmConfigArg */
12870
+ /* unused harmony exports readNpmConfigArg, parseAccessValue */
12869
12871
  function consumeFlag(argv, name) {
12870
12872
  const idx = argv.indexOf(`--${name}`);
12871
12873
  if (idx === -1) return false;
@@ -12883,6 +12885,14 @@ function readNpmConfigArg(name, env = process.env) {
12883
12885
  return typeof value === 'string' ? value : null;
12884
12886
  }
12885
12887
 
12888
+ function hasArg(argv, name) {
12889
+ return argv.includes(`--${name}`) || argv.some((arg) => arg.startsWith(`--${name}=`));
12890
+ }
12891
+
12892
+ function hasNpmConfigArg(name, env = process.env) {
12893
+ return typeof env[`npm_config_${name.replace(/-/g, '_')}`] === 'string';
12894
+ }
12895
+
12886
12896
  function parseNamedArg(argv, name, errorHint, fail, env = process.env) {
12887
12897
  const inlinePrefix = `--${name}=`;
12888
12898
  const inlineArg = argv.find((arg) => arg.startsWith(inlinePrefix));
@@ -12905,6 +12915,120 @@ function parseNamedArg(argv, name, errorHint, fail, env = process.env) {
12905
12915
  return readNpmConfigArg(name, env);
12906
12916
  }
12907
12917
 
12918
+ function hasLegacyAccessArgs(argv, env = process.env) {
12919
+ return (
12920
+ hasArg(argv, 'local') ||
12921
+ hasArg(argv, 'remote') ||
12922
+ hasArg(argv, 'tunnel') ||
12923
+ hasArg(argv, 'relay') ||
12924
+ hasArg(argv, 'host') ||
12925
+ hasArg(argv, 'fallback-hosts') ||
12926
+ readNpmConfigFlag('local', env) ||
12927
+ readNpmConfigFlag('remote', env) ||
12928
+ readNpmConfigFlag('tunnel', env) ||
12929
+ hasNpmConfigArg('relay', env) ||
12930
+ hasNpmConfigArg('host', env) ||
12931
+ hasNpmConfigArg('fallback-hosts', env)
12932
+ );
12933
+ }
12934
+
12935
+ function normalizeAccessHost(host) {
12936
+ return String(host ?? '')
12937
+ .trim()
12938
+ .replace(/\.$/, '')
12939
+ .toLowerCase();
12940
+ }
12941
+
12942
+ function isIpv4Host(host) {
12943
+ const parts = host.split('.');
12944
+ return parts.length === 4 && parts.every((part) => /^\d+$/.test(part) && Number(part) >= 0 && Number(part) <= 255);
12945
+ }
12946
+
12947
+ function isTrustedCleartextAccessHost(host) {
12948
+ const normalized = normalizeAccessHost(host).replace(/^::ffff:/, '');
12949
+ if (
12950
+ normalized === 'localhost' ||
12951
+ normalized === '127.0.0.1' ||
12952
+ normalized === '::1' ||
12953
+ normalized.endsWith('.local') ||
12954
+ normalized.endsWith('.ts.net')
12955
+ ) {
12956
+ return true;
12957
+ }
12958
+ if (isIpv4Host(normalized)) {
12959
+ const [first, second] = normalized.split('.').map(Number);
12960
+ return (
12961
+ first === 10 ||
12962
+ (first === 172 && second >= 16 && second <= 31) ||
12963
+ (first === 192 && second === 168) ||
12964
+ (first === 100 && second >= 64 && second <= 127)
12965
+ );
12966
+ }
12967
+ return Boolean(normalized) && !normalized.includes('.') && !normalized.includes(':');
12968
+ }
12969
+
12970
+ function parseAccessUrl(rawValue, fail) {
12971
+ let parsed;
12972
+ try {
12973
+ parsed = new URL(rawValue);
12974
+ } catch {
12975
+ fail(`--access must be one of: remote, local, https://..., or host[,fallback]`);
12976
+ }
12977
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
12978
+ fail('--access URL must use http:// or https://');
12979
+ }
12980
+ if (parsed.protocol === 'http:' && !isTrustedCleartextAccessHost(parsed.hostname)) {
12981
+ fail(`Refusing public cleartext access URL ${rawValue}. Use https:// for public relay URLs.`);
12982
+ }
12983
+ return {
12984
+ kind: 'relay',
12985
+ relayUrl: rawValue.replace(/\/$/, ''),
12986
+ source: 'access',
12987
+ };
12988
+ }
12989
+
12990
+ function parseAccessValue(rawValue, fail) {
12991
+ const value = String(rawValue ?? '').trim();
12992
+ if (value === '') {
12993
+ return { kind: 'clear', source: 'access' };
12994
+ }
12995
+
12996
+ const normalized = value.toLowerCase();
12997
+ if (normalized === 'remote' || normalized === 'quick') {
12998
+ return { kind: 'remote', source: 'access' };
12999
+ }
13000
+ if (normalized === 'local' || normalized === 'none') {
13001
+ return { kind: 'local', source: 'access' };
13002
+ }
13003
+
13004
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) {
13005
+ return parseAccessUrl(value, fail);
13006
+ }
13007
+
13008
+ const hosts = value
13009
+ .split(',')
13010
+ .map((entry) => normalizeAccessHost(entry))
13011
+ .filter(Boolean);
13012
+ if (hosts.length === 0) {
13013
+ fail(`--access must include a target host or URL`);
13014
+ }
13015
+ const unsafeHost = hosts.find((host) => !isTrustedCleartextAccessHost(host));
13016
+ if (unsafeHost) {
13017
+ fail(`Refusing public cleartext access host ${unsafeHost}. Use https:// for public relay URLs.`);
13018
+ }
13019
+ return {
13020
+ kind: 'direct',
13021
+ canonicalHost: hosts[0],
13022
+ fallbackHosts: hosts.slice(1),
13023
+ source: 'access',
13024
+ };
13025
+ }
13026
+
13027
+ function parseAccessTargetArg(argv, fail, env = process.env) {
13028
+ const rawValue = parseNamedArg(argv, 'access', 'remote|local|https://...|host[,fallback]', fail, env);
13029
+ return rawValue === null ? null : parseAccessValue(rawValue, fail);
13030
+ }
13031
+
12908
13032
 
12909
13033
  /***/ }),
12910
13034
 
@@ -12977,13 +13101,14 @@ function describeLaunchctlResult(result) {
12977
13101
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nccwpck_require__) => {
12978
13102
 
12979
13103
  /* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
13104
+ /* harmony export */ Gv: () => (/* binding */ buildWebUiUrl),
12980
13105
  /* harmony export */ N7: () => (/* binding */ buildPairingDeepLink),
12981
13106
  /* harmony export */ No: () => (/* binding */ normalizePairingConnections),
12982
13107
  /* harmony export */ YP: () => (/* binding */ createCompactPairingPayload),
12983
13108
  /* harmony export */ dE: () => (/* binding */ findUnsafeCleartextHosts),
12984
13109
  /* harmony export */ uR: () => (/* binding */ formatConnectionSummary)
12985
13110
  /* harmony export */ });
12986
- /* unused harmony exports normalizeHostValue, isIpv4Host, isTailscaleHost, isSharedIpv4Host, isLocalNetworkHost, isLoopbackHost, isPlainLocalHostname, isTrustedCleartextHost, parseCommaSeparatedHosts, isQuickTunnelHost, buildLegacyConnection, formatConnectionSourceLabel */
13111
+ /* unused harmony exports normalizeHostValue, isIpv4Host, isTailscaleHost, isSharedIpv4Host, isLocalNetworkHost, isLoopbackHost, isPlainLocalHostname, isTrustedCleartextHost, parseCommaSeparatedHosts, isQuickTunnelHost, buildLegacyConnection, formatConnectionSourceLabel, buildConnectionHttpUrl, encodePairingPayloadForUrlFragment */
12987
13112
  function normalizeHostValue(host) {
12988
13113
  if (typeof host !== 'string') {
12989
13114
  return '';
@@ -13017,16 +13142,11 @@ function isLocalNetworkHost(host) {
13017
13142
  return false;
13018
13143
  }
13019
13144
  const [first, second] = host.split('.').map(Number);
13020
- return first === 10
13021
- || (first === 172 && second >= 16 && second <= 31)
13022
- || (first === 192 && second === 168);
13145
+ return first === 10 || (first === 172 && second >= 16 && second <= 31) || (first === 192 && second === 168);
13023
13146
  }
13024
13147
 
13025
13148
  function isLoopbackHost(host) {
13026
- return host === 'localhost'
13027
- || host === '127.0.0.1'
13028
- || host === '::1'
13029
- || host === '::ffff:127.0.0.1';
13149
+ return host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '::ffff:127.0.0.1';
13030
13150
  }
13031
13151
 
13032
13152
  function isPlainLocalHostname(host) {
@@ -13035,24 +13155,28 @@ function isPlainLocalHostname(host) {
13035
13155
 
13036
13156
  function isTrustedCleartextHost(host) {
13037
13157
  const normalized = normalizeHostValue(host.replace(/^https?:\/\//, '').replace(/\/.*$/, ''));
13038
- return isLoopbackHost(normalized)
13039
- || isLocalNetworkHost(normalized)
13040
- || isTailscaleHost(normalized)
13041
- || isSharedIpv4Host(normalized)
13042
- || isPlainLocalHostname(normalized);
13158
+ return (
13159
+ isLoopbackHost(normalized) ||
13160
+ isLocalNetworkHost(normalized) ||
13161
+ isTailscaleHost(normalized) ||
13162
+ isSharedIpv4Host(normalized) ||
13163
+ isPlainLocalHostname(normalized)
13164
+ );
13043
13165
  }
13044
13166
 
13045
13167
  function parseCommaSeparatedHosts(rawValue) {
13046
13168
  return typeof rawValue === 'string'
13047
- ? rawValue.split(',').map((entry) => normalizeHostValue(entry)).filter(Boolean)
13169
+ ? rawValue
13170
+ .split(',')
13171
+ .map((entry) => normalizeHostValue(entry))
13172
+ .filter(Boolean)
13048
13173
  : [];
13049
13174
  }
13050
13175
 
13051
13176
  function findUnsafeCleartextHosts({ hostArg, fallbackHostsArg }) {
13052
- return [
13053
- ...(hostArg ? [normalizeHostValue(hostArg)] : []),
13054
- ...parseCommaSeparatedHosts(fallbackHostsArg),
13055
- ].filter((host) => host && !isTrustedCleartextHost(host));
13177
+ return [...(hostArg ? [normalizeHostValue(hostArg)] : []), ...parseCommaSeparatedHosts(fallbackHostsArg)].filter(
13178
+ (host) => host && !isTrustedCleartextHost(host),
13179
+ );
13056
13180
  }
13057
13181
 
13058
13182
  function isQuickTunnelHost(host) {
@@ -13099,22 +13223,23 @@ function buildLegacyConnection(host, port, isPrimary) {
13099
13223
  function normalizePairingConnections(pairingPayload) {
13100
13224
  const explicitConnections = Array.isArray(pairingPayload.connections)
13101
13225
  ? pairingPayload.connections
13102
- .filter((target) => (
13103
- target
13104
- && typeof target.host === 'string'
13105
- && Number.isFinite(target.port)
13106
- && typeof target.source === 'string'
13107
- && typeof target.stability === 'string'
13108
- ))
13109
- .map((target) => ({
13110
- kind: target.kind === 'relay' ? 'relay' : 'direct',
13111
- host: normalizeHostValue(target.host),
13112
- port: Math.floor(Number(target.port)),
13113
- ...(target.secure === true ? { secure: true } : {}),
13114
- source: target.source,
13115
- stability: target.stability,
13116
- }))
13117
- .filter((target) => target.host && target.port > 0)
13226
+ .filter(
13227
+ (target) =>
13228
+ target &&
13229
+ typeof target.host === 'string' &&
13230
+ Number.isFinite(target.port) &&
13231
+ typeof target.source === 'string' &&
13232
+ typeof target.stability === 'string',
13233
+ )
13234
+ .map((target) => ({
13235
+ kind: target.kind === 'relay' ? 'relay' : 'direct',
13236
+ host: normalizeHostValue(target.host),
13237
+ port: Math.floor(Number(target.port)),
13238
+ ...(target.secure === true ? { secure: true } : {}),
13239
+ source: target.source,
13240
+ stability: target.stability,
13241
+ }))
13242
+ .filter((target) => target.host && target.port > 0)
13118
13243
  : [];
13119
13244
 
13120
13245
  const dedupe = (targets) => {
@@ -13134,13 +13259,12 @@ function normalizePairingConnections(pairingPayload) {
13134
13259
  }
13135
13260
 
13136
13261
  const canonicalHost = normalizeHostValue(pairingPayload.canonicalHost) || 'localhost';
13137
- const port = Number.isFinite(pairingPayload.port) && pairingPayload.port > 0
13138
- ? Math.floor(Number(pairingPayload.port))
13139
- : 9876;
13262
+ const port =
13263
+ Number.isFinite(pairingPayload.port) && pairingPayload.port > 0 ? Math.floor(Number(pairingPayload.port)) : 9876;
13140
13264
  const fallbackHosts = Array.isArray(pairingPayload.fallbackHosts)
13141
13265
  ? pairingPayload.fallbackHosts
13142
- .map((host) => normalizeHostValue(host))
13143
- .filter((host) => host && host !== canonicalHost)
13266
+ .map((host) => normalizeHostValue(host))
13267
+ .filter((host) => host && host !== canonicalHost)
13144
13268
  : [];
13145
13269
 
13146
13270
  return dedupe([
@@ -13201,6 +13325,26 @@ function buildPairingDeepLink(pairingPayloadText) {
13201
13325
  return `vibelet://pair?data=${encodeURIComponent(pairingPayloadText)}`;
13202
13326
  }
13203
13327
 
13328
+ function formatUrlHost(host) {
13329
+ return host.includes(':') && !host.startsWith('[') ? `[${host}]` : host;
13330
+ }
13331
+
13332
+ function buildConnectionHttpUrl(target) {
13333
+ const secure = target.secure === true || Number(target.port) === 443;
13334
+ const scheme = secure ? 'https' : 'http';
13335
+ const port = Number(target.port);
13336
+ const portSuffix = (secure && port === 443) || (!secure && port === 80) ? '' : `:${port}`;
13337
+ return `${scheme}://${formatUrlHost(target.host)}${portSuffix}`;
13338
+ }
13339
+
13340
+ function encodePairingPayloadForUrlFragment(pairingPayload) {
13341
+ return Buffer.from(JSON.stringify(pairingPayload), 'utf8').toString('base64url');
13342
+ }
13343
+
13344
+ function buildWebUiUrl(target, pairingPayload) {
13345
+ return `${buildConnectionHttpUrl(target)}/web#pair=${encodePairingPayloadForUrlFragment(pairingPayload)}`;
13346
+ }
13347
+
13204
13348
 
13205
13349
  /***/ }),
13206
13350
 
@@ -14231,7 +14375,7 @@ async function ensureDaemonForTerminalControl(backend) {
14231
14375
  ? 'terminal-control token is missing'
14232
14376
  : 'the running daemon does not advertise terminal-control support';
14233
14377
  process.stderr.write(
14234
- `Vibelet daemon is running without terminal-control support (${reason}); running native TUI without App takeover because active sessions are present. Stop active App sessions and run \`vibelet restart --local\` to enable takeover.\n`,
14378
+ `Vibelet daemon is running without terminal-control support (${reason}); running native TUI without App takeover because active sessions are present. Stop active App sessions and run \`vibelet restart --access=local\` to enable takeover.\n`,
14235
14379
  );
14236
14380
  return healthyDaemon;
14237
14381
  }
@@ -14251,7 +14395,7 @@ function validateExplicitCleartextHosts({ hostArg, fallbackHostsArg }) {
14251
14395
  return;
14252
14396
  }
14253
14397
  fail(
14254
- `Refusing public cleartext host ${unsafeHosts[0]}. Use --relay=https://..., a Tailscale host, or a LAN/local address.`,
14398
+ `Refusing public cleartext host ${unsafeHosts[0]}. Use --access=https://..., a Tailscale host, or a LAN/local address.`,
14255
14399
  );
14256
14400
  }
14257
14401
 
@@ -14300,6 +14444,11 @@ async function printPairingSummary(existingHealth = null) {
14300
14444
  process.stdout.write(` - ${(0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_12__/* .formatConnectionSummary */ .uR)(target)}\n`);
14301
14445
  });
14302
14446
  }
14447
+ if (preferredConnection) {
14448
+ process.stdout.write(
14449
+ `Web UI: ${(0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_12__/* .buildWebUiUrl */ .Gv)(preferredConnection, (0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_12__/* .createCompactPairingPayload */ .YP)(pairingPayload))}\n`,
14450
+ );
14451
+ }
14303
14452
  process.stdout.write(`Paired devices: ${health.pairedDevices}\n`);
14304
14453
  await printPairingQr(pairingPayload);
14305
14454
  }
@@ -14315,15 +14464,13 @@ function printHelp() {
14315
14464
  );
14316
14465
  process.stdout.write(` npx ${packageJson.name} start Same as above\n`);
14317
14466
  process.stdout.write(
14318
- ` npx ${packageJson.name} --local Use LAN/local pairing only; skip Cloudflare and Tailscale\n`,
14467
+ ` npx ${packageJson.name} --access=local Use LAN/local pairing only; skip Cloudflare and Tailscale\n`,
14319
14468
  );
14320
- process.stdout.write(` npx ${packageJson.name} --force Force a new Cloudflare Tunnel URL\n`);
14321
- process.stdout.write(` npx ${packageJson.name} --relay <url> Use a custom tunnel URL for remote access\n`);
14322
- process.stdout.write(` npx ${packageJson.name} --host <ip> Set the primary LAN/Tailscale host/IP address\n`);
14469
+ process.stdout.write(` npx ${packageJson.name} --access=remote --force Force a new Cloudflare Tunnel URL\n`);
14470
+ process.stdout.write(` npx ${packageJson.name} --access=https://<url> Use a custom tunnel URL for remote access\n`);
14471
+ process.stdout.write(` npx ${packageJson.name} --access=<host> Set the primary LAN/Tailscale host/IP address\n`);
14323
14472
  process.stdout.write(` npx ${packageJson.name} --port <port> Start or query the daemon on a custom port\n`);
14324
- process.stdout.write(
14325
- ` npx ${packageJson.name} --fallback-hosts <ips> Comma-separated LAN/Tailscale fallback IPs\n`,
14326
- );
14473
+ process.stdout.write(` npx ${packageJson.name} --access=<host>,<fallbacks> Set fallback LAN/Tailscale hosts\n`);
14327
14474
  process.stdout.write(` npx ${packageJson.name} stop Stop the daemon\n`);
14328
14475
  process.stdout.write(` npx ${packageJson.name} restart Restart the daemon\n`);
14329
14476
  process.stdout.write(` npx ${packageJson.name} status Show service and daemon status\n`);
@@ -14341,15 +14488,16 @@ function printHelp() {
14341
14488
  process.stdout.write(` # Remote access is on by default for start/reset/restart\n`);
14342
14489
  process.stdout.write(` npx ${packageJson.name}\n\n`);
14343
14490
  process.stdout.write(` # Want LAN/local-only pairing for this run?\n`);
14344
- process.stdout.write(` npx ${packageJson.name} --local\n\n`);
14491
+ process.stdout.write(` npx ${packageJson.name} --access=local\n\n`);
14345
14492
  process.stdout.write(` # Need a fresh Cloudflare Tunnel URL?\n`);
14346
- process.stdout.write(` npx ${packageJson.name} --force\n\n`);
14493
+ process.stdout.write(` npx ${packageJson.name} --access=remote --force\n\n`);
14347
14494
  process.stdout.write(` # Or bring your own tunnel and pass the URL manually:\n`);
14348
14495
  process.stdout.write(` npx cloudflared tunnel --protocol http2 --url http://localhost:${port}\n`);
14349
14496
  process.stdout.write(` ngrok http ${port}\n`);
14350
- process.stdout.write(` npx ${packageJson.name} --relay=https://<your-tunnel-url>\n\n`);
14497
+ process.stdout.write(` npx ${packageJson.name} --access=https://<your-tunnel-url>\n\n`);
14351
14498
  process.stdout.write(` # Tailscale (P2P VPN, no tunnel needed)\n`);
14352
- process.stdout.write(` npx ${packageJson.name} --host=<tailscale-ip>\n`);
14499
+ process.stdout.write(` npx ${packageJson.name} --access=<tailscale-ip>\n\n`);
14500
+ process.stdout.write(`Legacy aliases still work: --local, --relay, --host, --fallback-hosts, --remote, --tunnel.\n`);
14353
14501
  }
14354
14502
 
14355
14503
  function parseNamedArg(name, errorHint) {
@@ -14370,6 +14518,31 @@ function parsePortArg() {
14370
14518
  return parsed;
14371
14519
  }
14372
14520
 
14521
+ function parseCommandArg(argv) {
14522
+ const namedArgsWithValues = new Set(['--access', '--relay', '--host', '--fallback-hosts', '--port']);
14523
+ for (let i = 2; i < argv.length; i += 1) {
14524
+ const arg = argv[i];
14525
+ if (namedArgsWithValues.has(arg)) {
14526
+ i += 1;
14527
+ continue;
14528
+ }
14529
+ if (
14530
+ arg.startsWith('--access=') ||
14531
+ arg.startsWith('--relay=') ||
14532
+ arg.startsWith('--host=') ||
14533
+ arg.startsWith('--fallback-hosts=') ||
14534
+ arg.startsWith('--port=')
14535
+ ) {
14536
+ continue;
14537
+ }
14538
+ if (arg === '--local' || arg === '--remote' || arg === '--tunnel' || arg === '--force') {
14539
+ continue;
14540
+ }
14541
+ return arg;
14542
+ }
14543
+ return 'default';
14544
+ }
14545
+
14373
14546
  function loadRelayConfig() {
14374
14547
  try {
14375
14548
  const data = JSON.parse((0,node_fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync)(relayConfigPath, 'utf8'));
@@ -14405,7 +14578,7 @@ async function main() {
14405
14578
  process.env.VIBE_PORT = String(portArg);
14406
14579
  }
14407
14580
 
14408
- let command = process.argv[2] ?? 'default';
14581
+ let command = parseCommandArg(process.argv);
14409
14582
 
14410
14583
  if (command === '--help' || command === '-h' || command === 'help') {
14411
14584
  printHelp();
@@ -14429,18 +14602,48 @@ async function main() {
14429
14602
  return;
14430
14603
  }
14431
14604
 
14432
- (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .consumeFlag */ .PC)(process.argv, 'remote') ||
14433
- (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .consumeFlag */ .PC)(process.argv, 'tunnel') ||
14434
- (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .readNpmConfigFlag */ .AW)('remote') ||
14435
- (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .readNpmConfigFlag */ .AW)('tunnel');
14605
+ const accessTarget = (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .parseAccessTargetArg */ .tY)(process.argv, fail);
14606
+ if (accessTarget && (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .hasLegacyAccessArgs */ .NT)(process.argv, process.env)) {
14607
+ fail(
14608
+ 'Do not combine --access with legacy access flags.',
14609
+ 'Use one form, for example `--access=local`, `--access=remote`, `--access=https://...`, or `--access=<host>`.',
14610
+ );
14611
+ }
14612
+ if (!accessTarget) {
14613
+ (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .consumeFlag */ .PC)(process.argv, 'remote') ||
14614
+ (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .consumeFlag */ .PC)(process.argv, 'tunnel') ||
14615
+ (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .readNpmConfigFlag */ .AW)('remote') ||
14616
+ (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .readNpmConfigFlag */ .AW)('tunnel');
14617
+ }
14436
14618
  const localFlag =
14437
- (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .consumeFlag */ .PC)(process.argv, 'local') || (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .readNpmConfigFlag */ .AW)('local') || isTruthyEnvFlag(process.env.VIBELET_LOCAL_ONLY);
14619
+ accessTarget?.kind === 'local' ||
14620
+ (!accessTarget &&
14621
+ ((0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .consumeFlag */ .PC)(process.argv, 'local') ||
14622
+ (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .readNpmConfigFlag */ .AW)('local') ||
14623
+ isTruthyEnvFlag(process.env.VIBELET_LOCAL_ONLY)));
14438
14624
  const forceFlag = (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .consumeFlag */ .PC)(process.argv, 'force') || (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_13__/* .readNpmConfigFlag */ .AW)('force');
14439
- const relayArg = parseRelayArg();
14440
- const hostArg = parseNamedArg('host', '100.x.x.x');
14441
- const fallbackHostsArg = parseNamedArg('fallback-hosts', '100.x.x.x,192.168.1.x');
14625
+ const relayArg =
14626
+ accessTarget?.kind === 'relay'
14627
+ ? accessTarget.relayUrl
14628
+ : accessTarget?.kind === 'clear'
14629
+ ? ''
14630
+ : accessTarget
14631
+ ? null
14632
+ : parseRelayArg();
14633
+ const hostArg =
14634
+ accessTarget?.kind === 'direct'
14635
+ ? accessTarget.canonicalHost
14636
+ : accessTarget
14637
+ ? null
14638
+ : parseNamedArg('host', '100.x.x.x');
14639
+ const fallbackHostsArg =
14640
+ accessTarget?.kind === 'direct'
14641
+ ? accessTarget.fallbackHosts.join(',')
14642
+ : accessTarget
14643
+ ? null
14644
+ : parseNamedArg('fallback-hosts', '100.x.x.x,192.168.1.x');
14442
14645
  let managedTunnelFailed = false;
14443
- command = process.argv[2] ?? 'default';
14646
+ command = parseCommandArg(process.argv);
14444
14647
  const startCommand = isDaemonStartCommand(command);
14445
14648
  // --remote/--tunnel remain accepted for compatibility, but startup commands
14446
14649
  // now default to managed remote access unless another connection target wins.
@@ -14471,13 +14674,13 @@ async function main() {
14471
14674
  const message = err instanceof Error ? err.message : String(err);
14472
14675
  process.stderr.write(`${message}\n`);
14473
14676
  process.stderr.write(
14474
- 'Continuing with LAN/local pairing. Use `npx vibelet --force` after fixing Cloudflare Tunnel, or pass `--relay=<url>` for a custom tunnel.\n',
14677
+ 'Continuing with LAN/local pairing. Use `npx vibelet --access=remote --force` after fixing Cloudflare Tunnel, or pass `--access=https://<url>` for a custom tunnel.\n',
14475
14678
  );
14476
14679
  }
14477
14680
  }
14478
14681
  }
14479
14682
 
14480
- // --relay "" clears saved relay; --relay <url> saves it; omitted uses saved value
14683
+ // --access= clears saved relay; --access=https://... saves it; omitted uses saved value.
14481
14684
  if (relayArg !== null) {
14482
14685
  if (relayArg) {
14483
14686
  saveRelayConfig(relayArg);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibelet",
3
- "version": "1.2.92",
3
+ "version": "1.2.96",
4
4
  "description": "Cross-platform CLI for installing and running the Vibelet daemon",
5
5
  "homepage": "https://vibelet.icu",
6
6
  "files": [