Your terminal. On your phone. Only when you share.
Keep the real shell on your machine. Open it from an authenticated device when you choose.
wrapper share wraps one shell (or wrapper run -- claude wraps one command)
so an authenticated device can mirror it. Your prompt, plugins, and history
behave as before. A session never leaves your machine until you share it.
Unshare tears the tunnel down.
Checksum-verified installer:
curl -fsSL https://wrapper.sh/install | bashHomebrew:
brew install heycupola/tap/wrapperSupported installer targets: darwin-arm64, darwin-x86_64, linux-arm64,
and linux-x86_64. Windows: use WSL.
More install options: docs.wrapper.sh/guides/installation. Latest CLI: v0.2.4.
curl -fsSL https://wrapper.sh/install | bash
wrapper auth login
wrapper sharewrapper share wraps your real shell and opens a relay tunnel. It prints a
share code. Join from another local terminal with wrapper attach, or from
another device with the printed join command and share code. Owners skip the
code; guests enter it in a hidden prompt.
In a running host: Ctrl+\ then s shares, Ctrl+\ then u unshares.
Local attach stays on 127.0.0.1 and does not need Pro. Remote share requires
Pro. Details: docs.wrapper.sh.
- You run
wrapper share. It spawns your real shell inside a PTY and starts a tiny local WebSocket server bound to127.0.0.1. Nothing is exposed until share completes; metadata stays off Convex until then. - From the same machine,
wrapper attachconnects to that local server and mirrors the session. The transport stays on loopback and does not need the relay, Pro, or a Convex session row. - When you share, the CLI opens a Convex session, asks for a short-lived
host ticket, connects to the relay on Fly.io, and prints a secret share
code. You join your own devices with
wrapper attach --relay --id <id>; anyone else enters the code in a hidden prompt, so knowing the session id alone is not enough. - By default viewer input prefers a direct WebRTC data channel for lower
latency. The host keeps relay output available for fallback and mixed
viewers, and you can force relay-only mode with
WRAPPER_P2P=0.
This is a Bun and Turborepo monorepo.
apps/
cli/ Wrapper CLI: shell wrapping, session registry, local + relay attach, device auth, default-on P2P
relay/ Relay service: authenticated WebSocket routing for shared sessions, deployed on Fly.io
web/ Next.js app on Vercel: landing page, device-login approval, onboarding, Pro upgrade
docs/ Mintlify documentation source, published at docs.wrapper.sh
mobile/ Git submodule pointer to the native SwiftUI iPhone/iPad viewer repository
packages/
protocol/ Zod wire schema shared by every wrapper component (JSON frames + WebRTC signal)
backend/ Convex backend: Better Auth, session lifecycle, relay tickets, onboarding, billing
terminal/ Bun-native PTY layer using the wrapper-pty-helper binary
logger/ Consola logging plus opt-in PostHog telemetry
typescript-config/ Single-source tsconfig presets
tools/
pty-helper/ C source and Makefile for the wrapper-pty-helper binary shipped with the CLI
The CLI is the heart of the project. See
apps/cli/README.md for how the wrapping flow works
and what every command does. The transport layer (relay WebSocket and the
default direct WebRTC path) is documented in
apps/cli/transport/README.md.
| Topic | Document |
|---|---|
| CLI commands, keystrokes, env vars | apps/cli/README.md |
| Relay + direct P2P transports | apps/cli/transport/README.md |
| Relay service and Fly deploy | apps/relay/README.md |
| Convex backend (auth, sessions, tickets, billing) | packages/backend/README.md |
| Wire protocol | packages/protocol/README.md |
| PTY internals | packages/terminal/README.md |
| Logging and telemetry | packages/logger/README.md |
| Dev and prod environments, deploy automation | ENVIRONMENTS.md |
| Production operations, incidents, backups, SLOs | OPERATIONS.md |
| Public documentation | docs.wrapper.sh |
| Documentation source | apps/docs (run bun run --cwd apps/docs dev) |
https://wrapper.sh is the canonical production website, auth, installer,
legal, and support origin. https://docs.wrapper.sh is the canonical public
documentation origin.
The CLI core, the Convex auth and backend, the relay transport, and the web
onboarding flow are implemented in this repository. Sharing attempts a direct
WebRTC P2P data path by default, with the relay kept online for signaling and
automatic fallback (WRAPPER_P2P=0 forces relay-only mode). The terminal title
shows the role, session, and active transport without reserving a screen row.
CLI v0.2.4 is the current share-first CLI release.
The native iPhone/iPad viewer lives in the apps/mobile submodule (Simulator /
TestFlight path). Do not treat App Store availability as the primary install
path until a public TestFlight or App Store URL is published.
The active focus is operational hardening:
- rotate
HOMEBREW_TAP_TOKENso release workflow can keep the tap in sync - keep dependency audit, lint, format, types, auth, and relay checks green
- complete the TestFlight public beta for the iOS viewer, then App Store review
- finish the remaining hosted-ops items in
OPERATIONS.md
Requirements:
- Bun 1.3.5 or newer for runtime, package management, and bundling.
- A POSIX system (macOS or Linux). On Windows, run Wrapper inside WSL.
Environment templates are included:
.env.example(shared)apps/cli/.env.exampleapps/relay/.env.examplepackages/backend/.env.example
Clone with the mobile submodule:
git clone --recurse-submodules https://github.com/heycupola/wrapper.git
cd wrapper
# For an existing clone:
git submodule update --init --recursiveThe mobile repository has its own git history. The parent repository tracks
only its commit pointer. For mobile development on macOS, install the
prerequisites in apps/mobile/README.md, then
generate the ignored Xcode project:
make -C apps/mobile bootstrapbun install # one-time
bun run check-types # typecheck every package
bun run lint # oxlint
bun run format # oxfmt --write
# try the wrapping flow locally
cd apps/cli && NODE_ENV=development bun run index.ts shell-hostNODE_ENV=development moves every on-disk path into a wrapper-dev namespace
under XDG state (or %APPDATA%\wrapper-dev\ on Windows), points the relay and
auth URLs at localhost, mirrors logs to stderr, and writes shell-config patches into
a throwaway directory. A developer running the CLI locally can never corrupt a
real installation's registry, logs, or shell config.
Setting CI to any value disables telemetry and console output. For the full
list of CLI environment variables, see
apps/cli/README.md.
- Bun for runtime, package management, and bundling.
- Turborepo for task orchestration and caching.
- oxlint and oxfmt for linting and formatting (no ESLint, no Prettier).
- Lefthook for git hooks (pre-commit oxfmt and oxlint, pre-push checks).
- Catalog dependencies so shared packages such as
react,next,zod, andtypescriptuse a single pinned version across the workspace. bun run auditfor advisory checks. Werift's abandonedipdependency is replaced by the testedpackages/ipcompatibility shim backed byipaddr.js. The audit script ignores only Bun's name-based false positive for that private shim.
This repository is MIT © 2026 Cupola Labs, LLC.
The iOS app in apps/mobile is a separate repository and is
not covered by this MIT license.
Security issues must be reported privately according to SECURITY.md.
Hosted-service policies are published at
wrapper.sh/privacy-policy and
wrapper.sh/terms-of-service.
