akashcli 4.8.5__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.5 → akashcli-4.8.6}/PKG-INFO +41 -5
  2. {akashcli-4.8.5 → akashcli-4.8.6}/README.md +40 -4
  3. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/__init__.py +1 -1
  4. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/cli.py +105 -158
  5. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/uploader.py +10 -4
  6. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli.egg-info/PKG-INFO +41 -5
  7. {akashcli-4.8.5 → akashcli-4.8.6}/pyproject.toml +1 -1
  8. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/_net.py +0 -0
  9. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/auth.py +0 -0
  10. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/client.py +0 -0
  11. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/config.py +0 -0
  12. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/crypto.py +0 -0
  13. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/env_manager.py +0 -0
  14. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/exceptions.py +0 -0
  15. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/exec.py +0 -0
  16. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/integrity.py +0 -0
  17. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/logger.py +0 -0
  18. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/models.py +0 -0
  19. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/p2p.py +0 -0
  20. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/packages.py +0 -0
  21. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/relay.py +0 -0
  22. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/restore.py +0 -0
  23. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/snapshot_crypto.py +0 -0
  24. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/storage.py +0 -0
  25. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/terminal.py +0 -0
  26. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/updater.py +0 -0
  27. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli/utils.py +0 -0
  28. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli.egg-info/SOURCES.txt +0 -0
  29. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli.egg-info/dependency_links.txt +0 -0
  30. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli.egg-info/entry_points.txt +0 -0
  31. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli.egg-info/requires.txt +0 -0
  32. {akashcli-4.8.5 → akashcli-4.8.6}/akashcli.egg-info/top_level.txt +0 -0
  33. {akashcli-4.8.5 → 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.5
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.8.5"
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,62 +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
- api_key, base = _resolve_client(require_key=False, silent=True)
475
- if not api_key:
476
- _err("Not logged in. You must be logged in to upload files.")
477
- print(f" {_DM}Run {_C}akash login{_RS}{_DM} to log in, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
478
- raise typer.Exit(1)
479
-
480
- try:
481
- client = AkashClient(api_key=api_key, api_url=base)
482
-
483
- def _cb(done, total):
484
- bar = _progress_bar(done, total)
485
- sys.stdout.write(f"\r {_C}↑{_RS} {bar} ")
486
- sys.stdout.flush()
487
-
488
- if text:
489
- res = client.upload_text(text, filename=name, burn=burn, expiry=expiry, password=password)
490
- else:
491
- if not path:
492
- _err("provide a file path or use --text")
493
- raise typer.Exit(1)
494
- res = client.upload_file(str(path), burn=burn, expiry=expiry, password=password, progress_callback=_cb)
495
-
496
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
497
- sys.stdout.flush()
498
- label = "done" if res.status == "done" else "processing"
499
- _ok(f"{label} code={_ye(res.file_code)}")
500
- _info(f"link {res.embed_url}")
501
- except typer.Exit:
502
- raise
503
- except Exception as e:
504
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
505
- _err(f"upload failed: {e}")
506
- raise typer.Exit(1)
504
+ """[DISCONTINUED] Upload a file or text snippet (Service retired due to lack of funds)."""
505
+ _storage_discontinued_notice()
507
506
 
508
507
 
509
508
  @app.command("upload")
510
509
  def app_upload(
511
- path: Optional[Path] = typer.Argument(None, help="File to upload"),
512
- text: Optional[str] = typer.Option(None, "--text", "-t", help="Upload raw text"),
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)"),
513
512
  name: Optional[str] = typer.Option(None, "--name", "-n", help="Custom filename"),
514
513
  burn: bool = typer.Option(False, "--burn", help="Delete after first download"),
515
514
  expiry: int = typer.Option(0, "--expiry","-e",help="Expire in N days (0 = never)"),
516
515
  password: Optional[str] = typer.Option(None, "--pass", "-p", help="Password-protect"),
517
516
  ):
518
- """Upload a file or text snippet (requires login)."""
519
- return cloud_upload(path=path, text=text, name=name, burn=burn, expiry=expiry, password=password)
517
+ """[DISCONTINUED] Upload a file or text snippet (Service retired due to lack of funds)."""
518
+ _storage_discontinued_notice()
520
519
 
521
520
 
522
521
  # ── akash cloud files ─────────────────────────────────────────────────────────
@@ -622,28 +621,8 @@ def cloud_manage(
622
621
 
623
622
  @cloud_app.command("bulk")
624
623
  def cloud_bulk(path: Path):
625
- """Recursively upload every file in a folder."""
626
- api_key, base = _resolve_client(require_key=False, silent=True)
627
- if not api_key:
628
- _err("Not logged in. You must be logged in to upload files.")
629
- print(f" {_DM}Run {_C}akash login{_RS}{_DM} to log in, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
630
- raise typer.Exit(1)
631
-
632
- try:
633
- client = AkashClient(api_key=api_key, api_url=base)
634
- uploader = VaultUploader(client)
635
- all_files = [p for p in path.glob("**/*") if p.is_file() and not p.name.startswith(".")]
636
- for i, file in enumerate(all_files, 1):
637
- sys.stdout.write(f"\r {_C}↑{_RS} [{i}/{len(all_files)}] {_DM}{file.name}{_RS} ")
638
- sys.stdout.flush()
639
- uploader.upload(file_path=str(file))
640
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
641
- sys.stdout.flush()
642
- _ok(f"uploaded {len(all_files)} files")
643
- except Exception as e:
644
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
645
- _err(str(e))
646
- raise typer.Exit(1)
624
+ """[DISCONTINUED] Recursively upload every file in a folder."""
625
+ _storage_discontinued_notice()
647
626
 
648
627
 
649
628
  # ── Helpers for backup/restore output ────────────────────────────────────────
@@ -2283,99 +2262,15 @@ def _decrypt_one(code: str, ident: dict, client, out: Optional[Path],
2283
2262
  # ── akash pipe ────────────────────────────────────────────────────────────────
2284
2263
 
2285
2264
  @app.command()
2286
- @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")
2287
2266
  def pipe(
2288
2267
  name: Optional[str] = typer.Option(None, "--name", "-n", help="Filename for the cloud snippet"),
2289
2268
  burn: bool = typer.Option(False, "--burn", help="Delete after first download"),
2290
2269
  expiry: int = typer.Option(0, "--expiry","-e", help="Expire in N days (0 = never)"),
2291
2270
  command: Optional[str] = typer.Option(None, "--run", "-c", help="Run a command and pipe its output"),
2292
2271
  ):
2293
- """Pipe stdin (or a command's output) to the cloud.
2294
-
2295
- Examples:
2296
- echo "hello" | akash pipe
2297
- cat debug.log | akash pipe --name debug.log
2298
- akash pipe --run "df -h" --name disk-report.txt
2299
- git log --oneline | akash pipe --burn --name git-log.txt
2300
- """
2301
- from .logger import log_op
2302
- import io
2303
-
2304
- api_key, base = _resolve_client(require_key=False, silent=True)
2305
- if not api_key:
2306
- _err("Not logged in. You must be logged in to pipe data to the cloud.")
2307
- print(f" {_DM}Run {_C}akash login{_RS}{_DM} to log in, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
2308
- raise typer.Exit(1)
2309
-
2310
- try:
2311
- client = AkashClient(api_key=api_key, api_url=base)
2312
- except Exception as e:
2313
- _err(f"not logged in: {e}")
2314
- raise typer.Exit(1)
2315
-
2316
- # ── Gather bytes ──────────────────────────────────────────────────────────
2317
- if command:
2318
- import subprocess as _sp
2319
- _info(f"running: {command}")
2320
- try:
2321
- result = _sp.run(command, shell=True, capture_output=True)
2322
- data = result.stdout + result.stderr
2323
- except Exception as e:
2324
- _err(f"command failed: {e}")
2325
- raise typer.Exit(1)
2326
- else:
2327
- import sys as _sys
2328
- if _sys.stdin.isatty():
2329
- _err("nothing to pipe - use --run or pipe stdin: echo 'hello' | akash pipe")
2330
- raise typer.Exit(1)
2331
- data = _sys.stdin.buffer.read()
2332
-
2333
- if not data:
2334
- _err("empty input - nothing to upload")
2335
- raise typer.Exit(1)
2336
-
2337
- size_kb = len(data) / 1024
2338
- filename = name or f"pipe_{__import__('time').strftime('%Y%m%d_%H%M%S')}.txt"
2339
-
2340
- # ── Upload ────────────────────────────────────────────────────────────────
2341
- import tempfile as _tf
2342
- with _tf.NamedTemporaryFile(suffix=".txt", prefix="akash_pipe_", delete=False) as tmp:
2343
- tmp.write(data)
2344
- tmp_path = tmp.name
2345
-
2346
- try:
2347
- def _cb(done, total):
2348
- bar = _progress_bar(done, total)
2349
- sys.stdout.write(f"\r {_C}↑{_RS} {bar} ")
2350
- sys.stdout.flush()
2351
-
2352
- # rename the tmp file so the server picks up the right name
2353
- import os as _os
2354
- named_path = _os.path.join(_os.path.dirname(tmp_path), filename)
2355
- _os.rename(tmp_path, named_path)
2356
-
2357
- result = client.upload_file(named_path, burn=burn, expiry=expiry, progress_callback=_cb)
2358
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
2359
- except Exception as e:
2360
- sys.stdout.write(chr(13) + chr(27) + "[2K"); sys.stdout.flush()
2361
- _err(f"upload failed: {e}")
2362
- log_op("pipe", ok=False, error=str(e))
2363
- raise typer.Exit(1)
2364
- finally:
2365
- try:
2366
- import os as _os2
2367
- _os2.unlink(named_path)
2368
- except Exception:
2369
- pass
2370
-
2371
- log_op("pipe", ok=True, code=result.file_code, filename=filename, size=len(data))
2372
- _p()
2373
- _ok(f"uploaded {_cy(filename)} {_dim(f'{size_kb:.1f} KB')}")
2374
- _info(f"code {_ye(result.file_code)}")
2375
- _info(f"link {result.embed_url}")
2376
- if burn:
2377
- _info("burns after first download")
2378
- _p()
2272
+ """[DISCONTINUED] Pipe stdin (or a command's output) to the cloud."""
2273
+ _storage_discontinued_notice()
2379
2274
 
2380
2275
 
2381
2276
  # ── akash log (+ --stats) ─────────────────────────────────────────────────────
@@ -2828,6 +2723,43 @@ def _render_inspection_card(r: dict) -> None:
2828
2723
  print(f" {_C}╰────────────────────────────────────────────────────────────────────{_RS}")
2829
2724
 
2830
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
+
2831
2763
  @agent_app.command("list")
2832
2764
  @agent_app.command("ls", hidden=True)
2833
2765
  @agent_app.command("ids", hidden=True)
@@ -2863,7 +2795,7 @@ def agent_list(raw: bool = typer.Option(False, "--json", help="Raw JSON output")
2863
2795
  default_pid = next(reversed(list(agents.keys())))
2864
2796
 
2865
2797
  _p()
2866
- 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")
2867
2799
  print(f" {_GR}{'─'*76}{_RS}")
2868
2800
 
2869
2801
  hdr_status = f"{'STATUS':<11}"
@@ -3400,7 +3332,8 @@ def agent_create(
3400
3332
  gemini_mcp_url = f"{base}/mcp"
3401
3333
 
3402
3334
  _p()
3403
- _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)
3404
3337
  print(f" {_DM}Profile ID :{_RS} {_C}{profile_id}{_RS}")
3405
3338
  print(f" {_DM}Client ID :{_RS} {_ye(cid)}")
3406
3339
  print(f" {_DM}Client Secret :{_RS} {_W}{csec}{_RS}")
@@ -3882,7 +3815,7 @@ def mcp_serve(
3882
3815
  worker_ws_url = f"{ws_base}/api/agent/mcp/worker?client_id={cid}&client_secret={csec}&device_fp={dev_fp}"
3883
3816
 
3884
3817
  _p()
3885
- print(" " + _C + "◈" + _RS + " " + _W + "Akash MCP Worker · Online" + _RS)
3818
+ _print_mcp_cloud_logo("Akash MCP Worker · Online", "Model Context Protocol Execution Host")
3886
3819
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
3887
3820
  print(" " + _DM + "Workspace : " + _RS + _cy(str(Path.cwd())))
3888
3821
  print(" " + _DM + "Gateway : " + _RS + _dim(base))
@@ -3969,7 +3902,8 @@ def mcp_serve(
3969
3902
 
3970
3903
  is_safe, sec_reason = _sanitize_agent_command(cmd, scopes=cached.get("scopes", "*"))
3971
3904
  if not is_safe:
3972
- 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}")
3973
3907
  ws.send(json.dumps({
3974
3908
  "type": "tool_response",
3975
3909
  "id": call_id,
@@ -4035,6 +3969,7 @@ def mcp_serve(
4035
3969
  ec_color = _G if returncode == 0 else _R
4036
3970
  ec_icon = f"{_G}✓{_RS}" if returncode == 0 else f"{_R}✗{_RS}"
4037
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)
4038
3973
 
4039
3974
  if returncode != 0:
4040
3975
  res_content = bounded_out or f"Command exited with status code {returncode} (no output)"
@@ -4053,6 +3988,7 @@ def mcp_serve(
4053
3988
  ok, msg_txt = _restore_undo_checkpoint()
4054
3989
  icon = f"{_G}✓{_RS}" if ok else f"{_R}✗{_RS}"
4055
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)
4056
3992
  ws.send(json.dumps({
4057
3993
  "type": "tool_response",
4058
3994
  "id": call_id,
@@ -4065,7 +4001,8 @@ def mcp_serve(
4065
4001
  with _Spin(f"checkpoint: {label} (packing workspace)", min_seconds=0.25, prefix=ts_pfx):
4066
4002
  _, manifest, _ = build_snapshot(label=label)
4067
4003
  elapsed_ms = (time.monotonic() - t0) * 1000
4068
- 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)
4069
4006
  ws.send(json.dumps({
4070
4007
  "type": "tool_response",
4071
4008
  "id": call_id,
@@ -4081,6 +4018,12 @@ def mcp_serve(
4081
4018
  elapsed_ms = (time.monotonic() - t0) * 1000
4082
4019
  icon = f"{_G}✓{_RS}" if not is_err else f"{_R}✗{_RS}"
4083
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)
4084
4027
  ws.send(json.dumps({
4085
4028
  "type": "tool_response",
4086
4029
  "id": call_id,
@@ -4097,6 +4040,7 @@ def mcp_serve(
4097
4040
  elapsed_ms = (time.monotonic() - t0) * 1000
4098
4041
  icon = f"{_G}✓{_RS}" if not is_err else f"{_R}✗{_RS}"
4099
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)
4100
4044
  ws.send(json.dumps({
4101
4045
  "type": "tool_response",
4102
4046
  "id": call_id,
@@ -4112,6 +4056,7 @@ def mcp_serve(
4112
4056
  elapsed_ms = (time.monotonic() - t0) * 1000
4113
4057
  icon = f"{_G}✓{_RS}" if not is_err else f"{_R}✗{_RS}"
4114
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)
4115
4060
  ws.send(json.dumps({
4116
4061
  "type": "tool_response",
4117
4062
  "id": call_id,
@@ -4122,7 +4067,8 @@ def mcp_serve(
4122
4067
  with _Spin("inspecting scopes…", min_seconds=0.15, prefix=ts_pfx):
4123
4068
  res_text, is_err = _handle_tool_scope_details(cached.get("scopes", "*"), pname, profile_id)
4124
4069
  elapsed_ms = (time.monotonic() - t0) * 1000
4125
- 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)
4126
4072
  ws.send(json.dumps({
4127
4073
  "type": "tool_response",
4128
4074
  "id": call_id,
@@ -4292,7 +4238,7 @@ def mcp_share(
4292
4238
  mode_label = "Permanent Small & Secure"
4293
4239
 
4294
4240
  _p()
4295
- 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)")
4296
4242
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
4297
4243
  print(" " + _DM + "Agent : " + _RS + _ye(name) + " " + _dim("(" + pid + ")"))
4298
4244
  print(" " + _DM + "Mode : " + _RS + _C + mode_label + _RS)
@@ -4327,10 +4273,11 @@ def mcp_share(
4327
4273
  _p()
4328
4274
 
4329
4275
  if show_all or claude:
4330
- print(" " + _C + "For Claude Desktop / Cursor" + _RS + " " + _dim("(config.json)") + ":")
4276
+ print(" " + _C + "For Claude Desktop, Cursor & Cline" + _RS + " " + _dim("(config.json / settings.json)") + ":")
4331
4277
  claude_cfg = json.dumps({"mcpServers": {"akash": {"url": local_url}}}, indent=2)
4332
4278
  for c_line in claude_cfg.splitlines():
4333
4279
  print(" " + c_line)
4280
+ print(" " + _DM + " Logo / Icon: Clean Cloud Icon delivered automatically via MCP handshake" + _RS)
4334
4281
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
4335
4282
  _p()
4336
4283
 
@@ -4361,7 +4308,7 @@ def mcp_status(
4361
4308
  _, base = _resolve_client(url or profile.get("url"), require_key=False, silent=True)
4362
4309
 
4363
4310
  _p()
4364
- print(" " + _C + "◈" + _RS + " " + _W + "Akash MCP · Health Check" + _RS)
4311
+ _print_mcp_cloud_logo("Akash MCP · Health Check", "Gateway & Tools Verification")
4365
4312
  print(" " + _GR + "──────────────────────────────────────────────────" + _RS)
4366
4313
 
4367
4314
  try:
@@ -26,8 +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
- if not getattr(self.client, "api_key", None):
30
- raise AuthenticationError("User is not logged in. An API key is required to upload files. Run 'akash login'.")
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
+ )
31
34
 
32
35
  # 1. Prepare Headers based on V3 Power-Control Specs
33
36
  headers = {
@@ -222,8 +225,11 @@ class VaultUploader:
222
225
 
223
226
  def upload_directory(self, folder_path: str, max_workers: int = 3) -> List[UploadResult]:
224
227
  """Recursively uploads all files in a folder using a thread pool."""
225
- if not getattr(self.client, "api_key", None):
226
- raise AuthenticationError("User is not logged in. An API key is required to upload files. Run 'akash login'.")
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
+ )
227
233
  # Convert string path to Path object
228
234
  root = Path(folder_path)
229
235
  if not root.is_dir():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akashcli
3
- Version: 4.8.5
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.5"
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
File without changes
File without changes