Skip to content

feat(users): add clerk users list subcommand#237

Draft
wyattjoh wants to merge 6 commits intomainfrom
wyattjoh/users-list
Draft

feat(users): add clerk users list subcommand#237
wyattjoh wants to merge 6 commits intomainfrom
wyattjoh/users-list

Conversation

@wyattjoh
Copy link
Copy Markdown
Contributor

@wyattjoh wyattjoh commented Apr 27, 2026

Summary

Adds clerk users list, the read side of the clerk users family. Lists users from the target instance with first-class flags for the filters Clerk's Backend API exposes on GET /v1/users: --limit, --offset, --query, repeatable (or comma-separated) --email-address / --phone-number / --username / --user-id / --external-id, and --order-by over Clerk's common user ordering fields with optional + / - prefix. Anything beyond that stays out of scope and remains accessible via clerk api.

In human mode the command renders a concise table (name, user ID, primary identifier) and a row count footer. --json and agent mode emit the full Backend API response body to stdout for piping. The network read is wrapped in the standard Fetching users... spinner.

The list action is also registered against the clerk users action registry so it appears in the top-level interactive menu alongside create. When invoked without a linked project, env var, or targeting flag in human mode, list now mirrors users create and pops the shared application picker so an unlinked user can choose an instance interactively. Direct invocation paths (--secret-key, CLERK_SECRET_KEY, --app, linked project) keep their original fast resolution. Agent mode preserves the original NO_SECRET_KEY usage error.

When the table is rendered inside the menu's intro/outro block, rows route to stderr so the gutter prefix () is applied consistently with the surrounding UI. Direct invocation continues to print the table to stdout for piping.

Test plan

  • bun run format:check
  • bun run lint
  • bun run typecheck
  • bun run test
  • bun run test:e2e:op
  • Reviewer: spot-check clerk users list --help and confirm the filter / pagination / sort flags behave as documented
  • Reviewer: drive the interactive clerk users menu with no project linked, confirm List → picker → instance selection → table inside the gutter

@wyattjoh
Copy link
Copy Markdown
Contributor Author

wyattjoh commented Apr 27, 2026

Stack: wyattjoh/users-list

Part of a stacked PR chain. Do not merge manually.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 27, 2026

🦋 Changeset detected

Latest commit: 35d2af5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
clerk Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@wyattjoh wyattjoh changed the title wyattjoh/users list feat(users): add clerk users list subcommand Apr 27, 2026
@wyattjoh wyattjoh force-pushed the wyattjoh/users-list branch 3 times, most recently from bd40ab6 to 100ee59 Compare April 27, 2026 21:02
Base automatically changed from wyattjoh/users-scaffolding-and-create to main April 27, 2026 21:44
Comment thread packages/cli-core/src/test/integration/users-commands.test.ts Dismissed
List users from the target instance with pagination, query search,
repeatable identifier filters, and order-by support. Human mode prints a
compact table; agent mode and `--json` return the raw BAPI response.
Mirror `users create`: when invoked without a linked project, env var, or
targeting flag, pop the shared application picker in human mode. Inside
the menu's intro/outro block, route table rows to stderr so the gutter
prefix is applied consistently.
…ields

Drop web3wallet, updated_at, and last_active_at from the --order-by
choice list. Keeps the five identifier fields rendered in the users
list table plus created_at and last_sign_in_at, the two timestamps
users actually sort by even though they aren't displayed.
The list, search-by-email, and `jq`-pipe scripting examples in the bundled clerk skill's `recipes.md` defaulted to raw `clerk api /users[?...]` calls. With `clerk users list` available, switch them to the curated command (with `--json` for the pipe forms) so agents reach for the dedicated subcommand by default. Count, fetch, update, and lifecycle recipes stay on raw API since their curated subcommands are still upstack.
Both the `users` parent command and its `list` subcommand define
`--secret-key` / `--app` / `--instance`. When a subcommand redefines an
option already set on its parent, commander attributes the parsed value
to the parent's option object, so a child's bare `cmd.opts()` returns
empty for those keys. The list action handler relied on commander's
default invocation (which passes only local opts), so `clerk users list
--app <id>` and `clerk users --app <id>` (interactive menu) silently
dropped the targeting flags and fell through to the no-secret-key error,
even though the documented usage in `users/README.md` includes both.

