Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/users-scaffolding-and-create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"clerk": minor
---

Add `clerk users` command scaffolding with `clerk users create`, plus an interactive mode for the `users` family. The create wizard reads instance settings from the Frontend API to prompt only for enabled fields, marking required ones. A top-level interactive menu (`clerk users` with no subcommand) routes to registered actions; agent mode preserves the strict flag-driven contract. The application picker (used by `clerk link` and the `clerk users` wizard fallback) now lists the "Create a new application" option at the bottom and de-emphasizes it until highlighted, so it reads as a fallback rather than a primary choice.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# E2E HAR output
test/e2e/.har

# Local planning/spec docs
docs/superpowers/
187 changes: 6 additions & 181 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ Clerk CLI

Options:
-v, --version Output the version number
--input-json <json> Pass command options as a JSON string, @file.json, or - for stdin
--input-json <json> Pass command options as a JSON string, @file.json, or -
for stdin
--mode <mode> Force interaction mode (human or agent). Defaults to
auto-detect based on TTY.
--verbose Show detailed output (enables debug messages)
Expand All @@ -34,194 +35,18 @@ Options:
Commands:
init [options] Initialize Clerk in your project
auth Manage authentication
login|signup Log in to your Clerk account
logout|signout Log out of your Clerk account
link [options] Link this project to a Clerk application
unlink [options] Unlink this project from its Clerk application
whoami Show the current logged-in user
open Open Clerk resources in your browser
dashboard [options] [subpath] Open the linked app's dashboard
apps Manage your Clerk applications
list [options] List your Clerk applications
create [options] <name> Create a new Clerk application
config Manage instance configuration
pull [options] Pull instance configuration from Clerk
schema [options] Pull instance config schema from Clerk
patch [options] Partially update instance configuration (PATCH)
put [options] Replace entire instance configuration (PUT)
users Manage Clerk users
env Manage environment variables
pull [options] Pull environment variables from Clerk to .env.local
config Manage instance configuration
api [options] [endpoint] [filter] Make authenticated requests to the Clerk API
ls [filter] List available API endpoints
(no args) Interactive request builder (TTY only)
doctor [options] Check your project's Clerk integration health
skill Manage the bundled Clerk CLI agent skill
install [options] Install the bundled clerk agent skill
switch-env [environment] Switch the active Clerk CLI environment
completion [shell] Generate shell autocompletion script
skill Manage the bundled Clerk CLI agent skill
update [options] Update the Clerk CLI to the latest version

Give AI agents better Clerk context: install the Clerk skills
$ clerk skill install

clerk init
--framework <name> Framework to set up (skips auto-detection)
--pm <manager> Package manager to use (skips prompt/auto-detection)
--name <project-name> Project name for --starter (skips prompt)
--app <id> Application ID to link (skips interactive picker)
--starter Bootstrap a new project from a starter template
--prompt Output a prompt for an AI agent to integrate Clerk
--yes Skip confirmation prompts
--no-skills Skip the optional agent skills install prompt
Examples:
$ clerk init Auto-detect framework and set up Clerk
$ clerk init --framework next Set up for Next.js (skips detection)
$ clerk init --app app_123 Link to a specific Clerk application
$ clerk init --starter Create a new project with Clerk
$ clerk init --starter --framework next --pm bun Bootstrap with Bun
$ clerk init --prompt Output a setup prompt for an AI agent
$ clerk init -y Skip all confirmation prompts
$ clerk init --no-skills Skip the agent skills install prompt

clerk auth login Log in via browser (OAuth)
clerk auth logout Remove stored credentials

clerk link
--app <id> Application ID to link (skips interactive picker)
Examples:
$ clerk link Pick an app interactively
$ clerk link --app app_abc123 Link directly by application ID

clerk unlink
--yes Skip confirmation prompt
Examples:
$ clerk unlink Unlink with confirmation prompt
$ clerk unlink --yes Skip confirmation

clerk whoami Show your email address

clerk open [subpath]
--print Print the URL without opening the browser
Examples:
$ clerk open Open the linked app's dashboard
$ clerk open users Open the users page
$ clerk open api-keys Open the API keys page
$ clerk open --print Print the dashboard URL

clerk config pull
--app <id> Application ID to target (works from any directory)
--instance <id> Instance to target (dev, prod, or a full instance ID)
--output <file> Write config to a file instead of stdout
Examples:
$ clerk config pull Print dev config to stdout
$ clerk config pull --instance prod Pull production config
$ clerk config pull --output config.json Save config to a file

clerk config schema
--app <id> Application ID to target (works from any directory)
--instance <id> Instance to target (dev, prod, or a full instance ID)
--output <file> Write schema to a file instead of stdout
--keys <keys...> Config keys to retrieve schema for
Examples:
$ clerk config schema Print full config schema
$ clerk config schema --keys social_login Schema for specific keys
$ clerk config schema --output schema.json Save schema to a file

clerk config patch
--app <id> Application ID to target (works from any directory)
--instance <id> Instance to target (dev, prod, or a full instance ID)
--file <path> Read config JSON from a file
--json <string> Pass config JSON inline
--dry-run Show what would be sent without making the API call
--yes Skip confirmation prompts
Examples:
$ clerk config patch --file config.json Apply partial update from file
$ clerk config patch --json '{"key":"value"}' Inline JSON patch
$ clerk config patch --file config.json --dry-run Preview without applying
$ clerk config patch --instance prod --file config.json Patch production config

