powerbase-cli 0.1.2__tar.gz → 0.1.4__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 (37) hide show
  1. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/PKG-INFO +21 -20
  2. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/README.md +20 -19
  3. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/pyproject.toml +1 -1
  4. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/auth.py +46 -41
  5. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/session.py +3 -2
  6. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/transport.py +3 -2
  7. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli.egg-info/PKG-INFO +21 -20
  8. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/tests/test_cli_commands.py +14 -14
  9. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/tests/test_cli_help.py +11 -2
  10. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/tests/test_session.py +2 -1
  11. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/tests/test_transport.py +4 -2
  12. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/setup.cfg +0 -0
  13. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/__init__.py +0 -0
  14. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/__main__.py +0 -0
  15. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/api.py +0 -0
  16. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/certs/powerbase-test-ca.pem +0 -0
  17. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/cli.py +0 -0
  18. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/__init__.py +0 -0
  19. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/agent.py +0 -0
  20. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/branch.py +0 -0
  21. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/config_cmd.py +0 -0
  22. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/context.py +0 -0
  23. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/database.py +0 -0
  24. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/instance.py +0 -0
  25. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/org.py +0 -0
  26. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/parser.py +0 -0
  27. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/publish.py +0 -0
  28. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/sandbox.py +0 -0
  29. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/shared.py +0 -0
  30. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/commands/sql.py +0 -0
  31. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli/config.py +0 -0
  32. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli.egg-info/SOURCES.txt +0 -0
  33. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli.egg-info/dependency_links.txt +0 -0
  34. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli.egg-info/entry_points.txt +0 -0
  35. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/src/powerbase_cli.egg-info/top_level.txt +0 -0
  36. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/tests/test_api.py +0 -0
  37. {powerbase_cli-0.1.2 → powerbase_cli-0.1.4}/tests/test_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: powerbase-cli
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: CLI for operating Powerbase console workflows
5
5
  Author: Powerbase
6
6
  Requires-Python: >=3.11
@@ -91,6 +91,7 @@ The preferred flow is:
91
91
 
92
92
  ```bash
93
93
  powerbase auth login
94
+ powerbase auth wait --login-id LOGIN_ID
94
95
  ```
95
96
 
96
97
  The CLI now includes a built-in `base_url` and `anon_key` default for this deployment. The test package also bundles this environment's self-signed CA certificate, so most users can start with browser login directly and only use flags or environment variables when overriding that default.
@@ -100,16 +101,14 @@ The bundled CA is a test-only convenience for the current self-signed deployment
100
101
  This will:
101
102
 
102
103
  1. request a CLI login session from Powerbase
103
- 2. print a browser URL
104
- 3. poll until browser approval or until `--timeout` elapses (default **600** seconds, ten minutes)
105
- 4. save the resulting session to `~/.config/powerbase/auth.json`
104
+ 2. return a `login_id` and browser URL
105
+ 3. wait for the user to approve the request in their own browser
106
+ 4. poll with `powerbase auth wait --login-id ...` until approval or until `--timeout` elapses (default **600** seconds, ten minutes)
107
+ 5. save the resulting session to `~/.config/powerbase/auth.json`
106
108
 
107
- Use `--timeout 0` to wait without a time limit. Use a larger value if users need more than ten minutes to complete login.
108
- For agent-guided workflows, prefer `powerbase auth login --no-wait --json` so the CLI returns the `login_url` and exits immediately instead of blocking on polling.
109
- If the browser link expires or the user is not currently signed in to the console, rerun `powerbase auth login --no-wait --json` to generate a fresh login URL before retrying.
110
- If an agent or wrapper script is coordinating the workflow, it is still helpful
111
- to tell the user: after browser approval, return to the current session so the
112
- remaining steps can continue.
109
+ Use `--timeout 0` on `auth wait` to wait without a time limit. Use a larger value if users need more than ten minutes to complete login.
110
+ For agent-guided workflows, run `powerbase auth login --json`, return the `login_url` to the user, stop, and wait for the user to confirm browser approval before running `powerbase auth wait --login-id ... --json`.
111
+ If the browser link expires or the user is not currently signed in to the console, rerun `powerbase auth login --json` to generate a fresh login URL before retrying.
113
112
 
