Appearance
iBoB kit
bob ibob checkgrades the declared phone setup against every machine it targets, read-only.bob ibob attach <machine>lists the live warp and cdfork sessions there with the command to type on the phone. The steps are in Set Up the iBoB Terminal Kit. (Back to reference index.)
The kit file
Operator data at config/ibob-kit.json in the operator repo (#2270), reached through operatorPath('ibob-kit.json'), validated by schemas/ibob-kit.schema.json and graded by check-operator.js. The product ships the schema and a template, templates/ibob/ibob-kit.json. No key material is stored: a key is named and fingerprinted only.
| Field | Meaning |
|---|---|
tailscale.app, tailscale.docs | The tailnet client on the phone. Every target is reached over the tailnet (decision #1773). |
client.name, client.transports, client.docs | The SSH/mosh app and what it speaks, in preference order. With mosh first, the check requires mosh-server on every target and attach prints a mosh command. |
remote_control.supported, remote_control.docs | Claude's own Remote Control for driving a Claude Code session from the Claude iOS app. BoB builds no replacement. |
devices[].id, label | One entry per phone or tablet. |
devices[].key.name, fingerprint, comment | The device's key. The SHA256: fingerprint (as ssh-keygen -lf prints it) is matched against each target's authorized_keys; without one, the comment (else the name) is. |
devices[].key.inventory_id | The credential in secrets-inventory.json that declares the key. |
devices[].authorized_on | machines.json ids whose authorized_keys must hold the key. |
attach.default_targets | machines.json ids probed and offered first. |
attach.user | The login user on the targets, when it is not the client's default. |
bob ibob check
bob ibob check [--machine <id>] [--json]Declaration rows (no network): the kit file exists and is schema-valid; each target is a machines.json id; each device key is a credential in secrets-inventory.json with an ssh-key location, and a secrets[] entry of operator.json with the same inventory_id — so bob secrets check reports it.
Per machine, in order, stopping at the first gate that fails:
| Check | Pass when | Fix named on failure |
|---|---|---|
tailnet | tailscale status --json lists the machine online | install Tailscale here / wake the machine / fix its tailscale_name |
ssh | one SSH call through scripts/fleet/audit.js sshRun succeeds | macOS: turn on Remote Login (reported, never enabled); Linux: start sshd; a refused key: authorize this machine's key |
key:<device> | the device key's fingerprint is in ~/.ssh/authorized_keys | append the device's public key |
mosh | mosh-server is on PATH (graded only when the client prefers mosh) | brew install mosh / sudo apt install mosh |
tmux | tmux is on PATH | brew install tmux / sudo apt install tmux |
The same SSH call lists the live tmux sessions with seg-windows.js list on the target (the one session parser), filtered to BoB's: warp-* (including warp-seg-*) and cdfork-*. Sessions are listed, never graded. A target without BoB deployed, or on a BoB older than seg-windows.js list, is noted (with "deploy" as the fix), not failed and never shown as "none live".
The machine running the check is probed locally when SSH refuses this machine's own key: "Permission denied" already proves the SSH server is up (Remote Login on), and the phone authenticates with its own key, so the authorized_keys, mosh-server, tmux and session probes read this machine directly. On any other machine a refused key is an ssh failure.
--json prints one ibob-kit/1 document: kit {path, source, exists}, ok, declaration[] {check, subject, ok, detail, fix}, and machines[] {id, tailscale_name, os, checks[] {check, ok, detail, fix}, sessions[], ok}.
| Exit | Meaning |
|---|---|
| 0 | converged — every declaration row and every machine check passes |
| 1 | drift — a missing or invalid kit, an undeclared key, or a failed check |
| 2 | usage — an unknown flag, or --machine that is not a kit target |
bob ibob attach
bob ibob attach <machine> [--json]Lists the live warp and cdfork sessions on one machine, each with the command to type in the phone client: mosh <host> -- tmux attach -t <session> when the client prefers mosh, else ssh -t <host> tmux attach -t <session> (<host> is the machine's tailscale_name, prefixed by attach.user@ when declared). --json prints ibob-attach/1: machine, ok, sessions[] {session, command}, error, fix. Exit 0 when at least one session is listed, 1 when none is live or the machine cannot be reached (the fix is printed), 2 on usage.
Remote Control
Driving a Claude Code session from the phone is Claude Remote Control: claude --remote-control (or /rc in a running session) on the machine, then the session in the Claude iOS app. It needs a claude.ai login on a Pro, Max, Team or Enterprise plan. The kit records it as the supported route; BoB adds nothing to it.
Tests
tests/test-ibob-kit.js drives bin/bob ibob in a throwaway HOME and operator repo with tailscale and ssh stubbed: converged, every drift with its fix, an offline peer, an absent and an invalid kit, usage exits, and attach. It also stages each failure the Run BoB from Your iPhone tutorial quotes and asserts every quoted line is what the check really prints.