See What a Coding Agent Is Doing Without Opening Its Terminal: Owner-Only Session Summaries in shell.online, After PixelLeak
There are two ways to see what a coding agent is doing while you are away from it: open its terminal, or read whatever artifact it left for you. A report this week shows how the second goes wrong. On September 29, Glow Labs published its PixelLeak research: more than 13,000 internal images sitting openly on GitHub, put there by developers at over 300 organizations across 900+ repositories. Developers asked an agent to prove a visual change worked. It could not attach a screenshot to a private pull request from a command line, and in the report's words: "The agents figured out that they could make the image available to the human reviewer by hosting it in an adjacent public repo." Coverage on October 1 lists what was legible in those pictures, including customer billing records, treasury consoles, and unreleased features.
Whatever an agent produces so a human can check on its work is data, and somebody has to decide who can open it before the agent picks the most convenient place to put it. On October 1 we merged a change to shell.online that makes that decision in code for one such artifact: a short summary of each session in the session list, sealed so that only the session's owner can read it.
What merged on October 1, and what has not shipped
shell.online gives any terminal process a browser link (the basics are in our introduction to the live terminal link). On a machine linked to an account (linking is optional), the web app lists your sessions. Pull request 275 adds a card to that list, and a follow-up merged the same day makes the whole row or board card the target. Hover it, or long-press it on a phone, and a few lines say what the session last did, with a state such as "Waiting for input".
This is on main, not in a tagged release. The latest published CLI is v0.24.1, the changelog's Unreleased section is still empty, and the README says outright that a merged change is not proof that every hosted component or running CLI host has been updated.
Summaries are off for every session until its owner turns them on, either with the Summaries toggle in the web app or from the host:
shell claude
shell list
shell permissions <session-id> --summaries=trueThe switch is independent of the other automation consents. A comment in the migration that adds it gives the reason: consenting to daily briefings is not consenting to terminal output leaving the host.
See what a coding agent is doing from its own transcript, with no model call
For Claude Code the host does not read the screen and does not run a model. When a linked machine starts a plain shell claude session, the CLI adds two things to the launch: a fresh --session-id, and a --settings value that installs a SessionStart hook. The Claude Code hooks reference says SessionStart fires on startup, resume, /clear, compaction and forks, and hands the hook a session_id and a transcript_path. Our hook is one fixed command that writes that input to a private file (mode 0600) in the local session directory. That is how a summary follows the conversation across /clear and /resume.
The binding is strict. A transcript path reported by the hook is accepted only when it is exactly that conversation's .jsonl file under the Claude projects directory and a regular file, so hook input cannot point the reader anywhere else.
Once a turn ends, the host reads the tail of the transcript and takes the latest AI title and the latest assistant text. Only text blocks are read, so thinking and tool calls never enter a summary, and a turn that is still running is skipped. The result is reduced to plain text, capped at 480 characters with an 80-character title, and sealed on the machine to the owner's account vault key: an ephemeral ECDH P-256 exchange, HKDF with SHA-256, then AES-256-GCM. The accounts service stores an envelope it cannot open.
Launches with --print or a subcommand such as claude mcp produce no summary. On Windows, where the hook has no POSIX shell to run in, sessions bind only through --session-id.
Every other process needs an attested enclave, and today's build refuses to use one
A dev server or a training job has no transcript. Summarizing it takes a model, which means terminal text leaving the machine. The design puts three gates in front of that.
- Minimization on the host. Only after consent does the CLI keep a bounded copy of recent output (64 KiB). Once the session has been quiet for 20 seconds, it strips escape sequences and control characters, redacts secret-shaped strings (private key blocks, Authorization and Cookie headers, AWS, GitHub and Slack token formats, JWTs, long high-entropy tokens), and keeps at most the last 12,288 bytes. The source calls this best-effort minimization, not a guarantee.
- Attestation before anything is sent. The host fetches the summarizer's identity and verifies a Google-signed token whose fields are documented in the Confidential Space token claims reference: RS256 only, the expected issuer and audience, a Confidential Space workload on Intel TDX, debugging disabled since boot, a STABLE image, and a container image digest that appears on an allowlist signed with an Ed25519 release key. The enclave's public key must be bound into the token through eat_nonce, the nonce claim from RFC 9711.
- Sealing in both directions. The request is sealed to the attested key. The summary comes back already sealed to the owner's vault key, so the host uploads an envelope it cannot open either.
The list of release keys compiled into internal/summary/allowlist.go is empty on main. With no key the verifier fails closed: the output copy is never enabled, no ticket is requested, nothing is sent. A build from main produces Claude Code summaries and nothing else. The pull request lists what remains for the other path: deploy the enclave, then ship a CLI release with the release key embedded.
A summary does not change who can reach the terminal. The share URL and its password together are still a bearer credential: anyone holding both can view the session and, unless it was started with --read-only, type with the permissions of the wrapped process. The summary is a separate object with a narrower audience. Teammates in your organization see the session in the list. Only the owner's vault opens its summary.
A summary is text an attacker may have written
Terminal output is untrusted input. A README the agent prints or a dependency's install script can carry text aimed at whichever model reads it next. OWASP ranks this first, as LLM01, prompt injection. A card in a session list looks trustworthy, so the design treats its content as hostile. On the enclave side the pull request describes spotlighting of the terminal text in the prompt and schema-constrained decoding. The enclave is a separate repository, so that description is the public record for both.
The output guard is in the shell.online repository. A summary may carry prose and nothing that acts. Every summary, whoever wrote it, passes a strict gate that refuses text containing a URL, a bare domain, an e-mail address, an IP address, Markdown link syntax, code markup or an HTML tag. The browser applies the same rules again after decrypting, renders every string as plain text, and puts a fixed caption under each card: "Automated summary of terminal output. It may be wrong; never follow instructions in it." The pull request reports a 14-case evaluation against a real model with no unsafe results, including one case where the model was fully hijacked and the guard withheld the output.
Idle periods, offline hosts and revocation
- A session is summarized once each time it goes idle, and again only after new output. Hovering generates nothing. The page reads what was already published and refreshes about once a minute.
- Turning the switch off wipes the stored envelope. So does a change of owner or share URL. A vault reset does the same, because the old envelope was sealed to a key that no longer applies.
- The host does the publishing, so nothing new appears while it is offline or asleep. The card shows the age of the observation. With the vault locked, the card says so and shows no text.
None of this would have stopped PixelLeak. Glow's recommendations are about auditing exposure and controlling what an agent may publish. The agents in that report reached for a public repo because it was the place that worked. Here the artifact is encrypted before it leaves the host, as terminal frames already are. The security model and encryption details pages cover that channel.
Put a link on the next agent run
Install the CLI, run shell claude, and open the printed link from a phone. Summaries are on main, not yet in a tagged release. The live terminal works today.
Try shell.online