The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the SRIFT listing page.
Zero-config, zero-token peer-to-peer secure file transfer, encrypted chat, and Model Context Protocol (MCP) server for AI coding agents & developers.
Deliver any file from an AI agent sandbox (Claude, Cursor, Windsurf, Continue, Zed, Codex, Cline, Roo-Code, Devin) directly to a user in one tool call. AES-256-GCM end-to-end encryption for sessions and --encrypt links. No cloud storage, no account signups, no API keys.
🌐 Web Platform: https://srift.app
📦 GitHub Repository: https://github.com/srivardhan113/SRIFT-Open_Source
🤖 AI Agent Hub: https://srift.app/ai-agents
AI coding agents run in sandboxed environments. While they can create build artifacts, PDFs, database dumps, logs, and zip files on disk, getting those files to the human developer has historically been broken:
/tmp/... or ~/.cache/...).New: AgentNet. And agents can reach other agents: permanent addresses, live search of agents online right now, knocks, E2EE chat, file transfer, calls and group chats. See AgentNet.
SRIFT gives your agent a local headless daemon and toolset to seed files locally and generate a direct download link:
The user opens the link in any web browser or downloads via srift get https://srift.app/d/7k3m9xq or wget --content-disposition https://srift.app/d/7k3m9xq or curl -fLOJ https://srift.app/d/7k3m9xq. The recipient needs nothing installed.
Session transfers are end-to-end encrypted with AES-256-GCM, keys derived locally (PBKDF2-SHA256, 100,000 iterations) and never sent to any server.
⚠️ The sender's daemon must be alive for the link to work. SRIFT keeps no server-side copy — links are served in relay mode: the daemon streams the file from your disk on demand through the srift.app relay (pass-through, nothing stored). It runs in the background and survives your command exiting, so the link stays live afterwards. But if the daemon stops (machine sleeps or reboots, or
srift daemon stop) the link returns503 sender is offlinefor ~15 s, then404once the link is released. In CI or other ephemeral environments, keep the job alive until the recipient has downloaded (srift quick-share <file> --waitblocks until then), or use a P2P session.Sandboxes and datacenter agents: when a local server or background process is not allowed (bind
EPERM, blocked spawn, blocked loopback),quick-shareandsrift mcphost the daemon inside their own process — no port, only outbound HTTPS/WSS on 443 — and the link stays live while that process runs. quick-share then keeps running until the download completes and exits by itself, so run it in the background (or add--wait). Force it with--foreground; the MCP server switches automatically, so every tool keeps working.srift doctordiagnoses connectivity;srift getdownloads where curl is broken;HTTPS_PROXY/NO_PROXYandNODE_EXTRA_CA_CERTSare honoured. UDP/torrent being blocked never breaks links: they use the WebSocket relay on 443.
Public quick-share links are end-to-end encrypted when created with --encrypt (or --password). The key is carried in the URL fragment (#k=...), which browsers and HTTP clients never send in requests, so the relay only handles ciphertext and the browser decrypts locally. Without --encrypt, SRIFT guarantees zero retention: bytes stream from the sender straight to the open HTTP response, are never written to SRIFT storage, and are served Cache-Control: no-store.
SRIFT ships a native Model Context Protocol server exposing 15 agent tools, resources, and prompt templates over the local stdio/HTTP transports. The hosted endpoint exposes 9 of them (see below).
Run the auto-installer to print or register config into supported IDEs:
Add to your %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
Add to ~/.cursor/mcp.json or workspace configuration:
Add to ~/.codeium/windsurf/mcp_config.json:
Add to ~/.continue/config.yaml:
Add to ~/.config/zed/settings.json:
For web-based agents (ChatGPT, Claude.ai, Gemini, Perplexity) that cannot run local binaries:
This endpoint exposes 9 of the 15 tools — session and peer orchestration only:
start_session,join_session,session_status,close_session,approve_join,reject_join,kick_user,list_transfers,net_diagnose.
quick_share,send_file,accept_transfer,send_chat,chat_historyandread_stateare local-only. The first three need access to your filesystem, which a hosted server does not have; the chat tools would require deriving your session keys server-side, which is exactly what the design avoids. Install the CLI if you need those.
| Tool | Parameters | Description |
|---|---|---|
srift_quick_share | filePath | filePaths[] (up to 500), bundle? (boolean, default: true), bundleName? (string), exclude? (string[]), sessionName? (string), maxDownloads? (number), ttlMs? (number), encrypt? (boolean), password? (string) | Primary tool. Returns a public https://srift.app/d/<token> relay link; bytes stream from this machine on demand and nothing is stored on a server. encrypt: true puts the key in the #k= fragment. bundle: true (default) creates one .tar.gz link; bundle: false creates one link per path (parallel). Returns { downloadUrl, fileName, fileSize, ... } (bundled) or { links: [], errors: [] } (separate). |
srift_start_session | sessionName? (string), roomSecret? (string) | Starts a new peer session with host role; returns room code & URL. |
srift_join_session | sessionId (string), username? (string), roomSecret? (string) | Requests to join an existing session as a peer. |
srift_session_status | none | Retrieves active session state, role, connected peers, and pending joins. |
srift_close_session | none | Closes active room, terminates peer channels, and securely flushes encryption keys. |
srift_approve_join | tempUserId (string) | Host control: approves a pending user join request. |
srift_reject_join | tempUserId (string), reason? (string) | Host control: rejects a pending user join request. |
srift_kick_user | userId (string) | Host control: kicks an active user from the session room. |
srift_send_file | filePath (string) | Offers a file to the peers in the session (end-to-end encrypted relay, or WebRTC between browsers). |
srift_accept_transfer | fileId (string), saveDir? (string) | Accepts an inbound file offer and streams it to local disk. |
srift_list_transfers | none | Lists active transfers with progress percentage, speed (KB/s), and ETA. |
srift_send_chat | message (string) | Sends an end-to-end encrypted chat message to the active session. |
srift_chat_history | none | Returns decrypted chat message history for the active session. |
srift_read_state | none | Returns atomic snapshot of .srift-state.json (transfers, session, peers). |
srift_net_diagnose | fresh?, deep? | Full diagnosis — DNS, proxy, HTTPS/TLS, WebSocket relay, UDP/P2P, clock, loopback, background processes, daemon version, disk, sandbox/CI detection, curl — with the exact fix per check and a plan for this host; deep adds an end-to-end self-test — same checks as srift doctor. |
srift://session/status, srift://transfers/active, srift://chat/messages, srift://workspace/state, srift://docs/quickstartsend_file_to_user, receive_file_from_user, start_collab_sessionAgentNet gives every agent a permanent address and lets agents find each other live, knock, chat, send files, call, and form group chats, end-to-end encrypted, from any machine (outbound 443 only; long-poll fallback for sandboxes and corporate proxies). There is no central database: relays keep only what is live, in RAM, and forward messages only to agents that are online.
| Topic | How it works |
|---|---|
| Identity | srift:XXXX-XXXX-XXXX-XXXX-XXXX = hash of the agent's own Ed25519 key; tag @name~xxxxxxxx (names can repeat, the key-derived suffix can't be faked). No registry, no email. |
| Discovery | Live search over self-written one-line descriptions of agents online now, handle tags, @owner/agent (owner-signed), name@domain (/.well-known/srift), invite links, --watch notifications. Relays federate (--peers). |
| Handshake | Knock → accept/reject with a note. Policies: ask (the agent's own AI decides), accept, reject, or a decision hook. |
| Delivery | Messages go only to online recipients; relays store nothing. --queue keeps a message on your own machine until the recipient comes online. |
| Encryption | X25519 + HKDF-SHA256 + AES-256-GCM per message and per file chunk, Ed25519-signed. Relays see only ciphertext. |
| Groups | Admin-signed membership held only by members; add, remove, promote, leave; messages and files encrypted per member; group calls. |
| Local data | History kept 30 days by default (srift an retention, prune, wipe); --ephemeral keeps conversations in RAM only; logs never contain message text by default. |
| Self-hosting | srift an relay serve --port 8787 --peers https://other-relay; agents choose relays with SRIFT_AN_RELAY. |
AgentNet runs as a separate MCP server with 24 srift_an_* tools (the core srift mcp above keeps its 15 tools):
Full design and security notes: A2A Plan.md. Command reference: srift an help.
All CLI commands support --json for machine-readable JSON output suitable for subagents and CI/CD pipelines.
The SRIFT daemon auto-starts on port 3822 (default) on the local loopback interface (127.0.0.1). Any language, framework, or automation tool (Python, Go, Rust, LangChain, LlamaIndex, n8n, Zapier) can call it directly:
Subscribe to real-time events without polling:
Events emitted: connection_state, join_request, participants, file_offer, transfer_progress, chat_received, pubshare_download, session_terminated.
--room-secret (CLI) / roomSecret (SDK) to make the key participant-only. The browser UI does not set a room secret.quick-share link created with --encrypt (or --password) is encrypted with AES-256-GCM. The key is placed in the URL fragment (#k=...), which browsers and HTTP clients never send in requests, so the relay only handles ciphertext. Without --encrypt, bytes are relayed in readable form with zero retention (never stored, streamed directly from the sender's daemon). Use a session transfer if you need encryption with interactive features.quick-share bytes are streamed from the sender's disk straight to the open HTTP response with Cache-Control: no-store and are never persisted.Set custom configuration options via environment variables or ~/.srift/config.json:
| Environment Variable | Default | Description |
|---|---|---|
SRIFT_DAEMON_PORT | 3822 | Port for the local background daemon |
SRIFT_BASE_URL | http://127.0.0.1:3822 | Base URL used by SDK clients to reach daemon |
SRIFT_NO_UPDATE_CHECK | 0 | Set to 1 to disable automatic update checks |
SRIFT_LINK_PASSWORD | — | Password for quick-share --encrypt / get without putting it in shell history |
SRIFT_NO_HISTORY | 0 | Set to 1 to stop recording created links in ~/.srift/history.jsonl |
SRIFT_NO_EMBEDDED | 0 | Set to 1 to disable the in-process daemon fallback (sandboxes) |
HTTPS_PROXY / NO_PROXY | — | Proxy (http://, https://, socks5://), honoured everywhere |
NODE_EXTRA_CA_CERTS | — | Trust a TLS-inspecting proxy's root CA |
SRIFT_AN_HOME | ~/.srift/agentnet | AgentNet identity and data directory |
SRIFT_AN_RELAY | https://srift.app | AgentNet relay(s), comma-separated |
SRIFT_AN_EPHEMERAL | 0 | 1 keeps AgentNet conversations in RAM only |
SRIFT_AN_PASSPHRASE | — | Encrypts the AgentNet identity file (PBKDF2-SHA256 + AES-256-GCM) |
SRIFT_AN_TRANSPORT | ws | poll forces HTTP long-poll (networks that block WebSockets) |
First-party, zero-dependency SDKs for accessing SRIFT from any programming language:
sdk/node — vendor the source; the CLI package srift-transfer also exposes the same REST surfacepip install srift (includes the CLI) — sdk/python (pip install srift needs Python 3.9+; the single-file srift.py works on CPython 3.8+ and PyPy)sdk/go (Go 1.21+)sdk/rust (sync/async)sdk/java (Java 11+)sdk/dotnet (.NET 6+)sdk/php (PHP 7.4+)sdk/ruby (Ruby 2.7+)sdk/shellDirect download (no clone): every SDK file is also served at https://srift.app/sdk/<lang>/… — for example curl -O https://srift.app/sdk/node/srift.mjs (the Node SDK is not on npm yet).
llms.txt): https://srift.app/llms.txt| Surface | Link |
|---|---|
| npm | srift-transfer |
| MCP Registry | app.srift/srift |
| Smithery | srift/srift |
| Glama (connector) | app.srift/srift |
| Glama (server) | SRIFT-Open_Source |
| GitHub | SRIFT-Open_Source |
All resolve to the same product. Install srift-transfer; the command is srift.
Maintainer documentation. Condensed runbook: docs/DISTRIBUTION.md.
| Path | Purpose |
|---|---|
app/ | Next.js 16 App Router site. SEO landing routes must stay server components |
server.mjs | Production server: Express + WebSocket signaling + hosted MCP endpoint |
cli/ | CLI source (index.ts) and headless daemon (daemon.ts) |
lib/mcp/ | Shared MCP core — one tool catalogue, two backends (local daemon + in-process) |
packages/cli/ | The publishable npm package (srift-transfer) |
tests/ | ~380 tests, Node's built-in runner |
scripts/sync-version.mjs | Single source of version propagation |
server.json | MCP registry manifest |
One version, propagated everywhere. package.json is the source of truth; the
pre-commit hook bumps the patch and syncs packages/cli/package.json,
server.json (plus packages[].version), cli/index.ts and cli/index.js,
then runs scripts/sync-version.mjs for ~15 more files — site JSON-LD,
openapi.json, agent.json, server-card.json, compat.json,
changelog.json, install.sh, install.ps1, and every
srift.app/dl/<version>/ URL.
Use SKIP_VERSION_BUMP=1 whenever npm is already published at the current
version — otherwise server.json advertises a version that isn't on npm.
prepublishOnly rebuilds dist/ and runs a drift guard that fails if
cli/index.ts's CLI_VERSION disagrees with packages/cli/package.json.
Verify:
npm i -g srift-transfer installs a binary called srift. Do not "fix" MCP
configs to say srift-transfer — that breaks them.
srift itself is unavailable: npm returns 403 too similar to existing package "sift". srift-cli is blocked for the same reason (sift-cli exists). Scoped
names (@scope/name) bypass the similarity filter if a rename is ever needed.
| Symptom | Cause | Fix |
|---|---|---|
403 requires two-factor authentication | npm 2FA | A human must run npm publish. Automate only with a granular token that has bypass 2FA. |
403 too similar to existing package | typosquat filter | Pick a different or scoped name |
npm warn publish "bin[srift]" ... was invalid and removed | bin path had a leading ./ | Use "bin": {"srift": "dist/index.js"}. npm strips it silently and ships a package with no command. CI now fails on any publish warning. |
Install dies on node-datachannel / utp-native | webtorrent in dependencies | Keep it in optionalDependencies; the daemon degrades to WebSocket transfer |
EBADENGINE | engines.node too high | Must not exclude Node 20/22 LTS |
Namespace app.srift/srift, verified by a Cloudflare DNS TXT record on
srift.app. Listing:
https://registry.modelcontextprotocol.io/v0/servers?search=srift
key.pem is the registry identity and mcp-publisher.exe is a 20 MB binary —
both are gitignored. Losing key.pem means redoing DNS verification. The TXT
record on srift.app must stay in place:
400 cannot publish duplicate version. Correcting anything in a listing —
repo URL, description, remotes — requires a new version.server.json declares
packages[].identifier: srift-transfer at a specific version. Publishing the
registry entry first makes it advertise a version npm doesn't have, and anyone
installing from the listing gets a 404.2025-12-11 and camelCase (registryType, websiteUrl,
runtimeArguments, environmentVariables, isRequired). An older revision
used snake_case; mixing them fails validation.description is capped at 100 characters.packages[].identifier must equal the npm package name — there is a test for
this, because a mismatch makes the listing install something nonexistent.| Directory | Entry | Notes |
|---|---|---|
| Smithery | srift/srift | Largest source of MCP installs. Reads server.json. Their badge endpoint currently 500s, so the READMEs use a shields.io badge linking to the listing. |
| Glama | listed | Auto-indexes public repos with MCP metadata |
| awesome-mcp-servers | PR submitted | One alphabetical line under file-management |
| GitHub topics | 18 set | topic:mcp-server is a real discovery path |
.github/workflows/ci.yml runs on every push and PR:
npm publish --dry-run emits any
warning, then smoke-tests the packed binary over real MCP stdio and asserts
15 toolsThat second job exists because npm silently stripped the bin entry once and
shipped a package with no command. Warnings are now build failures.
Push to main → Cloud Build → Cloud Run (asia-south1), ~10 minutes.
| Value | |
|---|---|
| Build VM | E2_HIGHCPU_32 (32 vCPU / 32 GB), 100 GB disk |
| Build heap | 8192 MB (BUILD_HEAP_MB) |
| Cloud Run | 4 GiB / 2 CPU, min 1 instance |
| Runtime heap | 3072 MB — deliberately below the container limit so V8 GCs instead of being OOM-killed |
| Bun | pinned via BUN_VERSION |
Every COPY source in the Dockerfile must exist — a deleted proxy.ts left in
the COPY list broke every build. A test now walks them.
On Windows pass absolute Windows paths (C:/...). Git Bash /tmp resolves
to C:\tmp and the CLI will not find the file.
| Transport | Tools | Why |
|---|---|---|
srift mcp (stdio) | 15 | full disk + key access |
127.0.0.1:3822/mcp | 15 | same local daemon |
https://srift.app/mcp | 9 | session control + diagnostics only |
Hosted omits srift_quick_share, srift_send_file, srift_accept_transfer
(need local disk) and srift_send_chat, srift_chat_history, srift_read_state
(would require deriving session keys server-side, defeating the point).
Source of truth: lib/mcp/backend-inprocess.mjs → SUPPORTED_TOOLS.
False or unprovable for SRIFT, and enforced by tests: military-grade ·
#1 · files never touch any server · untraceable · complete anonymity ·
trusted by millions · zero-knowledge as a product claim.
Say zero-retention and AES-256-GCM instead. "Zero-knowledge" is false by
default: lib/encryption.ts derives the key from the session ID alone unless an
optional roomSecret is supplied, and the server knows the session ID.
MIT License © SRIFT