114
113
  ### Manual Token Import
115
114
 
@@ -280,22 +279,24 @@ When Openclaw or another LLM agent uses `powerbase`:
280
279
  - run discovery commands before write operations
281
280
  - set context for long multi-step tasks
282
281
  - use `auth status` before workflows that assume login
283
- - prefer `auth login --no-wait --json` for browser login so the agent can hand `login_url` back to the user
284
- - if a protected command says authentication is missing or expired, rerun `auth login --no-wait --json` to generate a fresh login URL
282
+ - use `auth login --json` to generate a login URL, then stop and hand `login_url` to the user
285
283
  - do not have the agent open the browser login URL itself; the user must complete that approval step
284
+ - after the user confirms approval, run `auth wait --login-id ... --json` to complete login
285
+ - if a protected command says authentication is missing or expired, rerun `auth login --json` to generate a fresh login URL
286
286
  - remember that `--json` overrides a saved `config output text` setting for that command
287
287
 
288
288
  Recommended agent sequence:
289
289
 
290
290
  1. `powerbase auth status --json`
291
- 2. If unauthenticated, or if a protected command reports an auth error, run `powerbase auth login --no-wait --json`, return the `login_url` to the user, and wait for them to approve in the browser
292
- 3. `powerbase context show --json`
293
- 4. If no instance is selected, run `powerbase instance list --json`
294
- 5. If no suitable instance exists, prefer `powerbase instance create --name ... --org-id ... --json`
295
- 6. Use `powerbase database ...` only for the advanced bring-your-own-database path
296
- 7. Set context with `powerbase context use-instance ...`
297
- 8. If you want the sandbox agent preview on a non-main branch, run `powerbase branch switch ...`
298
- 9. Continue with `branch`, `sql`, `publish`, `sandbox files`, or `agent` commands
291
+ 2. If unauthenticated, or if a protected command reports an auth error, run `powerbase auth login --json` and return the `login_url` plus `login_id` to the user
292
+ 3. After the user confirms browser approval, run `powerbase auth wait --login-id LOGIN_ID --json`
293
+ 4. `powerbase context show --json`
294
+ 5. If no instance is selected, run `powerbase instance list --json`
295
+ 6. If no suitable instance exists, prefer `powerbase instance create --name ... --org-id ... --json`
296
+ 7. Use `powerbase database ...` only for the advanced bring-your-own-database path
297
+ 8. Set context with `powerbase context use-instance ...`
298
+ 9. If you want the sandbox agent preview on a non-main branch, run `powerbase branch switch ...`
299
+ 10. Continue with `branch`, `sql`, `publish`, `sandbox files`, or `agent` commands
299
300
 
300
301
  ## Testing
301
302
 
@@ -83,6 +83,7 @@ The preferred flow is:
83
83
 
84
84
  ```bash
85
85
  powerbase auth login
86
+ powerbase auth wait --login-id LOGIN_ID
86
87
  ```
87
88
 
88
89
  The CLI now includes a built-in `base_url` and `anon_key` default for this deployment. The test package also bundles this environment's self-signed CA certificate, so most users can start with browser login directly and only use flags or environment variables when overriding that default.
@@ -92,16 +93,14 @@ The bundled CA is a test-only convenience for the current self-signed deployment
92
93
  This will:
93
94
 
94
95
  1. request a CLI login session from Powerbase
95
- 2. print a browser URL
96
- 3. poll until browser approval or until `--timeout` elapses (default **600** seconds, ten minutes)
97
- 4. save the resulting session to `~/.config/powerbase/auth.json`
96
+ 2. return a `login_id` and browser URL
97
+ 3. wait for the user to approve the request in their own browser
98
+ 4. poll with `powerbase auth wait --login-id ...` until approval or until `--timeout` elapses (default **600** seconds, ten minutes)
99
+ 5. save the resulting session to `~/.config/powerbase/auth.json`
98
100
 
