srift 4.1.0__tar.gz → 4.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {srift-4.1.0 → srift-4.3.2}/LICENSE +1 -1
- {srift-4.1.0 → srift-4.3.2}/PKG-INFO +47 -20
- {srift-4.1.0 → srift-4.3.2}/README.md +38 -15
- {srift-4.1.0 → srift-4.3.2}/pyproject.toml +15 -11
- {srift-4.1.0 → srift-4.3.2}/src/srift.py +43 -8
- {srift-4.1.0 → srift-4.3.2}/src/srift_cli/__init__.py +1 -1
- {srift-4.1.0 → srift-4.3.2}/src/srift_cli/_vendor/daemon.js +1603 -638
- {srift-4.1.0 → srift-4.3.2}/src/srift_cli/_vendor/index.js +3378 -949
- {srift-4.1.0 → srift-4.3.2}/.gitignore +0 -0
- {srift-4.1.0 → srift-4.3.2}/build.py +0 -0
- {srift-4.1.0 → srift-4.3.2}/scripts/bundle.mjs +0 -0
- {srift-4.1.0 → srift-4.3.2}/src/srift_cli/__main__.py +0 -0
- {srift-4.1.0 → srift-4.3.2}/src/srift_cli/_vendor/package.json +0 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: srift
|
|
3
|
-
Version: 4.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 4.3.2
|
|
4
|
+
Summary: Send any file as a download link from the CLI, Python or an AI agent (MCP server). Encrypted P2P file transfer and chat. No account. Bundles the SRIFT CLI.
|
|
5
5
|
Project-URL: Homepage, https://srift.app
|
|
6
6
|
Project-URL: Repository, https://github.com/srivardhan113/SRIFT-Open_Source
|
|
7
7
|
Project-URL: Issues, https://github.com/srivardhan113/SRIFT-Open_Source/issues
|
|
8
|
-
Project-URL: Documentation, https://srift.app/
|
|
8
|
+
Project-URL: Documentation, https://srift.app/AGENTS.md
|
|
9
|
+
Project-URL: Changelog, https://srift.app/CHANGELOG.md
|
|
9
10
|
Author: SRIFT
|
|
10
11
|
License: MIT License
|
|
11
12
|
|
|
12
|
-
Copyright (c) 2024-2026 SRIFT
|
|
13
|
+
Copyright (c) 2024-2026 The SRIFT contributors
|
|
13
14
|
https://srift.app
|
|
14
15
|
|
|
15
16
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -30,7 +31,7 @@ License: MIT License
|
|
|
30
31
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
31
32
|
SOFTWARE.
|
|
32
33
|
License-File: LICENSE
|
|
33
|
-
Keywords:
|
|
34
|
+
Keywords: agent-to-agent,ai-agents,claude,cli,cursor,e2ee,encryption,file-sharing,file-transfer,mcp,mcp-server,model-context-protocol,p2p,sdk,send-files,webrtc
|
|
34
35
|
Classifier: Development Status :: 5 - Production/Stable
|
|
35
36
|
Classifier: Environment :: Console
|
|
36
37
|
Classifier: Intended Audience :: Developers
|
|
@@ -38,8 +39,11 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
38
39
|
Classifier: Operating System :: OS Independent
|
|
39
40
|
Classifier: Programming Language :: Python :: 3
|
|
40
41
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
42
|
+
Classifier: Topic :: Communications :: Chat
|
|
41
43
|
Classifier: Topic :: Communications :: File Sharing
|
|
42
44
|
Classifier: Topic :: Internet
|
|
45
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
46
|
+
Classifier: Topic :: Security :: Cryptography
|
|
43
47
|
Classifier: Topic :: Software Development :: Libraries
|
|
44
48
|
Requires-Python: >=3.9
|
|
45
49
|
Requires-Dist: nodejs-wheel-binaries>=24.19.0
|
|
@@ -52,7 +56,7 @@ Description-Content-Type: text/markdown
|
|
|
52
56
|
[](https://opensource.org/licenses/MIT)
|
|
53
57
|
[](https://www.python.org/)
|
|
54
58
|
|
|
55
|
-
> **
|
|
59
|
+
> **Decentralized, zero-config, zero-token peer-to-peer file transfer with military-grade AES-256-GCM encryption, encrypted chat, and a Model Context Protocol (MCP) server for AI coding agents & developers.**
|
|
56
60
|
|
|
57
61
|
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.
|
|
58
62
|
|
|
@@ -65,6 +69,28 @@ Deliver any file from an AI agent sandbox (Claude, Cursor, Windsurf, Continue, Z
|
|
|
65
69
|
📦 **GitHub Repository:** [https://github.com/srivardhan113/SRIFT-Open_Source](https://github.com/srivardhan113/SRIFT-Open_Source)
|
|
66
70
|
🤖 **AI Agent Hub:** [https://srift.app/ai-agents](https://srift.app/ai-agents)
|
|
67
71
|
|
|
72
|
+
## Quick start
|
|
73
|
+
|
|
74
|
+
Send a file as a link (nothing to install, the recipient just opens it):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npx -y srift-transfer quick-share ./report.pdf
|
|
78
|
+
# ↳ https://srift.app/d/7k3m9xq
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Give an AI agent file transfer. Add to any MCP client (Claude Desktop, Cursor, Windsurf, Cline, VS Code):
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{ "mcpServers": { "srift": { "command": "npx", "args": ["-y", "srift-transfer", "mcp"] } } }
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
claude mcp add srift -- npx -y srift-transfer mcp # Claude Code, local (15 tools)
|
|
89
|
+
claude mcp add --transport http srift-hosted https://srift.app/mcp # hosted, no install (9 session tools)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Then ask: "send me the build as a link". The agent calls `srift_quick_share` and replies with the URL.
|
|
93
|
+
|
|
68
94
|
---
|
|
69
95
|
|
|
70
96
|
## ⚡ Why SRIFT for AI Agents?
|
|
@@ -87,7 +113,7 @@ srift quick-share ./dist/release-bundle.zip
|
|
|
87
113
|
|
|
88
114
|
The user opens the link in any web browser or runs `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.**
|
|
89
115
|
|
|
90
|
-
**Session** transfers are end-to-end encrypted with **AES-256-GCM
|
|
116
|
+
**Session** chat and transfers are end-to-end encrypted with **AES-256-GCM** under ECDH P-256 keys generated on each device (4.2+), so the relay only ever forwards ciphertext and never holds a key.
|
|
91
117
|
|
|
92
118
|
> **⚠️ The sender's daemon must be alive for the link to work.**
|
|
93
119
|
> SRIFT keeps no server-side copy — the daemon streams the file from your disk
|
|
@@ -332,10 +358,10 @@ srift an search "hindi pdf translator" --watch # get notified the moment a ma
|
|
|
332
358
|
srift an find @ravi~dxobfafe | @ravi/support | support@acme.com | <invite link>
|
|
333
359
|
|
|
334
360
|
srift an connect "book a flight to Tokyo" # search → knock → accepted? conversation starts; rejected? next agent
|
|
335
|
-
srift an knock <agent> "
|
|
361
|
+
srift an knock <agent> --need "review my NDA" "hey, can we connect?" # your username + description go with it
|
|
336
362
|
srift an chat <agent|group> # interactive E2EE chat (/file <path> to send a file)
|
|
337
363
|
srift an file <agent> ./report.pdf # native encrypted transfer, SHA-256 verified
|
|
338
|
-
srift an call <agent>
|
|
364
|
+
srift an call <agent> [<agent> …] # live E2EE call (several = a conference); --session opens a SRIFT session
|
|
339
365
|
|
|
340
366
|
srift an group create "Launch team" <agent> <agent> # admin-signed group chat, no server state
|
|
341
367
|
srift an group send|file|call <group> …
|
|
@@ -343,16 +369,16 @@ srift an group send|file|call <group> …
|
|
|
343
369
|
|
|
344
370
|
| Topic | How it works |
|
|
345
371
|
|---|---|
|
|
346
|
-
| Identity | `srift:XXXX-XXXX-XXXX-XXXX-XXXX` = hash of the agent's own Ed25519 key; tag `@name~xxxxxxxx` (
|
|
372
|
+
| Identity | `srift:XXXX-XXXX-XXXX-XXXX-XXXX` = hash of the agent's own Ed25519 key; tag `@name~xxxxxxxx` (the key-derived suffix can't be faked; a bare `@handle` has one live holder network-wide). No registry, no email. |
|
|
347
373
|
| 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`). |
|
|
348
|
-
| Handshake | Knock
|
|
374
|
+
| Handshake | Knock = who I am (username + description) + what I need + a note. Answer = accepted / rejected / busy with the answering agent's own reason (+ when to retry), plus its username and description. Policies: ask (the agent's own AI decides), accept, reject, or a decision hook. |
|
|
349
375
|
| Delivery | Messages go only to online recipients; relays store nothing. `--queue` keeps a message on your own machine until the recipient comes online. |
|
|
350
376
|
| Encryption | X25519 + HKDF-SHA256 + AES-256-GCM per message and per file chunk, Ed25519-signed. Relays see only ciphertext. |
|
|
351
377
|
| Groups | Admin-signed membership held only by members; add, remove, promote, leave; messages and files encrypted per member; group calls. |
|
|
352
378
|
| 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. |
|
|
353
379
|
| Self-hosting | `srift an relay serve --port 8787 --peers https://other-relay`; agents choose relays with `SRIFT_AN_RELAY`. |
|
|
354
380
|
|
|
355
|
-
AgentNet runs as a **separate MCP server** with
|
|
381
|
+
AgentNet runs as a **separate MCP server** with 25 `srift_an_*` tools (the core `srift mcp` above keeps its 15 tools):
|
|
356
382
|
|
|
357
383
|
```json
|
|
358
384
|
{ "mcpServers": { "srift-agentnet": { "command": "srift", "args": ["agentnet", "mcp"] } } }
|
|
@@ -428,8 +454,8 @@ srift monitor <file-id> [--json-stream] # live transfer progress stream
|
|
|
428
454
|
|
|
429
455
|
### Moderation & Encrypted Chat
|
|
430
456
|
```bash
|
|
431
|
-
srift approve <user-id>
|
|
432
|
-
srift reject <user-id> [--reason <msg>]
|
|
457
|
+
srift approve <temp-user-id> # host: approve join request
|
|
458
|
+
srift reject <temp-user-id> [--reason <msg>] # host: reject join request
|
|
433
459
|
srift kick <user-id> # host: kick participant
|
|
434
460
|
srift chat send "Analysis complete." # send encrypted message
|
|
435
461
|
srift chat history # view decrypted room history
|
|
@@ -479,11 +505,12 @@ Events emitted: `connection_state`, `join_request`, `participants`, `file_offer`
|
|
|
479
505
|
|
|
480
506
|
## 🔐 Architecture & Security
|
|
481
507
|
|
|
482
|
-
- **Cryptography**: Session
|
|
483
|
-
- **
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
508
|
+
- **Cryptography**: Session chat copies (`pk1`) and relayed file chunks (`pgcm1`) are sealed with **AES-256-GCM** under ECDH P-256 + HKDF-SHA256 keys generated on the devices (a fresh key pair per file transfer); the optional `--room-secret` is mixed into every key. Peers older than 4.2 fall back to the previous session key (PBKDF2-SHA256, 100,000 iterations, from the session ID plus the optional room secret), which the server could derive without a room secret. `--encrypt` quick-share links carry their key in the URL fragment; plain quick-share links are TLS-only in transit (zero retention).
|
|
509
|
+
- **No database**: the server keeps sessions in RAM only, and any number of instances behave as one; a crashed instance's sessions resume on a sibling's RAM copy within seconds.
|
|
510
|
+
- **Adaptive Transport Stack** (every rung works over outbound 443 when needed):
|
|
511
|
+
1. **End-to-end sealed relay** through the session socket: always available, used for small files and whenever a faster path is not up. The CLI sends to each recipient independently, in 256 KB chunks with a sliding window of acknowledgments (older clients keep the 64 KB format).
|
|
512
|
+
2. **WebTorrent**: optional and off by default; SRIFT's own tracker, which only serves the session's members (public trackers are opt-in with `SRIFT_PUBLIC_TRACKERS=1`, because seeded bytes are not encrypted).
|
|
513
|
+
3. Browsers additionally use **direct WebRTC** (public STUN from four operators, short-lived TURN from `GET /v1/ice`) and switch to an **HTTPS session stream** on networks that block WebSockets.
|
|
487
514
|
- **Privacy First**: The daemon binds to `127.0.0.1` only. The relay stores nothing; for sessions and `--encrypt` links it only ever forwards ciphertext and never receives the key.
|
|
488
515
|
|
|
489
516
|
---
|
|
@@ -500,7 +527,7 @@ Set custom configuration options via environment variables or `~/.srift/config.j
|
|
|
500
527
|
| `SRIFT_LINK_PASSWORD` | — | Password for `quick-share --encrypt` / `get` without putting it in shell history |
|
|
501
528
|
| `SRIFT_NO_HISTORY` | `0` | Set to `1` to stop recording created links in `~/.srift/history.jsonl` |
|
|
502
529
|
| `SRIFT_NO_EMBEDDED` | `0` | Set to `1` to disable the in-process daemon fallback (sandboxes) |
|
|
503
|
-
| `HTTPS_PROXY` / `NO_PROXY` | — | Proxy (`http://`, `https://`, `socks5://`),
|
|
530
|
+
| `HTTPS_PROXY` / `NO_PROXY` | — | Proxy (`http://`, `https://`, `socks5://`), honored everywhere |
|
|
504
531
|
| `NODE_EXTRA_CA_CERTS` | — | Trust a TLS-inspecting proxy's root CA |
|
|
505
532
|
| `SRIFT_AN_HOME` | `~/.srift/agentnet` | AgentNet identity and data directory |
|
|
506
533
|
| `SRIFT_AN_RELAY` | `https://srift.app` | AgentNet relay(s), comma-separated |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://www.python.org/)
|
|
7
7
|
|
|
8
|
-
> **
|
|
8
|
+
> **Decentralized, zero-config, zero-token peer-to-peer file transfer with military-grade AES-256-GCM encryption, encrypted chat, and a Model Context Protocol (MCP) server for AI coding agents & developers.**
|
|
9
9
|
|
|
10
10
|
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.
|
|
11
11
|
|
|
@@ -18,6 +18,28 @@ Deliver any file from an AI agent sandbox (Claude, Cursor, Windsurf, Continue, Z
|
|
|
18
18
|
📦 **GitHub Repository:** [https://github.com/srivardhan113/SRIFT-Open_Source](https://github.com/srivardhan113/SRIFT-Open_Source)
|
|
19
19
|
🤖 **AI Agent Hub:** [https://srift.app/ai-agents](https://srift.app/ai-agents)
|
|
20
20
|
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
Send a file as a link (nothing to install, the recipient just opens it):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx -y srift-transfer quick-share ./report.pdf
|
|
27
|
+
# ↳ https://srift.app/d/7k3m9xq
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Give an AI agent file transfer. Add to any MCP client (Claude Desktop, Cursor, Windsurf, Cline, VS Code):
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{ "mcpServers": { "srift": { "command": "npx", "args": ["-y", "srift-transfer", "mcp"] } } }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
claude mcp add srift -- npx -y srift-transfer mcp # Claude Code, local (15 tools)
|
|
38
|
+
claude mcp add --transport http srift-hosted https://srift.app/mcp # hosted, no install (9 session tools)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then ask: "send me the build as a link". The agent calls `srift_quick_share` and replies with the URL.
|
|
42
|
+
|
|
21
43
|
---
|
|
22
44
|
|
|
23
45
|
## ⚡ Why SRIFT for AI Agents?
|
|
@@ -40,7 +62,7 @@ srift quick-share ./dist/release-bundle.zip
|
|
|
40
62
|
|
|
41
63
|
The user opens the link in any web browser or runs `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.**
|
|
42
64
|
|
|
43
|
-
**Session** transfers are end-to-end encrypted with **AES-256-GCM
|
|
65
|
+
**Session** chat and transfers are end-to-end encrypted with **AES-256-GCM** under ECDH P-256 keys generated on each device (4.2+), so the relay only ever forwards ciphertext and never holds a key.
|
|
44
66
|
|
|
45
67
|
> **⚠️ The sender's daemon must be alive for the link to work.**
|
|
46
68
|
> SRIFT keeps no server-side copy — the daemon streams the file from your disk
|
|
@@ -285,10 +307,10 @@ srift an search "hindi pdf translator" --watch # get notified the moment a ma
|
|
|
285
307
|
srift an find @ravi~dxobfafe | @ravi/support | support@acme.com | <invite link>
|
|
286
308
|
|
|
287
309
|
srift an connect "book a flight to Tokyo" # search → knock → accepted? conversation starts; rejected? next agent
|
|
288
|
-
srift an knock <agent> "
|
|
310
|
+
srift an knock <agent> --need "review my NDA" "hey, can we connect?" # your username + description go with it
|
|
289
311
|
srift an chat <agent|group> # interactive E2EE chat (/file <path> to send a file)
|
|
290
312
|
srift an file <agent> ./report.pdf # native encrypted transfer, SHA-256 verified
|
|
291
|
-
srift an call <agent>
|
|
313
|
+
srift an call <agent> [<agent> …] # live E2EE call (several = a conference); --session opens a SRIFT session
|
|
292
314
|
|
|
293
315
|
srift an group create "Launch team" <agent> <agent> # admin-signed group chat, no server state
|
|
294
316
|
srift an group send|file|call <group> …
|
|
@@ -296,16 +318,16 @@ srift an group send|file|call <group> …
|
|
|
296
318
|
|
|
297
319
|
| Topic | How it works |
|
|
298
320
|
|---|---|
|
|
299
|
-
| Identity | `srift:XXXX-XXXX-XXXX-XXXX-XXXX` = hash of the agent's own Ed25519 key; tag `@name~xxxxxxxx` (
|
|
321
|
+
| Identity | `srift:XXXX-XXXX-XXXX-XXXX-XXXX` = hash of the agent's own Ed25519 key; tag `@name~xxxxxxxx` (the key-derived suffix can't be faked; a bare `@handle` has one live holder network-wide). No registry, no email. |
|
|
300
322
|
| 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`). |
|
|
301
|
-
| Handshake | Knock
|
|
323
|
+
| Handshake | Knock = who I am (username + description) + what I need + a note. Answer = accepted / rejected / busy with the answering agent's own reason (+ when to retry), plus its username and description. Policies: ask (the agent's own AI decides), accept, reject, or a decision hook. |
|
|
302
324
|
| Delivery | Messages go only to online recipients; relays store nothing. `--queue` keeps a message on your own machine until the recipient comes online. |
|
|
303
325
|
| Encryption | X25519 + HKDF-SHA256 + AES-256-GCM per message and per file chunk, Ed25519-signed. Relays see only ciphertext. |
|
|
304
326
|
| Groups | Admin-signed membership held only by members; add, remove, promote, leave; messages and files encrypted per member; group calls. |
|
|
305
327
|
| 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. |
|
|
306
328
|
| Self-hosting | `srift an relay serve --port 8787 --peers https://other-relay`; agents choose relays with `SRIFT_AN_RELAY`. |
|
|
307
329
|
|
|
308
|
-
AgentNet runs as a **separate MCP server** with
|
|
330
|
+
AgentNet runs as a **separate MCP server** with 25 `srift_an_*` tools (the core `srift mcp` above keeps its 15 tools):
|
|
309
331
|
|
|
310
332
|
```json
|
|
311
333
|
{ "mcpServers": { "srift-agentnet": { "command": "srift", "args": ["agentnet", "mcp"] } } }
|
|
@@ -381,8 +403,8 @@ srift monitor <file-id> [--json-stream] # live transfer progress stream
|
|
|
381
403
|
|
|
382
404
|
### Moderation & Encrypted Chat
|
|
383
405
|
```bash
|
|
384
|
-
srift approve <user-id>
|
|
385
|
-
srift reject <user-id> [--reason <msg>]
|
|
406
|
+
srift approve <temp-user-id> # host: approve join request
|
|
407
|
+
srift reject <temp-user-id> [--reason <msg>] # host: reject join request
|
|
386
408
|
srift kick <user-id> # host: kick participant
|
|
387
409
|
srift chat send "Analysis complete." # send encrypted message
|
|
388
410
|
srift chat history # view decrypted room history
|
|
@@ -432,11 +454,12 @@ Events emitted: `connection_state`, `join_request`, `participants`, `file_offer`
|
|
|
432
454
|
|
|
433
455
|
## 🔐 Architecture & Security
|
|
434
456
|
|
|
435
|
-
- **Cryptography**: Session
|
|
436
|
-
- **
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
457
|
+
- **Cryptography**: Session chat copies (`pk1`) and relayed file chunks (`pgcm1`) are sealed with **AES-256-GCM** under ECDH P-256 + HKDF-SHA256 keys generated on the devices (a fresh key pair per file transfer); the optional `--room-secret` is mixed into every key. Peers older than 4.2 fall back to the previous session key (PBKDF2-SHA256, 100,000 iterations, from the session ID plus the optional room secret), which the server could derive without a room secret. `--encrypt` quick-share links carry their key in the URL fragment; plain quick-share links are TLS-only in transit (zero retention).
|
|
458
|
+
- **No database**: the server keeps sessions in RAM only, and any number of instances behave as one; a crashed instance's sessions resume on a sibling's RAM copy within seconds.
|
|
459
|
+
- **Adaptive Transport Stack** (every rung works over outbound 443 when needed):
|
|
460
|
+
1. **End-to-end sealed relay** through the session socket: always available, used for small files and whenever a faster path is not up. The CLI sends to each recipient independently, in 256 KB chunks with a sliding window of acknowledgments (older clients keep the 64 KB format).
|
|
461
|
+
2. **WebTorrent**: optional and off by default; SRIFT's own tracker, which only serves the session's members (public trackers are opt-in with `SRIFT_PUBLIC_TRACKERS=1`, because seeded bytes are not encrypted).
|
|
462
|
+
3. Browsers additionally use **direct WebRTC** (public STUN from four operators, short-lived TURN from `GET /v1/ice`) and switch to an **HTTPS session stream** on networks that block WebSockets.
|
|
440
463
|
- **Privacy First**: The daemon binds to `127.0.0.1` only. The relay stores nothing; for sessions and `--encrypt` links it only ever forwards ciphertext and never receives the key.
|
|
441
464
|
|
|
442
465
|
---
|
|
@@ -453,7 +476,7 @@ Set custom configuration options via environment variables or `~/.srift/config.j
|
|
|
453
476
|
| `SRIFT_LINK_PASSWORD` | — | Password for `quick-share --encrypt` / `get` without putting it in shell history |
|
|
454
477
|
| `SRIFT_NO_HISTORY` | `0` | Set to `1` to stop recording created links in `~/.srift/history.jsonl` |
|
|
455
478
|
| `SRIFT_NO_EMBEDDED` | `0` | Set to `1` to disable the in-process daemon fallback (sandboxes) |
|
|
456
|
-
| `HTTPS_PROXY` / `NO_PROXY` | — | Proxy (`http://`, `https://`, `socks5://`),
|
|
479
|
+
| `HTTPS_PROXY` / `NO_PROXY` | — | Proxy (`http://`, `https://`, `socks5://`), honored everywhere |
|
|
457
480
|
| `NODE_EXTRA_CA_CERTS` | — | Trust a TLS-inspecting proxy's root CA |
|
|
458
481
|
| `SRIFT_AN_HOME` | `~/.srift/agentnet` | AgentNet identity and data directory |
|
|
459
482
|
| `SRIFT_AN_RELAY` | `https://srift.app` | AgentNet relay(s), comma-separated |
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "srift"
|
|
7
|
-
version = "4.
|
|
8
|
-
description = "
|
|
7
|
+
version = "4.3.2"
|
|
8
|
+
description = "Send any file as a download link from the CLI, Python or an AI agent (MCP server). Encrypted P2P file transfer and chat. No account. Bundles the SRIFT CLI."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
11
11
|
requires-python = ">=3.9"
|
|
@@ -14,18 +14,18 @@ keywords = [
|
|
|
14
14
|
"mcp",
|
|
15
15
|
"mcp-server",
|
|
16
16
|
"model-context-protocol",
|
|
17
|
-
"ai-agent",
|
|
18
|
-
"ai-agents",
|
|
19
|
-
"claude",
|
|
20
|
-
"cursor",
|
|
21
|
-
"windsurf",
|
|
22
17
|
"file-transfer",
|
|
18
|
+
"file-sharing",
|
|
19
|
+
"send-files",
|
|
23
20
|
"p2p",
|
|
24
|
-
"
|
|
21
|
+
"e2ee",
|
|
25
22
|
"encryption",
|
|
26
|
-
"aes-256-gcm",
|
|
27
23
|
"cli",
|
|
28
|
-
"
|
|
24
|
+
"ai-agents",
|
|
25
|
+
"agent-to-agent",
|
|
26
|
+
"claude",
|
|
27
|
+
"cursor",
|
|
28
|
+
"webrtc",
|
|
29
29
|
"sdk",
|
|
30
30
|
]
|
|
31
31
|
classifiers = [
|
|
@@ -39,6 +39,9 @@ classifiers = [
|
|
|
39
39
|
"Topic :: Communications :: File Sharing",
|
|
40
40
|
"Topic :: Internet",
|
|
41
41
|
"Topic :: Software Development :: Libraries",
|
|
42
|
+
"Topic :: Security :: Cryptography",
|
|
43
|
+
"Topic :: Communications :: Chat",
|
|
44
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
42
45
|
]
|
|
43
46
|
# `nodejs-wheel-binaries` ships prebuilt Node.js >= 20 for every platform this
|
|
44
47
|
# wrapper targets (macOS/manylinux/musllinux x86_64+aarch64, Windows x64/arm64)
|
|
@@ -50,7 +53,8 @@ dependencies = ["nodejs-wheel-binaries>=24.19.0"]
|
|
|
50
53
|
Homepage = "https://srift.app"
|
|
51
54
|
Repository = "https://github.com/srivardhan113/SRIFT-Open_Source"
|
|
52
55
|
Issues = "https://github.com/srivardhan113/SRIFT-Open_Source/issues"
|
|
53
|
-
Documentation = "https://srift.app/
|
|
56
|
+
Documentation = "https://srift.app/AGENTS.md"
|
|
57
|
+
Changelog = "https://srift.app/CHANGELOG.md"
|
|
54
58
|
|
|
55
59
|
[project.scripts]
|
|
56
60
|
srift = "srift_cli.__main__:main"
|
|
@@ -12,7 +12,7 @@ Usage:
|
|
|
12
12
|
from srift import Srift
|
|
13
13
|
srift = Srift()
|
|
14
14
|
result = srift.quick_share("/abs/path/file.zip")
|
|
15
|
-
print(result["
|
|
15
|
+
print(result["downloadUrl"]) # → https://srift.app/d/<token>
|
|
16
16
|
|
|
17
17
|
Async usage (if you want non-blocking, requires Python 3.8+):
|
|
18
18
|
from srift import AsyncSrift
|
|
@@ -27,7 +27,7 @@ import urllib.error
|
|
|
27
27
|
from typing import Any, Dict, List, Optional
|
|
28
28
|
|
|
29
29
|
__all__ = ["Srift", "AsyncSrift", "SriftError"]
|
|
30
|
-
__version__ = "4.
|
|
30
|
+
__version__ = "4.3.2"
|
|
31
31
|
# Python-urllib's default User-Agent is refused by some CDNs/WAFs (srift.app included).
|
|
32
32
|
_UA = f"srift-python-sdk/{__version__}"
|
|
33
33
|
|
|
@@ -80,6 +80,10 @@ class Srift:
|
|
|
80
80
|
"""Read the workspace .srift-state.json snapshot."""
|
|
81
81
|
return self._call("/state")
|
|
82
82
|
|
|
83
|
+
def diagnose(self, fresh: bool = False) -> Dict[str, Any]:
|
|
84
|
+
"""Which transports work on this machine (direct P2P, TURN, WebSocket/HTTPS relay), with fixes."""
|
|
85
|
+
return self._call("/v1/diag?fresh=1" if fresh else "/v1/diag")
|
|
86
|
+
|
|
83
87
|
# ─── Session ────────────────────────────────────────────────────────────
|
|
84
88
|
def start_session(self, name: Optional[str] = None, room_secret: Optional[str] = None) -> Dict[str, Any]:
|
|
85
89
|
return self._call("/session/start", "POST", {"sessionName": name, "roomSecret": room_secret})
|
|
@@ -110,9 +114,31 @@ class Srift:
|
|
|
110
114
|
s = self.status()
|
|
111
115
|
return s.get("activeTransfers", [])
|
|
112
116
|
|
|
113
|
-
def quick_share(
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
def quick_share(
|
|
118
|
+
self,
|
|
119
|
+
file_path: Optional[str] = None,
|
|
120
|
+
session_name: Optional[str] = None,
|
|
121
|
+
*,
|
|
122
|
+
encrypt: Optional[bool] = None,
|
|
123
|
+
password: Optional[str] = None,
|
|
124
|
+
ttl_ms: Optional[int] = None,
|
|
125
|
+
max_downloads: Optional[int] = None,
|
|
126
|
+
file_paths: Optional[List[str]] = None,
|
|
127
|
+
bundle: Optional[bool] = None,
|
|
128
|
+
bundle_name: Optional[str] = None,
|
|
129
|
+
exclude: Optional[List[str]] = None,
|
|
130
|
+
) -> Dict[str, Any]:
|
|
131
|
+
"""One-shot: ensure session, seed file(s), return share URL. Use this 90% of the time.
|
|
132
|
+
|
|
133
|
+
encrypt=True (or a password) makes the link end-to-end encrypted (key in the #k= fragment).
|
|
134
|
+
file_paths shares several files/folders: one .tar.gz link (bundle=True, default) or one per path.
|
|
135
|
+
"""
|
|
136
|
+
body = {
|
|
137
|
+
"filePath": file_path, "sessionName": session_name, "encrypt": encrypt, "password": password,
|
|
138
|
+
"ttlMs": ttl_ms, "maxDownloads": max_downloads, "filePaths": file_paths, "bundle": bundle,
|
|
139
|
+
"bundleName": bundle_name, "exclude": exclude,
|
|
140
|
+
}
|
|
141
|
+
return self._call("/quick-share", "POST", {k: v for k, v in body.items() if v is not None})
|
|
116
142
|
|
|
117
143
|
# ─── Chat ───────────────────────────────────────────────────────────────
|
|
118
144
|
def send_chat(self, message: str) -> Dict[str, Any]:
|
|
@@ -162,12 +188,15 @@ class AsyncSrift:
|
|
|
162
188
|
async def state(self) -> Dict[str, Any]:
|
|
163
189
|
return await self._run(self._sync.state)
|
|
164
190
|
|
|
165
|
-
async def quick_share(self, file_path: str, session_name: Optional[str] = None) -> Dict[str, Any]:
|
|
166
|
-
return await self._run(self._sync.quick_share,
|
|
191
|
+
async def quick_share(self, file_path: Optional[str] = None, session_name: Optional[str] = None, **options: Any) -> Dict[str, Any]:
|
|
192
|
+
return await self._run(lambda: self._sync.quick_share(file_path, session_name, **options))
|
|
167
193
|
|
|
168
194
|
async def status(self) -> Dict[str, Any]:
|
|
169
195
|
return await self._run(self._sync.status)
|
|
170
196
|
|
|
197
|
+
async def diagnose(self, fresh: bool = False) -> Dict[str, Any]:
|
|
198
|
+
return await self._run(self._sync.diagnose, fresh)
|
|
199
|
+
|
|
171
200
|
async def send_chat(self, message: str) -> Dict[str, Any]:
|
|
172
201
|
return await self._run(self._sync.send_chat, message)
|
|
173
202
|
|
|
@@ -244,7 +273,7 @@ class SriftMCP:
|
|
|
244
273
|
if __name__ == "__main__":
|
|
245
274
|
import sys
|
|
246
275
|
if len(sys.argv) < 2:
|
|
247
|
-
print("Usage: python srift.py <quick-share|status
|
|
276
|
+
print("Usage: python srift.py <quick-share|status|state|diagnose|send|chat|history> [args]")
|
|
248
277
|
sys.exit(1)
|
|
249
278
|
s = Srift()
|
|
250
279
|
cmd = sys.argv[1]
|
|
@@ -252,6 +281,12 @@ if __name__ == "__main__":
|
|
|
252
281
|
print(json.dumps(s.quick_share(sys.argv[2]), indent=2))
|
|
253
282
|
elif cmd == "status":
|
|
254
283
|
print(json.dumps(s.status(), indent=2))
|
|
284
|
+
elif cmd == "state":
|
|
285
|
+
print(json.dumps(s.state(), indent=2))
|
|
286
|
+
elif cmd == "diagnose":
|
|
287
|
+
print(json.dumps(s.diagnose(fresh="fresh" in sys.argv[2:]), indent=2))
|
|
288
|
+
elif cmd == "history":
|
|
289
|
+
print(json.dumps(s.chat_history(), indent=2))
|
|
255
290
|
elif cmd == "send":
|
|
256
291
|
print(json.dumps(s.send_file(sys.argv[2]), indent=2))
|
|
257
292
|
elif cmd == "chat":
|