@waniwani/cli 0.0.23 → 0.0.25

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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command20 } from "commander";
4
+ import { Command as Command24 } from "commander";
5
5
 
6
6
  // src/commands/init.ts
7
7
  import { existsSync } from "fs";
@@ -687,7 +687,7 @@ var logoutCommand = new Command3("logout").description("Log out from WaniWani").
687
687
  });
688
688
 
689
689
  // src/commands/mcp/index.ts
690
- import { Command as Command15 } from "commander";
690
+ import { Command as Command19 } from "commander";
691
691
 
692
692
  // src/commands/mcp/create.ts
693
693
  import { Command as Command4 } from "commander";
@@ -730,11 +730,31 @@ async function request(method, path, options) {
730
730
  if (response.status === 204) {
731
731
  return void 0;
732
732
  }
733
- const data = await response.json();
733
+ let data;
734
+ let rawBody;
735
+ try {
736
+ rawBody = await response.text();
737
+ data = JSON.parse(rawBody);
738
+ } catch {
739
+ throw new ApiError(
740
+ rawBody || `Request failed with status ${response.status}`,
741
+ "API_ERROR",
742
+ response.status,
743
+ { statusText: response.statusText }
744
+ );
745
+ }
734
746
  if (!response.ok || data.error) {
735
- const error = data.error || {
736
- code: "API_ERROR",
737
- message: `Request failed with status ${response.status}`
747
+ const errorMessage = data.error?.message || data.message || data.error || rawBody || `Request failed with status ${response.status}`;
748
+ const errorCode = data.error?.code || data.code || "API_ERROR";
749
+ const errorDetails = {
750
+ ...data.error?.details,
751
+ statusText: response.statusText,
752
+ ...data.error ? {} : { rawResponse: data }
753
+ };
754
+ const error = {
755
+ code: errorCode,
756
+ message: errorMessage,
757
+ details: errorDetails
738
758
  };
739
759
  if (response.status === 401) {
740
760
  const refreshed = await auth.tryRefreshToken();
@@ -794,10 +814,41 @@ var createCommand = new Command4("create").description("Create a new MCP sandbox
794
814
  }
795
815
  });
796
816
 
797
- // src/commands/mcp/deploy.ts
817
+ // src/commands/mcp/delete.ts
798
818
  import { Command as Command5 } from "commander";
799
819
  import ora3 from "ora";
800
- var deployCommand = new Command5("deploy").description("Deploy MCP server to GitHub + Vercel from sandbox").option("--repo <name>", "GitHub repository name").option("--org <name>", "GitHub organization").option("--private", "Create private repository").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
820
+ var deleteCommand = new Command5("delete").description("Delete the MCP sandbox").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
821
+ const globalOptions = command.optsWithGlobals();
822
+ const json = globalOptions.json ?? false;
823
+ try {
824
+ let mcpId = options.mcpId;
825
+ if (!mcpId) {
826
+ mcpId = await config.getMcpId();
827
+ if (!mcpId) {
828
+ throw new McpError("No active MCP. Use --mcp-id to specify one.");
829
+ }
830
+ }
831
+ const spinner = ora3("Deleting MCP sandbox...").start();
832
+ await api.delete(`/api/mcp/sandboxes/${mcpId}`);
833
+ spinner.succeed("MCP sandbox deleted");
834
+ if (await config.getMcpId() === mcpId) {
835
+ await config.setMcpId(null);
836
+ }
837
+ if (json) {
838
+ formatOutput({ deleted: mcpId }, true);
839
+ } else {
840
+ formatSuccess("MCP sandbox deleted and cleaned up.", false);
841
+ }
842
+ } catch (error) {
843
+ handleError(error, json);
844
+ process.exit(1);
845
+ }
846
+ });
847
+
848
+ // src/commands/mcp/deploy.ts
849
+ import { Command as Command6 } from "commander";
850
+ import ora4 from "ora";
851
+ var deployCommand = new Command6("deploy").description("Deploy MCP server to GitHub + Vercel from sandbox").option("--repo <name>", "GitHub repository name").option("--org <name>", "GitHub organization").option("--private", "Create private repository").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
801
852
  const globalOptions = command.optsWithGlobals();
802
853
  const json = globalOptions.json ?? false;
803
854
  try {
@@ -810,7 +861,7 @@ var deployCommand = new Command5("deploy").description("Deploy MCP server to Git
810
861
  );
811
862
  }
812
863
  }
813
- const spinner = ora3("Deploying to GitHub...").start();
864
+ const spinner = ora4("Deploying to GitHub...").start();
814
865
  const result = await api.post(
815
866
  `/api/admin/mcps/${mcpId}/deploy`,
816
867
  {
@@ -841,71 +892,14 @@ var deployCommand = new Command5("deploy").description("Deploy MCP server to Git
841
892
  }
842
893
  });
843
894
 
844
- // src/commands/mcp/list.ts
845
- import chalk4 from "chalk";
846
- import { Command as Command6 } from "commander";
847
- import ora4 from "ora";
848
- var listCommand = new Command6("list").description("List all MCPs in your organization").option("--all", "Include stopped/expired MCPs").action(async (options, command) => {
849
- const globalOptions = command.optsWithGlobals();
850
- const json = globalOptions.json ?? false;
851
- try {
852
- const spinner = ora4("Fetching MCPs...").start();
853
- const mcps = await api.get(
854
- `/api/mcp/sandboxes${options.all ? "?all=true" : ""}`
855
- );
856
- spinner.stop();
857
- const activeMcpId = await config.getMcpId();
858
- if (json) {
859
- formatOutput(
860
- {
861
- mcps: mcps.map((m) => ({
862
- ...m,
863
- isActive: m.id === activeMcpId
864
- })),
865
- activeMcpId
866
- },
867
- true
868
- );
869
- } else {
870
- if (mcps.length === 0) {
871
- console.log("No MCPs found.");
872
- console.log("\nCreate a new MCP sandbox: waniwani mcp create <name>");
873
- return;
874
- }
875
- console.log(chalk4.bold("\nMCPs:\n"));
876
- const rows = mcps.map((m) => {
877
- const isActive = m.id === activeMcpId;
878
- const statusColor = m.status === "active" ? chalk4.green : m.status === "stopped" ? chalk4.red : chalk4.yellow;
879
- return [
880
- isActive ? chalk4.cyan(`* ${m.id.slice(0, 8)}`) : ` ${m.id.slice(0, 8)}`,
881
- m.name,
882
- statusColor(m.status),
883
- m.previewUrl,
884
- m.createdAt ? new Date(m.createdAt).toLocaleString() : "N/A"
885
- ];
886
- });
887
- formatTable(
888
- ["ID", "Name", "Status", "Preview URL", "Created"],
889
- rows,
890
- false
891
- );
892
- console.log();
893
- if (activeMcpId) {
894
- console.log(`Active MCP: ${chalk4.cyan(activeMcpId.slice(0, 8))}`);
895
- }
896
- console.log("\nSelect an MCP: waniwani mcp use <name>");
897
- }
898
- } catch (error) {
899
- handleError(error, json);
900
- process.exit(1);
901
- }
902
- });
895
+ // src/commands/mcp/file/index.ts
896
+ import { Command as Command10 } from "commander";
903
897
 