99
- Use `--timeout 0` to wait without a time limit. Use a larger value if users need more than ten minutes to complete login.
100
- For agent-guided workflows, prefer `powerbase auth login --no-wait --json` so the CLI returns the `login_url` and exits immediately instead of blocking on polling.
101
- If the browser link expires or the user is not currently signed in to the console, rerun `powerbase auth login --no-wait --json` to generate a fresh login URL before retrying.
102
- If an agent or wrapper script is coordinating the workflow, it is still helpful
103
- to tell the user: after browser approval, return to the current session so the
104
- remaining steps can continue.
101
+ Use `--timeout 0` on `auth wait` to wait without a time limit. Use a larger value if users need more than ten minutes to complete login.
102
+ For agent-guided workflows, run `powerbase auth login --json`, return the `login_url` to the user, stop, and wait for the user to confirm browser approval before running `powerbase auth wait --login-id ... --json`.
103
+ If the browser link expires or the user is not currently signed in to the console, rerun `powerbase auth login --json` to generate a fresh login URL before retrying.
105
104
 
106
105
  ### Manual Token Import
107
106
 
@@ -272,22 +271,24 @@ When Openclaw or another LLM agent uses `powerbase`:
272
271
  - run discovery commands before write operations
273
272
  - set context for long multi-step tasks
274
273
  - use `auth status` before workflows that assume login
275
- - prefer `auth login --no-wait --json` for browser login so the agent can hand `login_url` back to the user
276
- - if a protected command says authentication is missing or expired, rerun `auth login --no-wait --json` to generate a fresh login URL
274
+ - use `auth login --json` to generate a login URL, then stop and hand `login_url` to the user
277
275
  - do not have the agent open the browser login URL itself; the user must complete that approval step
276
+ - after the user confirms approval, run `auth wait --login-id ... --json` to complete login
277
+ - if a protected command says authentication is missing or expired, rerun `auth login --json` to generate a fresh login URL
278
278
  - remember that `--json` overrides a saved `config output text` setting for that command
279
279
 
280
280
  Recommended agent sequence:
281
281
 
282
282
  1. `powerbase auth status --json`
283
- 2. If unauthenticated, or if a protected command reports an auth error, run `powerbase auth login --no-wait --json`, return the `login_url` to the user, and wait for them to approve in the browser
284
- 3. `powerbase context show --json`
285
- 4. If no instance is selected, run `powerbase instance list --json`
286
- 5. If no suitable instance exists, prefer `powerbase instance create --name ... --org-id ... --json`
287
- 6. Use `powerbase database ...` only for the advanced bring-your-own-database path
288
- 7. Set context with `powerbase context use-instance ...`
289
- 8. If you want the sandbox agent preview on a non-main branch, run `powerbase branch switch ...`
290
- 9. Continue with `branch`, `sql`, `publish`, `sandbox files`, or `agent` commands
283
+ 2. If unauthenticated, or if a protected command reports an auth error, run `powerbase auth login --json` and return the `login_url` plus `login_id` to the user
284
+ 3. After the user confirms browser approval, run `powerbase auth wait --login-id LOGIN_ID --json`
285
+ 4. `powerbase context show --json`
286
+ 5. If no instance is selected, run `powerbase instance list --json`
287
+ 6. If no suitable instance exists, prefer `powerbase instance create --name ... --org-id ... --json`
288
+ 7. Use `powerbase database ...` only for the advanced bring-your-own-database path
289
+ 8. Set context with `powerbase context use-instance ...`
290
+ 9. If you want the sandbox agent preview on a non-main branch, run `powerbase branch switch ...`
291
+ 10. Continue with `branch`, `sql`, `publish`, `sandbox files`, or `agent` commands
291
292
 
292
293
  ## Testing
293
294
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "powerbase-cli"
7
- version = "0.1.2"
7
+ version = "0.1.4"
8
8
  description = "CLI for operating Powerbase console workflows"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -6,40 +6,18 @@ import time
6
6
  from .shared import AuthSession, AuthState, build_api, now_iso, render_output
7
7
 
8
8
 
9
- def handle_auth_login(args: argparse.Namespace) -> int:
9
+ def _poll_login_until_approved(args: argparse.Namespace, *, login_id: str) -> int:
10
10
  store, config, _, _, api = build_api(args)
