@oodarun/cli 0.1.4 → 0.1.5

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/cli.js +56 -52
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1804,15 +1804,11 @@ async function deployToolsViaRest(projectName, token, projectRoot, onProgress) {
1804
1804
  uploads.push(writeFile(`${projectRoot}/ooda-vite-plugin.mjs`, OODA_VITE_PLUGIN));
1805
1805
  uploads.push(writeFile("/tmp/ooda-patch-config.mjs", OODA_CONFIG_PATCH_SCRIPT));
1806
1806
  await Promise.all(uploads);
1807
- const [, patchResult] = await Promise.all([
1808
- exec(`cd "${projectRoot}" && node -e "require('ws')" 2>/dev/null || npm install --save-dev ws 2>/dev/null`).catch(() => {
1809
- }),
1810
- exec(`node /tmp/ooda-patch-config.mjs "${projectRoot}" 2>&1`).catch((err) => {
1811
- const msg = err instanceof Error ? err.message : String(err);
1812
- log(`Config patch failed: ${msg}`);
1813
- return "";
1814
- })
1815
- ]);
1807
+ const patchResult = await exec(`node /tmp/ooda-patch-config.mjs "${projectRoot}" 2>&1`).catch((err) => {
1808
+ const msg = err instanceof Error ? err.message : String(err);
1809
+ log(`Config patch failed: ${msg}`);
1810
+ return "";
1811
+ });
1816
1812
  if (patchResult) log(`Config patch: ${String(patchResult).trim()}`);
1817
1813
  }
1818
1814
 
@@ -2987,6 +2983,8 @@ async function patchServerConfig(projectName, token, projectRoot, onProgress) {
2987
2983
  console.log("[project-provisioner] Server config patch result:", result.trim());
2988
2984
  }
