Aether lets you share your terminal instantly across any network. By using direct peer-to-peer connections, it completely bypasses the headache of SSH keys, firewalls, and port forwarding so you can focus on collaborating
Aether lets you share your terminal with others over the internet. It connects devices directly, so you don't need to worry about setting up SSH keys, configuring firewalls, or forwarding ports. Just connect and start working together!. Aether is a frictionless, peer-to-peer terminal sharing tool. Instantly broadcast a live, interactive terminal session across any network using a simple 6-digit code. Designed for immediate collaboration, Aether entirely eliminates the need for user accounts, SSH key management, or complex firewall configurations.
$ aether shareA E T H E R
Secure terminal sharing
> Session code: 4 5 2 2 3 7
> Share URL: https://useaether.vercel.app/term/452237
> Give this code to anyone you want to share your terminal with.
Connecting to signaling server...
✓ Connected to signaling server
✓ Waiting for viewer...
The viewer opens the link, enters the code, and gets a live interactive terminal - streamed directly from your machine over an encrypted peer-to-peer connection. The signaling server never touches your terminal data.
Aether uses WebRTC DataChannels to establish direct, peer-to-peer (P2P) connections for terminal streaming. This architecture ensures low latency and high security, as your terminal data never passes through a central server.
Connection flow:
- Agent spawns a pseudo-terminal (PTY) and registers a 6-digit session code on the signaling server via WebSocket.
- Viewer enters the code in the web app; the server confirms the session exists.
- Signaling server relays the WebRTC offer → answer → ICE candidates between both peers.
- DataChannel opens - terminal I/O flows directly peer-to-peer, end-to-end encrypted.
- Server steps aside - it no longer participates in the session.
Aether is a monorepo structured as three npm workspaces:
| Workspace | Role | Key Technologies |
|---|---|---|
agent/ |
CLI tool that shares your terminal | Node.js,node-pty, @roamhq/wrtc |
server/ |
WebSocket signaling server | Express 5,ws, MongoDB (optional) |
web/ |
Browser-based terminal viewer | React 19, xterm.js 6, Tailwind CSS 4 |
Once the P2P connection is established, all communication uses a single reliable ordered DataChannel named "terminal":
| Direction | Payload |
|---|---|
| Agent → Viewer | Raw PTY output (text + ANSI escape sequences) |
| Viewer → Agent | Raw keystrokes,or { type: "resize", cols, rows } for terminal resize events |
- Node.js ≥ 22 (includes npm ≥ 10)
- Python & C++ build tools (Required by
node-ptynative bindings`) - MongoDB (Optional -server runs without it)
Setting up build tools:
# Windows
npm install --global windows-build-tools
# macOS
xcode-select --install
# Linux
sudo apt install build-essential python3# 1. Clone
git clone https://github.com/indrasuthar07/Aether.git
cd Aether
# 2. Install
npm install
# 3. Configure
cp .env.example .envstart each workspace individually:
npm run dev:server # Signaling server
npm run dev:web # Web app
npm run dev:agent # Agent CLIRun the following on the machine you want to share:
aether shareAether will:
- Spawn your default shell (PowerShell on Windows,
bash/zshon macOS/Linux) - Register a unique 6-digit session code
- Print a shareable link
- Wait for a viewer to connect via WebRTC
- Open project URL
- Click "Open Web Terminal"
- Enter the 6-digit session code
- Done - you're in a live, interactive session
Usage: aether [command]
Commands:
share Share your terminal (default command)
help, -h Show help information
version, -v Print the current version
Aether/
Aether/
├── agent/ # CLI terminal-sharing agent
│ ├── src/
│ │ ├── index.ts # Entry point & CLI parser
│ │ ├── session.ts # Session orchestrator (core logic)
│ │ ├── signaling-client.ts # WebSocket signaling client
│ │ ├── webrtc.ts # WebRTC peer connection wrapper
│ │ ├── pty.ts # PTY spawn + environment sanitization
│ │ ├── config.ts # Configuration with env overrides
│ │ ├── code.ts # 6-digit session code generator
│ │ └── logger.ts # Colored CLI output
│ └── package.json
│
├── server/ # WebSocket signaling server
│ ├── src/
│ │ ├── index.ts # Express + WebSocket server setup
│ │ ├── signaling.ts # Message handling & relay logic
│ │ ├── room.ts # Room lifecycle & management
│ │ ├── connection-manager.ts # Per-IP & global connection limits
│ │ ├── rate-limiter.ts # Sliding-window rate limiting
│ │ ├── validation.ts # Payload whitelisting & size gates
│ │ ├── config.ts # Server configuration
│ │ ├── logger.ts # Structured JSON logging
│ │ ├── db.ts # MongoDB connection (optional)
│ │ ├── models/
│ │ │ └── Session.ts # Session schema (scaffolded)
│ │ └── routes/
│ │ └── health.ts # GET /health endpoint
│ └── package.json
│
├── web/ # Browser-based terminal viewer
│ ├── src/
│ │ ├── App.tsx # Router & layout
│ │ ├── main.tsx # React entry point
│ │ ├── types.ts # Shared types & constants
│ │ ├── index.css # Tailwind theme + xterm overrides
│ │ ├── pages/
│ │ │ ├── Home.tsx # Landing page
│ │ │ ├── ConnectTerminal.tsx # Session code entry
│ │ │ ├── TerminalPage.tsx # Live terminal session
│ │ │ └── NotFound.tsx # 404 page
│ │ ├── components/
│ │ │ ├── Nav.tsx # Floating navigation bar
│ │ │ ├── Footer.tsx # Page footer
│ │ │ ├── CodeInput.tsx # 6-digit OTP-style input
│ │ │ ├── StatusBar.tsx # Terminal session status bar
│ │ │ ├── TerminalMockup.tsx # Decorative terminal (landing)
│ │ │ └── TerminalView.tsx # xterm.js wrapper component
│ │ └── hooks/
│ │ ├── useSignaling.tsx # WebSocket signaling hook
│ │ ├── useWebRTC.tsx # WebRTC peer connection hook
│ │ └── useTerminal.tsx # xterm.js lifecycle hook
│ └── package.json
│
├── .env.example # Environment variable template
├── package.json # Root workspace config
└── tsconfig.base.json # Shared TypeScript configuration
Security is a first-class concern in Aether, not an afterthought.
All terminal data is transmitted over WebRTC DataChannels, which mandate DTLS encryption - the same protocol underpinning HTTPS. The signaling server is architecturally incapable of reading terminal content; it only relays connection metadata during the handshake.
The agent scrubs 50+ patterns of sensitive environment variables before spawning the PTY shell. Cleared patterns include:
AWS_*·AZURE_*·GCP_*·GITHUB_*·STRIPE_*·OPENAI_*·*_API_KEY·*_TOKEN·*_SECRET·*_PASSWORD·*_DATABASE_URL· and more
Aether's own configuration variables are also excluded from the PTY environment.
| Control | Details |
|---|---|
| Origin validation | Browser clients must matchALLOWED_ORIGINS; CLI agents are exempt (no Origin header) |
| Rate limiting | Sliding-window per-IP limits - connections: 20/min, registrations: 5/min, joins: 15/min |
| Connection caps | Per-IP: 10 · Global: 500 |
| Payload validation | Whitelist-based key filtering with per-type size gates (offer/answer: 32 KB · ICE: 4 KB) |
| Message size limit | DataChannel messages capped at 4,096 bytes |
| Room TTL | Rooms expire after 5 minutes without a viewer; connected sessions stay open |
- Each session has a unique 6-digit code (guessing is rate-limited)
- Only one viewer may connect per session at a time
- Agent disconnect immediately tears down the room and evicts any active viewer
- Agent:Node.js 22+, node-pty (terminal spawning), @roamhq/wrtc (WebRTC), ws (WebSockets), nanoid.
- Server:Express 5, ws (WebSockets), Mongoose .
- Web:React 19, Vite 8, xterm.js 6 (browser terminal), Tailwind CSS 4, React Router 7, Lucide React.
- Shared:TypeScript 5, WebRTC (P2P transport).
Contributions are welcome. Here's how to get involved:
- Fork the repository
- Create a feature branch :
git checkout -b feature/my-feature - Commit your changes :
git commit -m "feat: describe what you did" - Push and open a Pull Request
- The monorepo uses npm workspaces - always run
npm installfrom the root npm run devstarts the server and web app together viaconcurrently- The agent must be started separately with
npm run dev:agent - TypeScript strict mode is enabled across all three workspaces
- Commits follow Conventional Commits -
feat:,fix:,chore:,docs:, etc.