11
- data = api.start_cli_login()
12
- login_id = data["login_id"]
13
- if getattr(args, "no_wait_login", False):
14
- render_output(
15
- args,
16
- {
17
- "status": "pending",
18
- "login_id": login_id,
19
- "login_url": data["login_url"],
20
- "poll_interval": data.get("poll_interval", 2),
21
- "next_action": "ask_user_to_open_url",
22
- "message": (
23
- "Ask the user to open login_url in a browser and approve the request. "
24
- "If the user is not already signed in to the console or this link expires, "
25
- "rerun `powerbase auth login --no-wait --json` to generate a fresh login URL. "
26
- "After approval, rerun `powerbase auth status --json` or invoke "
27
- "`powerbase auth login` without `--no-wait` to finish in this session."
28
- ),
29
- },
30
- )
31
- return 0
32
11
  timeout_sec = int(args.login_timeout)
33
12
  if timeout_sec < 0:
34
13
  raise RuntimeError("--timeout must be >= 0 (0 means wait indefinitely).")
35
14
  deadline: float | None = None
36
15
  if timeout_sec > 0:
37
16
  deadline = time.monotonic() + timeout_sec
38
- print(f"Open this URL in your browser:\n{data['login_url']}\n")
39
17
  if deadline is not None:
40
- print(f"Waiting for authorization (timeout {timeout_sec}s)...")
18
+ print(f"Waiting for authorization for login_id {login_id} (timeout {timeout_sec}s)...")
41
19
  else:
42
- print("Waiting for authorization (no timeout)...")
20
+ print(f"Waiting for authorization for login_id {login_id} (no timeout)...")
43
21
  while True:
44
22
  polled = api.poll_cli_login(login_id)
45
23
  status = polled.get("status")
@@ -49,8 +27,9 @@ def handle_auth_login(args: argparse.Namespace) -> int:
49
27
  if remaining <= 0:
50
28
  raise RuntimeError(
51
29
  f"Login timed out after {timeout_sec} seconds without browser approval. "
52
- "Complete login sooner, rerun `powerbase auth login --no-wait --json` to "
53
- "generate a fresh login URL, or pass a larger `--timeout` "
30
+ "Generate a fresh login URL with `powerbase auth login`, ask the user to "
31
+ "approve it in their own browser, then rerun `powerbase auth wait --login-id ...`. "
32
+ "Or pass a larger `--timeout` "
54
33
  "(use `--timeout 0` to wait indefinitely)."
55
34
  )
56
35
  else:
@@ -83,6 +62,32 @@ def handle_auth_login(args: argparse.Namespace) -> int:
83
62
  raise RuntimeError(f"Login failed with status: {status}")
84
63
 
85
64
 
65
+ def handle_auth_login(args: argparse.Namespace) -> int:
66
+ _, _, _, _, api = build_api(args)
67
+ data = api.start_cli_login()
68
+ login_id = data["login_id"]
69
+ render_output(
70
+ args,
71
+ {
72
+ "status": "pending",
73
+ "login_id": login_id,
74
+ "login_url": data["login_url"],
75
+ "poll_interval": data.get("poll_interval", 2),
76
+ "next_action": "ask_user_to_open_url",
77
+ "message": (
78
+ "Return login_url to the user and stop. "
79
+ "Do not open the URL or poll yet. After the user confirms approval, run "
80
+ f"`powerbase auth wait --login-id {login_id} --json`."
81
+ ),
82
+ },
83
+ )
84
+ return 0
85
+
86
+
87
+ def handle_auth_wait(args: argparse.Namespace) -> int:
88
+ return _poll_login_until_approved(args, login_id=args.login_id)
89
+
90
+
86
91
  def handle_auth_status(args: argparse.Namespace) -> int:
87
92
  store, _, _, session_manager, _ = build_api(args)
88
93
  auth = session_manager.get_auth_state()