clerk config put
--app <id> Application ID to target (works from any directory)
--instance <id> Instance to target (dev, prod, or a full instance ID)
--file <path> Read config JSON from a file
--json <string> Pass config JSON inline
--dry-run Show what would be sent without making the API call
--yes Skip confirmation prompts
Examples:
$ clerk config put --file config.json Replace entire config from file
$ clerk config put --file config.json --dry-run Preview the replacement
$ clerk config put --instance prod --file config.json Replace production config
$ clerk config put --file config.json --yes Skip confirmation prompt

clerk env pull
--app <id> Application ID to target (works from any directory)
--instance <id> Instance to target (dev, prod, or a full instance ID)
--file <path> Target env file (default: auto-detect)
Examples:
$ clerk env pull Pull dev keys to .env.local
$ clerk env pull --instance prod Pull production keys
$ clerk env pull --file .env Write to a specific file
$ clerk env pull --app app_abc123 Target a specific application

clerk api [endpoint] [filter]
-X, --method <method> HTTP method (default: GET, or POST if body provided)
-d, --data <json> JSON request body
--file <path> Read request body from a file
--include Show response headers
--app <id> Application ID to target when resolving keys
--secret-key <key> Override the secret key
--instance <id> Instance to target (dev, prod, or instance ID)
--platform Use Platform API instead of Backend API
--dry-run Show the request without executing it
--yes Skip confirmation for mutating requests
Examples:
$ clerk api ls List all available endpoints
$ clerk api ls users List endpoints matching "users"
$ clerk api /users GET /v1/users
$ clerk api /users -d '{"first_name":"Alice"}' POST with a JSON body

clerk api ls [filter] List available API endpoints
clerk api Interactive request builder (TTY only)

clerk apps list
--json Output as JSON

clerk apps create <name>
--json Output as JSON
Examples:
$ clerk apps create "My App" Create a new application
$ clerk apps create "My App" --json Output as JSON

clerk doctor
--verbose Show detailed output for each check
--json Output results as JSON
--spotlight Only show warnings and failures
--fix Attempt to auto-fix issues
Examples:
$ clerk doctor Run all health checks
$ clerk doctor --verbose Show detailed output for each check
$ clerk doctor --json Output results as machine-readable JSON
$ clerk doctor --fix Auto-fix detected issues
$ clerk doctor --spotlight Only show warnings and failures

clerk skill install
-y, --yes Skip prompts and run the `skills` CLI unattended
--pm <manager> Package manager hint for runner detection
Examples:
$ clerk skill install Install with an interactive runner picker
$ clerk skill install -y Install unattended
$ clerk skill install --pm bun Force bunx as the runner

clerk completion <shell>
shell: bash, zsh, fish, powershell

clerk update
--channel <tag> Release channel to update to (e.g. latest, canary)
-y, --yes Skip confirmation prompt
--all Update every clerk install found on PATH, not just the first
Examples:
$ clerk update Update to the latest stable release
$ clerk update --channel canary Update to the latest canary release
$ clerk update --yes Update without confirmation prompt
$ clerk update --all Update every clerk install on PATH
help [command] Display help for command
```
9 changes: 7 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/cli-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"yaml": "^2.8.3"
},
"devDependencies": {
"@clerk/shared": "^4.8.3",
"@types/semver": "^7.7.1"
}
}
56 changes: 56 additions & 0 deletions packages/cli-core/src/cli-program.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,62 @@ import { dirname, join } from "node:path";
import { createProgram, formatApiBody } from "./cli-program.ts";
import { STANDARD_AGENT_DIRS, EXTRA_REL_PATHS } from "./lib/skill-detection.ts";

test("registers users as a top-level command", () => {
const program = createProgram();
const users = program.commands.find((command) => command.name() === "users");
expect(users).toBeDefined();
});

test("registers users create as a subcommand", () => {
const program = createProgram();
const users = program.commands.find((command) => command.name() === "users")!;
const names = users.commands.map((command) => command.name());

expect(names).toContain("create");
});

test("users create exposes --json output, curated flags, and -d/--data for inline request bodies", () => {
const program = createProgram();
const users = program.commands.find((command) => command.name() === "users")!;
const create = users.commands.find((command) => command.name() === "create")!;
const optionNames = create.options.map((option) => option.long);

expect(optionNames).toEqual(
expect.arrayContaining([
"--json",
"--email",
"--phone",
"--username",
"--password",
"--first-name",
"--last-name",
"--external-id",
"--data",
"--file",
"--dry-run",
"--yes",
]),
);
});

test("users parent command exposes targeting flags inherited by subcommands", () => {
const program = createProgram();
const users = program.commands.find((command) => command.name() === "users")!;
const optionNames = users.options.map((option) => option.long);

expect(optionNames).toEqual(expect.arrayContaining(["--secret-key", "--app", "--instance"]));
});

test("users create documents -d and --file for raw BAPI request bodies", () => {
const program = createProgram();
const users = program.commands.find((command) => command.name() === "users")!;
const create = users.commands.find((command) => command.name() === "create")!;
const help = create.helpInformation();

expect(help).toContain("-d, --data");
expect(help).toContain("--file");
});

describe("formatApiBody", () => {
// --- Single error with meta ---

Expand Down
Loading
Loading