Apps · CoShell

A shared terminal, with the keys on your machine

Work through a problem on the same shell. Invite someone to watch, share a file, then hand them the keyboard when you are ready — and take it back. The shell itself never leaves your machine, so there is no inbound port and no SSH key handed to anybody.

0 inbound ports opened the helper on your machine connects outward; nothing listens for the internet
1 person can type at a time control is granted to a named person and taken back the same way
host decides, every time a guest asking for control is a request, never an instruction
How control works

Watching is the default; typing is granted

Somebody who opens the link can see the session. That is all they can do until you say otherwise, and the rule is enforced where the shell is — on your machine — rather than by the page they are looking at.

  • The shell runs under your account, on your machine. Nothing is provisioned anywhere else and there is nothing to tear down afterwards.
  • Write access is per person and revocable. Handing over the keyboard is an act, not a property of the link — so forwarding the link does not forward the keyboard.
  • Files move over the same session, so "send me that log" does not become a detour through somebody's cloud drive.

One terminal, one address

The terminal this page opens is the one maintained in the SDK repository, where it also serves as the platform's worked example of streaming a shell over a channel. It is deliberately the same build rather than a second copy with a different badge on it: two terminals at two addresses is how one of them silently rots, and the earlier standalone build in this folder is the evidence — it is kept for reference and nothing serves it.

Pricing

What it costs

Free — it runs against your own machine

Free. The shell runs on your machine under your account, so there is nothing being provisioned on our side to charge for.

How it's built

The part that matters, in the open

The service validates a message's type against its own enum and silently drops anything else, so a custom type travels inside a valid event.

legacy/js/sdk.js
const msg = {
  // 'chat-text' maps to a valid EventType and is always broadcast; the real
  // type travels in the envelope. See the note at the top of this file.
  type: 'chat-text',
  content: JSON.stringify({ [ENVELOPE_KEY]: [type, body] }),
};

Taken from this app's source, not written for the page. Built on the Messaging Platform SDK.