Webshell is a browser console for managing live shell terminals on your own machine or server.
It does not wrap Codex, Claude, SSH, or any specific CLI. It gives you stable browser-based shell sessions, then you run whatever command you want inside the shell.
- Multiple live shell sessions in one web UI
- Real PTY transport through
node-pty - xterm.js browser terminal
- Local username/password login
- Mobile responsive layout
- Mobile shortcut keys for
↑,↓, andShift+Tab - UTF-8 locale defaults for Chinese and other non-ASCII input
- In-memory terminal snapshots when switching sessions
- No terminal output persisted to disk
- Node.js 18 or newer
- macOS or Linux recommended
- A local shell such as
zsh,bash, orsh
git clone https://github.com/lcy360/webshell.git
cd webshell
npm install
WEBSHELL_USERNAME=admin WEBSHELL_PASSWORD='change-me' npm run init-user
npm startOpen:
http://127.0.0.1:4767
If you skip npm run init-user, first startup creates user admin and prints a random password in the server log.
Initialize credentials before first start:
WEBSHELL_USERNAME=admin WEBSHELL_PASSWORD='change-me' npm run init-userReset credentials later:
WEBSHELL_USERNAME=admin WEBSHELL_PASSWORD='new-secret' npm run reset-passwordreset-password clears browser login sessions. Restart the server after resetting credentials.
Environment variables:
HOST=127.0.0.1
PORT=4767
WEBSHELL_USERNAME=admin
WEBSHELL_PASSWORD=change-me
WEBSHELL_DATA_DIR=/path/to/runtime-data
WEBSHELL_OUTPUT_FLUSH_MS=4
WEBSHELL_OUTPUT_FLUSH_BYTES=16384
WEBSHELL_SNAPSHOT_REPLAY_LIMIT=80000
WEBSHELL_DATA_DIR defaults to ./data.
For lower perceived latency, reduce WEBSHELL_OUTPUT_FLUSH_MS. For less network and CPU churn, increase it. 4 is a practical default for interactive use.
WEBSHELL_SNAPSHOT_REPLAY_LIMIT controls how much terminal history is replayed when switching back to a shell. Lower values make switching faster. Higher values preserve more visible history.
Runtime files are ignored by git:
data/auth.json
data/state.json
auth.json contains the password hash and browser sessions. Do not commit it.
Live shell sessions and terminal output are runtime-only. They are not persisted after the process exits.
Bind Webshell to localhost and expose it through HTTPS:
HOST=127.0.0.1 PORT=4767 npm startCloudflare Tunnel target:
http://127.0.0.1:4767
Templates are included:
deploy/cloudflare-tunnel/config.ymldeploy/nginx/webshell.conf
Anyone who can log in can run shell commands as the operating-system user running Webshell. Use HTTPS, a strong password, and preferably Cloudflare Access or another upstream access control layer.
Linux systemd template:
sudo cp deploy/systemd/webshell.service /etc/systemd/system/webshell.service
sudo systemctl daemon-reload
sudo systemctl enable --now webshellEdit WorkingDirectory, ExecStart, and environment values before enabling.
macOS launchd template:
cp deploy/launchd/com.webshell.app.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.webshell.app.plistEdit paths and the npm executable path first. On Apple Silicon Homebrew, npm is often /opt/homebrew/bin/npm.
docker compose up -dThe Docker container manages a shell inside the container. It does not expose your host shell unless you deliberately mount host paths and design that isolation boundary yourself.
On phone browsers, Webshell switches to a compact layout:
- Shell creation stays at the top
- Terminal fills the main screen
↑,↓, andShift+Tabshortcut buttons sit next to theXclose button
These shortcut buttons send terminal control sequences directly to the PTY, which helps when a mobile keyboard cannot emit them.
Webshell sets LANG, LC_ALL, and LC_CTYPE to UTF-8 defaults when the host does not provide them. The browser terminal font stack includes common Chinese fonts on macOS and Linux.
The frontend tracks IME composition events so partially composed Chinese text is not sent early. Output uses immediate writes for small chunks and batched writes for large bursts, which keeps normal typing responsive without making large command output expensive.
Session switching uses a local per-session tail cache first, then reconciles with the server snapshot. This avoids replaying a large terminal buffer every time you switch tabs.
Syntax check:
npm run checkEnd-to-end smoke test:
npm run test:e2eThe E2E test starts Webshell on a temporary port with a temporary data directory, logs in, creates a shell, sends English and Chinese output, verifies it, and closes the shell.
- Not an SSH server
- Not a terminal transcript recorder
- Not an AI agent wrapper
- Not a multi-user authorization system
It is a lightweight remote-control surface for shell terminals you own.