@controlvector/cv-agent 1.6.0 → 1.7.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.
package/dist/bundle.cjs CHANGED
@@ -3036,8 +3036,11 @@ var {
3036
3036
  Help
3037
3037
  } = import_index.default;
3038
3038
 
3039
- // src/commands/agent.ts
3040
- var import_node_child_process4 = require("node:child_process");
3039
+ // src/commands/setup.ts
3040
+ var import_node_child_process = require("node:child_process");
3041
+ var import_node_fs = require("node:fs");
3042
+ var import_node_path = require("node:path");
3043
+ var import_node_os2 = require("node:os");
3041
3044
 
3042
3045
  // node_modules/chalk/source/vendor/ansi-styles/index.js
3043
3046
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -3630,6 +3633,210 @@ function cleanMachineName(name) {
3630
3633
  return name.trim().toLowerCase().replace(/\s+/g, "-");
3631
3634
  }
3632
3635
 
3636
+ // src/commands/setup.ts
3637
+ var SHARED_CRED_DIR = (0, import_node_path.join)((0, import_node_os2.homedir)(), ".config", "controlvector");
3638
+ var SHARED_CRED_PATH = (0, import_node_path.join)(SHARED_CRED_DIR, "credentials.json");
3639
+ function readSharedCreds() {
3640
+ try {
3641
+ const data = JSON.parse((0, import_node_fs.readFileSync)(SHARED_CRED_PATH, "utf-8"));
3642
+ if (data.token && data.hub_url) return data;
3643
+ return null;
3644
+ } catch {
3645
+ return null;
3646
+ }
3647
+ }
3648
+ function writeSharedCreds(creds) {
3649
+ (0, import_node_fs.mkdirSync)(SHARED_CRED_DIR, { recursive: true });
3650
+ (0, import_node_fs.writeFileSync)(SHARED_CRED_PATH, JSON.stringify(creds, null, 2) + "\n", { mode: 384 });
3651
+ }
3652
+ async function validateToken(hubUrl, token) {
3653
+ try {
3654
+ const controller = new AbortController();
3655
+ const timeout = setTimeout(() => controller.abort(), 1e4);
3656
+ const res = await fetch(`${hubUrl}/api/auth/me`, {
3657
+ headers: { Authorization: `Bearer ${token}` },
3658
+ signal: controller.signal
3659
+ });
3660
+ clearTimeout(timeout);
3661
+ if (!res.ok) return null;
3662
+ const data = await res.json();
3663
+ return data.user?.username || data.user?.email || "unknown";
3664
+ } catch {
3665
+ return null;
3666
+ }
3667
+ }
3668
+ function checkBinary(cmd) {
3669
+ try {
3670
+ return (0, import_node_child_process.execSync)(`${cmd} 2>&1`, { encoding: "utf8", timeout: 5e3 }).trim().split("\n")[0];
3671
+ } catch {
3672
+ return null;
3673
+ }
3674
+ }
3675
+ async function runSetup() {
3676
+ const hubUrl = "https://api.hub.controlvector.io";
3677
+ const appUrl = "https://hub.controlvector.io";
3678
+ console.log();
3679
+ console.log(source_default.bold(" CV-Agent Setup"));
3680
+ console.log();
3681
+ console.log(" Checking environment...");
3682
+ const nodeVersion = checkBinary("node --version");
3683
+ const gitVersion = checkBinary("git --version");
3684
+ const claudeVersion = checkBinary("claude --version");
3685
+ console.log(` ${nodeVersion ? source_default.green("\u2713") : source_default.red("\u2717")} Node.js ${nodeVersion || "\u2014 not found"}`);
3686
+ console.log(` ${gitVersion ? source_default.green("\u2713") : source_default.red("\u2717")} Git ${gitVersion || "\u2014 not found"}`);
3687
+ console.log(` ${claudeVersion ? source_default.green("\u2713") : source_default.red("\u2717")} Claude Code ${claudeVersion || "\u2014 not found"}`);
3688
+ console.log();
3689
+ if (!nodeVersion || !gitVersion) {
3690
+ if (!nodeVersion) console.log(source_default.red(" Node.js required: https://nodejs.org"));
3691
+ if (!gitVersion) console.log(source_default.red(" Git required: https://git-scm.com"));
3692
+ process.exit(1);
3693
+ }
3694
+ if (!claudeVersion) {
3695
+ console.log(source_default.yellow(" Claude Code not found. Install with:"));
3696
+ console.log(source_default.cyan(" npm install -g @anthropic-ai/claude-code"));
3697
+ console.log();
3698
+ console.log(source_default.gray(" Continuing setup \u2014 you can install Claude Code later."));
3699
+ console.log();
3700
+ }
3701
+ let username;
3702
+ let token;
3703
+ const shared = readSharedCreds();
3704
+ if (shared) {
3705
+ const user = await validateToken(shared.hub_url, shared.token);
3706
+ if (user) {
3707
+ username = user;
3708
+ token = shared.token;
3709
+ console.log(source_default.green(" \u2713") + ` Authenticated as ${source_default.bold(user)}`);
3710
+ }
3711
+ }
3712
+ if (!token) {
3713
+ const creds = await readCredentials();
3714
+ if (creds.CV_HUB_PAT) {
3715
+ const user = await validateToken(hubUrl, creds.CV_HUB_PAT);
3716
+ if (user) {
3717
+ username = user;
3718
+ token = creds.CV_HUB_PAT;
3719
+ console.log(source_default.green(" \u2713") + ` Authenticated as ${source_default.bold(user)} (from cv-hub credentials)`);
3720
+ writeSharedCreds({ hub_url: hubUrl, token, username, created_at: (/* @__PURE__ */ new Date()).toISOString() });
3721
+ }
3722
+ }
3723
+ }
3724
+ if (!token) {
3725
+ console.log(" Let's connect you to CV-Hub.");
3726
+ console.log();
3727
+ const autoName = `${(0, import_node_os2.hostname)()}-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
3728
+ const tokenUrl = `${appUrl}/settings/tokens/new?name=${encodeURIComponent(autoName)}&scopes=agent,repo`;
3729
+ console.log(source_default.gray(` Opening: ${tokenUrl}`));
3730
+ try {
3731
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
3732
+ (0, import_node_child_process.execSync)(`${openCmd} "${tokenUrl}" 2>/dev/null`, { timeout: 5e3 });
3733
+ } catch {
3734
+ console.log(source_default.gray(" (Could not open browser \u2014 copy the URL above)"));
3735
+ }
3736
+ console.log();
3737
+ const readline = await import("node:readline");
3738
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
3739
+ token = await new Promise((resolve) => {
3740
+ rl.question(" Paste your token here: ", (answer) => {
3741
+ rl.close();
3742
+ resolve(answer.trim());
3743
+ });
3744
+ });
3745
+ if (!token) {
3746
+ console.log(source_default.red(" No token provided. Run cva setup again."));
3747
+ process.exit(1);
3748
+ }
3749
+ const user = await validateToken(hubUrl, token);
3750
+ if (!user) {
3751
+ console.log(source_default.red(" Token validation failed. Check your token and try again."));
3752
+ process.exit(1);
3753
+ }
3754
+ username = user;
3755
+ console.log(source_default.green(" \u2713") + ` Authenticated as ${source_default.bold(user)}`);
3756
+ writeSharedCreds({ hub_url: hubUrl, token, username, created_at: (/* @__PURE__ */ new Date()).toISOString() });
3757
+ await writeCredentialField("CV_HUB_PAT", token);
3758
+ await writeCredentialField("CV_HUB_API", hubUrl);
3759
+ }
3760
+ console.log();
3761
+ console.log(" Claude.ai MCP connector:");
3762
+ const mcpUrl = `https://claude.ai/settings/integrations?add_mcp=${encodeURIComponent(`${hubUrl}/mcp`)}`;
3763
+ console.log(source_default.gray(` To connect Claude.ai to CV-Hub, visit:`));
3764
+ console.log(source_default.cyan(` ${mcpUrl}`));
3765
+ console.log();
3766
+ console.log(source_default.gray(' Click "Add Integration" \u2192 "Allow" when prompted.'));
3767
+ console.log(source_default.gray(" (You can do this later \u2014 setup will continue.)"));
3768
+ console.log();
3769
+ const cwd = process.cwd();
3770
+ const isGitRepo = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".git"));
3771
+ const hasCVDir = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cv"));
3772
+ const hasClaudeMd = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, "CLAUDE.md"));
3773
+ const repoName = (0, import_node_path.basename)(cwd);
3774
+ if (isGitRepo) {
3775
+ console.log(source_default.green(" \u2713") + ` Git repo found: ${repoName}`);
3776
+ } else {
3777
+ console.log(" Initializing git repository...");
3778
+ (0, import_node_child_process.execSync)("git init && git checkout -b main", { cwd, stdio: "pipe" });
3779
+ console.log(source_default.green(" \u2713") + " Git repo initialized");
3780
+ }
3781
+ if (!hasClaudeMd) {
3782
+ const template = `# ${repoName}
3783
+
3784
+ ## Overview
3785
+ [Describe your project here]
3786
+
3787
+ ## Tech Stack
3788
+ [What languages/frameworks does this project use?]
3789
+
3790
+ ## Build & Run
3791
+ [How to build and run this project]
3792
+ `;
3793
+ (0, import_node_fs.writeFileSync)((0, import_node_path.join)(cwd, "CLAUDE.md"), template);
3794
+ console.log(source_default.green(" \u2713") + " CLAUDE.md created");
3795
+ } else {
3796
+ console.log(source_default.green(" \u2713") + " CLAUDE.md present");
3797
+ }
3798
+ if (!hasCVDir) {
3799
+ (0, import_node_fs.mkdirSync)((0, import_node_path.join)(cwd, ".cv"), { recursive: true });
3800
+ }
3801
+ if (token && username) {
3802
+ const gitHost = "git.hub.controlvector.io";
3803
+ const remoteUrl = `https://${gitHost}/${username}/${repoName}.git`;
3804
+ try {
3805
+ const existingRemote = (0, import_node_child_process.execSync)('git remote get-url cv-hub 2>/dev/null || echo ""', { cwd, encoding: "utf8" }).trim();
3806
+ if (!existingRemote) {
3807
+ (0, import_node_child_process.execSync)(`git remote add cv-hub ${remoteUrl}`, { cwd, stdio: "pipe" });
3808
+ console.log(source_default.green(" \u2713") + ` Remote added: cv-hub \u2192 ${remoteUrl}`);
3809
+ } else {
3810
+ console.log(source_default.green(" \u2713") + ` CV-Hub remote exists`);
3811
+ }
3812
+ } catch {
3813
+ }
3814
+ }
3815
+ console.log();
3816
+ console.log(source_default.bold(" Setup Complete"));
3817
+ console.log(source_default.gray(" " + "\u2500".repeat(40)));
3818
+ console.log(` ${source_default.green("\u2713")} Authenticated as: ${source_default.cyan(username)}`);
3819
+ console.log(` ${source_default.green("\u2713")} Repository: ${source_default.cyan(repoName)}`);
3820
+ console.log(` ${source_default.green("\u2713")} CLAUDE.md: present`);
3821
+ console.log(source_default.gray(" " + "\u2500".repeat(40)));
3822
+ console.log();
3823
+ console.log(" What's next:");
3824
+ console.log(` ${source_default.cyan("cva agent --auto-approve")} \u2014 Start listening for tasks`);
3825
+ console.log(` Or open Claude.ai and dispatch a task to this repo.`);
3826
+ console.log();
3827
+ console.log(source_default.gray(` Dashboard: ${appUrl}`));
3828
+ console.log();
3829
+ }
3830
+ function setupCommand() {
3831
+ const cmd = new Command("setup");
3832
+ cmd.description("Set up CV-Agent \u2014 authentication, repo, and connections (start here)");
3833
+ cmd.action(runSetup);
3834
+ return cmd;
3835
+ }
3836
+
3837
+ // src/commands/agent.ts
3838
+ var import_node_child_process5 = require("node:child_process");
3839
+
3633
3840
  // src/utils/api.ts
