Let a Coding Agent Share Its Own Terminal Session in the Browser: the shell.online Skill and shell --json
Two things shipped today that point in opposite directions. OpenAI told its DevDay audience that the Codex app now runs fully in the cloud, so a laptop can be closed while the agent works. Docker published its first tagged releases of a skills repository that teaches coding agents to build and debug containers on your own machine. The second world still needs a way for a human to look at what the agent is doing. The shell.online agent skill covers that case: it tells an agent how to share a terminal session in the browser, then hand its operator the link and password in the conversation it is already having.
Skills became the way you teach an agent a tool, and Docker joined today
The Agent Skills format is a folder with a SKILL.md file. The file carries metadata, at minimum a name and a description, followed by instructions, and it may bundle scripts and reference material. Agents load skills by progressive disclosure: at startup only the name and description are read, the full instructions are pulled in when a task matches, and any bundled files are read during execution. Anthropic developed the format and released it as an open standard, and the Agent Skills site now lists dozens of clients that read it, including Claude Code, Codex, Cursor, Gemini CLI and OpenCode.
Docker's docker/skills repository tagged v0.1.0, v0.2.0, v0.3.0 and v0.3.1 all on 29 September 2026. Its README describes the contents as "Docker-authored knowledge skills that improve AI coding agent output for Docker-related tasks", written "as portable SKILL.md directories and discovered automatically by any compliant agent through standard skill paths". The catalog covers Dockerfiles, Compose, Docker Sandboxes and Docker Agent, plus one cross-product skill whose whole job is to make an agent confirm before running an irreversible Docker operation.
Codex reads skills from a fixed set of paths: every .agents/skills directory from the working directory up to the repository root, then the user's home directory, then an admin location. Its documentation says the feature "builds on the open agent skills standard". The agent on your machine is not going away. What changes is how much of its work you are around to see.
What the shell.online skill instructs an agent to do
The skill is served at shell.online/skill as plain text, and it is byte-for-byte the file at public/skill/shell-online/SKILL.md in the shell.online repository. Its frontmatter name is shell-online and the description reads: "Share and manage shell.online terminal sessions, or observe and send explicitly authorized input through their scoped MCP grants. Use for remote progress monitoring, human handoff, and agent-to-agent terminal control."
The start-and-share procedure is short. The agent checks for the CLI, installs it if missing, and then wraps the process it wants to expose:
command -v shell || curl -fsSL https://shell.online/install | sh
shell --json -- python train.py
shell --read-only --json -- npm run build
The skill tells the agent to prefer the read-only form whenever the operator only needs to watch. It then tells the agent to read the first JSON event and extract three fields: share_url, e2ee_password and session_id. The example event in the skill looks like this:
{"type":"session","session_id":"…","share_url":"https://shell.online/s/…#salt=…","e2ee_password":"Ab3dE7-_xY","read_only":false,"encrypted":true,"background":true}
Two details matter for anyone wiring this into an agent harness. First, the event goes to stderr, not stdout. The flag definition in cmd/shell/main.go describes --json as "emit the session event as JSON on stderr", and the CLI reference repeats it: new-session JSON goes to stderr and includes e2ee_password for encrypted sessions. Second, the URL has a #salt= fragment that must be preserved. The salt is not the secret; nothing decrypts without the password, but a truncated URL will not open. The skill is explicit that the agent must send the complete URL.
The final step is the human part. The agent posts share_url and e2ee_password into the active conversation, says which process the link exposes, and says whether read_only is true. The operator is about to open a link on a phone and needs to know whether tapping a key will type into a running process.
Share a terminal session in the browser, then be clear about who holds the key
Once the operator has both values, they open the URL in any modern browser, enter the password, and see the same PTY the agent is driving. The process and the terminal stay on the machine that ran the command, which is the whole premise of a browser link to a terminal process rather than a remote machine. What travels through the relay is ciphertext: the CLI encrypts terminal frames before they reach the Cloudflare relay and the browser decrypts them. The security page lists what the relay can still observe: connection IPs, timing, encrypted sizes, frame types, labels, access mode, lifecycle and terminal grid dimensions. It cannot read the output.
The same page states the access rule plainly: "Anyone with the complete link and password can view and type with the wrapped process's operating-system permissions." The URL plus the password is a bearer credential. If an agent pastes both into a shared channel, everyone in that channel can type into the process with the agent's own permissions. The skill accounts for this in two ways. It says to treat the pair as a bearer secret and never send the host token, and for sensitive or long-lived work it suggests setting a longer password through the SHELL_ONLINE_E2EE_PASSWORD variable and sending the URL and password through separate operator-approved channels.
Read-only is the safer default for monitoring, and it is enforced away from the browser. The security page says input "is rejected by both the relay and the CLI. A modified browser cannot turn this into an interactive session." The agents page adds that a read-only session cannot be made interactive by an MCP grant either. So an agent that starts a read-only share for a build has given its operator a window, not a keyboard, and no client-side trick changes that.
The skill also constrains the one weakening option. --no-e2ee is only for an explicit operator request; the JSON event then reports encrypted: false and omits e2ee_password entirely, and the relay can read terminal input and output.
Handing off a live Claude Code conversation
There is one path in the skill that goes further than sharing a fresh process. When an operator asks an agent running inside Claude Code to share the current conversation, the skill says to run:
shell --json -- claude
Inside a Claude Code Bash subprocess, the CLI detects the CLAUDE_CODE_SESSION_ID variable and starts a shareable fork with claude --resume on the current session plus --fork-session. The operator receives a share link to a second Claude Code process that has the same conversation history and the same workspace. The skill is careful about the limits: the original process stays open, messages sent after the handoff do not synchronize between the two, and the agent must never claim that shell.online adopted the original PID or PTY. It is a fork with shared history, which is what you want when steering the same task from a phone.
Edge cases the skill already decides for the agent
Most mistakes an agent can make with a shared terminal are lifecycle mistakes, and the skill spends most of its length on them.
- Status without a new link. When asked for progress, the agent runs shell list --json first and reports the label, elapsed time and status, repeating the existing share_url and e2ee_password if useful. It does not start a second session to "refresh" a link.
- Recovering or revoking access. shell password on a session ID reveals the active password locally; shell password rotate disconnects current viewers, prints a new salted link and password, and also revokes any MCP grants. The agent sends only the new pair and says the old credentials no longer decrypt later frames.
- Process exit ends the share. The session closes when the wrapped process exits. Closing the browser does not stop the process. The skill says to use shell kill only when asked to stop the task.
- Deadlines are opt-in. shell --auto-close 5m -- python train.py closes the share five minutes in, but the CLI docs note that a deadline cannot keep a task alive after it exits.
The reason to encode this in a skill rather than a prompt is the same reason Docker shipped a destructive-operations guardrail as a skill: the instructions are versioned, readable before the agent acts, and identical across every client that speaks the format. The shell.online skill file in the repo is the full statement of what an agent will do with your terminal.
For the underlying model of a share, one command printing a URL and password with the PTY staying local, the earlier post on live terminal links covers it. shell.online is developed by Pilot Protocol, and the skill's MCP section is where the two meet: scoped, expiring grants for another agent to observe or control a session, issued from the same CLI.
Give your agent the skill
Point your agent at the skill file, and the next time it runs something worth watching it can hand you an encrypted browser link with the read-only flag stated up front.
Try shell.online