{ "version": "0.25.0", "pages": { "docs": { "eyebrow": "Quick start", "title": "Your terminal. Open anywhere.", "intro": "Start a session on your computer, then open it in any browser. Watch your agent, reply to a prompt, or bring in a teammate. No account needed.", "seo": { "description": "Start a session on your computer, then open it in any browser. Watch your agent, reply to a prompt, or bring in a teammate. No account needed.", "socialTitle": "Your terminal. Open anywhere. | shell.online", "socialDescription": "Start a session on your computer, then open it in any browser. Watch your agent, reply to a prompt, or bring in a teammate. No account needed." }, "cards": [ [ "1. Install on your computer", "Use the computer where your agent or command will run. Choose the command for its operating system.", [ [ "curl -fsSL https://shell.online/install | sh", "macOS, Linux, BSD or Solaris. Run in a terminal." ], [ "irm https://shell.online/install.ps1 | iex", "Windows. Run in PowerShell." ] ] ], [ "2. Start something to share", "Put `shell` before the command you normally use. Your agent must already be installed and signed in. This starts a new process; it does not attach to one that is already running.", [ [ "shell claude", "Start Claude Code." ], [ "shell codex", "Start Codex." ], [ "shell opencode", "Start OpenCode." ], [ "shell muse", "Start Muse Code." ], [ "shell -- npm run dev", "Or share another terminal command." ] ] ], [ "3. Open the link", "The terminal prints a link, password and QR code. Scan the QR code on your phone, or open the full link in another browser and enter the password.\n\nYou should see the same terminal output. You can type unless the session is read-only. Keep the host computer awake and connected to the internet." ], [ "Leave the tab. Keep the work.", "Closing the browser does not stop the process. Normal sessions run in the background. Reopen the link to return, or attach on the host computer.", [ [ "shell list", "Find your local sessions and their IDs." ], [ "shell attach ", "Return to a local session. Press Ctrl-X, then D to detach without stopping it." ], [ "shell kill -- ", "Stop that process and close its share." ] ] ], [ "Share only what you mean to", "An interactive link and its password let someone type with the process’s permissions. Give them only to people you trust. For watching without typing, start a read-only session.", [ [ "shell --read-only claude", "Watch-only browser access. Choose this when creating the session." ] ] ], [ "Ready for more?", "[Link your machines](/app/) to find sessions in one app. [Connect another agent](/agents/) with a separate MCP grant. If the view is blank or offline, [start here](/reliability/)." ] ] }, "platforms": { "eyebrow": "Install & update", "title": "Get shell.online on your computer.", "intro": "Install the CLI on the machine doing the work. Phones and other viewing devices need only a browser. Choose an install method, then start a session.", "seo": { "description": "Install the CLI on the machine doing the work. Phones and other viewing devices need only a browser. Choose an install method, then start a session.", "socialTitle": "Get shell.online on your computer. | shell.online", "socialDescription": "Install the CLI on the machine doing the work. Phones and other viewing devices need only a browser. Choose an install method, then start a session." }, "cards": [ [ "Install on macOS, Linux, BSD or Solaris", "The installer selects the right binary and checks its SHA-256 checksum. It does not run sudo or silently change your PATH.", [ [ "curl -fsSL https://shell.online/install | sh", "If the installer prints PATH instructions, follow them before opening a session." ] ] ], [ "Install on Windows", "Open PowerShell and run the installer. The CLI uses Windows’ native ConPTY terminal support.", [ [ "irm https://shell.online/install.ps1 | iex", "Works with the published x86, x64 and ARM64 builds." ] ] ], [ "Prefer Homebrew?", "Use the project’s tap. The tap can lag behind the direct installer; check `shell --version` when you need a particular release.", [ [ "brew tap teoslayer/shell-online https://github.com/TeoSlayer/shell.online", "Add the project’s tap." ], [ "brew trust --tap teoslayer/shell-online", "Approve the tap if your Homebrew version requires it." ], [ "brew install shell-online", "Install the CLI." ] ] ], [ "Build the CLI from source", "Install Git and Go 1.26.9 first. Clone the release tag, not an unpinned development branch. This builds the CLI only: you do not need Node.js or a local web server to use the hosted service. The Go build downloads the dependencies pinned by go.mod and go.sum.\n\nThe commands below assume a new checkout directory. On macOS, Linux and other Unix systems:", [ [ "git clone --depth 1 --branch v0.25.0 https://github.com/TeoSlayer/shell.online.git\ncd shell.online\ngo build -buildvcs=false -trimpath -ldflags=\"-X main.version=0.25.0\" -o shell ./cmd/shell\n./shell --version", "Expect version 0.25.0. Then use ./shell codex, ./shell claude, or your own command from this directory." ], [ "git clone --depth 1 --branch v0.25.0 https://github.com/TeoSlayer/shell.online.git\ncd shell.online\ngo build -buildvcs=false -trimpath -ldflags=\"-X main.version=0.25.0\" -o shell.exe ./cmd/shell\n.\\shell.exe --version", "Windows PowerShell: run these instead. Then use .\\shell.exe codex or another installed command." ], [ "Make it available elsewhere", "Move the built binary into a directory on your PATH if you want to type shell from anywhere. No sudo is needed when you choose a user-owned directory. Existing sessions are not restarted by a build." ], [ "Develop the website too?", "That is a separate build using Node.js and npm. See the repository’s [development instructions](https://github.com/TeoSlayer/shell.online#development). On MIPS64, keep Go 1.26.9: the repository documents a Go 1.27 runtime regression." ] ] ], [ "Check or update your version", "Run the same installer again to update an installer-managed copy. For Homebrew, use `brew upgrade shell-online`.\n\nUpdating the binary does not update hosts that are already running. Save your agent’s work and restart its Shell host when safe to use new host features. Do not stop an active task just to update.", [ [ "shell --version", "Check the executable your terminal is using." ] ] ], [ "Supported host systems", "These are release targets, not a promise that every device or agent runs on every architecture. Published checksums are in [SHA256SUMS](/downloads/SHA256SUMS).", [ [ "macOS", "amd64, arm64. Build-verified." ], [ "Windows", "386, amd64, arm64. Native runtime checks on amd64; other targets build-verified." ], [ "Linux", "386, amd64, armv5/6/7, arm64, loong64, mips, mipsle, mips64, mips64le, ppc64, ppc64le, riscv64, s390x. Runtime checks under QEMU." ], [ "FreeBSD", "386, amd64, armv7, arm64. Build-verified." ], [ "OpenBSD", "386, amd64, armv7, arm64, ppc64, riscv64. Build-verified." ], [ "NetBSD", "386, amd64, armv7, arm64. Build-verified." ], [ "DragonFly BSD", "amd64. Build-verified." ], [ "Solaris", "amd64. Build-verified." ] ] ], [ "Routers, small computers and ROS", "A supported binary still needs a working PTY and outbound HTTPS/WebSockets. Vendor firmware, kernel restrictions and storage can affect small Linux devices; QEMU checks do not cover those hardware differences.\n\nFor ROS, first load your usual ROS environment, then put `shell` before its command. Shell’s platform support does not extend ROS’s own support." ], [ "If the command is not found", "Follow the installer’s PATH instructions, open a new terminal, and try `shell --version`. Make sure you installed on the host computer—not on the phone you use to view it. Then [start your first session](/docs/)." ] ] }, "mobile": { "eyebrow": "Use your phone", "title": "Keep work moving from your phone.", "intro": "Open the share link in your phone’s browser. Read output, scroll back, and reply to your agent without moving its work off your computer.", "seo": { "description": "Open the share link in your phone’s browser. Read output, scroll back, and reply to your agent without moving its work off your computer.", "socialTitle": "Keep work moving from your phone. | shell.online", "socialDescription": "Open the share link in your phone’s browser. Read output, scroll back, and reply to your agent without moving its work off your computer." }, "cards": [ [ "Open your session", "Scan the QR code printed by the CLI. Or open the complete link and enter its password. A signed-in session listing is not a substitute for its terminal password." ], [ "Type and use terminal keys", "Tap the terminal to open your keyboard. Use the terminal key controls for keys your phone keyboard lacks. Ctrl-C interrupts the running command; it is not a copy shortcut here.\n\nCtrl-D can end a shell. The browser warns on the first press; repeating it within three seconds deliberately sends EOF." ], [ "Scroll without losing your place", "Drag with one finger to scroll terminal history. In full-screen programs that handle mouse input, gestures are sent as terminal wheel input instead. How that program scrolls depends on the program itself.\n\nIf rendering or input looks wrong, select the default xterm.js renderer and [check the recovery steps](/reliability/)." ], [ "Paste carefully", "Pasting sends text to the terminal; it may contain commands. Check what you are sending. Paste input is split into bounded 16 KiB frames and waits when the connection is busy." ], [ "Why the screen changes size", "Everyone sees one shared terminal grid. Any connected phone selects the portrait grid, including a read-only phone. The grid returns to desktop size when the last phone leaves.", [ [ "Desktop only", "120 columns × 36 rows." ], [ "Phone connected", "80 columns × 40 rows with a current host; older hosts use 80 × 24." ], [ "Resizing the browser", "Fits the shared grid to your screen. It does not give each viewer a separate terminal size." ] ] ], [ "Choose light or dark", "On a shared link, open Controls → Appearance and choose Light, Dark or System. The sun/moon button switches quickly. In the app, use Account → Appearance. Each site remembers your choice in this browser. System follows your device’s appearance; switching themes does not restart your terminal." ], [ "Paste on a phone", "Tap Paste in the terminal controls. Review the text, then choose Insert into terminal. If your browser cannot read the clipboard, touch and hold inside the text box and choose Paste. No Enter is added, but line breaks in the text can still run commands. You need input access; read-only viewers cannot paste." ], [ "Keep active sessions together", "On a shared link, open Controls and choose Sign up. Create an account and link your computer to find its sessions in the app. This does not share the current session’s password or automatically import someone else’s session." ], [ "Close the browser when you’re done", "Closing the tab leaves the task running. Keep the host computer awake and online. A sleeping laptop cannot be controlled until it reconnects. The session ends when its process exits." ] ] }, "app": { "eyebrow": "Sessions & teammates", "title": "Find your work in one place.", "intro": "The optional app brings sessions from linked computers into one list. Open a terminal, invite a teammate, and keep control of who gets access.", "seo": { "description": "The optional app brings sessions from linked computers into one list. Open a terminal, invite a teammate, and keep control of who gets access.", "socialTitle": "Find your work in one place. | shell.online", "socialDescription": "The optional app brings sessions from linked computers into one list. Open a terminal, invite a teammate, and keep control of who gets access." }, "cards": [ [ "1. Link your computer", "Create or sign into your account at [app.shell.online](https://app.shell.online/), then run this on the host computer. Complete the approval in your browser.", [ [ "shell auth", "Link this machine. Remote start is a separate choice during setup." ], [ "shell whoami", "Check the linked account." ] ] ], [ "2. Open a session", "Sessions started on linked machines appear in the app. Open one to view the same terminal. Tabs stay connected while you switch between them.\n\nTo decrypt a session, unlock your personal vault if it contains the password, or enter the session password. Seeing a listing alone does not reveal its encrypted contents.", [ [ "shell password ", "Recover an active session password on its host computer. Treat the printed value as a secret." ] ] ], [ "3. Bring in a teammate", "Invite the person to your organization, then assign or share the session as appropriate. Session responsibility, terminal passwords and MCP grants are different kinds of access.\n\nFor a plain browser share, give your teammate the complete link and password. If someone should only watch, create a [read-only session](/security/)." ], [ "Start sessions from the browser", "Only an approved, online machine can accept a browser-start request. The process runs on that machine—not on an app server. Enabling this grants remote execution authority; choose it deliberately.", [ [ "shell auth --allow-remote-start", "Allow your signed-in browser to start sessions on this machine." ], [ "shell auth --no-remote-start", "Link the account without allowing remote start, or withdraw that permission." ], [ "shell daemon status", "Check the local listener." ], [ "shell daemon stop", "Pause the listener. A later Shell command can start it again." ], [ "shell service uninstall", "Remove the installed background service. This is separate from account access." ] ] ], [ "Use your personal vault", "The vault is per account, not per organization. It stores encrypted password copies and unlocks in your browser with its password or a supported PRF passkey. Keep your recovery key somewhere safe.\n\nA teammate does not automatically receive your vault. If every owner-held password and recovery copy is lost, the service cannot recover them." ], [ "Understand the session state", "A session’s status describes reachability, not whether an agent completed its task.", [ [ "Online / Starting", "The host is connected or starting." ], [ "Offline / Unavailable", "The app cannot currently reach a usable host. Check the machine before assuming the process stopped." ], [ "Finished", "A known process exit. It is not proof that the requested work succeeded." ] ] ], [ "Automation is a separate permission", "Owners can set team MCP, daily-briefing and briefing-sharing preferences in the app or CLI. The switches are independent.\n\nIn this release, daily-briefing consent can allow an updated host to publish an owner-encrypted title and existing response excerpt for a supported, explicitly resumed OpenCode conversation. It does not prompt an agent or generate a new summary. Team delivery and a team MCP gateway are not implemented. [See the exact limits](https://github.com/TeoSlayer/shell.online/blob/main/docs/session-content.md).", [ [ "shell permissions ", "Read the session’s automation preferences." ], [ "shell permissions --daily-briefing=true", "Change only daily-briefing consent." ], [ "shell briefings on --all", "Set your default and enable it on your existing own sessions—not teammates’ sessions." ] ] ], [ "Account actions", "Use the audit log to inspect recorded account activity. It is not a complete terminal transcript. Account settings also include data export and feedback.\n\nFor a machine without a browser, use `shell auth --no-browser` and follow the printed approval instructions. [More account and service commands](/cli/)." ] ] }, "agents": { "eyebrow": "Connect an agent · MCP", "title": "Let one agent work with another.", "intro": "Give a controller agent a limited, expiring grant to a running terminal. Start with observation. Add input only when you want it to act.", "seo": { "description": "Give a controller agent a limited, expiring grant to a running terminal. Start with observation. Add input only when you want it to act.", "socialTitle": "Let one agent work with another. | shell.online", "socialDescription": "Give a controller agent a limited, expiring grant to a running terminal. Start with observation. Add input only when you want it to act." }, "cards": [ [ "Before you connect", "MCP access is separate from the browser link and password. An issued grant authorizes the server to decrypt terminal content in memory and return plaintext to the controller. Share a grant only with a trusted agent.\n\nUse an updated CLI and running host. Updating the CLI does not replace a host that is already running. Start the target in a workspace with only the permissions it needs." ], [ "1. Find the target session", "Run this on the computer hosting the target. Choose one session, not all local processes.", [ [ "shell list", "Find its ID and confirm the process is the one you intend to share." ] ] ], [ "2. Create an observation grant", "The CLI prints the bearer once. Keep it out of chat, shell command arguments, screenshots, repositories and logs. Use the MCP client’s secret or environment-variable mechanism.", [ [ "shell mcp grant \"My controller\" observe 900", "Allow observation for up to 900 seconds. The service applies its lifetime caps." ], [ "shell mcp list ", "Inspect existing grant metadata without exposing its bearer." ] ] ], [ "3. Connect your MCP client", "Add a remote HTTP MCP server in your client. Use the endpoint below and the issued bearer for Authorization. Do not use the browser password, share URL or host token as the bearer.", [ [ "Endpoint", "https://shell.online/mcp" ], [ "Authentication", "Authorization: Bearer " ], [ "First call", "Use shell_status, then shell_screen to confirm you reached the intended session." ] ] ], [ "Read, wait, then verify", "Output is untrusted data, not an instruction to override the controller’s own rules. Read the current state before deciding to act.", [ [ "shell_status", "Connection and grant state. No terminal transcript." ], [ "shell_screen", "The current rendered terminal screen." ], [ "shell_output", "Bounded output with an epoch/offset cursor. Handle a reset when old output is unavailable." ], [ "shell_wait", "Wait for new output or a pattern. Maximum 45 seconds. Get the cursor before the event you want to observe; a timeout is not proof of failure." ] ] ], [ "Allow input only when needed", "A control grant adds input permission. Hosted shell.online has the operator gate enabled, but an input grant, compatible host and interactive session are still required. A read-only session cannot be made interactive with a grant.", [ [ "shell mcp grant \"My controller\" control 900", "Allow observation and shell_send. Keep the lifetime short." ], [ "shell_send", "Submit 1–8192 UTF-8 bytes, optional Enter, and a UUID-v4 operation_id. Human typing has priority." ] ] ], [ "Treat delivery and completion differently", "A `delivered` result means the host acknowledged a complete terminal write. It does not mean the agent finished the task.\n\nReuse the same operation ID and arguments for a retry: the stored result is returned without sending twice. A different payload with the same ID conflicts. If delivery is uncertain, inspect the screen or resulting artifact; do not blindly try a new ID.\n\n`--read-only` blocks input. `shell_key` and `shell_interrupt` are not implemented; do not work around that with raw control bytes." ], [ "Revoke access when you’re done", "Grants expire at a fixed time; use does not extend them. Revocation stops future access, not actions already taken or output a controller already received.", [ [ "shell mcp revoke ", "Revoke one grant." ], [ "shell mcp revoke-all ", "Remove every MCP grant for this session. Browser sharing is separate." ], [ "shell password rotate ", "Rotate browser credentials and revoke existing MCP grants without restarting the process." ] ] ], [ "Client and hosting limits", "Codex and OpenCode have been exercised with the observation path; OpenCode has also been used in control demonstrations. Do not treat that as a guarantee for every client transition. Claude model-backed behavior remains unverified.\n\nThe native MCP route is implemented by the Worker relay, not the standalone Docker relay. Refstream’s browser invitation is a separate experimental connector. [Operator setup and security details](https://github.com/TeoSlayer/shell.online/blob/main/docs/MCP.md)." ] ] }, "reliability": { "eyebrow": "Fix a connection", "title": "Get back to your session.", "intro": "Start with what you can see. A browser disconnect, an offline host and an exited process need different fixes. Check before restarting anything.", "seo": { "description": "Start with what you can see. A browser disconnect, an offline host and an exited process need different fixes. Check before restarting anything.", "socialTitle": "Get back to your session. | shell.online", "socialDescription": "Start with what you can see. A browser disconnect, an offline host and an exited process need different fixes. Check before restarting anything." }, "cards": [ [ "The page says offline", "Check that the host computer is awake, online and still running the process. The CLI and browser retry temporary connection failures automatically.\n\nOn the host, use the local session list. A stale app row is not proof that a process is still alive.", [ [ "shell list", "Check local process and relay state separately." ], [ "shell attach ", "If the local session is alive, inspect it without relying on the browser. Detach with Ctrl-X, then D." ] ] ], [ "The terminal is blank or looks wrong", "Wait for the reconnect snapshot, then try reopening the view. If you selected Refstream, switch back to xterm.js. Check whether the running host predates your installed CLI.\n\nInstalling an update does not restart hosts. Save work and arrange a safe restart if a host update is needed. Never kill all sessions to fix one view." ], [ "The password no longer works", "Use the complete link, including its `#salt=` fragment, and the current password. Password rotation changes both the salt and password and disconnects old viewers.\n\nIf the app has a sealed copy, unlock your personal vault. Otherwise recover the password on the host.", [ [ "shell password ", "Print the active password locally. Do not put it in a bug report." ] ] ], [ "You cannot type", "Check whether the session was created read-only or another person currently holds input. A read-only session requires a new interactive share if its owner wants typing enabled.\n\nFor MCP, check the grant scope, expiry and host version. [MCP setup](/agents/) explains the additional input requirements." ], [ "A command exits before you get a link", "Very short tasks may finish during startup. The CLI reports their exit status instead of printing a dead link. Try a longer-running process or start a fresh shell.", [ [ "shell", "Start an interactive shell to test the share path." ] ] ], [ "What survives a disconnect", "The process runs on your computer. A temporary browser or network failure does not intentionally stop it. Current hosts keep bounded screen state and restore the screen when viewers return.\n\nAn ordinary disconnected share can recover its link for 12 hours. A known task exit closes the ordinary share. A persistent identity can be reused, but it is not a process checkpoint." ], [ "High output and nested terminals", "Display queues are bounded. When output outruns the connection or renderer, stale display work may be replaced by a fresh screen snapshot rather than an unlimited transcript.\n\nCurrent snapshot handling suppresses replies to old terminal queries. It is designed for full-screen programs, tmux and nested terminal use, but a specific application can still expose a compatibility bug." ], [ "Report a useful bug", "Use Report in the shared terminal, or [send feedback](https://app.shell.online/feedback). No account is required. Signed-in users can choose to send without their account or email; anonymous reports cannot receive replies. Terminal text, passwords and sharing links are not attached automatically.\n\nInclude your CLI version, operating system, browser, renderer and a small reproduction that contains no private work. Say whether the problem happens locally, in a browser, or only after reconnecting. Remove share links, passwords, tokens and raw terminal logs before sending feedback or [opening an issue](https://github.com/TeoSlayer/shell.online/issues)." ] ] }, "security": { "eyebrow": "Share safely", "title": "Choose who can watch. Choose who can type.", "intro": "A shared terminal gives real access to a process on your computer. Keep credentials private, use read-only when possible, and understand the MCP boundary.", "seo": { "description": "A shared terminal gives real access to a process on your computer. Keep credentials private, use read-only when possible, and understand the MCP boundary.", "socialTitle": "Choose who can watch. Choose who can type. | shell.online", "socialDescription": "A shared terminal gives real access to a process on your computer. Keep credentials private, use read-only when possible, and understand the MCP boundary." }, "cards": [ [ "Start with the access you need", "Interactive access is the default. Anyone with the complete link and password can view and type with the wrapped process’s operating-system permissions.\n\nFor demos, reviews or a second screen that only needs to watch, create a read-only session.", [ [ "shell --read-only claude", "Input is rejected by both the relay and the CLI. A modified browser cannot turn this into an interactive session." ] ] ], [ "Keep the link, password and QR private", "The QR code includes the password for one-scan access. Treat it like the link and password together. Do not put it in a public screenshot.\n\nRemoving someone from an account cannot erase a password they already know. Rotate active session credentials when that access must end.", [ [ "shell password rotate ", "Disconnect old viewers, change the password and salt, and revoke existing MCP grants. The process keeps running." ] ] ], [ "Files require their own opt-in", "Files are not shared by default. `--files` exposes regular files under the working directory; `--files-root` chooses a root. Requests are checked on the host, including traversal and symlink-escape checks.\n\nRead-only terminal access does not cancel file access you explicitly enabled. Choose the root carefully." ], [ "What the service can see", "With default E2EE, the host encrypts terminal payloads before the relay forwards them. The relay carries authenticated ciphertext, plus visible connection metadata.", [ [ "Visible metadata", "Connection IPs, timing, encrypted sizes, frame types, labels, access mode, lifecycle and terminal grid dimensions." ], [ "MCP exception", "Issuing a grant authorizes server-side, in-memory decryption. The controller receives plaintext results. The browser disclosure remains for the grant’s lifetime." ], [ "No-E2EE exception", "An explicit --no-e2ee session exposes terminal contents to the relay. HTTPS/WSS still protects the network hop." ] ] ], [ "What is retained", "The host keeps bounded screen/replay state. The hosted relay also keeps a bounded last-screen cache for offline viewing: ciphertext in E2EE mode, potentially plaintext with `--no-e2ee`.\n\nMCP’s durable records contain bearer hashes, grant metadata and operation fingerprints/outcomes—not plaintext terminal contents, bearers or frame keys. Ordinary task exit deletes its relay session state. This is not a full-history archive." ], [ "Encryption does not remove every trust", "The browser code served by the website is trusted while you view a terminal or unlock your vault. E2EE does not protect against malicious code on either endpoint, or hide traffic timing.\n\nBrowser-started processes also trust the account service after you explicitly enable remote start. Use a restricted workspace and local permissions appropriate to the task." ], [ "If you shared too much", "Rotate a leaked browser password; revoke a leaked MCP grant. Stop the specific target if its actions are unsafe. These actions cannot undo earlier commands or remove copies someone already made.\n\n[Encryption details](/e2ee/) explain key derivation and replay protection. [MCP access](/agents/) explains grants and uncertain delivery." ] ] }, "e2ee": { "eyebrow": "Passwords & encryption", "title": "Keep terminal contents private.", "intro": "Encryption is on by default. Your computer encrypts terminal data and authorized browsers decrypt it. MCP grants deliberately add a separate decryption path.", "seo": { "description": "Encryption is on by default. Your computer encrypts terminal data and authorized browsers decrypt it. MCP grants deliberately add a separate decryption path.", "socialTitle": "Keep terminal contents private. | shell.online", "socialDescription": "Encryption is on by default. Your computer encrypts terminal data and authorized browsers decrypt it. MCP grants deliberately add a separate decryption path." }, "cards": [ [ "Use the generated password", "A normal session generates a random ten-character base64url password. The CLI prints it with the share link. The QR code includes it for one-scan access.\n\nFor sensitive or longer-lived work, use a longer unique password through `SHELL_ONLINE_E2EE_PASSWORD`. Do not reuse an account password or put the value in logs." ], [ "Recover an active password", "On the host computer, retrieve the password from its local session record. If you enabled your account’s personal vault, a sealed copy may also be available there.", [ [ "shell password ", "Reveal one session password deliberately. The service has no recovery backdoor if all owner-held copies are lost." ] ] ], [ "Rotate without restarting the task", "Rotation changes the password, URL salt and cipher generation. Current viewers disconnect, old MCP grants are revoked, and persistent state and the owner’s vault copy are updated.", [ [ "shell password rotate ", "Share the new complete link and password only with people who should retain access." ] ] ], [ "How keys are made", "The link’s `#salt=` fragment contains a random salt. The host and browser derive the AES-256-GCM frame key locally using PBKDF2-HMAC-SHA256 with 600,000 iterations.\n\nURL fragments are not part of HTTP requests. The QR’s password remains sensitive to anyone who sees the QR. Ten random base64url characters provide 60 bits of randomness; a longer unique password is preferable for sensitive, long-lived sessions." ], [ "Encrypted content and visible metadata", "Terminal input, output, snapshots and latency probes are authenticated ciphertext. Current envelope-v2 frames bind direction, sender stream and sequence so receivers reject duplicate or stale frames.\n\nThe relay can still delay or drop traffic. It sees timing, addresses, encrypted sizes, labels and lifecycle metadata. Grid dimensions travel in plaintext control messages: `terminal_size` to viewers, the host's own `terminal_grid`, and a viewer's `grid_request`." ], [ "MCP changes who can decrypt", "A host-issued MCP grant supplies the server with the authority to decrypt in memory for that grant’s lifetime. The controller receives plaintext output. This is why the browser visibly says server-side decryption is authorized.\n\nRevoking grants removes future MCP access; it does not erase results already received. [Create or revoke a grant](/agents/)." ], [ "Vault and browser storage", "The optional vault keeps encrypted password copies per account. Unlocking happens in the browser. A vault password, supported PRF passkey or recovery key is needed; team membership alone is not enough.\n\nThe current browser password cache is memory-only. A reload needs the vault or password again. A legacy password blob may remain as a read-only migration source until it can be migrated safely; this does not mean new passwords are written there." ], [ "Turning encryption off", "`--no-e2ee` is an explicit compatibility/debugging choice, not the default. The relay can then read terminal contents. It conflicts with password overrides and persistence. Avoid it for private work." ] ] }, "docker": { "eyebrow": "Keep a Docker workspace", "title": "A workspace with a link you can reuse.", "intro": "Run a shared terminal in a container. Named volumes keep its workspace and session identity across container restarts—not the memory of a running process.", "seo": { "description": "Run a shared terminal in a container. Named volumes keep its workspace and session identity across container restarts—not the memory of a running process.", "socialTitle": "A workspace with a link you can reuse. | shell.online", "socialDescription": "Run a shared terminal in a container. Named volumes keep its workspace and session identity across container restarts—not the memory of a running process." }, "cards": [ [ "1. Get the project", "You need Docker with Compose. Clone the project and use the Compose file in its root. This runs a client of the hosted relay, not your own relay.", [ [ "git clone https://github.com/TeoSlayer/shell.online.git\ncd shell.online", "Open the repository directory." ] ] ], [ "2. Start the container", "The first launch prints the browser link and generated password. The logs contain credentials: read them privately, not in a shared report.", [ [ "docker compose up --build -d", "Build and start the container." ], [ "docker compose logs shell-online", "Read the session link and password." ] ] ], [ "3. Open the session", "Open the printed link in your browser and enter the password. The default configuration keeps state and workspace in separate named volumes.", [ [ "shell-online-state", "Host identity, browser password and encryption material. Protect this volume and its backups as secrets." ], [ "shell-online-workspace", "The files you work on inside the container." ] ] ], [ "What a restart preserves", "The container reuses its saved link and password, then starts a new terminal process. It does not restore an agent’s in-memory conversation or a running job.\n\nA saved identity can be revived from its state volume after the relay’s offline retention expires. Deleting that volume loses the saved identity. Do not use volume deletion as a routine restart step." ], [ "Choose or rotate a password", "You may set a longer `SHELL_ONLINE_E2EE_PASSWORD` before first launch. Restarts reuse saved credentials. To change an active password, run `shell password rotate ` inside the running container; an environment change alone does not rotate stored state." ], [ "Want your own server instead?", "The root Compose file connects to hosted shell.online. To run your own relay and domain, follow [Run your own relay](/self-hosting/)." ] ] }, "refstream": { "eyebrow": "Try Refstream · alpha", "title": "An optional terminal view.", "intro": "xterm.js is the default. Refstream adds experimental terminal tools and a browser-mediated agent connector. Switch back if your program does not behave correctly.", "seo": { "description": "xterm.js is the default. Refstream adds experimental terminal tools and a browser-mediated agent connector. Switch back if your program does not behave correctly.", "socialTitle": "An optional terminal view. | shell.online", "socialDescription": "xterm.js is the default. Refstream adds experimental terminal tools and a browser-mediated agent connector. Switch back if your program does not behave correctly." }, "cards": [ [ "Choose a renderer", "Open Terminal controls and select Refstream (unstable alpha), or use the Renderer selector in an app terminal tab. The choice is saved for that browser.\n\nSwitching changes the browser view. It does not restart the process, change encryption or grant extra permissions. This build includes Refstream v0.1.0-alpha.5." ], [ "Search and inspect output", "Refstream offers literal search, text sizing, themes, a back-to-live shortcut and retained-output download. Command inspection needs OSC 133 shell markers from the program; it cannot reliably infer commands or exit status from arbitrary text." ], [ "Connect an agent from the browser", "The Connect agent invitation is private, short-lived and revocable. Choose read access or read-and-control. Reuse the returned connector session for follow-ups instead of pairing again each time.\n\nThis is not the native `/mcp` bearer channel. Its invitation and tools are different. For the host-managed MCP route, use [Connect an agent](/agents/)." ], [ "Know when a task is really done", "A stable task ID protects a retry from submitting the same prompt twice. A delivery acknowledgement, output burst or quiet terminal is not proof of completion.\n\nA generic terminal view cannot safely infer an agent’s editor state. Local keyboard activity and stale sequence guards can block remote input; do not bypass them." ], [ "Files and saved output", "File access still needs an explicit host `--files` or `--files-root` setting. A filename printed in terminal output does not grant access to it.\n\nCurrent Shell integration keeps terminal recovery state in memory, not new localStorage/sessionStorage snapshots, and purges legacy Refstream cache entries. Reload re-syncs from the host’s live screen. Exported output is a separate copy you must protect." ], [ "If something looks wrong", "Switch back to xterm.js. Refstream does not implement every xterm behavior or addon. For a report, include a minimal reproduction without private output or credentials.\n\n[Upstream release](https://github.com/TeoSlayer/refstream.js/releases/tag/v0.1.0-alpha.5) · [Connector protocol](https://github.com/TeoSlayer/refstream.js/blob/v0.1.0-alpha.5/docs/agents.md)." ] ] }, "self-hosting": { "eyebrow": "Run your own relay", "title": "Use your own server and domain.", "intro": "The standalone relay runs with Docker and Caddy on one host. Your CLI stays the same; point it at your server. Accounts and native MCP are separate deployments.", "seo": { "description": "The standalone relay runs with Docker and Caddy on one host. Your CLI stays the same; point it at your server. Accounts and native MCP are separate deployments.", "socialTitle": "Use your own server and domain. | shell.online", "socialDescription": "The standalone relay runs with Docker and Caddy on one host. Your CLI stays the same; point it at your server. Accounts and native MCP are separate deployments." }, "cards": [ [ "Before you start", "You need Docker with Compose, a domain pointing at the server, and ports 80/443 reachable for HTTPS. The standalone relay is single-node. It is not the optional accounts app or the native Worker MCP implementation." ], [ "1. Get the standalone deployment", "Use the `standalone` directory, not the root Compose file. The root file starts a terminal client; this one runs a relay.", [ [ "git clone https://github.com/TeoSlayer/shell.online.git\ncd shell.online/standalone", "Prepare the relay on your server." ] ] ], [ "2. Set your public domain", "Replace the example domain with your own. Caddy obtains HTTPS certificates when DNS and ports are ready.", [ [ "SHELL_ONLINE_PUBLIC_URL=https://relay.example.com SHELL_ONLINE_SITE=relay.example.com docker compose up -d --build", "Start the relay and HTTPS proxy." ] ] ], [ "3. Start a session through it", "On the computer doing the work, select your relay. Keep HTTPS for a real deployment.", [ [ "shell --server https://relay.example.com claude", "The generated link points at your server." ] ] ], [ "Try it locally first", "For a loopback-only trial, the default Compose settings use HTTP localhost. This is not a public deployment configuration.", [ [ "docker compose up -d --build", "Run from the standalone directory." ], [ "curl http://localhost/api/health", "Check the local relay response." ] ] ], [ "Protect state and keep one replica", "The `relay-state` volume contains session metadata and host-token hashes, not browser passwords or E2EE frame keys. Back it up. Do not run multiple relay replicas against the same state file.\n\nLive sockets reconnect after a restart. The standalone relay stores metadata, not a terminal transcript. Default E2EE still happens between the host and browser." ], [ "Configuration reference", "Trust forwarded addresses only when the relay is behind your own trusted proxy.", [ [ "SHELL_ONLINE_PUBLIC_URL", "Exact public origin used in links and browser-origin checks." ], [ "SHELL_ONLINE_SITE", "Caddy hostname for HTTPS; http://localhost for local tests." ], [ "SHELL_ONLINE_STATE_FILE", "Metadata file path. Default /var/lib/shell-online/relay.json." ], [ "SHELL_ONLINE_TRUST_PROXY", "Enabled by the supplied proxy deployment. Do not expose that trust directly to untrusted clients." ] ] ], [ "Cloudflare and accounts", "The Worker deployment is also available and provides the native MCP channel with its required bindings and keys. An accounts app needs its own identity provider and PostgreSQL.\n\nFollow the [operator guide](https://github.com/TeoSlayer/shell.online/blob/main/docs/self-hosting.md) for these deployments. The terminal relay works without an account." ] ] }, "cli": { "eyebrow": "Command reference", "title": "Find the command you need.", "intro": "A task-first reference for the Shell CLI. Start with the common commands below; flags and technical details follow. Commands run on the host computer.", "seo": { "description": "A task-first reference for the Shell CLI. Start with the common commands below; flags and technical details follow. Commands run on the host computer.", "socialTitle": "Find the command you need. | shell.online", "socialDescription": "A task-first reference for the Shell CLI. Start with the common commands below; flags and technical details follow. Commands run on the host computer." }, "cards": [ [ "Start a session", "`shell` starts a process in a local terminal and shares it. Use `--` to separate Shell options from the program’s arguments.", [ [ "shell [arguments...]", "Share a new process in the background." ], [ "shell", "Start your default shell. On Windows, PowerShell is preferred, then COMSPEC." ], [ "shell --foreground claude", "Keep local foreground interaction while sharing." ], [ "shell --read-only claude", "Allow browser viewing, not input." ], [ "shell --name \"Review\" -- codex", "Give the session a readable name." ] ] ], [ "Find, attach and stop", "Local and account lists are different. Use a full ID or an unambiguous local prefix of at least six characters.", [ [ "shell list", "Local sessions and relay state." ], [ "shell list --json", "Local JSON on stdout. Can contain e2ee_password; treat it as secret." ], [ "shell ls", "Open sessions in your linked account." ], [ "shell ls --all", "Include ended account sessions." ], [ "shell ls --json", "Account metadata as JSON, without session passwords." ], [ "shell attach ", "Attach locally. Ctrl-X, then D detaches; Ctrl-] is a legacy alternative." ], [ "shell kill -- ", "Stop one session. The -- also handles IDs beginning with a dash." ], [ "shell kill --all", "Stops every locally managed session. Do not use it to clean up a single test." ] ] ], [ "Passwords", "The complete share link and password grant browser access. Do not print them into shared logs.", [ [ "shell password ", "Reveal the active browser password locally." ], [ "shell password rotate ", "Change password, salt and cipher generation; disconnect viewers and revoke MCP grants without restarting the task." ] ] ], [ "Account and remote start", "Account linking is optional. Remote start grants additional authority to run commands on this machine.", [ [ "shell auth", "Link your machine through browser approval." ], [ "shell auth --no-browser", "Print the approval URL and follow the callback instructions." ], [ "shell auth --allow-remote-start", "Enable browser-started sessions deliberately." ], [ "shell auth --no-remote-start", "Disable that capability." ], [ "shell whoami", "Show the linked account." ], [ "shell logout", "Unlink and revoke the account token." ], [ "shell daemon status", "Check the background listener." ], [ "shell daemon start", "Start the listener when authorized." ], [ "shell daemon stop", "Stop the listener; a later Shell command may start it again." ], [ "shell agent", "Run the listener in the foreground." ], [ "shell service install", "Install background service availability." ], [ "shell service status", "Inspect the installed service." ], [ "shell service uninstall", "Remove the background service." ] ] ], [ "MCP grants", "A bearer is not a browser password. The grant permits server-side decryption for the controller. [Read the MCP workflow](/agents/) before granting input.", [ [ "shell mcp grant \"Controller\" observe 900", "Create an expiring observation grant; bearer printed once." ], [ "shell mcp grant \"Controller\" control 900", "Add input permission when the host and operator allow it." ], [ "shell mcp list ", "List grant metadata." ], [ "shell mcp revoke ", "Revoke one grant." ], [ "shell mcp revoke-all ", "Revoke this session’s MCP grants." ] ] ], [ "Automation preferences", "Only the session owner can change these settings. Unspecified switches are preserved. Consent does not imply a new agent summary or a team MCP gateway is running.", [ [ "shell permissions ", "Read the three independent preferences." ], [ "shell permissions --daily-briefing=true", "Allow supported daily content publication." ], [ "shell permissions --mcp-team-access=true", "Set team MCP consent; the team gateway is not implemented in this release." ], [ "shell permissions --briefing-team-access=true", "Set separate team-briefing consent; current excerpt delivery remains owner-only." ], [ "shell briefings status", "Read your default for new sessions." ], [ "shell briefings on --all", "Enable the default and your existing own sessions." ], [ "shell briefings off", "Disable the default. Add --all to also update your existing own sessions." ] ] ], [ "Start flags", "Put these before the wrapped command. Options that control access are chosen at session creation.", [ [ "--read-only", "Reject browser and MCP input." ], [ "--name ", "One-line session label, up to 120 characters." ], [ "--foreground", "Mirror and control the process in the launching terminal." ], [ "--persistent ", "Reuse a saved identity, password and URL. Does not restore process memory." ], [ "--files", "Allow on-demand regular-file access under the working directory. Requires E2EE." ], [ "--files-root ", "Use another explicitly chosen file root." ], [ "--auto-close ", "Set an earlier deadline; task exit still closes the share." ], [ "--json", "New-session JSON goes to stderr and includes e2ee_password for encrypted sessions." ], [ "--server ", "Override the relay URL." ], [ "--e2ee", "Compatibility flag; encryption is already the default." ], [ "--no-e2ee", "Disable payload encryption explicitly. Conflicts with password overrides and persistence." ], [ "--version", "Print the CLI version." ], [ "-h, --help", "Show help." ] ] ], [ "Set an auto-close deadline", "A deadline cannot keep a task alive after it exits. Missing or invalid values return exit status 2.", [ [ "shell --auto-close 30m claude", "Close after a relative duration." ], [ "Relative values", "ms, s, m, h, d, w, mo, y. Examples: 1h30m or 2d 3h." ], [ "Date and time", "today 18:30, tomorrow 09:00, local ISO-like dates, RFC3339, or the next occurrence of HH:MM." ] ] ], [ "Environment variables", "Use these only on the host. Password values are secrets; do not include them in bug reports.", [ [ "SHELL", "Default command on Unix when no command is supplied." ], [ "SHELL_ONLINE_SERVER", "Default relay URL; --server overrides it." ], [ "SHELL_ONLINE_E2EE_PASSWORD", "Choose a unique browser password instead of the generated one." ], [ "SHELL_ONLINE_INSTALL_DIR", "Installer-only absolute writable destination." ] ] ], [ "Output and exit status", "A fast-exiting task reports its exit status without printing a dead link. New-session JSON is on stderr; list JSON is on stdout. Redirect each deliberately and keep credential-bearing output private.", [ [ "e2ee_password", "Included in encrypted start/local-list JSON. Not an MCP bearer." ], [ "0", "Successful start, or a fast task that exited successfully." ], [ "1", "Operational failure." ], [ "2", "Invalid flags or arguments." ] ] ], [ "Help and aliases", "The executable has an offline reference. Aliases do not change permissions or behavior.", [ [ "shell help reference", "Read the full built-in reference." ], [ "shell help ", "Ask about a command or topic, such as start, files, attach, password, e2ee or docker." ], [ "shell ps", "Alias for shell list." ], [ "shell stop ", "Alias for shell kill." ] ] ] ] } } }