3634
3841
  async function apiCall(creds, method, path, body) {
3635
3842
  const url = `${creds.CV_HUB_API}${path}`;
@@ -3835,10 +4042,10 @@ function parseClaudeCodeOutput(line) {
3835
4042
  }
3836
4043
 
3837
4044
  // src/commands/agent-git.ts
3838
- var import_node_child_process = require("node:child_process");
4045
+ var import_node_child_process2 = require("node:child_process");
3839
4046
  function gitExec(cmd, cwd) {
3840
4047
  try {
3841
- return (0, import_node_child_process.execSync)(cmd, { cwd, encoding: "utf-8", timeout: 1e4 }).trim();
4048
+ return (0, import_node_child_process2.execSync)(cmd, { cwd, encoding: "utf-8", timeout: 1e4 }).trim();
3842
4049
  } catch {
3843
4050
  return null;
3844
4051
  }
@@ -3991,7 +4198,7 @@ function verifyGitRemote(cwd, task, gitHost) {
3991
4198
  const currentRemote = gitExec("git remote get-url origin", cwd);
3992
4199
  if (!currentRemote) {
3993
4200
  try {
3994
- (0, import_node_child_process.execSync)(`git remote add origin ${expectedRemote}`, { cwd, timeout: 5e3 });
4201
+ (0, import_node_child_process2.execSync)(`git remote add origin ${expectedRemote}`, { cwd, timeout: 5e3 });
3995
4202
  } catch {
3996
4203
  }
3997
4204
  return { remoteName: "origin", remoteUrl: expectedRemote };
@@ -4001,7 +4208,7 @@ function verifyGitRemote(cwd, task, gitHost) {
4001
4208
  }
4002
4209
  if (currentRemote.includes(gitHost)) {
4003
4210
  try {
4004
- (0, import_node_child_process.execSync)(`git remote set-url origin ${expectedRemote}`, { cwd, timeout: 5e3 });
4211
+ (0, import_node_child_process2.execSync)(`git remote set-url origin ${expectedRemote}`, { cwd, timeout: 5e3 });
4005
4212
  } catch {
4006
4213
  }
4007
4214
  return { remoteName: "origin", remoteUrl: expectedRemote };
@@ -4009,12 +4216,12 @@ function verifyGitRemote(cwd, task, gitHost) {
4009
4216
  const cvRemote = gitExec("git remote get-url cv-hub", cwd);
4010
4217
  if (!cvRemote) {
4011
4218
  try {
4012
- (0, import_node_child_process.execSync)(`git remote add cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4219
+ (0, import_node_child_process2.execSync)(`git remote add cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4013
4220
  } catch {
4014
4221
  }
4015
4222
  } else if (cvRemote !== expectedRemote) {
4016
4223
  try {
4017
- (0, import_node_child_process.execSync)(`git remote set-url cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4224
+ (0, import_node_child_process2.execSync)(`git remote set-url cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4018
4225
  } catch {
4019
4226
  }
4020
4227
  }
@@ -4104,9 +4311,9 @@ async function writeConfig(config) {
4104
4311
  }
4105
4312
 
4106
4313
  // src/commands/git-safety.ts
4107
- var import_node_child_process2 = require("node:child_process");
4314
+ var import_node_child_process3 = require("node:child_process");
4108
4315
  function git(cmd, cwd) {
4109
- return (0, import_node_child_process2.execSync)(cmd, { cwd, encoding: "utf8", timeout: 3e4 }).trim();
4316
+ return (0, import_node_child_process3.execSync)(cmd, { cwd, encoding: "utf8", timeout: 3e4 }).trim();
4110
4317
  }
4111
4318
  function gitSafetyNet(workspaceRoot, taskTitle, taskId, branch) {
4112
4319
  const targetBranch = branch || "main";
@@ -4201,12 +4408,12 @@ Files: ${added} added, ${modified} modified, ${deleted} deleted`;
4201
4408
  }
4202
4409
 
4203
4410
  // src/commands/deploy-manifest.ts
4204
- var import_node_child_process3 = require("node:child_process");
4205
- var import_node_fs = require("node:fs");
4206
- var import_node_path = require("node:path");
4411
+ var import_node_child_process4 = require("node:child_process");
4412
+ var import_node_fs2 = require("node:fs");
4413
+ var import_node_path2 = require("node:path");
4207
4414
  function exec(cmd, cwd, timeoutMs = 3e5, env2) {
4208
4415
  try {
4209
- const stdout = (0, import_node_child_process3.execSync)(cmd, {
4416
+ const stdout = (0, import_node_child_process4.execSync)(cmd, {
4210
4417
  cwd,
4211
4418
  encoding: "utf8",
4212
4419
  timeout: timeoutMs,
@@ -4240,16 +4447,16 @@ async function checkHealth(url, timeoutSeconds) {
4240
4447
  }
4241
4448
  function getHeadCommit(cwd) {
4242
4449
  try {
4243
- return (0, import_node_child_process3.execSync)("git rev-parse HEAD", { cwd, encoding: "utf8", timeout: 5e3 }).trim();
4450
+ return (0, import_node_child_process4.execSync)("git rev-parse HEAD", { cwd, encoding: "utf8", timeout: 5e3 }).trim();
4244
4451
  } catch {
4245
4452
  return null;
4246
4453
  }
4247
4454
  }
4248
4455
  function loadDeployManifest(workspaceRoot) {
4249
- const manifestPath = (0, import_node_path.join)(workspaceRoot, ".cva", "deploy.json");
4250
- if (!(0, import_node_fs.existsSync)(manifestPath)) return null;
4456
+ const manifestPath = (0, import_node_path2.join)(workspaceRoot, ".cva", "deploy.json");
4457
+ if (!(0, import_node_fs2.existsSync)(manifestPath)) return null;
4251
4458
  try {
4252
- const raw = (0, import_node_fs.readFileSync)(manifestPath, "utf8");
4459
+ const raw = (0, import_node_fs2.readFileSync)(manifestPath, "utf8");
4253
4460
  const manifest = JSON.parse(raw);
4254
4461
  if (!manifest.version || manifest.version < 1) {
4255
4462
  console.log(" [deploy] Invalid manifest version");
@@ -4274,7 +4481,7 @@ async function postTaskDeploy(workspaceRoot, taskId, log) {
4274
4481
  console.log(` [deploy] Building: ${buildStep.name}`);
4275
4482
  log("lifecycle", `Building: ${buildStep.name}`);
4276
4483
  const start = Date.now();
4277
- const cwd = (0, import_node_path.join)(workspaceRoot, buildStep.working_dir || ".");
4484
+ const cwd = (0, import_node_path2.join)(workspaceRoot, buildStep.working_dir || ".");
4278
4485
  const timeoutMs = (buildStep.timeout_seconds || 300) * 1e3;
4279
4486
  const result = exec(buildStep.command, cwd, timeoutMs);
4280
4487
  if (!result.ok) {
@@ -4365,7 +4572,7 @@ async function rollback(workspaceRoot, targetCommit, manifest, log) {
4365
4572
  }
4366
4573
  if (manifest.build?.steps) {
4367
4574
  for (const step of manifest.build.steps) {
4368
- exec(step.command, (0, import_node_path.join)(workspaceRoot, step.working_dir || "."), (step.timeout_seconds || 300) * 1e3);
4575
+ exec(step.command, (0, import_node_path2.join)(workspaceRoot, step.working_dir || "."), (step.timeout_seconds || 300) * 1e3);
4369
4576
  }
4370
4577
  }
4371
4578
  if (manifest.service?.restart_command) {
@@ -4395,7 +4602,7 @@ function containsAuthError(text) {
4395
4602
  }
4396
4603
  async function checkClaudeAuth() {
4397
4604
  try {
4398
- const output = (0, import_node_child_process4.execSync)("claude --version 2>&1", {
4605
+ const output = (0, import_node_child_process5.execSync)("claude --version 2>&1", {
4399
4606
  encoding: "utf8",
4400
4607
  timeout: 1e4,
4401
4608
  env: { ...process.env }
@@ -4606,7 +4813,7 @@ async function launchAutoApproveMode(prompt, options) {
4606
4813
  if (sessionId && !isContinue) {
4607
4814
  args.push("--session-id", sessionId);
4608
4815
  }
4609
- const child = (0, import_node_child_process4.spawn)("claude", args, {
4816
+ const child = (0, import_node_child_process5.spawn)("claude", args, {
4610
4817
  cwd: options.cwd,
4611
4818
  stdio: ["inherit", "pipe", "pipe"],
4612
4819
  env: options.spawnEnv || { ...process.env }
@@ -4740,7 +4947,7 @@ ${source_default.red("!")} Claude Code auth failure (stderr): "${authError}"`);
4740
4947
  }
4741
4948
  async function launchRelayMode(prompt, options) {
4742
4949
  return new Promise((resolve, reject) => {
4743
- const child = (0, import_node_child_process4.spawn)("claude", [], {
4950
+ const child = (0, import_node_child_process5.spawn)("claude", [], {
4744
4951
  cwd: options.cwd,
4745
4952
  stdio: ["pipe", "pipe", "pipe"],
4746
4953
  env: options.spawnEnv || { ...process.env }
@@ -4966,19 +5173,19 @@ async function handleSelfUpdate(task, state, creds) {
4966
5173
  let output = "";
4967
5174
  if (source === "npm" || source.startsWith("npm:")) {
4968
5175
  const pkg = source === "npm" ? "@controlvector/cv-agent@latest" : source.replace("npm:", "");
4969
- output = (0, import_node_child_process4.execSync)(`npm install -g ${pkg} 2>&1`, { encoding: "utf8", timeout: 12e4 });
5176
+ output = (0, import_node_child_process5.execSync)(`npm install -g ${pkg} 2>&1`, { encoding: "utf8", timeout: 12e4 });
4970
5177
  } else if (source.startsWith("git:")) {
4971
5178
  const repoPath = source.replace("git:", "");
4972
- output = (0, import_node_child_process4.execSync)(`cd ${repoPath} && git pull && npm install && npm run build && npm link 2>&1`, {
5179
+ output = (0, import_node_child_process5.execSync)(`cd ${repoPath} && git pull && npm install && npm run build && npm link 2>&1`, {
4973
5180
  encoding: "utf8",
4974
5181
  timeout: 3e5
4975
5182
  });
4976
5183
  } else {
4977
- output = (0, import_node_child_process4.execSync)(`npm install -g @controlvector/cv-agent@latest 2>&1`, { encoding: "utf8", timeout: 12e4 });
5184
+ output = (0, import_node_child_process5.execSync)(`npm install -g @controlvector/cv-agent@latest 2>&1`, { encoding: "utf8", timeout: 12e4 });
4978
5185
  }
4979
5186
  let newVersion = "unknown";
4980
5187
  try {
4981
- newVersion = (0, import_node_child_process4.execSync)("cva --version 2>/dev/null || echo unknown", { encoding: "utf8" }).trim();
5188
+ newVersion = (0, import_node_child_process5.execSync)("cva --version 2>/dev/null || echo unknown", { encoding: "utf8" }).trim();
4982
5189
  } catch {
4983
5190
  }
4984
5191
  postTaskEvent(creds, task.id, {
@@ -5004,7 +5211,7 @@ async function handleSelfUpdate(task, state, creds) {
5004
5211
  if (task.input?.constraints?.includes("restart")) {
5005
5212
  console.log(source_default.yellow("Restarting agent with updated binary..."));
5006
5213
  const args = process.argv.slice(1).join(" ");
5007
- (0, import_node_child_process4.execSync)(`nohup cva ${args} > /tmp/cva-restart.log 2>&1 &`, { stdio: "ignore" });
5214
+ (0, import_node_child_process5.execSync)(`nohup cva ${args} > /tmp/cva-restart.log 2>&1 &`, { stdio: "ignore" });
5008
5215
  process.exit(0);
5009
5216
  }
5010
5217
  } catch (err) {
@@ -5036,7 +5243,7 @@ async function runAgent(options) {
5036
5243
  process.exit(1);
5037
5244
  }
5038
5245
  try {
5039
- (0, import_node_child_process4.execSync)("claude --version", { stdio: "pipe", timeout: 5e3 });
5246
+ (0, import_node_child_process5.execSync)("claude --version", { stdio: "pipe", timeout: 5e3 });
5040
5247
  } catch {
5041
5248
  console.log();
5042
5249
  console.log(source_default.red("Claude Code CLI not found.") + " Install it first:");
@@ -5065,7 +5272,7 @@ async function runAgent(options) {
5065
5272
  currentAuthStatus = "api_key_fallback";
5066
5273
  }
5067
5274
  try {
5068
- (0, import_node_child_process4.execSync)("cv --version", { stdio: "pipe", timeout: 5e3 });
5275
+ (0, import_node_child_process5.execSync)("cv --version", { stdio: "pipe", timeout: 5e3 });
5069
5276
  } catch {
5070
5277
  console.log(source_default.yellow("!") + " cv-git CLI not found. Claude Code will fall back to raw git commands.");
5071
5278
  console.log(` Install it: ${source_default.cyan("npm install -g @controlvector/cv-git")}`);
@@ -5085,7 +5292,7 @@ async function runAgent(options) {
5085
5292
  }
5086
5293
  let detectedRepoId;
5087
5294
  try {
5088
- const remoteUrl = (0, import_node_child_process4.execSync)("git remote get-url origin 2>/dev/null", {
5295
+ const remoteUrl = (0, import_node_child_process5.execSync)("git remote get-url origin 2>/dev/null", {
5089
5296
  cwd: workingDir,
5090
5297
  encoding: "utf8",
5091
5298
  timeout: 5e3
@@ -5609,7 +5816,7 @@ function authCommand() {
5609
5816
  }
5610
5817
 
5611
5818
  // src/commands/remote.ts
5612
- var import_node_child_process5 = require("node:child_process");
5819
+ var import_node_child_process6 = require("node:child_process");
5613
5820
  function getGitHost(apiUrl) {
5614
5821
  return apiUrl.replace(/^https?:\/\//, "").replace(/^api\./, "git.");
5615
5822
  }
@@ -5624,16 +5831,16 @@ async function remoteAdd(ownerRepo) {
5624
5831
  }
5625
5832
  const remoteUrl = `https://${gitHost}/${owner}/${repo}.git`;
5626
5833
  try {
5627
- const existing = (0, import_node_child_process5.execSync)("git remote get-url cvhub", { encoding: "utf-8", timeout: 5e3 }).trim();
5834
+ const existing = (0, import_node_child_process6.execSync)("git remote get-url cvhub", { encoding: "utf-8", timeout: 5e3 }).trim();
5628
5835
  if (existing === remoteUrl) {
5629
5836
  console.log(source_default.gray(`Remote 'cvhub' already set to ${remoteUrl}`));
5630
5837
  return;
5631
5838
  }
5632
- (0, import_node_child_process5.execSync)(`git remote set-url cvhub ${remoteUrl}`, { timeout: 5e3 });
5839
+ (0, import_node_child_process6.execSync)(`git remote set-url cvhub ${remoteUrl}`, { timeout: 5e3 });
5633
5840
  console.log(source_default.green("Updated") + ` remote 'cvhub' -> ${remoteUrl}`);
5634
5841
  } catch {
5635
5842
  try {
5636
- (0, import_node_child_process5.execSync)(`git remote add cvhub ${remoteUrl}`, { timeout: 5e3 });
5843
+ (0, import_node_child_process6.execSync)(`git remote add cvhub ${remoteUrl}`, { timeout: 5e3 });
5637
5844
  console.log(source_default.green("Added") + ` remote 'cvhub' -> ${remoteUrl}`);
5638
5845
  } catch (err) {
5639
5846
  console.log(source_default.red("Failed to add remote:") + ` ${err.message}`);
@@ -5825,7 +6032,8 @@ function statusCommand() {
5825
6032
 
5826
6033
  // src/index.ts
5827
6034
  var program2 = new Command();
5828
- program2.name("cva").description("CV-Hub Agent \u2014 bridges Claude Code with CV-Hub task dispatch").version(true ? "1.6.0" : "1.1.0");
6035
+ program2.name("cva").description('CV-Hub Agent \u2014 bridges Claude Code with CV-Hub task dispatch.\n\nRun "cva setup" to get started.').version(true ? "1.7.0" : "1.6.0");
6036
+ program2.addCommand(setupCommand());
5829
6037
  program2.addCommand(agentCommand());
5830
6038
  program2.addCommand(authCommand());
5831
6039
  program2.addCommand(remoteCommand());