From 75667dad6121f8df00502df438b8123f79804351 Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Wed, 5 Aug 2026 23:31:51 -0500 Subject: [PATCH 1/2] fix(setup)!: default the agent-setup consent prompt to No (AUTH-6734) AUTH-6734: never install skills/MCP into the user environment without explicit opt-in. The post-login/post-install setup offer already gates behind a prompt, but it defaulted to Yes, so an absent-minded Enter installed skills and MCP config into ~/.claude, ~/.cursor, etc. - Flip the "Set up now?" confirm to initialValue: false so the default answer installs nothing; the only ways anything lands are an explicit "yes" at the prompt or an explicit flag (workos setup --yes, workos skills install, workos mcp install). - On decline, print the exact manual-install commands (scoped to what was offered) instead of a one-line hint, so opting in later is self-serve. - Document the opt-in policy in the README. BREAKING CHANGE: the automatic setup offer after login/install now defaults to No; pressing Enter at the prompt declines instead of installing. Non-interactive contexts remain untouched (nothing is ever installed without --yes). --- README.md | 68 ++++++++++++++++++++++---------------- src/commands/setup.spec.ts | 33 ++++++++++++++++++ src/commands/setup.ts | 29 ++++++++++++++-- 3 files changed, 99 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 3df20538..1967f427 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Get your credentials from [dashboard.workos.com](https://dashboard.workos.com): ## CLI Options -```bash +````bash workos [command] Commands: @@ -95,43 +95,53 @@ Commands: mcp Manage the WorkOS MCP server in coding agents setup Set up WorkOS skills and the MCP server -`workos setup` installs WorkOS skills and configures the MCP server only after consent. Use `workos skills list` to check skill status, `workos mcp status` to check whether the server definition is configured, or `workos doctor --fix` to refresh stale skills. +**Nothing is installed into your coding agents without explicit opt-in.** The CLI never silently writes skills or MCP configuration into `~/.claude`, `~/.cursor`, etc. After `workos login` or `workos install`, an interactive session may offer to set up your agents — the prompt defaults to **No**, and declining (or running non-interactively) installs nothing. To opt in at any time: + +```bash +workos setup # interactive setup (skills + MCP server) +workos setup --yes # non-interactive opt-in +workos skills install # skills only +workos mcp install # MCP server only +```` + +Use `workos skills list` to check skill status, `workos mcp status` to check whether the server definition is configured, or `workos doctor --fix` to refresh stale skills you previously installed. MCP configuration and OAuth authentication are separate states. The WorkOS CLI never inspects a coding agent's credentials, so "configured" means the server definition is in place — it cannot prove that OAuth is usable in any agent. Each agent owns its own OAuth; with Codex, for example, complete or refresh it with `codex mcp login workos` in your normal host shell. See the [WorkOS MCP setup and recovery guide](https://workos.com/docs/mcp) for user-global and trusted-project-only configuration. Resource Management: - organization (org) Manage organizations - user Manage users - role Manage roles (RBAC) - permission Manage permissions (RBAC) - membership Manage organization memberships - invitation Manage user invitations - session Manage user sessions - connection Manage SSO connections - directory Manage directory sync - event Query events - audit-log Manage audit logs - feature-flag Manage feature flags - webhook Manage webhooks - config Manage redirect URIs, CORS, homepage URL - portal Generate Admin Portal links - vault Manage encrypted secrets - api-key Manage per-org API keys - org-domain Manage organization domains +organization (org) Manage organizations +user Manage users +role Manage roles (RBAC) +permission Manage permissions (RBAC) +membership Manage organization memberships +invitation Manage user invitations +session Manage user sessions +connection Manage SSO connections +directory Manage directory sync +event Query events +audit-log Manage audit logs +feature-flag Manage feature flags +webhook Manage webhooks +config Manage redirect URIs, CORS, homepage URL +portal Generate Admin Portal links +vault Manage encrypted secrets +api-key Manage per-org API keys +org-domain Manage organization domains Migrations: - migrations Migrate users and SSO connections into WorkOS +migrations Migrate users and SSO connections into WorkOS Local Development: - emulate Start a local WorkOS API emulator +emulate Start a local WorkOS API emulator Workflows: - seed Declarative resource provisioning from YAML - setup-org One-shot organization onboarding - onboard-user Send invitation and assign role - debug-sso Diagnose SSO connection issues - debug-sync Diagnose directory sync issues -``` +seed Declarative resource provisioning from YAML +setup-org One-shot organization onboarding +onboard-user Send invitation and assign role +debug-sso Diagnose SSO connection issues +debug-sync Diagnose directory sync issues + +```` All management commands support `--json` for structured output (auto-enabled in non-TTY) and `--api-key` to override the active environment's key. @@ -149,7 +159,7 @@ workos env list # Claim the environment to link it to your WorkOS account workos env claim -``` +```` Management commands work on unclaimed environments with a warning reminding you to claim. diff --git a/src/commands/setup.spec.ts b/src/commands/setup.spec.ts index 28593d6b..f92324bc 100644 --- a/src/commands/setup.spec.ts +++ b/src/commands/setup.spec.ts @@ -203,6 +203,15 @@ describe('runSetup — automatic triggers (login/install)', () => { expect(prefs.recordSetupCompleted).not.toHaveBeenCalled(); }); + it('defaults the consent prompt to No (AUTH-6734: install is explicit opt-in)', async () => { + detectSome(); + vi.mocked(ui.confirm).mockResolvedValue(false); + + await runSetup({ trigger: 'login' }); + + expect(ui.confirm).toHaveBeenCalledWith(expect.objectContaining({ initialValue: false })); + }); + it('records an absolute decline and installs nothing on "no"', async () => { detectSome(); vi.mocked(ui.confirm).mockResolvedValue(false); @@ -214,6 +223,19 @@ describe('runSetup — automatic triggers (login/install)', () => { expect(prefs.recordSetupCompleted).not.toHaveBeenCalled(); }); + it('prints manual-install instructions when the user declines', async () => { + detectSome(); + vi.mocked(ui.confirm).mockResolvedValue(false); + + await runSetup({ trigger: 'login' }); + + const hints = vi.mocked(ui.log.hint).mock.calls.map(([msg]) => String(msg)); + expect(hints.some((m) => m.includes('Nothing was installed'))).toBe(true); + expect(hints.some((m) => m.includes('workos setup'))).toBe(true); + expect(hints.some((m) => m.includes('workos skills install'))).toBe(true); + expect(hints.some((m) => m.includes('workos mcp install'))).toBe(true); + }); + it('treats cancel (ctrl-c) as skip — no decline recorded, but emits a cancelled event', async () => { detectSome(); vi.mocked(ui.confirm).mockResolvedValue(CANCEL); @@ -307,6 +329,17 @@ describe('runSetup — command trigger', () => { expect(prefs.recordSetupDeclined).not.toHaveBeenCalled(); }); + it('scopes the decline instructions to what was offered', async () => { + vi.mocked(detectAgents).mockReturnValue([claudeAgent as any]); + vi.mocked(ui.confirm).mockResolvedValue(false); + + await runSetup({ trigger: 'command', skillsOnly: true }); + + const hints = vi.mocked(ui.log.hint).mock.calls.map(([msg]) => String(msg)); + expect(hints.some((m) => m.includes('workos skills install'))).toBe(true); + expect(hints.some((m) => m.includes('workos mcp install'))).toBe(false); + }); + it('skillsOnly skips MCP detection/install', async () => { vi.mocked(detectAgents).mockReturnValue([claudeAgent as any]); vi.mocked(ui.confirm).mockResolvedValue(true); diff --git a/src/commands/setup.ts b/src/commands/setup.ts index 668e858a..efd2a6aa 100644 --- a/src/commands/setup.ts +++ b/src/commands/setup.ts @@ -15,6 +15,11 @@ * The consent contract is the whole point: nothing is written to a coding agent * unless the user says yes (or passes --yes). This replaces the auto-install * that a customer called "prompt injection malware". + * + * AUTH-6734 policy: never install silently. The consent prompt defaults to No, + * so an absent-minded Enter (or any non-answer) installs nothing; the only ways + * anything lands are an explicit "yes" at the prompt or an explicit flag + * (`workos setup --yes`, `workos skills install`, `workos mcp install`). */ import { homedir } from 'node:os'; @@ -144,7 +149,9 @@ export async function runSetup(opts: RunSetupOptions): Promise { `scaffold auth and manage WorkOS resources. Nothing is written until you confirm.`, ); - const answer = await ui.confirm({ message: 'Set up now?', initialValue: true }); + // Default MUST stay No (AUTH-6734): installation is opt-in only, so the + // default answer — what an impatient Enter produces — installs nothing. + const answer = await ui.confirm({ message: 'Set up now?', initialValue: false }); // Cancel (ctrl-c) is not a decline — skip silently and ask again next time, // but record it so the cut-off is observable in telemetry. if (isCancel(answer)) { @@ -154,7 +161,7 @@ export async function runSetup(opts: RunSetupOptions): Promise { if (!answer) { if (!isCommand) recordSetupDeclined(); emitSetupEvent(opts.trigger, startedAt, 'declined', { skills: [], mcpInstalled: [], mcpFailed: [] }); - ui.log.hint(`No problem. Run \`${formatWorkOSCommand('setup')}\` anytime.`); + printManualInstallInstructions(wantSkills, wantMcp); return; } } @@ -209,6 +216,24 @@ async function installAndReport( reportResults(skillResult ? { agents: skillAgentNames, count: skillResult.skills.length } : null, mcpResults); } +/** + * A decline is the safe default, not a dead end (AUTH-6734): always leave the + * exact manual-install commands behind so opting in later is self-serve. + * Scoped to what the offer actually covered (--skills-only / --mcp-only). + */ +function printManualInstallInstructions(wantSkills: boolean, wantMcp: boolean): void { + ui.log.hint('Nothing was installed. To install later, run any of:'); + if (wantSkills && wantMcp) { + ui.log.hint(` ${formatWorkOSCommand('setup')} skills + MCP server`); + } + if (wantSkills) { + ui.log.hint(` ${formatWorkOSCommand('skills install')} skills only`); + } + if (wantMcp) { + ui.log.hint(` ${formatWorkOSCommand('mcp install')} MCP server only`); + } +} + interface SkillSummary { agents: string[]; count: number; From b54d014957e57ca1ce3bee65985a4eb9437b842e Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Thu, 6 Aug 2026 16:05:49 -0500 Subject: [PATCH 2/2] fix: repair README markdown fence rendering (AUTH-6734) --- README.md | 61 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 1967f427..572d0394 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Get your credentials from [dashboard.workos.com](https://dashboard.workos.com): ## CLI Options -````bash +```bash workos [command] Commands: @@ -94,6 +94,7 @@ Commands: skills Manage WorkOS skills for coding agents (install, uninstall, list) mcp Manage the WorkOS MCP server in coding agents setup Set up WorkOS skills and the MCP server +``` **Nothing is installed into your coding agents without explicit opt-in.** The CLI never silently writes skills or MCP configuration into `~/.claude`, `~/.cursor`, etc. After `workos login` or `workos install`, an interactive session may offer to set up your agents — the prompt defaults to **No**, and declining (or running non-interactively) installs nothing. To opt in at any time: @@ -102,46 +103,46 @@ workos setup # interactive setup (skills + MCP server) workos setup --yes # non-interactive opt-in workos skills install # skills only workos mcp install # MCP server only -```` +``` Use `workos skills list` to check skill status, `workos mcp status` to check whether the server definition is configured, or `workos doctor --fix` to refresh stale skills you previously installed. MCP configuration and OAuth authentication are separate states. The WorkOS CLI never inspects a coding agent's credentials, so "configured" means the server definition is in place — it cannot prove that OAuth is usable in any agent. Each agent owns its own OAuth; with Codex, for example, complete or refresh it with `codex mcp login workos` in your normal host shell. See the [WorkOS MCP setup and recovery guide](https://workos.com/docs/mcp) for user-global and trusted-project-only configuration. +```text Resource Management: -organization (org) Manage organizations -user Manage users -role Manage roles (RBAC) -permission Manage permissions (RBAC) -membership Manage organization memberships -invitation Manage user invitations -session Manage user sessions -connection Manage SSO connections -directory Manage directory sync -event Query events -audit-log Manage audit logs -feature-flag Manage feature flags -webhook Manage webhooks -config Manage redirect URIs, CORS, homepage URL -portal Generate Admin Portal links -vault Manage encrypted secrets -api-key Manage per-org API keys -org-domain Manage organization domains + organization (org) Manage organizations + user Manage users + role Manage roles (RBAC) + permission Manage permissions (RBAC) + membership Manage organization memberships + invitation Manage user invitations + session Manage user sessions + connection Manage SSO connections + directory Manage directory sync + event Query events + audit-log Manage audit logs + feature-flag Manage feature flags + webhook Manage webhooks + config Manage redirect URIs, CORS, homepage URL + portal Generate Admin Portal links + vault Manage encrypted secrets + api-key Manage per-org API keys + org-domain Manage organization domains Migrations: -migrations Migrate users and SSO connections into WorkOS + migrations Migrate users and SSO connections into WorkOS Local Development: -emulate Start a local WorkOS API emulator + emulate Start a local WorkOS API emulator Workflows: -seed Declarative resource provisioning from YAML -setup-org One-shot organization onboarding -onboard-user Send invitation and assign role -debug-sso Diagnose SSO connection issues -debug-sync Diagnose directory sync issues - -```` + seed Declarative resource provisioning from YAML + setup-org One-shot organization onboarding + onboard-user Send invitation and assign role + debug-sso Diagnose SSO connection issues + debug-sync Diagnose directory sync issues +``` All management commands support `--json` for structured output (auto-enabled in non-TTY) and `--api-key` to override the active environment's key. @@ -159,7 +160,7 @@ workos env list # Claim the environment to link it to your WorkOS account workos env claim -```` +``` Management commands work on unclaimed environments with a warning reminding you to claim.