Skip to content

feat(keyless): make keyless the default and let agents configure a keyless instance#395

Draft
rafa-thayto wants to merge 1 commit into
mainfrom
rafa-thayto/keyless-mode-default
Draft

feat(keyless): make keyless the default and let agents configure a keyless instance#395
rafa-thayto wants to merge 1 commit into
mainfrom
rafa-thayto/keyless-mode-default

Conversation

@rafa-thayto

Copy link
Copy Markdown
Contributor

What

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

No backend changes required. Every route used here was verified live against api.clerk.dev with an unclaimed keyless application's sk_test_ key before being written against.

Init

Flag / case Behavior
unauthenticated + keyless-capable framework keyless again (human bootstrap + all agent runs); existing-project human runs still log in
--keyless forces keyless even when signed in, existing projects included
--login forces the authenticated flow
--template <b2b-saas|b2c-saas|native|waitlist> pre-configures the application at creation

Usage errors: --keyless --login, --keyless --app, --template --login, and agent-mode --login while signed out (agents can't complete browser OAuth).

-y means confirmations only — it neither forces nor bypasses keyless.

Operating a keyless instance

clerk config pull / patch fall back to the Backend API using the instance secret key. The payload names BAPI resources 1:1 rather than translating the Platform API's document shape:

clerk config patch --json '{"instance":{"support_email":"dev@acme.com"},"organization_settings":{"enabled":true}}'

Groups: instance, communication, restrictions, organization_settings, protect, oauth_application_settings, instance_settings. Any other key is a usage error naming the supported ones.

Also now account-free: clerk enable/disable orgs, clerk whoami (reports the instance identity), clerk env pull (writes locally-held keys). Keys are additionally discovered from .clerk/.tmp/keyless.json, the file Clerk SDKs write when they mint their own application — previously invisible to the CLI.

Account credentials are deliberately not part of the keyless decision. Only --app or a linked profile selects the account path, so these work with or without a platform key/login. When credentials do exist and the directory simply isn't linked, the command still runs and warns that linking gives the full configuration.

Known limits (documented, not worked around)

  • Billing and auth strategies / social providers have no secret-key-reachable route — both exit with a clear auth_required explanation. RFC drafted separately.
  • restrictions and instance_settings are write-only (no GET route).
  • GET /v1/instance returns fewer fields than PATCH accepts, so the pre-write diff is best-effort; the write is unaffected.
  • Backend API has no dry run, so --dry-run previews locally and sends nothing.
  • Multi-group writes aren't atomic (no transaction); a mid-sequence failure names the groups already applied.

Test plan

  • bun run format:check, bun run lint, bun run typecheck — clean
  • bun run test1947 pass, 0 fail
  • E2E not run locally (1Password vault unavailable); relies on CI
  • Verified live against a real keyless app: config pull/patch across groups, enable orgs (membership limit change confirmed via Frontend API), whoami, env pull on an SDK-created app with no .env, --template b2b-saas (orgs enabled on creation vs. off without it), and every guard rail
  • Dev servers booted on all five keyless-capable frameworks; the Clerk <SignIn /> widget rendered live from a keyless app

Notes for reviewers

  • All account/keyless dispatch is centralized in commands/config/io.ts over a typed InstanceTarget; no command branches on it directly.
  • init/index.test.ts crossed 1000 lines, so it was split into index.test.ts (plumbing) and strategy.test.ts (strategy selection), with the shared spy harness extracted to src/test/lib/init-harness.ts.
  • Branch is based on an older main; the diff is clean against the merge base but a rebase before merge is reasonable.

@changeset-bot

changeset-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 92f9de8

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

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

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

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

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change introduces unified keyless/account target resolution across configuration workflows and adds Backend API reads and writes for unclaimed applications. clerk init now supports keyless defaults, --login, flag validation, and application templates. Environment, organization, billing, schema, and whoami commands receive keyless-specific behavior. Documentation and tests cover key discovery, configuration payloads, init strategy selection, dry runs, identity output, and command restrictions.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • clerk/cli#387: Also changes clerk init keyless strategy behavior and related scaffolding.

Suggested reviewers: wyattjoh

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.98% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main change: restoring keyless as the default and expanding agent keyless configuration.
Description check ✅ Passed The description is detailed and directly matches the pull request’s keyless-init and keyless-configuration changes.

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

…e 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.
@rafa-thayto
rafa-thayto force-pushed the rafa-thayto/keyless-mode-default branch from ee5482e to 92f9de8 Compare July 24, 2026 21:20
@rafa-thayto
rafa-thayto marked this pull request as draft July 24, 2026 21:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
packages/cli-core/src/commands/orgs/README.md (1)

65-71: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the keyless BAPI endpoint to the reference table.

The endpoints table only lists the two account-mode (PLAPI) endpoints, omitting the PATCH /v1/instance/organization_settings BAPI endpoint that the keyless-mode section above (Line 9) already documents. As per path instructions, flagging because this table is a reference/audit surface where an incomplete endpoint list is a real, if small, correctness gap.

📝 Proposed table addition
 | Method | Endpoint                                                          | Description                                                               |
 | ------ | ------------------------------------------------------------------ | -------------------------------------------------------------------------- |
 | GET    | `/v1/platform/applications/{appId}/instances/{instanceId}/config` | Fetch current config for diff and the org-billing dependency check        |
 | PATCH  | `/v1/platform/applications/{appId}/instances/{instanceId}/config` | Patch `organization_settings` (with `?dry_run=true` when `--dry-run` set) |
+| PATCH  | `/v1/instance/organization_settings`                              | Keyless mode: patch org settings directly on the unclaimed application    |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli-core/src/commands/orgs/README.md` around lines 65 - 71, Update
the “Clerk API endpoints” reference table in the README to include the keyless
BAPI PATCH /v1/instance/organization_settings endpoint, using a description that
reflects its organization_settings patch behavior. Keep the existing PLAPI
endpoint rows unchanged.

Source: Path instructions

packages/cli-core/src/commands/config/io.ts (1)

58-83: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

writeInstanceConfig silently drops --destructive for keyless targets; PUT/PATCH invariant relies on caller discipline.

writeInstanceConfig's keyless branch ignores options.method and options.destructive, trusting comments-only invariants ("PUT is rejected before reaching here", "payload was validated before the diff was shown") instead of enforcing them. This surfaces today in push.ts: clerk config patch --destructive against a keyless target silently no-ops the flag with no warning, and any future caller that skips assertPayloadWritable or passes method: "PUT" for a keyless target would get an unvalidated payload sent to BAPI or a silent PATCH instead of the expected error.

  • packages/cli-core/src/commands/config/io.ts#L58-L83: have writeInstanceConfig warn (or throw) when destructive is set for a keyless target, and/or assert options.method === "PATCH" before calling patchKeylessConfig, rather than relying solely on caller-side comments.
  • packages/cli-core/src/commands/config/push.ts#L119-L126: until the above is added, consider warning the user (or stripping destructive) when target.kind === "keyless" before this call, since the flag currently has no effect but no feedback either.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli-core/src/commands/config/io.ts` around lines 58 - 83, Update
writeInstanceConfig in packages/cli-core/src/commands/config/io.ts (lines 58-83)
to enforce keyless-target invariants: reject non-PATCH methods and explicitly
handle destructive instead of silently dropping it before calling
patchKeylessConfig. Update packages/cli-core/src/commands/config/push.ts (lines
119-126) to provide user feedback or strip destructive for keyless targets; this
site may be made redundant if the centralized validation fully handles the flag.
packages/cli-core/src/commands/whoami/index.ts (1)

76-93: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Wrap the BAPI call with withApiContext for consistent error messaging.

describeKeyless calls bapiRequest directly, unlike the analogous keyless-aware calls added elsewhere in this PR (e.g., schema.ts's fetchInstanceConfigSchema, env/pull.ts's fetchApplication), which wrap the network call in withApiContext for a friendly failure message. A raw network failure here (revoked key, connectivity issue) will surface without that context.

♻️ Proposed fix
 async function describeKeyless(keyless: KeylessTarget): Promise<Identity> {
   const instance = await withSpinner("Fetching instance info...", async () => {
-    const response = await bapiRequest({
-      method: "GET",
-      path: "/v1/instance",
-      secretKey: keyless.secretKey,
-    });
+    const response = await withApiContext(
+      bapiRequest({ method: "GET", path: "/v1/instance", secretKey: keyless.secretKey }),
+      "Failed to fetch instance info",
+    );
     return response.body as { id?: string; environment_type?: string };
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli-core/src/commands/whoami/index.ts` around lines 76 - 93, Update
describeKeyless to wrap its bapiRequest call for /v1/instance with
withApiContext, matching the established keyless-aware request pattern and
preserving the existing response handling and identity mapping.
packages/cli-core/src/commands/init/strategy.test.ts (1)

248-259: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test isolation relies on a manual workaround instead of fixing the root cause.

Both tests re-mock config.resolveProfile specifically to guard against "leakage from earlier tests that spy on resolveProfile ... but don't track those spies for restoration" (per the inline comment). That's an order-dependent test suite — untracked ad hoc spyOn calls elsewhere can bleed into unrelated tests, and the defensive re-mock only patches the symptom for these two cases.

Consider having tests consistently pipe ad hoc spyOn calls through the harness's track() helper (or wrapping spyOn in the harness to auto-track), so afterEach restores everything and defensive re-mocking becomes unnecessary.

Also applies to: 274-292

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli-core/src/commands/init/strategy.test.ts` around lines 248 - 259,
Fix test isolation in the harness by ensuring ad hoc spyOn calls, including
config.resolveProfile spies used by neighboring tests, are registered through
the harness track() helper or automatically tracked by its spy wrapper so
afterEach restores them. Then remove the defensive config.resolveProfile
re-mocks from the authenticated-flow tests at lines 248-259 and 274-292,
preserving their intended setup and assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli-core/src/commands/config/README.md`:
- Around line 204-213: Update the “API Endpoints (keyless mode)” table to
include the documented routes for the four omitted groups: communication,
protect, oauth_application_settings, and instance_settings. Keep their endpoint
paths, readability values, and coverage descriptions consistent with the
corresponding Payload shape entries and keyless.test.ts behavior.

In `@packages/cli-core/src/commands/init/index.ts`:
- Around line 160-184: Update assertUsableFlags to reject options.template
combined with options.app, using the same usage-error pattern as the existing
--keyless/--app validation. Ensure template requests are not silently discarded
when runStrategy selects a non-keyless path; preserve the existing
--template/--login validation and, if strategy selection is adjusted, make
pickStrategy or runStrategy explicitly warn or force keyless when a template is
provided without --keyless.

---

Nitpick comments:
In `@packages/cli-core/src/commands/config/io.ts`:
- Around line 58-83: Update writeInstanceConfig in
packages/cli-core/src/commands/config/io.ts (lines 58-83) to enforce
keyless-target invariants: reject non-PATCH methods and explicitly handle
destructive instead of silently dropping it before calling patchKeylessConfig.
Update packages/cli-core/src/commands/config/push.ts (lines 119-126) to provide
user feedback or strip destructive for keyless targets; this site may be made
redundant if the centralized validation fully handles the flag.

In `@packages/cli-core/src/commands/init/strategy.test.ts`:
- Around line 248-259: Fix test isolation in the harness by ensuring ad hoc
spyOn calls, including config.resolveProfile spies used by neighboring tests,
are registered through the harness track() helper or automatically tracked by
its spy wrapper so afterEach restores them. Then remove the defensive
config.resolveProfile re-mocks from the authenticated-flow tests at lines
248-259 and 274-292, preserving their intended setup and assertions.

In `@packages/cli-core/src/commands/orgs/README.md`:
- Around line 65-71: Update the “Clerk API endpoints” reference table in the
README to include the keyless BAPI PATCH /v1/instance/organization_settings
endpoint, using a description that reflects its organization_settings patch
behavior. Keep the existing PLAPI endpoint rows unchanged.

In `@packages/cli-core/src/commands/whoami/index.ts`:
- Around line 76-93: Update describeKeyless to wrap its bapiRequest call for
/v1/instance with withApiContext, matching the established keyless-aware request
pattern and preserving the existing response handling and identity mapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 45807ed9-c06a-4293-a40a-630c1b79b426

📥 Commits

Reviewing files that changed from the base of the PR and between 699f7dc and 92f9de8.

📒 Files selected for processing (28)
  • .changeset/keyless-mode-default.md
  • packages/cli-core/src/commands/billing/README.md
  • packages/cli-core/src/commands/billing/index.ts
  • packages/cli-core/src/commands/config/README.md
  • packages/cli-core/src/commands/config/apply-patch.ts
  • packages/cli-core/src/commands/config/io.ts
  • packages/cli-core/src/commands/config/keyless.test.ts
  • packages/cli-core/src/commands/config/keyless.ts
  • packages/cli-core/src/commands/config/pull.ts
  • packages/cli-core/src/commands/config/push.ts
  • packages/cli-core/src/commands/config/schema.ts
  • packages/cli-core/src/commands/env/README.md
  • packages/cli-core/src/commands/env/pull.ts
  • packages/cli-core/src/commands/init/README.md
  • packages/cli-core/src/commands/init/heuristics.ts
  • packages/cli-core/src/commands/init/index.test.ts
  • packages/cli-core/src/commands/init/index.ts
  • packages/cli-core/src/commands/init/strategy.test.ts
  • packages/cli-core/src/commands/orgs/README.md
  • packages/cli-core/src/commands/orgs/index.ts
  • packages/cli-core/src/commands/whoami/README.md
  • packages/cli-core/src/commands/whoami/index.ts
  • packages/cli-core/src/lib/credential-store.ts
  • packages/cli-core/src/lib/keyless-target.ts
  • packages/cli-core/src/lib/keyless.ts
  • packages/cli-core/src/test/integration/lib/harness.ts
  • packages/cli-core/src/test/lib/init-harness.ts
  • packages/cli-core/src/test/lib/stubs.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go (manual)
  • clerk/dashboard (manual)
  • clerk/accounts (manual)
  • clerk/backoffice (manual)
  • clerk/clerk (manual)
  • clerk/clerk-docs (manual)
  • clerk/cloudflare-workers (manual)

Comment on lines +204 to +213
| Top-level key | Endpoint | Readable | Covers |
| ---------------------------- | ----------------------------------------- | -------- | ----------------------------------------------------------------------------------- |
| `instance` | `/v1/instance` | Yes | Support email, home URL, allowed origins |
| `communication` | `/v1/instance/communication` | Yes | Blocked country codes and communication settings |
| `restrictions` | `/v1/instance/restrictions` | No | Allowlist / blocklist sign-up restrictions |
| `organization_settings` | `/v1/instance/organization_settings` | Yes | Organizations: enabled, membership limits, domains, creation defaults |
| `protect` | `/v1/instance/protect` | Yes | Bot protection |
| `oauth_application_settings` | `/v1/instance/oauth_application_settings` | Yes | Dynamic OAuth client registration |
| `instance_settings` | `/v1/beta_features/instance_settings` | No | `test_mode`, `progressive_sign_up`, `from_email_address`, `restricted_to_allowlist` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

API Endpoints table is missing rows for 4 of 7 documented groups.

The Payload shape table lists communication, protect, oauth_application_settings, and instance_settings as supported/readable groups, and keyless.test.ts exercises GET/PATCH routes for all of them, but the "API Endpoints (keyless mode)" table only documents /v1/instance, /v1/instance/restrictions, and /v1/instance/organization_settings. Readers relying on this table alone will miss the other supported routes.

📝 Proposed additional rows
 | Method  | Endpoint                             | Description                                                                                |
 | ------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
 | `GET`   | `/v1/instance`                       | Reads instance settings for `config pull` and for the pre-write diff.                      |
 | `PATCH` | `/v1/instance`                       | Updates instance settings. Answers `204` with no body, so the group is re-read afterwards. |
 | `PATCH` | `/v1/instance/restrictions`          | Updates sign-up restrictions (allowlist, blocklist). Write-only — no read route exists.    |
+| `GET`   | `/v1/instance/communication`         | Reads communication settings for `config pull` and for the pre-write diff.                 |
+| `PATCH` | `/v1/instance/communication`         | Updates communication settings.                                                            |
 | `GET`   | `/v1/instance/organization_settings` | Reads organization settings for `config pull` and for the pre-write diff.                  |
 | `PATCH` | `/v1/instance/organization_settings` | Updates organization settings.                                                             |
+| `GET`   | `/v1/instance/protect`               | Reads bot-protection settings for `config pull` and for the pre-write diff.                 |
+| `PATCH` | `/v1/instance/protect`               | Updates bot-protection settings.                                                           |
+| `GET`   | `/v1/instance/oauth_application_settings` | Reads dynamic OAuth client registration settings.                                     |
+| `PATCH` | `/v1/instance/oauth_application_settings` | Updates dynamic OAuth client registration settings.                                  |
+| `PATCH` | `/v1/beta_features/instance_settings` | Updates `test_mode`, `progressive_sign_up`, `from_email_address`, `restricted_to_allowlist`. Beta route; write-only. |

Also applies to: 234-244

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli-core/src/commands/config/README.md` around lines 204 - 213,
Update the “API Endpoints (keyless mode)” table to include the documented routes
for the four omitted groups: communication, protect, oauth_application_settings,
and instance_settings. Keep their endpoint paths, readability values, and
coverage descriptions consistent with the corresponding Payload shape entries
and keyless.test.ts behavior.

Comment on lines +160 to +184
/**
* Rejects flag combinations that can't both be honoured, before anything is
* bootstrapped on disk. `--keyless` and `--template` describe an application the
* CLI creates; `--login` and `--app` describe one that already exists.
*/
async function assertUsableFlags(options: InitOptions, agent: boolean): Promise<void> {
if (options.keyless && options.login) {
throwUsageError("--keyless and --login cannot be combined.");
}
if (options.keyless && options.app) {
throwUsageError(
"--keyless cannot be combined with --app. Drop --keyless to link the app, or drop --app to use temporary development keys.",
);
}
if (options.template && options.login) {
throwUsageError(
"--template applies to keyless applications and cannot be combined with --login.",
);
}
if (options.login && agent && !(await isAuthenticated())) {
throwUsageError(
"--login requires an interactive terminal to complete the browser login. Ask the user to run `clerk auth login`, then re-run `clerk init`.",
);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

--template is silently ignored whenever the resolved strategy isn't "keyless".

assertUsableFlags only rejects --template combined with --login (Line 174-178), but options.template is dropped with no warning whenever pickStrategy resolves to "authenticate" — e.g. --template b2b-saas --app app_123, or plain --template b2b-saas while already authenticated (CLERK_PLATFORM_API_KEY set or stored session) with no --keyless. runStrategy (Line 323-338) only consumes template in the "keyless" case, so the user's explicit intent is silently discarded — risky for agent scripts that assume the template was applied (e.g., expecting orgs enabled per the docs) but get a default app instead.

At minimum, mirror the existing --keyless+--app guard for --template+--app.

🐛 Proposed fix to reject the --template + --app combination
   if (options.template && options.login) {
     throwUsageError(
       "--template applies to keyless applications and cannot be combined with --login.",
     );
   }
+  if (options.template && options.app) {
+    throwUsageError(
+      "--template applies to keyless applications and cannot be combined with --app.",
+    );
+  }

The implicit-authenticated-drop case (no --keyless, no --app, but already logged in) is harder to guard upfront without extra I/O, but consider having setupKeylessApp/runStrategy warn (or pickStrategy account for template when deciding whether to force keyless) rather than silently ignoring it.

Also applies to: 317-327

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli-core/src/commands/init/index.ts` around lines 160 - 184, Update
assertUsableFlags to reject options.template combined with options.app, using
the same usage-error pattern as the existing --keyless/--app validation. Ensure
template requests are not silently discarded when runStrategy selects a
non-keyless path; preserve the existing --template/--login validation and, if
strategy selection is adjusted, make pickStrategy or runStrategy explicitly warn
or force keyless when a template is provided without --keyless.

@rafa-thayto rafa-thayto changed the title feat(keyless): make keyless the default again and let agents configure a keyless instance feat(keyless): make keyless the default and let agents configure a keyless instance Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant