@runtypelabs/cli 2.29.0 → 2.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +496 -121
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -136,8 +136,8 @@ var init_credential_store = __esm({
136
136
  });
137
137
 
138
138
  // src/index.ts
139
- import { Command as Command38 } from "commander";
140
- import chalk47 from "chalk";
139
+ import { Command as Command39 } from "commander";
140
+ import chalk48 from "chalk";
141
141
 
142
142
  // src/lib/load-env.ts
143
143
  import { readFileSync } from "fs";
@@ -41975,6 +41975,14 @@ var mcpToolFulfillmentSchema = external_exports.object({
41975
41975
  rung: external_exports.literal("mcp_tool"),
41976
41976
  tool: external_exports.string(),
41977
41977
  args: external_exports.record(external_exports.string(), external_exports.unknown()),
41978
+ /**
41979
+ * Operator-supplied arguments that MUST be merged into `args` before the
41980
+ * call does anything — executing `args` alone is accepted by the tool but
41981
+ * writes nothing, so a consumer that sees this field non-empty must obtain
41982
+ * these values (from the operator or a secret store) first. Keyed by arg
41983
+ * name; the value describes what to supply.
41984
+ */
41985
+ pendingArgs: external_exports.record(external_exports.string(), external_exports.string()).optional(),
41978
41986
  summary: external_exports.string()
41979
41987
  });
