{"id":48921062,"url":"https://github.com/clerk/protect-cli","last_synced_at":"2026-04-17T05:02:02.114Z","repository":{"id":335591347,"uuid":"1143454713","full_name":"clerk/protect-cli","owner":"clerk","description":"Clerk's command line tool (Early Access)","archived":false,"fork":false,"pushed_at":"2026-03-24T06:36:16.000Z","size":303,"stargazers_count":6,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-14T22:13:14.671Z","etag":null,"topics":["clerk","cli"],"latest_commit_sha":null,"homepage":"https://github.com/clerk/cli","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clerk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-27T15:50:07.000Z","updated_at":"2026-03-27T11:53:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"361ef508-01ce-429e-84d8-a30f57f4b368","html_url":"https://github.com/clerk/protect-cli","commit_stats":null,"previous_names":["clerk/cli"],"tags_count":86,"template":false,"template_full_name":null,"purl":"pkg:github/clerk/protect-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clerk%2Fprotect-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clerk%2Fprotect-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clerk%2Fprotect-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clerk%2Fprotect-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clerk","download_url":"https://codeload.github.com/clerk/protect-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clerk%2Fprotect-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31915900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clerk","cli"],"created_at":"2026-04-17T05:00:51.311Z","updated_at":"2026-04-17T05:02:02.092Z","avatar_url":"https://github.com/clerk.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Clerk CLI\n\n\u003e **Early Access** — This CLI is under active development and not yet officially supported. We'd love your feedback! Please open an issue or reach out with suggestions.\n\nA command-line interface for managing your Clerk instances. This CLI provides tools for managing users, organizations, sessions, domains, Clerk Protect, and more.\n\n## Installation\n\nFrom Homebrew:\n\n```bash\n## new install:\nbrew tap clerk/cli git@github.com:clerk/cli.git \u0026\u0026 brew install clerk\n\n## or to update:\nbrew update \u0026\u0026 brew upgrade clerk\n\n```\n\nFrom NPX:\n\n```\nnpx --yes github:clerk/cli@latest [command] [options]\n```\n\nBuild from source:\n\n```bash\ngo build -o clerk ./cmd/clerk\n```\n\n## Quick Start\n\n### Interactive Setup\n\nRun the setup wizard to configure your first profile:\n\n```bash\nclerk init\n```\n\nThis will guide you through:\n- Entering your Clerk Secret Key (find it in the [Clerk Dashboard](https://dashboard.clerk.com) → API Keys)\n- Optionally creating a named profile\n\n### Manual Setup\n\nAlternatively, create a profile directly:\n\n```bash\nclerk config profile create default --api-key sk_live_xxxxx\n```\n\n### Verify Configuration\n\n```bash\nclerk whoami\n```\n\n### Start Using Commands\n\n```bash\nclerk users list\nclerk protect rules list SIGN_IN\n```\n\nIf you run a command without an API key configured, the CLI will prompt you to enter one in interactive terminals.\n\n---\n\n## Global Options\n\nThese options can be used with any command:\n\n| Option | Description |\n|--------|-------------|\n| `-p, --profile \u003cname\u003e` | Use a specific profile |\n| `-o, --output \u003cformat\u003e` | Output format: `table`, `json`, or `yaml` (default: `table`) |\n| `--dotenv` | Use `CLERK_SECRET_KEY` from `.env` file (see [Project-Level Configuration](#project-level-configuration-env-files)) |\n| `--debug` | Enable debug mode (outputs HTTP requests to stderr) |\n| `-h, --help` | Display colorized help |\n\nHelp output is automatically colorized when running in an interactive terminal. You can control this behavior with environment variables:\n- `NO_COLOR=1` - Disable colors\n- `FORCE_COLOR=1` - Force colors even in non-interactive mode\n\n```bash\n# Output as JSON\nclerk -o json protect rules list SIGN_IN\n\n# Output as YAML\nclerk --output yaml users get user_abc123\n\n# Combine options\nclerk --profile staging -o json protect rules list\n```\n\n---\n\n## Command Shortcuts\n\n### Prefix Matching\n\nYou can abbreviate commands as long as they're unambiguous:\n\n```bash\nclerk prot rul list SIGN_IN    # protect rules list\nclerk conf prof li              # config profile list\nclerk w                         # whoami\nclerk us ls                     # users list\n```\n\nIf a prefix matches multiple commands, an error is shown.\n\n### Command Aliases\n\nCreate custom shortcuts for frequently used commands:\n\n```bash\n# Create aliases\nclerk config alias add prl -- protect rules list\nclerk config alias add pra protect rules add\n\n# Use aliases\nclerk prl SIGN_IN              # expands to: clerk protect rules list SIGN_IN\nclerk pra SIGN_IN -g \"block\"   # expands to: clerk protect rules add SIGN_IN -g \"block\"\n```\n\nSee [`clerk config alias`](#clerk-config-alias) for full documentation.\n\n---\n\n## Global Commands\n\n### `clerk init`\n\nRun the interactive setup wizard to configure the CLI. This is the recommended way to get started.\n\n```bash\nclerk init\n```\n\nThe wizard will prompt you for:\n- Clerk Secret Key\n- Profile name (default: \"default\")\n\nNote: This command requires an interactive terminal.\n\n### `clerk whoami`\n\nDisplay the currently active profile and how it was selected.\n\n```bash\nclerk whoami\n# Active profile: production\n#   (set via CLERK_PROFILE environment variable)\n```\n\n---\n\n## Configuration\n\nThe CLI uses an INI-based configuration system where **profiles** can override **default settings**. Each profile can have its own API key, output format, debug mode, and other settings.\n\n### Configuration Resolution\n\nWhen resolving a setting value, the CLI checks in this order:\n1. Command-line flag (e.g., `--output json`)\n2. Environment variable (e.g., `CLERK_SECRET_KEY`)\n3. `.env` file (for `clerk.key` only, when applicable — see below)\n4. Active profile's value\n5. Default value\n\n### Project-Level Configuration (.env files)\n\nThe CLI can automatically detect and use a `CLERK_SECRET_KEY` from a `.env` file in your project directory. This is useful for development workflows where you want to use project-specific API keys without configuring global profiles.\n\n#### How It Works\n\nWhen you run a command without the `-p` flag, the CLI searches for a `.env` file starting from the current directory and walking up through parent directories. If found, it reads the `CLERK_SECRET_KEY` value.\n\n```bash\n# Example .env file in your project root\nCLERK_SECRET_KEY=sk_test_xxxxx\n```\n\n#### Resolution Priority\n\nThe `.env` file is used as a **fallback** when no profile key is configured:\n\n1. If your profile already has a `clerk.key` configured → profile key is used\n2. If your profile has no key → `.env` file is used automatically\n\nWhen a `.env` file exists but your profile has a key configured, the CLI warns you:\n\n```\n⚠ Found .env file at /path/to/project/.env but using profile key. Use --dotenv to use the .env file instead.\n```\n\n#### Using `--dotenv` Flag\n\nUse the `--dotenv` flag to explicitly use the `.env` file, even when your profile has a key configured:\n\n```bash\n# Force using .env file instead of profile key\nclerk users list --dotenv\n\n# See which key would be used\nclerk whoami --dotenv\n\n# Check config resolution\nclerk config list --dotenv\n```\n\n#### When `.env` Is NOT Used\n\nThe `.env` file is skipped in these cases:\n\n- When `-p \u003cprofile\u003e` flag is specified (explicit profile selection)\n- When `CLERK_SECRET_KEY` environment variable is set (env var takes priority)\n- When `--dotenv` is not specified and the active profile has a key configured\n\n#### Example Workflow\n\n```bash\n# Project structure\nmy-app/\n├── .env                    # Contains CLERK_SECRET_KEY=sk_test_project_key\n└── src/\n\n# In the project directory (no profile key configured)\ncd my-app\nclerk users list            # Uses sk_test_project_key from .env\n\n# With a profile key configured\nclerk config set clerk.key sk_test_profile_key\nclerk users list            # Uses sk_test_profile_key (warns about .env)\nclerk users list --dotenv   # Uses sk_test_project_key from .env\n\n# Using explicit profile\nclerk users list -p staging # Uses staging profile, ignores .env\n```\n\n#### Supported `.env` Format\n\nThe CLI supports standard `.env` file format:\n\n```bash\n# Comments are ignored\nCLERK_SECRET_KEY=sk_test_xxxxx\n\n# Quoted values are supported\nCLERK_SECRET_KEY=\"sk_test_xxxxx\"\nCLERK_SECRET_KEY='sk_test_xxxxx'\n\n# Spaces around = are allowed\nCLERK_SECRET_KEY = sk_test_xxxxx\n```\n\nOnly `CLERK_SECRET_KEY` is read from `.env` files. Other Clerk environment variables (like `CLERK_API_URL`) should be set via profiles or shell environment variables.\n\n### Available Settings\n\n| Setting | Description | Env Var |\n|---------|-------------|---------|\n| `clerk.key` | Clerk secret API key (sk_*) | `CLERK_SECRET_KEY` |\n| `clerk.api.url` | Clerk API URL (default: `https://api.clerk.com`) | `CLERK_API_URL` |\n| `clerk.platform.key` | Clerk Platform API key (ak_*) | `CLERK_PLATFORM_KEY` |\n| `clerk.platform.api.url` | Platform API URL (default: `https://api.clerk.com/v1/platform`) | `CLERK_PLATFORM_API_URL` |\n| `output` | Default output format (`table`, `json`, `yaml`) | |\n| `debug` | Enable debug mode (`true`, `false`) | `CLERK_CLI_DEBUG` |\n| `ai.provider` | AI provider (`openai`, `anthropic`) | |\n| `ai.openai.key` | OpenAI API key | `OPENAI_API_KEY` |\n| `ai.openai.model` | OpenAI model (default: `gpt-4o`) | |\n| `ai.anthropic.key` | Anthropic API key | `ANTHROPIC_API_KEY` |\n| `ai.anthropic.model` | Anthropic model (default: `claude-sonnet-4-20250514`) | |\n| `ai.mcp.config` | Path to MCP servers config file (default: `~/.config/clerk/cli/mcp.json`) | |\n\n---\n\n## Configuration Commands\n\n### `clerk config set \u003ckey\u003e \u003cvalue\u003e [options]`\n\nSet a configuration value. Use `--profile` to set in a specific profile.\n\n| Option | Description |\n|--------|-------------|\n| `-p, --profile \u003cname\u003e` | Set value in a specific profile |\n| `--type \u003ctype\u003e` | Value type: `command` (executes shell command to get value) |\n\n```bash\n# Set default output format\nclerk config set output json\n\n# Set API key in a specific profile\nclerk config set clerk.key sk_live_xxxxx --profile production\n\n# Use a command to fetch the API key from a secrets manager\nclerk config set clerk.key \"op read 'op://Vault/Clerk/api-key'\" --type=command --profile production\n```\n\n### `clerk config get \u003ckey\u003e [options]`\n\nGet a configuration value.\n\n| Option | Description |\n|--------|-------------|\n| `-p, --profile \u003cname\u003e` | Get value for a specific profile |\n| `--resolve` | Execute command-type values to get the actual value |\n\n```bash\nclerk config get output\n# json\n\nclerk config get clerk.key --profile production\n# ****xxxx\n\n# For command-type values, use --resolve to execute\nclerk config get clerk.key --profile production --resolve\n# sk_live_xxxxx\n```\n\n### `clerk config unset \u003ckey\u003e [options]`\n\nRemove a configuration value.\n\n| Option | Description |\n|--------|-------------|\n| `-p, --profile \u003cname\u003e` | Unset from a specific profile |\n\n```bash\nclerk config unset output\nclerk config unset debug --profile development\n```\n\n### `clerk config list [options]`\n\nList all configuration settings and their current values.\n\n| Option | Description |\n|--------|-------------|\n| `-p, --profile \u003cname\u003e` | Show resolved values for a specific profile |\n\n```bash\nclerk config list\n# Profile: default\n#\n# KEY                VALUE                SOURCE\n# clerk.key          sk_te****xxxx        profile\n# clerk.api.url      https://api.clerk…   default\n# output             table                default\n# debug              (not set)            -\n```\n\n### `clerk config path`\n\nShow the configuration file path.\n\n```bash\nclerk config path\n# /Users/you/.config/clerk/cli/profiles\n```\n\n---\n\n### `clerk config profile`\n\nManage CLI profiles. Profiles allow you to switch between different Clerk instances (development, staging, production) with different settings.\n\n#### `clerk config profile list`\n\nList all configured profiles.\n\n```bash\nclerk config profile list\n#    NAME\n# *  default\n#    staging\n#    production\n```\n\n#### `clerk config profile create \u003cname\u003e [options]`\n\nCreate a new profile.\n\n| Option | Description |\n|--------|-------------|\n| `--api-key \u003ckey\u003e` | Clerk secret API key |\n| `--api-url \u003curl\u003e` | Custom API URL |\n\n```bash\n# Basic usage\nclerk config profile create production --api-key sk_live_xxxxx\n\n# With custom API URL\nclerk config profile create staging --api-key sk_test_xxxxx --api-url https://api.staging.clerk.com\n```\n\n#### `clerk config profile update \u003cname\u003e`\n\nUpdate an existing profile. Use `clerk config set` with `--profile` to update individual settings.\n\n```bash\nclerk config set clerk.key sk_live_new_key --profile production\n```\n\n#### `clerk config profile delete \u003cname\u003e`\n\nDelete a profile.\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk config profile delete staging\n```\n\n#### `clerk config profile use \u003cname\u003e`\n\nSet the active profile.\n\n```bash\nclerk config profile use production\n```\n\n#### `clerk config profile show [name]`\n\nShow profile details. If no name is provided, shows the active profile.\n\n```bash\nclerk config profile show production\n# Profile: production\n# clerk.key: ****xxxx\n# clerk.api.url: https://api.clerk.com\n```\n\n#### `clerk config profile path`\n\nDisplay the path to the profiles configuration file.\n\n```bash\nclerk config profile path\n# /Users/you/.config/clerk/cli/profiles\n```\n\n---\n\n### `clerk config alias`\n\nManage command aliases for creating shortcuts to frequently used commands.\n\n#### `clerk config alias add \u003cname\u003e \u003ccommand\u003e`\n\nCreate a command alias. Arguments passed when using the alias are appended to the command.\n\n```bash\nclerk config alias add prl protect rules list\nclerk config alias add pra protect rules add\nclerk config alias add cpl config profile list\n```\n\n#### `clerk config alias remove \u003cname\u003e`\n\nRemove a command alias. Also available as `clerk config alias rm`.\n\n```bash\nclerk config alias remove prl\nclerk config alias rm pra\n```\n\n#### `clerk config alias list`\n\nList all configured aliases. Also available as `clerk config alias ls`.\n\n```bash\nclerk config alias list\n# NAME  COMMAND\n# prl   protect rules list\n# pra   protect rules add\n```\n\n#### `clerk config alias path`\n\nShow the aliases file path.\n\n```bash\nclerk config alias path\n# /Users/you/.config/clerk/cli/aliases.json\n```\n\n#### Using Aliases\n\nWhen you use an alias, any additional arguments are appended:\n\n```bash\n# If prl = \"protect rules list\"\nclerk prl SIGN_IN --limit 5\n# Expands to: clerk protect rules list SIGN_IN --limit 5\n```\n\n#### Suggested Aliases\n\n```bash\nclerk config alias add prl protect rules list\nclerk config alias add pra protect rules add\nclerk config alias add prg protect rules get\nclerk config alias add prd protect rules delete\nclerk config alias add pre protect rules edit\nclerk config alias add prr protect rules reorder\nclerk config alias add prf protect rules flush\nclerk config alias add ps protect schema show\n```\n\n---\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `CLERK_PROFILE` | Profile name to use (overrides the default profile) |\n| `CLERK_SECRET_KEY` | Backend API key - sk_* (overrides profile's API key) |\n| `CLERK_API_URL` | Backend API URL (overrides profile's API URL) |\n| `CLERK_PLATFORM_KEY` | Platform API key - ak_* (for `apps` and `transfers` commands) |\n| `CLERK_PLATFORM_API_URL` | Platform API URL (overrides default) |\n| `CLERK_CLI_DEBUG` | Set to `1` or `true` to enable debug mode |\n| `OPENAI_API_KEY` | OpenAI API key for AI-powered rule generation |\n| `ANTHROPIC_API_KEY` | Anthropic API key for AI-powered rule generation |\n\n### Profile Selection Priority\n\nThe CLI determines which profile to use in this order:\n\n1. `--profile \u003cname\u003e` command-line flag\n2. `CLERK_PROFILE` environment variable\n3. Default profile from configuration file\n4. Falls back to a profile named \"default\"\n\n### Example Usage\n\n```bash\n# Use a specific profile for one command\nclerk --profile staging protect rules list SIGN_IN\n\n# Set profile via environment variable\nexport CLERK_PROFILE=production\nclerk protect rules list SIGN_IN\n\n# Override API key for CI/CD\nCLERK_SECRET_KEY=${{ secrets.CLERK_KEY }} clerk protect rules list SIGN_IN\n```\n\n---\n\n## Clerk Protect Commands\n\nAll protect subcommands accept the following option:\n\n| Option | Description |\n|--------|-------------|\n| `--mcp-config \u003cpath\u003e` | Path to MCP servers config file (overrides profile setting and default) |\n\n### `clerk protect rules`\n\nManage Clerk Protect rules for blocking suspicious authentication attempts.\n\n#### Rulesets\n\nRules are organized into rulesets based on the event type:\n\n| Ruleset | Description |\n|---------|-------------|\n| `ALL` | Rules applied to all event types |\n| `SIGN_IN` | Rules for sign-in authentication attempts |\n| `SIGN_UP` | Rules for new user registrations |\n| `SMS` | Rules for SMS verification requests |\n| `EMAIL` | Rules for email verification requests |\n\n#### `clerk protect rules list [ruleset] [options]`\n\nList all rules in a ruleset. If no ruleset is specified, lists rules from all rulesets.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum number of rules to return |\n| `--after \u003cid\u003e` | Pagination cursor (rule ID to start after) |\n\n```bash\nclerk protect rules list SIGN_IN\n```\n\n#### `clerk protect rules get \u003cruleset\u003e \u003cruleId\u003e`\n\nGet details of a specific rule.\n\n```bash\nclerk protect rules get SIGN_IN rule_abc123\n```\n\n#### `clerk protect rules edit \u003cruleset\u003e \u003cruleId\u003e [options]`\n\nOpen a rule's expression in your preferred editor (`$VISUAL` or `$EDITOR`).\n\n| Option | Description |\n|--------|-------------|\n| `--description \u003ctext\u003e` | Also update the rule description |\n\n```bash\nclerk protect rules edit SIGN_IN rule_abc123\n```\n\nNote: Set the `EDITOR` or `VISUAL` environment variable to use a specific editor (e.g., `export EDITOR=nano`). For GUI editors that detach, use a wait flag (e.g., `export EDITOR=\"code --wait\"`).\n\n#### `clerk protect rules add [ruleset] [options]`\n\nAdd a new rule. If ruleset or expression are not provided and the terminal is interactive, you will be prompted to enter them.\n\n| Option | Description |\n|--------|-------------|\n| `--expression \u003cexpr\u003e` | Rule expression (must evaluate to boolean) |\n| `-g, --generate \u003cdesc\u003e` | Generate expression from natural language using AI |\n| `--action \u003caction\u003e` | Action when expression is true (default: `BLOCK`) |\n| `--description \u003ctext\u003e` | Human-readable description |\n| `--before \u003cid\u003e` | Insert before this rule ID |\n| `--after \u003cid\u003e` | Insert after this rule ID |\n| `--index \u003cn\u003e` | Insert at specific index |\n\n```bash\n# With all options specified\nclerk protect rules add SIGN_IN \\\n  --expression \"ip.privacy.is_vpn == true\" \\\n  --description \"Block VPN users\" \\\n  --action BLOCK\n\n# Interactive mode (will prompt for ruleset, expression, and description)\nclerk protect rules add\n\n# Generate expression from natural language description\nclerk protect rules add SIGN_IN --generate \"block requests from datacenters\"\nclerk protect rules add SIGN_IN -g \"when the bot score is greater than 50%\"\n```\n\n#### `clerk protect rules delete \u003cruleset\u003e \u003cruleId\u003e [-f]`\n\nDelete a specific rule.\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk protect rules delete SIGN_IN rule_abc123\n```\n\n#### `clerk protect rules flush \u003cruleset\u003e [-f]`\n\nDelete all rules in a ruleset.\n\n```bash\nclerk protect rules flush SIGN_IN --force\n```\n\n#### `clerk protect rules reorder \u003cruleset\u003e`\n\nInteractively reorder rules within a ruleset. Rules are evaluated in order from top to bottom.\n\n```bash\nclerk protect rules reorder SIGN_IN\n```\n\nNote: This command requires an interactive terminal.\n\n---\n\n### AI-Powered Rule Generation\n\nThe `--generate` (or `-g`) flag on `clerk protect rules add` uses AI to convert natural language descriptions into valid rule expressions.\n\n#### Configuration\n\nConfigure an AI provider using settings, commands, or environment variables:\n\n```bash\n# Option 1: Using config settings (stores key in plain text)\nclerk config set ai.provider openai\nclerk config set ai.openai.key sk-...\n\n# Option 2: Using a command to fetch from a secret manager (recommended)\nclerk config set ai.provider openai\nclerk config set ai.openai.key \"op read 'op://Vault/OpenAI/api-key'\" --type=command\n\n# Or for Anthropic\nclerk config set ai.provider anthropic\nclerk config set ai.anthropic.key \"vault kv get -field=api_key secret/anthropic\" --type=command\n\n# Option 3: Using environment variables\nexport OPENAI_API_KEY=sk-...\n# or\nexport ANTHROPIC_API_KEY=sk-ant-...\n```\n\nWhen using `--type=command`, the command is executed each time the API key is needed, ensuring you always have fresh credentials.\n\n#### Usage\n\n```bash\n# Generate and create a rule\nclerk protect rules add SIGN_IN --generate \"block requests from datacenters\"\n\n# The CLI will:\n# 1. Fetch the schema for the ruleset\n# 2. Generate an expression using AI\n# 3. Show you the generated expression\n# 4. Ask for confirmation before creating\n```\n\n#### Example Descriptions\n\n- \"block VPN users\"\n- \"requests from Russia or China\"\n- \"when the IP is from a datacenter\"\n- \"high bot scores above 70%\"\n- \"non-US phone numbers with suspicious activity\"\n- \"block if automation score exceeds 50%\"\n\n#### MCP Tool Servers\n\nYou can connect external tool servers using the [Model Context Protocol (MCP)](https://modelcontextprotocol.io) to give the AI access to live data during rule generation. This is useful for lookups that the AI can't do on its own, such as:\n\n- Converting an ASN name (e.g., \"Cloudflare\") to its ASN number\n- Looking up which ASN is announcing a specific IP address\n- Querying domain name registration (WHOIS) data\n- Resolving hostnames or checking IP reputation\n\n##### Configuration\n\nCreate `~/.config/clerk/cli/mcp.json`:\n\n```json\n{\n  \"servers\": {\n    \"asn-lookup\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@example/asn-mcp-server\"]\n    },\n    \"whois\": {\n      \"command\": \"/usr/local/bin/whois-mcp-server\",\n      \"env\": {\n        \"API_KEY\": \"your-api-key\"\n      }\n    }\n  }\n}\n```\n\nEach server entry has:\n\n| Field | Description |\n|-------|-------------|\n| `command` | The executable to run (required) |\n| `args` | Command-line arguments (optional) |\n| `env` | Additional environment variables (optional) |\n\nServers are started as subprocesses using the MCP stdio transport. The CLI discovers available tools from each server at startup and makes them available to the LLM during expression generation and modification.\n\nTo use a different config file, pass `--mcp-config` to any protect subcommand:\n\n```bash\nclerk protect rules add --generate \"block VPNs\" --mcp-config /path/to/mcp.json\n```\n\nYou can also set it per profile:\n\n```bash\nclerk config set ai.mcp.config /path/to/custom/mcp.json --profile production\n```\n\n##### How It Works\n\nWhen MCP servers are configured, the AI can call tools during rule generation:\n\n```\n$ clerk protect rules add SIGN_IN -g \"block traffic from Cloudflare's ASN\"\nLoaded 3 tool(s) from MCP servers\nGenerating expression for: block traffic from Cloudflare's ASN\n\n# The AI calls the asn-lookup tool to resolve \"Cloudflare\" → AS13335\n# Then generates the expression using the resolved number\n\nGenerated expression:\n  ip.asn.number == 13335\n\n? Create rule with this expression? Yes\n```\n\nIf no MCP servers are configured, the AI generates expressions using only the schema and its built-in knowledge — no tools are called. Servers that fail to start are skipped gracefully.\n\n##### Debugging\n\nUse `--debug` or `CLERK_CLI_DEBUG=1` to see MCP tool calls and results:\n\n```bash\nCLERK_CLI_DEBUG=1 clerk protect rules add SIGN_IN -g \"block Cloudflare ASN\"\n# [DEBUG] MCP tool call: resolve_asn({\"name\":\"Cloudflare\"})\n# [DEBUG] MCP tool result: {\"asn\":13335,\"name\":\"Cloudflare, Inc.\",\"country\":\"US\"}\n```\n\n---\n\n### `clerk protect schema`\n\nView expression schemas for rule expressions.\n\n#### `clerk protect schema show [eventType] [options]`\n\nShow the detailed schema for an event type.\n\n| Option | Description |\n|--------|-------------|\n| `--flat` | Show fields as flat dot-notation paths |\n\n```bash\nclerk protect schema show SIGN_IN\nclerk protect schema show SIGN_IN --flat\n```\n\n#### `clerk protect schema list`\n\nList all available event types and their top-level fields.\n\n```bash\nclerk protect schema list\n```\n\n#### `clerk protect schema type [names...]`\n\nShow struct type details. If no type names are specified, lists all available types.\n\n```bash\nclerk protect schema type\nclerk protect schema type ip geo\n```\n\n---\n\n## User Management Commands\n\n### `clerk users`\n\nManage Clerk users - list, create, update, delete, ban, lock, and more. Also available as `clerk user`.\n\n#### `clerk users list [options]`\n\nList all users with optional filtering and pagination.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum number of users to return (default: 10) |\n| `--offset \u003cn\u003e` | Number of users to skip for pagination |\n| `--order-by \u003cfield\u003e` | Sort field (prefix with `-` for desc, `+` for asc) |\n| `--email \u003cemails\u003e` | Filter by email addresses (comma-separated) |\n| `--phone \u003cphones\u003e` | Filter by phone numbers (comma-separated) |\n| `--username \u003cusernames\u003e` | Filter by usernames (comma-separated) |\n| `--external-id \u003cids\u003e` | Filter by external IDs (comma-separated) |\n| `--user-id \u003cids\u003e` | Filter by user IDs (comma-separated) |\n| `--organization-id \u003cids\u003e` | Filter by organization membership (comma-separated) |\n| `--query \u003ctext\u003e` | Search across email, phone, username, name, user ID |\n| `--last-active-since \u003ctimestamp\u003e` | Filter users active since this Unix timestamp |\n\n```bash\nclerk users list\nclerk users list --limit 50 --offset 100\nclerk users list --query \"john\"\nclerk users list --email john@example.com\nclerk users list --order-by -last_active_at\n```\n\n#### `clerk users count [options]`\n\nGet total user count with optional filtering.\n\n| Option | Description |\n|--------|-------------|\n| `--email \u003cemail\u003e` | Filter by email |\n| `--phone \u003cphone\u003e` | Filter by phone |\n| `--query \u003ctext\u003e` | Search query |\n\n```bash\nclerk users count\nclerk users count --query \"example.com\"\n```\n\n#### `clerk users get \u003cuserId\u003e`\n\nGet detailed information about a specific user.\n\n```bash\nclerk users get user_2abc123def456\n```\n\n#### `clerk users create [options]`\n\nCreate a new user.\n\n| Option | Description |\n|--------|-------------|\n| `--email \u003cemails\u003e` | Email addresses (comma-separated) |\n| `--phone \u003cphones\u003e` | Phone numbers (comma-separated) |\n| `--username \u003cusername\u003e` | Username |\n| `--first-name \u003cname\u003e` | First name |\n| `--last-name \u003cname\u003e` | Last name |\n| `--password \u003cpassword\u003e` | Password |\n| `--external-id \u003cid\u003e` | External ID |\n| `--public-metadata \u003cjson\u003e` | Public metadata (JSON) |\n| `--private-metadata \u003cjson\u003e` | Private metadata (JSON) |\n| `--skip-password-checks` | Skip password complexity validation |\n| `--skip-password-requirement` | Allow creating user without password |\n\n```bash\nclerk users create --email john@example.com --first-name John --last-name Doe\nclerk users create --email john@example.com --password \"securepassword123\"\n```\n\n#### `clerk users update \u003cuserId\u003e [options]`\n\nUpdate an existing user.\n\n| Option | Description |\n|--------|-------------|\n| `--first-name \u003cname\u003e` | First name |\n| `--last-name \u003cname\u003e` | Last name |\n| `--username \u003cusername\u003e` | Username |\n| `--password \u003cpassword\u003e` | New password |\n| `--external-id \u003cid\u003e` | External ID |\n| `--primary-email-id \u003cid\u003e` | Set primary email address by ID |\n| `--primary-phone-id \u003cid\u003e` | Set primary phone number by ID |\n| `--public-metadata \u003cjson\u003e` | Public metadata (replaces existing) |\n| `--private-metadata \u003cjson\u003e` | Private metadata (replaces existing) |\n| `--skip-password-checks` | Skip password complexity validation |\n| `--sign-out-other-sessions` | Sign out all other sessions after password change |\n\n```bash\nclerk users update user_123 --first-name Jane --last-name Smith\nclerk users update user_123 --password \"newpassword123\" --sign-out-other-sessions\n```\n\n#### `clerk users delete \u003cuserId\u003e [-f]`\n\nDelete a user permanently.\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk users delete user_123\nclerk users delete user_123 --force\n```\n\n#### `clerk users ban \u003cuserId\u003e`\n\nBan a user, revoking all sessions and preventing sign-in.\n\n```bash\nclerk users ban user_123\n```\n\n#### `clerk users unban \u003cuserId\u003e`\n\nRemove the ban from a user.\n\n```bash\nclerk users unban user_123\n```\n\n#### `clerk users lock \u003cuserId\u003e`\n\nLock a user account temporarily.\n\n```bash\nclerk users lock user_123\n```\n\n#### `clerk users unlock \u003cuserId\u003e`\n\nRemove the lockout from a user account.\n\n```bash\nclerk users unlock user_123\n```\n\n#### `clerk users verify-password \u003cuserId\u003e [options]`\n\nVerify a user's password.\n\n| Option | Description |\n|--------|-------------|\n| `--password \u003cpassword\u003e` | Password to verify (prompts if not provided) |\n\n```bash\nclerk users verify-password user_123 --password \"testpassword\"\nclerk users verify-password user_123  # interactive prompt\n```\n\n---\n\n## Organization Commands\n\n### `clerk organizations`\n\nManage organizations, memberships, and invitations. Also available as `clerk orgs`.\n\n#### `clerk organizations list [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum number to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n| `--order-by \u003cfield\u003e` | Sort field |\n| `--query \u003ctext\u003e` | Search by name or slug |\n| `--include-members-count` | Include member counts |\n\n```bash\nclerk organizations list\nclerk orgs list --query \"acme\" --include-members-count\n```\n\n#### `clerk organizations get \u003corganizationId\u003e`\n\nGet organization details.\n\n```bash\nclerk organizations get org_abc123\n```\n\n#### `clerk organizations create [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Organization name (required) |\n| `--slug \u003cslug\u003e` | URL-friendly identifier |\n| `--created-by \u003cuserId\u003e` | User ID of the creator |\n| `--max-allowed-memberships \u003cn\u003e` | Maximum members allowed |\n| `--public-metadata \u003cjson\u003e` | Public metadata |\n| `--private-metadata \u003cjson\u003e` | Private metadata |\n\n```bash\nclerk organizations create --name \"Acme Corp\"\nclerk orgs create --name \"Acme Corp\" --slug \"acme\" --max-allowed-memberships 50\n```\n\n#### `clerk organizations update \u003corganizationId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Organization name |\n| `--slug \u003cslug\u003e` | Slug |\n| `--max-allowed-memberships \u003cn\u003e` | Max membership limit |\n| `--public-metadata \u003cjson\u003e` | Public metadata |\n| `--private-metadata \u003cjson\u003e` | Private metadata |\n\n```bash\nclerk organizations update org_abc123 --name \"Acme Corporation\"\n```\n\n#### `clerk organizations delete \u003corganizationId\u003e [-f]`\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk organizations delete org_abc123 --force\n```\n\n---\n\n### `clerk organizations members`\n\n#### `clerk organizations members list \u003corganizationId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum members to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n| `--role \u003croles\u003e` | Filter by role(s) |\n\n```bash\nclerk orgs members list org_abc123\nclerk orgs members list org_abc123 --role admin\n```\n\n#### `clerk organizations members add \u003corganizationId\u003e \u003cuserId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--role \u003crole\u003e` | Role to assign (required) |\n\n```bash\nclerk orgs members add org_abc123 user_xyz --role basic_member\n```\n\n#### `clerk organizations members update \u003corganizationId\u003e \u003cmemberId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--role \u003crole\u003e` | New role to assign |\n\n```bash\nclerk orgs members update org_abc123 mem_xyz --role admin\n```\n\n#### `clerk organizations members remove \u003corganizationId\u003e \u003cmemberId\u003e`\n\n```bash\nclerk orgs members remove org_abc123 mem_xyz\n```\n\n---\n\n### `clerk organizations invitations`\n\n#### `clerk organizations invitations list \u003corganizationId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum invitations to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n| `--status \u003cstatus\u003e` | Filter by status: `pending`, `accepted`, `revoked` |\n\n```bash\nclerk orgs invitations list org_abc123 --status pending\n```\n\n#### `clerk organizations invitations create \u003corganizationId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--email \u003cemail\u003e` | Email address to invite (required) |\n| `--role \u003crole\u003e` | Role to assign when accepted (required) |\n| `--inviter-user-id \u003cid\u003e` | User ID of the inviter |\n| `--redirect-url \u003curl\u003e` | URL to redirect to after accepting |\n\n```bash\nclerk orgs invitations create org_abc123 --email john@example.com --role basic_member\n```\n\n#### `clerk organizations invitations revoke \u003corganizationId\u003e \u003cinvitationId\u003e`\n\n```bash\nclerk orgs invitations revoke org_abc123 inv_xyz\n```\n\n---\n\n## Session Commands\n\n### `clerk sessions`\n\nManage user sessions. Also available as `clerk session`.\n\n#### `clerk sessions list [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--user-id \u003cid\u003e` | Filter by user ID |\n| `--client-id \u003cid\u003e` | Filter by client ID |\n| `--status \u003cstatus\u003e` | Filter by status |\n| `--limit \u003cn\u003e` | Maximum sessions to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk sessions list --user-id user_2abc123\nclerk sessions list --user-id user_2abc123 --status active\n```\n\n#### `clerk sessions get \u003csessionId\u003e`\n\n```bash\nclerk sessions get sess_abc123\n```\n\n#### `clerk sessions revoke \u003csessionId\u003e`\n\n```bash\nclerk sessions revoke sess_abc123\n```\n\n---\n\n## API Keys Commands\n\n### `clerk apikeys`\n\nManage API keys. Also available as `clerk api-keys`.\n\n#### `clerk apikeys list [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--subject \u003cid\u003e` | Filter by user ID or organization ID |\n| `--query \u003ctext\u003e` | Search by name |\n| `--limit \u003cn\u003e` | Maximum keys to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk apikeys list\nclerk apikeys list --subject user_2abc123\n```\n\n#### `clerk apikeys get \u003capiKeyId\u003e`\n\n```bash\nclerk apikeys get ak_abc123\n```\n\n#### `clerk apikeys create [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Name for the API key (required) |\n| `--subject \u003cid\u003e` | User ID or organization ID (required) |\n| `--description \u003ctext\u003e` | Description |\n| `--scopes \u003cscopes\u003e` | Comma-separated scopes |\n| `--expires-in \u003cseconds\u003e` | Seconds until expiration |\n\n```bash\nclerk apikeys create --name \"My API Key\" --subject user_2abc123\n```\n\n#### `clerk apikeys revoke \u003capiKeyId\u003e [-f]`\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk apikeys revoke ak_abc123\n```\n\n---\n\n## Invitation Commands\n\n### `clerk invitations`\n\nManage instance-level invitations. Also available as `clerk invite`.\n\n#### `clerk invitations list [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--status \u003cstatus\u003e` | Filter by status: `pending`, `accepted`, `revoked`, `expired` |\n| `--limit \u003cn\u003e` | Maximum invitations to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk invitations list\nclerk invitations list --status pending\n```\n\n#### `clerk invitations create [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--email \u003cemail\u003e` | Email address to invite (required) |\n| `--redirect-url \u003curl\u003e` | URL to redirect to after accepting |\n| `--expires-in-days \u003cn\u003e` | Days until expiration |\n| `--no-notify` | Don't send the invitation email |\n| `--ignore-existing` | Create even if invitation already exists |\n| `--public-metadata \u003cjson\u003e` | Public metadata |\n\n```bash\nclerk invitations create --email john@example.com\nclerk invitations create --email john@example.com --no-notify --expires-in-days 7\n```\n\n#### `clerk invitations bulk-create [options]`\n\nCreate multiple invitations at once.\n\n| Option | Description |\n|--------|-------------|\n| `--emails \u003cemails\u003e` | Comma-separated email addresses (required) |\n| `--redirect-url \u003curl\u003e` | Redirect URL |\n| `--expires-in-days \u003cn\u003e` | Days until expiration |\n| `--no-notify` | Don't send invitation emails |\n\n```bash\nclerk invitations bulk-create --emails user1@example.com,user2@example.com,user3@example.com\n```\n\n#### `clerk invitations revoke \u003cinvitationId\u003e [-f]`\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk invitations revoke inv_abc123\n```\n\n---\n\n## Restrictions Commands\n\n### `clerk restrictions`\n\nManage allowlist and blocklist restrictions for sign-ups.\n\n#### `clerk restrictions list`\n\nList all allowlist and blocklist identifiers.\n\n```bash\nclerk restrictions list\nclerk restrictions ls\n```\n\n#### `clerk restrictions add \u003cidentifier\u003e [options]`\n\nAdd an identifier to the allowlist or blocklist.\n\n| Option | Description |\n|--------|-------------|\n| `--allow` | Add to allowlist (permits sign-up) |\n| `--block` | Add to blocklist (prevents sign-up) |\n| `--notify` | Send notification email (allowlist only) |\n\n```bash\n# Add to allowlist\nclerk restrictions add john@example.com --allow\nclerk restrictions add john@example.com --allow --notify\n\n# Add to blocklist\nclerk restrictions add spammer@example.com --block\nclerk restrictions add \"@spam-domain.com\" --block\n```\n\n#### `clerk restrictions remove \u003cid\u003e`\n\nRemove an identifier from the allowlist or blocklist by its ID. Also available as `clerk restrictions rm`.\n\n```bash\nclerk restrictions remove alid_abc123\nclerk restrictions rm blid_abc123\n```\n\n---\n\n## User Email Commands\n\n### `clerk users emails`\n\nManage email addresses for users. Also available as `clerk users email`.\n\n#### `clerk users emails list \u003cuserId\u003e`\n\nList all email addresses for a user.\n\n```bash\nclerk users emails list user_abc123\n```\n\n#### `clerk users emails get \u003cemailAddressId\u003e`\n\nGet details of an email address.\n\n```bash\nclerk users emails get idn_abc123\n```\n\n#### `clerk users emails add \u003cuserId\u003e [options]`\n\nAdd an email address to a user.\n\n| Option | Description |\n|--------|-------------|\n| `--email \u003cemail\u003e` | Email address (required) |\n| `--verified` | Mark as verified |\n| `--primary` | Set as primary email |\n\n```bash\nclerk users emails add user_abc123 --email john@example.com\nclerk users emails add user_abc123 --email john@example.com --verified --primary\n```\n\n#### `clerk users emails update \u003cemailAddressId\u003e [options]`\n\nUpdate an email address.\n\n| Option | Description |\n|--------|-------------|\n| `--verified` | Mark as verified |\n| `--primary` | Set as primary email |\n\n```bash\nclerk users emails update idn_abc123 --verified --primary\n```\n\n#### `clerk users emails remove \u003cemailAddressId\u003e`\n\nRemove an email address.\n\n```bash\nclerk users emails remove idn_abc123\n```\n\n---\n\n## User Phone Commands\n\n### `clerk users phones`\n\nManage phone numbers for users. Also available as `clerk users phone`.\n\n#### `clerk users phones list \u003cuserId\u003e`\n\nList all phone numbers for a user.\n\n```bash\nclerk users phones list user_abc123\n```\n\n#### `clerk users phones get \u003cphoneNumberId\u003e`\n\nGet details of a phone number.\n\n```bash\nclerk users phones get idn_abc123\n```\n\n#### `clerk users phones add \u003cuserId\u003e [options]`\n\nAdd a phone number to a user.\n\n| Option | Description |\n|--------|-------------|\n| `--phone \u003cnumber\u003e` | Phone number in E.164 format (required) |\n| `--verified` | Mark as verified |\n| `--primary` | Set as primary phone number |\n\n```bash\nclerk users phones add user_abc123 --phone \"+15551234567\"\nclerk users phones add user_abc123 --phone \"+15551234567\" --verified --primary\n```\n\n#### `clerk users phones update \u003cphoneNumberId\u003e [options]`\n\nUpdate a phone number.\n\n| Option | Description |\n|--------|-------------|\n| `--verified` | Mark as verified |\n| `--primary` | Set as primary phone number |\n\n```bash\nclerk users phones update idn_abc123 --verified --primary\n```\n\n#### `clerk users phones remove \u003cphoneNumberId\u003e`\n\nRemove a phone number.\n\n```bash\nclerk users phones remove idn_abc123\n```\n\n---\n\n## Domain Commands\n\n### `clerk domains`\n\nManage instance domains including satellite domains.\n\n#### `clerk domains list`\n\n```bash\nclerk domains list\n```\n\n#### `clerk domains get \u003cdomainId\u003e`\n\n```bash\nclerk domains get dom_abc123\n```\n\n#### `clerk domains add [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Domain name (required) |\n| `--proxy-url \u003curl\u003e` | Proxy URL |\n\n```bash\nclerk domains add --name app.example.com\n```\n\n#### `clerk domains update \u003cdomainId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | New domain name |\n| `--proxy-url \u003curl\u003e` | Proxy URL |\n\n```bash\nclerk domains update dom_abc123 --name new.example.com\n```\n\n#### `clerk domains delete \u003cdomainId\u003e [-f]`\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk domains delete dom_abc123 --force\n```\n\n---\n\n## JWT Templates Commands\n\n### `clerk jwttemplates`\n\nManage JWT templates. Also available as `clerk jwt`.\n\n#### `clerk jwttemplates list`\n\n```bash\nclerk jwttemplates list\n```\n\n#### `clerk jwttemplates get \u003ctemplateId\u003e`\n\n```bash\nclerk jwttemplates get jtmpl_abc123\n```\n\n#### `clerk jwttemplates create [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Template name (required) |\n| `--claims \u003cjson\u003e` | Claims as JSON object (required) |\n| `--lifetime \u003cseconds\u003e` | Token lifetime in seconds |\n| `--clock-skew \u003cseconds\u003e` | Allowed clock skew in seconds |\n| `--signing-algorithm \u003calg\u003e` | Signing algorithm (e.g., RS256, HS256) |\n| `--signing-key \u003ckey\u003e` | Signing private key |\n\n```bash\nclerk jwttemplates create \\\n  --name \"Hasura\" \\\n  --claims '{\"https://hasura.io/jwt/claims\": {\"x-hasura-user-id\": \"{{user.id}}\"}}'\n```\n\n#### `clerk jwttemplates update \u003ctemplateId\u003e [options]`\n\nSame options as create.\n\n```bash\nclerk jwttemplates update jtmpl_abc123 --lifetime 7200\n```\n\n#### `clerk jwttemplates delete \u003ctemplateId\u003e [-f]`\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk jwttemplates delete jtmpl_abc123 --force\n```\n\n---\n\n## JWKS Commands\n\n### `clerk jwks get`\n\nRetrieve JSON Web Key Sets for your Clerk instance.\n\n```bash\nclerk jwks get\nclerk jwks get -o json\n```\n\n---\n\n## Instance Commands\n\n### `clerk instance`\n\nManage instance-level settings and restrictions.\n\n#### `clerk instance get`\n\n```bash\nclerk instance get\n```\n\n#### `clerk instance update [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--test-mode` / `--no-test-mode` | Enable/disable test mode |\n| `--hibp` / `--no-hibp` | Enable/disable HIBP password breach checking |\n| `--support-email \u003cemail\u003e` | Support email address |\n| `--clerk-js-version \u003cversion\u003e` | Clerk.js version |\n| `--development-origin \u003corigin\u003e` | Development origin URL |\n| `--allowed-origins \u003corigins\u003e` | Allowed origins (comma-separated) |\n| `--url-based-session-syncing` / `--no-url-based-session-syncing` | URL-based session syncing |\n\n```bash\nclerk instance update --test-mode\nclerk instance update --support-email support@example.com\n```\n\n### `clerk instance restrictions update [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--allowlist` / `--no-allowlist` | Enable/disable allowlist |\n| `--blocklist` / `--no-blocklist` | Enable/disable blocklist |\n| `--block-email-subaddresses` / `--no-block-email-subaddresses` | Block email subaddresses |\n| `--block-disposable-emails` / `--no-block-disposable-emails` | Block disposable emails |\n\n```bash\nclerk instance restrictions update --allowlist --block-disposable-emails\n```\n\n---\n\n## M2M Commands\n\n### `clerk m2m`\n\nManage machine-to-machine authentication.\n\n### `clerk m2m tokens`\n\n#### `clerk m2m tokens list [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--machine-id \u003cid\u003e` | Filter by machine ID |\n| `--limit \u003cn\u003e` | Maximum tokens to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk m2m tokens list --machine-id mch_abc123\n```\n\n#### `clerk m2m tokens create [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--machine-id \u003cid\u003e` | Machine ID (required) |\n| `--scopes \u003cscopes\u003e` | Comma-separated scopes |\n| `--expires-in \u003cseconds\u003e` | Seconds until expiration |\n\n```bash\nclerk m2m tokens create --machine-id mch_abc123 --scopes \"read:users,write:users\"\n```\n\n#### `clerk m2m tokens verify [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--token \u003ctoken\u003e` | Token to verify (required) |\n\n```bash\nclerk m2m tokens verify --token clerk_m2m_xxxxx\n```\n\n### `clerk m2m machines`\n\n#### `clerk m2m machines list [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum machines to return |\n| `--offset \u003cn\u003e` | Pagination offset |\n| `--query \u003ctext\u003e` | Search query |\n\n```bash\nclerk m2m machines list\nclerk m2m machines list --query \"backend\"\n```\n\n#### `clerk m2m machines get \u003cmachineId\u003e`\n\n```bash\nclerk m2m machines get mch_abc123\n```\n\n#### `clerk m2m machines create [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Machine name (required) |\n| `--scopes \u003cscopes\u003e` | Comma-separated scopes |\n\n```bash\nclerk m2m machines create --name \"Backend Service\"\n```\n\n#### `clerk m2m machines update \u003cmachineId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | New machine name |\n\n```bash\nclerk m2m machines update mch_abc123 --name \"New Service Name\"\n```\n\n#### `clerk m2m machines delete \u003cmachineId\u003e`\n\n```bash\nclerk m2m machines delete mch_abc123\n```\n\n#### `clerk m2m machines get-secret \u003cmachineId\u003e`\n\nRetrieve the secret for a machine.\n\n```bash\nclerk m2m machines get-secret mch_abc123\n```\n\n#### `clerk m2m machines add-scope \u003cmachineId\u003e [options]`\n\n| Option | Description |\n|--------|-------------|\n| `--scope \u003cscope\u003e` | Scope to add (required) |\n\n```bash\nclerk m2m machines add-scope mch_abc123 --scope \"read:users\"\n```\n\n---\n\n## Billing Commands\n\n### `clerk billing`\n\nManage billing plans, subscriptions, and statements.\n\n### `clerk billing plans`\n\n#### `clerk billing plans list [options]`\n\nList all billing plans.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum plans to return (default: 10) |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk billing plans list\nclerk billing plans ls -o json\n```\n\n---\n\n### `clerk billing subscription`\n\n#### `clerk billing subscription get-user \u003cuserId\u003e`\n\nGet the billing subscription for a user.\n\n```bash\nclerk billing subscription get-user user_abc123\nclerk billing subscription get-user user_abc123 -o json\n```\n\n#### `clerk billing subscription get-org \u003corganizationId\u003e`\n\nGet the billing subscription for an organization.\n\n```bash\nclerk billing subscription get-org org_abc123\nclerk billing subscription get-org org_abc123 -o json\n```\n\n---\n\n### `clerk billing subscription-items`\n\nManage subscription items. Also available as `clerk billing items`.\n\n#### `clerk billing subscription-items list [options]`\n\nList all subscription items.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum items to return (default: 10) |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk billing subscription-items list\nclerk billing items ls\n```\n\n#### `clerk billing subscription-items delete \u003csubscriptionItemId\u003e [-f]`\n\nDelete a subscription item.\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk billing subscription-items delete csub_item_abc123\nclerk billing items delete csub_item_abc123 --force\n```\n\n#### `clerk billing subscription-items extend-trial \u003csubscriptionItemId\u003e [options]`\n\nExtend the free trial for a subscription item.\n\n| Option | Description |\n|--------|-------------|\n| `--days \u003cn\u003e` | Number of days to extend the trial |\n\n```bash\nclerk billing subscription-items extend-trial csub_item_abc123 --days 14\n```\n\n#### `clerk billing subscription-items transition-price \u003csubscriptionItemId\u003e [options]`\n\nTransition a subscription item to a new price.\n\n| Option | Description |\n|--------|-------------|\n| `--price-id \u003cid\u003e` | New price ID |\n| `--immediate` | Apply transition immediately |\n\n```bash\nclerk billing subscription-items transition-price csub_item_abc123 --price-id cprice_xyz --immediate\n```\n\n---\n\n### `clerk billing statements`\n\n#### `clerk billing statements list [options]`\n\nList all billing statements.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum statements to return (default: 10) |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk billing statements list\nclerk billing statements ls -o json\n```\n\n#### `clerk billing statements get \u003cstatementId\u003e`\n\nGet details of a specific statement.\n\n```bash\nclerk billing statements get stmt_abc123\nclerk billing statements get stmt_abc123 -o json\n```\n\n#### `clerk billing statements payment-attempts \u003cstatementId\u003e [options]`\n\nList payment attempts for a statement.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum attempts to return (default: 10) |\n| `--offset \u003cn\u003e` | Pagination offset |\n\n```bash\nclerk billing statements payment-attempts stmt_abc123\nclerk billing statements payment-attempts stmt_abc123 -o json\n```\n\n---\n\n## Platform API Commands\n\nThe Platform API uses workspace-level API keys (`ak_*`) instead of instance-level secret keys (`sk_*`). These commands manage resources across your entire Clerk workspace.\n\n### Configuration\n\n```bash\n# Set Platform API key via environment variable\nexport CLERK_PLATFORM_KEY=ak_...\n\n# Or configure in your profile\nclerk config set clerk.platform.key ak_...\n```\n\n---\n\n### `clerk apps`\n\nManage applications in your Clerk workspace. Also available as `clerk applications`.\n\n#### `clerk apps list [options]`\n\nList all applications in the workspace.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum applications to return (default: 10) |\n| `--offset \u003cn\u003e` | Pagination offset |\n| `--query \u003ctext\u003e` | Search query |\n\n```bash\nclerk apps list\nclerk apps ls -o json\n```\n\n#### `clerk apps get \u003cappId\u003e`\n\nGet details of a specific application.\n\n```bash\nclerk apps get app_abc123\n```\n\n#### `clerk apps create [options]`\n\nCreate a new application.\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Application name (required) |\n| `--environment-types \u003ctypes\u003e` | Environment types for instances (comma-separated, e.g. `development,production`) |\n| `--proxy-path \u003cpath\u003e` | Proxy path for the application |\n| `--template \u003ctemplate\u003e` | Template for the application |\n| `--domain \u003cdomain\u003e` | Domain for the application |\n\n```bash\nclerk apps create --name \"My New App\"\nclerk apps create --name \"My App\" --environment-types development,production --domain example.com\n```\n\n#### `clerk apps update \u003cappId\u003e [options]`\n\nUpdate an existing application.\n\n| Option | Description |\n|--------|-------------|\n| `--name \u003cname\u003e` | Application name |\n\n```bash\nclerk apps update app_abc123 --name \"Updated Name\"\n```\n\n#### `clerk apps delete \u003cappId\u003e [-f]`\n\nDelete an application.\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk apps delete app_abc123 --force\n```\n\n---\n\n### `clerk apps instances`\n\nManage application instances (environments).\n\n#### `clerk apps instances list \u003cappId\u003e [options]`\n\nList all instances for an application.\n\n| Option | Description |\n|--------|-------------|\n| `--include-secret-keys` | Include secret keys in output |\n\n```bash\nclerk apps instances list app_abc123\nclerk apps instances list app_abc123 --include-secret-keys\n```\n\n---\n\n### `clerk transfers`\n\nManage application transfers between workspaces.\n\n#### `clerk transfers list [options]`\n\nList all transfers.\n\n| Option | Description |\n|--------|-------------|\n| `--limit \u003cn\u003e` | Maximum transfers to return (default: 10) |\n| `--offset \u003cn\u003e` | Pagination offset |\n| `--status \u003cstatus\u003e` | Filter by status: `pending`, `accepted`, `canceled`, `expired` |\n\n```bash\nclerk transfers list\nclerk transfers list --status pending\n```\n\n#### `clerk transfers get \u003ctransferId\u003e`\n\nGet details of a specific transfer.\n\n```bash\nclerk transfers get txfr_abc123\n```\n\n#### `clerk transfers create [options]`\n\nCreate a new transfer request.\n\n| Option | Description |\n|--------|-------------|\n| `--app-id \u003cid\u003e` | Application ID to transfer (required) |\n| `--target-workspace \u003cid\u003e` | Target workspace ID (required) |\n\n```bash\nclerk transfers create --app-id app_abc123 --target-workspace ws_xyz789\n```\n\n#### `clerk transfers accept \u003ctransferId\u003e`\n\nAccept a pending transfer.\n\n```bash\nclerk transfers accept txfr_abc123\n```\n\n#### `clerk transfers cancel \u003ctransferId\u003e [-f]`\n\nCancel a pending transfer.\n\n| Option | Description |\n|--------|-------------|\n| `-f, --force` | Skip confirmation prompt |\n\n```bash\nclerk transfers cancel txfr_abc123 --force\n```\n\n---\n\n## Configuration Files\n\nThe CLI stores configuration in `~/.config/clerk/cli/`:\n\n| File | Purpose |\n|------|---------|\n| `profiles` | Configuration profiles and settings (INI format) |\n| `aliases.json` | Command aliases (JSON format) |\n| `mcp.json` | MCP tool server configuration (JSON format, optional) |\n\n### Profiles File\n\nConfiguration is stored in `~/.config/clerk/cli/profiles` using INI format:\n\n```ini\n[default]\nprofile = production\n\n[profile default]\nclerk.key = sk_test_xxxxx\noutput = table\n\n[profile production]\nclerk.key = sk_live_xxxxx\nclerk.platform.key = ak_xxxxx\noutput = json\n\n[profile staging]\nclerk.key = sk_test_yyyyy\nclerk.api.url = https://api.staging.clerk.com\n\n[profile vault]\nclerk.key = !op read 'op://Vault/Clerk/api-key'\nclerk.platform.key = !op read 'op://Vault/Clerk/platform-key'\noutput = table\n```\n\n**Structure:**\n- `[default]` section: Global settings and active profile\n- `[profile \u003cname\u003e]` sections: Profile-specific settings\n- Lines starting with `#` or `;` are comments\n- Values prefixed with `!` are treated as shell commands\n\n### Aliases File\n\nAliases are stored in `~/.config/clerk/cli/aliases.json`:\n\n```json\n{\n  \"prl\": \"protect rules list\",\n  \"pra\": \"protect rules add\"\n}\n```\n\n### Using Commands to Fetch Secrets\n\nInstead of storing API keys directly, use `--type=command` with `config set` to store a command that fetches a value dynamically. The command string is stored with a `!` prefix in the profiles file and executed via your shell each time the value is needed.\n\n```bash\nclerk config set clerk.key \"op read 'op://Vault/Clerk/api-key'\" --type=command --profile production\n```\n\n#### Example: 1Password CLI\n\n```bash\nclerk config set clerk.key \"op read 'op://Vault/Clerk Production/api-key'\" --type=command --profile production\n```\n\n#### Example: AWS Secrets Manager\n\n```bash\nclerk config set clerk.key \"aws secretsmanager get-secret-value --secret-id clerk/api-key --query SecretString --output text\" --type=command --profile production\n```\n\n#### Example: HashiCorp Vault\n\n```bash\nclerk config set clerk.key \"vault kv get -field=api_key secret/clerk/production\" --type=command --profile production\n```\n\n---\n\n## Contributing\n\n### Project Structure\n\n```\ncmd/clerk/\n  main.go                    # Entry point\ninternal/\n  api/\n    client.go                # Backend API HTTP client (sk_* keys)\n    platform_client.go       # Platform API HTTP client (ak_* keys)\n    users.go                 # Users API\n    organizations.go         # Organizations API\n    sessions.go              # Sessions API\n    apikeys.go               # API Keys API\n    invitations.go           # Invitations API\n    restrictions.go          # Restrictions API (allowlist/blocklist)\n    emails.go                # Email Addresses API\n    phones.go                # Phone Numbers API\n    domains.go               # Domains API\n    jwttemplates.go          # JWT Templates API\n    instance.go              # Instance API\n    jwks.go                  # JWKS API\n    m2m.go                   # M2M API (tokens + machines)\n    billing.go               # Billing API (plans, subscriptions, statements)\n    protect.go               # Protect Rules \u0026 Schema API\n    applications.go          # Applications API (Platform)\n    transfers.go             # Transfers API (Platform)\n  cmd/\n    root.go                  # Root command, global flags, prefix matching\n    args.go                  # Argument validation helpers\n    prefix.go                # Prefix matching logic\n    init.go                  # Init/setup wizard\n    whoami.go                # Whoami command\n    config.go                # Config, profile, and alias commands\n    users.go                 # Users commands\n    organizations.go         # Organizations commands\n    sessions.go              # Sessions commands\n    apikeys.go               # API Keys commands\n    invitations.go           # Invitations commands\n    restrictions.go          # Restrictions (allowlist/blocklist) commands\n    emails.go                # User email addresses commands (under users)\n    phones.go                # User phone numbers commands (under users)\n    domains.go               # Domains commands\n    jwttemplates.go          # JWT templates commands\n    instance.go              # Instance commands\n    jwks.go                  # JWKS commands\n    m2m.go                   # M2M commands\n    billing.go               # Billing commands\n    protect.go               # Protect commands\n    apps.go                  # Applications commands (Platform API)\n    transfers.go             # Transfers commands (Platform API)\n  config/\n    config.go                # Configuration management (INI format)\n    aliases.go               # Command aliases (JSON format)\n  output/\n    format.go                # Output formatting (table/json/yaml)\n    colors.go                # Colorized output helpers\n  ai/\n    ai.go                    # AI provider abstraction\n    openai.go                # OpenAI provider\n    anthropic.go             # Anthropic provider\n    mcp.go                   # MCP client (JSON-RPC over stdio)\n    mcp_config.go            # MCP server configuration loader\n    tools.go                 # Tool manager (routes calls to MCP servers)\n```\n\n### Architecture\n\nThe CLI is built with [Cobra](https://github.com/spf13/cobra) and follows a modular architecture:\n\n- **cmd/** - Command definitions using Cobra. Each file defines a command group with its subcommands and flags.\n- **api/** - HTTP client layer. Each file implements API calls for a specific resource type. The base client handles authentication, retries with exponential backoff, and debug logging.\n- **config/** - Configuration management using INI-based profiles with support for command-type values that execute shell commands.\n- **output/** - Output formatting supporting table, JSON, and YAML formats with colorized terminal output.\n- **ai/** - Pluggable AI provider integration for natural language rule generation.\n\n### Dependencies\n\n| Package | Purpose |\n|---------|---------|\n| `github.com/spf13/cobra` | CLI framework |\n| `github.com/AlecAivazis/survey/v2` | Interactive prompts |\n| `github.com/fatih/color` | Terminal colors |\n| `github.com/olekukonov/tablewriter` | Table output |\n| `gopkg.in/yaml.v3` | YAML output |\n| `golang.org/x/term` | Terminal detection |\n\n### Development\n\n```bash\n# Build\ngo build -o clerk ./cmd/clerk\n\n# Run\n./clerk --help\n\n# Test commands\n./clerk config path\n./clerk config set clerk.key \"test_key\" --profile test\n./clerk whoami\n./clerk users list --output json\n```\n\n---\n\n## Releasing\n\nReleases are automated via GitHub Actions. When you push a tag (e.g., `v1.0.0`), the workflow:\n\n1. Builds binaries for all platforms (darwin, linux, windows × amd64, arm64)\n2. Signs and notarizes macOS .pkg installers (if configured)\n3. Creates a GitHub Release with all artifacts\n4. Updates the Homebrew formula and Cask versions\n\n### Creating a Release\n\n```bash\ngit tag v1.0.0\ngit push origin v1.0.0\n```\n\n### Distribution Channels\n\n| Channel | Type | Command |\n|---------|------|---------|\n| Homebrew (source) | Formula | `brew install clerk/cli/clerk` |\n| Homebrew (signed pkg) | Cask | `brew install --cask clerk/cli/clerk` |\n| NPM | Binary wrapper | `npx clerk-cli` |\n| GitHub Releases | Direct download | Download from releases page |\n\n---\n\n## macOS Code Signing Setup\n\nTo distribute signed and notarized macOS .pkg installers via Homebrew Cask, you need an Apple Developer account and certificates.\n\n### Prerequisites\n\n1. **Apple Developer Program membership** ($99/year) - https://developer.apple.com/programs/enroll/\n2. **Developer ID certificates**:\n   - Developer ID Application (signs the binary)\n   - Developer ID Installer (signs the .pkg)\n3. **App-Specific Password** for notarization - generate at https://appleid.apple.com\n\n### Required GitHub Secrets\n\nAdd these secrets in your repository settings (Settings → Secrets and variables → Actions → Secrets):\n\n| Secret | Description |\n|--------|-------------|\n| `APPLE_DEVELOPER_ID_APPLICATION_P12` | Base64-encoded .p12 of Developer ID Application cert |\n| `APPLE_DEVELOPER_ID_INSTALLER_P12` | Base64-encoded .p12 of Developer ID Installer cert |\n| `APPLE_CERTIFICATE_PASSWORD` | Password used when exporting the .p12 files |\n| `APPLE_ID` | Your Apple ID email |\n| `APPLE_APP_SPECIFIC_PASSWORD` | App-specific password for notarization |\n| `APPLE_TEAM_ID` | Your 10-character Apple Team ID |\n| `APPLE_DEVELOPER_NAME` | Developer name as shown in certificate (e.g., \"Your Name\" or \"Your Company, Inc.\") |\n\n### Required Repository Variable\n\nAdd this variable (Settings → Secrets and variables → Actions → Variables):\n\n| Variable | Value |\n|----------|-------|\n| `MACOS_SIGNING_ENABLED` | `true` |\n\n### Exporting Certificates\n\n1. Open **Keychain Access** on your Mac\n2. Find your **Developer ID Application** certificate\n3. Right-click → **Export** → Save as .p12 file with a password\n4. Repeat for **Developer ID Installer** certificate\n5. Run the helper script to get base64-encoded values:\n\n```bash\n./scripts/export-certs-for-github.sh\n```\n\n### How Signing Works\n\nThe release workflow includes a `sign-macos` job that:\n\n1. Runs on `macos-latest` (required for codesign/notarytool)\n2. Imports certificates into a temporary keychain\n3. Signs the Go binary with `codesign` (hardened runtime)\n4. Builds a .pkg installer with `pkgbuild`\n5. Signs the .pkg with `productsign`\n6. Submits to Apple for notarization via `notarytool`\n7. Staples the notarization ticket to the .pkg\n\nThe signed .pkg files are uploaded to GitHub Releases alongside the unsigned binaries.\n\n### Homebrew Cask\n\nThe `Casks/clerk.rb` file defines the Homebrew Cask that installs the signed .pkg:\n\n```bash\n# Add the tap\nbrew tap clerk/cli https://github.com/clerk/cli\n\n# Install via Cask (uses signed .pkg)\nbrew install --cask clerk/cli/clerk\n\n# Or install via Formula (builds from source)\nbrew install clerk/cli/clerk\n```\n\n### Troubleshooting\n\n**Notarization fails**: Check that your Apple ID has accepted the latest developer agreements at https://developer.apple.com\n\n**Certificate not found**: Ensure the certificate names match exactly. Run `security find-identity -v -p codesigning` to list available certificates.\n\n**Gatekeeper blocks the binary**: The binary must be signed with hardened runtime (`--options runtime`) and successfully notarized.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclerk%2Fprotect-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclerk%2Fprotect-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclerk%2Fprotect-cli/lists"}