hypercli-cli 2026.3.8__tar.gz → 2026.3.13__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 (27) hide show
  1. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/PKG-INFO +10 -10
  2. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/README.md +6 -6
  3. hypercli_cli-2026.3.13/hypercli_cli/__init__.py +1 -0
  4. hypercli_cli-2026.3.8/hypercli_cli/claw.py → hypercli_cli-2026.3.13/hypercli_cli/agent.py +75 -64
  5. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/agents.py +257 -136
  6. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/cli.py +3 -3
  7. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/embed.py +12 -12
  8. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/onboard.py +24 -23
  9. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/stt.py +3 -3
  10. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/voice.py +15 -15
  11. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/pyproject.toml +4 -4
  12. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/tests/test_exec_shell_dryrun.py +4 -4
  13. hypercli_cli-2026.3.8/hypercli_cli/__init__.py +0 -1
  14. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/.gitignore +0 -0
  15. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/billing.py +0 -0
  16. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/comfyui.py +0 -0
  17. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/flow.py +0 -0
  18. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/instances.py +0 -0
  19. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/jobs.py +0 -0
  20. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/keys.py +0 -0
  21. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/output.py +0 -0
  22. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/renders.py +0 -0
  23. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/tui/__init__.py +0 -0
  24. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/tui/job_monitor.py +0 -0
  25. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/user.py +0 -0
  26. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/hypercli_cli/wallet.py +0 -0
  27. {hypercli_cli-2026.3.8 → hypercli_cli-2026.3.13}/tests/test_jobs_list_tags.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypercli-cli
3
- Version: 2026.3.8
3
+ Version: 2026.3.13
4
4
  Summary: CLI for HyperCLI - GPU orchestration and LLM API
5
5
  Project-URL: Homepage, https://hypercli.com
6
6
  Project-URL: Documentation, https://docs.hypercli.com
@@ -9,7 +9,7 @@ Author-email: HyperCLI <support@hypercli.com>
9
9
  License: MIT
10
10
  Requires-Python: >=3.10
11
11
  Requires-Dist: httpx>=0.27.0
12
- Requires-Dist: hypercli-sdk>=2026.3.8
12
+ Requires-Dist: hypercli-sdk>=2026.3.13
13
13
  Requires-Dist: mutagen>=1.47.0
14
14
  Requires-Dist: pyyaml>=6.0
15
15
  Requires-Dist: rich>=14.2.0
@@ -19,11 +19,11 @@ Provides-Extra: all
19
19
  Requires-Dist: argon2-cffi>=25.0.0; extra == 'all'
20
20
  Requires-Dist: eth-account>=0.13.0; extra == 'all'
21
21
  Requires-Dist: faster-whisper>=1.1.0; extra == 'all'
22
- Requires-Dist: hypercli-sdk[comfyui]>=2026.3.8; extra == 'all'
22
+ Requires-Dist: hypercli-sdk[comfyui]>=2026.3.13; extra == 'all'
23
23
  Requires-Dist: web3>=7.0.0; extra == 'all'
24
24
  Requires-Dist: x402[evm,httpx]>=2.0.0; extra == 'all'
25
25
  Provides-Extra: comfyui
26
- Requires-Dist: hypercli-sdk[comfyui]>=2026.3.8; extra == 'comfyui'
26
+ Requires-Dist: hypercli-sdk[comfyui]>=2026.3.13; extra == 'comfyui'
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: pytest>=8.0.0; extra == 'dev'
29
29
  Requires-Dist: ruff>=0.3.0; extra == 'dev'
@@ -78,14 +78,14 @@ hyper flow text-to-image "a cinematic portrait"
78
78
  hyper flow text-to-image "a cinematic portrait" --x402
79
79
 
80
80
  # HyperClaw checkout/config