41980
41988
  var restFulfillmentSchema = external_exports.object({
@@ -71871,6 +71879,7 @@ function isCI() {
71871
71879
  var SKILLS_OFFER_SKIP_COMMANDS = /* @__PURE__ */ new Set([
71872
71880
  "skills",
71873
71881
  "install-mcp",
71882
+ "onboard",
71874
71883
  "init",
71875
71884
  "login",
71876
71885
  "auth"
@@ -72611,8 +72620,6 @@ function getMcpRestartInstruction(agent) {
72611
72620
  function getMcpSkillsAgentId(agent) {
72612
72621
  return MCP_AGENT_DEFINITIONS[agent].skillsAgentId;
72613
72622
  }
72614
-
72615
- // src/commands/install-mcp.ts
72616
72623
  async function selectAgent(options, tty) {
72617
72624
  if (options.agent) {
72618
72625
  const explicit = normalizeMcpAgent(options.agent);
@@ -72648,6 +72655,8 @@ async function selectAgent(options, tty) {
72648
72655
  { promptLabel: "Agent" }
72649
72656
  );
72650
72657
  }
72658
+
72659
+ // src/commands/install-mcp.ts
72651
72660
  async function installSkillsForAgent(agent, jsonMode) {
72652
72661
  const rosieId = getMcpSkillsAgentId(agent);
72653
72662
  try {
@@ -72814,13 +72823,378 @@ Setting up Runtype for ${definition.displayName}\u2026`));
72814
72823
  if (partial2) process.exitCode = 1;
72815
72824
  });
72816
72825
 
72817
- // src/commands/apps.ts
72818
- import { readdirSync as readdirSync7, readFileSync as readFileSync20, lstatSync, statSync as statSync7, existsSync as existsSync16 } from "fs";
72819
- import { join as join14, relative as relative7 } from "path";
72826
+ // src/commands/onboard.ts
72827
+ import { existsSync as existsSync16, readFileSync as readFileSync20 } from "fs";
72828
+ import { join as join14 } from "path";
72820
72829
  import { Command as Command34 } from "commander";
72821
72830
  import chalk42 from "chalk";
72831
+
72832
+ // ../shared/dist/agent-onboarding-content.mjs
72833
+ var AGENT_ONBOARDING_MARKDOWN = `# Runtype for Coding Agents
72834
+
72835
+ You are reading the setup script served by \`https://runtype.ai\`. Your durable goal is to leave this coding harness connected to Runtype's hosted MCP server with browser OAuth. Use the Runtype CLI as a bridge during this first session; do not treat it as the final integration.
72836
+
72837
+ ## Golden path \u2014 do exactly this
72838
+
72839
+ If the live Runtype MCP tools are already available in this session, skip setup and go to "After MCP is active" below. Otherwise follow every step in order:
72840
+
72841
+ ### 1. Install and authenticate the CLI
72842
+
72843
+ \`\`\`bash
72844
+ npm install -g @runtypelabs/cli
72845
+ runtype auth login
72846
+ \`\`\`
72847
+
72848
+ Complete the browser sign-in when it opens. The CLI makes this first session productive even though a running coding harness often cannot discover a newly installed MCP connection until it restarts.
72849
+
72850
+ ### 2. Install skills and the OAuth MCP connection
72851
+
72852
+ \`\`\`bash
72853
+ runtype install-mcp
72854
+ \`\`\`
72855
+
72856
+ This command detects the current coding harness, installs the Runtype agent skills for it, writes the user-level hosted MCP configuration, and starts the harness's own OAuth flow when possible. If it asks which harness to configure, select the harness running this session. If a browser opens, have the user complete OAuth.
72857
+
72858
+ Do not manually create an API key, export the CLI key into MCP, or choose a different setup path merely to avoid a restart. CLI authentication and MCP OAuth are separate on purpose: the CLI is the first-session bridge; client-owned OAuth MCP is the durable connection.
72859
+
72860
+ ### 3. Keep working in this session with the CLI
72861
+
72862
+ Do not stop just because the new MCP connection is not visible yet. Use CLI commands for useful first-session work:
72863
+
72864
+ \`\`\`bash
72865
+ runtype auth whoami
72866
+ runtype agents list
72867
+ runtype flows list
72868
+ runtype products list
72869
+ runtype --help
72870
+ \`\`\`
72871
+
72872
+ The CLI also supports dispatch, records, validation, product setup, and other account operations. Read command help before mutating resources, and report concrete IDs and URLs to the user.
72873
+
72874
+ ### 4. Tell the user to restart or reload the harness
72875
+
72876
+ Before finishing this session, read the final status and next steps from \`runtype install-mcp\`. Complete any OAuth action it requests and retry any failed skill installation. Do not call setup complete while the command reports \`action-required\`, \`partial\`, or an error.
72877
+
72878
+ Only after skills and OAuth both succeed, tell the user exactly what changed and ask them to restart or reload the coding harness. Use direct language such as:
72879
+
72880
+ > Runtype skills and the OAuth MCP connection are installed. Please restart or reload this coding agent (or start a new session) so it can activate the new MCP tools. I used the CLI to keep this first session productive; after restart I will use MCP by default.
72881
+
72882
+ If an action remains, report that exact action instead of using the success wording above. Do not claim the running agent can use MCP until its Runtype tools actually appear.
72883
+
72884
+ ### 5. Switch to MCP after restart
72885
+
72886
+ In the next session, use Runtype MCP first. Do not fall back to the CLI just because it worked previously. Start by calling:
72887
+
72888
+ \`\`\`json
72889
+ {
72890
+ "task": "build-product",
72891
+ "description": "Describe the user's product goal here"
72892
+ }
72893
+ \`\`\`
72894
+
72895
+ with \`get_build_instructions\`. Then use \`get_platform_documentation\` for exact schemas and catalogs, create or update resources with MCP tools, validate them, and test the result with a real run.
72896
+
72897
+ ## If the install needs recovery
72898
+
72899
+ \`runtype install-mcp\` intentionally changes one confidently selected harness, not every agent config it can find. If detection is ambiguous, re-run it with one explicit id:
72900
+
72901
+ \`\`\`bash
72902
+ runtype install-mcp --agent claude
72903
+ runtype install-mcp --agent codex
72904
+ runtype install-mcp --agent cursor
72905
+ runtype install-mcp --agent gemini
72906
+ runtype install-mcp --agent opencode
72907
+ runtype install-mcp --agent vscode
72908
+ \`\`\`
72909
+
72910
+ Use only the line for the current harness. Follow the command's OAuth and restart instructions. Use \`--force\` only when the command reports that an existing MCP server named \`runtype\` points to a different URL and the user agrees to replace it.
72911
+
72912
+ ## Headless exception \u2014 not the normal path
72913
+
72914
+ Only use an API key when browser OAuth is genuinely impossible in the user's environment, not merely inconvenient. Ask the user before switching authentication modes, then follow the canonical headless registration and claim protocol at \`https://runtype.com/auth.md\`. Never print a secret into the transcript or write a bearer token directly into a committed config file.
72915
+
72916
+ The hosted MCP endpoint is \`https://api.runtype.com/v1/mcp/protocol\`. A user-supplied \`RUNTYPE_API_KEY\` can authenticate CLI commands in a headless environment, but return to client-owned OAuth MCP when the harness can support it.
72917
+
72918
+ ## After MCP is active
72919
+
72920
+ - Call \`get_build_instructions\` before building.
72921
+ - Use \`get_platform_documentation\` instead of inventing payload shapes.
72922
+ - Let the installed Runtype skills route task-specific work: product builds, live account operations, Persona embeds, templates, and SDK/CLI workflows.
72923
+ - If the user gives you a \`use.runtype.com/now?...\`, example, or template/FPO link, use the Runtype template skill and MCP tools rather than opening the login-gated dashboard page.
72924
+ - Validate before shipping and test with a real execution.
72925
+
72926
+ Runtype MCP can create and operate agents, flows, products, records, secrets, evals, and surfaces; attach built-in, HTTP, MCP, flow, and subagent tools; and ship chat, API, webhook, messaging, schedule, MCP, and hosted-page experiences.
72927
+
72928
+ Docs: [runtype.com](https://runtype.com)
72929
+ Dashboard: [use.runtype.com](https://use.runtype.com)
72930
+ API: [api.runtype.com](https://api.runtype.com)
72931
+ `;
72932
+
72933
+ // src/commands/onboard.ts
72934
+ init_credential_store();
72935
+ var AUTH_LOGIN_INSTRUCTION = "Sign in to Runtype: run `runtype auth login` (or set RUNTYPE_API_KEY), then re-run `runtype onboard`.";
72936
+ var AFTER_RESTART_STEPS = [
72937
+ "Use the Runtype MCP server first for all Runtype work.",
72938
+ "Start with the get_build_instructions tool before creating or changing resources.",
72939
+ "Do not fall back to the Runtype CLI once the MCP connection is active."
72940
+ ];
72941
+ var EXISTING_PROJECT_ADVICE = "Building AI features into an existing codebase? After restart, decide with the user whether flow/agent config should be hosted (dashboard-editable, called via the dispatch API) or code-first in this repo via the TypeScript SDK. They run on the same platform and can be mixed.";
72942
+ function detectExistingProject(cwd = process.cwd()) {
72943
+ const packageJsonPath = join14(cwd, "package.json");
72944
+ const hasPackageJson = existsSync16(packageJsonPath);
72945
+ if (!hasPackageJson && !existsSync16(join14(cwd, ".git"))) return false;
72946
+ if (hasPackageJson) {
72947
+ try {
72948
+ const parsed = JSON.parse(readFileSync20(packageJsonPath, "utf8"));
72949
+ if (parsed.name === "@runtypelabs/cli") return false;
72950
+ } catch {
72951
+ }
72952
+ }
72953
+ return true;
72954
+ }
72955
+ var defaultDependencies = {
72956
+ getEnvApiKey: () => getRuntimeApiKey(),
72957
+ getStoredCredentials: async () => {
72958
+ const credentials = await new CredentialStore().getCredentials();
72959
+ if (!credentials) return null;
72960
+ return { userId: credentials.userId, orgId: credentials.orgId };
72961
+ },
72962
+ ensureAuth,
72963
+ selectAgent,
72964
+ configureMcp: (agent, options) => configureMcpAgent(agent, options),
72965
+ authenticateMcp: (agent, options) => authenticateMcpAgent(agent, options),
72966
+ installSkills: installSkillsForAgent,
72967
+ isExistingProject: detectExistingProject,
72968
+ setExitCode: (code) => {
72969
+ process.exitCode = code;
72970
+ }
72971
+ };
72972
+ async function resolveAuth(dependencies, options) {
72973
+ if (dependencies.getEnvApiKey()) {
72974
+ return { authenticated: true, method: "env" };
72975
+ }
72976
+ const stored = await dependencies.getStoredCredentials();
72977
+ if (stored) {
72978
+ return { authenticated: true, method: "stored", userId: stored.userId, orgId: stored.orgId };
72979
+ }
72980
+ if (!options.interactiveLogin) {
72981
+ return { authenticated: false, instruction: AUTH_LOGIN_INSTRUCTION };
72982
+ }
72983
+ const apiKey = await dependencies.ensureAuth({ exitOnFailure: false });
72984
+ if (!apiKey) {
72985
+ return { authenticated: false, instruction: AUTH_LOGIN_INSTRUCTION };
72986
+ }
72987
+ const after = await dependencies.getStoredCredentials();
72988
+ return {
72989
+ authenticated: true,
72990
+ method: "browser-login",
72991
+ userId: after?.userId,
72992
+ orgId: after?.orgId
72993
+ };
72994
+ }
72995
+ function printAuthLine(auth) {
72996
+ if (!auth.authenticated) {
72997
+ console.log(chalk42.yellow(`! Not signed in. ${auth.instruction}`));
72998
+ return;
72999
+ }
73000
+ if (auth.method === "env") {
73001
+ console.log(chalk42.green("\u2713 Signed in with RUNTYPE_API_KEY from the environment."));
73002
+ return;
73003
+ }
73004
+ const identity = auth.userId ? ` (user ${auth.userId}${auth.orgId ? `, org ${auth.orgId}` : ""})` : "";
73005
+ if (auth.method === "stored") {
73006
+ console.log(chalk42.green(`\u2713 Already signed in${identity}.`));
73007
+ } else {
73008
+ console.log(chalk42.green(`\u2713 Signed in${identity}.`));
73009
+ }
73010
+ }
73011
+ function createOnboardCommand(overrides = {}) {
73012
+ const dependencies = { ...defaultDependencies, ...overrides };
73013
+ return new Command34("onboard").description("Set up Runtype for this coding agent: sign in, install skills and OAuth MCP").option("--agent <id>", "Coding agent to configure (auto-detected by default)").option("--force", 'Replace a conflicting MCP server named "runtype"').option("--dry-run", "Show the selected agent and planned changes without writing them").option("--no-login", "Skip browser sign-in and MCP OAuth").option("--no-skills", "Skip installing Runtype agent skills").option("--json", "Structured JSON output; implies --no-login").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").option("--print-instructions", "Print the canonical agent onboarding markdown and exit").action(async (options, cmd) => {
73014
+ if (options.printInstructions) {
73015
+ console.log(AGENT_ONBOARDING_MARKDOWN);
73016
+ return;
73017
+ }
73018
+ const globals = cmd.optsWithGlobals();
73019
+ const jsonMode = !!(options.json ?? globals.json);
73020
+ const tty = isTTY(options);
73021
+ const loginAllowed = !jsonMode && tty && options.login !== false;
73022
+ if (!jsonMode) {
73023
+ console.log(chalk42.cyan("\nRuntype onboarding"));
73024
+ console.log(
73025
+ "Runtype is a platform for building AI products: agents, flows, evals, and surfaces your team ships to its own users."
73026
+ );
73027
+ console.log(
73028
+ chalk42.dim(
73029
+ "This command signs you in, installs Runtype skills and the hosted OAuth MCP server, then prints next steps.\n"
73030
+ )
73031
+ );
73032
+ }
73033
+ let auth;
73034
+ try {
73035
+ auth = await resolveAuth(dependencies, {
73036
+ interactiveLogin: loginAllowed && !options.dryRun
73037
+ });
73038
+ } catch (error51) {
73039
+ const message = error51 instanceof Error ? error51.message : String(error51);
73040
+ if (jsonMode) {
73041
+ printJson({ status: "error", code: "AUTH_RESOLUTION_FAILED", error: message });
73042
+ } else {
73043
+ console.error(chalk42.red(`Could not read Runtype credentials: ${message}`));
73044
+ }
73045
+ dependencies.setExitCode(1);
73046
+ return;
73047
+ }
73048
+ if (!jsonMode) printAuthLine(auth);
73049
+ let agent;
73050
+ try {
73051
+ agent = await dependencies.selectAgent({ agent: options.agent, json: jsonMode }, tty);
73052
+ } catch (error51) {
73053
+ const message = error51 instanceof Error ? error51.message : String(error51);
73054
+ if (jsonMode) {
73055
+ printJson({ status: "error", code: "AGENT_DETECTION_FAILED", auth, error: message });
73056
+ } else {
73057
+ console.error(chalk42.red(message));
73058
+ }
73059
+ dependencies.setExitCode(1);
73060
+ return;
73061
+ }
73062
+ const definition = MCP_AGENT_DEFINITIONS[agent];
73063
+ if (!jsonMode) {
73064
+ console.log(chalk42.cyan(`
73065
+ Setting up Runtype for ${definition.displayName}\u2026`));
73066
+ }
73067
+ const configuration = await dependencies.configureMcp(agent, {
73068
+ force: options.force,
73069
+ dryRun: options.dryRun
73070
+ });
73071
+ if (!configuration.configured) {
73072
+ if (jsonMode) {
73073
+ printJson({ status: "error", code: "MCP_CONFIG_FAILED", agent, auth, configuration });
73074
+ } else {
73075
+ console.error(chalk42.red(configuration.error ?? "Could not configure Runtype MCP."));
73076
+ }
73077
+ dependencies.setExitCode(1);
73078
+ return;
73079
+ }
73080
+ if (!jsonMode) {
73081
+ if (options.dryRun) {
73082
+ console.log(chalk42.green("\u2713 Would install the user-level Runtype MCP connection."));
73083
+ } else if (configuration.changed) {
73084
+ console.log(chalk42.green("\u2713 Installed the user-level Runtype MCP connection."));
73085
+ } else {
73086
+ console.log(chalk42.green("\u2713 Runtype MCP is already configured at the correct URL."));
73087
+ }
73088
+ if (configuration.configPath) {
73089
+ console.log(chalk42.dim(` ${configuration.configPath}`));
73090
+ }
73091
+ if (configuration.backupPath) {
73092
+ console.log(chalk42.dim(` Backup: ${configuration.backupPath}`));
73093
+ }
73094
+ }
73095
+ const authentication = await dependencies.authenticateMcp(agent, {
73096
+ login: loginAllowed,
73097
+ dryRun: options.dryRun
73098
+ });
73099
+ if (!jsonMode && !options.dryRun) {
73100
+ if (authentication.authenticated) {
73101
+ console.log(chalk42.green("\u2713 MCP OAuth completed."));
73102
+ } else if (authentication.error) {
73103
+ console.log(chalk42.yellow(`! ${authentication.error}`));
73104
+ } else if (authentication.instruction) {
73105
+ console.log(chalk42.yellow(`! OAuth action required: ${authentication.instruction}`));
73106
+ }
73107
+ }
73108
+ const skills = options.skills === false || options.dryRun ? {
73109
+ status: options.dryRun ? "planned" : "skipped",
73110
+ installedAgents: [],
73111
+ failedAgents: []
73112
+ } : await dependencies.installSkills(agent, jsonMode);
73113
+ if (!jsonMode && !options.dryRun && skills.status === "error") {
73114
+ console.log(
73115
+ chalk42.yellow(
73116
+ `! Runtype MCP is configured, but skill installation failed: ${skills.error ?? "unknown error"}`
73117
+ )
73118
+ );
73119
+ }
73120
+ const restartInstruction = getMcpRestartInstruction(agent);
73121
+ const existingProject = dependencies.isExistingProject();
73122
+ const nextSteps = [];
73123
+ if (options.dryRun) {
73124
+ nextSteps.push(
73125
+ `Re-run \`runtype onboard --agent ${agent}\` without --dry-run to sign in, install skills, and configure MCP.`
73126
+ );
73127
+ } else {
73128
+ if (!auth.authenticated && auth.instruction) nextSteps.push(auth.instruction);
73129
+ if (authentication.instruction) nextSteps.push(authentication.instruction);
73130
+ if (authentication.error && !authentication.instruction) {
73131
+ nextSteps.push("Resolve the OAuth blocker reported above, then re-run `runtype onboard`.");
73132
+ }
73133
+ if (skills.status === "error") {
73134
+ nextSteps.push(
73135
+ `Retry skill installation with \`runtype skills install --agent ${getMcpSkillsAgentId(agent)}\`.`
73136
+ );
73137
+ } else if (skills.status === "skipped") {
73138
+ nextSteps.push(
73139
+ `Install the Runtype skills with \`runtype skills install --agent ${getMcpSkillsAgentId(agent)}\`.`
73140
+ );
73141
+ }
73142
+ nextSteps.push(
73143
+ "Continue this first session with the Runtype CLI; this running agent may not see the new MCP connection yet."
73144
+ );
73145
+ if (auth.authenticated && authentication.authenticated && skills.status !== "error") {
73146
+ nextSteps.push(
73147
+ `Tell the user that Runtype is set up, then ask them to restart or reload ${definition.displayName}.`
73148
+ );
73149
+ } else {
73150
+ nextSteps.push(
73151
+ "Tell the user that setup still has the action(s) above; do not call onboarding complete yet."
73152
+ );
73153
+ }
73154
+ nextSteps.push(`After completing any action above, ${restartInstruction}`);
73155
+ }
73156
+ const partial2 = !options.dryRun && (Boolean(authentication.error) || skills.status === "error");
73157
+ const status = options.dryRun ? "planned" : partial2 ? "partial" : auth.authenticated && authentication.authenticated ? "ok" : "action-required";
73158
+ if (jsonMode) {
73159
+ printJson({
73160
+ status,
73161
+ agent,
73162
+ auth,
73163
+ configuration,
73164
+ authentication,
73165
+ skills,
73166
+ activation: options.dryRun ? "not-configured" : "restart-required",
73167
+ restartInstruction,
73168
+ afterRestart: AFTER_RESTART_STEPS,
73169
+ ...existingProject ? { existingProjectAdvice: EXISTING_PROJECT_ADVICE } : {},
73170
+ nextSteps
73171
+ });
73172
+ } else {
73173
+ console.log(chalk42.bold(`
73174
+ Onboarding status: ${status}`));
73175
+ console.log(chalk42.bold("\nDo exactly this next:"));
73176
+ nextSteps.forEach((step, index) => console.log(` ${index + 1}. ${step}`));
73177
+ console.log(chalk42.bold(`
73178
+ After restarting ${definition.displayName}:`));
73179
+ AFTER_RESTART_STEPS.forEach((step) => console.log(` - ${step}`));
73180
+ if (existingProject) {
73181
+ console.log(`
73182
+ ${EXISTING_PROJECT_ADVICE}`);
73183
+ }
73184
+ console.log("");
73185
+ }
73186
+ if (partial2) dependencies.setExitCode(1);
73187
+ });
73188
+ }
73189
+ var onboardCommand = createOnboardCommand();
73190
+
73191
+ // src/commands/apps.ts
73192
+ import { readdirSync as readdirSync7, readFileSync as readFileSync21, lstatSync, statSync as statSync7, existsSync as existsSync17 } from "fs";
73193
+ import { join as join15, relative as relative7 } from "path";
73194
+ import { Command as Command35 } from "commander";
73195
+ import chalk43 from "chalk";
72822
73196
  import { zipSync } from "fflate";
72823
- var appsCommand = new Command34("apps").description(
73197
+ var appsCommand = new Command35("apps").description(
72824
73198
  "Manage Runtype Apps (hosted AI apps on *.runtype.run)"
72825
73199
  );
72826
73200
  var MANIFEST_FILENAME = "runtype.app.json";
@@ -72829,14 +73203,14 @@ function collectBundleFiles(dir) {
72829
73203
  const walk = (current) => {
72830
73204
  for (const entry of readdirSync7(current)) {
72831
73205
  if (entry.startsWith(".")) continue;
72832
- const full = join14(current, entry);
73206
+ const full = join15(current, entry);
72833
73207
  const stat2 = lstatSync(full);
72834
73208
  if (stat2.isSymbolicLink()) continue;
72835
73209
  if (stat2.isDirectory()) {
72836
73210
  if (entry === "node_modules") continue;
72837
73211
  walk(full);
72838
73212
  } else {
72839
- zippable[relative7(dir, full).split("\\").join("/")] = readFileSync20(full);
73213
+ zippable[relative7(dir, full).split("\\").join("/")] = readFileSync21(full);
72840
73214
  }
72841
73215
  }
72842
73216
  };
@@ -72847,7 +73221,7 @@ function fail(message, jsonMode, code) {
72847
73221
  if (jsonMode) {
72848
73222
  printJson({ status: "error", error: message, code });
72849
73223
  } else {
72850
- console.error(chalk42.red(message));
73224
+ console.error(chalk43.red(message));
72851
73225
  }
72852
73226
  process.exit(1);
72853
73227
  }
@@ -72872,13 +73246,13 @@ appsCommand.command("list").description("List your apps").option("--json", "Stru
72872
73246
  return;
72873
73247
  }
72874
73248
  if (data.length === 0) {
72875
- console.log(chalk42.yellow("No apps yet. Create one with `runtype apps create`."));
73249
+ console.log(chalk43.yellow("No apps yet. Create one with `runtype apps create`."));
72876
73250
  return;
72877
73251
  }
72878
73252
  for (const app of data) {
72879
- const status = app.status === "suspended" ? chalk42.red("suspended") : chalk42.green("active");
72880
- const serving = app.activeVersionId ? "" : chalk42.dim(" (no active version)");
72881
- console.log(`${chalk42.bold(app.name)} ${chalk42.dim(app.id)}`);
73253
+ const status = app.status === "suspended" ? chalk43.red("suspended") : chalk43.green("active");
73254
+ const serving = app.activeVersionId ? "" : chalk43.dim(" (no active version)");
73255
+ console.log(`${chalk43.bold(app.name)} ${chalk43.dim(app.id)}`);
72882
73256
  console.log(` ${app.url} ${status} ${app.visibility}${serving}`);
72883
73257
  }
72884
73258
  } catch (error51) {
@@ -72907,9 +73281,9 @@ appsCommand.command("create").description("Create an app (the hostname is {slug}
72907
73281
  printJson(app);
72908
73282
  return;
72909
73283
  }
72910
- console.log(chalk42.green(`Created ${app.name} (${app.id})`));
73284
+ console.log(chalk43.green(`Created ${app.name} (${app.id})`));
72911
73285
  console.log(` ${app.url}`);
72912
- console.log(chalk42.dim(" Deploy a bundle with `runtype apps deploy <dir> --app " + app.id + "`"));
73286
+ console.log(chalk43.dim(" Deploy a bundle with `runtype apps deploy <dir> --app " + app.id + "`"));
72913
73287
  } catch (error51) {
72914
73288
  fail(
72915
73289
  `Failed to create app: ${error51 instanceof Error ? error51.message : String(error51)}`,
@@ -72925,7 +73299,7 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
72925
73299
  const jsonMode = !!(options.json ?? globals.json);
72926
73300
  const apiKey = await ensureAuth();
72927
73301
  if (!apiKey) return;
72928
- if (!existsSync16(dir) || !statSync7(dir).isDirectory()) {
73302
+ if (!existsSync17(dir) || !statSync7(dir).isDirectory()) {
72929
73303
  fail(`Not a directory: ${dir}`, jsonMode, "INVALID_DIR");
72930
73304
  }
72931
73305
  let bundleFiles = {};
@@ -72955,7 +73329,7 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
72955
73329
  const client = createCliClient(apiKey);
72956
73330
  try {
72957
73331
  const zipBytes = zipSync(bundleFiles);
72958
- if (!jsonMode) console.log(chalk42.dim(`Uploading ${(zipBytes.byteLength / 1024).toFixed(1)} KB bundle...`));
73332
+ if (!jsonMode) console.log(chalk43.dim(`Uploading ${(zipBytes.byteLength / 1024).toFixed(1)} KB bundle...`));
72959
73333
  const version2 = await appsApi.uploadVersion(client, options.app, zipBytes);
72960
73334
  let app;
72961
73335
  if (options.activate) {
@@ -72973,8 +73347,8 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
72973
73347
  activated: false
72974
73348
  });
72975
73349
  } else {
72976
- console.error(chalk42.red(`Uploaded version ${version2.versionNumber}, but activation failed: ${message}`));
72977
- console.error(chalk42.dim(` Retry with \`runtype apps activate ${options.app} ${version2.id}\` (no re-upload needed).`));
73350
+ console.error(chalk43.red(`Uploaded version ${version2.versionNumber}, but activation failed: ${message}`));
73351
+ console.error(chalk43.dim(` Retry with \`runtype apps activate ${options.app} ${version2.id}\` (no re-upload needed).`));
72978
73352
  }
72979
73353
  process.exit(1);
72980
73354
  }
@@ -72984,14 +73358,14 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
72984
73358
  return;
72985
73359
  }
72986
73360
  console.log(
72987
- chalk42.green(
73361
+ chalk43.green(
72988
73362
  `Deployed version ${version2.versionNumber} (${version2.fileCount} files, ${(version2.sizeBytes / 1024).toFixed(1)} KB)`
72989
73363
  )
72990
73364
  );
72991
73365
  if (app) {
72992
- console.log(` Live at ${chalk42.bold(app.url)}`);
73366
+ console.log(` Live at ${chalk43.bold(app.url)}`);
72993
73367
  } else {
72994
- console.log(chalk42.dim(` Uploaded but not activated. Activate with \`runtype apps activate ${options.app} ${version2.id}\``));
73368
+ console.log(chalk43.dim(` Uploaded but not activated. Activate with \`runtype apps activate ${options.app} ${version2.id}\``));
72995
73369
  }
72996
73370
  } catch (error51) {
72997
73371
  fail(
@@ -73015,13 +73389,13 @@ appsCommand.command("versions <appId>").description("List an app's versions, new
73015
73389
  return;
73016
73390
  }
73017
73391
  if (data.length === 0) {
73018
- console.log(chalk42.yellow("No versions uploaded yet."));
73392
+ console.log(chalk43.yellow("No versions uploaded yet."));
73019
73393
  return;
73020
73394
  }
73021
73395
  for (const version2 of data) {
73022
- const marker = version2.status === "active" ? chalk42.green(" (active)") : "";
73396
+ const marker = version2.status === "active" ? chalk43.green(" (active)") : "";
73023
73397
  console.log(
73024
- `v${version2.versionNumber} ${chalk42.dim(version2.id)} ${version2.fileCount} files, ${(version2.sizeBytes / 1024).toFixed(1)} KB${marker}`
73398
+ `v${version2.versionNumber} ${chalk43.dim(version2.id)} ${version2.fileCount} files, ${(version2.sizeBytes / 1024).toFixed(1)} KB${marker}`
73025
73399
  );
73026
73400
  }
73027
73401
  } catch (error51) {
@@ -73044,8 +73418,8 @@ appsCommand.command("activate <appId> <versionId>").description("Activate an upl
73044
73418
  printJson({ app, version: version2 });
73045
73419
  return;
73046
73420
  }
73047
- console.log(chalk42.green(`Activated version ${version2.versionNumber}`));
73048
- console.log(` Live at ${chalk42.bold(app.url)}`);
73421
+ console.log(chalk43.green(`Activated version ${version2.versionNumber}`));
73422
+ console.log(` Live at ${chalk43.bold(app.url)}`);
73049
73423
  } catch (error51) {
73050
73424
  fail(
73051
73425
  `Activation failed: ${error51 instanceof Error ? error51.message : String(error51)}`,
@@ -73066,7 +73440,7 @@ appsCommand.command("delete <appId>").description("Permanently delete an app, it
73066
73440
  printJson({ status: "deleted", appId });
73067
73441
  return;
73068
73442
  }
73069
- console.log(chalk42.green(`Deleted ${appId}`));
73443
+ console.log(chalk43.green(`Deleted ${appId}`));
73070
73444
  } catch (error51) {
73071
73445
  fail(
73072
73446
  `Delete failed: ${error51 instanceof Error ? error51.message : String(error51)}`,
@@ -73077,17 +73451,17 @@ appsCommand.command("delete <appId>").description("Permanently delete an app, it
73077
73451
  });
73078
73452
 
73079
73453
  // src/commands/update.ts
73080
- import chalk44 from "chalk";
73081
- import { Command as Command35 } from "commander";
73454
+ import chalk45 from "chalk";
73455
+ import { Command as Command36 } from "commander";
73082
73456
 
73083
73457
  // src/lib/auto-update.ts
73084
73458
  import { spawn as spawn2 } from "child_process";
73085
73459
  import {
73086
73460
  closeSync,
73087
- existsSync as existsSync17,
73461
+ existsSync as existsSync18,
73088
73462
  mkdirSync as mkdirSync12,
73089
73463
  openSync,
73090
- readFileSync as readFileSync21,
73464
+ readFileSync as readFileSync22,
73091
73465
  readdirSync as readdirSync8,
73092
73466
  realpathSync as realpathSync3,
73093
73467
  renameSync,
@@ -73096,10 +73470,10 @@ import {
73096
73470
  writeFileSync as writeFileSync10
73097
73471
  } from "fs";
73098
73472
  import { constants as osConstants } from "os";
73099
- import { dirname as dirname10, isAbsolute as isAbsolute4, join as join15, relative as relative8, resolve as resolve12, sep as sep6 } from "path";
73473
+ import { dirname as dirname10, isAbsolute as isAbsolute4, join as join16, relative as relative8, resolve as resolve12, sep as sep6 } from "path";
73100
73474
 
73101
73475
  // src/lib/update-check.ts
73102
- import chalk43 from "chalk";
73476
+ import chalk44 from "chalk";
73103
73477
  import Conf3 from "conf";
73104
73478
  var UPDATE_CHECK_INTERVAL_MS = 60 * 60 * 1e3;
73105
73479
  var UPDATE_NOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
@@ -73193,7 +73567,7 @@ function notifyFromCachedCliUpdate(args, options = {}) {
73193
73567
  console.error(message);
73194
73568
  });
73195
73569
  notify(
73196
- `${chalk43.yellow("Update available:")} ${chalk43.red(currentVersion)} ${chalk43.gray("->")} ${chalk43.green(latestVersion)} ${chalk43.gray(`(${getUpgradeCommand()})`)}`
73570
+ `${chalk44.yellow("Update available:")} ${chalk44.red(currentVersion)} ${chalk44.gray("->")} ${chalk44.green(latestVersion)} ${chalk44.gray(`(${getUpgradeCommand()})`)}`
73197
73571
  );
73198
73572
  store.set("lastNotifiedAt", now.toISOString());
73199
73573
  store.set("lastNotifiedVersion", latestVersion);
@@ -73252,32 +73626,32 @@ function isStableCliVersion(version2) {
73252
73626
  return Boolean(version2 && /^\d+\.\d+\.\d+$/.test(version2));
73253
73627
  }
73254
73628
  function getManagedCliPaths(homeDir = getRuntypeHomeDir()) {
73255
- const root = join15(homeDir, "cli");
73629
+ const root = join16(homeDir, "cli");
73256
73630
  return {
73257
73631
  home: homeDir,
73258
73632
  root,
73259
- versions: join15(root, "versions"),
73260
- state: join15(root, "current.json"),
73261
- lock: join15(root, "update.lock"),
73262
- log: join15(root, "update.log")
73633
+ versions: join16(root, "versions"),
73634
+ state: join16(root, "current.json"),
73635
+ lock: join16(root, "update.lock"),
73636
+ log: join16(root, "update.log")
73263
73637
  };
73264
73638
  }
73265
73639
  function getVersionRoot(paths, version2) {
73266
73640
  if (!isStableCliVersion(version2)) {
73267
73641
  throw new Error(`Invalid CLI version: ${version2}`);
73268
73642
  }
73269
- return join15(paths.versions, version2);
73643
+ return join16(paths.versions, version2);
73270
73644
  }
73271
73645
  function getVersionPackageRoot(paths, version2) {
73272
- return join15(getVersionRoot(paths, version2), "node_modules", "@runtypelabs", "cli");
73646
+ return join16(getVersionRoot(paths, version2), "node_modules", "@runtypelabs", "cli");
73273
73647
  }
73274
73648
  function getVersionEntrypoint(paths, version2) {
73275
- return join15(getVersionPackageRoot(paths, version2), "dist", "index.js");
73649
+ return join16(getVersionPackageRoot(paths, version2), "dist", "index.js");
73276
73650
  }
73277
73651
  function getManagedCliState(homeDir = getRuntypeHomeDir()) {
73278
73652
  const { state } = getManagedCliPaths(homeDir);
73279
73653
  try {
73280
- const parsed = JSON.parse(readFileSync21(state, "utf8"));
73654
+ const parsed = JSON.parse(readFileSync22(state, "utf8"));
73281
73655
  return parsed && typeof parsed === "object" ? parsed : {};
73282
73656
  } catch {
73283
73657
  return {};
@@ -73296,7 +73670,7 @@ function writeManagedCliState(paths, state) {
73296
73670
  }
73297
73671
  function readInstalledPackageVersion(packageRoot) {
73298
73672
  try {
73299
- const pkg = JSON.parse(readFileSync21(join15(packageRoot, "package.json"), "utf8"));
73673
+ const pkg = JSON.parse(readFileSync22(join16(packageRoot, "package.json"), "utf8"));
73300
73674
  if (pkg.name === CLI_PACKAGE_NAME && isStableCliVersion(pkg.version)) {
73301
73675
  return pkg.version;
73302
73676
  }
@@ -73307,7 +73681,7 @@ function readInstalledPackageVersion(packageRoot) {
73307
73681
  function isHealthyManagedVersion(paths, version2) {
73308
73682
  if (!isStableCliVersion(version2)) return false;
73309
73683
  const packageRoot = getVersionPackageRoot(paths, version2);
73310
- return readInstalledPackageVersion(packageRoot) === version2 && existsSync17(getVersionEntrypoint(paths, version2));
73684
+ return readInstalledPackageVersion(packageRoot) === version2 && existsSync18(getVersionEntrypoint(paths, version2));
73311
73685
  }
73312
73686
  function isPathInside(parent, child) {
73313
73687
  const canonicalize = (path20) => {
@@ -73323,7 +73697,7 @@ function isPathInside(parent, child) {
73323
73697
  function isSourceCheckout(entrypoint) {
73324
73698
  let current = dirname10(entrypoint);
73325
73699
  for (let depth = 0; depth < 8; depth += 1) {
73326
- if (existsSync17(join15(current, ".git")) || existsSync17(join15(current, "pnpm-workspace.yaml"))) {
73700
+ if (existsSync18(join16(current, ".git")) || existsSync18(join16(current, "pnpm-workspace.yaml"))) {
73327
73701
  return true;
73328
73702
  }
73329
73703
  const parent = dirname10(current);
@@ -73335,7 +73709,7 @@ function isSourceCheckout(entrypoint) {
73335
73709
  function findProjectRoot(cwd) {
73336
73710
  let current = resolve12(cwd);
73337
73711
  while (true) {
73338
- if (existsSync17(join15(current, "package.json")) || existsSync17(join15(current, "pnpm-workspace.yaml"))) {
73712
+ if (existsSync18(join16(current, "package.json")) || existsSync18(join16(current, "pnpm-workspace.yaml"))) {
73339
73713
  return current;
73340
73714
  }
73341
73715
  const parent = dirname10(current);
@@ -73353,7 +73727,7 @@ function shouldManageInstalledCli(context = {}) {
73353
73727
  const env = context.env ?? process.env;
73354
73728
  const entrypoint = context.entrypoint ?? process.argv[1];
73355
73729
  const cwd = context.cwd ?? process.cwd();
73356
- if (!entrypoint || !existsSync17(entrypoint)) return false;
73730
+ if (!entrypoint || !existsSync18(entrypoint)) return false;
73357
73731
  if (env.NODE_ENV === "test" || Boolean(env.CI)) return false;
73358
73732
  if (env.RUNTYPE_DISABLE_AUTO_UPDATE === "true") return false;
73359
73733
  if (isEphemeralPackageRun(entrypoint, env)) return false;
@@ -73553,7 +73927,7 @@ async function installAndActivateCliVersion(version2, options = {}) {
73553
73927
  if (!releaseLock) return "busy";
73554
73928
  const commandRunner = options.commandRunner ?? defaultCommandRunner;
73555
73929
  const finalRoot = getVersionRoot(paths, version2);
73556
- const temporaryRoot = join15(paths.versions, `.${version2}-${process.pid}-${now.getTime()}`);
73930
+ const temporaryRoot = join16(paths.versions, `.${version2}-${process.pid}-${now.getTime()}`);
73557
73931
  let installed = false;
73558
73932
  try {
73559
73933
  mkdirSync12(paths.versions, { recursive: true });
@@ -73583,9 +73957,9 @@ async function installAndActivateCliVersion(version2, options = {}) {
73583
73957
  if (installResult.status !== 0) {
73584
73958
  throw installResult.error ?? new Error(`npm install exited with ${installResult.status}`);
73585
73959
  }
73586
- const temporaryPackageRoot = join15(temporaryRoot, "node_modules", "@runtypelabs", "cli");
73587
- const temporaryEntrypoint = join15(temporaryPackageRoot, "dist", "index.js");
73588
- if (readInstalledPackageVersion(temporaryPackageRoot) !== version2 || !existsSync17(temporaryEntrypoint)) {
73960
+ const temporaryPackageRoot = join16(temporaryRoot, "node_modules", "@runtypelabs", "cli");
73961
+ const temporaryEntrypoint = join16(temporaryPackageRoot, "dist", "index.js");
73962
+ if (readInstalledPackageVersion(temporaryPackageRoot) !== version2 || !existsSync18(temporaryEntrypoint)) {
73589
73963
  throw new Error(
73590
73964
  `Installed package did not contain a healthy ${CLI_PACKAGE_NAME}@${version2}`
73591
73965
  );
@@ -73610,7 +73984,7 @@ async function installAndActivateCliVersion(version2, options = {}) {
73610
73984
  `Installed CLI verification failed (expected ${version2}, got ${verifyResult.stdout.trim() || "no version"})`
73611
73985
  );
73612
73986
  }
73613
- if (existsSync17(finalRoot)) {
73987
+ if (existsSync18(finalRoot)) {
73614
73988
  const corruptRoot = `${finalRoot}.replaced-${now.getTime()}`;
73615
73989
  renameSync(finalRoot, corruptRoot);
73616
73990
  try {
@@ -73657,7 +74031,7 @@ function isAutoUpdateWorkerInvocation(args, env = process.env) {
73657
74031
  function spawnAutoUpdateWorker(version2, context = {}) {
73658
74032
  if (!isStableCliVersion(version2)) return false;
73659
74033
  const entrypoint = context.entrypoint ?? process.argv[1];
73660
- if (!entrypoint || !existsSync17(entrypoint)) return false;
74034
+ if (!entrypoint || !existsSync18(entrypoint)) return false;
73661
74035
  const paths = getManagedCliPaths();
73662
74036
  mkdirSync12(paths.root, { recursive: true });
73663
74037
  const logDescriptor = openSync(paths.log, "a", 384);
@@ -73749,9 +74123,9 @@ function rollbackManagedCli(homeDir = getRuntypeHomeDir()) {
73749
74123
  }
73750
74124
 
73751
74125
  // src/commands/update.ts
73752
- var updateCommand = new Command35("update").description("Check for, install, or roll back CLI updates").option("--check", "Check for an update without installing it").option("--rollback", "Roll back the most recent managed update").action(async (options) => {
74126
+ var updateCommand = new Command36("update").description("Check for, install, or roll back CLI updates").option("--check", "Check for an update without installing it").option("--rollback", "Roll back the most recent managed update").action(async (options) => {
73753
74127
  if (options.check && options.rollback) {
73754
- console.error(chalk44.red("Use either --check or --rollback, not both"));
74128
+ console.error(chalk45.red("Use either --check or --rollback, not both"));
73755
74129
  process.exitCode = 1;
73756
74130
  return;
73757
74131
  }
@@ -73759,10 +74133,10 @@ var updateCommand = new Command35("update").description("Check for, install, or
73759
74133
  try {
73760
74134
  const result = rollbackManagedCli();
73761
74135
  const target = result.to ?? "the package-manager-installed version";
73762
- console.log(chalk44.green(`Rolled back ${result.from} -> ${target}`));
73763
- console.log(chalk44.gray("The rollback will be used on the next invocation."));
74136
+ console.log(chalk45.green(`Rolled back ${result.from} -> ${target}`));
74137
+ console.log(chalk45.gray("The rollback will be used on the next invocation."));
73764
74138
  } catch (error51) {
73765
- console.error(chalk44.red(error51 instanceof Error ? error51.message : String(error51)));
74139
+ console.error(chalk45.red(error51 instanceof Error ? error51.message : String(error51)));
73766
74140
  process.exitCode = 1;
73767
74141
  }
73768
74142
  return;
@@ -73770,19 +74144,19 @@ var updateCommand = new Command35("update").description("Check for, install, or
73770
74144
  const currentVersion = getCliVersion();
73771
74145
  const latestVersion = await refreshCliUpdateMetadata({ force: true });
73772
74146
  if (!latestVersion) {
73773
- console.error(chalk44.red("Unable to determine the latest CLI version from npm"));
74147
+ console.error(chalk45.red("Unable to determine the latest CLI version from npm"));
73774
74148
  process.exitCode = 1;
73775
74149
  return;
73776
74150
  }
73777
74151
  const comparison = compareVersions(latestVersion, currentVersion);
73778
74152
  if (comparison <= 0) {
73779
74153
  const status = comparison === 0 ? "up to date" : "newer than the latest published version";
73780
- console.log(chalk44.green(`Runtype CLI ${currentVersion} is ${status}.`));
74154
+ console.log(chalk45.green(`Runtype CLI ${currentVersion} is ${status}.`));
73781
74155
  return;
73782
74156
  }
73783
74157
  if (options.check) {
73784
74158
  console.log(
73785
- `${chalk44.yellow("Update available:")} ${chalk44.red(currentVersion)} ${chalk44.gray("->")} ${chalk44.green(latestVersion)}`
74159
+ `${chalk45.yellow("Update available:")} ${chalk45.red(currentVersion)} ${chalk45.gray("->")} ${chalk45.green(latestVersion)}`
73786
74160
  );
73787
74161
  return;
73788
74162
  }
@@ -73790,22 +74164,22 @@ var updateCommand = new Command35("update").description("Check for, install, or
73790
74164
  try {
73791
74165
  const result = await installAndActivateCliVersion(latestVersion);
73792
74166
  if (result === "busy") {
73793
- console.log(chalk44.yellow("Another CLI update is already in progress."));
74167
+ console.log(chalk45.yellow("Another CLI update is already in progress."));
73794
74168
  return;
73795
74169
  }
73796
- console.log(chalk44.green(`Runtype CLI ${latestVersion} is ready.`));
73797
- console.log(chalk44.gray("It will be used on the next invocation."));
74170
+ console.log(chalk45.green(`Runtype CLI ${latestVersion} is ready.`));
74171
+ console.log(chalk45.gray("It will be used on the next invocation."));
73798
74172
  } catch (error51) {
73799
74173
  console.error(
73800
- chalk44.red(`CLI update failed: ${error51 instanceof Error ? error51.message : error51}`)
74174
+ chalk45.red(`CLI update failed: ${error51 instanceof Error ? error51.message : error51}`)
73801
74175
  );
73802
74176
  process.exitCode = 1;
73803
74177
  }
73804
74178
  });
73805
74179
 
73806
74180
  // src/commands/mcp.ts
73807
- import { Command as Command36, InvalidArgumentError } from "commander";
73808
- import chalk45 from "chalk";
74181
+ import { Command as Command37, InvalidArgumentError } from "commander";
74182
+ import chalk46 from "chalk";
73809
74183
 
73810
74184
  // src/lib/mcp-client.ts
73811
74185
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -74024,7 +74398,7 @@ async function resolveMcpArguments(options, dependencies = {}) {
74024
74398
  }
74025
74399
 
74026
74400
  // src/commands/mcp.ts
74027
- var defaultDependencies = {
74401
+ var defaultDependencies2 = {
74028
74402
  ensureAuth,
74029
74403
  connect: connectMcpClient,
74030
74404
  resolveArguments: resolveMcpArguments,
@@ -74073,16 +74447,16 @@ async function withMcpClient(options, dependencies, operation, authOptions) {
74073
74447
  }
74074
74448
  function printTools(tools, target) {
74075
74449
  if (tools.length === 0) {
74076
- console.log(chalk45.gray("No MCP tools found"));
74450
+ console.log(chalk46.gray("No MCP tools found"));
74077
74451
  return;
74078
74452
  }
74079
74453
  const label = target === "code" ? "Code Mode MCP Tools" : "MCP Tools";
74080
- console.log(chalk45.cyan(`${label}:`));
74454
+ console.log(chalk46.cyan(`${label}:`));
74081
74455
  for (const tool of tools) {
74082
74456
  const description = tool.description?.split("\n", 1)[0];
74083
- console.log(` ${chalk45.green(tool.name)}${description ? chalk45.gray(` \u2014 ${description}`) : ""}`);
74457
+ console.log(` ${chalk46.green(tool.name)}${description ? chalk46.gray(` \u2014 ${description}`) : ""}`);
74084
74458
  }
74085
- console.log(chalk45.dim(`
74459
+ console.log(chalk46.dim(`
74086
74460
  Total: ${tools.length} tools`));
74087
74461
  }
74088
74462
  function printTool(tool) {
@@ -74112,8 +74486,8 @@ function printCallResult(result, json2) {
74112
74486
  printJson(result);
74113
74487
  }
74114
74488
  function createMcpCommand(overrides = {}) {
74115
- const dependencies = { ...defaultDependencies, ...overrides };
74116
- const command = new Command36("mcp").description(
74489
+ const dependencies = { ...defaultDependencies2, ...overrides };
74490
+ const command = new Command37("mcp").description(
74117
74491
  "Discover and call tools on the Runtype MCP servers"
74118
74492
  );
74119
74493
  addCommonOptions(
@@ -74126,7 +74500,7 @@ function createMcpCommand(overrides = {}) {
74126
74500
  else printTools(tools, options.server);
74127
74501
  });
74128
74502
  } catch (error51) {
74129
- console.error(chalk45.red(`Failed to list MCP tools: ${errorMessage(error51)}`));
74503
+ console.error(chalk46.red(`Failed to list MCP tools: ${errorMessage(error51)}`));
74130
74504
  dependencies.setExitCode(1);
74131
74505
  }
74132
74506
  });
@@ -74144,7 +74518,7 @@ function createMcpCommand(overrides = {}) {
74144
74518
  else printTool(tool);
74145
74519
  });
74146
74520
  } catch (error51) {
74147
- console.error(chalk45.red(`Failed to inspect MCP tool: ${errorMessage(error51)}`));
74521
+ console.error(chalk46.red(`Failed to inspect MCP tool: ${errorMessage(error51)}`));
74148
74522
  dependencies.setExitCode(1);
74149
74523
  }
74150
74524
  });
@@ -74182,7 +74556,7 @@ function createMcpCommand(overrides = {}) {
74182
74556
  usesMcpStdin(options) ? { interactive: false, exitOnFailure: false } : void 0
74183
74557
  );
74184
74558
  } catch (error51) {
74185
- console.error(chalk45.red(`MCP tool call failed: ${errorMessage(error51)}`));
74559
+ console.error(chalk46.red(`MCP tool call failed: ${errorMessage(error51)}`));
74186
74560
  dependencies.setExitCode(1);
74187
74561
  }
74188
74562
  });
@@ -74193,8 +74567,8 @@ var mcpCommand = createMcpCommand();
74193
74567
  // src/commands/devices.ts
74194
74568
  import { spawn as spawn4 } from "child_process";
74195
74569
  import { readFile as readFile2 } from "fs/promises";
74196
- import { Command as Command37 } from "commander";
74197
- import chalk46 from "chalk";
74570
+ import { Command as Command38 } from "commander";
74571
+ import chalk47 from "chalk";
74198
74572
 
74199
74573
  // src/lib/device-provider.ts
74200
74574
  var DEVICE_SIDECAR_PROTOCOL_VERSION = 1;
@@ -74582,7 +74956,7 @@ var MacOSDeviceProvider = class {
74582
74956
  };
74583
74957
 
74584
74958
  // src/commands/devices.ts
74585
- var defaultDependencies2 = {
74959
+ var defaultDependencies3 = {
74586
74960
  ensureAuth,
74587
74961
  createClient: (apiKey) => createCliClient(apiKey),
74588
74962
  createProvider: () => new MacOSDeviceProvider(),
@@ -74614,8 +74988,8 @@ function isRecordedRevocationError(error51) {
74614
74988
  return detail.toLowerCase().includes("revocation was recorded");
74615
74989
  }
74616
74990
  function printCommandError(label, error51) {
74617
- console.error(chalk46.red(label));
74618
- console.error(chalk46.red(errorMessage2(error51)));
74991
+ console.error(chalk47.red(label));
74992
+ console.error(chalk47.red(errorMessage2(error51)));
74619
74993
  }
74620
74994
  function printDevice(device) {
74621
74995
  printDetail("Runtype Device", [
@@ -74665,8 +75039,8 @@ async function runTail2(logPath, lines) {
74665
75039
  });
74666
75040
  }
74667
75041
  function createDevicesCommand(overrides = {}) {
74668
- const dependencies = { ...defaultDependencies2, ...overrides };
74669
- const command = new Command37("devices").description(
75042
+ const dependencies = { ...defaultDependencies3, ...overrides };
75043
+ const command = new Command38("devices").description(
74670
75044
  "Manage local computers connected to Runtype agents"
74671
75045
  );
74672
75046
  command.command("setup").description("Install, pair, and start Runtype Device on this Mac").option("--name <name>", "Device name shown in Runtype").option("--helper-path <path>", "Install a locally built native helper (internal alpha)").option("--json", "Output as JSON").action(async (options) => {
@@ -74710,26 +75084,26 @@ function createDevicesCommand(overrides = {}) {
74710
75084
  printJson(result);
74711
75085
  return;
74712
75086
  }
74713
- console.log(chalk46.green(`Paired and started ${paired.name}`));
74714
- console.log(` Device ID: ${chalk46.green(paired.deviceId)}`);
75087
+ console.log(chalk47.green(`Paired and started ${paired.name}`));
75088
+ console.log(` Device ID: ${chalk47.green(paired.deviceId)}`);
74715
75089
  console.log(
74716
- ` Relay: ${device?.status?.online ? chalk46.green("online") : chalk46.yellow("connecting")}`
75090
+ ` Relay: ${device?.status?.online ? chalk47.green("online") : chalk47.yellow("connecting")}`
74717
75091
  );
74718
75092
  if (device?.mcpUrl) console.log(` MCP URL: ${device.mcpUrl}`);
74719
75093
  if (local.messagesDatabaseReadable !== true) {
74720
75094
  console.log(
74721
- chalk46.yellow(
75095
+ chalk47.yellow(
74722
75096
  `
74723
75097
  Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage reads.`
74724
75098
  )
74725
75099
  );
74726
75100
  }
74727
- console.log(chalk46.gray("iMessage sending remains disabled by local policy."));
75101
+ console.log(chalk47.gray("iMessage sending remains disabled by local policy."));
74728
75102
  } catch (error51) {
74729
75103
  printCommandError("Failed to set up Runtype Device", error51);
74730
75104
  if (pairedDeviceId) {
74731
75105
  console.error(
74732
- chalk46.yellow(
75106
+ chalk47.yellow(
74733
75107
  `Pairing completed as ${pairedDeviceId}, but startup did not finish. Run \`runtype devices install\` after correcting the error.`
74734
75108
  )
74735
75109
  );
@@ -74745,7 +75119,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74745
75119
  if (options.json) {
74746
75120
  printJson({ installation, service });
74747
75121
  } else {
74748
- console.log(chalk46.green("Runtype Device is installed and running"));
75122
+ console.log(chalk47.green("Runtype Device is installed and running"));
74749
75123
  console.log(` Helper: ${installation.binaryPath}`);
74750
75124
  if (typeof service.logPath === "string") console.log(` Logs: ${service.logPath}`);
74751
75125
  }
@@ -74764,13 +75138,13 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74764
75138
  return;
74765
75139
  }
74766
75140
  if (devices.length === 0) {
74767
- console.log(chalk46.gray("No paired devices"));
75141
+ console.log(chalk47.gray("No paired devices"));
74768
75142
  return;
74769
75143
  }
74770
- console.log(chalk46.cyan("Runtype Devices:"));
75144
+ console.log(chalk47.cyan("Runtype Devices:"));
74771
75145
  for (const device of devices) {
74772
75146
  const state = device.revokedAt ? "revoked" : device.status?.online ? "online" : "offline";
74773
- console.log(` ${chalk46.green(device.id)} ${device.name} ${state}`);
75147
+ console.log(` ${chalk47.green(device.id)} ${device.name} ${state}`);
74774
75148
  }
74775
75149
  } catch (error51) {
74776
75150
  printCommandError("Failed to list Runtype devices", error51);
@@ -74821,7 +75195,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74821
75195
  printJson(result);
74822
75196
  } else {
74823
75197
  console.log(
74824
- healthy ? chalk46.green("Runtype Device is healthy") : chalk46.yellow("Runtype Device needs attention")
75198
+ healthy ? chalk47.green("Runtype Device is healthy") : chalk47.yellow("Runtype Device needs attention")
74825
75199
  );
74826
75200
  console.log(` Platform supported: ${probe.supported ? "yes" : "no"}`);
74827
75201
  console.log(` Helper installed: ${probe.installed ? "yes" : "no"}`);
@@ -74833,7 +75207,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74833
75207
  );
74834
75208
  if (local.messagesDatabaseReadable !== true) {
74835
75209
  console.log(
74836
- chalk46.yellow(` Grant Full Disk Access to ${String(local.executablePath)}`)
75210
+ chalk47.yellow(` Grant Full Disk Access to ${String(local.executablePath)}`)
74837
75211
  );
74838
75212
  }
74839
75213
  }
@@ -74846,7 +75220,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74846
75220
  });
74847
75221
  command.command("policy <mode>").description("Set local iMessage send policy (allow-send or deny-send)").option("--json", "Output as JSON").action(async (mode, options) => {
74848
75222
  if (mode !== "allow-send" && mode !== "deny-send") {
74849
- console.error(chalk46.red("Policy must be allow-send or deny-send"));
75223
+ console.error(chalk47.red("Policy must be allow-send or deny-send"));
74850
75224
  dependencies.setExitCode(1);
74851
75225
  return;
74852
75226
  }
@@ -74867,15 +75241,15 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74867
75241
  if (options.json) printJson(result);
74868
75242
  else {
74869
75243
  console.log(
74870
- chalk46.green(
75244
+ chalk47.green(
74871
75245
  `Local iMessage sending is ${mode === "allow-send" ? "enabled" : "disabled"}`
74872
75246
  )
74873
75247
  );
74874
75248
  if (service)
74875
- console.log(chalk46.gray("Restarted the device service to publish capabilities."));
75249
+ console.log(chalk47.gray("Restarted the device service to publish capabilities."));
74876
75250
  else {
74877
75251
  console.log(
74878
- chalk46.yellow(
75252
+ chalk47.yellow(
74879
75253
  "The device service is not installed; run `runtype devices install` to publish this policy."
74880
75254
  )
74881
75255
  );
@@ -74906,7 +75280,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74906
75280
  });
74907
75281
  command.command("revoke <id>").description("Revoke a paired device in Runtype").option("--yes", "Confirm irreversible device revocation").option("--json", "Output as JSON").action(async (id, options) => {
74908
75282
  if (!options.yes) {
74909
- console.error(chalk46.red("Pass --yes to confirm irreversible device revocation"));
75283
+ console.error(chalk47.red("Pass --yes to confirm irreversible device revocation"));
74910
75284
  dependencies.setExitCode(1);
74911
75285
  return;
74912
75286
  }
@@ -74918,8 +75292,8 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74918
75292
  );
74919
75293
  if (options.json) printJson(device);
74920
75294
  else {
74921
- console.log(chalk46.green(`Revoked ${device.name} (${device.id})`));
74922
- console.log(chalk46.gray("If this is the local Mac, run `runtype devices reset --yes`."));
75295
+ console.log(chalk47.green(`Revoked ${device.name} (${device.id})`));
75296
+ console.log(chalk47.gray("If this is the local Mac, run `runtype devices reset --yes`."));
74923
75297
  }
74924
75298
  } catch (error51) {
74925
75299
  if (isRecordedRevocationError(error51)) {
@@ -74932,12 +75306,12 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74932
75306
  if (options.json) printJson(result);
74933
75307
  else {
74934
75308
  console.error(
74935
- chalk46.yellow(
75309
+ chalk47.yellow(
74936
75310
  `Revocation was recorded for ${id}, but relay disconnection was not confirmed.`
74937
75311
  )
74938
75312
  );
74939
75313
  console.error(
74940
- chalk46.yellow("Retry this command, and reset the local Mac if applicable.")
75314
+ chalk47.yellow("Retry this command, and reset the local Mac if applicable.")
74941
75315
  );
74942
75316
  }
74943
75317
  dependencies.setExitCode(1);
@@ -74970,7 +75344,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74970
75344
  if (entries.at(-1) === "") entries.pop();
74971
75345
  const selected = entries.slice(-lines).join("\n");
74972
75346
  if (selected) console.log(selected);
74973
- else console.log(chalk46.gray("No local device logs yet"));
75347
+ else console.log(chalk47.gray("No local device logs yet"));
74974
75348
  } catch (error51) {
74975
75349
  printCommandError("Failed to read Runtype Device logs", error51);
74976
75350
  dependencies.setExitCode(1);
@@ -74982,7 +75356,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74982
75356
  const service = await provider.invoke("uninstall");
74983
75357
  const removedBinary = options.removeBinary ? await provider.removeInstalledBinary() : false;
74984
75358
  if (options.json) printJson({ service, removedBinary });
74985
- else console.log(chalk46.green("Stopped and uninstalled the local Runtype Device service"));
75359
+ else console.log(chalk47.green("Stopped and uninstalled the local Runtype Device service"));
74986
75360
  } catch (error51) {
74987
75361
  printCommandError("Failed to uninstall Runtype Device", error51);
74988
75362
  dependencies.setExitCode(1);
@@ -74990,7 +75364,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74990
75364
  });
74991
75365
  command.command("reset").description("Clear local pairing state and rotate the native signing identity").option("--yes", "Confirm destructive local reset").option("--json", "Output as JSON").action(async (options) => {
74992
75366
  if (!options.yes) {
74993
- console.error(chalk46.red("Pass --yes to confirm destructive local reset"));
75367
+ console.error(chalk47.red("Pass --yes to confirm destructive local reset"));
74994
75368
  dependencies.setExitCode(1);
74995
75369
  return;
74996
75370
  }
@@ -74998,9 +75372,9 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
74998
75372
  const result = await dependencies.createProvider().invoke("reset", { rotateIdentity: true });
74999
75373
  if (options.json) printJson(result);
75000
75374
  else {
75001
- console.log(chalk46.green("Cleared local device state and rotated the signing identity"));
75375
+ console.log(chalk47.green("Cleared local device state and rotated the signing identity"));
75002
75376
  console.log(
75003
- chalk46.gray("Revoke the old device in Runtype if it has not already been revoked.")
75377
+ chalk47.gray("Revoke the old device in Runtype if it has not already been revoked.")
75004
75378
  );
75005
75379
  }
75006
75380
  } catch (error51) {
@@ -75031,7 +75405,7 @@ function registerGlobalOptionForwarding(program2) {
75031
75405
  // src/index.ts
75032
75406
  loadEnv();
75033
75407
  setCliTitle();
75034
- var program = new Command38();
75408
+ var program = new Command39();
75035
75409
  program.name("runtype").description("CLI for Runtype AI Platform").version(getCliVersion()).option("-v, --verbose", "Enable verbose output").option("--api-url <url>", "Override API URL").option("--json", "Output as JSON");
75036
75410
  program.addCommand(initCommand);
75037
75411
  program.addCommand(loginCommand);
@@ -75068,6 +75442,7 @@ program.addCommand(deployCommand);
75068
75442
  program.addCommand(skillsCommand);
75069
75443
  program.addCommand(updateCommand);
75070
75444
  program.addCommand(installMcpCommand);
75445
+ program.addCommand(onboardCommand);
75071
75446
  program.addCommand(mcpCommand);
75072
75447
  program.addCommand(devicesCommand);
75073
75448
  program.addCommand(appsCommand, { hidden: process.env.RUNTYPE_APPS_CLI !== "1" });
@@ -75102,17 +75477,17 @@ async function run() {
75102
75477
  run().catch((error51) => {
75103
75478
  const commanderError = error51;
75104
75479
  if (commanderError.code === "commander.missingArgument") {
75105
- console.error(chalk47.red(`Error: ${commanderError.message}`));
75480
+ console.error(chalk48.red(`Error: ${commanderError.message}`));
75106
75481
  process.exit(1);
75107
75482
  } else if (commanderError.code === "commander.unknownOption") {
75108
- console.error(chalk47.red(`Error: ${commanderError.message}`));
75483
+ console.error(chalk48.red(`Error: ${commanderError.message}`));
75109
75484
  process.exit(1);
75110
75485
  } else if (commanderError.code === "commander.unknownCommand") {
75111
75486
  process.exit(1);
75112
75487
  } else if (commanderError.code === "commander.help" || commanderError.code === "commander.helpDisplayed" || commanderError.code === "commander.version") {
75113
75488
  process.exit(0);
75114
75489
  } else {
75115
- console.error(chalk47.red("An unexpected error occurred:"));
75490
+ console.error(chalk48.red("An unexpected error occurred:"));
75116
75491
  console.error(error51);
75117
75492
  process.exit(1);
75118
75493
  }
@@ -75121,12 +75496,12 @@ async function handleNoCommand() {
75121
75496
  const store = new CredentialStore();
75122
75497
  const hasCredentials = await store.hasCredentials();
75123
75498
  if (!hasCredentials) {
75124
- console.log(chalk47.cyan("\nWelcome to Runtype CLI!\n"));
75499
+ console.log(chalk48.cyan("\nWelcome to Runtype CLI!\n"));
75125
75500
  console.log("It looks like this is your first time. Run the setup wizard:");
75126
- console.log(` ${chalk47.green("runtype init")}
75501
+ console.log(` ${chalk48.green("runtype init")}
75127
75502
  `);
75128
75503
  console.log("Or see all available commands:");
75129
- console.log(` ${chalk47.green("runtype --help")}
75504
+ console.log(` ${chalk48.green("runtype --help")}
75130
75505
  `);
75131
75506
  } else {
75132
75507
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/cli",
3
- "version": "2.29.0",
3
+ "version": "2.30.0",
4
4
  "description": "Command-line interface for Runtype AI platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -41,7 +41,7 @@
41
41
  "tsx": "^4.7.1",
42
42
  "typescript": "^6.0.3",
43
43
  "vitest": "^4.1.0",
44
- "@runtypelabs/shared": "3.4.2"
44
+ "@runtypelabs/shared": "3.4.3"
45
45
  },
46
46
  "engines": {
47
47
  "node": ">=22.12.0"