Content
# sshrew
<p align="center">
<img src="sshrew/assets/sshrew.png" alt="sshrew" width="220">
</p>
Let Claude reach any machine you'd normally SSH into. Claude can now read
files, tail logs, run allowlisted commands **without inbound SSH, port
forwarding, or config files.** Works on home servers, VPSes, Raspberry Pis,
Jetsons, whatever. If it runs Linux and can dial out, sshrew can bridge it.
## Quick start
On the machine you want Claude to see:
```bash
curl -fsSL https://raw.githubusercontent.com/duriantaco/sshrew/main/install.sh | bash
```
It prints:
```
==============================================================
Your bridge is live. In Claude, go to:
Settings -> Connectors -> Add custom connector
and paste this URL:
https://random-words.trycloudflare.com/kJx.../mcp
==============================================================
```
Paste that URL into claude.ai, enable the connector in a chat, done. By
default Claude can only read `~/.sshrew-share`; pass `--root DIR` when you
want to expose a specific project or log directory.
That one command handles everything: installs `uv` (which brings its own
Python 3.12, so old distros work), fetches sshrew, generates and saves a
secret token, downloads the right `cloudflared` binary for your CPU, opens
the tunnel, and starts the server.
## How it works
SSH is you reaching *in*. sshrew is the box reaching *out*:
```
claude.ai --(custom MCP connector)--> https://xxx.trycloudflare.com/<token>/mcp
|
cloudflared (outbound only)
|
sshrew on 127.0.0.1:8787
```
You need access to the machine exactly once — to run the installer. After
that (especially as a systemd service) you never reach in again.
The secret token lives in the URL path, so possession of the URL is the
credential. It's stored in `~/.config/sshrew/token`, reused across restarts,
and rotated with `--rotate-token`.
Every tool call is also recorded locally in `~/.config/sshrew/audit.jsonl`.
The log stores metadata like tool name, path, argv, exit code, bytes returned,
duration, and a token fingerprint. It does not store file contents, command
output, or the secret token itself. Ask Claude to call `recent_activity()` to
review what happened in the current session.
## Multiple machines
Run sshrew on each box. Each gets its own token and its own connector entry
("home-server", "lab-pi", "gpu-box"). Enable several in one chat and ask
Claude to compare across them.
## Options
Default is **read-only**, scoped to `~/.sshrew-share`.
```bash
sshrew --profile readonly # default: shared folder only
sshrew --profile dev # shared folder plus ~/projects and ~/src if present
sshrew --profile server # logs plus safe read-only diagnostics
sshrew --profile edge # server profile plus edge-device diagnostics
sshrew --profile full-trust # home directory plus unrestricted shell; be careful
sshrew --root ~/projects --root /var/log # narrow what Claude can read
sshrew --allow-shell --allow journalctl --allow systemctl
sshrew --allow-shell # full shell access; use only on trusted links
sshrew --no-tunnel # bring your own tunnel
sshrew --rotate-token # invalidate the old URL
```
Profiles are conservative. `dev` does not enable shell. `server`, `edge`,
`workstation`, and `ops` enable only a small read-oriented command allowlist.
`full-trust` is the only profile that grants unrestricted shell access.
Flags pass through the installer too:
```bash
curl -fsSL .../install.sh | bash -s -- --profile server
```
## Installing permanently
```bash
uv tool install --python 3.12 git+https://github.com/duriantaco/sshrew
sshrew
```
Run at boot with systemd. This installs the service for the current Linux user:
```bash
sed "s/^User=me/User=$USER/" sshrew.service | sudo tee /etc/systemd/system/sshrew.service >/dev/null
sudo systemctl daemon-reload && sudo systemctl enable --now sshrew
```
That user controls what sshrew can read and run. Keep it non-root.
Heads-up: **quick-tunnel URLs change every restart**, so a reboot means
re-pasting the connector URL. For a stable URL, point a named Cloudflare
tunnel or Tailscale Funnel at `127.0.0.1:8787` and run `sshrew --no-tunnel`.
The sample service includes systemd sandboxing and only allows writes to
`~/.config/sshrew` and `~/.sshrew-share`.
## Do I need nginx?
Not for the default setup. sshrew listens on `127.0.0.1`, and `cloudflared`
is the only public-facing network layer. nginx does not fix token leakage,
path scoping, or command execution risk.
Use nginx, Caddy, or a named Cloudflare Tunnel with Cloudflare Access if you
are directly exposing a stable domain and need TLS termination, request
limits, access logs, mTLS, SSO, or extra rate limiting.
## Roadmap
sshrew should be more than a tunnel. The goal is an agent-aware host capsule
for anything you can run: laptops, workstations, home servers, VPSes, lab
machines, Raspberry Pis, Jetsons, NAS boxes, CI runners, and edge devices.
Every machine gets explicit, inspectable rules for what an AI agent can see
or do.
- Capability tokens: mint separate URLs for separate roots, tools, and TTLs.
- Local approval queue: require terminal approval for risky operations like
service restarts, package installs, or writes.
- Audit controls: retention, export, tamper-evident hashes, and per-token
activity views.
- Profiles: per-profile command arguments, root templates, and generated
systemd services.
- Host facts: richer GPU, network, process, and service inventory.
- Device packs: optional tools for specific environments like NVIDIA Jetson,
Raspberry Pi, Docker hosts, systemd servers, macOS laptops, Linux laptops,
NAS boxes, and CI runners.
- Safer ops tools: expose `tail_logs`, `restart_service`, `docker_status`, and
`journal_errors` as structured tools instead of relying on raw shell.
- Stable URL wizard: generate named Cloudflare Tunnel, Tailscale Funnel, or
local-only configs from one command.
- Cloudflare Access mode: support service-token headers and JWT validation for
stable public deployments.
- Live dashboard: show current URL, roots, enabled tools, recent calls, and a
one-click token revoke.
- Event channels: push alerts when logs spike, thermals go high, disk fills, or
a watched service fails.
## Security notes
- The URL is the password. Long random token, never post it, rotate if in doubt.
- `--root` is a hard jail. Paths are fully resolved, including symlinks, and refused if they escape.
- Shell is off unless you pass `--allow-shell`. With `--allow CMD`, sshrew executes the parsed command directly instead of through a shell, so shell operators like `&&` and `|` are not executed. Without `--allow`, `--allow-shell` grants full shell access.
- sshrew runs with the permissions of its user. DO NOT run it as root.
- Reads are size-capped, negative offsets and sizes are refused, and binary files are refused.
- Search skips hidden directories and symlinks that point outside the allowed roots.
## Tools exposed
| tool | what it does |
|---|---|
| `list_dir(path)` | directory listing inside allowed roots |
| `read_file(path, offset, max_bytes)` | chunked text reads |
| `file_info(path)` | size / mtime / permissions |
| `search_files(root, name_glob, contains)` | recursive find + grep-lite |
| `run_command(command)` | shell, gated by `--allow-shell` / `--allow` |
| `host_facts()` | structured OS / CPU / memory / disk / service / device facts |
| `system_status()` | uptime, memory, disk (+ tegrastats if it's a Jetson) |
| `recent_activity(limit)` | recent audit log entries for accountability |
## License
MIT
Connection Info
You Might Also Like
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
markitdown
Python tool for converting files and office documents to Markdown.
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.
TrendRadar
TrendRadar: Your hotspot assistant for real news in just 30 seconds.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.