@vibetasks/cli 0.1.0 → 0.2.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/vibetasks.js +729 -114
  2. package/package.json +2 -2
package/dist/vibetasks.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // bin/vibetasks.ts
4
- import { Command as Command11 } from "commander";
4
+ import { Command as Command13 } from "commander";
5
5
 
6
6
  // src/commands/login.ts
7
7
  import { Command } from "commander";
@@ -721,59 +721,131 @@ Error: ${error.message}
721
721
  }
722
722
  });
723
723
 
724
- // src/commands/search.ts
724
+ // src/commands/vibing.ts
725
725
  import { Command as Command5 } from "commander";
726
726
  import chalk6 from "chalk";
727
- import Table2 from "cli-table3";
727
+ import ora5 from "ora";
728
+ import inquirer2 from "inquirer";
728
729
  import { AuthManager as AuthManager6, TaskOperations as TaskOperations4 } from "@vibetasks/core";
729
- var searchCommand = new Command5("search").description("Search tasks by title").argument("<query>", "Search query").option("-l, --limit <number>", "Maximum number of results", "20").action(async (query, options) => {
730
+ var WIP_LIMIT = 3;
731
+ var vibingCommand = new Command5("vibing").alias("start").alias("v").description("Start working on a task (move to vibing status)").argument("[task-id]", "Task ID to start vibing on").option("-p, --pick", "Pick from todo tasks interactively").action(async (taskId, options) => {
732
+ const spinner = ora5();
730
733
  try {
731
734
  const authManager = new AuthManager6();
732
735
  const taskOps = await TaskOperations4.fromAuthManager(authManager);
736
+ const allTasks = await taskOps.getTasks("all");
737
+ const vibingTasks = allTasks.filter((t) => t.status === "vibing" && !t.completed);
738
+ if (vibingTasks.length >= WIP_LIMIT) {
739
+ console.log(chalk6.yellow("\n\u26A0 WIP Limit Warning"));
740
+ console.log(chalk6.gray(` You already have ${vibingTasks.length} tasks in progress.`));
741
+ console.log(chalk6.gray(" Research shows 3+ concurrent tasks = 40% productivity loss.\n"));
742
+ console.log(chalk6.white("Currently vibing:"));
743
+ vibingTasks.forEach((t, i) => {
744
+ console.log(chalk6.magenta(` ${i + 1}. ${t.title}`));
745
+ });
746
+ console.log("");
747
+ const { proceed } = await inquirer2.prompt([{
748
+ type: "confirm",
749
+ name: "proceed",
750
+ message: "Start another task anyway?",
751
+ default: false
752
+ }]);
753
+ if (!proceed) {
754
+ console.log(chalk6.gray("\nFocus on finishing what you started! Run `vibetasks done <id>` when ready.\n"));
755
+ process.exit(0);
756
+ }
757
+ }
758
+ if (!taskId || options.pick) {
759
+ const todoTasks = allTasks.filter((t) => t.status === "todo" && !t.completed);
760
+ if (todoTasks.length === 0) {
761
+ console.log(chalk6.yellow('\nNo todo tasks found. Add one with `vibetasks add "task title"`\n'));
762
+ process.exit(0);
763
+ }
764
+ const { selectedTask } = await inquirer2.prompt([{
765
+ type: "list",
766
+ name: "selectedTask",
767
+ message: "Pick a task to start:",
768
+ choices: todoTasks.map((t) => ({
769
+ name: `${t.title}${t.project_tag ? chalk6.gray(` [${t.project_tag}]`) : ""}`,
770
+ value: t.id
771
+ }))
772
+ }]);
773
+ taskId = selectedTask;
774
+ }
775
+ spinner.start("Starting task...");
776
+ await taskOps.updateTask(taskId, {
777
+ status: "vibing",
778
+ completed: false
779
+ });
780
+ const task = allTasks.find((t) => t.id === taskId);
781
+ spinner.succeed(chalk6.green("Now vibing on:"));
782
+ console.log(chalk6.white(`
783
+ ${task?.title || taskId}
784
+ `));
785
+ console.log(chalk6.gray(" Tips:"));
786
+ console.log(chalk6.gray(" \u2022 Update context notes as you work"));
787
+ console.log(chalk6.gray(" \u2022 Run `vibetasks done " + taskId.slice(0, 8) + "` when finished"));
788
+ console.log(chalk6.gray(' \u2022 In Claude Code, say "show my vibing tasks"\n'));
789
+ } catch (error) {
790
+ spinner.fail(chalk6.red("Failed to start task"));
791
+ console.error(chalk6.red(error.message));
792
+ process.exit(1);
793
+ }
794
+ });
795
+
796
+ // src/commands/search.ts
797
+ import { Command as Command6 } from "commander";
798
+ import chalk7 from "chalk";
799
+ import Table2 from "cli-table3";
800
+ import { AuthManager as AuthManager7, TaskOperations as TaskOperations5 } from "@vibetasks/core";
801
+ var searchCommand = new Command6("search").description("Search tasks by title").argument("<query>", "Search query").option("-l, --limit <number>", "Maximum number of results", "20").action(async (query, options) => {
802
+ try {
803
+ const authManager = new AuthManager7();
804
+ const taskOps = await TaskOperations5.fromAuthManager(authManager);
733
805
  const limit = parseInt(options.limit, 10);
734
806
  const tasks = await taskOps.searchTasks(query, limit);
735
807
  if (tasks.length === 0) {
736
- console.log(chalk6.gray(`
808
+ console.log(chalk7.gray(`
737
809
  No tasks found matching: "${query}"
738
810
  `));
739
811
  process.exit(0);
740
812
  }
741
813
  const table = new Table2({
742
814
  head: [
743
- chalk6.cyan("ID"),
744
- chalk6.cyan("Title"),
745
- chalk6.cyan("Priority"),
746
- chalk6.cyan("Due Date")
815
+ chalk7.cyan("ID"),
816
+ chalk7.cyan("Title"),
817
+ chalk7.cyan("Priority"),
818
+ chalk7.cyan("Due Date")
747
819
  ],
748
820
  colWidths: [12, 50, 10, 12],
749
821
  wordWrap: true
750
822
  });
751
823
  tasks.forEach((task) => {
752
824
  const priorityColors = {
753
- high: chalk6.red,
754
- medium: chalk6.yellow,
755
- low: chalk6.blue,
756
- none: chalk6.gray
825
+ high: chalk7.red,
826
+ medium: chalk7.yellow,
827
+ low: chalk7.blue,
828
+ none: chalk7.gray
757
829
  };
758
830
  const priorityColor = priorityColors[task.priority || "none"];
759
831
  table.push([
760
832
  task.id.substring(0, 8),
761
833
  task.title,
762
834
  priorityColor(task.priority || "none"),
763
- task.due_date ? task.due_date.split("T")[0] : chalk6.gray("-")
835
+ task.due_date ? task.due_date.split("T")[0] : chalk7.gray("-")
764
836
  ]);
765
837
  });
766
838
  console.log("\n" + table.toString());
767
- console.log(chalk6.gray(`
839
+ console.log(chalk7.gray(`
768
840
  Found ${tasks.length} task${tasks.length === 1 ? "" : "s"} matching "${query}"
769
841
  `));
770
842
  process.exit(0);
771
843
  } catch (error) {
772
844
  if (error.message.includes("Not authenticated")) {
773
- console.error(chalk6.yellow("\n\u26A0\uFE0F You need to login first"));
774
- console.error(chalk6.gray("Run: taskflow login\n"));
845
+ console.error(chalk7.yellow("\n\u26A0\uFE0F You need to login first"));
846
+ console.error(chalk7.gray("Run: taskflow login\n"));
775
847
  } else {
776
- console.error(chalk6.red(`
848
+ console.error(chalk7.red(`
777
849
  Error: ${error.message}
778
850
  `));
779
851
  }
@@ -782,27 +854,27 @@ Error: ${error.message}
782
854
  });
783
855
 
784
856
  // src/commands/update.ts
785
- import { Command as Command6 } from "commander";
786
- import ora5 from "ora";
787
- import chalk7 from "chalk";
788
- import { AuthManager as AuthManager7, TaskOperations as TaskOperations5 } from "@vibetasks/core";
789
- var updateCommand = new Command6("update").description("Update a task").argument("<id>", "Task ID (full or first 8 characters)").option("-t, --title <title>", "New title").option("-n, --notes <notes>", "New notes").option("-d, --due <date>", "New due date").option("-p, --priority <level>", "New priority: low, medium, high, none").option("-s, --status <status>", "New status: todo, vibing, done").option("--project <name>", "New project tag").option("-e, --energy <level>", "Energy required: low, medium, high").option("-c, --context <notes>", "Update context notes").action(async (id, options) => {
857
+ import { Command as Command7 } from "commander";
858
+ import ora6 from "ora";
859
+ import chalk8 from "chalk";
860
+ import { AuthManager as AuthManager8, TaskOperations as TaskOperations6 } from "@vibetasks/core";
861
+ var updateCommand = new Command7("update").description("Update a task").argument("<id>", "Task ID (full or first 8 characters)").option("-t, --title <title>", "New title").option("-n, --notes <notes>", "New notes").option("-d, --due <date>", "New due date").option("-p, --priority <level>", "New priority: low, medium, high, none").option("-s, --status <status>", "New status: todo, vibing, done").option("--project <name>", "New project tag").option("-e, --energy <level>", "Energy required: low, medium, high").option("-c, --context <notes>", "Update context notes").action(async (id, options) => {
790
862
  if (!options.title && !options.notes && !options.due && !options.priority && !options.status && !options.project && !options.energy && !options.context) {
791
- console.error(chalk7.red("\nError: No updates specified"));
792
- console.error(chalk7.gray("Provide at least one option: --title, --notes, --due, --priority, --status, --project, --energy, or --context\n"));
863
+ console.error(chalk8.red("\nError: No updates specified"));
864
+ console.error(chalk8.gray("Provide at least one option: --title, --notes, --due, --priority, --status, --project, --energy, or --context\n"));
793
865
  process.exit(1);
794
866
  }
795
- const spinner = ora5("Updating task...").start();
867
+ const spinner = ora6("Updating task...").start();
796
868
  try {
797
- const authManager = new AuthManager7();
798
- const taskOps = await TaskOperations5.fromAuthManager(authManager);
869
+ const authManager = new AuthManager8();
870
+ const taskOps = await TaskOperations6.fromAuthManager(authManager);
799
871
  let taskId = id;
800
872
  if (id.length < 32) {
801
873
  const allTasks = await taskOps.getTasks("all");
802
874
  const matchingTask = allTasks.find((t) => t.id.startsWith(id));
803
875
  if (!matchingTask) {
804
- spinner.fail(chalk7.red("Task not found"));
805
- console.error(chalk7.gray(`
876
+ spinner.fail(chalk8.red("Task not found"));
877
+ console.error(chalk8.gray(`
806
878
  No task found with ID starting with: ${id}
807
879
  `));
808
880
  process.exit(1);
@@ -837,18 +909,18 @@ No task found with ID starting with: ${id}
837
909
  updates.energy_required = options.energy;
838
910
  }
839
911
  const task = await taskOps.updateTask(taskId, updates);
840
- spinner.succeed(chalk7.green("Task updated!"));
841
- console.log(chalk7.gray(`
912
+ spinner.succeed(chalk8.green("Task updated!"));
913
+ console.log(chalk8.gray(`
842
914
  \u2713 ${task.title}
843
915
  `));
844
916
  process.exit(0);
845
917
  } catch (error) {
846
- spinner.fail(chalk7.red("Failed to update task"));
918
+ spinner.fail(chalk8.red("Failed to update task"));
847
919
  if (error.message.includes("Not authenticated")) {
848
- console.error(chalk7.yellow("\n\u26A0\uFE0F You need to login first"));
849
- console.error(chalk7.gray("Run: taskflow login\n"));
920
+ console.error(chalk8.yellow("\n\u26A0\uFE0F You need to login first"));
921
+ console.error(chalk8.gray("Run: taskflow login\n"));
850
922
  } else {
851
- console.error(chalk7.red(`
923
+ console.error(chalk8.red(`
852
924
  Error: ${error.message}
853
925
  `));
854
926
  }
@@ -857,23 +929,23 @@ Error: ${error.message}
857
929
  });
858
930
 
859
931
  // src/commands/delete.ts
860
- import { Command as Command7 } from "commander";
861
- import ora6 from "ora";
862
- import chalk8 from "chalk";
863
- import inquirer2 from "inquirer";
864
- import { AuthManager as AuthManager8, TaskOperations as TaskOperations6 } from "@vibetasks/core";
865
- var deleteCommand = new Command7("delete").description("Delete a task").argument("<id>", "Task ID (full or first 8 characters)").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
932
+ import { Command as Command8 } from "commander";
933
+ import ora7 from "ora";
934
+ import chalk9 from "chalk";
935
+ import inquirer3 from "inquirer";
936
+ import { AuthManager as AuthManager9, TaskOperations as TaskOperations7 } from "@vibetasks/core";
937
+ var deleteCommand = new Command8("delete").description("Delete a task").argument("<id>", "Task ID (full or first 8 characters)").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
866
938
  try {
867
- const authManager = new AuthManager8();
868
- const taskOps = await TaskOperations6.fromAuthManager(authManager);
939
+ const authManager = new AuthManager9();
940
+ const taskOps = await TaskOperations7.fromAuthManager(authManager);
869
941
  let taskId = id;
870
942
  let taskTitle = "";
871
943
  if (id.length < 32) {
872
944
  const allTasks = await taskOps.getTasks("all");
873
945
  const matchingTask = allTasks.find((t) => t.id.startsWith(id));
874
946
  if (!matchingTask) {
875
- console.error(chalk8.red("\nTask not found"));
876
- console.error(chalk8.gray(`No task found with ID starting with: ${id}
947
+ console.error(chalk9.red("\nTask not found"));
948
+ console.error(chalk9.gray(`No task found with ID starting with: ${id}
877
949
  `));
878
950
  process.exit(1);
879
951
  }
@@ -884,7 +956,7 @@ var deleteCommand = new Command7("delete").description("Delete a task").argument
884
956
  taskTitle = task.title;
885
957
  }
886
958
  if (!options.yes) {
887
- const answers = await inquirer2.prompt([
959
+ const answers = await inquirer3.prompt([
888
960
  {
889
961
  type: "confirm",
890
962
  name: "confirm",
@@ -893,24 +965,24 @@ var deleteCommand = new Command7("delete").description("Delete a task").argument
893
965
  }
894
966
  ]);
895
967
  if (!answers.confirm) {
896
- console.log(chalk8.gray("\nDeletion cancelled.\n"));
968
+ console.log(chalk9.gray("\nDeletion cancelled.\n"));
897
969
  process.exit(0);
898
970
  }
899
971
  }
900
- const spinner = ora6("Deleting task...").start();
972
+ const spinner = ora7("Deleting task...").start();
901
973
  await taskOps.deleteTask(taskId);
902
- spinner.succeed(chalk8.green("Task deleted!"));
903
- console.log(chalk8.gray(`
974
+ spinner.succeed(chalk9.green("Task deleted!"));
975
+ console.log(chalk9.gray(`
904
976
  \u2717 ${taskTitle}
905
977
  `));
906
978
  process.exit(0);
907
979
  } catch (error) {
908
- console.error(chalk8.red("\nFailed to delete task"));
980
+ console.error(chalk9.red("\nFailed to delete task"));
909
981
  if (error.message.includes("Not authenticated")) {
910
- console.error(chalk8.yellow("\n\u26A0\uFE0F You need to login first"));
911
- console.error(chalk8.gray("Run: taskflow login\n"));
982
+ console.error(chalk9.yellow("\n\u26A0\uFE0F You need to login first"));
983
+ console.error(chalk9.gray("Run: taskflow login\n"));
912
984
  } else {
913
- console.error(chalk8.red(`Error: ${error.message}
985
+ console.error(chalk9.red(`Error: ${error.message}
914
986
  `));
915
987
  }
916
988
  process.exit(1);
@@ -918,28 +990,28 @@ var deleteCommand = new Command7("delete").description("Delete a task").argument
918
990
  });
919
991
 
920
992
  // src/commands/config.ts
921
- import { Command as Command8 } from "commander";
922
- import chalk9 from "chalk";
923
- import { AuthManager as AuthManager9 } from "@vibetasks/core";
924
- var configCommand = new Command8("config").description("View or set configuration").argument("[key]", "Configuration key").argument("[value]", "Configuration value").action(async (key, value) => {
993
+ import { Command as Command9 } from "commander";
994
+ import chalk10 from "chalk";
995
+ import { AuthManager as AuthManager10 } from "@vibetasks/core";
996
+ var configCommand = new Command9("config").description("View or set configuration").argument("[key]", "Configuration key").argument("[value]", "Configuration value").action(async (key, value) => {
925
997
  try {
926
- const authManager = new AuthManager9();
998
+ const authManager = new AuthManager10();
927
999
  if (!key) {
928
1000
  const configManager = authManager["configManager"];
929
1001
  const config = await configManager.getConfig();
930
1002
  const configPath = configManager.getConfigPath();
931
- console.log(chalk9.blue.bold("\n\u{1F4CB} TaskFlow Configuration\n"));
932
- console.log(chalk9.gray(`Location: ${configPath}
1003
+ console.log(chalk10.blue.bold("\n\u{1F4CB} TaskFlow Configuration\n"));
1004
+ console.log(chalk10.gray(`Location: ${configPath}
933
1005
  `));
934
1006
  if (Object.keys(config).length === 0) {
935
- console.log(chalk9.gray("No configuration set.\n"));
1007
+ console.log(chalk10.gray("No configuration set.\n"));
936
1008
  process.exit(0);
937
1009
  }
938
1010
  Object.entries(config).forEach(([k, v]) => {
939
1011
  if (k.includes("token") || k.includes("key")) {
940
- console.log(`${chalk9.cyan(k)}: ${chalk9.gray("[hidden]")}`);
1012
+ console.log(`${chalk10.cyan(k)}: ${chalk10.gray("[hidden]")}`);
941
1013
  } else {
942
- console.log(`${chalk9.cyan(k)}: ${chalk9.white(String(v))}`);
1014
+ console.log(`${chalk10.cyan(k)}: ${chalk10.white(String(v))}`);
943
1015
  }
944
1016
  });
945
1017
  console.log();
@@ -948,16 +1020,16 @@ var configCommand = new Command8("config").description("View or set configuratio
948
1020
  if (!value) {
949
1021
  const val = await authManager.getConfig(key);
950
1022
  if (val === void 0) {
951
- console.log(chalk9.gray(`
1023
+ console.log(chalk10.gray(`
952
1024
  Configuration key "${key}" not set.
953
1025
  `));
954
1026
  } else {
955
1027
  if (key.includes("token") || key.includes("key")) {
956
- console.log(chalk9.gray(`
1028
+ console.log(chalk10.gray(`
957
1029
  ${key}: [hidden]
958
1030
  `));
959
1031
  } else {
960
- console.log(chalk9.white(`
1032
+ console.log(chalk10.white(`
961
1033
  ${key}: ${val}
962
1034
  `));
963
1035
  }
@@ -965,12 +1037,12 @@ ${key}: ${val}
965
1037
  process.exit(0);
966
1038
  }
967
1039
  await authManager.setConfig(key, value);
968
- console.log(chalk9.green(`
1040
+ console.log(chalk10.green(`
969
1041
  \u2713 Configuration updated: ${key} = ${value}
970
1042
  `));
971
1043
  process.exit(0);
972
1044
  } catch (error) {
973
- console.error(chalk9.red(`
1045
+ console.error(chalk10.red(`
974
1046
  Error: ${error.message}
975
1047
  `));
976
1048
  process.exit(1);
@@ -978,20 +1050,20 @@ Error: ${error.message}
978
1050
  });
979
1051
 
980
1052
  // src/commands/hooks.ts
981
- import { Command as Command9 } from "commander";
982
- import chalk10 from "chalk";
983
- import ora7 from "ora";
1053
+ import { Command as Command10 } from "commander";
1054
+ import chalk11 from "chalk";
1055
+ import ora8 from "ora";
984
1056
  import fs from "fs/promises";
985
1057
  import path from "path";
986
- var hooksCommand = new Command9("hooks").description("Manage git hooks integration").command("install").description("Install git hooks in current repository").action(async () => {
987
- const spinner = ora7("Installing git hooks...").start();
1058
+ var hooksCommand = new Command10("hooks").description("Manage git hooks integration").command("install").description("Install git hooks in current repository").action(async () => {
1059
+ const spinner = ora8("Installing git hooks...").start();
988
1060
  try {
989
1061
  const gitDir = path.join(process.cwd(), ".git");
990
1062
  try {
991
1063
  await fs.access(gitDir);
992
1064
  } catch {
993
- spinner.fail(chalk10.red("Not a git repository"));
994
- console.error(chalk10.gray("\nRun this command from the root of a git repository.\n"));
1065
+ spinner.fail(chalk11.red("Not a git repository"));
1066
+ console.error(chalk11.gray("\nRun this command from the root of a git repository.\n"));
995
1067
  process.exit(1);
996
1068
  }
997
1069
  const hooksDir = path.join(gitDir, "hooks");
@@ -1027,19 +1099,19 @@ fi
1027
1099
  exit 0
1028
1100
  `;
1029
1101
  await fs.writeFile(postCommitPath, hookScript, { mode: 493 });
1030
- spinner.succeed(chalk10.green("Git hooks installed!"));
1031
- console.log(chalk10.gray("\n\u{1F4CC} Post-commit hook created"));
1032
- console.log(chalk10.gray("Location:"), postCommitPath);
1033
- console.log(chalk10.blue.bold("\n\u2728 How to use:\n"));
1034
- console.log(chalk10.white("1. Link commits to tasks:"));
1035
- console.log(chalk10.gray(' git commit -m "feat: Add login [TASK-abc123]"'));
1036
- console.log(chalk10.white("\n2. Auto-complete tasks:"));
1037
- console.log(chalk10.gray(' git commit -m "feat: Complete feature [TASK-abc123] [COMPLETE]"'));
1102
+ spinner.succeed(chalk11.green("Git hooks installed!"));
1103
+ console.log(chalk11.gray("\n\u{1F4CC} Post-commit hook created"));
1104
+ console.log(chalk11.gray("Location:"), postCommitPath);
1105
+ console.log(chalk11.blue.bold("\n\u2728 How to use:\n"));
1106
+ console.log(chalk11.white("1. Link commits to tasks:"));
1107
+ console.log(chalk11.gray(' git commit -m "feat: Add login [TASK-abc123]"'));
1108
+ console.log(chalk11.white("\n2. Auto-complete tasks:"));
1109
+ console.log(chalk11.gray(' git commit -m "feat: Complete feature [TASK-abc123] [COMPLETE]"'));
1038
1110
  console.log();
1039
1111
  process.exit(0);
1040
1112
  } catch (error) {
1041
- spinner.fail(chalk10.red("Failed to install hooks"));
1042
- console.error(chalk10.red(`
1113
+ spinner.fail(chalk11.red("Failed to install hooks"));
1114
+ console.error(chalk11.red(`
1043
1115
  Error: ${error.message}
1044
1116
  `));
1045
1117
  process.exit(1);
@@ -1047,16 +1119,16 @@ Error: ${error.message}
1047
1119
  });
1048
1120
 
1049
1121
  // src/commands/init.ts
1050
- import { Command as Command10 } from "commander";
1051
- import inquirer3 from "inquirer";
1052
- import ora8 from "ora";
1053
- import chalk11 from "chalk";
1054
- import { AuthManager as AuthManager10 } from "@vibetasks/core";
1122
+ import { Command as Command11 } from "commander";
1123
+ import inquirer4 from "inquirer";
1124
+ import ora9 from "ora";
1125
+ import chalk12 from "chalk";
1126
+ import { AuthManager as AuthManager11 } from "@vibetasks/core";
1055
1127
  import { detectProject as detectProject2 } from "@vibetasks/shared/utils/project-detector";
1056
- var initCommand = new Command10("init").description("Initialize TaskFlow for current project (auto-detect from git)").option("--name <name>", "Manually specify project name").action(async (options) => {
1057
- const spinner = ora8("Detecting project...").start();
1128
+ var initCommand = new Command11("init").description("Initialize TaskFlow for current project (auto-detect from git)").option("--name <name>", "Manually specify project name").action(async (options) => {
1129
+ const spinner = ora9("Detecting project...").start();
1058
1130
  try {
1059
- const authManager = new AuthManager10();
1131
+ const authManager = new AuthManager11();
1060
1132
  const cwd = process.cwd();
1061
1133
  let project;
1062
1134
  if (options.name) {
@@ -1065,17 +1137,17 @@ var initCommand = new Command10("init").description("Initialize TaskFlow for cur
1065
1137
  source: "manual",
1066
1138
  path: cwd
1067
1139
  };
1068
- spinner.succeed(chalk11.green("Using manual project name"));
1140
+ spinner.succeed(chalk12.green("Using manual project name"));
1069
1141
  } else {
1070
1142
  project = await detectProject2(cwd);
1071
- spinner.succeed(chalk11.green("Project detected!"));
1143
+ spinner.succeed(chalk12.green("Project detected!"));
1072
1144
  }
1073
- console.log(chalk11.white("\n\u{1F4C1} Project Info:"));
1074
- console.log(chalk11.gray(` Name: ${chalk11.white(project.name)}`));
1075
- console.log(chalk11.gray(` Source: ${chalk11.white(project.source)}`));
1076
- console.log(chalk11.gray(` Path: ${chalk11.white(project.path)}
1145
+ console.log(chalk12.white("\n\u{1F4C1} Project Info:"));
1146
+ console.log(chalk12.gray(` Name: ${chalk12.white(project.name)}`));
1147
+ console.log(chalk12.gray(` Source: ${chalk12.white(project.source)}`));
1148
+ console.log(chalk12.gray(` Path: ${chalk12.white(project.path)}
1077
1149
  `));
1078
- const answers = await inquirer3.prompt([
1150
+ const answers = await inquirer4.prompt([
1079
1151
  {
1080
1152
  type: "confirm",
1081
1153
  name: "confirm",
@@ -1084,38 +1156,581 @@ var initCommand = new Command10("init").description("Initialize TaskFlow for cur
1084
1156
  }
1085
1157
  ]);
1086
1158
  if (!answers.confirm) {
1087
- console.log(chalk11.gray("\nCancelled. Tasks will use default project.\n"));
1159
+ console.log(chalk12.gray("\nCancelled. Tasks will use default project.\n"));
1088
1160
  process.exit(0);
1089
1161
  }
1090
1162
  await authManager.setConfig(`project_${cwd}`, project.name);
1091
- console.log(chalk11.green("\n\u2713 Project initialized!"));
1163
+ console.log(chalk12.green("\n\u2713 Project initialized!"));
1092
1164
  console.log(
1093
- chalk11.gray(
1165
+ chalk12.gray(
1094
1166
  `
1095
- All tasks created from ${chalk11.white(cwd)} will be tagged as ${chalk11.white(project.name)}
1167
+ All tasks created from ${chalk12.white(cwd)} will be tagged as ${chalk12.white(project.name)}
1096
1168
  `
1097
1169
  )
1098
1170
  );
1099
- console.log(chalk11.blue("Next steps:"));
1100
- console.log(chalk11.gray(' \u2022 Run taskflow add "Your task" to create tasks'));
1101
- console.log(chalk11.gray(" \u2022 Tasks will automatically be tagged with this project"));
1102
- console.log(chalk11.gray(" \u2022 Use taskflow list --project to filter by project\n"));
1171
+ console.log(chalk12.blue("Next steps:"));
1172
+ console.log(chalk12.gray(' \u2022 Run taskflow add "Your task" to create tasks'));
1173
+ console.log(chalk12.gray(" \u2022 Tasks will automatically be tagged with this project"));
1174
+ console.log(chalk12.gray(" \u2022 Use taskflow list --project to filter by project\n"));
1103
1175
  process.exit(0);
1104
1176
  } catch (error) {
1105
- spinner.fail(chalk11.red("Failed to initialize project"));
1106
- console.error(chalk11.red(`
1177
+ spinner.fail(chalk12.red("Failed to initialize project"));
1178
+ console.error(chalk12.red(`
1107
1179
  Error: ${error.message}
1108
1180
  `));
1109
1181
  process.exit(1);
1110
1182
  }
1111
1183
  });
1112
1184
 
1185
+ // src/commands/setup.ts
1186
+ import { Command as Command12 } from "commander";
1187
+ import inquirer5 from "inquirer";
1188
+ import ora10 from "ora";
1189
+ import chalk13 from "chalk";
1190
+ import fs2 from "fs/promises";
1191
+ import path2 from "path";
1192
+ import os from "os";
1193
+ import { createServer as createServer2 } from "http";
1194
+ import { exec as exec2 } from "child_process";
1195
+ import { promisify as promisify2 } from "util";
1196
+ import { AuthManager as AuthManager12, TaskOperations as TaskOperations8, createSupabaseClient as createSupabaseClient2 } from "@vibetasks/core";
1197
+ import { detectProject as detectProject3 } from "@vibetasks/shared/utils/project-detector";
1198
+ var execAsync2 = promisify2(exec2);
1199
+ var SUPABASE_URL = "https://cbkkztbcoitrfcleghfd.supabase.co";
1200
+ var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNia2t6dGJjb2l0cmZjbGVnaGZkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njc3NTc0MjgsImV4cCI6MjA4MzMzMzQyOH0.G7ILx-nntP0NbxO1gKt5yASb7nt7OmpJ8qtykeGYbQA";
1201
+ async function openBrowser2(url) {
1202
+ const platform = process.platform;
1203
+ let command;
1204
+ if (platform === "win32") {
1205
+ command = `start "" "${url}"`;
1206
+ } else if (platform === "darwin") {
1207
+ command = `open "${url}"`;
1208
+ } else {
1209
+ command = `xdg-open "${url}"`;
1210
+ }
1211
+ try {
1212
+ await execAsync2(command);
1213
+ } catch (error) {
1214
+ }
1215
+ }
1216
+ async function getAvailablePort2(startPort = 3737) {
1217
+ return new Promise((resolve, reject) => {
1218
+ const server = createServer2();
1219
+ server.listen(startPort, () => {
1220
+ const port = server.address().port;
1221
+ server.close(() => resolve(port));
1222
+ });
1223
+ server.on("error", (error) => {
1224
+ if (error.code === "EADDRINUSE") {
1225
+ resolve(getAvailablePort2(startPort + 1));
1226
+ } else {
1227
+ reject(error);
1228
+ }
1229
+ });
1230
+ });
1231
+ }
1232
+ function getClaudeConfigPath() {
1233
+ const configHome = process.env.XDG_CONFIG_HOME || path2.join(os.homedir(), ".config");
1234
+ return path2.join(configHome, "claude-code", "config.json");
1235
+ }
1236
+ async function claudeCodeConfigExists() {
1237
+ try {
1238
+ const configDir = path2.dirname(getClaudeConfigPath());
1239
+ await fs2.access(configDir);
1240
+ return true;
1241
+ } catch {
1242
+ return false;
1243
+ }
1244
+ }
1245
+ function showWelcome() {
1246
+ console.log("\n");
1247
+ console.log(chalk13.bold.magenta("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
1248
+ console.log(chalk13.bold.white(" VibeTasks Setup Wizard"));
1249
+ console.log(chalk13.bold.magenta("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
1250
+ console.log("");
1251
+ console.log(chalk13.gray(" This wizard will set up VibeTasks in about 2 minutes:"));
1252
+ console.log("");
1253
+ console.log(chalk13.white(" 1.") + chalk13.gray(" Authenticate with your account"));
1254
+ console.log(chalk13.white(" 2.") + chalk13.gray(" Configure Claude Code integration"));
1255
+ console.log(chalk13.white(" 3.") + chalk13.gray(" Initialize project (optional)"));
1256
+ console.log(chalk13.white(" 4.") + chalk13.gray(" Verify everything works"));
1257
+ console.log("");
1258
+ }
1259
+ async function checkExistingAuth() {
1260
+ try {
1261
+ const authManager = new AuthManager12();
1262
+ const token = await authManager.getAccessToken();
1263
+ if (!token) return { authenticated: false };
1264
+ const supabaseUrl = await authManager.getConfig("supabase_url") || SUPABASE_URL;
1265
+ const supabaseKey = await authManager.getConfig("supabase_key") || SUPABASE_ANON_KEY;
1266
+ const supabase = createSupabaseClient2({ supabaseUrl, supabaseKey, accessToken: token });
1267
+ const { data: { user } } = await supabase.auth.getUser();
1268
+ if (user?.email) {
1269
+ return { authenticated: true, email: user.email };
1270
+ }
1271
+ return { authenticated: false };
1272
+ } catch {
1273
+ return { authenticated: false };
1274
+ }
1275
+ }
1276
+ async function runBrowserAuth() {
1277
+ const port = await getAvailablePort2();
1278
+ return new Promise((resolve) => {
1279
+ let timeoutId = null;
1280
+ const server = createServer2(async (req, res) => {
1281
+ if (req.method === "OPTIONS") {
1282
+ res.writeHead(200, {
1283
+ "Access-Control-Allow-Origin": "*",
1284
+ "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
1285
+ "Access-Control-Allow-Headers": "Content-Type"
1286
+ });
1287
+ res.end();
1288
+ return;
1289
+ }
1290
+ if (req.url?.startsWith("/callback")) {
1291
+ const url = new URL(req.url, `http://localhost:${port}`);
1292
+ const accessToken = url.searchParams.get("access_token");
1293
+ const refreshToken = url.searchParams.get("refresh_token");
1294
+ const email = url.searchParams.get("email");
1295
+ const supabaseUrl = url.searchParams.get("supabase_url");
1296
+ const supabaseKey = url.searchParams.get("supabase_key");
1297
+ if (!accessToken || !refreshToken || !email) {
1298
+ res.writeHead(400, { "Content-Type": "text/html" });
1299
+ res.end(getErrorHtml("Missing authentication data"));
1300
+ if (timeoutId) clearTimeout(timeoutId);
1301
+ server.close(() => resolve({ success: false }));
1302
+ return;
1303
+ }
1304
+ try {
1305
+ const authManager = new AuthManager12();
1306
+ await authManager.setAccessToken(accessToken);
1307
+ await authManager.setRefreshToken(refreshToken);
1308
+ if (supabaseUrl) await authManager.setConfig("supabase_url", supabaseUrl);
1309
+ if (supabaseKey) await authManager.setConfig("supabase_key", supabaseKey);
1310
+ const storageMethod = authManager.getStorageMethod();
1311
+ const storageLocation = storageMethod === "keychain" ? "system keychain" : authManager["configManager"].getConfigPath();
1312
+ res.writeHead(200, { "Content-Type": "text/html" });
1313
+ res.end(getSuccessHtml(email));
1314
+ if (timeoutId) clearTimeout(timeoutId);
1315
+ server.close(() => resolve({ success: true, email, storageLocation }));
1316
+ } catch (error) {
1317
+ res.writeHead(500, { "Content-Type": "text/html" });
1318
+ res.end(getErrorHtml("Failed to store tokens"));
1319
+ if (timeoutId) clearTimeout(timeoutId);
1320
+ server.close(() => resolve({ success: false }));
1321
+ }
1322
+ return;
1323
+ }
1324
+ res.writeHead(404);
1325
+ res.end();
1326
+ });
1327
+ server.listen(port, async () => {
1328
+ const taskflowPort = process.env.TASKFLOW_WEB_PORT || "2843";
1329
+ const authUrl = `http://localhost:${taskflowPort}/cli-auth?port=${port}`;
1330
+ console.log(chalk13.gray(`
1331
+ If browser doesn't open, visit:`));
1332
+ console.log(chalk13.cyan(` ${authUrl}
1333
+ `));
1334
+ await openBrowser2(authUrl);
1335
+ });
1336
+ server.on("error", () => {
1337
+ resolve({ success: false });
1338
+ });
1339
+ timeoutId = setTimeout(() => {
1340
+ server.close(() => resolve({ success: false }));
1341
+ }, 3 * 60 * 1e3);
1342
+ });
1343
+ }
1344
+ async function stepAuthentication() {
1345
+ console.log(chalk13.bold.blue("\n\u2501\u2501\u2501 Step 1: Authentication \u2501\u2501\u2501\n"));
1346
+ const existing = await checkExistingAuth();
1347
+ if (existing.authenticated) {
1348
+ console.log(chalk13.green(" \u2713") + chalk13.white(` Already logged in as ${chalk13.cyan(existing.email)}`));
1349
+ const { reauth } = await inquirer5.prompt([{
1350
+ type: "confirm",
1351
+ name: "reauth",
1352
+ message: "Re-authenticate with a different account?",
1353
+ default: false
1354
+ }]);
1355
+ if (!reauth) {
1356
+ return { success: true, email: existing.email, skipped: true };
1357
+ }
1358
+ }
1359
+ const { authMethod } = await inquirer5.prompt([{
1360
+ type: "list",
1361
+ name: "authMethod",
1362
+ message: "How would you like to authenticate?",
1363
+ choices: [
1364
+ { name: "Browser login (recommended)", value: "browser" },
1365
+ { name: "Email & password", value: "terminal" }
1366
+ ]
1367
+ }]);
1368
+ if (authMethod === "browser") {
1369
+ const spinner = ora10("Opening browser for authentication...").start();
1370
+ spinner.stop();
1371
+ console.log(chalk13.gray(" Waiting for browser authentication...\n"));
1372
+ const result = await runBrowserAuth();
1373
+ if (result.success) {
1374
+ console.log(chalk13.green("\n \u2713") + chalk13.white(` Logged in as ${chalk13.cyan(result.email)}`));
1375
+ console.log(chalk13.gray(` Tokens stored in: ${result.storageLocation}`));
1376
+ } else {
1377
+ console.log(chalk13.red("\n \u2717 Authentication failed or timed out"));
1378
+ }
1379
+ return result;
1380
+ } else {
1381
+ const answers = await inquirer5.prompt([
1382
+ {
1383
+ type: "input",
1384
+ name: "email",
1385
+ message: "Email:",
1386
+ validate: (input) => input.includes("@") || "Please enter a valid email"
1387
+ },
1388
+ {
1389
+ type: "password",
1390
+ name: "password",
1391
+ message: "Password:",
1392
+ mask: "*",
1393
+ validate: (input) => input.length >= 6 || "Password must be at least 6 characters"
1394
+ }
1395
+ ]);
1396
+ const spinner = ora10("Authenticating...").start();
1397
+ try {
1398
+ const authManager = new AuthManager12();
1399
+ await authManager.setConfig("supabase_url", SUPABASE_URL);
1400
+ await authManager.setConfig("supabase_key", SUPABASE_ANON_KEY);
1401
+ const supabase = createSupabaseClient2({
1402
+ supabaseUrl: SUPABASE_URL,
1403
+ supabaseKey: SUPABASE_ANON_KEY
1404
+ });
1405
+ const { data, error } = await supabase.auth.signInWithPassword({
1406
+ email: answers.email,
1407
+ password: answers.password
1408
+ });
1409
+ if (error) throw error;
1410
+ if (!data.session) throw new Error("No session returned");
1411
+ await authManager.setAccessToken(data.session.access_token);
1412
+ await authManager.setRefreshToken(data.session.refresh_token);
1413
+ const storageMethod = authManager.getStorageMethod();
1414
+ const storageLocation = storageMethod === "keychain" ? "system keychain" : authManager["configManager"].getConfigPath();
1415
+ spinner.succeed(chalk13.green("Authenticated successfully"));
1416
+ console.log(chalk13.gray(` Tokens stored in: ${storageLocation}`));
1417
+ return { success: true, email: answers.email, storageLocation };
1418
+ } catch (error) {
1419
+ spinner.fail(chalk13.red("Authentication failed"));
1420
+ console.log(chalk13.red(` ${error.message}`));
1421
+ return { success: false };
1422
+ }
1423
+ }
1424
+ }
1425
+ async function stepClaudeCodeConfig() {
1426
+ console.log(chalk13.bold.blue("\n\u2501\u2501\u2501 Step 2: Claude Code Integration \u2501\u2501\u2501\n"));
1427
+ const hasClaudeCode = await claudeCodeConfigExists();
1428
+ if (!hasClaudeCode) {
1429
+ console.log(chalk13.yellow(" \u26A0") + chalk13.gray(" Claude Code config directory not found"));
1430
+ console.log(chalk13.gray(" Run this command again after installing Claude Code"));
1431
+ const { createAnyway } = await inquirer5.prompt([{
1432
+ type: "confirm",
1433
+ name: "createAnyway",
1434
+ message: "Create config directory anyway?",
1435
+ default: false
1436
+ }]);
1437
+ if (!createAnyway) {
1438
+ return { success: true, skipped: true };
1439
+ }
1440
+ }
1441
+ const { configure } = await inquirer5.prompt([{
1442
+ type: "confirm",
1443
+ name: "configure",
1444
+ message: "Configure VibeTasks MCP server for Claude Code?",
1445
+ default: true
1446
+ }]);
1447
+ if (!configure) {
1448
+ return { success: true, skipped: true };
1449
+ }
1450
+ const spinner = ora10("Configuring Claude Code...").start();
1451
+ try {
1452
+ const configPath = getClaudeConfigPath();
1453
+ const configDir = path2.dirname(configPath);
1454
+ await fs2.mkdir(configDir, { recursive: true });
1455
+ let config = {};
1456
+ try {
1457
+ const existing = await fs2.readFile(configPath, "utf-8");
1458
+ config = JSON.parse(existing);
1459
+ } catch {
1460
+ }
1461
+ if (!config.mcpServers) config.mcpServers = {};
1462
+ if (!config.hooks) config.hooks = {};
1463
+ if (!config.hooks.SessionStart) config.hooks.SessionStart = [];
1464
+ if (!config.hooks.Stop) config.hooks.Stop = [];
1465
+ let mcpCommand = "vibetasks-mcp";
1466
+ let mcpArgs = [];
1467
+ try {
1468
+ if (process.platform === "win32") {
1469
+ await execAsync2("where vibetasks-mcp");
1470
+ } else {
1471
+ await execAsync2("which vibetasks-mcp");
1472
+ }
1473
+ } catch {
1474
+ mcpCommand = "npx";
1475
+ mcpArgs = ["@vibetasks/mcp-server"];
1476
+ }
1477
+ config.mcpServers.vibetasks = {
1478
+ command: mcpCommand,
1479
+ ...mcpArgs.length > 0 && { args: mcpArgs },
1480
+ env: {
1481
+ TASKFLOW_SUPABASE_URL: SUPABASE_URL,
1482
+ TASKFLOW_SUPABASE_KEY: SUPABASE_ANON_KEY
1483
+ }
1484
+ };
1485
+ const hasSessionStartHook = config.hooks.SessionStart.some(
1486
+ (h) => h.command === mcpCommand || h.command === "vibetasks-mcp"
1487
+ );
1488
+ const hasStopHook = config.hooks.Stop.some(
1489
+ (h) => h.command === mcpCommand || h.command === "vibetasks-mcp"
1490
+ );
1491
+ if (!hasSessionStartHook) {
1492
+ config.hooks.SessionStart.push({
1493
+ type: "command",
1494
+ command: mcpCommand,
1495
+ ...mcpArgs.length > 0 && { args: mcpArgs },
1496
+ env: {
1497
+ CLAUDE_HOOK_TYPE: "SessionStart",
1498
+ TASKFLOW_SUPABASE_URL: SUPABASE_URL
1499
+ }
1500
+ });
1501
+ }
1502
+ if (!hasStopHook) {
1503
+ config.hooks.Stop.push({
1504
+ type: "command",
1505
+ command: mcpCommand,
1506
+ ...mcpArgs.length > 0 && { args: mcpArgs },
1507
+ env: {
1508
+ CLAUDE_HOOK_TYPE: "SessionEnd",
1509
+ TASKFLOW_SUPABASE_URL: SUPABASE_URL
1510
+ }
1511
+ });
1512
+ }
1513
+ await fs2.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
1514
+ spinner.succeed(chalk13.green("Claude Code configured"));
1515
+ console.log(chalk13.gray(` Config: ${configPath}`));
1516
+ console.log(chalk13.gray(" Added: MCP server, SessionStart hook, SessionEnd hook"));
1517
+ return { success: true, configured: true, configPath };
1518
+ } catch (error) {
1519
+ spinner.fail(chalk13.red("Failed to configure Claude Code"));
1520
+ console.log(chalk13.red(` ${error.message}`));
1521
+ return { success: false };
1522
+ }
1523
+ }
1524
+ async function stepProjectInit() {
1525
+ console.log(chalk13.bold.blue("\n\u2501\u2501\u2501 Step 3: Project Setup (Optional) \u2501\u2501\u2501\n"));
1526
+ const spinner = ora10("Detecting project...").start();
1527
+ let project;
1528
+ try {
1529
+ project = await detectProject3(process.cwd());
1530
+ spinner.succeed(chalk13.green(`Detected: ${project.name}`));
1531
+ console.log(chalk13.gray(` Source: ${project.source}`));
1532
+ console.log(chalk13.gray(` Path: ${project.path}`));
1533
+ } catch {
1534
+ spinner.info(chalk13.gray("No project detected in current directory"));
1535
+ return { success: true, skipped: true };
1536
+ }
1537
+ const { setupProject } = await inquirer5.prompt([{
1538
+ type: "confirm",
1539
+ name: "setupProject",
1540
+ message: `Auto-tag tasks created here as "${project.name}"?`,
1541
+ default: true
1542
+ }]);
1543
+ if (!setupProject) {
1544
+ return { success: true, skipped: true };
1545
+ }
1546
+ try {
1547
+ const authManager = new AuthManager12();
1548
+ await authManager.setConfig(`project_${process.cwd()}`, project.name);
1549
+ console.log(chalk13.green("\n \u2713") + chalk13.white(` Project "${project.name}" configured`));
1550
+ return { success: true, projectName: project.name };
1551
+ } catch (error) {
1552
+ console.log(chalk13.yellow("\n \u26A0") + chalk13.gray(` Could not save project config: ${error.message}`));
1553
+ return { success: true, skipped: true };
1554
+ }
1555
+ }
1556
+ async function stepVerify() {
1557
+ console.log(chalk13.bold.blue("\n\u2501\u2501\u2501 Step 4: Verification \u2501\u2501\u2501\n"));
1558
+ const result = {
1559
+ supabaseConnected: false,
1560
+ mcpConfigured: false
1561
+ };
1562
+ const supabaseSpinner = ora10("Testing Supabase connection...").start();
1563
+ try {
1564
+ const authManager = new AuthManager12();
1565
+ const taskOps = await TaskOperations8.fromAuthManager(authManager);
1566
+ const tasks = await taskOps.getTasks("all");
1567
+ result.supabaseConnected = true;
1568
+ result.taskCount = tasks.length;
1569
+ supabaseSpinner.succeed(chalk13.green(`Supabase connected (${tasks.length} tasks found)`));
1570
+ } catch (error) {
1571
+ supabaseSpinner.fail(chalk13.red("Supabase connection failed"));
1572
+ console.log(chalk13.gray(` ${error.message}`));
1573
+ }
1574
+ const mcpSpinner = ora10("Checking MCP configuration...").start();
1575
+ try {
1576
+ const configPath = getClaudeConfigPath();
1577
+ const configContent = await fs2.readFile(configPath, "utf-8");
1578
+ const config = JSON.parse(configContent);
1579
+ if (config.mcpServers?.vibetasks) {
1580
+ result.mcpConfigured = true;
1581
+ mcpSpinner.succeed(chalk13.green("MCP server configured"));
1582
+ } else {
1583
+ mcpSpinner.warn(chalk13.yellow("MCP server not found in config"));
1584
+ }
1585
+ } catch {
1586
+ mcpSpinner.warn(chalk13.yellow("Could not read Claude Code config"));
1587
+ }
1588
+ return result;
1589
+ }
1590
+ function showCompletion(auth, claude, project, verify) {
1591
+ console.log("\n");
1592
+ console.log(chalk13.bold.green("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
1593
+ console.log(chalk13.bold.white(" Setup Complete!"));
1594
+ console.log(chalk13.bold.green("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
1595
+ console.log("");
1596
+ console.log(chalk13.white(" Summary:"));
1597
+ console.log(` ${auth.success ? chalk13.green("\u2713") : chalk13.red("\u2717")} Authentication: ${auth.email || "Not configured"}`);
1598
+ console.log(` ${claude.configured ? chalk13.green("\u2713") : chalk13.yellow("\u25CB")} Claude Code: ${claude.configured ? "Configured" : "Skipped"}`);
1599
+ console.log(` ${project.projectName ? chalk13.green("\u2713") : chalk13.yellow("\u25CB")} Project: ${project.projectName || "None"}`);
1600
+ console.log(` ${verify.supabaseConnected ? chalk13.green("\u2713") : chalk13.red("\u2717")} Connection: ${verify.supabaseConnected ? `${verify.taskCount} tasks` : "Failed"}`);
1601
+ console.log("");
1602
+ if (claude.configured) {
1603
+ console.log(chalk13.yellow(" \u26A1 Important: Restart Claude Code to activate MCP server"));
1604
+ console.log("");
1605
+ }
1606
+ console.log(chalk13.white(" What you can do now:"));
1607
+ console.log("");
1608
+ console.log(chalk13.gray(" CLI Commands:"));
1609
+ console.log(chalk13.cyan(' $ vibetasks add "My first task"'));
1610
+ console.log(chalk13.cyan(" $ vibetasks list"));
1611
+ console.log(chalk13.cyan(" $ vibetasks done <task-id>"));
1612
+ console.log("");
1613
+ if (claude.configured) {
1614
+ console.log(chalk13.gray(" In Claude Code (after restart):"));
1615
+ console.log(chalk13.cyan(' "Create a task to fix the login bug"'));
1616
+ console.log(chalk13.cyan(' "Show my tasks for today"'));
1617
+ console.log(chalk13.cyan(' "What should I work on next?"'));
1618
+ }
1619
+ console.log("");
1620
+ console.log(chalk13.gray(" Need help? https://github.com/vyasapps/vibetasks"));
1621
+ console.log("");
1622
+ }
1623
+ function getSuccessHtml(email) {
1624
+ return `<!DOCTYPE html>
1625
+ <html>
1626
+ <head>
1627
+ <title>VibeTasks - Setup Success</title>
1628
+ <style>
1629
+ * { margin: 0; padding: 0; box-sizing: border-box; }
1630
+ body {
1631
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1632
+ display: flex; align-items: center; justify-content: center;
1633
+ min-height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1634
+ }
1635
+ .container {
1636
+ text-align: center; padding: 60px 40px; background: white;
1637
+ border-radius: 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); max-width: 450px;
1638
+ }
1639
+ .check { font-size: 64px; margin-bottom: 20px; }
1640
+ h1 { color: #2d3748; font-size: 24px; margin-bottom: 8px; }
1641
+ .email { color: #667eea; font-weight: 600; margin-bottom: 20px; }
1642
+ p { color: #718096; line-height: 1.6; }
1643
+ .badge {
1644
+ display: inline-block; background: #f0fdf4; color: #15803d;
1645
+ padding: 8px 16px; border-radius: 20px; font-size: 14px; margin-top: 20px;
1646
+ }
1647
+ </style>
1648
+ </head>
1649
+ <body>
1650
+ <div class="container">
1651
+ <div class="check">\u2713</div>
1652
+ <h1>Authentication Successful!</h1>
1653
+ <p class="email">${email}</p>
1654
+ <p>Return to your terminal to continue setup.</p>
1655
+ <div class="badge">You can close this window</div>
1656
+ </div>
1657
+ </body>
1658
+ </html>`;
1659
+ }
1660
+ function getErrorHtml(message) {
1661
+ return `<!DOCTYPE html>
1662
+ <html>
1663
+ <head>
1664
+ <title>VibeTasks - Error</title>
1665
+ <style>
1666
+ body {
1667
+ font-family: system-ui; display: flex; align-items: center;
1668
+ justify-content: center; height: 100vh; margin: 0; background: #f5f5f5;
1669
+ }
1670
+ .container {
1671
+ text-align: center; padding: 40px; background: white;
1672
+ border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);
1673
+ }
1674
+ h1 { color: #e53e3e; margin-bottom: 16px; }
1675
+ </style>
1676
+ </head>
1677
+ <body>
1678
+ <div class="container">
1679
+ <h1>Authentication Failed</h1>
1680
+ <p>${message}</p>
1681
+ </div>
1682
+ </body>
1683
+ </html>`;
1684
+ }
1685
+ var setupCommand = new Command12("setup").description("Interactive setup wizard for VibeTasks").option("--skip-auth", "Skip authentication step").option("--skip-claude", "Skip Claude Code configuration").option("--skip-project", "Skip project initialization").option("--skip-verify", "Skip verification step").action(async (options) => {
1686
+ showWelcome();
1687
+ const { proceed } = await inquirer5.prompt([{
1688
+ type: "confirm",
1689
+ name: "proceed",
1690
+ message: "Ready to begin setup?",
1691
+ default: true
1692
+ }]);
1693
+ if (!proceed) {
1694
+ console.log(chalk13.gray("\nSetup cancelled. Run `vibetasks setup` anytime to continue.\n"));
1695
+ process.exit(0);
1696
+ }
1697
+ let authResult = { success: false };
1698
+ if (!options.skipAuth) {
1699
+ authResult = await stepAuthentication();
1700
+ if (!authResult.success) {
1701
+ console.log(chalk13.red("\n\u2717 Authentication is required to continue."));
1702
+ console.log(chalk13.gray(" Run `vibetasks setup` to try again.\n"));
1703
+ process.exit(1);
1704
+ }
1705
+ } else {
1706
+ authResult = { success: true, skipped: true };
1707
+ }
1708
+ let claudeResult = { success: true, skipped: true };
1709
+ if (!options.skipClaude) {
1710
+ claudeResult = await stepClaudeCodeConfig();
1711
+ }
1712
+ let projectResult = { success: true, skipped: true };
1713
+ if (!options.skipProject) {
1714
+ projectResult = await stepProjectInit();
1715
+ }
1716
+ let verifyResult = { supabaseConnected: false, mcpConfigured: false };
1717
+ if (!options.skipVerify && authResult.success && !authResult.skipped) {
1718
+ verifyResult = await stepVerify();
1719
+ } else if (authResult.skipped) {
1720
+ verifyResult = await stepVerify();
1721
+ }
1722
+ showCompletion(authResult, claudeResult, projectResult, verifyResult);
1723
+ process.exit(0);
1724
+ });
1725
+
1113
1726
  // bin/vibetasks.ts
1114
- var program = new Command11();
1115
- program.name("vibetasks").description("VibeTasks CLI - Fast task management for developers").version("0.1.0");
1727
+ var program = new Command13();
1728
+ program.name("vibetasks").description("VibeTasks CLI - Fast task management for vibers").version("0.2.0");
1729
+ program.addCommand(setupCommand);
1116
1730
  program.addCommand(loginCommand);
1117
1731
  program.addCommand(addCommand);
1118
1732
  program.addCommand(listCommand);
1733
+ program.addCommand(vibingCommand);
1119
1734
  program.addCommand(doneCommand);
1120
1735
  program.addCommand(searchCommand);
1121
1736
  program.addCommand(updateCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibetasks/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "VibeTasks CLI - Lightning-fast task management from your terminal. Works with Claude Code, Cursor, and all AI coding tools.",
5
5
  "author": "Vyas",
6
6
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  "typecheck": "tsc --noEmit"
44
44
  },
45
45
  "dependencies": {
46
- "@vibetasks/core": "^0.1.0",
46
+ "@vibetasks/core": "^0.2.0",
47
47
  "@vibetasks/shared": "^1.0.0",
48
48
  "commander": "^11.1.0",
49
49
  "chalk": "^5.3.0",