Skip to content

Commit ca258c9

Browse files
authored
refactor(cli): centralize settings and modernize ESM module system (#4)
1 parent 1146ff9 commit ca258c9

39 files changed

Lines changed: 377 additions & 392 deletions

packages/cli/bin.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#!/usr/bin/env node
22
import { satisfies } from 'semver';
3-
import { red } from './src/utils/logging';
3+
import { red } from './src/utils/logging.js';
4+
import { getSettings } from './src/lib/settings.js';
45

56
import yargs from 'yargs';
67
import { hideBin } from 'yargs/helpers';
78
import chalk from 'chalk';
89

9-
const NODE_VERSION_RANGE = '>=18.17.0';
10+
const NODE_VERSION_RANGE = getSettings().nodeVersion;
1011

1112
// Have to run this above the other imports because they are importing clack that
1213
// has the problematic imports.
@@ -17,10 +18,10 @@ if (!satisfies(process.version, NODE_VERSION_RANGE)) {
1718
process.exit(1);
1819
}
1920

20-
import type { WizardOptions } from './src/utils/types';
21-
import { runWizard } from './src/run';
22-
import { isNonInteractiveEnvironment } from './src/utils/environment';
23-
import clack from './src/utils/clack';
21+
import type { WizardOptions } from './src/utils/types.js';
22+
import { runWizard } from './src/run.js';
23+
import { isNonInteractiveEnvironment } from './src/utils/environment.js';
24+
import clack from './src/utils/clack.js';
2425

2526
// E2E tests removed - no mock server needed
2627

@@ -142,4 +143,4 @@ yargs(hideBin(process.argv))
142143
.alias('help', 'h')
143144
.version()
144145
.alias('version', 'v')
145-
.wrap(process.stdout.isTTY ? yargs.terminalWidth() : 80).argv;
146+
.wrap(process.stdout.isTTY && process.stdout.columns ? process.stdout.columns : 80).argv;

packages/cli/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "@workos/authkit-wizard",
33
"version": "1.0.0",
4+
"type": "module",
45
"description": "CLI wizard for automatically setting up WorkOS AuthKit in your project",
56
"keywords": [
67
"workos",
@@ -22,6 +23,7 @@
2223
"files": [
2324
"dist/bin.*",
2425
"dist/src",
26+
"dist/settings.json",
2527
".claude-plugin",
2628
"skills",
2729
"package.json",
@@ -37,7 +39,7 @@
3739
"@clack/core": "^0.3.4",
3840
"@clack/prompts": "0.7.0",
3941
"axios": "1.7.4",
40-
"chalk": "^2.4.1",
42+
"chalk": "^5.4.1",
4143
"fast-glob": "^3.3.3",
4244
"glob": "9.3.5",
4345
"inquirer": "^6.2.0",
@@ -64,7 +66,7 @@
6466
"@types/opn": "5.1.0",
6567
"@types/rimraf": "^3.0.2",
6668
"@types/semver": "^7.3.7",
67-
"@types/yargs": "^16.0.9",
69+
"@types/yargs": "^17.0.33",
6870
"@typescript-eslint/eslint-plugin": "^5.13.0",
6971
"@typescript-eslint/parser": "^5.13.0",
7072
"@vitest/ui": "^4.0.17",
@@ -94,7 +96,7 @@
9496
"prebuild": "pnpm clean",
9597
"build:watch": "pnpm tsc -w",
9698
"build": "pnpm tsc",
97-
"postbuild": "chmod +x ./dist/bin.js && cp -r scripts/** dist",
99+
"postbuild": "chmod +x ./dist/bin.js && cp settings.json dist/ && cp -r scripts/** dist",
98100
"lint": "pnpm lint:prettier && pnpm lint:eslint",
99101
"lint:prettier": "prettier --check \"{lib,src,test}/**/*.ts\"",
100102
"lint:eslint": "eslint . --cache --format stylish",

packages/cli/settings.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"version": "1.0.0",
3+
"model": "claude-opus-4-5-20251101",
4+
"gateway": {
5+
"development": "http://localhost:8000",
6+
"production": "https://llm-gateway.example.com",
7+
"port": 8000
8+
},
9+
"api": {
10+
"workos": {
11+
"development": "http://localhost:8000",
12+
"production": "https://api.workos.com"
13+
},
14+
"dashboard": {
15+
"development": "http://localhost:3000",
16+
"production": "https://dashboard.workos.com"
17+
}
18+
},
19+
"telemetry": {
20+
"enabled": false,
21+
"eventName": "wizard interaction"
22+
},
23+
"nodeVersion": ">=18.17.0",
24+
"logging": {
25+
"logFile": "/tmp/authkit-wizard.log",
26+
"debugMode": false
27+
},
28+
"documentation": {
29+
"workosDocsUrl": "https://workos.com/docs/authkit",
30+
"dashboardUrl": "https://dashboard.workos.com",
31+
"issuesUrl": "https://github.com/workos/authkit-wizard/issues"
32+
},
33+
"frameworks": {
34+
"nextjs": {
35+
"port": 3000,
36+
"callbackPath": "/api/auth/callback"
37+
},
38+
"react": {
39+
"port": 5173,
40+
"callbackPath": "/callback"
41+
},
42+
"tanstackStart": {
43+
"port": 3000,
44+
"callbackPath": "/api/auth/callback"
45+
},
46+
"reactRouter": {
47+
"port": 5173,
48+
"callbackPath": "/callback"
49+
},
50+
"vanillaJs": {
51+
"port": 5173,
52+
"callbackPath": "/callback"
53+
}
54+
},
55+
"legacy": {
56+
"oauthPort": 8239
57+
},
58+
"branding": {
59+
"showAsciiArt": true,
60+
"asciiArt": "░██ ░██ ░██ ░██████ ░██████ \n░██ ░██ ░██ ░██ ░██ ░██ ░██ \n░██ ░██ ░██ ░███████ ░██░████ ░██ ░██░██ ░██ ░██ \n░██ ░████ ░██ ░██ ░██ ░███ ░██ ░██ ░██ ░██ ░████████ \n░██░██ ░██░██ ░██ ░██ ░██ ░███████ ░██ ░██ ░██ \n░████ ░████ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n░███ ░███ ░███████ ░██ ░██ ░██ ░██████ ░██████ \n \n \n \n ░███ ░██ ░██ ░██ ░██ ░██ ░██ \n ░██░██ ░██ ░██ ░██ ░██ ░██ \n ░██ ░██ ░██ ░██ ░████████ ░████████ ░██ ░██ ░██░████████ \n░█████████ ░██ ░██ ░██ ░██ ░██ ░███████ ░██ ░██ \n░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n░██ ░██ ░██ ░███ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n░██ ░██ ░█████░██ ░████ ░██ ░██ ░██ ░██ ░██ ░████ "
61+
}
62+
}

packages/cli/src/lib/agent-interface.ts

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
*/
55

66
import path from 'path';
7-
import clack from '../utils/clack';
8-
import { debug, logToFile, initLogFile, LOG_FILE_PATH } from '../utils/debug';
9-
import type { WizardOptions } from '../utils/types';
10-
import { analytics } from '../utils/analytics';
11-
import { WIZARD_INTERACTION_EVENT_NAME } from './constants';
12-
import { LINTING_TOOLS } from './safe-tools';
13-
import { getLlmGatewayUrlFromHost } from '../utils/urls';
7+
import { fileURLToPath } from 'url';
8+
import clack from '../utils/clack.js';
9+
import { debug, logToFile, initLogFile, LOG_FILE_PATH } from '../utils/debug.js';
10+
import type { WizardOptions } from '../utils/types.js';
11+
import { analytics } from '../utils/analytics.js';
12+
import { WIZARD_INTERACTION_EVENT_NAME } from './constants.js';
13+
import { LINTING_TOOLS } from './safe-tools.js';
14+
import { getLlmGatewayUrlFromHost } from '../utils/urls.js';
15+
import { getSettings } from './settings.js';
1416

1517
// Dynamic import cache for ESM module
1618
let _sdkModule: any = null;
@@ -21,16 +23,6 @@ async function getSDKModule(): Promise<any> {
2123
return _sdkModule;
2224
}
2325

24-
/**
25-
* Get the path to the bundled Claude Code CLI from the SDK package.
26-
* This ensures we use the SDK's bundled version rather than the user's installed Claude Code.
27-
*/
28-
function getClaudeCodeExecutablePath(): string {
29-
// require.resolve finds the package's main entry, then we get cli.js from same dir
30-
const sdkPackagePath = require.resolve('@anthropic-ai/claude-agent-sdk');
31-
return path.join(path.dirname(sdkPackagePath), 'cli.js');
32-
}
33-
3426
// Using `any` because typed imports from ESM modules require import attributes
3527
// syntax which prettier cannot parse. See PR discussion for details.
3628
type SDKMessage = any;
@@ -254,9 +246,10 @@ export function initializeAgent(
254246
// Configure LLM gateway for Claude API calls
255247
// Local testing: use localhost LLM gateway
256248
// Production: use WorkOS production gateway
249+
const settings = getSettings();
257250
const gatewayUrl = options.local
258-
? 'http://localhost:8000'
259-
: getLlmGatewayUrlFromHost(config.workOSApiHost);
251+
? settings.gateway.development
252+
: getLlmGatewayUrlFromHost();
260253

261254
process.env.ANTHROPIC_BASE_URL = gatewayUrl;
262255
process.env.ANTHROPIC_AUTH_TOKEN = config.workOSApiKey;
@@ -279,7 +272,7 @@ export function initializeAgent(
279272
args: ['-y', '@workos/mcp-docs-server'],
280273
},
281274
},
282-
model: 'claude-opus-4-5-20251101',
275+
model: settings.model,
283276
allowedTools: [
284277
'Skill',
285278
'Read',
@@ -348,9 +341,7 @@ export async function runAgent(
348341

349342
spinner.start(spinnerMessage);
350343

351-
const cliPath = getClaudeCodeExecutablePath();
352344
logToFile('Starting agent run');
353-
logToFile('Claude Code executable:', cliPath);
354345
logToFile('Prompt:', prompt);
355346

356347
const startTime = Date.now();
@@ -379,6 +370,8 @@ export async function runAgent(
379370

380371
// Load plugin with bundled skills
381372
// Path from dist/src/lib/ back to package root
373+
const __filename = fileURLToPath(import.meta.url);
374+
const __dirname = path.dirname(__filename);
382375
const pluginPath = path.join(__dirname, '../../..');
383376
logToFile('Loading plugin from:', pluginPath);
384377

packages/cli/src/lib/agent-runner.ts

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,25 @@ import {
22
getWelcomeMessage,
33
SPINNER_MESSAGE,
44
type FrameworkConfig,
5-
} from './framework-config';
6-
import type { WizardOptions } from '../utils/types';
5+
} from './framework-config.js';
6+
import type { WizardOptions } from '../utils/types.js';
77
import {
8-
abort,
98
confirmContinueIfNoOrDirtyGitRepo,
109
ensurePackageIsInstalled,
1110
getOrAskForWorkOSCredentials,
1211
getPackageDotJson,
1312
isUsingTypeScript,
1413
printWelcome,
15-
} from '../utils/clack-utils';
16-
import { analytics } from '../utils/analytics';
17-
import { WIZARD_INTERACTION_EVENT_NAME } from './constants';
18-
import clack from '../utils/clack';
19-
import {
20-
initializeAgent,
21-
runAgent,
22-
AgentSignals,
23-
AgentErrorType,
24-
} from './agent-interface';
25-
import { getCloudUrlFromRegion } from '../utils/urls';
14+
} from '../utils/clack-utils.js';
15+
import { analytics } from '../utils/analytics.js';
16+
import { WIZARD_INTERACTION_EVENT_NAME } from './constants.js';
17+
import clack from '../utils/clack.js';
18+
import { initializeAgent, runAgent } from './agent-interface.js';
2619
import chalk from 'chalk';
27-
import { uploadEnvironmentVariablesStep } from '../steps';
28-
import { autoConfigureWorkOSEnvironment } from './workos-management';
29-
import { detectPort, getCallbackPath } from './port-detection';
30-
import { writeEnvLocal } from './env-writer';
20+
import { uploadEnvironmentVariablesStep } from '../steps/index.js';
21+
import { autoConfigureWorkOSEnvironment } from './workos-management.js';
22+
import { detectPort, getCallbackPath } from './port-detection.js';
23+
import { writeEnvLocal } from './env-writer.js';
3124

3225
/**
3326
* Universal agent-powered wizard runner.
@@ -134,7 +127,8 @@ export async function runAgentWizard(
134127
options,
135128
);
136129

137-
const agentResult = await runAgent(
130+
// Run agent - errors will throw naturally with skill-based approach
131+
await runAgent(
138132
agent,
139133
integrationPrompt,
140134
options,
@@ -146,9 +140,6 @@ export async function runAgentWizard(
146140
},
147141
);
148142

149-
// No error detection needed - we use skill-based approach
150-
// If agent fails, it will error naturally
151-
152143
// Build environment variables from WorkOS credentials
153144
const envVars = config.environment.getEnvVars(apiKey, clientId);
154145

packages/cli/src/lib/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axios, { AxiosError } from 'axios';
22
import { z } from 'zod';
3-
import { analytics } from '../utils/analytics';
3+
import { analytics } from '../utils/analytics.js';
44

55
export const ApiUserSchema = z.object({
66
distinct_id: z.string(),

packages/cli/src/lib/config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { getPackageDotJson } from '../utils/clack-utils';
2-
import { hasPackageInstalled } from '../utils/package-json';
3-
import type { WizardOptions } from '../utils/types';
4-
import { Integration } from './constants';
1+
import { getPackageDotJson } from '../utils/clack-utils.js';
2+
import { hasPackageInstalled } from '../utils/package-json.js';
3+
import type { WizardOptions } from '../utils/types.js';
4+
import { Integration } from './constants.js';
55

66
type IntegrationConfig = {
77
name: string;

packages/cli/src/lib/constants.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { getSettings } from './settings.js';
2+
13
export enum Integration {
24
nextjs = 'nextjs',
35
react = 'react',
@@ -44,15 +46,12 @@ export const IS_DEV = ['test', 'development'].includes(
4446
process.env.NODE_ENV ?? '',
4547
);
4648

47-
export const DEBUG = false;
48-
49-
export const WORKOS_DOCS_URL = 'https://workos.com/docs/authkit';
50-
export const WORKOS_DASHBOARD_URL = 'https://dashboard.workos.com';
51-
export const ISSUES_URL = 'https://github.com/workos/authkit-wizard/issues';
52-
53-
// Telemetry (disabled for now - can be enabled later)
54-
export const ANALYTICS_ENABLED = false;
55-
export const WIZARD_INTERACTION_EVENT_NAME = 'wizard interaction';
49+
const settings = getSettings();
5650

57-
// OAuth port (kept for legacy compatibility, not used by WorkOS wizard)
58-
export const OAUTH_PORT = 8239;
51+
export const DEBUG = settings.logging.debugMode;
52+
export const WORKOS_DOCS_URL = settings.documentation.workosDocsUrl;
53+
export const WORKOS_DASHBOARD_URL = settings.documentation.dashboardUrl;
54+
export const ISSUES_URL = settings.documentation.issuesUrl;
55+
export const ANALYTICS_ENABLED = settings.telemetry.enabled;
56+
export const WIZARD_INTERACTION_EVENT_NAME = settings.telemetry.eventName;
57+
export const OAUTH_PORT = settings.legacy.oauthPort;

packages/cli/src/lib/env-writer.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import {
55
unlinkSync,
66
writeFileSync,
77
mkdtempSync,
8-
} from 'fs';
9-
import { join } from 'path';
10-
import { tmpdir } from 'os';
8+
} from 'node:fs';
9+
import { join } from 'node:path';
10+
import { tmpdir } from 'node:os';
1111
import { writeEnvLocal } from './env-writer.js';
1212

1313
describe('writeEnvLocal', () => {

packages/cli/src/lib/framework-config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { Integration } from './constants';
2-
import type { WizardOptions } from '../utils/types';
1+
import type { Integration } from './constants.js';
2+
import type { WizardOptions } from '../utils/types.js';
33

44
/**
55
* Configuration interface for framework-specific agent integrations.

0 commit comments

Comments
 (0)