akashcli 4.8.4__tar.gz → 4.8.6__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.
Files changed (33) hide show
  1. {akashcli-4.8.4 → akashcli-4.8.6}/PKG-INFO +41 -5
  2. {akashcli-4.8.4 → akashcli-4.8.6}/README.md +40 -4
  3. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/__init__.py +1 -1
  4. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/cli.py +140 -138
  5. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/client.py +1 -1
  6. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/storage.py +4 -0
  7. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/uploader.py +11 -1
  8. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli.egg-info/PKG-INFO +41 -5
  9. {akashcli-4.8.4 → akashcli-4.8.6}/pyproject.toml +1 -1
  10. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/_net.py +0 -0
  11. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/auth.py +0 -0
  12. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/config.py +0 -0
  13. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/crypto.py +0 -0
  14. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/env_manager.py +0 -0
  15. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/exceptions.py +0 -0
  16. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/exec.py +0 -0
  17. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/integrity.py +0 -0
  18. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/logger.py +0 -0
  19. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/models.py +0 -0
  20. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/p2p.py +0 -0
  21. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/packages.py +0 -0
  22. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/relay.py +0 -0
  23. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/restore.py +0 -0
  24. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/snapshot_crypto.py +0 -0
  25. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/terminal.py +0 -0
  26. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/updater.py +0 -0
  27. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli/utils.py +0 -0
  28. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli.egg-info/SOURCES.txt +0 -0
  29. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli.egg-info/dependency_links.txt +0 -0
  30. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli.egg-info/entry_points.txt +0 -0
  31. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli.egg-info/requires.txt +0 -0
  32. {akashcli-4.8.4 → akashcli-4.8.6}/akashcli.egg-info/top_level.txt +0 -0
  33. {akashcli-4.8.4 → akashcli-4.8.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akashcli
3
- Version: 4.8.4
3
+ Version: 4.8.6
4
4
  Summary: Akash CLI — secure remote shell relay, file vault, and device management
5
5
  License-Expression: MIT
6
6
  Keywords: akash,cli,relay,remote-shell,vault
@@ -35,6 +35,7 @@ Requires-Dist: websockets
35
35
  [Quickstart](#-quickstart-in-60-seconds) •
36
36
  [Core Features](#-core-features) •
37
37
  [Zero-Login Guest Mode](#-zero-login-guest-mode) •
38
+ [💖 Sponsoring](#-sponsorship--restoring-storage-services) •
38
39
  [Documentation](#-in-depth-documentation-guides) •
39
40
  [Command Matrix](#-command-matrix)
40
41
 
@@ -42,6 +43,14 @@ Requires-Dist: websockets
42
43
 
43
44
  </div>
44
45
 
46
+ > [!WARNING]
47
+ > ### ⚠️ Cloud Storage & Upload Services Discontinued Due to Lack of Funding
48
+ > **Notice:** Public cloud file uploading and storage hosting services (`akash upload`, `akash cloud upload`, `akash cloud bulk`, `akash pipe`) have been **discontinued due to infrastructure hosting costs and lack of funding**.
49
+ >
50
+ > All terminal features (**remote shell relays, 1-click guest pairing, environment snapshots, local .env management, and AI MCP agent bridges**) remain **100% active and free**.
51
+ >
52
+ > 💖 **Help us bring back community storage infrastructure:** Please consider [Sponsoring the Project](#-sponsorship--restoring-storage-services) or running `akash sponsor`.
53
+
45
54
  ## 🌟 Why Akash CLI?
46
55
 
47
56
  Modern developer workflows demand flexibility across multiple machines — laptops, cloud servers, and mobile environments like Android Termux. Akash CLI solves daily pain points with a unified, secure toolkit:
@@ -175,8 +184,16 @@ akash env push prod --burn
175
184
  akash env pull eX481p prod
176
185
  ```
177
186
 
178
- ### 6. 🤖 AI Agent Gateway (MCP) & Guard Console
187
+ ### 6. AI Agent Gateway (MCP) & Guard Console
179
188
  Supercharge Cursor and Claude Desktop with local terminal execution, protected by real-time human approval:
189
+
190
+ ```
191
+ ╭─────╮
192
+ ╭──╯ ╰──╮ AKASH MCP
193
+ ( M C P ) Model Context Protocol · Claude · Cursor · Codex
194
+ ╰───────────╯
195
+ ```
196
+
180
197
  ```bash
181
198
  # 1. Create agent profile with safe role preset:
182
199
  akash agent create --name "Cursor" --role @coder
@@ -215,6 +232,7 @@ Explore comprehensive guides in the [`docs/`](docs/) directory:
215
232
 
216
233
  ```text
217
234
  akash
235
+ ├── sponsor 💖 Information on sponsoring & bringing back storage nodes
218
236
  ├── login Connect API key with hardware binding
219
237
  ├── whoami Account quota & device fingerprint
220
238
  ├── backup Save terminal environment to cloud or local archive
@@ -225,12 +243,12 @@ akash
225
243
  ├── serve Make device reachable (--daemon, --share for guest mode)
226
244
  ├── devices List, authorize, or revoke enrolled machines
227
245
  ├── cloud
228
- │ ├── upload Upload file or secret text snippet
246
+ │ ├── upload [DISCONTINUED] Upload file (run 'akash sponsor' for details)
229
247
  │ ├── files List vault files
230
248
  │ ├── stream Direct streaming link or launch in VLC
231
- │ ├── bulk Recursively upload directory
249
+ │ ├── bulk [DISCONTINUED] Recursively upload directory
232
250
  │ └── delete Purge file permanently
233
- ├── pipe Upload stdin or command output directly to cloud
251
+ ├── pipe [DISCONTINUED] Upload stdin directly to cloud
234
252
  ├── send End-to-end encrypted P2P transfer to user public key
235
253
  ├── inbox Receive and decrypt incoming P2P files
236
254
  ├── id View or export P2P identity key and manage contacts
@@ -267,6 +285,24 @@ Akash CLI enforces security at every layer:
267
285
 
268
286
  ---
269
287
 
288
+ ## 💖 Sponsorship & Restoring Storage Services
289
+
290
+ Akash CLI is an independent, community-driven open-source project. We previously provided free, high-speed public file uploading, sharing, and native media streaming. However, due to mounting NVMe cloud server expenses, bandwidth costs, and **a lack of operational funding**, public storage and uploading services had to be discontinued.
291
+
292
+ ### How Your Sponsorship Helps
293
+ Your financial contribution directly funds:
294
+ * 💽 **Dedicated NVMe Storage Nodes**: Restoring community cloud vault storage for backups and files.
295
+ * 🌐 **High-Bandwidth Network Transit**: Low-latency global relay clusters for terminal sessions and fast file retrieval.
296
+ * 🛡️ **Long-Term Open Source Maintenance**: Ongoing development for Termux, Linux, macOS, and Windows.
297
+
298
+ ### Ways to Sponsor & Donate
299
+ * **GitHub Sponsors**: [https://github.com/sponsors/juniorsir](https://github.com/sponsors/juniorsir)
300
+ * **Telegram Channel / Support**: [@EveryDL_bot](https://t.me/EveryDL_bot)
301
+ * **Direct / UPI / Crypto Support**: Reach out to maintainers via Telegram ([@EveryDL_bot](https://t.me/EveryDL_bot))
302
+ * **Console Command**: Run `akash sponsor` directly from your terminal to view sponsorship details.
303
+
304
+ ---
305
+
270
306
  ## 📄 License
271
307
 
272
308
  Distributed under the MIT License. See [LICENSE](LICENSE) for details.
@@ -16,6 +16,7 @@
16
16
  [Quickstart](#-quickstart-in-60-seconds) •
17
17
  [Core Features](#-core-features) •
18
18
  [Zero-Login Guest Mode](#-zero-login-guest-mode) •
19
+ [💖 Sponsoring](#-sponsorship--restoring-storage-services) •
19
20
  [Documentation](#-in-depth-documentation-guides) •
20
21
  [Command Matrix](#-command-matrix)
21
22
 
@@ -23,6 +24,14 @@
23
24
 
24
25
  </div>
25
26
 
27
+ > [!WARNING]
28
+ > ### ⚠️ Cloud Storage & Upload Services Discontinued Due to Lack of Funding
29
+ > **Notice:** Public cloud file uploading and storage hosting services (`akash upload`, `akash cloud upload`, `akash cloud bulk`, `akash pipe`) have been **discontinued due to infrastructure hosting costs and lack of funding**.
30
+ >
31
+ > All terminal features (**remote shell relays, 1-click guest pairing, environment snapshots, local .env management, and AI MCP agent bridges**) remain **100% active and free**.
32
+ >
33
+ > 💖 **Help us bring back community storage infrastructure:** Please consider [Sponsoring the Project](#-sponsorship--restoring-storage-services) or running `akash sponsor`.
34
+
26
35
  ## 🌟 Why Akash CLI?
27
36
 
28
37
  Modern developer workflows demand flexibility across multiple machines — laptops, cloud servers, and mobile environments like Android Termux. Akash CLI solves daily pain points with a unified, secure toolkit:
@@ -156,8 +165,16 @@ akash env push prod --burn
156
165
  akash env pull eX481p prod
157
166
  ```
158
167
 
159
- ### 6. 🤖 AI Agent Gateway (MCP) & Guard Console
168
+ ### 6. AI Agent Gateway (MCP) & Guard Console
160
169
  Supercharge Cursor and Claude Desktop with local terminal execution, protected by real-time human approval:
170
+
171
+ ```
172
+ ╭─────╮
173
+ ╭──╯ ╰──╮ AKASH MCP
174
+ ( M C P ) Model Context Protocol · Claude · Cursor · Codex
175
+ ╰───────────╯
176
+ ```
177
+
161
178
  ```bash
162
179
  # 1. Create agent profile with safe role preset:
163
180
  akash agent create --name "Cursor" --role @coder
@@ -196,6 +213,7 @@ Explore comprehensive guides in the [`docs/`](docs/) directory:
196
213
 
197
214
  ```text
198
215
  akash
216
+ ├── sponsor 💖 Information on sponsoring & bringing back storage nodes
199
217
  ├── login Connect API key with hardware binding
200
218
  ├── whoami Account quota & device fingerprint
201
219
  ├── backup Save terminal environment to cloud or local archive
@@ -206,12 +224,12 @@ akash
206
224
  ├── serve Make device reachable (--daemon, --share for guest mode)
207
225
  ├── devices List, authorize, or revoke enrolled machines
208
226
  ├── cloud
209
- │ ├── upload Upload file or secret text snippet
227
+ │ ├── upload [DISCONTINUED] Upload file (run 'akash sponsor' for details)
210
228
  │ ├── files List vault files
211
229
  │ ├── stream Direct streaming link or launch in VLC
212
- │ ├── bulk Recursively upload directory
230
+ │ ├── bulk [DISCONTINUED] Recursively upload directory
213
231
  │ └── delete Purge file permanently
214
- ├── pipe Upload stdin or command output directly to cloud
232
+ ├── pipe [DISCONTINUED] Upload stdin directly to cloud
215
233
  ├── send End-to-end encrypted P2P transfer to user public key
216
234
  ├── inbox Receive and decrypt incoming P2P files
217
235
  ├── id View or export P2P identity key and manage contacts
@@ -248,6 +266,24 @@ Akash CLI enforces security at every layer:
248
266
 
249
267
  ---
250
268
 
269
+ ## 💖 Sponsorship & Restoring Storage Services
270
+
271
+ Akash CLI is an independent, community-driven open-source project. We previously provided free, high-speed public file uploading, sharing, and native media streaming. However, due to mounting NVMe cloud server expenses, bandwidth costs, and **a lack of operational funding**, public storage and uploading services had to be discontinued.
272
+
273
+ ### How Your Sponsorship Helps
274
+ Your financial contribution directly funds:
275
+ * 💽 **Dedicated NVMe Storage Nodes**: Restoring community cloud vault storage for backups and files.
276
+ * 🌐 **High-Bandwidth Network Transit**: Low-latency global relay clusters for terminal sessions and fast file retrieval.
277
+ * 🛡️ **Long-Term Open Source Maintenance**: Ongoing development for Termux, Linux, macOS, and Windows.
278
+
279
+ ### Ways to Sponsor & Donate
280
+ * **GitHub Sponsors**: [https://github.com/sponsors/juniorsir](https://github.com/sponsors/juniorsir)
281
+ * **Telegram Channel / Support**: [@EveryDL_bot](https://t.me/EveryDL_bot)
282
+ * **Direct / UPI / Crypto Support**: Reach out to maintainers via Telegram ([@EveryDL_bot](https://t.me/EveryDL_bot))
283
+ * **Console Command**: Run `akash sponsor` directly from your terminal to view sponsorship details.
284
+
285
+ ---
286
+
251
287
  ## 📄 License
252
288
 
253
289
  Distributed under the MIT License. See [LICENSE](LICENSE) for details.
@@ -2,7 +2,7 @@ try:
2
2
  from importlib.metadata import version
3
3
  __version__ = version("akashcli")
4
4
  except Exception:
5
- __version__ = "4.7.4"
5
+ __version__ = "4.8.6"
6
6
 
7
7
  AKASH_VERSION = __version__
8
8
 
@@ -423,6 +423,8 @@ def whoami():
423
423
  _err(str(e))
424
424
  raise typer.Exit(1)
425
425
 
426
+
427
+
426
428
  @app.command("url")
427
429
  @cloud_app.command("url")
428
430
  def cmd_url(
@@ -461,43 +463,59 @@ def cmd_url(
461
463
  _info("To switch URL : akash url <NEW_URL> (e.g. akash url https://jstore.2bd.net)")
462
464
  _info("To reset URL : akash url --reset")
463
465
  _p()
466
+ def _storage_discontinued_notice():
467
+ print(f"\n{_R}⚠️ [SERVICE DISCONTINUED] Cloud storage & upload services are disabled.{_RS}")
468
+ print(f" {_DM}Public cloud uploading has been discontinued due to lack of funds and hosting costs.{_RS}")
469
+ print(f" {_DM}We are actively seeking sponsors to help restore community storage infrastructure.{_RS}\n")
470
+ print(f" {_C}💖 Sponsoring the project:{_RS}")
471
+ print(f" Run {_YE}akash sponsor{_RS} or visit {_CY}https://github.com/juniorsir/akashcli#sponsorship{_RS}\n")
472
+ raise typer.Exit(1)
473
+
474
+
475
+ @app.command("sponsor")
476
+ def cmd_sponsor():
477
+ """Information on sponsoring Akash CLI to restore storage services."""
478
+ print(f"\n{_C}╔═══════════════════════════════════════════════════════════════╗{_RS}")
479
+ print(f"{_C}║ 💖 SPONSOR AKASH CLI INFRASTRUCTURE ║{_RS}")
480
+ print(f"{_C}╚═══════════════════════════════════════════════════════════════╝{_RS}\n")
481
+ print(f" {_B}Status Update:{_RS}")
482
+ print(f" Public cloud storage and file uploading services have been")
483
+ print(f" discontinued due to infrastructure costs and lack of funding.\n")
484
+ print(f" {_B}Why We Need Sponsors:{_RS}")
485
+ print(f" • High-performance NVMe storage nodes for community vaulting")
486
+ print(f" • Global high-bandwidth relays for low-latency PTY terminals")
487
+ print(f" • Free open-source developer tooling & automated backups\n")
488
+ print(f" {_B}How You Can Sponsor & Help:{_RS}")
489
+ print(f" • GitHub Sponsors : {_YE}https://github.com/sponsors/juniorsir{_RS}")
490
+ print(f" • Telegram Channel: {_YE}https://t.me/EveryDL_bot{_RS}")
491
+ print(f" • Direct / UPI : Contact via Telegram (@EveryDL_bot)\n")
492
+ print(f" {_DM}Every contribution helps bring back community storage services!{_RS}\n")
493
+
494
+
464
495
  @cloud_app.command("upload")
465
496
  def cloud_upload(
466
- path: Optional[Path] = typer.Argument(None, help="File to upload"),
467
- text: Optional[str] = typer.Option(None, "--text", "-t", help="Upload raw text"),
497
+ path: Optional[Path] = typer.Argument(None, help="File to upload (DISCONTINUED)"),
498
+ text: Optional[str] = typer.Option(None, "--text", "-t", help="Upload raw text (DISCONTINUED)"),
468
499
  name: Optional[str] = typer.Option(None, "--name", "-n", help="Custom filename"),
469
500
  burn: bool = typer.Option(False, "--burn", help="Delete after first download"),
470
501
  expiry: int = typer.Option(0, "--expiry","-e",help="Expire in N days (0 = never)"),
471
502
  password: Optional[str] = typer.Option(None, "--pass", "-p", help="Password-protect"),
472
503
  ):
473
- """Upload a file or text snippet."""
474
- try:
475
- client = AkashClient()
504
+ """[DISCONTINUED] Upload a file or text snippet (Service retired due to lack of funds)."""
505
+ _storage_discontinued_notice()
476
506
 
477
- def _cb(done, total):
478
- bar = _progress_bar(done, total)
479
- sys.stdout.write(f"\r {_C}↑{_RS} {bar} ")
480
- sys.stdout.flush()
481
507
 
482
- if text:
483
- res = client.upload_text(text, filename=name, burn=burn, expiry=expiry, password=password)
484
- else:
485
- if not path:
486
- _err("provide a file path or use --text")
487
- raise typer.Exit(1)
488
- res = client.upload_file(str(path), burn=burn, expiry=expiry, password=password, progress_callback=_cb)
489
-
490
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
491
- sys.stdout.flush()
492
- label = "done" if res.status == "done" else "processing"
493
- _ok(f"{label} code={_ye(res.file_code)}")
494
- _info(f"link {res.embed_url}")
495
- except typer.Exit:
496
- raise
497
- except Exception as e:
498
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
499
- _err(f"upload failed: {e}")
500
- raise typer.Exit(1)
508
+ @app.command("upload")
509
+ def app_upload(
510
+ path: Optional[Path] = typer.Argument(None, help="File to upload (DISCONTINUED)"),
511
+ text: Optional[str] = typer.Option(None, "--text", "-t", help="Upload raw text (DISCONTINUED)"),
512
+ name: Optional[str] = typer.Option(None, "--name", "-n", help="Custom filename"),
513
+ burn: bool = typer.Option(False, "--burn", help="Delete after first download"),
514
+ expiry: int = typer.Option(0, "--expiry","-e",help="Expire in N days (0 = never)"),
515
+ password: Optional[str] = typer.Option(None, "--pass", "-p", help="Password-protect"),
516
+ ):
517
+ """[DISCONTINUED] Upload a file or text snippet (Service retired due to lack of funds)."""
518
+ _storage_discontinued_notice()
501
519
 
502
520
 
503
521
  # ── akash cloud files ─────────────────────────────────────────────────────────
@@ -603,22 +621,8 @@ def cloud_manage(
603
621
 
604
622
  @cloud_app.command("bulk")
605
623
  def cloud_bulk(path: Path):
606
- """Recursively upload every file in a folder."""
607
- try:
608
- client = AkashClient()
609
- uploader = VaultUploader(client)
610
- all_files = [p for p in path.glob("**/*") if p.is_file() and not p.name.startswith(".")]
611
- for i, file in enumerate(all_files, 1):
612
- sys.stdout.write(f"\r {_C}↑{_RS} [{i}/{len(all_files)}] {_DM}{file.name}{_RS} ")
613
- sys.stdout.flush()
614
- uploader.upload(file_path=str(file))
615
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
616
- sys.stdout.flush()
617
- _ok(f"uploaded {len(all_files)} files")
618
- except Exception as e:
619
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
620
- _err(str(e))
621
- raise typer.Exit(1)
624
+ """[DISCONTINUED] Recursively upload every file in a folder."""
625
+ _storage_discontinued_notice()
622
626
 
623
627
 
624
628
  # ── Helpers for backup/restore output ────────────────────────────────────────
@@ -2008,8 +2012,14 @@ def send(
2008
2012
  _ok(f"encrypted {_dim(f'{size_kb:.1f} KB → {enc_kb:.1f} KB')}")
2009
2013
 
2010
2014
  # ── 4. Upload envelope ────────────────────────────────────────────────────
2015
+ api_key, base = _resolve_client(require_key=False, silent=True)
2016
+ if not api_key:
2017
+ _err("Not logged in. You must be logged in to send files.")
2018
+ print(f" {_DM}Run {_C}akash login{_RS}{_DM} to log in, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
2019
+ raise typer.Exit(1)
2020
+
2011
2021
  try:
2012
- client = AkashClient()
2022
+ client = AkashClient(api_key=api_key, api_url=base)
2013
2023
  except Exception as e:
2014
2024
  _err(f"not logged in: {e}")
2015
2025
  raise typer.Exit(1)
@@ -2086,8 +2096,14 @@ def inbox(
2086
2096
  _err(f"failed to load identity: {e}")
2087
2097
  raise typer.Exit(1)
2088
2098
 
2099
+ api_key, base = _resolve_client(require_key=False, silent=True)
2100
+ if not api_key:
2101
+ _err("Not logged in. You must be logged in to view your inbox.")
2102
+ print(f" {_DM}Run {_C}akash login{_RS}{_DM} to log in, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
2103
+ raise typer.Exit(1)
2104
+
2089
2105
  try:
2090
- client = AkashClient()
2106
+ client = AkashClient(api_key=api_key, api_url=base)
2091
2107
  except Exception as e:
2092
2108
  _err(f"not logged in: {e}")
2093
2109
  raise typer.Exit(1)
@@ -2246,93 +2262,15 @@ def _decrypt_one(code: str, ident: dict, client, out: Optional[Path],
2246
2262
  # ── akash pipe ────────────────────────────────────────────────────────────────
2247
2263
 
2248
2264
  @app.command()
2249
- @cloud_app.command("pipe", help="Upload stdin or a command's output")
2265
+ @cloud_app.command("pipe", help="[DISCONTINUED] Upload stdin or a command's output")
2250
2266
  def pipe(
2251
2267
  name: Optional[str] = typer.Option(None, "--name", "-n", help="Filename for the cloud snippet"),
2252
2268
  burn: bool = typer.Option(False, "--burn", help="Delete after first download"),
2253
2269
  expiry: int = typer.Option(0, "--expiry","-e", help="Expire in N days (0 = never)"),
2254
2270
  command: Optional[str] = typer.Option(None, "--run", "-c", help="Run a command and pipe its output"),
2255
2271
  ):
2256
- """Pipe stdin (or a command's output) to the cloud.
2257
-
2258
- Examples:
2259
- echo "hello" | akash pipe
2260
- cat debug.log | akash pipe --name debug.log
2261
- akash pipe --run "df -h" --name disk-report.txt
2262
- git log --oneline | akash pipe --burn --name git-log.txt
2263
- """
2264
- from .logger import log_op
2265
- import io
2266
-
2267
- try:
2268
- client = AkashClient()
2269
- except Exception as e:
2270
- _err(f"not logged in: {e}")
2271
- raise typer.Exit(1)
2272
-
2273
- # ── Gather bytes ──────────────────────────────────────────────────────────
2274
- if command:
2275
- import subprocess as _sp
2276
- _info(f"running: {command}")
2277
- try:
2278
- result = _sp.run(command, shell=True, capture_output=True)
2279
- data = result.stdout + result.stderr
2280
- except Exception as e:
2281
- _err(f"command failed: {e}")
2282
- raise typer.Exit(1)
2283
- else:
2284
- import sys as _sys
2285
- if _sys.stdin.isatty():
2286
- _err("nothing to pipe - use --run or pipe stdin: echo 'hello' | akash pipe")
2287
- raise typer.Exit(1)
2288
- data = _sys.stdin.buffer.read()
2289
-
2290
- if not data:
2291
- _err("empty input - nothing to upload")
2292
- raise typer.Exit(1)
2293
-
2294
- size_kb = len(data) / 1024
2295
- filename = name or f"pipe_{__import__('time').strftime('%Y%m%d_%H%M%S')}.txt"
2296
-
2297
- # ── Upload ────────────────────────────────────────────────────────────────
2298
- import tempfile as _tf
2299
- with _tf.NamedTemporaryFile(suffix=".txt", prefix="akash_pipe_", delete=False) as tmp:
2300
- tmp.write(data)
2301
- tmp_path = tmp.name
2302
-
2303
- try:
2304
- def _cb(done, total):
2305
- bar = _progress_bar(done, total)
2306
- sys.stdout.write(f"\r {_C}↑{_RS} {bar} ")
2307
- sys.stdout.flush()
2308
-
2309
- # rename the tmp file so the server picks up the right name
2310
- import os as _os
2311
- named_path = _os.path.join(_os.path.dirname(tmp_path), filename)
2312
- _os.rename(tmp_path, named_path)
2313
-
2314
- result = client.upload_file(named_path, burn=burn, expiry=expiry, progress_callback=_cb)
2315
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
2316
- except Exception as e:
2317
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
2318
- _err(f"upload failed: {e}")
2319
- log_op("pipe", ok=False, error=str(e))
2320
- raise typer.Exit(1)
2321
- finally:
2322
- try:
2323
- import os as _os2
2324
- _os2.unlink(named_path)
2325
- except Exception:
2326
- pass
2327
-
2328
- log_op("pipe", ok=True, code=result.file_code, filename=filename, size=len(data))
2329
- _p()
2330
- _ok(f"uploaded {_cy(filename)} {_dim(f'{size_kb:.1f} KB')}")
2331
- _info(f"code {_ye(result.file_code)}")
2332
- _info(f"link {result.embed_url}")
2333
- if burn:
2334
- _info("burns after first download")
2335
- _p()
2272
+ """[DISCONTINUED] Pipe stdin (or a command's output) to the cloud."""
2273
+ _storage_discontinued_notice()
2336
2274
 
2337
2275
 
2338
2276
  # ── akash log (+ --stats) ─────────────────────────────────────────────────────
@@ -2644,8 +2582,14 @@ def env_push(
2644
2582
  from .logger import log_op
2645
2583
  import tempfile as _tf
2646
2584
 
2585
+ api_key, base = _resolve_client(require_key=False, silent=True)
2586
+ if not api_key:
2587
+ _err("Not logged in. You must be logged in to push environment variables.")
2588
+ print(f" {_DM}Run {_C}akash login{_RS}{_DM} to log in, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
2589
+ raise typer.Exit(1)
2590
+
2647
2591
  try:
2648
- client = AkashClient()
2592
+ client = AkashClient(api_key=api_key, api_url=base)
2649
2593
  except Exception as e:
2650
2594
  _err(f"not logged in: {e}")
2651
2595
  raise typer.Exit(1)
@@ -2708,8 +2652,14 @@ def env_pull(
2708
2652
  from .env_manager import env_save_blob
2709
2653
  from .logger import log_op
2710
2654
 
2655
+ api_key, base = _resolve_client(require_key=False, silent=True)
2656
+ if not api_key:
2657
+ _err("Not logged in. You must be logged in to pull environment variables.")
2658
+ print(f" {_DM}Run {_C}akash login{_RS}{_DM} to log in, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
2659
+ raise typer.Exit(1)
2660
+
2711
2661
  try:
2712
- client = AkashClient()
2662
+ client = AkashClient(api_key=api_key, api_url=base)
2713
2663
  except Exception as e:
2714
2664
  _err(f"not logged in: {e}")
2715
2665
  raise typer.Exit(1)
@@ -2773,6 +2723,43 @@ def _render_inspection_card(r: dict) -> None:
2773
2723
  print(f" {_C}╰────────────────────────────────────────────────────────────────────{_RS}")
2774
2724
 
2775
2725
 
2726
+ def _print_mcp_cloud_logo(title: str = "Akash MCP", subtitle: str = "Model Context Protocol · Claude · Cursor · Codex"):
2727
+ """Renders the clean cloud icon logo for Akash MCP commands."""
2728
+ C, W, DM, RS = _C, _W, _DM, _RS
2729
+ print(f" {C} ╭─────╮{RS}")
2730
+ print(f" {C} ╭──╯ ╰──╮{RS} {W}{title}{RS}")
2731
+ print(f" {C} ( M C P ){RS} {DM}{subtitle}{RS}")
2732
+ print(f" {C} ╰───────────╯{RS}")
2733
+
2734
+
2735
+ def _print_cmd_tree_output(raw_out: str, max_lines: int = 5, indent: str = " "):
2736
+ """Prints tool/command output in gray with tree-based branching (├─, └─)."""
2737
+ if not raw_out or not str(raw_out).strip():
2738
+ print(f"{indent}{_GR}└─{_RS} {_GR}{_DM}(no output){_RS}")
2739
+ return
2740
+
2741
+ clean_text = re.sub(r"\x1b\[[0-9;]*[a-zA-Z]", "", str(raw_out))
2742
+ lines = [ln.strip() for ln in clean_text.splitlines() if ln.strip()]
2743
+
2744
+ if not lines:
2745
+ print(f"{indent}{_GR}└─{_RS} {_GR}{_DM}(no output){_RS}")
2746
+ return
2747
+
2748
+ show_lines = lines[:max_lines]
2749
+ has_more = len(lines) > max_lines
2750
+
2751
+ for i, line in enumerate(show_lines):
2752
+ if len(line) > 85:
2753
+ line = line[:82] + "…"
2754
+ is_last = (i == len(show_lines) - 1) and not has_more
2755
+ branch = "└─" if is_last else "├─"
2756
+ print(f"{indent}{_GR}{branch}{_RS} {_GR}{_DM}{line}{_RS}")
2757
+
2758
+ if has_more:
2759
+ more_count = len(lines) - max_lines
2760
+ print(f"{indent}{_GR}└─{_RS} {_GR}{_DM}… ({more_count} more lines){_RS}")
2761
+
2762
+
2776
2763
  @agent_app.command("list")
2777
2764
  @agent_app.command("ls", hidden=True)
2778
2765
  @agent_app.command("ids", hidden=True)
@@ -2808,7 +2795,7 @@ def agent_list(raw: bool = typer.Option(False, "--json", help="Raw JSON output")
2808
2795
  default_pid = next(reversed(list(agents.keys())))
2809
2796
 
2810
2797
  _p()
2811
- print(f" {_C}◈{_RS} {_W}Akash MCP Profiles & Agent IDs{_RS} {_dim(f'({len(agents)} configured)')}")
2798
+ _print_mcp_cloud_logo("Akash MCP Profiles & Agent IDs", f"{len(agents)} configured · Claude · Cursor · Codex")
2812
2799
  print(f" {_GR}{'─'*76}{_RS}")
2813
2800
 
2814
2801
  hdr_status = f"{'STATUS':<11}"
@@ -3345,7 +3332,8 @@ def agent_create(
3345
3332
  gemini_mcp_url = f"{base}/mcp"
3346
3333
 
3347
3334
  _p()
3348
- _ok(f"Agent Credentials Issued & Saved Locally: {_cy(name)}")
3335
+ _print_mcp_cloud_logo("Akash MCP Profile Created", f"Credentials Issued for {_cy(name)}")
3336
+ print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
3349
3337
  print(f" {_DM}Profile ID :{_RS} {_C}{profile_id}{_RS}")
3350
3338
  print(f" {_DM}Client ID :{_RS} {_ye(cid)}")
3351
3339
  print(f" {_DM}Client Secret :{_RS} {_W}{csec}{_RS}")
@@ -3827,7 +3815,7 @@ def mcp_serve(
3827
3815
  worker_ws_url = f"{ws_base}/api/agent/mcp/worker?client_id={cid}&client_secret={csec}&device_fp={dev_fp}"
3828
3816
 
3829
3817
  _p()
3830
- print(" " + _C + "◈" + _RS + " " + _W + "Akash MCP Worker · Online" + _RS)
3818
+ _print_mcp_cloud_logo("Akash MCP Worker · Online", "Model Context Protocol Execution Host")
3831
3819
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
3832
3820
  print(" " + _DM + "Workspace : " + _RS + _cy(str(Path.cwd())))
3833
3821
  print(" " + _DM + "Gateway : " + _RS + _dim(base))
@@ -3914,7 +3902,8 @@ def mcp_serve(
3914
3902
 
3915
3903
  is_safe, sec_reason = _sanitize_agent_command(cmd, scopes=cached.get("scopes", "*"))
3916
3904
  if not is_safe:
3917
- print(f"{ts_pfx} {_R}🚨 Blocked{_RS} -> {disp_cmd} {_dim('(' + sec_reason + ')')}")
3905
+ print(f"{ts_pfx} {_R}✗ Blocked:{_RS} {disp_cmd}")
3906
+ _print_cmd_tree_output(f"Security Policy Block: {sec_reason}")
3918
3907
  ws.send(json.dumps({
3919
3908
  "type": "tool_response",
3920
3909
  "id": call_id,
@@ -3980,6 +3969,7 @@ def mcp_serve(
3980
3969
  ec_color = _G if returncode == 0 else _R
3981
3970
  ec_icon = f"{_G}✓{_RS}" if returncode == 0 else f"{_R}✗{_RS}"
3982
3971
  print(f"{ts_pfx} {ec_icon} {ec_color}exec:{_RS} {disp_cmd} {ec_color}[{returncode}]{_RS} {_dim(f'{elapsed_ms:.1f}ms')}")
3972
+ _print_cmd_tree_output(raw_out)
3983
3973
 
3984
3974
  if returncode != 0:
3985
3975
  res_content = bounded_out or f"Command exited with status code {returncode} (no output)"
@@ -3998,6 +3988,7 @@ def mcp_serve(
3998
3988
  ok, msg_txt = _restore_undo_checkpoint()
3999
3989
  icon = f"{_G}✓{_RS}" if ok else f"{_R}✗{_RS}"
4000
3990
  print(f"{ts_pfx} {icon} {(_G if ok else _R)}undo:{_RS} {_dim(msg_txt)}")
3991
+ _print_cmd_tree_output(msg_txt, max_lines=1)
4001
3992
  ws.send(json.dumps({
4002
3993
  "type": "tool_response",
4003
3994
  "id": call_id,
@@ -4010,7 +4001,8 @@ def mcp_serve(
4010
4001
  with _Spin(f"checkpoint: {label} (packing workspace)", min_seconds=0.25, prefix=ts_pfx):
4011
4002
  _, manifest, _ = build_snapshot(label=label)
4012
4003
  elapsed_ms = (time.monotonic() - t0) * 1000
4013
- print(f"{ts_pfx} {_C}📸 checkpoint:{_RS} {_dim(label)} ({len(manifest.get('files', []))} files) {_dim(f'{elapsed_ms:.1f}ms')}")
4004
+ print(f"{ts_pfx} {_C}● checkpoint:{_RS} {_dim(label)} ({len(manifest.get('files', []))} files) {_dim(f'{elapsed_ms:.1f}ms')}")
4005
+ _print_cmd_tree_output(f"Checkpoint '{label}' created ({len(manifest.get('files', []))} files tracked)", max_lines=1)
4014
4006
  ws.send(json.dumps({
4015
4007
  "type": "tool_response",
4016
4008
  "id": call_id,
@@ -4026,6 +4018,12 @@ def mcp_serve(
4026
4018
  elapsed_ms = (time.monotonic() - t0) * 1000
4027
4019
  icon = f"{_G}✓{_RS}" if not is_err else f"{_R}✗{_RS}"
4028
4020
  print(f"{ts_pfx} {icon} {(_G if not is_err else _R)}read:{_RS} {disp_f} {_dim(f'{elapsed_ms:.1f}ms')}")
4021
+ if is_err:
4022
+ _print_cmd_tree_output(res_text, max_lines=2)
4023
+ else:
4024
+ char_count = len(res_text)
4025
+ line_count = len(res_text.splitlines())
4026
+ _print_cmd_tree_output(f"{char_count} bytes, {line_count} lines", max_lines=1)
4029
4027
  ws.send(json.dumps({
4030
4028
  "type": "tool_response",
4031
4029
  "id": call_id,
@@ -4042,6 +4040,7 @@ def mcp_serve(
4042
4040
  elapsed_ms = (time.monotonic() - t0) * 1000
4043
4041
  icon = f"{_G}✓{_RS}" if not is_err else f"{_R}✗{_RS}"
4044
4042
  print(f"{ts_pfx} {icon} {(_G if not is_err else _R)}write:{_RS} {disp_f} {_dim(f'{elapsed_ms:.1f}ms')}")
4043
+ _print_cmd_tree_output(res_text, max_lines=2)
4045
4044
  ws.send(json.dumps({
4046
4045
  "type": "tool_response",
4047
4046
  "id": call_id,
@@ -4057,6 +4056,7 @@ def mcp_serve(
4057
4056
  elapsed_ms = (time.monotonic() - t0) * 1000
4058
4057
  icon = f"{_G}✓{_RS}" if not is_err else f"{_R}✗{_RS}"
4059
4058
  print(f"{ts_pfx} {icon} {(_G if not is_err else _R)}list:{_RS} {disp_d} {_dim(f'{elapsed_ms:.1f}ms')}")
4059
+ _print_cmd_tree_output(res_text, max_lines=3)
4060
4060
  ws.send(json.dumps({
4061
4061
  "type": "tool_response",
4062
4062
  "id": call_id,
@@ -4067,7 +4067,8 @@ def mcp_serve(
4067
4067
  with _Spin("inspecting scopes…", min_seconds=0.15, prefix=ts_pfx):
4068
4068
  res_text, is_err = _handle_tool_scope_details(cached.get("scopes", "*"), pname, profile_id)
4069
4069
  elapsed_ms = (time.monotonic() - t0) * 1000
4070
- print(f"{ts_pfx} {_C}🔒 scopes:{_RS} {_dim(pname)} {_dim(f'{elapsed_ms:.1f}ms')}")
4070
+ print(f"{ts_pfx} {_C}● scopes:{_RS} {_dim(pname)} {_dim(f'{elapsed_ms:.1f}ms')}")
4071
+ _print_cmd_tree_output(cached.get("scopes", "*") or "@coder", max_lines=2)
4071
4072
  ws.send(json.dumps({
4072
4073
  "type": "tool_response",
4073
4074
  "id": call_id,
@@ -4237,7 +4238,7 @@ def mcp_share(
4237
4238
  mode_label = "Permanent Small & Secure"
4238
4239
 
4239
4240
  _p()
4240
- print(" " + _C + "◈" + _RS + " " + _W + "Akash MCP · Quick Connect" + _RS)
4241
+ _print_mcp_cloud_logo("Akash MCP · Quick Connect", "AI Assistant Setup (Cursor, Claude Desktop, Gemini)")
4241
4242
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
4242
4243
  print(" " + _DM + "Agent : " + _RS + _ye(name) + " " + _dim("(" + pid + ")"))
4243
4244
  print(" " + _DM + "Mode : " + _RS + _C + mode_label + _RS)
@@ -4272,10 +4273,11 @@ def mcp_share(
4272
4273
  _p()
4273
4274
 
4274
4275
  if show_all or claude:
4275
- print(" " + _C + "For Claude Desktop / Cursor" + _RS + " " + _dim("(config.json)") + ":")
4276
+ print(" " + _C + "For Claude Desktop, Cursor & Cline" + _RS + " " + _dim("(config.json / settings.json)") + ":")
4276
4277
  claude_cfg = json.dumps({"mcpServers": {"akash": {"url": local_url}}}, indent=2)
4277
4278
  for c_line in claude_cfg.splitlines():
4278
4279
  print(" " + c_line)
4280
+ print(" " + _DM + " Logo / Icon: Clean Cloud Icon delivered automatically via MCP handshake" + _RS)
4279
4281
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
4280
4282
  _p()
4281
4283
 
@@ -4306,7 +4308,7 @@ def mcp_status(
4306
4308
  _, base = _resolve_client(url or profile.get("url"), require_key=False, silent=True)
4307
4309
 
4308
4310
  _p()
4309
- print(" " + _C + "◈" + _RS + " " + _W + "Akash MCP · Health Check" + _RS)
4311
+ _print_mcp_cloud_logo("Akash MCP · Health Check", "Gateway & Tools Verification")
4310
4312
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
4311
4313
 
4312
4314
  try:
@@ -20,7 +20,7 @@ class AkashClient:
20
20
  _patch_dns(_up(self.base_url).hostname or "")
21
21
 
22
22
  if not self.api_key:
23
- raise AuthenticationError("No API Key found. Run 'akash login' or set AKASH_API_KEY env var.")
23
+ raise AuthenticationError("User is not logged in. An API key is required. Run 'akash login' or set AKASH_API_KEY env var.")
24
24
 
25
25
  def _get_headers(self, custom: dict = None):
26
26
  h = {"x-api-key": self.api_key, "Origin": "https://akash.cli"}
@@ -379,6 +379,10 @@ def upload_large_file(
379
379
  progress_cb: Optional[Callable[[int, int], None]] = None,
380
380
  ) -> dict:
381
381
  from .uploader import VaultUploader
382
+ from .exceptions import AuthenticationError
383
+
384
+ if not getattr(client, "api_key", None):
385
+ raise AuthenticationError("User is not logged in. An API key is required to upload files. Run 'akash login'.")
382
386
 
383
387
  size = path.stat().st_size
384
388
  digest = sha256_file(path)
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  from typing import Optional, Callable, List
7
7
  from concurrent.futures import ThreadPoolExecutor
8
8
  from .models import UploadResult
9
- from .exceptions import UploadFailed, QuotaExceeded
9
+ from .exceptions import UploadFailed, QuotaExceeded, AuthenticationError
10
10
 
11
11
  class VaultUploader:
12
12
  def __init__(self, client):
@@ -26,6 +26,11 @@ class VaultUploader:
26
26
  Standardizes both File and Text uploads into a single stream.
27
27
  progress_callback signature: (bytes_read, total_bytes)
28
28
  """
29
+ raise UploadFailed(
30
+ "Cloud storage & upload services have been discontinued due to lack of funding. "
31
+ "Please consider sponsoring the project to help bring back storage nodes: "
32
+ "https://github.com/juniorsir/akashcli#sponsorship"
33
+ )
29
34
 
30
35
  # 1. Prepare Headers based on V3 Power-Control Specs
31
36
  headers = {
@@ -220,6 +225,11 @@ class VaultUploader:
220
225
 
221
226
  def upload_directory(self, folder_path: str, max_workers: int = 3) -> List[UploadResult]:
222
227
  """Recursively uploads all files in a folder using a thread pool."""
228
+ raise UploadFailed(
229
+ "Cloud storage & upload services have been discontinued due to lack of funding. "
230
+ "Please consider sponsoring the project to help bring back storage nodes: "
231
+ "https://github.com/juniorsir/akashcli#sponsorship"
232
+ )
223
233
  # Convert string path to Path object
224
234
  root = Path(folder_path)
225
235
  if not root.is_dir():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akashcli
3
- Version: 4.8.4
3
+ Version: 4.8.6
4
4
  Summary: Akash CLI — secure remote shell relay, file vault, and device management
5
5
  License-Expression: MIT
6
6
  Keywords: akash,cli,relay,remote-shell,vault
@@ -35,6 +35,7 @@ Requires-Dist: websockets
35
35
  [Quickstart](#-quickstart-in-60-seconds) •
36
36
  [Core Features](#-core-features) •
37
37
  [Zero-Login Guest Mode](#-zero-login-guest-mode) •
38
+ [💖 Sponsoring](#-sponsorship--restoring-storage-services) •
38
39
  [Documentation](#-in-depth-documentation-guides) •
39
40
  [Command Matrix](#-command-matrix)
40
41
 
@@ -42,6 +43,14 @@ Requires-Dist: websockets
42
43
 
43
44
  </div>
44
45
 
46
+ > [!WARNING]
47
+ > ### ⚠️ Cloud Storage & Upload Services Discontinued Due to Lack of Funding
48
+ > **Notice:** Public cloud file uploading and storage hosting services (`akash upload`, `akash cloud upload`, `akash cloud bulk`, `akash pipe`) have been **discontinued due to infrastructure hosting costs and lack of funding**.
49
+ >
50
+ > All terminal features (**remote shell relays, 1-click guest pairing, environment snapshots, local .env management, and AI MCP agent bridges**) remain **100% active and free**.
51
+ >
52
+ > 💖 **Help us bring back community storage infrastructure:** Please consider [Sponsoring the Project](#-sponsorship--restoring-storage-services) or running `akash sponsor`.
53
+
45
54
  ## 🌟 Why Akash CLI?
46
55
 
47
56
  Modern developer workflows demand flexibility across multiple machines — laptops, cloud servers, and mobile environments like Android Termux. Akash CLI solves daily pain points with a unified, secure toolkit:
@@ -175,8 +184,16 @@ akash env push prod --burn
175
184
  akash env pull eX481p prod
176
185
  ```
177
186
 
178
- ### 6. 🤖 AI Agent Gateway (MCP) & Guard Console
187
+ ### 6. AI Agent Gateway (MCP) & Guard Console
179
188
  Supercharge Cursor and Claude Desktop with local terminal execution, protected by real-time human approval:
189
+
190
+ ```
191
+ ╭─────╮
192
+ ╭──╯ ╰──╮ AKASH MCP
193
+ ( M C P ) Model Context Protocol · Claude · Cursor · Codex
194
+ ╰───────────╯
195
+ ```
196
+
180
197
  ```bash
181
198
  # 1. Create agent profile with safe role preset:
182
199
  akash agent create --name "Cursor" --role @coder
@@ -215,6 +232,7 @@ Explore comprehensive guides in the [`docs/`](docs/) directory:
215
232
 
216
233
  ```text
217
234
  akash
235
+ ├── sponsor 💖 Information on sponsoring & bringing back storage nodes
218
236
  ├── login Connect API key with hardware binding
219
237
  ├── whoami Account quota & device fingerprint
220
238
  ├── backup Save terminal environment to cloud or local archive
@@ -225,12 +243,12 @@ akash
225
243
  ├── serve Make device reachable (--daemon, --share for guest mode)
226
244
  ├── devices List, authorize, or revoke enrolled machines
227
245
  ├── cloud
228
- │ ├── upload Upload file or secret text snippet
246
+ │ ├── upload [DISCONTINUED] Upload file (run 'akash sponsor' for details)
229
247
  │ ├── files List vault files
230
248
  │ ├── stream Direct streaming link or launch in VLC
231
- │ ├── bulk Recursively upload directory
249
+ │ ├── bulk [DISCONTINUED] Recursively upload directory
232
250
  │ └── delete Purge file permanently
233
- ├── pipe Upload stdin or command output directly to cloud
251
+ ├── pipe [DISCONTINUED] Upload stdin directly to cloud
234
252
  ├── send End-to-end encrypted P2P transfer to user public key
235
253
  ├── inbox Receive and decrypt incoming P2P files
236
254
  ├── id View or export P2P identity key and manage contacts
@@ -267,6 +285,24 @@ Akash CLI enforces security at every layer:
267
285
 
268
286
  ---
269
287
 
288
+ ## 💖 Sponsorship & Restoring Storage Services
289
+
290
+ Akash CLI is an independent, community-driven open-source project. We previously provided free, high-speed public file uploading, sharing, and native media streaming. However, due to mounting NVMe cloud server expenses, bandwidth costs, and **a lack of operational funding**, public storage and uploading services had to be discontinued.
291
+
292
+ ### How Your Sponsorship Helps
293
+ Your financial contribution directly funds:
294
+ * 💽 **Dedicated NVMe Storage Nodes**: Restoring community cloud vault storage for backups and files.
295
+ * 🌐 **High-Bandwidth Network Transit**: Low-latency global relay clusters for terminal sessions and fast file retrieval.
296
+ * 🛡️ **Long-Term Open Source Maintenance**: Ongoing development for Termux, Linux, macOS, and Windows.
297
+
298
+ ### Ways to Sponsor & Donate
299
+ * **GitHub Sponsors**: [https://github.com/sponsors/juniorsir](https://github.com/sponsors/juniorsir)
300
+ * **Telegram Channel / Support**: [@EveryDL_bot](https://t.me/EveryDL_bot)
301
+ * **Direct / UPI / Crypto Support**: Reach out to maintainers via Telegram ([@EveryDL_bot](https://t.me/EveryDL_bot))
302
+ * **Console Command**: Run `akash sponsor` directly from your terminal to view sponsorship details.
303
+
304
+ ---
305
+
270
306
  ## 📄 License
271
307
 
272
308
  Distributed under the MIT License. See [LICENSE](LICENSE) for details.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "akashcli"
3
- version = "4.8.4"
3
+ version = "4.8.6"
4
4
  description = "Akash CLI — secure remote shell relay, file vault, and device management"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes