Headless mode
Keep your development stack running on a stable host and return to the same work from your desktop app, a browser, or the hob mobile app.
Run hob on a VM, workstation, or server so your development environment stays available when you leave your laptop. Headless mode runs the hob Host without requiring a native window. Connect your hob desktop app to it for the full app, including web panes. The Web IDE brings the same workspaces to a browser tab on a computer without hob, and the hob mobile app brings monitoring and steering to your phone.
- Isolation — keep project files, agent tools, and credentials on a dedicated machine.
- Uptime — let agents, commands, and automations continue when your laptop sleeps or disconnects.
- One setup — install and authenticate your development stack once on the host.
- Remote review — return to the same conversations, previews, and changes from another device.
Access requirements
The Host you connect to and the desktop that connects both need an active hob Pro+ license. The Web IDE and hob mobile need it on the Host. Without one, the Host still starts and keeps running, but without remote access. See If the license is inactive. Use the same operating-system account for installation, license activation, agent authentication, and the service.
Set up a new VM
From your desktop app, hob sets up a VM over SSH. You need the hob desktop app
on your own computer, with an active Pro+ license, and an SSH login to the VM
that works without typing a password each time, such as an SSH key. An entry in
~/.ssh/config makes the VM appear in the list.
Check the VM for hob
In the desktop app, choose the computer button at the left of the titlebar,
then Connect to a new computer. Select Choose SSH machine, then pick the VM, or enter the
destination you use with ssh, such as [email protected]. hob checks the VM
and shows the result on the same form. hob uses your own ssh, keys, and
~/.ssh/config, and stores no SSH credentials.
If ssh must ask you something first, such as whether to trust the VM's host key, choose Sign in in a terminal.
Take the next step
The check shows one next step at a time:
- Install hob runs the installer on the VM in a terminal.
- Activate hob runs
hob app license activateon the VM in a terminal. Paste your key at the prompt; the input stays hidden. - Start hob starts the Host in the background with
hob --headless --detach. - Turn on desktop connections sets them to Localhost only.
After Start hob, hob turns on desktop connections and starts pairing on its own. In a window that shows another Host, hob shows each terminal command with Copy, so you run it on your own computer.
Remote access needs Pro+ on both computers. If you do not have a key, start the hob Pro+ trial. The free trial on the desktop's Activate hob step can be a Pro trial, which does not include remote access; that step links to the Pro+ trial.
Pair and connect
hob opens an SSH tunnel and approves the request on the VM over SSH, so you need
no second terminal. The code is shown for your information. If hob cannot
approve it, approve the request on the VM with hob connection pending and
hob connection approve <request-id>, then compare the codes. Name the Host and
choose Connect.
Each later connect opens a new tunnel; there is nothing to keep running. Install and sign in to your agent tools on the VM: the Host's own setup offers this the first time a window shows it. The first time you connect, hob also asks whether to set up the VM like this computer. See Set up the other Host from your desktop.
From the command line, hob connection check --ssh <destination> shows the next
step, and hob connection pair --ssh <destination> pairs.
Set up from the VM's terminal
You can also set up the VM in its own terminal and pair through an SSH tunnel that you run.
-
Install hob on the VM:
curl -fsSL https://get.hob.dev/install | shInstall and authenticate your agent backends on this host too. Bring the repositories, language runtimes, package managers, MCP configuration, and other tools the projects need. Accounts and profiles let you keep backend setups organized on this machine.
-
Start the Host:
hob --headlessWhen this machine has no active license, hob asks for the key:
hob headless is running without remote access: the license is inactive. Activate the license on this computer: hob app license activate No license key yet? Start a hob Pro+ trial: https://hob.dev/trial License key (Enter skips):Paste the key. The input stays hidden. hob activates the license on the running Host and continues:
License activated: hob Pro+ trial, expires <date>. hob headless is ready. Desktop app (recommended): desktop connections set to Localhost only, port 22907. Web IDE (browser fallback): <your credentialed access URL> -
The guided pairing session starts next. Press Enter to keep Localhost only. On your computer, open an SSH tunnel and keep it running:
ssh -N -o ExitOnForwardFailure=yes -L 22908:127.0.0.1:22907 <user>@<address you use for SSH>Then run
hob connection pair 127.0.0.1:22908on your computer, or choose the computer button in the titlebar, then Connect to a new computer, and enter127.0.0.1:22908. The VM shows the request with its code. Approve it only when the code matches on both computers, then confirm the code on your computer and name the Host. Choose Connect to open the VM in your desktop app.On a VPN, choose Private networks in the session and pair with the VM's VPN address instead; see VPN or private network.
The order does not matter. You can activate first with
hob app license activate, then run hob --headless. For a script or a
service, give the key on standard input:
printf '%s\n' "$HOB_LICENSE_KEY" | hob app license activate --key-stdinhob asks for the key only in a terminal, and never with --detach or under a
service manager.
Desktop and Host
In the 1.19 beta, the desktop window runs in Electron. The Go Host owns your projects, sessions, and files. Headless mode runs that same Host without a desktop window; your desktop app on another computer, a browser, or the hob mobile app supplies the interface. Closing a window and stopping the Host are different actions.
Choose how to keep it running
Choose how the Host keeps running after setup:
| Method | Use it for | Lifetime |
|---|---|---|
Foreground: hob --headless | Setup and troubleshooting. | Stays attached; Ctrl-C or SIGTERM requests Host shutdown. |
Daemon: hob --headless --detach | Leaving the Host running after your shell exits. | Enables the daemon service and returns. Does not install an operating-system startup service. |
| systemd user service | A Linux host that starts at boot. | Manages the foreground command; enable lingering for boot without login. |
| tmux, byobu, or screen | Keeping a foreground session you can reattach to. | Survives SSH disconnect while the multiplexer lives; does not start after reboot. |
Closing an app or a browser, or losing its connection, does not stop the Host. Host shutdown ends running agents, commands, and preview servers; a later start restores saved context. See Returning to your work for that boundary.
Run the Host
Start in the foreground
hob --headless stays attached to your terminal. Its output starts with the
ready lines:
hob headless is ready.
Desktop app (recommended): desktop connections set to Localhost only, port 22907.
Web IDE (browser fallback): <your credentialed access URL>The desktop line comes first because the desktop app is the recommended way to use a headless Host. The Web IDE line appears once the Web IDE serves. Keep that URL private: it carries the Web IDE credential.
The Host restores saved project/window context when available. On a fresh setup, open a folder from the desktop app or the Web IDE to choose a project on the host.
Do not append a project path to --headless. The current command starts
headless service mode and rejects a path or native-window target. The shell's
working directory does not select a project. Choose and switch projects from
the connected app instead.
Press Ctrl-C to request Host shutdown and wait for it to finish. During a long shutdown or restart, the command reports progress; a second interrupt detaches the foreground command without forcing the Host to exit. Closing a terminal abruptly is not a substitute for this explicit shutdown.
If the license is inactive
Without an active Pro+ license, hob --headless does not exit. The Host starts
without remote access and prints:
hob headless is running without remote access: the license is inactive.
Activate the license on this computer: hob app license activateIn a terminal, hob then asks for the key, as in
Set up a new VM. Press Enter to skip. Without a
terminal, or with --detach, hob does not ask.
In this mode there is no Web IDE or remote access, and agents, terminals, and
automations stay unavailable. A service manager sees a running service, so a
systemd unit does not restart in a loop. To activate later, run
hob app license activate from another shell as the same user. The Host
switches to full service at once, without a restart, and the foreground
command prints its ready lines within a few seconds.
If the Web IDE is off
If you set the Web IDE to Off, hob --headless starts normally and says so:
Web IDE (browser fallback) is off. Turn it on: hob connection web-ide localhostDesktop connections are a separate switch; see Desktop connections and the Web IDE.
If the port is in use
If another program already listens on the Host's port, hob keeps running and
prints the port, a command that finds the program, and the next steps. Stop
that program and the Host takes the port again by itself, within about 30
seconds. To use another port instead, set server.port in hob's
settings.json and restart hob.
Enable the daemon service
hob --headless --detachThe command enables the elected Host's headless service, prints the same ready lines, and returns to the shell. The Host keeps running after the shell exits. This is hob's daemon mode; use systemd below if it should also start at boot.
To print the Web IDE URL again without staying attached, run the same command.
To stop a daemon you started this way, run hob --headless as the same user,
wait for its ready message, then press Ctrl-C once and wait for shutdown.
For a systemd-managed Host, use systemctl --user stop instead.
Run an always-available systemd service
Check the installed executable path:
command -v hobCreate a user service:
mkdir -p ~/.config/systemd/user
${EDITOR:-vi} ~/.config/systemd/user/hob-headless.serviceUse this unit. If your installed path differs from ~/.local/bin/hob, replace
ExecStart with that absolute path:
[Unit]
Description=hob headless IDE
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
ExecStart=%h/.local/bin/hob --headless
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.targetKeep ExecStart in the foreground: do not add --detach or a project path.
Before transferring an existing daemon to systemd, shut it down through its
foreground attachment so the service starts the Host with the unit's environment.
Then enable and start the unit:
systemctl --user daemon-reload
systemctl --user enable --now hob-headless.service
systemctl --user status hob-headless.serviceEnable lingering so this user's services can start at boot and remain available without a login:
sudo loginctl enable-linger "$USER"This may require an administrator. Without lingering, a user service normally starts with the user's login. Read startup output, including the access URL, with:
journalctl --user -u hob-headless.service -fManage the service with:
systemctl --user stop hob-headless.service
systemctl --user start hob-headless.service
systemctl --user restart hob-headless.servicesystemd does not run your interactive shell startup files. Set any required
PATH and environment variables in the unit or an EnvironmentFile. After
changing the unit, run systemctl --user daemon-reload, then restart it.
Keep journal access private: startup output includes the credentialed browser URL.
Use a terminal multiplexer
Run hob --headless inside your existing tmux, byobu, or screen session and
detach the multiplexer as usual. Reattach to return to its output. Pressing
Ctrl-C inside that foreground session requests Host shutdown; detaching the
multiplexer leaves it running.
Desktop connections and the Web IDE
A headless Host serves two kinds of connection on one listener port, 22907
by default. Each has its own switch:
| Desktop connections | Web IDE | |
|---|---|---|
| What connects | The hob desktop app on another computer | A browser tab on another computer |
| Where to set it | hob desktop tab of Access to this computer | Web IDE tab of Access to this computer |
| Command on the Host | hob connection desktop [off|localhost|lan] | hob connection web-ide [off|localhost|lan] |
Each switch is Off, Localhost only, or Private networks only,
independently of the other. A new profile starts with both switches Off.
hob --headless sets each switch that you never chose to Localhost only
and saves it, so Settings shows the real value. A switch that you set to Off
stays Off. Run the commands from any shell on the Host, as the same user;
hob connection access is the older name of hob connection desktop.
Use the desktop app when you can: web panes and agent web steps run only in the desktop app (see Web steps need the desktop app). Use the Web IDE on a computer without hob.
Pair your desktop app
A foreground hob --headless runs the guided pairing session while no computer
is approved yet. To pair another computer later, run hob --headless --pair,
also while the Host runs in the background.
- Choose which computers' hob desktop app can connect: Private networks, Localhost only (for an SSH tunnel), or Off. The session shows the address that each choice makes reachable.
- On your computer, run
hob connection pair <address>, or choose the computer button in the titlebar, then Connect to a new computer, and enter the address. With SSH access to the Host, you can instead select Choose SSH machine there, or runhob connection pair --ssh <destination>; hob opens the tunnel and approves the request over SSH. With Localhost only, the SSH tunnel must already run on your computer, and the address is127.0.0.1:22908. - The session shows the request with its source address and code. Approve it only when the code matches on both computers, then confirm the code on your computer.
Then connect from your computer with Connect, or later from the Host button in the titlebar. See Connect your desktop to another Host.
Reach a VM over the internet
Desktop connections and the Web IDE accept only this machine (Localhost only) or private networks (Private networks only). A public address cannot connect. For a VM on the public internet, choose one path:
| Path | Switch on the Host | Address to pair or open |
|---|---|---|
| SSH from the desktop app | Localhost only, the hob --headless default | The SSH destination; hob opens the tunnel. See Set up a new VM. |
| SSH tunnel | Localhost only | 127.0.0.1:22908 on your computer |
| VPN, such as Tailscale | Private networks only | The VM's VPN address |
A cloud VM's private address, such as 10.0.0.5, is reachable only from inside
that cloud network.
SSH tunnel
When you connect over SSH from the desktop app, hob opens and closes this tunnel for you. Run it yourself for the Web IDE, or when you pair by address. On your computer, forward a local port to the Host's listener and keep the command running:
ssh -N -o ExitOnForwardFailure=yes -L 22908:127.0.0.1:22907 <user>@<address you use for SSH>22908 is the local port on your computer; choose a free one. 22907 is the
Host's listener port; substitute its configured port if different.
ExitOnForwardFailure stops SSH if it cannot establish the tunnel. When you
choose Localhost only, the guided pairing session prints this command with
the Host's user and port.
- Desktop app: pair with
hob connection pair 127.0.0.1:22908, or enter127.0.0.1:22908under Connect to a new computer. - Web IDE: open the printed Web IDE URL on your computer, changing only its
host and port to
127.0.0.1:22908. Preserve the path and credential fragment. The Host normally serves HTTPS using its generated local certificate, so the browser may ask you to accept that certificate on your first connection.
VPN or private network
On the Host, set the switches that you use to Private networks only:
hob connection desktop lan, hob connection web-ide lan, or the guided
pairing session. Then pair or open the URL with the VM's VPN or LAN address.
The default listener is 0.0.0.0:22907; Settings → Remote connections →
Listen address is available in Advanced mode. Restrict firewall access to the
networks you intend to use. Only hob mobile supports the
internet relay.
Restrict external file access
Some hosts should keep hob's file operations inside the active project or worktree. Set the containment policy in the environment that starts the Host:
HOB_ALLOW_READS_OUTSIDE_PROJECT_ROOTS=false hob --headlessFor the systemd unit, put this under [Service]:
Environment=HOB_ALLOW_READS_OUTSIDE_PROJECT_ROOTS=false| Question | Behavior |
|---|---|
| Default | Unset means true: hob can access external paths where the OS user has permission. An empty or invalid value prevents Host startup. |
| How to change it | Stop the Host, set the variable, then start it again. An additional launch cannot change the running Host's environment; ordinary relaunch helpers retain the policy. |
| What it governs | With false, hob-facilitated browsing, mentions, reads, rendering, creation, edits, rename, move, and deletion stay inside the active project/worktree, including checks against escaping symlinks. External requests get a policy error. Despite the historical READS name, mutations are covered too. |
| What it does not govern | Agent subprocess filesystem access. Set each backend's permissions and sandbox separately; use OS isolation for the machine-level boundary. |
Use the work from another device
Connect from your desktop app, the Web IDE, or hob mobile, and take control when prompted. Closing the app or the browser leaves the Host and its work running. Remote access explains the surface choice, device approval, and control handoff.
The Web IDE supports project switching; native new window actions are unavailable in the browser. A native hob invocation on a machine with a desktop can attach a window to the same headless Host.
Web steps need the desktop app
Web panes render only in the hob desktop app. Agent web steps (hob web act,
hob web flow run, waits and screenshots of web panes) and automations that
drive web pages therefore run on a headless Host only while a hob desktop app
is attached to it, on the same machine or from another one. The page's network
traffic then goes through the Host's network.
With no desktop app attached, or with only the Web IDE or hob mobile
connected, these steps fail at once with pane_unavailable (no desktop) and
say how to fix it: open the hob desktop app on this machine, or attach one from
another machine. If the desktop app disconnects during a step, that step fails
the same way.
Reconnect, reopen, or restart
hob elects one Host per canonical data directory. An ordinary invocation such as
hob /path/to/project submits a native launch request to that Host; it can attach
or focus a native presentation. It is not the way to choose a project on a VM
without a desktop. A second hob --headless joins the existing Host and stays
attached, while hob --headless --detach enables the service and exits.
Native windows attached to a headless service are presentation clients. Closing them does not stop that service. Use the foreground shutdown flow or your service manager when you intend to stop the Host.
A dropped browser connection needs a reconnect, not a new Host. After an actual Host restart, reopen the access URL and return to the saved work. Start any agent processes, terminal commands, or preview servers that ended; saved conversations and layouts are distinct from running processes.
For agents
Agents run on the host with its tools and backend configuration. They use the same hob CLI to open panes, run visible terminal commands, and bring results into the workspace you review remotely. Keep the working context in hob so the person can continue from whichever device controls it.
Security checklist
- Use a dedicated OS account and scope repository, cloud, and provider credentials to its work.
- Keep desktop connections and the Web IDE on Localhost only for an SSH tunnel, or use a trusted LAN/VPN.
- Restrict listener/firewall access; desktop connections and the Web IDE have no public relay mode.
- Set hob mobile to Internet only when you want phone access through
connect.hob.dev. - Keep access URLs and startup logs private; regenerate exposed credentials in Remote.
- Set file containment and backend permissions to match the host's intended use.