Skip to content

Commit 54f055f

Browse files
yeldarbyclaude
andcommitted
fix(cli): project list/get auto-detect workspace from API key
Added resolve_default_workspace() helper to _resolver.py that queries the API validation endpoint when RF_WORKSPACE is not in config. Used by project list, project get (short slug), and workspace list so all commands work consistently with just ROBOFLOW_API_KEY set. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1756e4e commit 54f055f

3 files changed

Lines changed: 48 additions & 25 deletions

File tree

roboflow/cli/_resolver.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,39 @@
1717

1818
from __future__ import annotations
1919

20+
import os
2021
from typing import Optional, Tuple
2122

2223
from roboflow.config import get_conditional_configuration_variable
2324

2425

26+
def resolve_default_workspace(api_key: Optional[str] = None) -> Optional[str]:
27+
"""Return the default workspace URL, querying the API if necessary.
28+
29+
Checks (in order): ``RF_WORKSPACE`` in config/env, then the API
30+
validation endpoint using the supplied *api_key* (or ``ROBOFLOW_API_KEY``).
31+
"""
32+
ws = get_conditional_configuration_variable("RF_WORKSPACE", default=None)
33+
if ws:
34+
return ws
35+
36+
key = api_key or os.getenv("ROBOFLOW_API_KEY")
37+
if not key:
38+
return None
39+
40+
import requests
41+
42+
from roboflow.config import API_URL
43+
44+
try:
45+
resp = requests.post(API_URL + "/?api_key=" + key)
46+
if resp.status_code == 200:
47+
return resp.json().get("workspace") or None
48+
except Exception: # noqa: BLE001
49+
pass
50+
return None
51+
52+
2553
def resolve_resource(
2654
shorthand: str,
2755
workspace_override: Optional[str] = None,
@@ -49,7 +77,7 @@ def resolve_resource(
4977
"""
5078
parts = shorthand.strip("/").split("/")
5179

52-
default_ws = workspace_override or get_conditional_configuration_variable("RF_WORKSPACE", default=None)
80+
default_ws = workspace_override or resolve_default_workspace()
5381

5482
if len(parts) == 1:
5583
# "my-project"

roboflow/cli/handlers/project.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ def _list_projects(args: argparse.Namespace) -> None:
5656

5757
workspace_url = args.workspace
5858
if not workspace_url:
59-
from roboflow.config import get_conditional_configuration_variable
59+
from roboflow.cli._resolver import resolve_default_workspace
6060

61-
workspace_url = get_conditional_configuration_variable("RF_WORKSPACE", default=None)
61+
workspace_url = resolve_default_workspace(api_key=args.api_key)
6262

6363
if not workspace_url:
6464
output_error(args, "No workspace specified.", hint="Use --workspace or run 'roboflow auth login'.")

roboflow/cli/handlers/workspace.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def _list_workspaces(args: argparse.Namespace) -> None:
3030
import os
3131

3232
from roboflow.cli._output import output
33+
from roboflow.cli._resolver import resolve_default_workspace
3334
from roboflow.cli._table import format_table
3435
from roboflow.config import APP_URL, get_conditional_configuration_variable
3536

@@ -39,28 +40,22 @@ def _list_workspaces(args: argparse.Namespace) -> None:
3940
# When no workspaces in config, fall back to API using available API key
4041
if not workspaces:
4142
api_key = getattr(args, "api_key", None) or os.getenv("ROBOFLOW_API_KEY")
42-
if api_key:
43-
import requests
44-
45-
from roboflow.config import API_URL
46-
47-
resp = requests.post(API_URL + "/?api_key=" + api_key)
48-
if resp.status_code == 200:
49-
data = resp.json()
50-
ws_url = data.get("workspace", "")
51-
if ws_url:
52-
ws_name = ws_url
53-
try:
54-
from roboflow.adapters import rfapi
55-
56-
ws_json = rfapi.get_workspace(api_key, ws_url)
57-
ws_detail = ws_json.get("workspace", ws_json)
58-
ws_name = ws_detail.get("name", ws_url)
59-
except Exception: # noqa: BLE001
60-
pass
61-
workspaces = {ws_url: {"url": ws_url, "name": ws_name, "apiKey": api_key}}
62-
if not default_ws_url:
63-
default_ws_url = ws_url
43+
ws_url = resolve_default_workspace(api_key=api_key)
44+
if ws_url:
45+
ws_name = ws_url
46+
if api_key or os.getenv("ROBOFLOW_API_KEY"):
47+
try:
48+
from roboflow.adapters import rfapi
49+
50+
key = api_key or os.getenv("ROBOFLOW_API_KEY") or ""
51+
ws_json = rfapi.get_workspace(key, ws_url)
52+
ws_detail = ws_json.get("workspace", ws_json)
53+
ws_name = ws_detail.get("name", ws_url)
54+
except Exception: # noqa: BLE001
55+
pass
56+
workspaces = {ws_url: {"url": ws_url, "name": ws_name}}
57+
if not default_ws_url:
58+
default_ws_url = ws_url
6459

6560
rows = []
6661
for w in workspaces.values():

0 commit comments

Comments
 (0)