@@ -138,27 +143,27 @@ def register_auth_commands(subparsers: argparse._SubParsersAction[argparse.Argum
138
143
  )
139
144
  auth_sub = auth.add_subparsers(
140
145
  dest="auth_command",
141
- metavar="{login,status,refresh,logout}",
146
+ metavar="{login,wait,status,refresh,logout}",
142
147
  )
143
148
  p = auth_sub.add_parser(
144
149
  "login",
145
- help="Start browser login.",
150
+ help="Generate browser login URL.",
146
151
  description=(
147
- "Start browser-based login. This prints a login URL, polls until approval in the browser "
148
- "or until --timeout seconds elapse (default 600), then saves the session to "
149
- "~/.config/powerbase/auth.json. Use --timeout 0 to wait without a time limit. "
150
- "Use --no-wait to print the login URL and exit immediately without polling."
152
+ "Start browser login and return login_url plus login_id. "
153
+ "Give the URL to the user. Do not open it or poll yet. "
154
+ "After the user confirms approval, run `powerbase auth wait --login-id ...`."
151
155
  ),
152
156
  )
153
- p.add_argument(
154
- "--no-wait",
155
- dest="no_wait_login",
156
- action="store_true",
157
- help=(
158
- "Return the login URL and exit immediately without polling for approval. "
159
- "Useful for agent-guided flows where the user must open the URL manually."
157
+ p.set_defaults(handler=handle_auth_login)
158
+ p = auth_sub.add_parser(
159
+ "wait",
160
+ help="Poll for browser approval.",
161
+ description=(
162
+ "Poll a previously started browser login by login_id. Run this only after the user "
163
+ "confirms they approved the login request in their own browser."
160
164
  ),
161
165
  )
166
+ p.add_argument("--login-id", required=True, help="Login ID returned by `powerbase auth login`.")
162
167
  p.add_argument(
163
168
  "--timeout",
164
169
  dest="login_timeout",
@@ -170,7 +175,7 @@ def register_auth_commands(subparsers: argparse._SubParsersAction[argparse.Argum
170
175
  "Pass 0 to wait indefinitely."
171
176
  ),
172
177
  )
173
- p.set_defaults(handler=handle_auth_login)
178
+ p.set_defaults(handler=handle_auth_wait)
174
179
  p = auth_sub.add_parser(
175
180
  "status",
176
181
  help="Show current auth status.",
@@ -41,8 +41,9 @@ class SessionManager:
41
41
 
42
42
  def _login_guidance(self) -> str:
43
43
  return (
44
- "Run `powerbase auth login --no-wait --json` to generate a fresh login URL, "
45
- "ask the user to open it in their own browser, and retry after approval."
44
+ "Run `powerbase auth login --json` to generate a fresh login URL, "
45
+ "ask the user to open it in their own browser, and after they confirm approval "
46
+ "run `powerbase auth wait --login-id ... --json`."
46
47
  )
47
48
 
48
49
  def _urlopen(self, req: request.Request):
@@ -29,8 +29,9 @@ class PowerbaseTransport:
29
29
 
30
30
  def _login_guidance(self) -> str:
31
31
  return (
32
- "Run `powerbase auth login --no-wait --json` to generate a fresh login URL, "
33
- "ask the user to open it in their own browser, and retry after approval."
32
+ "Run `powerbase auth login --json` to generate a fresh login URL, "
33
+ "ask the user to open it in their own browser, and after they confirm approval "
34
+ "run `powerbase auth wait --login-id ... --json`."
34
35
  )
35
36
 
36
37
  def _urlopen(self, req: request.Request):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: powerbase-cli
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: CLI for operating Powerbase console workflows
5
5
  Author: Powerbase
6
6
  Requires-Python: >=3.11
@@ -91,6 +91,7 @@ The preferred flow is:
91
91
 
92
92
  ```bash
93
93
  powerbase auth login
94
+ powerbase auth wait --login-id LOGIN_ID
94
95
  ```
95
96
 
96
97
  The CLI now includes a built-in `base_url` and `anon_key` default for this deployment. The test package also bundles this environment's self-signed CA certificate, so most users can start with browser login directly and only use flags or environment variables when overriding that default.
@@ -100,16 +101,14 @@ The bundled CA is a test-only convenience for the current self-signed deployment
100
101
  This will:
101
102
 
102
103
  1. request a CLI login session from Powerbase
103
- 2. print a browser URL
104
- 3. poll until browser approval or until `--timeout` elapses (default **600** seconds, ten minutes)
105
- 4. save the resulting session to `~/.config/powerbase/auth.json`
104
+ 2. return a `login_id` and browser URL
105
+ 3. wait for the user to approve the request in their own browser
106
+ 4. poll with `powerbase auth wait --login-id ...` until approval or until `--timeout` elapses (default **600** seconds, ten minutes)
107
+ 5. save the resulting session to `~/.config/powerbase/auth.json`
106
108
 
107
- Use `--timeout 0` to wait without a time limit. Use a larger value if users need more than ten minutes to complete login.
108
- For agent-guided workflows, prefer `powerbase auth login --no-wait --json` so the CLI returns the `login_url` and exits immediately instead of blocking on polling.
109
- If the browser link expires or the user is not currently signed in to the console, rerun `powerbase auth login --no-wait --json` to generate a fresh login URL before retrying.
110
- If an agent or wrapper script is coordinating the workflow, it is still helpful
111
- to tell the user: after browser approval, return to the current session so the
112
- remaining steps can continue.
109
+ Use `--timeout 0` on `auth wait` to wait without a time limit. Use a larger value if users need more than ten minutes to complete login.
110
+ For agent-guided workflows, run `powerbase auth login --json`, return the `login_url` to the user, stop, and wait for the user to confirm browser approval before running `powerbase auth wait --login-id ... --json`.
111
+ If the browser link expires or the user is not currently signed in to the console, rerun `powerbase auth login --json` to generate a fresh login URL before retrying.
113
112
 
114
113
  ### Manual Token Import
115
114
 
@@ -280,22 +279,24 @@ When Openclaw or another LLM agent uses `powerbase`:
280
279
  - run discovery commands before write operations
281
280
  - set context for long multi-step tasks
282
281
  - use `auth status` before workflows that assume login
283
- - prefer `auth login --no-wait --json` for browser login so the agent can hand `login_url` back to the user
284
- - if a protected command says authentication is missing or expired, rerun `auth login --no-wait --json` to generate a fresh login URL
282
+ - use `auth login --json` to generate a login URL, then stop and hand `login_url` to the user
285
283
  - do not have the agent open the browser login URL itself; the user must complete that approval step
284
+ - after the user confirms approval, run `auth wait --login-id ... --json` to complete login
285
+ - if a protected command says authentication is missing or expired, rerun `auth login --json` to generate a fresh login URL
286
286
  - remember that `--json` overrides a saved `config output text` setting for that command
287
287
 
288
288
  Recommended agent sequence:
289
289
 
290
290
  1. `powerbase auth status --json`
291
- 2. If unauthenticated, or if a protected command reports an auth error, run `powerbase auth login --no-wait --json`, return the `login_url` to the user, and wait for them to approve in the browser
292
- 3. `powerbase context show --json`
293
- 4. If no instance is selected, run `powerbase instance list --json`
294
- 5. If no suitable instance exists, prefer `powerbase instance create --name ... --org-id ... --json`
295
- 6. Use `powerbase database ...` only for the advanced bring-your-own-database path
296
- 7. Set context with `powerbase context use-instance ...`
297
- 8. If you want the sandbox agent preview on a non-main branch, run `powerbase branch switch ...`
298
- 9. Continue with `branch`, `sql`, `publish`, `sandbox files`, or `agent` commands
291
+ 2. If unauthenticated, or if a protected command reports an auth error, run `powerbase auth login --json` and return the `login_url` plus `login_id` to the user
292
+ 3. After the user confirms browser approval, run `powerbase auth wait --login-id LOGIN_ID --json`
293
+ 4. `powerbase context show --json`
294
+ 5. If no instance is selected, run `powerbase instance list --json`
295
+ 6. If no suitable instance exists, prefer `powerbase instance create --name ... --org-id ... --json`
296
+ 7. Use `powerbase database ...` only for the advanced bring-your-own-database path
297
+ 8. Set context with `powerbase context use-instance ...`
298
+ 9. If you want the sandbox agent preview on a non-main branch, run `powerbase branch switch ...`
299
+ 10. Continue with `branch`, `sql`, `publish`, `sandbox files`, or `agent` commands
299
300
 
300
301
  ## Testing
301
302
 
@@ -12,6 +12,7 @@ from unittest import mock
12
12
  sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
13
13
 
14
14
  from powerbase_cli.commands.auth import handle_auth_login as auth_handle_auth_login
15
+ from powerbase_cli.commands.auth import handle_auth_wait as auth_handle_auth_wait
15
16
  from powerbase_cli.commands.agent import handle_agent_chat as agent_handle_agent_chat
16
17
  from powerbase_cli.commands.shared import resolve_config as shared_resolve_config
17
18
  from powerbase_cli.config import (
@@ -37,16 +38,16 @@ class FakeApiPending:
37
38
  return {"status": "pending", "poll_interval": 2}
38
39
 
39
40
 
40
- class FakeApiNoWait:
41
+ class FakeApiStartOnly:
41
42
  def start_cli_login(self):
42
43
  return {
43
- "login_id": "login-nowait",
44
- "login_url": "https://console.example.com/cli-auth/login-nowait",
44
+ "login_id": "login-start",
45
+ "login_url": "https://console.example.com/cli-auth/login-start",
45
46
  "poll_interval": 2,
46
47
  }
47
48
 
48
49
  def poll_cli_login(self, login_id: str):
49
- raise AssertionError("poll_cli_login should not be called when --no-wait is set")
50
+ raise AssertionError("poll_cli_login should not be called by auth login")
50
51
 
51
52
 
52
53
  class FakeApi:
@@ -120,14 +121,14 @@ class CliCommandTests(unittest.TestCase):
120
121
  anon_key=None,
121
122
  json=True,
122
123
  login_timeout=300,
123
- no_wait_login=False,
124
+ login_id="login-1",
124
125
  insecure=False,
125
126
  )
126
127
 
127
128
  with mock.patch("powerbase_cli.commands.auth.build_api", return_value=(store, config, None, None, FakeApi())):
128
129
  with mock.patch("powerbase_cli.commands.auth.time.sleep", return_value=None):
129
130
  with mock.patch("sys.stdout", new=StringIO()):
130
- exit_code = auth_handle_auth_login(args)
131
+ exit_code = auth_handle_auth_wait(args)
131
132
 
132
133
  self.assertEqual(exit_code, 0)
133
134
  saved = store.load_auth()
@@ -135,7 +136,7 @@ class CliCommandTests(unittest.TestCase):
135
136
  self.assertEqual(saved.session.access_token, "new-access")
136
137
  self.assertEqual(saved.user["id"], "user-1")
137
138
 
138
- def test_auth_login_no_wait_returns_login_url_without_polling(self) -> None:
139
+ def test_auth_login_returns_login_url_without_polling(self) -> None:
139
140
  with tempfile.TemporaryDirectory() as temp_dir:
140
141
  store = ConfigStore(Path(temp_dir))
141
142
  config = AppConfig(base_url="https://console.example.com", anon_key="anon")
@@ -144,24 +145,23 @@ class CliCommandTests(unittest.TestCase):
144
145
  base_url=None,
145
146
  anon_key=None,
146
147
  json=True,
147
- login_timeout=300,
148
- no_wait_login=True,
149
148
  insecure=False,
150
149
  )
151
150
 
152
- with mock.patch("powerbase_cli.commands.auth.build_api", return_value=(store, config, None, None, FakeApiNoWait())):
151
+ with mock.patch("powerbase_cli.commands.auth.build_api", return_value=(store, config, None, None, FakeApiStartOnly())):
153
152
  with mock.patch("sys.stdout", new=StringIO()) as stdout:
154
153
  exit_code = auth_handle_auth_login(args)
155
154
 
156
155
  self.assertEqual(exit_code, 0)
157
156
  payload = json.loads(stdout.getvalue())
158
157
  self.assertEqual(payload["status"], "pending")
159
- self.assertEqual(payload["login_id"], "login-nowait")
158
+ self.assertEqual(payload["login_id"], "login-start")
160
159
  self.assertEqual(payload["next_action"], "ask_user_to_open_url")
161
160
  self.assertIn("login_url", payload)
161
+ self.assertIn("powerbase auth wait --login-id login-start --json", payload["message"])
162
162
  self.assertIsNone(store.load_auth())
163
163
 
164
- def test_auth_login_times_out(self) -> None:
164
+ def test_auth_wait_times_out(self) -> None:
165
165
  clock = {"t": 0.0}
166
166
 
167
167
  def fake_monotonic() -> float:
@@ -179,7 +179,7 @@ class CliCommandTests(unittest.TestCase):
179
179
  anon_key=None,
180
180
  json=False,
181
181
  login_timeout=5,
182
- no_wait_login=False,
182
+ login_id="login-pending",
183
183
  insecure=False,
184
184
  )
185
185
 
@@ -188,7 +188,7 @@ class CliCommandTests(unittest.TestCase):
188
188
  with mock.patch("powerbase_cli.commands.auth.time.sleep", fake_sleep):
189
189
  with mock.patch("sys.stdout", new=StringIO()):
190
190
  with self.assertRaises(RuntimeError) as ctx:
191
- auth_handle_auth_login(args)
191
+ auth_handle_auth_wait(args)
192
192
 
193
193
  self.assertIn("timed out", str(ctx.exception).lower())
194
194
  self.assertIn("5", str(ctx.exception))
@@ -22,13 +22,22 @@ class CliHelpTests(unittest.TestCase):
22
22
  self.assertIn("--insecure", help_text)
23
23
  self.assertIn("--ca-cert", help_text)
24
24
 
25
- def test_auth_login_help_mentions_timeout(self) -> None:
25
+ def test_auth_login_help_mentions_wait_follow_up(self) -> None:
26
26
  parser = build_parser()
27
27
  auth_parser = parser._subparsers._group_actions[0].choices["auth"]
28
28
  login_parser = auth_parser._subparsers._group_actions[0].choices["login"]
29
29
  help_text = login_parser.format_help()
30
+ self.assertIn("login_id", help_text)
31
+ self.assertIn("Do not open", help_text)
32
+ self.assertIn("powerbase auth wait", help_text)
33
+
34
+ def test_auth_wait_help_mentions_timeout(self) -> None:
35
+ parser = build_parser()
36
+ auth_parser = parser._subparsers._group_actions[0].choices["auth"]
37
+ wait_parser = auth_parser._subparsers._group_actions[0].choices["wait"]
38
+ help_text = wait_parser.format_help()
39
+ self.assertIn("--login-id", help_text)
30
40
  self.assertIn("--timeout", help_text)
31
- self.assertIn("--no-wait", help_text)
32
41
  self.assertIn("600", help_text)
33
42
 
34
43
  def test_auth_help_does_not_list_token_set_subcommand(self) -> None:
@@ -38,7 +38,8 @@ class SessionManagerTests(unittest.TestCase):
38
38
  manager.refresh()
39
39
 
40
40
  self.assertIn("No authentication session available", str(ctx.exception))
41
- self.assertIn("powerbase auth login --no-wait --json", str(ctx.exception))
41
+ self.assertIn("powerbase auth login --json", str(ctx.exception))
42
+ self.assertIn("powerbase auth wait --login-id ... --json", str(ctx.exception))
42
43
 
43
44
  def test_refresh_updates_saved_auth_file(self) -> None:
44
45
  with tempfile.TemporaryDirectory() as temp_dir:
@@ -47,7 +47,8 @@ class PowerbaseTransportTests(unittest.TestCase):
47
47
 
48
48
  self.assertEqual(ctx.exception.status, 401)
49
49
  self.assertIn("No authentication session available", str(ctx.exception))
50
- self.assertIn("powerbase auth login --no-wait --json", str(ctx.exception))
50
+ self.assertIn("powerbase auth login --json", str(ctx.exception))
51
+ self.assertIn("powerbase auth wait --login-id ... --json", str(ctx.exception))
51
52
  self.assertEqual(urlopen_mock.call_count, 0)
52
53
 
53
54
  def test_invoke_uses_unverified_tls_context_when_insecure(self) -> None:
@@ -182,7 +183,8 @@ class PowerbaseTransportTests(unittest.TestCase):
182
183
  transport.invoke("instances", method="GET")
183
184
 
184
185
  self.assertEqual(ctx.exception.status, 401)
185
- self.assertIn("powerbase auth login --no-wait --json", str(ctx.exception))
186
+ self.assertIn("powerbase auth login --json", str(ctx.exception))
187
+ self.assertIn("powerbase auth wait --login-id ... --json", str(ctx.exception))
186
188
  self.assertEqual(refresh_mock.call_count, 0)
187
189
  self.assertEqual(urlopen_mock.call_count, 1)
188
190
 
File without changes