Skip to content

Tags: clerk/cli

Tags

v3.0.1-canary.ffd027c

Toggle v3.0.1-canary.ffd027c's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(keyless): make keyless the default and let agents configure a ke…

…yless instance (#395)

* feat(keyless): make keyless the default again and let agents configure a keyless instance

Restores keyless mode as the default for unauthenticated `clerk init` (reversing
PR #268), and extends keyless so an agent can bootstrap and configure Clerk end
to end without a Clerk account.

Init:
- Unauthenticated runs on keyless-capable frameworks use keyless again — human
  bootstrap and all agent runs. Existing-project human runs still log in.
- `--login` forces the authenticated flow; `--keyless` now forces keyless even
  when signed in. `--keyless --login`, `--keyless --app`, and agent `--login`
  while signed out are usage errors.
- `--template <b2b-saas|b2c-saas|native|waitlist>` pre-configures the keyless
  application at creation.

Operating a keyless instance (Backend API, instance secret key only):
- `clerk config pull` and `clerk config patch` cover seven resource groups.
- `clerk enable/disable orgs`, `clerk whoami`, and `clerk env pull` work with no
  account. Billing stays account-only and says why.
- Keys are also discovered from `.clerk/.tmp/keyless.json`, so an application a
  Clerk SDK minted for itself is reachable from the CLI.

Account credentials are deliberately not part of the keyless decision: only
`--app` or a linked profile selects the account path, so these commands work
with or without a platform API key or login session.

* feat(keyless): configure an unclaimed application end to end without an account

Close the gaps between "keyless is the default" and "keyless actually works
with no human intervention":

- config patch validates instance fields against the Backend API's own schema
  before sending — PATCH /v1/instance answers 204 and silently discards
  unknown fields, so a typo or an account-only setting (password, social,
  second_factors, ...) used to print "Config pushed successfully" and change
  nothing. The refusal names the accepted fields and, for settings BAPI has
  no route for at all, says claiming is the only path.
- config patch no longer prints a stale eventually-consistent re-read as the
  result of a write; bodyless groups are reported as unconfirmed.
- allowlist_identifiers/blocklist_identifiers point at `clerk api` (which
  reaches them keyless) instead of demanding a login.
- users open explains that an unclaimed app has no dashboard page and offers
  `clerk api /users/<id>`, instead of blaming "not linked" and suggesting
  remedies that need an application ID that doesn't exist yet.
- whoami/env pull detect publishable/secret keys that belong to different
  applications; env pull refuses to write a mismatched pair.
- doctor, open, users, api, env pull, whoami, enable/disable orgs and
  templates verified end to end on a live unclaimed instance, all under
  --mode agent with non-TTY stdin: no hangs, no prompts, no browser.

docs/keyless-demos: before/after screenshots proving CLI writes reach the
live hosted UI pre-claim (orgs step inserted into the sign-in flow,
allowlist enforced then lifted), with a README on the FAPI /v1/environment
oracle and its limits.

* fix(keyless): address CodeRabbit findings on secret handling and error classification

- demo-env.sh: bound the accountless-application curl request with connect/max
  timeouts, and stop echoing the raw minting response (it can contain a live
  secret_key when only one of the two fields fails to parse).
- 09-health-and-users.tape: redact the claim token before it's recorded by
  piping `clerk open --print` through sed.
- open/README.md: add a language to the fenced usage-error example (MD040).
- bapi-command.ts: describeBapiTarget now checks options.secretKey first,
  mirroring resolveBapiSecretKey's actual precedence.
- credential-store.ts: exclude 429 from isUnrecoverableRefreshFailure so a
  rate-limited token refresh isn't reported as an expired session.

* chore(keyless): remove demo assets from the repo

* fix(keyless): address CodeRabbit findings on doctor side effects, claim-url trust, and env-file key priority

* fix(keyless): address review feedback on key precedence, init guard, and doctor diagnostics

- Restore CLERK_SECRET_KEY's precedence: the env var wins over a linked
  profile again, and --instance next to it stays a no-op instead of a usage
  error. Routing it through resolveKeylessTarget had silently changed both,
  breaking invocations that work on main; real env-var-path tests pin it now.
- init's keep-the-existing-app guard also recognizes an application the SDK
  minted for itself (.clerk/.tmp/keyless.json), instead of silently orphaning
  it with a replacement.
- doctor reports a malformed local secret key as one named failing check with
  a remedy, instead of five anonymous 'Check crashed' lines.
- whoami: keyless next-steps no longer point at clerk link (which cannot work
  pre-claim), and an unlinked directory holding a local secret key is called
  out, since clerk api/users will use that key's instance, not the account.
- Smaller review items: billing asserts on an already-resolved target,
  config schema resolves its target once, apply-patch dry-run messages reuse
  the verb, claim-url validation inlined, keylessTargetStubs covers every
  export for module mocks, positive test for the non-429 refresh refusal,
  keyless disable-orgs test, README corrections, changeset trimmed.

* refactor(keyless): gather user-facing keyless copy into lib/copy.ts

One function per sentence with typed parameters, so a future i18n layer can
swap the module's bodies without touching call sites; pluralisation and
agreement rules move with the prose. No visible string changes.

* docs(changeset): take the keyless-default release to major

Signed-out `clerk init` changes behaviour — it now mints a keyless
application instead of launching the browser login — so the release is not
purely additive even with CLERK_SECRET_KEY precedence restored.

* test(env): restore the iOS test's closing brace lost in a rebase conflict seam

* fix(keyless): surface malformed local keys and exported key overrides

Resolve the local secret key error in checkLoggedIn even when a stored
account token exists, so a broken local CLERK_SECRET_KEY isn't hidden
behind "Logged in" — other commands still prefer that key over the
account session.

whoami now also detects an exported CLERK_SECRET_KEY when a directory
is linked, matching resolveBapiSecretKey's precedence: that env var
overrides even a linked profile, so whoami's answer was wrong for the
commands that honor it.

Also list a `clerk api /<path>` example for every key, not just the
first, when telling the user which keys are already reachable on an
unclaimed application.

Addresses CodeRabbit review feedback on PR #395.

v2.4.1-canary.bc8b757

Toggle v2.4.1-canary.bc8b757's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(init): close the framework scaffolding gaps for expo, express, f…

…astify, ios, and android (#394)

v2.3.3-canary.89af68a

Toggle v2.3.3-canary.89af68a's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(users): confirm before creating a user, and unstick the skill aud…

…it (#400)

* fix(users): confirm before creating a user

`users create` registers `--yes` as "Skip confirmation prompt" and its
`setExamples` recommend passing it, but no prompt existed. The flag was
declared on `CreateUserOptions` and never read, so the user was created
immediately in every mode.

The surrounding code already assumed a prompt: the `catch` handles
`UserAbortError` and `isPromptExitError`, neither of which anything
inside the `try` could throw. Nearly every existing test threads
`yes: true` through to the BAPI call. This wires up the gate those were
written against.

Human mode now prints the redacted request body and confirms before the
POST, matching `clerk api`, `config push`, `unlink`, and `impersonate`.
Agent mode is untouched: `isHuman()` is false there, so it never
prompts and `--dry-run` stays the safety net.

Chose this over dropping the flag because `--help` and the shipped
examples have been telling people the prompt exists. Removing `--yes`
would break the documented invocations; adding the prompt makes them
correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(skills): point audit-clerk-skill at clerk/skills

The audit that keeps the `clerk-cli` skill in sync with this binary
targets `skills/clerk-cli/SKILL.md`. #315 moved the skill out to
clerk/skills, so that path has not existed here since. The audit has
been checking nothing, which is how the skill drifted into promising
confirmation prompts and a guidance-only agent login that neither
exist.

Retarget it at a `$SKILL_ROOT` clone of clerk/skills, and drop the
`{{CLI_VERSION}}` and `clerk skill install` references that went with
the bundled copy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

v2.3.2-canary.3006b5b

Toggle v2.3.2-canary.3006b5b's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(link): pin the create-application option to the top of the app pi…

…cker (#401)

v2.3.2-canary.8d82754

Toggle v2.3.2-canary.8d82754's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Stop emitting explicit version in Homebrew formulae (#402)

v2.3.1

Toggle v2.3.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
ci(repo): version packages (#391)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

v2.3.2-canary.e2224f0

Toggle v2.3.2-canary.e2224f0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(test): fail fast when Bun predates `—parallel` test isolation (#…

…392)

* chore(test): fail fast when Bun predates --parallel test isolation

bun test --parallel (and --isolate) first shipped in Bun 1.3.13. Older
Bun silently ignores the flags, runs every test file in one process, and
lets mock.module() registrations bleed across files — surfacing as
hundreds of order-dependent failures. Bun does not enforce engines.bun at
install time, so raise the floor to >=1.3.13 and add a preflight
(scripts/check-bun-version.ts) that both test scripts run first, failing
loudly with an upgrade hint instead of a confusing test cascade.

Also sync stale docs that still referenced the removed scripts/run-tests.ts
runner (gone since #280) and its flags — notably e2e.md, which documented
`test:e2e:op -- --filter react` to scope a run when a forwarded positional
pattern now broadens the run to the whole (expensive) e2e suite instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(test): correct stale test commands surfaced in review

- e2e.md: the single-fixture example targeted the fixture project dir
  (test/e2e/fixtures/react/), which matches no tests; point at the test
  file (test/e2e/react.test.ts) instead, and fix the patch filename
  (1.58.2 -> 1.60.0).
- CLAUDE.md: CI runs `bun run test`, not a bare `bun test`.
- CONTRIBUTING.md: steer contributors to `bun run test` (isolation +
  version preflight) over bare `bun test`, and replace the removed
  runner's --filter/--debug/--har flags with the env-var equivalents.
- run-e2e-op.ts: the JSDoc example used the dead --filter flag; forwarded
  args now go to `bun test`, where a positional path broadens the run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(test): use a real E2E test name in run-e2e-op.ts example

The `-t "sign in"` example matched no test name. The registered names
are "project builds with no errors", "typecheck passes with no errors",
and "app loads and auth flow works" — use "project builds".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

v2.3.2-canary.699f7dc

Toggle v2.3.2-canary.699f7dc's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
docs(e2e): align fixture-authoring docs with the #280 manifest harness (

#393)

The E2E fixture-authoring docs still described the pre-#280 harness. Update
them to match the current manifest-driven setup:

- Fixture config now lives in test/e2e/fixtures.manifest.ts (keyed by name),
  not exported from each test file; tests call createFixtureHarness(name).
- Correct the exported helpers to the plural runFixtureTests()/runBrowserTests()
  in CONTRIBUTING.md (were the singular runFixtureTest()/runBrowserTest()).
- Fixture setup uses `npm ci` (fixtures migrated from bun to npm with a
  checked-in package-lock.json), not `bun install`.
- Refresh the FixtureConfig field list (drop removed `description`/`pinned`,
  add `pinnedDependencyRanges`/`packageJsonOverrides`) and drop the stale
  `--force`/non-pinned refresh flags (the script only accepts `--only`).

Follow-up to #392, which deliberately scoped this rewrite out.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

v2.3.2-canary.7fb79a6

Toggle v2.3.2-canary.7fb79a6's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(orgs): enable organization creation defaults with --auto-create (#…

…390)

The API only auto-creates organizations when both
organization_creation_defaults.enabled and the nested
automatic_organization_creation.enabled are true. The --auto-create flag
previously patched only the nested flag, so on instances where the
umbrella setting was never enabled the command succeeded silently but no
organization was ever auto-created.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

v2.3.1-canary.1a5baee

Toggle v2.3.1-canary.1a5baee's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
build(deps): bump actions/setup-node from 6 to 7 (#385)

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>