81
- hyper claw plans
82
- hyper claw subscribe 1aiu
83
- hyper claw config env
84
- hyper claw exec <agent_id> "ls -la"
85
- hyper claw shell <agent_id>
81
+ hyper agent plans
82
+ hyper agent subscribe 1aiu
83
+ hyper agent config env
84
+ hyper agent exec <agent_id> "ls -la"
85
+ hyper agent shell <agent_id>
86
86
  ```
87
87
 
88
88
  ## Notes
89
89
 
90
90
  - `hyper llm` command surface has been removed.
91
- - For inference setup, use HyperClaw (`hyper claw config ...`) and your agent/client's OpenAI-compatible configuration.
91
+ - For inference setup, use HyperClaw (`hyper agent config ...`) and your agent/client's OpenAI-compatible configuration.
@@ -39,14 +39,14 @@ hyper flow text-to-image "a cinematic portrait"
39
39
  hyper flow text-to-image "a cinematic portrait" --x402
40
40
 
41
41
  # HyperClaw checkout/config
42
- hyper claw plans
43
- hyper claw subscribe 1aiu
44
- hyper claw config env
45
- hyper claw exec <agent_id> "ls -la"
46
- hyper claw shell <agent_id>
42
+ hyper agent plans
43
+ hyper agent subscribe 1aiu
44
+ hyper agent config env
45
+ hyper agent exec <agent_id> "ls -la"
46
+ hyper agent shell <agent_id>
47
47
  ```
48
48
 
49
49
  ## Notes
50
50
 
51
51
  - `hyper llm` command surface has been removed.
52
- - For inference setup, use HyperClaw (`hyper claw config ...`) and your agent/client's OpenAI-compatible configuration.
52
+ - For inference setup, use HyperClaw (`hyper agent config ...`) and your agent/client's OpenAI-compatible configuration.
@@ -0,0 +1 @@
1
+ __version__ = "2026.3.13"
@@ -1,4 +1,4 @@
1
- """HyperClaw inference commands"""
1
+ """HyperAgent inference commands"""
2
2
  import asyncio
3
3
  import json
4
4
  import os
@@ -13,7 +13,7 @@ from .voice import app as voice_app
13
13
  from .stt import transcribe as _stt_transcribe
14
14
  from .embed import app as embed_app
15
15
 
16
- app = typer.Typer(help="HyperClaw inference commands")
16
+ app = typer.Typer(help="HyperAgent inference commands")
17
17
  console = Console()
18
18
 
19
19
  # Register subcommands