904
- // src/commands/mcp/list-files.ts
905
- import chalk5 from "chalk";
898
+ // src/commands/mcp/file/list.ts
899
+ import chalk4 from "chalk";
906
900
  import { Command as Command7 } from "commander";
907
901
  import ora5 from "ora";
908
- var listFilesCommand = new Command7("list-files").description("List files in the MCP sandbox").argument("[path]", "Directory path (defaults to /app)", "/app").option("--mcp-id <id>", "Specific MCP ID").action(async (path, options, command) => {
902
+ var listCommand = new Command7("list").description("List files in the MCP sandbox").argument("[path]", "Directory path (defaults to /app)", "/app").option("--mcp-id <id>", "Specific MCP ID").action(async (path, options, command) => {
909
903
  const globalOptions = command.optsWithGlobals();
910
904
  const json = globalOptions.json ?? false;
911
905
  try {
@@ -926,15 +920,15 @@ var listFilesCommand = new Command7("list-files").description("List files in the
926
920
  if (json) {
927
921
  formatOutput(result, true);
928
922
  } else {
929
- console.log(chalk5.bold(`
923
+ console.log(chalk4.bold(`
930
924
  Directory: ${result.path}
931
925
  `));
932
926
  if (result.entries.length === 0) {
933
927
  console.log(" (empty)");
934
928
  } else {
935
929
  const rows = result.entries.map((entry) => {
936
- const name = entry.type === "directory" ? chalk5.blue(`${entry.name}/`) : entry.name;
937
- const size = entry.type === "directory" ? chalk5.gray("<dir>") : formatSize(entry.size);
930
+ const name = entry.type === "directory" ? chalk4.blue(`${entry.name}/`) : entry.name;
931
+ const size = entry.type === "directory" ? chalk4.gray("<dir>") : formatSize(entry.size);
938
932
  return [name, size];
939
933
  });
940
934
  formatTable(["Name", "Size"], rows, false);
@@ -953,11 +947,11 @@ function formatSize(bytes) {
953
947
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
954
948
  }
955
949
 
956
- // src/commands/mcp/read-file.ts
950
+ // src/commands/mcp/file/read.ts
957
951
  import { writeFile as writeFile4 } from "fs/promises";
958
952
  import { Command as Command8 } from "commander";
959
953
  import ora6 from "ora";
960
- var readFileCommand = new Command8("read-file").description("Read a file from the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--output <file>", "Write to local file instead of stdout").option("--base64", "Output as base64 (for binary files)").action(async (path, options, command) => {
954
+ var readCommand = new Command8("read").description("Read a file from the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--output <file>", "Write to local file instead of stdout").option("--base64", "Output as base64 (for binary files)").action(async (path, options, command) => {
961
955
  const globalOptions = command.optsWithGlobals();
962
956
  const json = globalOptions.json ?? false;
963
957
  try {
@@ -1001,11 +995,281 @@ var readFileCommand = new Command8("read-file").description("Read a file from th
1001
995
  }
1002
996
  });
1003
997
 
1004
- // src/commands/mcp/run-command.ts
1005
- import chalk6 from "chalk";
998
+ // src/commands/mcp/file/write.ts
999
+ import { readFile as readFile3 } from "fs/promises";
1006
1000
  import { Command as Command9 } from "commander";
1007
1001
  import ora7 from "ora";
1008
- var runCommandCommand = new Command9("run-command").description("Run a command in the MCP sandbox").argument("<command>", "Command to run").argument("[args...]", "Command arguments").option("--mcp-id <id>", "Specific MCP ID").option("--cwd <path>", "Working directory").option(
1002
+ var writeCommand = new Command9("write").description("Write a file to the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--content <content>", "Content to write").option("--file <localFile>", "Local file to upload").option("--base64", "Treat content as base64 encoded").action(async (path, options, command) => {
1003
+ const globalOptions = command.optsWithGlobals();
1004
+ const json = globalOptions.json ?? false;
1005
+ try {
1006
+ let mcpId = options.mcpId;
1007
+ if (!mcpId) {
1008
+ mcpId = await config.getMcpId();
1009
+ if (!mcpId) {
1010
+ throw new McpError(
1011
+ "No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
1012
+ );
1013
+ }
1014
+ }
1015
+ let content;
1016
+ let encoding = "utf8";
1017
+ if (options.content) {
1018
+ content = options.content;
1019
+ if (options.base64) {
1020
+ encoding = "base64";
1021
+ }
1022
+ } else if (options.file) {
1023
+ const fileBuffer = await readFile3(options.file);
1024
+ if (options.base64) {
1025
+ content = fileBuffer.toString("base64");
1026
+ encoding = "base64";
1027
+ } else {
1028
+ content = fileBuffer.toString("utf8");
1029
+ }
1030
+ } else {
1031
+ throw new CLIError(
1032
+ "Either --content or --file is required",
1033
+ "MISSING_CONTENT"
1034
+ );
1035
+ }
1036
+ const spinner = ora7(`Writing ${path}...`).start();
1037
+ const result = await api.post(
1038
+ `/api/mcp/sandboxes/${mcpId}/files`,
1039
+ {
1040
+ files: [{ path, content, encoding }]
1041
+ }
1042
+ );
1043
+ spinner.succeed(`Wrote ${path}`);
1044
+ if (json) {
1045
+ formatOutput(result, true);
1046
+ } else {
1047
+ formatSuccess(`File written: ${path}`, false);
1048
+ }
1049
+ } catch (error) {
1050
+ handleError(error, json);
1051
+ process.exit(1);
1052
+ }
1053
+ });
1054
+
1055
+ // src/commands/mcp/file/index.ts
1056
+ var fileCommand = new Command10("file").description("File operations in MCP sandbox").addCommand(readCommand).addCommand(writeCommand).addCommand(listCommand);
1057
+
1058
+ // src/commands/mcp/list.ts
1059
+ import chalk5 from "chalk";
1060
+ import { Command as Command11 } from "commander";
1061
+ import ora8 from "ora";
1062
+ var listCommand2 = new Command11("list").description("List all MCPs in your organization").option("--all", "Include stopped/expired MCPs").action(async (options, command) => {
1063
+ const globalOptions = command.optsWithGlobals();
1064
+ const json = globalOptions.json ?? false;
1065
+ try {
1066
+ const spinner = ora8("Fetching MCPs...").start();
1067
+ const mcps = await api.get(
1068
+ `/api/mcp/sandboxes${options.all ? "?all=true" : ""}`
1069
+ );
1070
+ spinner.stop();
1071
+ const activeMcpId = await config.getMcpId();
1072
+ if (json) {
1073
+ formatOutput(
1074
+ {
1075
+ mcps: mcps.map((m) => ({
1076
+ ...m,
1077
+ isActive: m.id === activeMcpId
1078
+ })),
1079
+ activeMcpId
1080
+ },
1081
+ true
1082
+ );
1083
+ } else {
1084
+ if (mcps.length === 0) {
1085
+ console.log("No MCPs found.");
1086
+ console.log("\nCreate a new MCP sandbox: waniwani mcp create <name>");
1087
+ return;
1088
+ }
1089
+ console.log(chalk5.bold("\nMCPs:\n"));
1090
+ const rows = mcps.map((m) => {
1091
+ const isActive = m.id === activeMcpId;
1092
+ const statusColor = m.status === "active" ? chalk5.green : m.status === "stopped" ? chalk5.red : chalk5.yellow;
1093
+ return [
1094
+ isActive ? chalk5.cyan(`* ${m.id.slice(0, 8)}`) : ` ${m.id.slice(0, 8)}`,
1095
+ m.name,
1096
+ statusColor(m.status),
1097
+ m.previewUrl,
1098
+ m.createdAt ? new Date(m.createdAt).toLocaleString() : "N/A"
1099
+ ];
1100
+ });
1101
+ formatTable(
1102
+ ["ID", "Name", "Status", "Preview URL", "Created"],
1103
+ rows,
1104
+ false
1105
+ );
1106
+ console.log();
1107
+ if (activeMcpId) {
1108
+ console.log(`Active MCP: ${chalk5.cyan(activeMcpId.slice(0, 8))}`);
1109
+ }
1110
+ console.log("\nSelect an MCP: waniwani mcp use <name>");
1111
+ }
1112
+ } catch (error) {
1113
+ handleError(error, json);
1114
+ process.exit(1);
1115
+ }
1116
+ });
1117
+
1118
+ // src/commands/mcp/logs.ts
1119
+ import chalk6 from "chalk";
1120
+ import { Command as Command12 } from "commander";
1121
+ import ora9 from "ora";
1122
+ var logsCommand = new Command12("logs").description("Stream logs from the MCP server").argument("[cmdId]", "Command ID (defaults to running server)").option("--mcp-id <id>", "Specific MCP ID").option("-f, --follow", "Keep streaming logs (default)", true).option("--no-follow", "Fetch logs and exit").action(async (cmdIdArg, options, command) => {
1123
+ const globalOptions = command.optsWithGlobals();
1124
+ const json = globalOptions.json ?? false;
1125
+ let reader;
1126
+ const cleanup = () => {
1127
+ if (reader) {
1128
+ reader.cancel().catch(() => {
1129
+ });
1130
+ }
1131
+ process.exit(0);
1132
+ };
1133
+ process.on("SIGINT", cleanup);
1134
+ process.on("SIGTERM", cleanup);
1135
+ try {
1136
+ let mcpId = options.mcpId;
1137
+ if (!mcpId) {
1138
+ mcpId = await config.getMcpId();
1139
+ if (!mcpId) {
1140
+ throw new McpError(
1141
+ "No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
1142
+ );
1143
+ }
1144
+ }
1145
+ const token = await auth.getAccessToken();
1146
+ if (!token) {
1147
+ throw new AuthError(
1148
+ "Not logged in. Run 'waniwani login' to authenticate."
1149
+ );
1150
+ }
1151
+ let cmdId = cmdIdArg;
1152
+ if (!cmdId) {
1153
+ const spinner = ora9("Getting server status...").start();
1154
+ const status = await api.post(
1155
+ `/api/mcp/sandboxes/${mcpId}/server`,
1156
+ { action: "status" }
1157
+ );
1158
+ spinner.stop();
1159
+ if (!status.running || !status.cmdId) {
1160
+ throw new McpError(
1161
+ "No server is running. Run 'waniwani mcp start' first."
1162
+ );
1163
+ }
1164
+ cmdId = status.cmdId;
1165
+ }
1166
+ const baseUrl = await api.getBaseUrl();
1167
+ const streamParam = options.follow ? "?stream=true" : "";
1168
+ const url = `${baseUrl}/api/mcp/sandboxes/${mcpId}/commands/${cmdId}${streamParam}`;
1169
+ if (!json) {
1170
+ console.log(chalk6.gray(`Streaming logs for command ${cmdId}...`));
1171
+ console.log(chalk6.gray("Press Ctrl+C to stop\n"));
1172
+ }
1173
+ const response = await fetch(url, {
1174
+ method: "GET",
1175
+ headers: {
1176
+ Authorization: `Bearer ${token}`,
1177
+ Accept: options.follow ? "text/event-stream" : "application/json"
1178
+ }
1179
+ });
1180
+ if (!response.ok) {
1181
+ const error = await response.json().catch(() => ({ message: response.statusText }));
1182
+ throw new Error(
1183
+ error.message || `Request failed with status ${response.status}`
1184
+ );
1185
+ }
1186
+ if (!options.follow) {
1187
+ const data = await response.json();
1188
+ if (json) {
1189
+ formatOutput(data, true);
1190
+ } else {
1191
+ if (data.stdout) {
1192
+ process.stdout.write(data.stdout);
1193
+ }
1194
+ if (data.stderr) {
1195
+ process.stderr.write(chalk6.red(data.stderr));
1196
+ }
1197
+ if (data.exitCode !== void 0) {
1198
+ console.log(chalk6.gray(`
1199
+ Exit code: ${data.exitCode}`));
1200
+ }
1201
+ }
1202
+ return;
1203
+ }
1204
+ reader = response.body?.getReader();
1205
+ if (!reader) {
1206
+ throw new Error("No response body");
1207
+ }
1208
+ const decoder = new TextDecoder();
1209
+ let buffer = "";
1210
+ const collectedLogs = [];
1211
+ while (true) {
1212
+ const { done, value } = await reader.read();
1213
+ if (done) break;
1214
+ buffer += decoder.decode(value, { stream: true });
1215
+ const lines = buffer.split("\n");
1216
+ buffer = lines.pop() || "";
1217
+ for (const line of lines) {
1218
+ if (line.startsWith("event: ")) {
1219
+ continue;
1220
+ }
1221
+ if (line.startsWith("data: ")) {
1222
+ const data = line.slice(6);
1223
+ if (!data || data === "[DONE]") continue;
1224
+ try {
1225
+ const event = JSON.parse(data);
1226
+ collectedLogs.push(event);
1227
+ if (json) {
1228
+ continue;
1229
+ }
1230
+ if (event.cmdId) {
1231
+ continue;
1232
+ }
1233
+ if (event.stream && event.data !== void 0) {
1234
+ if (event.stream === "stdout") {
1235
+ process.stdout.write(event.data);
1236
+ } else if (event.stream === "stderr") {
1237
+ process.stderr.write(chalk6.red(event.data));
1238
+ }
1239
+ }
1240
+ if (event.exitCode !== void 0) {
1241
+ const exitColor = event.exitCode === 0 ? chalk6.green : chalk6.red;
1242
+ console.log(
1243
+ exitColor(`
1244
+ Process exited with code ${event.exitCode}`)
1245
+ );
1246
+ }
1247
+ if (event.error) {
1248
+ console.error(chalk6.red(`
1249
+ Error: ${event.error}`));
1250
+ }
1251
+ } catch {
1252
+ }
1253
+ }
1254
+ }
1255
+ }
1256
+ if (json) {
1257
+ formatOutput(collectedLogs, true);
1258
+ }
1259
+ } catch (error) {
1260
+ handleError(error, json);
1261
+ process.exit(1);
1262
+ } finally {
1263
+ process.off("SIGINT", cleanup);
1264
+ process.off("SIGTERM", cleanup);
1265
+ }
1266
+ });
1267
+
1268
+ // src/commands/mcp/run-command.ts
1269
+ import chalk7 from "chalk";
1270
+ import { Command as Command13 } from "commander";
1271
+ import ora10 from "ora";
1272
+ var runCommandCommand = new Command13("run-command").description("Run a command in the MCP sandbox").argument("<command>", "Command to run").argument("[args...]", "Command arguments").option("--mcp-id <id>", "Specific MCP ID").option("--cwd <path>", "Working directory").option(
1009
1273
  "--timeout <ms>",
1010
1274
  "Command timeout in milliseconds (default: 30000, max: 300000)"
1011
1275
  ).action(async (cmd, args, options, command) => {
@@ -1022,9 +1286,9 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
1022
1286
  }
1023
1287
  }
1024
1288
  const timeout = options.timeout ? Number.parseInt(options.timeout, 10) : void 0;
1025
- const spinner = ora7(`Running: ${cmd} ${args.join(" ")}`.trim()).start();
1289
+ const spinner = ora10(`Running: ${cmd} ${args.join(" ")}`.trim()).start();
1026
1290
  const result = await api.post(
1027
- `/api/mcp/sandboxes/${mcpId}/command`,
1291
+ `/api/mcp/sandboxes/${mcpId}/commands`,
1028
1292
  {
1029
1293
  command: cmd,
1030
1294
  args: args.length > 0 ? args : void 0,
@@ -1037,7 +1301,7 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
1037
1301
  formatOutput(result, true);
1038
1302
  } else {
1039
1303
  const cmdLine = [cmd, ...args].join(" ");
1040
- console.log(chalk6.gray(`$ ${cmdLine}`));
1304
+ console.log(chalk7.gray(`$ ${cmdLine}`));
1041
1305
  console.log();
1042
1306
  if (result.stdout) {
1043
1307
  process.stdout.write(result.stdout);
@@ -1046,16 +1310,16 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
1046
1310
  }
1047
1311
  }
1048
1312
  if (result.stderr) {
1049
- process.stderr.write(chalk6.red(result.stderr));
1313
+ process.stderr.write(chalk7.red(result.stderr));
1050
1314
  if (!result.stderr.endsWith("\n")) {
1051
1315
  process.stderr.write("\n");
1052
1316
  }
1053
1317
  }
1054
1318
  console.log();
1055
- const exitColor = result.exitCode === 0 ? chalk6.green : chalk6.red;
1319
+ const exitColor = result.exitCode === 0 ? chalk7.green : chalk7.red;
1056
1320
  console.log(
1057
1321
  exitColor(`Exit code: ${result.exitCode}`),
1058
- chalk6.gray(`(${(result.duration / 1e3).toFixed(2)}s)`)
1322
+ chalk7.gray(`(${(result.duration / 1e3).toFixed(2)}s)`)
1059
1323
  );
1060
1324
  }
1061
1325
  if (result.exitCode !== 0) {
@@ -1067,11 +1331,56 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
1067
1331
  }
1068
1332
  });
1069
1333
 
1334
+ // src/commands/mcp/start.ts
1335
+ import chalk8 from "chalk";
1336
+ import { Command as Command14 } from "commander";
1337
+ import ora11 from "ora";
1338
+ var startCommand = new Command14("start").description("Start the MCP server (npm run dev)").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
1339
+ const globalOptions = command.optsWithGlobals();
1340
+ const json = globalOptions.json ?? false;
1341
+ try {
1342
+ let mcpId = options.mcpId;
1343
+ if (!mcpId) {
1344
+ mcpId = await config.getMcpId();
1345
+ if (!mcpId) {
1346
+ throw new McpError(
1347
+ "No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
1348
+ );
1349
+ }
1350
+ }
1351
+ const spinner = ora11("Starting MCP server...").start();
1352
+ const result = await api.post(
1353
+ `/api/mcp/sandboxes/${mcpId}/server`,
1354
+ { action: "start" }
1355
+ );
1356
+ spinner.succeed("MCP server started");
1357
+ if (json) {
1358
+ formatOutput(result, true);
1359
+ } else {
1360
+ console.log();
1361
+ formatList(
1362
+ [
1363
+ { label: "Command ID", value: result.cmdId },
1364
+ { label: "Preview URL", value: chalk8.cyan(result.previewUrl) }
1365
+ ],
1366
+ false
1367
+ );
1368
+ console.log();
1369
+ console.log(
1370
+ chalk8.gray("Run 'waniwani mcp logs' to stream server output")
1371
+ );
1372
+ }
1373
+ } catch (error) {
1374
+ handleError(error, json);
1375
+ process.exit(1);
1376
+ }
1377
+ });
1378
+
1070
1379
  // src/commands/mcp/status.ts
1071
- import chalk7 from "chalk";
1072
- import { Command as Command10 } from "commander";
1073
- import ora8 from "ora";
1074
- var statusCommand = new Command10("status").description("Show current MCP sandbox status").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
1380
+ import chalk9 from "chalk";
1381
+ import { Command as Command15 } from "commander";
1382
+ import ora12 from "ora";
1383
+ var statusCommand = new Command15("status").description("Show current MCP sandbox status").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
1075
1384
  const globalOptions = command.optsWithGlobals();
1076
1385
  const json = globalOptions.json ?? false;
1077
1386
  try {
@@ -1084,13 +1393,24 @@ var statusCommand = new Command10("status").description("Show current MCP sandbo
1084
1393
  );
1085
1394
  }
1086
1395
  }
1087
- const spinner = ora8("Fetching MCP status...").start();
1088
- const result = await api.get(`/api/mcp/sandboxes/${mcpId}`);
1396
+ const spinner = ora12("Fetching MCP status...").start();
1397
+ const [result, serverStatus] = await Promise.all([
1398
+ api.get(`/api/mcp/sandboxes/${mcpId}`),
1399
+ api.post(`/api/mcp/sandboxes/${mcpId}/server`, {
1400
+ action: "status"
1401
+ }).catch(() => ({
1402
+ running: false,
1403
+ cmdId: void 0,
1404
+ previewUrl: void 0
1405
+ }))
1406
+ ]);
1089
1407
  spinner.stop();
1090
1408
  if (json) {
1091
- formatOutput(result, true);
1409
+ formatOutput({ ...result, server: serverStatus }, true);
1092
1410
  } else {
1093
- const statusColor = result.status === "active" ? chalk7.green : chalk7.red;
1411
+ const statusColor = result.status === "active" ? chalk9.green : chalk9.red;
1412
+ const serverRunning = serverStatus.running;
1413
+ const serverStatusColor = serverRunning ? chalk9.green : chalk9.yellow;
1094
1414
  formatList(
1095
1415
  [
1096
1416
  { label: "MCP ID", value: result.id },
@@ -1098,6 +1418,11 @@ var statusCommand = new Command10("status").description("Show current MCP sandbo
1098
1418
  { label: "Status", value: statusColor(result.status) },
1099
1419
  { label: "Sandbox ID", value: result.sandboxId },
1100
1420
  { label: "Preview URL", value: result.previewUrl },
1421
+ {
1422
+ label: "Server",
1423
+ value: serverStatusColor(serverRunning ? "Running" : "Stopped")
1424
+ },
1425
+ ...serverStatus.cmdId ? [{ label: "Server Cmd ID", value: serverStatus.cmdId }] : [],
1101
1426
  { label: "Created", value: result.createdAt },
1102
1427
  { label: "Expires", value: result.expiresAt ?? "N/A" }
1103
1428
  ],
@@ -1111,9 +1436,9 @@ var statusCommand = new Command10("status").description("Show current MCP sandbo
1111
1436
  });
1112
1437
 
1113
1438
  // src/commands/mcp/stop.ts
1114
- import { Command as Command11 } from "commander";
1115
- import ora9 from "ora";
1116
- var stopCommand = new Command11("stop").description("Stop and clean up the MCP sandbox").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
1439
+ import { Command as Command16 } from "commander";
1440
+ import ora13 from "ora";
1441
+ var stopCommand = new Command16("stop").description("Stop the MCP server process").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
1117
1442
  const globalOptions = command.optsWithGlobals();
1118
1443
  const json = globalOptions.json ?? false;
1119
1444
  try {
@@ -1121,19 +1446,25 @@ var stopCommand = new Command11("stop").description("Stop and clean up the MCP s
1121
1446
  if (!mcpId) {
1122
1447
  mcpId = await config.getMcpId();
1123
1448
  if (!mcpId) {
1124
- throw new McpError("No active MCP. Use --mcp-id to specify one.");
1449
+ throw new McpError(
1450
+ "No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
1451
+ );
1125
1452
  }
1126
1453
  }
1127
- const spinner = ora9("Stopping MCP sandbox...").start();
1128
- await api.delete(`/api/mcp/sandboxes/${mcpId}`);
1129
- spinner.succeed("MCP sandbox stopped");
1130
- if (await config.getMcpId() === mcpId) {
1131
- await config.setMcpId(null);
1454
+ const spinner = ora13("Stopping MCP server...").start();
1455
+ const result = await api.post(
1456
+ `/api/mcp/sandboxes/${mcpId}/server`,
1457
+ { action: "stop" }
1458
+ );
1459
+ if (result.stopped) {
1460
+ spinner.succeed("MCP server stopped");
1461
+ } else {
1462
+ spinner.warn("Server was not running");
1132
1463
  }
1133
1464
  if (json) {
1134
- formatOutput({ stopped: mcpId }, true);
1465
+ formatOutput(result, true);
1135
1466
  } else {
1136
- formatSuccess("MCP sandbox stopped and cleaned up.", false);
1467
+ formatSuccess("MCP server stopped.", false);
1137
1468
  }
1138
1469
  } catch (error) {
1139
1470
  handleError(error, json);
@@ -1142,10 +1473,10 @@ var stopCommand = new Command11("stop").description("Stop and clean up the MCP s
1142
1473
  });
1143
1474
 
1144
1475
  // src/commands/mcp/test.ts
1145
- import chalk8 from "chalk";
1146
- import { Command as Command12 } from "commander";
1147
- import ora10 from "ora";
1148
- var testCommand = new Command12("test").description("Test MCP tools via the sandbox").argument("[tool]", "Tool name to test (lists tools if omitted)").argument("[args...]", "JSON arguments for the tool").option("--mcp-id <id>", "Specific MCP ID").action(
1476
+ import chalk10 from "chalk";
1477
+ import { Command as Command17 } from "commander";
1478
+ import ora14 from "ora";
1479
+ var testCommand = new Command17("test").description("Test MCP tools via the sandbox").argument("[tool]", "Tool name to test (lists tools if omitted)").argument("[args...]", "JSON arguments for the tool").option("--mcp-id <id>", "Specific MCP ID").action(
1149
1480
  async (tool, args, options, command) => {
1150
1481
  const globalOptions = command.optsWithGlobals();
1151
1482
  const json = globalOptions.json ?? false;
@@ -1160,7 +1491,7 @@ var testCommand = new Command12("test").description("Test MCP tools via the sand
1160
1491
  }
1161
1492
  }
1162
1493
  if (!tool) {
1163
- const spinner = ora10("Fetching available tools...").start();
1494
+ const spinner = ora14("Fetching available tools...").start();
1164
1495
  const result = await api.post(
1165
1496
  `/api/mcp/sandboxes/${mcpId}/test`,
1166
1497
  { action: "list" }
@@ -1173,7 +1504,7 @@ var testCommand = new Command12("test").description("Test MCP tools via the sand
1173
1504
  if (tools.length === 0) {
1174
1505
  console.log("No tools available.");
1175
1506
  } else {
1176
- console.log(chalk8.bold("\nAvailable Tools:\n"));
1507
+ console.log(chalk10.bold("\nAvailable Tools:\n"));
1177
1508
  formatTable(
1178
1509
  ["Name", "Description"],
1179
1510
  tools.map((t) => [t.name, t.description || "No description"]),
@@ -1196,7 +1527,7 @@ Test a tool: waniwani mcp test <tool-name> '{"arg": "value"}'`
1196
1527
  );
1197
1528
  }
1198
1529
  }
1199
- const spinner = ora10(`Calling tool "${tool}"...`).start();
1530
+ const spinner = ora14(`Calling tool "${tool}"...`).start();
1200
1531
  const startTime = Date.now();
1201
1532
  const result = await api.post(
1202
1533
  `/api/mcp/sandboxes/${mcpId}/test`,
@@ -1217,11 +1548,11 @@ Test a tool: waniwani mcp test <tool-name> '{"arg": "value"}'`
1217
1548
  if (json) {
1218
1549
  formatOutput(output, true);
1219
1550
  } else {
1220
- console.log(chalk8.bold("\nTool Result:\n"));
1221
- console.log(chalk8.gray("Tool:"), tool);
1222
- console.log(chalk8.gray("Input:"), JSON.stringify(toolArgs));
1223
- console.log(chalk8.gray("Duration:"), `${duration}ms`);
1224
- console.log(chalk8.gray("Result:"));
1551
+ console.log(chalk10.bold("\nTool Result:\n"));
1552
+ console.log(chalk10.gray("Tool:"), tool);
1553
+ console.log(chalk10.gray("Input:"), JSON.stringify(toolArgs));
1554
+ console.log(chalk10.gray("Duration:"), `${duration}ms`);
1555
+ console.log(chalk10.gray("Result:"));
1225
1556
  console.log(JSON.stringify(result.result, null, 2));
1226
1557
  }
1227
1558
  }
@@ -1233,13 +1564,13 @@ Test a tool: waniwani mcp test <tool-name> '{"arg": "value"}'`
1233
1564
  );
1234
1565
 
1235
1566
  // src/commands/mcp/use.ts
1236
- import { Command as Command13 } from "commander";
1237
- import ora11 from "ora";
1238
- var useCommand = new Command13("use").description("Select an MCP to use for subsequent commands").argument("<name>", "Name of the MCP to use").option("--global", "Save to global config instead of project config").action(async (name, options, command) => {
1567
+ import { Command as Command18 } from "commander";
1568
+ import ora15 from "ora";
1569
+ var useCommand = new Command18("use").description("Select an MCP to use for subsequent commands").argument("<name>", "Name of the MCP to use").option("--global", "Save to global config instead of project config").action(async (name, options, command) => {
1239
1570
  const globalOptions = command.optsWithGlobals();
1240
1571
  const json = globalOptions.json ?? false;
1241
1572
  try {
1242
- const spinner = ora11("Fetching MCPs...").start();
1573
+ const spinner = ora15("Fetching MCPs...").start();
1243
1574
  const mcps = await api.get("/api/admin/mcps");
1244
1575
  spinner.stop();
1245
1576
  const mcp = mcps.find((m) => m.name === name);
@@ -1274,78 +1605,21 @@ var useCommand = new Command13("use").description("Select an MCP to use for subs
1274
1605
  }
1275
1606
  });
1276
1607
 
1277
- // src/commands/mcp/write-file.ts
1278
- import { readFile as readFile3 } from "fs/promises";
1279
- import { Command as Command14 } from "commander";
1280
- import ora12 from "ora";
1281
- var writeFileCommand = new Command14("write-file").description("Write a file to the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--content <content>", "Content to write").option("--file <localFile>", "Local file to upload").option("--base64", "Treat content as base64 encoded").action(async (path, options, command) => {
1282
- const globalOptions = command.optsWithGlobals();
1283
- const json = globalOptions.json ?? false;
1284
- try {
1285
- let mcpId = options.mcpId;
1286
- if (!mcpId) {
1287
- mcpId = await config.getMcpId();
1288
- if (!mcpId) {
1289
- throw new McpError(
1290
- "No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
1291
- );
1292
- }
1293
- }
1294
- let content;
1295
- let encoding = "utf8";
1296
- if (options.content) {
1297
- content = options.content;
1298
- if (options.base64) {
1299
- encoding = "base64";
1300
- }
1301
- } else if (options.file) {
1302
- const fileBuffer = await readFile3(options.file);
1303
- if (options.base64) {
1304
- content = fileBuffer.toString("base64");
1305
- encoding = "base64";
1306
- } else {
1307
- content = fileBuffer.toString("utf8");
1308
- }
1309
- } else {
1310
- throw new CLIError(
1311
- "Either --content or --file is required",
1312
- "MISSING_CONTENT"
1313
- );
1314
- }
1315
- const spinner = ora12(`Writing ${path}...`).start();
1316
- const result = await api.post(
1317
- `/api/mcp/sandboxes/${mcpId}/files`,
1318
- {
1319
- files: [{ path, content, encoding }]
1320
- }
1321
- );
1322
- spinner.succeed(`Wrote ${path}`);
1323
- if (json) {
1324
- formatOutput(result, true);
1325
- } else {
1326
- formatSuccess(`File written: ${path}`, false);
1327
- }
1328
- } catch (error) {
1329
- handleError(error, json);
1330
- process.exit(1);
1331
- }
1332
- });
1333
-
1334
1608
  // src/commands/mcp/index.ts
1335
- var mcpCommand = new Command15("mcp").description("MCP sandbox management commands").addCommand(createCommand).addCommand(listCommand).addCommand(useCommand).addCommand(statusCommand).addCommand(stopCommand).addCommand(testCommand).addCommand(deployCommand).addCommand(writeFileCommand).addCommand(readFileCommand).addCommand(listFilesCommand).addCommand(runCommandCommand);
1609
+ var mcpCommand = new Command19("mcp").description("MCP sandbox management commands").addCommand(createCommand).addCommand(listCommand2).addCommand(useCommand).addCommand(statusCommand).addCommand(startCommand).addCommand(stopCommand).addCommand(logsCommand).addCommand(deleteCommand).addCommand(testCommand).addCommand(deployCommand).addCommand(fileCommand).addCommand(runCommandCommand);
1336
1610
 
1337
1611
  // src/commands/org/index.ts
1338
- import { Command as Command18 } from "commander";
1612
+ import { Command as Command22 } from "commander";
1339
1613
 
1340
1614
  // src/commands/org/list.ts
1341
- import chalk9 from "chalk";
1342
- import { Command as Command16 } from "commander";
1343
- import ora13 from "ora";
1344
- var listCommand2 = new Command16("list").description("List your organizations").action(async (_, command) => {
1615
+ import chalk11 from "chalk";
1616
+ import { Command as Command20 } from "commander";
1617
+ import ora16 from "ora";
1618
+ var listCommand3 = new Command20("list").description("List your organizations").action(async (_, command) => {
1345
1619
  const globalOptions = command.optsWithGlobals();
1346
1620
  const json = globalOptions.json ?? false;
1347
1621
  try {
1348
- const spinner = ora13("Fetching organizations...").start();
1622
+ const spinner = ora16("Fetching organizations...").start();
1349
1623
  const result = await api.get("/api/oauth/orgs");
1350
1624
  spinner.stop();
1351
1625
  const { orgs, activeOrgId } = result;
@@ -1365,11 +1639,11 @@ var listCommand2 = new Command16("list").description("List your organizations").
1365
1639
  console.log("No organizations found.");
1366
1640
  return;
1367
1641
  }
1368
- console.log(chalk9.bold("\nOrganizations:\n"));
1642
+ console.log(chalk11.bold("\nOrganizations:\n"));
1369
1643
  const rows = orgs.map((o) => {
1370
1644
  const isActive = o.id === activeOrgId;
1371
1645
  return [
1372
- isActive ? chalk9.cyan(`* ${o.name}`) : ` ${o.name}`,
1646
+ isActive ? chalk11.cyan(`* ${o.name}`) : ` ${o.name}`,
1373
1647
  o.slug,
1374
1648
  o.role
1375
1649
  ];
@@ -1379,7 +1653,7 @@ var listCommand2 = new Command16("list").description("List your organizations").
1379
1653
  if (activeOrgId) {
1380
1654
  const activeOrg = orgs.find((o) => o.id === activeOrgId);
1381
1655
  if (activeOrg) {
1382
- console.log(`Active organization: ${chalk9.cyan(activeOrg.name)}`);
1656
+ console.log(`Active organization: ${chalk11.cyan(activeOrg.name)}`);
1383
1657
  }
1384
1658
  }
1385
1659
  console.log("\nSwitch organization: waniwani org switch <name>");
@@ -1391,13 +1665,13 @@ var listCommand2 = new Command16("list").description("List your organizations").
1391
1665
  });
1392
1666
 
1393
1667
  // src/commands/org/switch.ts
1394
- import { Command as Command17 } from "commander";
1395
- import ora14 from "ora";
1396
- var switchCommand = new Command17("switch").description("Switch to a different organization").argument("<name>", "Name or slug of the organization to switch to").action(async (name, _, command) => {
1668
+ import { Command as Command21 } from "commander";
1669
+ import ora17 from "ora";
1670
+ var switchCommand = new Command21("switch").description("Switch to a different organization").argument("<name>", "Name or slug of the organization to switch to").action(async (name, _, command) => {
1397
1671
  const globalOptions = command.optsWithGlobals();
1398
1672
  const json = globalOptions.json ?? false;
1399
1673
  try {
1400
- const spinner = ora14("Fetching organizations...").start();
1674
+ const spinner = ora17("Fetching organizations...").start();
1401
1675
  const { orgs } = await api.get("/api/oauth/orgs");
1402
1676
  const org = orgs.find((o) => o.name === name || o.slug === name);
1403
1677
  if (!org) {
@@ -1430,13 +1704,13 @@ var switchCommand = new Command17("switch").description("Switch to a different o
1430
1704
  });
1431
1705
 
1432
1706
  // src/commands/org/index.ts
1433
- var orgCommand = new Command18("org").description("Organization management commands").addCommand(listCommand2).addCommand(switchCommand);
1707
+ var orgCommand = new Command22("org").description("Organization management commands").addCommand(listCommand3).addCommand(switchCommand);
1434
1708
 
1435
1709
  // src/commands/task.ts
1436
- import chalk10 from "chalk";
1437
- import { Command as Command19 } from "commander";
1438
- import ora15 from "ora";
1439
- var taskCommand = new Command19("task").description("Send a task to Claude running in the sandbox").argument("<prompt>", "Task description/prompt").option("--mcp-id <id>", "Specific MCP ID").option("--model <model>", "Claude model to use").option("--max-steps <n>", "Maximum tool use steps").action(async (prompt, options, command) => {
1710
+ import chalk12 from "chalk";
1711
+ import { Command as Command23 } from "commander";
1712
+ import ora18 from "ora";
1713
+ var taskCommand = new Command23("task").description("Send a task to Claude running in the sandbox").argument("<prompt>", "Task description/prompt").option("--mcp-id <id>", "Specific MCP ID").option("--model <model>", "Claude model to use").option("--max-steps <n>", "Maximum tool use steps").action(async (prompt, options, command) => {
1440
1714
  const globalOptions = command.optsWithGlobals();
1441
1715
  const json = globalOptions.json ?? false;
1442
1716
  try {
@@ -1460,10 +1734,10 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
1460
1734
  const maxSteps = options.maxSteps ? Number.parseInt(options.maxSteps, 10) : defaults.maxSteps;
1461
1735
  if (!json) {
1462
1736
  console.log();
1463
- console.log(chalk10.bold("Task:"), prompt);
1737
+ console.log(chalk12.bold("Task:"), prompt);
1464
1738
  console.log();
1465
1739
  }
1466
- const spinner = ora15("Starting task...").start();
1740
+ const spinner = ora18("Starting task...").start();
1467
1741
  const baseUrl = await api.getBaseUrl();
1468
1742
  const response = await fetch(
1469
1743
  `${baseUrl}/api/mcp/sandboxes/${mcpId}/task`,
@@ -1517,7 +1791,7 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
1517
1791
  const event = parsed;
1518
1792
  steps.push({ type: "text", text: event.content });
1519
1793
  if (!json && event.content) {
1520
- console.log(chalk10.white(event.content));
1794
+ console.log(chalk12.white(event.content));
1521
1795
  }
1522
1796
  } else if (parsed.type === "tool_call") {
1523
1797
  const event = parsed;
@@ -1528,24 +1802,24 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
1528
1802
  output: event.output
1529
1803
  });
1530
1804
  if (!json) {
1531
- console.log(chalk10.cyan(`> Using tool: ${event.tool}`));
1805
+ console.log(chalk12.cyan(`> Using tool: ${event.tool}`));
1532
1806
  if (event.input?.command) {
1533
- console.log(chalk10.gray(` $ ${event.input.command}`));
1807
+ console.log(chalk12.gray(` $ ${event.input.command}`));
1534
1808
  }
1535
1809
  if (event.output) {
1536
1810
  const outputLines = event.output.split("\n");
1537
1811
  if (outputLines.length > 10) {
1538
1812
  console.log(
1539
- chalk10.gray(outputLines.slice(0, 5).join("\n"))
1813
+ chalk12.gray(outputLines.slice(0, 5).join("\n"))
1540
1814
  );
1541
1815
  console.log(
1542
- chalk10.gray(
1816
+ chalk12.gray(
1543
1817
  ` ... (${outputLines.length - 10} more lines)`
1544
1818
  )
1545
1819
  );
1546
- console.log(chalk10.gray(outputLines.slice(-5).join("\n")));
1820
+ console.log(chalk12.gray(outputLines.slice(-5).join("\n")));
1547
1821
  } else {
1548
- console.log(chalk10.gray(event.output));
1822
+ console.log(chalk12.gray(event.output));
1549
1823
  }
1550
1824
  }
1551
1825
  console.log();
@@ -1572,12 +1846,12 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
1572
1846
  } else {
1573
1847
  console.log();
1574
1848
  console.log(
1575
- chalk10.green("\u2713"),
1849
+ chalk12.green("\u2713"),
1576
1850
  `Task completed in ${finalStepCount} steps.`
1577
1851
  );
1578
1852
  if (maxStepsReached) {
1579
1853
  console.log(
1580
- chalk10.yellow("\u26A0"),
1854
+ chalk12.yellow("\u26A0"),
1581
1855
  "Maximum steps reached. Task may be incomplete."
1582
1856
  );
1583
1857
  }
@@ -1590,7 +1864,7 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
1590
1864
 
1591
1865
  // src/cli.ts
1592
1866
  var version = "0.1.0";
1593
- var program = new Command20().name("waniwani").description("WaniWani CLI for MCP development workflow").version(version).option("--json", "Output results as JSON").option("--verbose", "Enable verbose logging");
1867
+ var program = new Command24().name("waniwani").description("WaniWani CLI for MCP development workflow").version(version).option("--json", "Output results as JSON").option("--verbose", "Enable verbose logging");
1594
1868
  program.addCommand(loginCommand);
1595
1869
  program.addCommand(logoutCommand);
1596
1870
  program.addCommand(initCommand);