2989
2985
  async function provisionFromFolder(localPath, projectName, token, onProgress, branchName, gitInfo, claudeToken, claudeEnv, githubToken) {
2986
+ const t0 = Date.now();
2987
+ const progress = (p) => onProgress({ ...p, step: `[+${((Date.now() - t0) / 1e3).toFixed(1)}s] ${p.step}` });
2990
2988
  const projectRoot = `/home/user/${path5.basename(localPath)}`;
2991
2989
  const headers = { Authorization: `Bearer ${token}` };
2992
2990
  async function exec(cmd) {
@@ -3011,20 +3009,20 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
3011
3009
  try {
3012
3010
  const project = detectProject(localPath);
3013
3011
  console.log(`[project-provisioner] Detected: framework=${project.framework}, pm=${project.packageManager}, config=${project.configFile}`);
3014
- const projectUrl = await createOrReuseProject(projectName, token, onProgress);
3015
- const fileCount = await uploadFolder(localPath, projectRoot, projectName, token, onProgress);
3016
- onProgress({ step: "Upload complete", detail: `${fileCount} files` });
3012
+ const projectUrl = await createOrReuseProject(projectName, token, progress);
3013
+ const fileCount = await uploadFolder(localPath, projectRoot, projectName, token, progress);
3014
+ progress({ step: "Upload complete", detail: `${fileCount} files` });
3017
3015
  const effectiveClaudeToken = claudeToken || process.env.CLAUDE_CODE_OAUTH_TOKEN;
3018
3016
  if (effectiveClaudeToken) {
3019
- await setupClaudeAuth(projectName, token, effectiveClaudeToken, onProgress, claudeEnv);
3017
+ await setupClaudeAuth(projectName, token, effectiveClaudeToken, progress, claudeEnv);
3020
3018
  }
3021
- await deployClaudeConfig(projectName, token, projectRoot, project.framework, onProgress, gitInfo || null, branchName || null);
3019
+ await deployClaudeConfig(projectName, token, projectRoot, project.framework, progress, gitInfo || null, branchName || null);
3022
3020
  await writeRemoteFile("/home/user/.ooda/publish.mjs", PUBLISH_SCRIPT2);
3023
- await patchServerConfig(projectName, token, projectRoot, onProgress);
3024
- await installSourcePlugin(projectName, token, projectRoot, project.framework, onProgress);
3021
+ await patchServerConfig(projectName, token, projectRoot, progress);
3022
+ await installSourcePlugin(projectName, token, projectRoot, project.framework, progress);
3025
3023
  try {
3026
3024
  await deployToolsViaRest(projectName, token, projectRoot, (msg) => {
3027
- onProgress({ step: msg });
3025
+ progress({ step: msg });
3028
3026
  });
3029
3027
  } catch (err) {
3030
3028
  console.warn("[project-provisioner] Tool deployment failed:", err instanceof Error ? err.message : String(err));
@@ -3040,21 +3038,21 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
3040
3038
  (t) => t.mcp?.transport === "stdio"
3041
3039
  );
3042
3040
  if (hasInstallableTools) {
3043
- onProgress({ step: "Installing MCP tools..." });
3041
+ progress({ step: "Installing MCP tools..." });
3044
3042
  await installToolsViaRest(projectName, token, projectRoot, tools, pm, (msg) => {
3045
- onProgress({ step: msg });
3043
+ progress({ step: msg });
3046
3044
  });
3047
3045
  }
3048
3046
  if (hasMcpTools) {
3049
3047
  const mcpJson = serializeMcpJson(tools);
3050
3048
  await writeRemoteFile(`${projectRoot}/.mcp.json`, mcpJson);
3051
- onProgress({ step: "Wrote .mcp.json" });
3049
+ progress({ step: "Wrote .mcp.json" });
3052
3050
  }
3053
3051
  } catch (err) {
3054
3052
  console.warn("[project-provisioner] MCP tool setup failed:", err instanceof Error ? err.message : String(err));
3055
3053
  }
3056
3054
  if (branchName && gitInfo?.isGitRepo) {
3057
- onProgress({ step: "Initializing git on project..." });
3055
+ progress({ step: "Initializing git on project..." });
3058
3056
  const userName = gitInfo.userName || "Ooda User";
3059
3057
  const userEmail = gitInfo.userEmail || "user@ooda.dev";
3060
3058
  const gitInitScript = [
@@ -3076,7 +3074,7 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
3076
3074
  console.log(`[project-provisioner] Added remote: ${gitInfo.originUrl}`);
3077
3075
  }
3078
3076
  if (githubToken) {
3079
- onProgress({ step: "Setting up git credentials..." });
3077
+ progress({ step: "Setting up git credentials..." });
3080
3078
  const homeDir = "/home/user";
3081
3079
  await exec(`git config --global credential.helper store`);
3082
3080
  await writeRemoteFile(
@@ -3090,7 +3088,7 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
3090
3088
  console.error("[project-provisioner] Git init failed:", err);
3091
3089
  }
3092
3090
  }
3093
- onProgress({ step: "Ready for setup", detail: projectUrl });
3091
+ progress({ step: "Ready for setup", detail: projectUrl });
3094
3092
  return {
3095
3093
  success: true,
3096
3094
  projectName,
@@ -3162,6 +3160,8 @@ async function detectProjectRemote(projectName, token, projectRoot) {
3162
3160
  return { framework, packageManager, devCommand, configFile };
3163
3161
  }
3164
3162
  async function provisionFromGitHub(parsed, projectName, token, onProgress, githubToken, claudeToken) {
3163
+ const t0 = Date.now();
3164
+ const progress = (p) => onProgress({ ...p, step: `[+${((Date.now() - t0) / 1e3).toFixed(1)}s] ${p.step}` });
3165
3165
  const headers = { Authorization: `Bearer ${token}` };
3166
3166
  let homeDir = "/home/user";
3167
3167
  async function exec(cmd) {
@@ -3184,8 +3184,8 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3184
3184
  });
3185
3185
  }
3186
3186
  try {
3187
- const projectUrl = await createOrReuseProject(projectName, token, onProgress);
3188
- onProgress({ step: "Waiting for sandbox to be ready..." });
3187
+ const projectUrl = await createOrReuseProject(projectName, token, progress);
3188
+ progress({ step: "Waiting for sandbox to be ready..." });
3189
3189
  for (let i = 0; i < 15; i++) {
3190
3190
  const check = await exec("test -d /home/user && echo OK || echo NOT_READY");
3191
3191
  const trimmed = check.trim();
@@ -3199,7 +3199,7 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3199
3199
  console.log(`[project-provisioner] Sandbox home directory: ${homeDir}`);
3200
3200
  const projectRoot = `${homeDir}/${parsed.repo}`;
3201
3201
  const cloneUrl = buildAuthenticatedCloneUrl(parsed, githubToken);
3202
- onProgress({ step: "Cloning from GitHub...", detail: `${parsed.owner}/${parsed.repo}` });
3202
+ progress({ step: "Cloning from GitHub...", detail: `${parsed.owner}/${parsed.repo}` });
3203
3203
  const cloneOutput = await exec(
3204
3204
  `cd ${homeDir} && git clone ${cloneUrl} ${parsed.repo} 2>&1`
3205
3205
  );
@@ -3219,7 +3219,7 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3219
3219
  const workingBranch = `ooda/${baseBranch}`;
3220
3220
  await exec(`cd ${projectRoot} && git checkout -b ${workingBranch} 2>&1`);
3221
3221
  if (githubToken) {
3222
- onProgress({ step: "Setting up git credentials..." });
3222
+ progress({ step: "Setting up git credentials..." });
3223
3223
  await exec(`cd ${projectRoot} && git remote set-url origin https://github.com/${parsed.owner}/${parsed.repo}.git`);
3224
3224
  await exec(`git config --global credential.helper store`);
3225
3225
  await writeRemoteFile(
@@ -3229,12 +3229,12 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3229
3229
  );
3230
3230
  }
3231
3231
  await exec(`cd ${projectRoot} && git config user.name "ooda" && git config user.email "dev@ooda.run"`);
3232
- onProgress({ step: "Detecting project..." });
3232
+ progress({ step: "Detecting project..." });
3233
3233
  const project = await detectProjectRemote(projectName, token, projectRoot);
3234
3234
  console.log(`[project-provisioner] Detected: framework=${project.framework}, pm=${project.packageManager}`);
3235
3235
  const effectiveClaudeToken = claudeToken || process.env.CLAUDE_CODE_OAUTH_TOKEN;
3236
3236
  if (effectiveClaudeToken) {
3237
- await setupClaudeAuth(projectName, token, effectiveClaudeToken, onProgress);
3237
+ await setupClaudeAuth(projectName, token, effectiveClaudeToken, progress);
3238
3238
  }
3239
3239
  const gitInfo = {
3240
3240
  isGitRepo: true,
@@ -3244,7 +3244,7 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3244
3244
  userName: "ooda",
3245
3245
  userEmail: "dev@ooda.run"
3246
3246
  };
3247
- await deployClaudeConfig(projectName, token, projectRoot, project.framework, onProgress, gitInfo, workingBranch);
3247
+ await deployClaudeConfig(projectName, token, projectRoot, project.framework, progress, gitInfo, workingBranch);
3248
3248
  const gitWorkflowPatch = `
3249
3249
  ## Git Workflow
3250
3250
  - This project was cloned from GitHub (${parsed.owner}/${parsed.repo}).
@@ -3266,11 +3266,11 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3266
3266
  );
3267
3267
  await writeRemoteFile(`${projectRoot}/CLAUDE.md`, updatedClaudeMd);
3268
3268
  await writeRemoteFile(`${homeDir}/.ooda/publish.mjs`, PUBLISH_SCRIPT2);
3269
- await patchServerConfig(projectName, token, projectRoot, onProgress);
3270
- await installSourcePlugin(projectName, token, projectRoot, project.framework, onProgress);
3269
+ await patchServerConfig(projectName, token, projectRoot, progress);
3270
+ await installSourcePlugin(projectName, token, projectRoot, project.framework, progress);
3271
3271
  try {
3272
3272
  await deployToolsViaRest(projectName, token, projectRoot, (msg) => {
3273
- onProgress({ step: msg });
3273
+ progress({ step: msg });
3274
3274
  });
3275
3275
  } catch (err) {
3276
3276
  console.warn("[project-provisioner] Tool deployment failed:", err instanceof Error ? err.message : String(err));
@@ -3292,21 +3292,21 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3292
3292
  (t) => t.mcp?.transport === "stdio"
3293
3293
  );
3294
3294
  if (hasInstallableTools) {
3295
- onProgress({ step: "Installing MCP tools..." });
3295
+ progress({ step: "Installing MCP tools..." });
3296
3296
  await installToolsViaRest(projectName, token, projectRoot, tools, pm, (msg) => {
3297
- onProgress({ step: msg });
3297
+ progress({ step: msg });
3298
3298
  });
3299
3299
  }
3300
3300
  if (hasMcpTools) {
3301
3301
  const mcpJson = serializeMcpJson(tools);
3302
3302
  await writeRemoteFile(`${projectRoot}/.mcp.json`, mcpJson);
3303
- onProgress({ step: "Wrote .mcp.json" });
3303
+ progress({ step: "Wrote .mcp.json" });
3304
3304
  }
3305
3305
  }
3306
3306
  } catch (err) {
3307
3307
  console.warn("[project-provisioner] MCP tool setup failed:", err instanceof Error ? err.message : String(err));
3308
3308
  }
3309
- onProgress({ step: "Ready for setup", detail: projectUrl });
3309
+ progress({ step: "Ready for setup", detail: projectUrl });
3310
3310
  return {
3311
3311
  success: true,
3312
3312
  projectName,
@@ -3321,6 +3321,8 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
3321
3321
  }
3322
3322
  }
3323
3323
  async function provisionFromTemplate(projectName, templateId, token, onProgress, claudeToken, claudeEnv) {
3324
+ const t0 = Date.now();
3325
+ const progress = (p) => onProgress({ ...p, step: `[+${((Date.now() - t0) / 1e3).toFixed(1)}s] ${p.step}` });
3324
3326
  const { getProjectTemplateById: getProjectTemplateById2 } = await Promise.resolve().then(() => (init_project_templates(), project_templates_exports));
3325
3327
  const template = getProjectTemplateById2(templateId);
3326
3328
  if (!template) {
@@ -3356,20 +3358,20 @@ async function provisionFromTemplate(projectName, templateId, token, onProgress,
3356
3358
  }
3357
3359
  }
3358
3360
  try {
3359
- const projectUrl = await createOrReuseProject(projectName, token, onProgress);
3360
- onProgress({ step: "Uploading template files...", detail: `${template.files.length} files` });
3361
+ const projectUrl = await createOrReuseProject(projectName, token, progress);
3362
+ progress({ step: "Uploading template files...", detail: `${template.files.length} files` });
3361
3363
  for (const file of template.files) {
3362
3364
  await writeFile(`${projectRoot}/${file.path}`, file.content);
3363
3365
  }
3364
3366
  const effectiveClaudeToken = claudeToken || process.env.CLAUDE_CODE_OAUTH_TOKEN;
3365
3367
  if (effectiveClaudeToken) {
3366
- await setupClaudeAuth(projectName, token, effectiveClaudeToken, onProgress, claudeEnv);
3368
+ await setupClaudeAuth(projectName, token, effectiveClaudeToken, progress, claudeEnv);
3367
3369
  }
3368
- await deployClaudeConfig(projectName, token, projectRoot, "vite", onProgress);
3370
+ await deployClaudeConfig(projectName, token, projectRoot, "vite", progress);
3369
3371
  await writeFile("/home/user/.ooda/publish.mjs", PUBLISH_SCRIPT2);
3370
3372
  try {
3371
3373
  await deployToolsViaRest(projectName, token, projectRoot, (msg) => {
3372
- onProgress({ step: msg });
3374
+ progress({ step: msg });
3373
3375
  });
3374
3376
  } catch {
3375
3377
  }
@@ -3383,26 +3385,26 @@ async function provisionFromTemplate(projectName, templateId, token, onProgress,
3383
3385
  (t) => t.mcp?.transport === "stdio"
3384
3386
  );
3385
3387
  if (hasInstallableTools) {
3386
- onProgress({ step: "Installing MCP tools..." });
3388
+ progress({ step: "Installing MCP tools..." });
3387
3389
  await installToolsViaRest(projectName, token, projectRoot, tools, "npm", (msg) => {
3388
- onProgress({ step: msg });
3390
+ progress({ step: msg });
3389
3391
  });
3390
3392
  }
3391
3393
  if (hasMcpTools) {
3392
3394
  const mcpJson = serializeMcpJson(tools);
3393
3395
  await writeFile(`${projectRoot}/.mcp.json`, mcpJson);
3394
- onProgress({ step: "Wrote .mcp.json" });
3396
+ progress({ step: "Wrote .mcp.json" });
3395
3397
  }
3396
3398
  } catch (err) {
3397
3399
  console.warn("[project-provisioner] MCP tool setup failed:", err instanceof Error ? err.message : String(err));
3398
3400
  }
3399
- onProgress({ step: "Starting dev server..." });
3401
+ progress({ step: "Starting dev server..." });
3400
3402
  await exec("pkill -f vite || true");
3401
3403
  await new Promise((r) => setTimeout(r, 2e3));
3402
3404
  exec(`cd ${projectRoot} && ${template.startCmd}`).catch(() => {
3403
3405
  });
3404
3406
  await new Promise((r) => setTimeout(r, 6e3));
3405
- onProgress({ step: "Done!", detail: projectUrl });
3407
+ progress({ step: "Done!", detail: projectUrl });
3406
3408
  return {
3407
3409
  success: true,
3408
3410
  projectName,
@@ -4616,6 +4618,8 @@ function getActiveProject() {
4616
4618
  return _activeProject;
4617
4619
  }
4618
4620
  async function connectAndRunClaude(projectName, apiToken, claudeToken, projectUrl, initialPrompt, previewUrl) {
4621
+ const t0 = Date.now();
4622
+ const elapsed = () => `[+${((Date.now() - t0) / 1e3).toFixed(1)}s]`;
4619
4623
  console.log(`
4620
4624
  ${c.cyan}Connecting to ${c.bold}${projectName}${c.reset}${c.cyan}...${c.reset}`);
4621
4625
  const orgClaude = isOrgMode() ? getOrgClaudeConfig() : null;
@@ -4677,7 +4681,7 @@ async function connectAndRunClaude(projectName, apiToken, claudeToken, projectUr
4677
4681
  return;
4678
4682
  }
4679
4683
  const projectRoot = await findProjectRoot(projectName, apiToken);
4680
- console.log(` ${c.green}${c.bold}\u2713${c.reset} Connected`);
4684
+ console.log(` ${c.green}${c.bold}\u2713${c.reset} Connected ${c.gray}${elapsed()}${c.reset}`);
4681
4685
  pushPhase("setup", "Writing config files");
4682
4686
  const devServerStatus = await readDevServerStatus(client);
4683
4687
  if (devServerStatus) {
@@ -4808,7 +4812,7 @@ with open(p, 'w') as f: json.dump(d, f)
4808
4812
  }
4809
4813
  }
4810
4814
  pushPhase("starting", "Launching Claude Code");
4811
- console.log(` ${c.gray}Launching claude in ${projectRoot}...${c.reset}
4815
+ console.log(` ${c.gray}${elapsed()} Launching claude in ${projectRoot}...${c.reset}
4812
4816
  `);
4813
4817
  if (process.stdin.readable) {
4814
4818
  process.stdin.resume();
@@ -5073,8 +5077,8 @@ ${text}`;
5073
5077
  `);
5074
5078
  break;
5075
5079
  }
5076
- const elapsed = Date.now() - spawnedAt;
5077
- if (cmdAlive || elapsed >= EARLY_DROP_THRESHOLD_MS) {
5080
+ const elapsed2 = Date.now() - spawnedAt;
5081
+ if (cmdAlive || elapsed2 >= EARLY_DROP_THRESHOLD_MS) {
5078
5082
  break;
5079
5083
  }
5080
5084
  if (attempt < MAX_SPAWN_RETRIES) {
@@ -5322,7 +5326,7 @@ async function deployFromGitHubFlow(target, apiToken, claudeToken) {
5322
5326
  }
5323
5327
 
5324
5328
  // src/cli/index.ts
5325
- var CLI_VERSION = "0.1.4";
5329
+ var CLI_VERSION = "0.1.5";
5326
5330
  function formatMutationError(result) {
5327
5331
  const parts = [];
5328
5332
  if (result.status !== void 0) parts.push(String(result.status));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oodarun/cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Launch Claude Code on cloud dev environments",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",