@@ -35,9 +35,9 @@ def transcribe(
35
35
  """Transcribe audio to text using faster-whisper (runs locally).
36
36
 
37
37
  Examples:
38
- hyper claw transcribe voice.ogg
39
- hyper claw transcribe meeting.mp3 --model large-v3 --language en
40
- hyper claw transcribe audio.wav --json -o transcript.json
38
+ hyper agent transcribe voice.ogg
39
+ hyper agent transcribe meeting.mp3 --model large-v3 --language en
40
+ hyper agent transcribe audio.wav --json -o transcript.json
41
41
  """
42
42
  _stt_transcribe(audio_file, model, language, device, compute_type, json_output, output)
43
43
 
@@ -52,9 +52,9 @@ except ImportError:
52
52
  X402_AVAILABLE = False
53
53
 
54
54
  HYPERCLI_DIR = Path.home() / ".hypercli"
55
- CLAW_KEY_PATH = HYPERCLI_DIR / "claw-key.json"
56
- DEV_API_BASE = "https://dev-api.hyperclaw.app"
57
- PROD_API_BASE = "https://api.hyperclaw.app"
55
+ AGENT_KEY_PATH = HYPERCLI_DIR / "agent-key.json"
56
+ DEV_API_BASE = "https://api.dev.hypercli.com"
57
+ PROD_API_BASE = "https://api.hypercli.com"
58
58
 
59
59
 
60
60
  def require_x402_deps():
@@ -70,7 +70,7 @@ def require_x402_deps():
70
70
  def subscribe(
71
71
  plan_id: str = typer.Argument("1aiu", help="Plan ID: 1aiu, 2aiu, 5aiu, 10aiu (default: 1aiu)"),
72
72
  amount: str = typer.Argument(None, help="USDC amount to pay (e.g., '25' for $25). Duration scales proportionally."),
73
- dev: bool = typer.Option(False, "--dev", help="Use dev API (dev-api.hyperclaw.app)")
73
+ dev: bool = typer.Option(False, "--dev", help="Use dev API (api.dev.hypercli.com)")
74
74
  ):
75
75
  """Subscribe to a HyperClaw plan via x402 payment.
76
76
 
@@ -80,9 +80,9 @@ def subscribe(
80
80
  - $1 → ~1.3 days
81
81
 
82
82
  Examples:
83
- hyper claw subscribe 1aiu 25 # Pay $25 for 32 days
84
- hyper claw subscribe 1aiu 50 # Pay $50 for 64 days
85
- hyper claw subscribe 5aiu 100 # Pay $100 for 5aiu plan
83
+ hyper agent subscribe 1aiu 25 # Pay $25 for 32 days
84
+ hyper agent subscribe 1aiu 50 # Pay $50 for 64 days
85
+ hyper agent subscribe 5aiu 100 # Pay $100 for 5aiu plan
86
86
  """
87
87
  require_x402_deps()
88
88
 
@@ -109,7 +109,7 @@ def subscribe(
109
109
 
110
110
  # Save key (current)
111
111
  HYPERCLI_DIR.mkdir(parents=True, exist_ok=True)
112
- with open(CLAW_KEY_PATH, "w") as f:
112
+ with open(AGENT_KEY_PATH, "w") as f:
113
113
  json.dump(result, f, indent=2)
114
114
 
115
115
  # Build history entry with key info
@@ -128,7 +128,7 @@ def subscribe(
128
128
  }
129
129
 
130
130
  # Load existing keys or start fresh
131
- keys_history_path = HYPERCLI_DIR / "claw-keys.yaml"
131
+ keys_history_path = HYPERCLI_DIR / "agent-keys.yaml"
132
132
  if keys_history_path.exists():
133
133
  with open(keys_history_path) as f:
134
134
  keys_data = yaml.safe_load(f) or {"keys": []}
@@ -147,9 +147,9 @@ def subscribe(
147
147
  console.print(f"Duration: [bold]{result.get('duration_days', 30):.2f} days[/bold]")
148
148
  console.print(f"Expires: {result['expires_at']}")
149
149
  console.print(f"Limits: {result['tpm_limit']:,} TPM / {result['rpm_limit']:,} RPM")
150
- console.print(f"\n[green]✓[/green] Key saved to [bold]{CLAW_KEY_PATH}[/bold]")
150
+ console.print(f"\n[green]✓[/green] Key saved to [bold]{AGENT_KEY_PATH}[/bold]")
151
151
  console.print(f"[green]✓[/green] Key history: [bold]{keys_history_path}[/bold]")
152
- console.print("\nConfigure OpenClaw with: [bold]hyper claw openclaw-setup[/bold]")
152
+ console.print("\nConfigure OpenClaw with: [bold]hyper agent openclaw-setup[/bold]")
153
153
 
154
154
 
155
155
  async def _subscribe_async(account, plan_id: str, api_base: str, amount: str = None):
@@ -220,8 +220,8 @@ async def _subscribe_async(account, plan_id: str, api_base: str, amount: str = N
220
220
  payment_headers = http_client.encode_payment_signature_header(payment_payload)
221
221
  console.print(f"[green]✓[/green] Payment signed")
222
222
 
223
- # Step 6: Retry with payment (include JWT if available from claw login)
224
- jwt_path = HYPERCLI_DIR / "claw-jwt.json"
223
+ # Step 6: Retry with payment (include JWT if available from agent login)
224
+ jwt_path = HYPERCLI_DIR / "agent-jwt.json"
225
225
  if jwt_path.exists():
226
226
  try:
227
227
  with open(jwt_path) as f:
@@ -229,7 +229,7 @@ async def _subscribe_async(account, plan_id: str, api_base: str, amount: str = N
229
229
  jwt_token = jwt_data.get("token", "")
230
230
  if jwt_token:
231
231
  payment_headers["Authorization"] = f"Bearer {jwt_token}"
232
- console.print("[green]✓[/green] Attaching user auth (from claw login)")
232
+ console.print("[green]✓[/green] Attaching user auth (from agent login)")
233
233
  except Exception:
234
234
  pass
235
235
 
@@ -259,12 +259,12 @@ async def _subscribe_async(account, plan_id: str, api_base: str, amount: str = N
259
259
  def status():
260
260
  """Show current HyperClaw key status"""
261
261
 
262
- if not CLAW_KEY_PATH.exists():
262
+ if not AGENT_KEY_PATH.exists():
263
263
  console.print("[yellow]No HyperClaw key found.[/yellow]")
264
- console.print("Subscribe with: [bold]hyper claw subscribe <aiu>[/bold]")
264
+ console.print("Subscribe with: [bold]hyper agent subscribe <aiu>[/bold]")
265
265
  raise typer.Exit(0)
266
266
 
267
- with open(CLAW_KEY_PATH) as f:
267
+ with open(AGENT_KEY_PATH) as f:
268
268
  key_data = json.load(f)
269
269
 
270
270
  # Parse expiry
@@ -339,7 +339,7 @@ def plans(
339
339
  console.print()
340
340
  console.print(table)
341
341
  console.print()
342
- console.print("Subscribe with: [bold]hyper claw subscribe <plan_id> <amount>[/bold]")
342
+ console.print("Subscribe with: [bold]hyper agent subscribe <plan_id> <amount>[/bold]")
343
343
 
344
344
 
345
345
  @app.command("models")
@@ -426,12 +426,12 @@ def login(
426
426
  1. Signs a challenge with your wallet private key
427
427
  2. Backend verifies signature, creates/finds your user
428
428
  3. Creates an API key bound to your user account
429
- 4. Saves the key to ~/.hypercli/claw-key.json
429
+ 4. Saves the key to ~/.hypercli/agent-key.json
430
430
 
431
431
  After login, you can use:
432
432
  hyper agents create Launch an OpenClaw agent pod
433
433
  hyper agents list List your agents
434
- hyper claw config Generate provider configs
434
+ hyper agent config Generate provider configs
435
435
  """
436
436
  try:
437
437
  from eth_account.messages import encode_defunct
@@ -492,17 +492,17 @@ def login(
492
492
  team_id = login_data.get("team_id", "")
493
493
  wallet_addr = login_data.get("wallet_address", account.address)
494
494
 
495
- # Step 5: Create a claw API key using the JWT
495
+ # Step 5: Create an agent API key using the JWT
496
496
  console.print("[bold]Creating API key...[/bold]")
497
497
  with httpx.Client(timeout=15) as client:
498
498
  resp = client.post(
499
499
  f"{base_url}/api/keys",
500
- json={"name": "claw-cli"},
500
+ json={"name": "agent-cli"},
501
501
  headers={"Authorization": f"Bearer {jwt_token}"},
502
502
  )
503
503
  if resp.status_code != 200:
504
504
  # Save JWT anyway so user can still auth
505
- jwt_path = HYPERCLI_DIR / "claw-jwt.json"
505
+ jwt_path = HYPERCLI_DIR / "agent-jwt.json"
506
506
  HYPERCLI_DIR.mkdir(parents=True, exist_ok=True)
507
507
  with open(jwt_path, "w") as f:
508
508
  json.dump({"token": jwt_token, "user_id": user_id, "team_id": team_id}, f, indent=2)
@@ -514,9 +514,9 @@ def login(
514
514
 
515
515
  api_key = key_data.get("api_key", key_data.get("key", ""))
516
516
 
517
- # Step 6: Save as claw key
517
+ # Step 6: Save as agent key
518
518
  HYPERCLI_DIR.mkdir(parents=True, exist_ok=True)
519
- claw_key_data = {
519
+ agent_key_data = {
520
520
  "key": api_key,
521
521
  "plan_id": login_data.get("plan_id", "free"),
522
522
  "user_id": user_id,
@@ -526,22 +526,27 @@ def login(
526
526
  "rpm_limit": 0,
527
527
  "expires_at": "",
528
528
  }
529
- with open(CLAW_KEY_PATH, "w") as f:
530
- json.dump(claw_key_data, f, indent=2)
529
+ with open(AGENT_KEY_PATH, "w") as f:
530
+ json.dump(agent_key_data, f, indent=2)
531
531
 
532
- console.print(f"[green]✓[/green] API key saved to [bold]{CLAW_KEY_PATH}[/bold]\n")
532
+ console.print(f"[green]✓[/green] API key saved to [bold]{AGENT_KEY_PATH}[/bold]\n")
533
533
  console.print(f" User: {user_id[:12]}...")
534
534
  console.print(f" Team: {team_id[:12]}...")
535
535
  console.print(f" Key: {api_key[:20]}...")
536
536
  console.print(f" Wallet: {wallet_addr}")
537
537
  console.print(f"\n[green]You're all set![/green]")
538
538
  console.print(f" Launch agent: [bold]hyper agents create[/bold]")
539
- console.print(f" Configure: [bold]hyper claw config openclaw --apply[/bold]")
539
+ console.print(f" Configure: [bold]hyper agent config openclaw --apply[/bold]")
540
540
 
541
541
 
542
542
  OPENCLAW_CONFIG_PATH = Path.home() / ".openclaw" / "openclaw.json"
543
543
 
544
544
 
545
+ def _resolve_api_base(base_url: str | None = None, dev: bool = False) -> str:
546
+ """Resolve API base from flag/env, then fall back to dev/prod defaults."""
547
+ return (base_url or os.environ.get("HYPERCLAW_API_BASE") or (DEV_API_BASE if dev else PROD_API_BASE)).rstrip("/")
548
+
549
+
545
550
  def fetch_models(api_key: str, api_base: str = PROD_API_BASE) -> list[dict]:
546
551
  """Fetch available models from LiteLLM /v1/models (served by HyperClaw)."""
547
552
  import httpx
@@ -555,7 +560,7 @@ def fetch_models(api_key: str, api_base: str = PROD_API_BASE) -> list[dict]:
555
560
  data = resp.json().get("data", [])
556
561
  # Known model metadata (context windows, reasoning, etc.)
557
562
  MODEL_META = {
558
- "kimi-k2.5": {"name": "Kimi K2.5", "reasoning": False, "contextWindow": 262144},
563
+ "kimi-k2.5": {"name": "Kimi K2.5", "reasoning": True, "contextWindow": 262144},
559
564
  "glm-5": {"name": "GLM-5", "reasoning": True, "contextWindow": 202752},
560
565
  }
561
566
  return [
@@ -577,7 +582,7 @@ def fetch_models(api_key: str, api_base: str = PROD_API_BASE) -> list[dict]:
577
582
  {
578
583
  "id": "kimi-k2.5",
579
584
  "name": "Kimi K2.5",
580
- "reasoning": False,
585
+ "reasoning": True,
581
586
  "input": ["text"],
582
587
  "contextWindow": 262144,
583
588
  },
@@ -597,18 +602,18 @@ def openclaw_setup(
597
602
  ):
598
603
  """Patch OpenClaw config with your HyperClaw API key.
599
604
 
600
- Reads key from ~/.hypercli/claw-key.json, patches only the
605
+ Reads key from ~/.hypercli/agent-key.json, patches only the
601
606
  models.providers.hyperclaw section in ~/.openclaw/openclaw.json.
602
607
  Everything else in the config is left untouched.
603
608
  """
604
609
 
605
610
  # Load HyperClaw key
606
- if not CLAW_KEY_PATH.exists():
611
+ if not AGENT_KEY_PATH.exists():
607
612
  console.print("[red]❌ No HyperClaw key found.[/red]")
608
- console.print("Run: [bold]hyper claw subscribe 1aiu <amount>[/bold]")
613
+ console.print("Run: [bold]hyper agent subscribe 1aiu <amount>[/bold]")
609
614
  raise typer.Exit(1)
610
615
 
611
- with open(CLAW_KEY_PATH) as f:
616
+ with open(AGENT_KEY_PATH) as f:
612
617
  api_key = json.load(f).get("key", "")
613
618
 
614
619
  if not api_key:
@@ -630,13 +635,13 @@ def openclaw_setup(
630
635
  chat_models = [m for m in models if m.get("mode") != "embedding"]
631
636
  embedding_models = [m for m in models if m.get("mode") == "embedding"]
632
637
  config["models"]["providers"]["hyperclaw"] = {
633
- "baseUrl": "https://api.hyperclaw.app",
638
+ "baseUrl": "https://api.hypercli.com",
634
639
  "apiKey": api_key,
635
640
  "api": "anthropic-messages",
636
641
  "models": chat_models,
637
642
  }
638
643
  config["models"]["providers"]["hyperclaw-embed"] = {
639
- "baseUrl": "https://api.hyperclaw.app/v1",
644
+ "baseUrl": "https://api.hypercli.com/v1",
640
645
  "apiKey": api_key,
641
646
  "api": "openai-completions",
642
647
  "models": embedding_models,
@@ -645,10 +650,10 @@ def openclaw_setup(
645
650
  # Always set embedding provider (reuses same API key)
646
651
  config.setdefault("agents", {}).setdefault("defaults", {})
647
652
  config["agents"]["defaults"]["memorySearch"] = {
648
- "provider": "hyperclaw-embed",
653
+ "provider": "openai",
649
654
  "model": "qwen3-embedding-4b",
650
655
  "remote": {
651
- "baseUrl": "https://api.hyperclaw.app/v1/",
656
+ "baseUrl": "https://api.hypercli.com/v1/",
652
657
  "apiKey": api_key,
653
658
  }
654
659
  }
@@ -675,30 +680,32 @@ def openclaw_setup(
675
680
  console.print(f" model: hyperclaw-embed/{m['id']}")
676
681
  if default and chat_models:
677
682
  console.print(f" default model: hyperclaw/{chat_models[0]['id']}")
678
- console.print("\nRun: [bold]openclaw gateway restart[/bold]")
683
+ console.print("\nOpenClaw will use the Anthropic-compatible /v1/messages endpoint.")
684
+ console.print("Run: [bold]openclaw gateway restart[/bold]")
679
685
 
680
686
 
681
687
  # ---------------------------------------------------------------------------
682
- # hyper claw config — generate / apply provider configs for various tools
688
+ # hyper agent config — generate / apply provider configs for various tools
683
689
  # ---------------------------------------------------------------------------
684
690
 
685
691
  def _resolve_api_key(key: str | None) -> str:
686
- """Resolve API key from --key flag or ~/.hypercli/claw-key.json."""
692
+ """Resolve API key from --key flag or ~/.hypercli/agent-key.json."""
687
693
  if key:
688
694
  return key
689
- if CLAW_KEY_PATH.exists():
690
- with open(CLAW_KEY_PATH) as f:
695
+ if AGENT_KEY_PATH.exists():
696
+ with open(AGENT_KEY_PATH) as f:
691
697
  k = json.load(f).get("key", "")
692
698
  if k:
693
699
  return k
694
700
  console.print("[red]❌ No API key found.[/red]")
695
701
  console.print("Either pass [bold]--key sk-...[/bold] or subscribe first:")
696
- console.print(" [bold]hyper claw subscribe 1aiu[/bold]")
702
+ console.print(" [bold]hyper agent subscribe 1aiu[/bold]")
697
703
  raise typer.Exit(1)
698
704
 
699
705
 
700
706
  def _config_openclaw(api_key: str, models: list[dict], api_base: str = PROD_API_BASE) -> dict:
701
707
  """OpenClaw openclaw.json provider snippet (LLM + embeddings)."""
708
+ api_base = api_base.rstrip("/")
702
709
  chat_models = [m for m in models if m.get("mode") != "embedding"]
703
710
  embedding_models = [m for m in models if m.get("mode") == "embedding"]
704
711
  return {
@@ -728,7 +735,7 @@ def _config_openclaw(api_key: str, models: list[dict], api_base: str = PROD_API_
728
735
  **{f"hyperclaw-embed/{m['id']}": {"alias": m['id'].split('-')[0]} for m in embedding_models},
729
736
  },
730
737
  "memorySearch": {
731
- "provider": "hyperclaw-embed",
738
+ "provider": "openai",
732
739
  "model": "qwen3-embedding-4b",
733
740
  "remote": {
734
741
  "baseUrl": f"{api_base}/v1/",
@@ -740,8 +747,9 @@ def _config_openclaw(api_key: str, models: list[dict], api_base: str = PROD_API_
740
747
  }
741
748
 
742
749
 
743
- def _config_opencode(api_key: str, models: list[dict]) -> dict:
750
+ def _config_opencode(api_key: str, models: list[dict], api_base: str = PROD_API_BASE) -> dict:
744
751
  """OpenCode opencode.json provider snippet."""
752
+ api_base = api_base.rstrip("/")
745
753
  model_entries = {}
746
754
  for m in models:
747
755
  model_entries[m["id"]] = {"name": m["id"]}
@@ -752,7 +760,7 @@ def _config_opencode(api_key: str, models: list[dict]) -> dict:
752
760
  "npm": "@ai-sdk/openai-compatible",
753
761
  "name": "HyperCLI",
754
762
  "options": {
755
- "baseURL": "https://api.hyperclaw.app/v1",
763
+ "baseURL": f"{api_base}/v1",
756
764
  "apiKey": api_key,
757
765
  },
758
766
  "models": model_entries,
@@ -761,11 +769,12 @@ def _config_opencode(api_key: str, models: list[dict]) -> dict:
761
769
  }
762
770
 
763
771
 
764
- def _config_env(api_key: str, models: list[dict]) -> str:
772
+ def _config_env(api_key: str, models: list[dict], api_base: str = PROD_API_BASE) -> str:
765
773
  """Shell env vars for generic OpenAI-compatible tools."""
774
+ api_base = api_base.rstrip("/")
766
775
  lines = [
767
776
  f'export OPENAI_API_KEY="{api_key}"',
768
- 'export OPENAI_BASE_URL="https://api.hyperclaw.app/v1"',
777
+ f'export OPENAI_BASE_URL="{api_base}/v1"',
769
778
  f'# Available models: {", ".join(m["id"] for m in models)}',
770
779
  ]
771
780
  return "\n".join(lines)
@@ -802,21 +811,23 @@ def config_cmd(
802
811
  None,
803
812
  help=f"Output format: {', '.join(FORMAT_CHOICES)}. Omit to show all.",
804
813
  ),
805
- key: str = typer.Option(None, "--key", "-k", help="API key (sk-...). Falls back to ~/.hypercli/claw-key.json"),
814
+ key: str = typer.Option(None, "--key", "-k", help="API key (sk-...). Falls back to ~/.hypercli/agent-key.json"),
815
+ base_url: str = typer.Option(None, "--base-url", help="HyperClaw API base URL. Falls back to HYPERCLAW_API_BASE, then --dev/prod defaults"),
806
816
  apply: bool = typer.Option(False, "--apply", help="Write config to the appropriate file (openclaw/opencode only)"),
807
817
  dev: bool = typer.Option(False, "--dev", help="Use dev API"),
808
818
  ):
809
819
  """Generate provider configs for OpenClaw, OpenCode, and other tools.
810
820
 
811
821
  Examples:
812
- hyper claw config # Show all configs
813
- hyper claw config openclaw # OpenClaw snippet
814
- hyper claw config opencode --key sk-... # OpenCode with explicit key
815
- hyper claw config openclaw --apply # Write directly to openclaw.json
816
- hyper claw config env # Shell export lines
822
+ hyper agent config # Show all configs
823
+ hyper agent config openclaw # OpenClaw snippet
824
+ hyper agent config opencode --key sk-... # OpenCode with explicit key
825
+ hyper agent config openclaw --base-url https://api.dev.hypercli.com
826
+ hyper agent config openclaw --apply # Write directly to openclaw.json
827
+ hyper agent config env # Shell export lines
817
828
  """
818
829
  api_key = _resolve_api_key(key)
819
- api_base = DEV_API_BASE if dev else PROD_API_BASE
830
+ api_base = _resolve_api_base(base_url, dev)
820
831
 
821
832
  # Validate key & fetch models
822
833
  console.print(f"[dim]Validating key against {api_base}...[/dim]")
@@ -836,12 +847,12 @@ def config_cmd(
836
847
  snippet = _config_openclaw(api_key, models, api_base)
837
848
  _show_snippet("OpenClaw", "~/.openclaw/openclaw.json", snippet, apply, OPENCLAW_CONFIG_PATH)
838
849
  elif fmt == "opencode":
839
- snippet = _config_opencode(api_key, models)
850
+ snippet = _config_opencode(api_key, models, api_base)
840
851
  target = Path.cwd() / "opencode.json"
841
852
  _show_snippet("OpenCode", "opencode.json", snippet, apply, target)
842
853
  elif fmt == "env":
843
854
  console.print("[bold]── Shell Environment ──[/bold]")
844
- console.print(_config_env(api_key, models))
855
+ console.print(_config_env(api_key, models, api_base))
845
856
  console.print()
846
857
 
847
858