Mirror the create subcommand's wiring: replace the bare `.action(handler)`
with `.action((_opts, cmd) => handler(cmd.optsWithGlobals()))` for both
the `users` parent menu action and the `users list` action. `create`
already uses this pattern and works correctly.

Adds an integration test covering the regression: `clerk users list
--app app_1 --instance development` resolves the secret key via the
Platform API without a linked project, then issues the BAPI list call.
@wyattjoh wyattjoh force-pushed the wyattjoh/users-list branch from 60021bc to 13bc1e2 Compare April 27, 2026 21:50
@wyattjoh wyattjoh marked this pull request as ready for review April 27, 2026 21:50
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3893c054-b651-4ff4-88e9-7f7a741d8a3f

📥 Commits

Reviewing files that changed from the base of the PR and between 13bc1e2 and 35d2af5.

📒 Files selected for processing (2)
  • packages/cli-core/src/commands/users/list.test.ts
  • packages/cli-core/src/commands/users/list.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/cli-core/src/commands/users/list.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/cli-core/src/commands/users/list.ts

📝 Walkthrough

Walkthrough

Adds a new clerk users list CLI command with options for JSON output, pagination (--limit, --offset), free-text --query, repeatable filters (--email-address, --phone-number, --username, --user-id, --external-id), and --order-by with supported user fields. Implements option parsing and validation, request construction against GET /v1/users (including multi-value query params), secret-key resolution with an interactive instance picker fallback in human mode, table and JSON output paths, logging gutter awareness, tests (unit and integration), and documentation/changeset updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a new clerk users list subcommand to the CLI, which aligns with the comprehensive changeset covering command implementation, tests, and documentation.
Description check ✅ Passed The description thoroughly explains the feature, its flags, behavior in different modes, interactive menu integration, credential resolution strategy, and table routing to stderr within the menu context, all of which directly relate to the changeset provided.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli-core/src/commands/users/list.ts`:
- Around line 155-157: The current catch branch treats any
ERROR_CODE.NO_SECRET_KEY as OK to call resolveUsersInstanceContext (involving
resolveUsersInstanceContext and returning ctx.secretKey), which causes explicit
invocations with --app/--instance to fall into interactive picker; change the
condition around isHuman() && error instanceof CliError && error.code ===
ERROR_CODE.NO_SECRET_KEY to only perform the interactive fallback when the user
did NOT explicitly target an instance/app (i.e., ensure
options.instance/options.app are falsy), and otherwise rethrow or propagate the
CliError so targeted runs do not trigger resolveUsersInstanceContext; update the
logic surrounding resolveUsersInstanceContext and the error handling to reflect
this intent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 865fcf59-6d62-40a4-8b4a-d5b514d2e355

📥 Commits

Reviewing files that changed from the base of the PR and between 5784df6 and 13bc1e2.

📒 Files selected for processing (10)
  • .changeset/users-list.md
  • packages/cli-core/src/cli-program.test.ts
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/commands/users/README.md
  • packages/cli-core/src/commands/users/index.ts
  • packages/cli-core/src/commands/users/list.test.ts
  • packages/cli-core/src/commands/users/list.ts
  • packages/cli-core/src/lib/log.ts
  • packages/cli-core/src/test/integration/users-commands.test.ts
  • skills/clerk/references/recipes.md

Comment thread packages/cli-core/src/commands/users/list.ts Outdated
`clerk users list` would silently switch applications if a user passed
`--app <id>` (or other explicit targeting) and the resolved instance had
no secret key — `resolveBapiSecretKey` threw NO_SECRET_KEY, and the catch
opened the picker without preserving the explicit target. Surface the
original error in those cases; only fall back to the picker when no
target was provided.
@wyattjoh wyattjoh marked this pull request as draft April 28, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants