vibelet
v1.2.243
Published
Cross-platform CLI for installing and running the Vibelet daemon
Readme
Vibelet
@vibelet/cli is a cross-platform CLI that installs and manages the Vibelet daemon for remote coding sessions. The same package is also published as vibelet.
Official website: https://vibelet.icu
Requirements
- macOS / Linux / Windows
- Node.js 20 or newer
Install
npx @vibelet/cli
npx vibeletOr install it globally:
npm install -g @vibelet/cli
npm install -g vibelet
vibeletThe CLI prints the official website on each run so users can always jump back to the main docs and download page.
Commands
vibelet # Install/start daemon, auto-enable remote access, and print pairing QR code
vibelet start # Same as above
vibelet stop # Stop the daemon
vibelet restart # Restart the daemon
vibelet status # Show service and daemon status
vibelet logs # Print recent daemon logs
vibelet reset # Clear pairings and saved device connections; print a fresh QR code
vibelet --help # Show help
vibelet --version # Show CLI versionreset clears this daemon's synced device profiles (including saved connection addresses),
revokes all pairings, and disconnects authenticated clients. Scan the fresh QR code to pair again.
It does not erase records stored on your phone; those can sync back after pairing,
so remove obsolete computers in the app as well when you want to discard them permanently.
The printed Web UI link uses http://localhost:<port> for a stable, browser-trusted
same-machine connection. When another advertised route is available, the CLI also
prints Web UI (other devices) for LAN or remote browsers.
Updates from the app
On Linux, a systemd-managed daemon launches the updater in a separate transient user service.
This keeps the updater alive when restarting the daemon stops its service cgroup; detached
alone does not provide that isolation. Launch failures are reported to the app without falling
back to an updater inside the daemon service. Older daemons need one manual CLI update to gain
this behavior. The updater keeps the daemon's environment and writes to the existing daemon logs.
When an app-triggered daemon update interrupts an active Vibelet-managed turn, the new daemon resumes that conversation and sends one continuation instruction, even when the phone is disconnected. It preserves the session's model and approval settings and asks the agent to inspect current state before continuing, rather than replaying the original request. Running tools are interrupted; this is conversation recovery, not process checkpointing.
Idle, stopped, starting, and approval/question-waiting sessions are not automatically continued. Ordinary CLI stop/restart and crashes do not opt in. Recovery is attempted once, expires after 30 minutes, and falls back to manual continuation on failure. Both the outgoing daemon and the updater CLI must support this behavior, so the first upgrade from an older daemon still needs manual continuation. Updates of the daemon bundled with Vibelet Desktop are not covered.
Options
vibelet --access=local # Disable Remote Direct and Cloudflare for this run
vibelet --access=remote --force # Force a fresh tunnel URL
vibelet --access=https://<your-tunnel-url> # Use your own tunnel URL
vibelet --access=<tailscale-or-lan-host> # Use a direct private-network host
vibelet --access=<host>,<fallback1> # Add fallback private-network hosts
vibelet --access= # Clear saved relay URL
vibelet --remote-direct # Enable account-free Remote Direct
vibelet --no-remote-direct # Disable previously enabled Remote Direct accessRemote Direct is enabled by default; Cloudflare is opt-in for vibelet, vibelet start, vibelet restart, and vibelet reset. Use --access=local when you want a LAN-only QR code for that run. This also disables Remote Direct for the current run, even if it was previously enabled; the saved Remote Direct choice is unchanged. Legacy aliases still work: --local, --relay, --host, --fallback-hosts, --remote, and --tunnel.
Managed Cloudflare Tunnels use cloudflared's auto transport so QUIC is preferred
when UDP is available and HTTP/2 remains the fallback. Release packages include
pinned cloudflared binaries; installing or starting Vibelet does not download
cloudflared separately. The CLI verifies the bundled binary checksum and security
version before use. Upgrade Vibelet to upgrade this binary. A missing, corrupted,
or unsafe bundled binary fails explicitly rather than triggering an online install.
System package-manager binaries are never modified.
The release build downloads official assets listed in scripts/cloudflared-release.json,
verifies their pinned SHA-256 checksums, and includes the license and a runtime
manifest in dist/cloudflared. macOS supports arm64/x64, Linux supports arm64/x64/arm/ia32,
and Windows supports x64/ia32; Windows arm64 uses the official x64 executable under
Windows emulation. This compatibility path requires Windows validation before a
Windows release. All targets must be present before bundling or publishing.
For a targeted local check, prepare an isolated native bundle with
dev-gate run --kind heavy -- node apps/vibelet-cli/scripts/verify-bundled-cloudflared.mjs --prepare .verify/vibelet-cloudflared,
then run the same script with --verify under dev-gate run --kind runtime.
This exercises ncc, the real binary with an empty PATH, and missing/corrupt bundle
rejection. It is not a full cross-platform release build; partial output is
forbidden in the production bundle directory and rejected by publishing.
App-triggered updates report that download/installation is still running while npm works. They have a ten-minute execution limit; on macOS/Windows a timed-out updater tree is terminated before retry becomes available. On systemd Linux the transient update service enforces the same limit. The existing daemon remains available until the replacement CLI begins its normal restart.
Remote Direct
Run npx vibelet and scan the new QR with the current app. Remote Direct is enabled by default and requires no separate networking app or account. Vibelet attempts an encrypted direct path and falls back to an encrypted relay when needed.
Cloudflare is off by default. Add --cloudflare for an additional path, or use --access=local for LAN-only pairing. Internal forwarding addresses are managed automatically and are hidden from ordinary connection displays. Use status and logs for diagnostics; do not share connection credentials.
Release
pnpm publish:dual:dry-run
pnpm publish:dualThe dual publish script builds once, then publishes the same CLI bundle to both @vibelet/cli and vibelet. The dry-run path stages both packages and validates them with npm pack --dry-run without touching the registry.
Notes
- The npm package publishes the CLI plus a minified daemon runtime bundle.
- The package is intended for end users of the Vibelet host daemon, not for importing as a library.
- The daemon keeps
~/.vibelet/data/audit.jsonland~/.vibelet/logs/daemon.*.logsize-bounded by trimming the oldest content in place. - Environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
|
VIBE_PORT|9876| Daemon listen port | |VIBE_IDLE_TIMEOUT_MS|1800000(30 min) | Idle timeout before a driver is released (0 = disabled) | |VIBE_TURN_STALL_TIMEOUT_MS|300000(5 min) | Soft inactivity threshold for suspecting an in-flight turn has stalled (0 = disabled) | |VIBE_TURN_STALL_HARD_TIMEOUT_MS|900000(15 min) | Stop threshold when both turn activity and verified execution-client presence are absent (0 = warn only; confirmed process death can still stop a turn) | |VIBE_TEXT_DELTA_BATCH_MS|24| Maximum delay for combining streaming text updates before WebSocket broadcast (0 = disabled) | |VIBE_AUDIT_MAX_BYTES|8388608(8 MB) | Max audit.jsonl size before trimming | |VIBE_DAEMON_LOG_MAX_BYTES|16777216(16 MB) | Max daemon log file size before trimming | |VIBE_STORAGE_HOUSEKEEPING_INTERVAL_MS|300000(5 min) | Log trimming check interval | |CLAUDE_PATH| auto-detect | Path to Claude binary | |CODEX_PATH| auto-detect | Path to Codex binary |
Execution-driver presence is checked locally every 2 seconds during a turn and
every 15 seconds while idle. These checks do not send prompts or consume model
tokens, and do not update the last actual activity time. A silent turn with
verified process presence produces a warning after the soft threshold but is
not stopped or subjected to tool-process recovery merely for silence. This
covers long commands, sleep, and polling without requiring a scheduling tool.
Presence means the execution process/connection is alive, not that its model or
tools are making progress; a live deadlock still needs explicit cancellation or
the tool's own timeout. If presence can no longer be verified, the hard timeout
also checks time since the last verified presence; a single missed check after a
long wait does not immediately terminate the turn. The existing idle-driver
release policy is independent and still applies after the turn finishes.
Remote Direct is enabled by default. Cloudflare is off unless explicitly requested with npx vibelet --cloudflare. Use --access=local for LAN-only pairing.
Your own domain and port forwarding
To advertise your own domain while listening locally on port 5773:
npx vibelet --port 5773 --local --host nas.example.com --json--host nas.example.com:15773 advertises external port 15773 without changing the
local listening port. Configure your router or reverse proxy separately; Vibelet
does not create a port mapping. Port 443 uses HTTPS and requires your own TLS proxy.
The generated QR and link use this endpoint, retaining local fallback addresses.
The override applies to this command's pairing output; include it again when
regenerating pairing information. Existing saved device connections are unchanged.
For public HTTP endpoints, the updated mobile app asks for confirmation before
pairing because credentials, messages, and files travel without encryption. Older
apps may reject these endpoints; update the mobile app as well as the CLI.
--json additionally prints editable pairing JSON; it does not replace the link
saved in ~/.vibelet/pairing-code.txt. Treat both as private pairing credentials.
