@datacore-one/cli 1.0.4 → 1.0.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/index.js +684 -301
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7015,12 +7015,12 @@ async function invokeAgent(invocation, options = {}) {
7015
7015
  error: `Working directory not found: ${cwd}`
7016
7016
  };
7017
7017
  }
7018
- const prompt = buildAgentPrompt(invocation);
7018
+ const prompt2 = buildAgentPrompt(invocation);
7019
7019
  return new Promise((resolve) => {
7020
7020
  const chunks = [];
7021
7021
  let errorChunks = [];
7022
7022
  let timedOut = false;
7023
- const proc = spawn2("claude", ["--print", prompt], {
7023
+ const proc = spawn2("claude", ["--print", prompt2], {
7024
7024
  cwd,
7025
7025
  stdio: ["ignore", "pipe", "pipe"],
7026
7026
  env: {
@@ -7107,9 +7107,9 @@ function listAgents() {
7107
7107
  return [];
7108
7108
  }
7109
7109
  try {
7110
- const { readFileSync: readFileSync6 } = __require("fs");
7110
+ const { readFileSync: readFileSync5 } = __require("fs");
7111
7111
  const { parse: parse3 } = require_dist();
7112
- const content = readFileSync6(registryPath, "utf-8");
7112
+ const content = readFileSync5(registryPath, "utf-8");
7113
7113
  const registry = parse3(content);
7114
7114
  return registry.agents?.map((a) => a.name) || [];
7115
7115
  } catch {
@@ -7991,14 +7991,56 @@ function getVersion(cmd, versionFlag = "--version") {
7991
7991
  return;
7992
7992
  }
7993
7993
  }
7994
- function checkGit(platform2) {
7994
+ function getGitConfig(key) {
7995
+ try {
7996
+ return execSync2(`git config --global ${key}`, { encoding: "utf-8", stdio: "pipe" }).trim();
7997
+ } catch {
7998
+ return;
7999
+ }
8000
+ }
8001
+ function checkGitHubAuth() {
8002
+ try {
8003
+ const output2 = execSync2("gh auth status 2>&1", { encoding: "utf-8", stdio: "pipe" });
8004
+ const userMatch = output2.match(/Logged in to github\.com.*account (\S+)/i);
8005
+ return { authenticated: true, user: userMatch?.[1] };
8006
+ } catch {
8007
+ return { authenticated: false };
8008
+ }
8009
+ }
8010
+ function checkGitDetailed() {
7995
8011
  const installed = commandExists("git");
8012
+ if (!installed) {
8013
+ return { installed: false, configured: false, githubAuth: false };
8014
+ }
8015
+ const userName = getGitConfig("user.name");
8016
+ const userEmail = getGitConfig("user.email");
8017
+ const configured = !!(userName && userEmail);
8018
+ const ghInstalled = commandExists("gh");
8019
+ let githubAuth = false;
8020
+ let githubUser;
8021
+ if (ghInstalled) {
8022
+ const ghStatus = checkGitHubAuth();
8023
+ githubAuth = ghStatus.authenticated;
8024
+ githubUser = ghStatus.user;
8025
+ }
8026
+ return {
8027
+ installed: true,
8028
+ version: getVersion("git"),
8029
+ configured,
8030
+ userName,
8031
+ userEmail,
8032
+ githubAuth,
8033
+ githubUser
8034
+ };
8035
+ }
8036
+ function checkGit(platform2) {
8037
+ const status = checkGitDetailed();
7996
8038
  return {
7997
8039
  name: "git",
7998
8040
  required: true,
7999
- installed,
8000
- version: installed ? getVersion("git") : undefined,
8001
- installCommand: installed ? undefined : getInstallCommand("git", platform2) ?? undefined
8041
+ installed: status.installed,
8042
+ version: status.version,
8043
+ installCommand: status.installed ? undefined : getInstallCommand("git", platform2) ?? undefined
8002
8044
  };
8003
8045
  }
8004
8046
  function checkGitLfs(platform2) {
@@ -8320,7 +8362,21 @@ function createSpace(name, type = "team") {
8320
8362
  throw new Error(`Space already exists: ${folderName}`);
8321
8363
  }
8322
8364
  mkdirSync2(spacePath, { recursive: true });
8323
- const dirs = [
8365
+ const dirs = type === "personal" ? [
8366
+ ".datacore",
8367
+ ".datacore/commands",
8368
+ ".datacore/agents",
8369
+ ".datacore/learning",
8370
+ ".datacore/state",
8371
+ ".datacore/env",
8372
+ "org",
8373
+ "0-inbox",
8374
+ "notes",
8375
+ "notes/journals",
8376
+ "notes/pages",
8377
+ "notes/zettel",
8378
+ "journal"
8379
+ ] : [
8324
8380
  ".datacore",
8325
8381
  ".datacore/commands",
8326
8382
  ".datacore/agents",
@@ -8331,6 +8387,11 @@ function createSpace(name, type = "team") {
8331
8387
  "0-inbox",
8332
8388
  "journal",
8333
8389
  "1-tracks",
8390
+ "1-tracks/ops",
8391
+ "1-tracks/product",
8392
+ "1-tracks/dev",
8393
+ "1-tracks/research",
8394
+ "1-tracks/comms",
8334
8395
  "2-projects",
8335
8396
  "3-knowledge",
8336
8397
  "3-knowledge/pages",
@@ -8342,20 +8403,87 @@ function createSpace(name, type = "team") {
8342
8403
  for (const dir of dirs) {
8343
8404
  mkdirSync2(join3(spacePath, dir), { recursive: true });
8344
8405
  }
8345
- writeFileSync2(join3(spacePath, "org", "inbox.org"), `#+TITLE: Inbox
8406
+ if (type === "personal") {
8407
+ writeFileSync2(join3(spacePath, "org", "inbox.org"), `#+TITLE: Inbox
8408
+ #+FILETAGS: :inbox:
8409
+
8410
+ Capture everything here. Process daily to zero.
8411
+
8412
+ * Inbox
8413
+ `);
8414
+ writeFileSync2(join3(spacePath, "org", "next_actions.org"), `#+TITLE: Next Actions
8415
+ #+FILETAGS: :tasks:
8416
+
8417
+ Tasks organized by context. Tag with :AI: to delegate to agents.
8418
+
8419
+ * @computer
8420
+ * @phone
8421
+ * @errands
8422
+ * @home
8423
+ * @office
8424
+ * @waiting
8425
+ `);
8426
+ writeFileSync2(join3(spacePath, "org", "projects.org"), `#+TITLE: Projects
8427
+ #+FILETAGS: :projects:
8428
+
8429
+ Active projects (outcomes requiring multiple actions).
8430
+
8431
+ * Projects
8432
+ `);
8433
+ writeFileSync2(join3(spacePath, "org", "someday.org"), `#+TITLE: Someday/Maybe
8434
+ #+FILETAGS: :someday:
8435
+
8436
+ Ideas and projects for the future. Review monthly.
8437
+
8438
+ * Someday
8439
+ `);
8440
+ } else {
8441
+ writeFileSync2(join3(spacePath, "org", "inbox.org"), `#+TITLE: Inbox
8346
8442
  #+FILETAGS: :inbox:
8347
8443
 
8348
8444
  * Capture items here
8349
8445
  `);
8350
- writeFileSync2(join3(spacePath, "org", "next_actions.org"), `#+TITLE: Next Actions
8446
+ writeFileSync2(join3(spacePath, "org", "next_actions.org"), `#+TITLE: Next Actions
8351
8447
  #+FILETAGS: :tasks:
8352
8448
 
8353
8449
  * Tasks
8354
8450
  ** TODO items go here
8355
8451
  `);
8356
- writeFileSync2(join3(spacePath, "_index.md"), `# ${name}
8452
+ }
8453
+ if (type === "personal") {
8454
+ writeFileSync2(join3(spacePath, "_index.md"), `# Personal Space
8455
+
8456
+ Your personal knowledge base and GTD system.
8457
+
8458
+ ## GTD Workflow
8459
+
8460
+ 1. **Capture** → \`org/inbox.org\` - dump everything here
8461
+ 2. **Clarify** → Is it actionable? What's the next action?
8462
+ 3. **Organize** → Move to \`next_actions.org\` by context
8463
+ 4. **Reflect** → Weekly review, monthly strategic
8464
+ 5. **Engage** → Do the work, delegate with :AI: tags
8465
+
8466
+ ## Quick Links
8467
+
8468
+ - [Inbox](org/inbox.org) - Capture here
8469
+ - [Next Actions](org/next_actions.org) - Today's work
8470
+ - [Projects](org/projects.org) - Active projects
8471
+ - [Someday](org/someday.org) - Future ideas
8472
+ - [Notes](notes/) - Knowledge base
8473
+ - [Journal](journal/) - Daily entries
8474
+ `);
8475
+ } else {
8476
+ writeFileSync2(join3(spacePath, "_index.md"), `# ${name}
8477
+
8478
+ Team space.
8479
+
8480
+ ## Structure
8357
8481
 
8358
- ${type === "personal" ? "Personal" : "Team"} space.
8482
+ - \`org/\` - Task coordination
8483
+ - \`1-tracks/\` - Department work
8484
+ - \`2-projects/\` - Code repositories
8485
+ - \`3-knowledge/\` - Shared knowledge
8486
+ - \`4-archive/\` - Historical content
8359
8487
 
8360
8488
  ## Quick Links
8361
8489
 
@@ -8364,14 +8492,46 @@ ${type === "personal" ? "Personal" : "Team"} space.
8364
8492
  - [Journal](journal/)
8365
8493
  - [Knowledge](3-knowledge/)
8366
8494
  `);
8367
- writeFileSync2(join3(spacePath, "CLAUDE.base.md"), `# ${name} Space
8495
+ }
8496
+ if (type === "personal") {
8497
+ writeFileSync2(join3(spacePath, "CLAUDE.base.md"), `# Personal Space
8498
+
8499
+ Personal GTD system and knowledge base.
8500
+
8501
+ ## GTD Workflow
8502
+
8503
+ - \`org/inbox.org\` - Single capture point, process to zero daily
8504
+ - \`org/next_actions.org\` - Tasks by context (@computer, @phone, etc.)
8505
+ - \`org/projects.org\` - Active multi-step outcomes
8506
+ - \`org/someday.org\` - Future ideas, review monthly
8507
+
8508
+ ## AI Delegation
8509
+
8510
+ Tag tasks with \`:AI:\` to delegate to agents:
8511
+ - \`:AI:research:\` - Research and summarize
8512
+ - \`:AI:content:\` - Draft content
8513
+ - \`:AI:data:\` - Analyze data
8514
+
8515
+ ## Knowledge
8516
+
8517
+ - \`notes/\` - Personal knowledge base (Obsidian)
8518
+ - \`notes/journals/\` - Daily reflections
8519
+ - \`notes/zettel/\` - Atomic concept notes
8520
+
8521
+ ## See Also
8522
+
8523
+ Parent: ~/Data/CLAUDE.md
8524
+ `);
8525
+ } else {
8526
+ writeFileSync2(join3(spacePath, "CLAUDE.base.md"), `# ${name} Space
8368
8527
 
8369
- ${type === "personal" ? "Personal" : "Team"} space for ${name}.
8528
+ Team space for ${name}.
8370
8529
 
8371
8530
  ## Structure
8372
8531
 
8373
8532
  See parent CLAUDE.md for full documentation.
8374
8533
  `);
8534
+ }
8375
8535
  writeFileSync2(join3(spacePath, ".datacore", "config.yaml"), `# Space configuration
8376
8536
  name: ${normalizedName}
8377
8537
  type: ${type}
@@ -8388,7 +8548,11 @@ Human feedback log.
8388
8548
 
8389
8549
  Style and preference notes.
8390
8550
  `);
8391
- writeFileSync2(join3(spacePath, ".gitignore"), `.datacore/state/
8551
+ writeFileSync2(join3(spacePath, ".gitignore"), type === "personal" ? `.datacore/state/
8552
+ .datacore/env/
8553
+ CLAUDE.md
8554
+ CLAUDE.local.md
8555
+ ` : `.datacore/state/
8392
8556
  .datacore/env/
8393
8557
  CLAUDE.md
8394
8558
  CLAUDE.local.md
@@ -8539,26 +8703,193 @@ function getGitRepos() {
8539
8703
  }
8540
8704
 
8541
8705
  // src/lib/init.ts
8542
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, symlinkSync } from "fs";
8543
- import { join as join6 } from "path";
8706
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, symlinkSync } from "fs";
8707
+ import { join as join7 } from "path";
8708
+ import { createInterface } from "readline";
8709
+
8710
+ // src/lib/module.ts
8711
+ import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync2, rmSync } from "fs";
8712
+ import { join as join5, basename as basename3 } from "path";
8713
+ import { execSync as execSync4 } from "child_process";
8714
+ var DATA_DIR4 = join5(process.env.HOME || "~", "Data");
8715
+ var MODULES_DIR = join5(DATA_DIR4, ".datacore", "modules");
8716
+ var AVAILABLE_MODULES = [
8717
+ {
8718
+ name: "nightshift",
8719
+ description: "Overnight AI task execution",
8720
+ repo: "https://github.com/datacore-one/module-nightshift",
8721
+ features: ["Queues :AI: tasks for overnight processing", "Morning briefing with results", "Remote server support"]
8722
+ },
8723
+ {
8724
+ name: "crm",
8725
+ description: "Contact relationship management",
8726
+ repo: "https://github.com/datacore-one/module-crm",
8727
+ features: ["Contact profiles", "Interaction history", "Relationship tracking"]
8728
+ },
8729
+ {
8730
+ name: "meetings",
8731
+ description: "Meeting preparation and follow-up",
8732
+ repo: "https://github.com/datacore-one/module-meetings",
8733
+ features: ["Pre-meeting briefs", "Transcript processing", "Action item extraction"]
8734
+ },
8735
+ {
8736
+ name: "health",
8737
+ description: "Personal health and wellness tracking",
8738
+ repo: "https://github.com/datacore-one/module-health",
8739
+ features: ["Health metrics", "Habit tracking", "Wellness insights"]
8740
+ }
8741
+ ];
8742
+ function getAvailableModules() {
8743
+ const installed = listModules().map((m) => m.name);
8744
+ return AVAILABLE_MODULES.filter((m) => !installed.includes(m.name));
8745
+ }
8746
+ function listModules() {
8747
+ if (!existsSync5(MODULES_DIR)) {
8748
+ return [];
8749
+ }
8750
+ const entries = readdirSync2(MODULES_DIR, { withFileTypes: true });
8751
+ const modules = [];
8752
+ for (const entry of entries) {
8753
+ if (!entry.isDirectory())
8754
+ continue;
8755
+ if (entry.name.startsWith("."))
8756
+ continue;
8757
+ const modulePath = join5(MODULES_DIR, entry.name);
8758
+ const info2 = getModuleInfo(modulePath);
8759
+ if (info2) {
8760
+ modules.push(info2);
8761
+ }
8762
+ }
8763
+ return modules;
8764
+ }
8765
+ function getModuleInfo(modulePath) {
8766
+ const name = basename3(modulePath);
8767
+ const yamlPath = join5(modulePath, "module.yaml");
8768
+ const ymlPath = join5(modulePath, "module.yml");
8769
+ const configPath = existsSync5(yamlPath) ? yamlPath : existsSync5(ymlPath) ? ymlPath : null;
8770
+ let version;
8771
+ let description;
8772
+ if (configPath) {
8773
+ try {
8774
+ const { parse: parse2 } = require_dist();
8775
+ const content = readFileSync2(configPath, "utf-8");
8776
+ const config = parse2(content);
8777
+ version = config.version;
8778
+ description = config.description;
8779
+ } catch {}
8780
+ }
8781
+ const agentsDir = join5(modulePath, "agents");
8782
+ const agents = [];
8783
+ if (existsSync5(agentsDir)) {
8784
+ const agentFiles = readdirSync2(agentsDir);
8785
+ for (const file of agentFiles) {
8786
+ if (file.endsWith(".md")) {
8787
+ agents.push(file.replace(".md", ""));
8788
+ }
8789
+ }
8790
+ }
8791
+ const commandsDir = join5(modulePath, "commands");
8792
+ const commands = [];
8793
+ if (existsSync5(commandsDir)) {
8794
+ const cmdFiles = readdirSync2(commandsDir);
8795
+ for (const file of cmdFiles) {
8796
+ if (file.endsWith(".md")) {
8797
+ commands.push(file.replace(".md", ""));
8798
+ }
8799
+ }
8800
+ }
8801
+ return {
8802
+ name,
8803
+ path: modulePath,
8804
+ version,
8805
+ description,
8806
+ agents,
8807
+ commands
8808
+ };
8809
+ }
8810
+ function installModule(source) {
8811
+ if (!existsSync5(MODULES_DIR)) {
8812
+ const { mkdirSync: mkdirSync3 } = __require("fs");
8813
+ mkdirSync3(MODULES_DIR, { recursive: true });
8814
+ }
8815
+ let name;
8816
+ let isGit = false;
8817
+ if (source.includes("github.com") || source.startsWith("git@") || source.endsWith(".git")) {
8818
+ isGit = true;
8819
+ const match = source.match(/([^/]+?)(?:\.git)?$/);
8820
+ name = match?.[1] ?? source.split("/").pop() ?? "unknown";
8821
+ name = name.replace(/^module-/, "");
8822
+ } else if (source.startsWith("@")) {
8823
+ name = source.split("/").pop()?.replace(/^datacore-/, "") ?? "unknown";
8824
+ } else {
8825
+ name = source.replace(/^datacore-/, "").replace(/^module-/, "");
8826
+ }
8827
+ const modulePath = join5(MODULES_DIR, name);
8828
+ if (existsSync5(modulePath)) {
8829
+ throw new Error(`Module already installed: ${name}`);
8830
+ }
8831
+ if (isGit) {
8832
+ execSync4(`git clone ${source} "${modulePath}"`, { stdio: "pipe" });
8833
+ } else {
8834
+ const gitUrl = `https://github.com/datacore/module-${name}.git`;
8835
+ try {
8836
+ execSync4(`git clone ${gitUrl} "${modulePath}"`, { stdio: "pipe" });
8837
+ } catch {
8838
+ throw new Error(`Could not install module: ${source}`);
8839
+ }
8840
+ }
8841
+ const info2 = getModuleInfo(modulePath);
8842
+ if (!info2) {
8843
+ rmSync(modulePath, { recursive: true, force: true });
8844
+ throw new Error("Invalid module: missing module.yaml");
8845
+ }
8846
+ return info2;
8847
+ }
8848
+ function updateModules(name) {
8849
+ const modules = listModules();
8850
+ const results = [];
8851
+ const toUpdate = name ? modules.filter((m) => m.name === name) : modules;
8852
+ for (const mod of toUpdate) {
8853
+ try {
8854
+ const gitDir = join5(mod.path, ".git");
8855
+ if (existsSync5(gitDir)) {
8856
+ execSync4("git pull", { cwd: mod.path, stdio: "pipe" });
8857
+ results.push({ name: mod.name, updated: true });
8858
+ } else {
8859
+ results.push({ name: mod.name, updated: false, error: "Not a git repository" });
8860
+ }
8861
+ } catch (err) {
8862
+ results.push({ name: mod.name, updated: false, error: err.message });
8863
+ }
8864
+ }
8865
+ return results;
8866
+ }
8867
+ function removeModule(name) {
8868
+ const modulePath = join5(MODULES_DIR, name);
8869
+ if (!existsSync5(modulePath)) {
8870
+ return false;
8871
+ }
8872
+ rmSync(modulePath, { recursive: true, force: true });
8873
+ return true;
8874
+ }
8544
8875
 
8545
8876
  // src/state.ts
8546
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
8547
- import { join as join5 } from "path";
8548
- var STATE_DIR = join5(process.env.HOME || "~", "Data", ".datacore", "state");
8549
- var STATE_FILE = join5(STATE_DIR, "operations.json");
8877
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
8878
+ import { join as join6 } from "path";
8879
+ var STATE_DIR = join6(process.env.HOME || "~", "Data", ".datacore", "state");
8880
+ var STATE_FILE = join6(STATE_DIR, "operations.json");
8550
8881
  function ensureStateDir() {
8551
- if (!existsSync5(STATE_DIR)) {
8882
+ if (!existsSync6(STATE_DIR)) {
8552
8883
  mkdirSync3(STATE_DIR, { recursive: true });
8553
8884
  }
8554
8885
  }
8555
8886
  function loadState() {
8556
8887
  ensureStateDir();
8557
- if (!existsSync5(STATE_FILE)) {
8888
+ if (!existsSync6(STATE_FILE)) {
8558
8889
  return { operations: [] };
8559
8890
  }
8560
8891
  try {
8561
- const content = readFileSync2(STATE_FILE, "utf-8");
8892
+ const content = readFileSync3(STATE_FILE, "utf-8");
8562
8893
  return JSON.parse(content);
8563
8894
  } catch {
8564
8895
  return { operations: [] };
@@ -8651,6 +8982,7 @@ function startOperation(operation, params = {}) {
8651
8982
  }
8652
8983
 
8653
8984
  // src/lib/animation.ts
8985
+ var SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
8654
8986
  var c = {
8655
8987
  reset: "\x1B[0m",
8656
8988
  bright: "\x1B[1m",
@@ -8686,6 +9018,44 @@ ${c.green}${c.bright}
8686
9018
  ╚═══════════════════════════════════════════════════════════════╝
8687
9019
  ${c.reset}
8688
9020
  `;
9021
+ function sleep(ms) {
9022
+ return new Promise((resolve) => setTimeout(resolve, ms));
9023
+ }
9024
+ class Spinner {
9025
+ interval = null;
9026
+ frame = 0;
9027
+ message;
9028
+ constructor(message) {
9029
+ this.message = message;
9030
+ }
9031
+ start() {
9032
+ process.stdout.write("\x1B[?25l");
9033
+ this.interval = setInterval(() => {
9034
+ const spinner = SPINNER_FRAMES[this.frame % SPINNER_FRAMES.length];
9035
+ process.stdout.write(`\r${c.cyan}${spinner}${c.reset} ${this.message}`);
9036
+ this.frame++;
9037
+ }, 80);
9038
+ }
9039
+ update(message) {
9040
+ this.message = message;
9041
+ }
9042
+ succeed(message) {
9043
+ this.stop();
9044
+ console.log(`\r${c.green}✓${c.reset} ${message || this.message}`);
9045
+ }
9046
+ fail(message) {
9047
+ this.stop();
9048
+ console.log(`\r${c.yellow}✗${c.reset} ${message || this.message}`);
9049
+ }
9050
+ stop() {
9051
+ if (this.interval) {
9052
+ clearInterval(this.interval);
9053
+ this.interval = null;
9054
+ }
9055
+ process.stdout.write("\x1B[?25h");
9056
+ process.stdout.write("\r" + " ".repeat(this.message.length + 10) + "\r");
9057
+ }
9058
+ }
8689
9059
  function section(title) {
8690
9060
  console.log();
8691
9061
  console.log(`${c.cyan}${c.bright}▸ ${title}${c.reset}`);
@@ -8693,20 +9063,53 @@ function section(title) {
8693
9063
  }
8694
9064
 
8695
9065
  // src/lib/init.ts
8696
- var DATA_DIR4 = join6(process.env.HOME || "~", "Data");
8697
- var DATACORE_DIR = join6(DATA_DIR4, ".datacore");
9066
+ var DATA_DIR5 = join7(process.env.HOME || "~", "Data");
9067
+ var DATACORE_DIR = join7(DATA_DIR5, ".datacore");
9068
+ var c2 = {
9069
+ reset: "\x1B[0m",
9070
+ bold: "\x1B[1m",
9071
+ dim: "\x1B[2m",
9072
+ green: "\x1B[32m",
9073
+ yellow: "\x1B[33m",
9074
+ red: "\x1B[31m",
9075
+ cyan: "\x1B[36m",
9076
+ magenta: "\x1B[35m"
9077
+ };
9078
+ async function prompt(question, defaultValue) {
9079
+ const rl = createInterface({
9080
+ input: process.stdin,
9081
+ output: process.stdout
9082
+ });
9083
+ return new Promise((resolve) => {
9084
+ const defaultHint = defaultValue ? ` [${defaultValue}]` : "";
9085
+ rl.question(`${question}${defaultHint}: `, (answer) => {
9086
+ rl.close();
9087
+ resolve(answer.trim() || defaultValue || "");
9088
+ });
9089
+ });
9090
+ }
9091
+ async function confirm(question, defaultYes = true) {
9092
+ const hint = defaultYes ? "[Y/n]" : "[y/N]";
9093
+ const answer = await prompt(`${question} ${hint}`);
9094
+ if (!answer)
9095
+ return defaultYes;
9096
+ return answer.toLowerCase().startsWith("y");
9097
+ }
8698
9098
  function isInitialized() {
8699
- return existsSync6(DATACORE_DIR);
9099
+ return existsSync7(DATACORE_DIR);
8700
9100
  }
8701
9101
  async function initDatacore(options = {}) {
8702
9102
  const { nonInteractive = false, skipChecks = false, stream = false } = options;
8703
9103
  const isTTY = stream && process.stdout.isTTY;
9104
+ const interactive = isTTY && !nonInteractive;
8704
9105
  const result = {
8705
9106
  success: false,
8706
9107
  created: [],
8707
9108
  warnings: [],
8708
9109
  errors: [],
8709
- nextSteps: []
9110
+ nextSteps: [],
9111
+ spacesCreated: [],
9112
+ modulesInstalled: []
8710
9113
  };
8711
9114
  const op = startOperation("init", { options });
8712
9115
  op.start();
@@ -8714,42 +9117,63 @@ async function initDatacore(options = {}) {
8714
9117
  if (isTTY) {
8715
9118
  console.clear();
8716
9119
  console.log(BANNER);
9120
+ console.log(` ${c2.dim}Setting up your AI-powered second brain...${c2.reset}`);
8717
9121
  console.log();
9122
+ await sleep(300);
8718
9123
  }
8719
- const TOTAL_STEPS = 6;
8720
9124
  op.addStep("check_dependencies");
8721
9125
  op.startStep("check_dependencies");
8722
9126
  if (!skipChecks) {
8723
9127
  if (isTTY) {
8724
- section("Checking Dependencies");
8725
- console.log(" \x1B[90mDatacore requires a few tools to manage your knowledge system.\x1B[0m");
9128
+ section("Step 1: Checking Your System");
8726
9129
  console.log();
8727
9130
  }
8728
9131
  const doctor = runDoctor();
8729
- const depInfo = {
8730
- git: "Version control for your knowledge repos",
8731
- "git-lfs": "Large file support (PDFs, images, videos)",
8732
- node: "Runtime for CLI tools and automation",
8733
- python: "Powers AI agents and data processing",
8734
- claude: "Claude Code AI assistant integration"
8735
- };
9132
+ const gitStatus = checkGitDetailed();
8736
9133
  if (isTTY) {
9134
+ if (gitStatus.installed) {
9135
+ console.log(` ${c2.green}✓${c2.reset} git ${c2.dim}(${gitStatus.version})${c2.reset}`);
9136
+ if (gitStatus.configured) {
9137
+ console.log(` ${c2.dim}Configured as: ${gitStatus.userName} <${gitStatus.userEmail}>${c2.reset}`);
9138
+ } else {
9139
+ console.log(` ${c2.yellow}⚠${c2.reset} ${c2.yellow}Not configured. Run:${c2.reset}`);
9140
+ console.log(` ${c2.dim}git config --global user.name "Your Name"${c2.reset}`);
9141
+ console.log(` ${c2.dim}git config --global user.email "you@example.com"${c2.reset}`);
9142
+ result.warnings.push("git not configured with user.name and user.email");
9143
+ }
9144
+ } else {
9145
+ console.log(` ${c2.red}✗${c2.reset} git ${c2.red}(required)${c2.reset}`);
9146
+ console.log(` ${c2.dim}Version control for your knowledge system${c2.reset}`);
9147
+ result.errors.push("git is required but not installed");
9148
+ }
9149
+ if (gitStatus.githubAuth) {
9150
+ console.log(` ${c2.green}✓${c2.reset} GitHub ${c2.dim}(authenticated as ${gitStatus.githubUser})${c2.reset}`);
9151
+ } else {
9152
+ console.log(` ${c2.yellow}○${c2.reset} GitHub ${c2.dim}(not authenticated)${c2.reset}`);
9153
+ console.log(` ${c2.dim}Optional: Install gh CLI and run 'gh auth login'${c2.reset}`);
9154
+ }
8737
9155
  for (const dep of doctor.dependencies) {
8738
- const info2 = depInfo[dep.name] || "";
9156
+ if (dep.name === "git")
9157
+ continue;
9158
+ const info2 = {
9159
+ "git-lfs": "Large file support (PDFs, images, videos)",
9160
+ node: "Runtime for automation scripts",
9161
+ python: "Powers AI agents and data processing",
9162
+ claude: "Claude Code AI assistant"
9163
+ };
8739
9164
  if (dep.installed) {
8740
- console.log(` \x1B[32m✓\x1B[0m ${dep.name} ${dep.version ? `\x1B[90m(${dep.version})\x1B[0m` : ""}`);
8741
- console.log(` \x1B[90m${info2}\x1B[0m`);
9165
+ console.log(` ${c2.green}✓${c2.reset} ${dep.name} ${dep.version ? `${c2.dim}(${dep.version})${c2.reset}` : ""}`);
8742
9166
  } else if (dep.required) {
8743
- console.log(` \x1B[31m✗\x1B[0m ${dep.name} \x1B[31m(required)\x1B[0m`);
8744
- console.log(` \x1B[90m${info2}\x1B[0m`);
9167
+ console.log(` ${c2.red}✗${c2.reset} ${dep.name} ${c2.red}(required)${c2.reset}`);
9168
+ console.log(` ${c2.dim}${info2[dep.name] || ""}${c2.reset}`);
8745
9169
  if (dep.installCommand) {
8746
- console.log(` \x1B[33mInstall: ${dep.installCommand}\x1B[0m`);
9170
+ console.log(` ${c2.yellow}Install: ${dep.installCommand}${c2.reset}`);
8747
9171
  }
8748
9172
  } else {
8749
- console.log(` \x1B[33m○\x1B[0m ${dep.name} \x1B[90m(optional)\x1B[0m`);
8750
- console.log(` \x1B[90m${info2}\x1B[0m`);
9173
+ console.log(` ${c2.yellow}○${c2.reset} ${dep.name} ${c2.dim}(recommended)${c2.reset}`);
9174
+ console.log(` ${c2.dim}${info2[dep.name] || ""}${c2.reset}`);
8751
9175
  if (dep.installCommand) {
8752
- console.log(` \x1B[90mInstall later: ${dep.installCommand}\x1B[0m`);
9176
+ console.log(` ${c2.dim}Install: ${dep.installCommand}${c2.reset}`);
8753
9177
  }
8754
9178
  }
8755
9179
  }
@@ -8758,19 +9182,22 @@ async function initDatacore(options = {}) {
8758
9182
  if (doctor.status === "missing_required") {
8759
9183
  const missing = doctor.dependencies.filter((d) => d.required && !d.installed);
8760
9184
  for (const dep of missing) {
8761
- result.errors.push(`Missing required dependency: ${dep.name}`);
8762
- if (dep.installCommand) {
8763
- result.errors.push(` Install with: ${dep.installCommand}`);
8764
- }
9185
+ result.errors.push(`Missing required: ${dep.name}`);
9186
+ }
9187
+ if (isTTY) {
9188
+ console.log(` ${c2.red}${c2.bold}Cannot continue - install required dependencies first.${c2.reset}`);
9189
+ console.log();
8765
9190
  }
8766
9191
  op.failStep("check_dependencies", "Missing required dependencies");
8767
9192
  op.fail("Missing required dependencies");
8768
9193
  return result;
8769
9194
  }
8770
- if (doctor.status === "missing_recommended") {
8771
- const missing = doctor.dependencies.filter((d) => !d.required && !d.installed);
8772
- for (const dep of missing) {
8773
- result.warnings.push(`Optional: ${dep.name} - install for full functionality`);
9195
+ if (interactive && !gitStatus.configured) {
9196
+ const proceed = await confirm("Git is not configured. Continue anyway?", false);
9197
+ if (!proceed) {
9198
+ result.errors.push("User cancelled: git not configured");
9199
+ op.fail("User cancelled");
9200
+ return result;
8774
9201
  }
8775
9202
  }
8776
9203
  }
@@ -8778,51 +9205,51 @@ async function initDatacore(options = {}) {
8778
9205
  op.addStep("create_data_dir");
8779
9206
  op.startStep("create_data_dir");
8780
9207
  if (isTTY) {
8781
- section("Setting Up ~/Data");
8782
- console.log(" \x1B[90mThis is your central knowledge directory. Everything lives here.\x1B[0m");
9208
+ section("Step 2: Creating ~/Data");
9209
+ console.log(` ${c2.dim}Your central knowledge directory. Everything lives here.${c2.reset}`);
8783
9210
  console.log();
8784
9211
  }
8785
- if (!existsSync6(DATA_DIR4)) {
8786
- mkdirSync4(DATA_DIR4, { recursive: true });
8787
- result.created.push(DATA_DIR4);
9212
+ if (!existsSync7(DATA_DIR5)) {
9213
+ mkdirSync4(DATA_DIR5, { recursive: true });
9214
+ result.created.push(DATA_DIR5);
8788
9215
  if (isTTY)
8789
- console.log(` \x1B[32m✓\x1B[0m Created ${DATA_DIR4}`);
8790
- } else if (isTTY) {
8791
- console.log(` \x1B[32m✓\x1B[0m Found existing ${DATA_DIR4}`);
9216
+ console.log(` ${c2.green}✓${c2.reset} Created ${DATA_DIR5}`);
9217
+ } else {
9218
+ if (isTTY)
9219
+ console.log(` ${c2.green}✓${c2.reset} Found ${DATA_DIR5}`);
8792
9220
  }
9221
+ if (isTTY)
9222
+ console.log();
8793
9223
  op.completeStep("create_data_dir");
8794
9224
  op.addStep("create_datacore_dir");
8795
9225
  op.startStep("create_datacore_dir");
8796
9226
  if (isTTY) {
8797
- console.log();
8798
- section("Creating .datacore");
8799
- console.log(" \x1B[90mSystem configuration, agents, and modules live here.\x1B[0m");
9227
+ section("Step 3: Creating .datacore");
9228
+ console.log(` ${c2.dim}System configuration, agents, commands, and modules.${c2.reset}`);
8800
9229
  console.log();
8801
9230
  }
8802
- if (!existsSync6(DATACORE_DIR)) {
9231
+ if (!existsSync7(DATACORE_DIR)) {
8803
9232
  const dirs = [
8804
- { path: "", desc: "Core configuration" },
8805
- { path: "commands", desc: "Slash commands (e.g., /today, /sync)" },
9233
+ { path: "", desc: "" },
9234
+ { path: "commands", desc: "Slash commands (/today, /sync, etc.)" },
8806
9235
  { path: "agents", desc: "AI agents for task automation" },
8807
- { path: "modules", desc: "Optional extensions (CRM, meetings, etc.)" },
9236
+ { path: "modules", desc: "Optional extensions" },
8808
9237
  { path: "specs", desc: "System documentation" },
8809
9238
  { path: "lib", desc: "Shared utilities" },
8810
- { path: "env", desc: "Secrets and API keys (gitignored)" },
8811
- { path: "state", desc: "Runtime state (gitignored)" },
8812
- { path: "registry", desc: "Agent and command discovery" }
9239
+ { path: "env", desc: "API keys and secrets" },
9240
+ { path: "state", desc: "Runtime state" },
9241
+ { path: "registry", desc: "Agent/command discovery" }
8813
9242
  ];
8814
9243
  for (const { path: dir, desc } of dirs) {
8815
- const path = join6(DATACORE_DIR, dir);
8816
- if (!existsSync6(path)) {
8817
- mkdirSync4(path, { recursive: true });
8818
- result.created.push(path);
8819
- if (isTTY && dir) {
8820
- console.log(` \x1B[32m✓\x1B[0m ${dir}/ \x1B[90m- ${desc}\x1B[0m`);
8821
- }
9244
+ const path = join7(DATACORE_DIR, dir);
9245
+ mkdirSync4(path, { recursive: true });
9246
+ result.created.push(path);
9247
+ if (isTTY && dir) {
9248
+ console.log(` ${c2.green}✓${c2.reset} ${dir}/ ${c2.dim}- ${desc}${c2.reset}`);
8822
9249
  }
8823
9250
  }
8824
- writeFileSync4(join6(DATACORE_DIR, "settings.yaml"), `# Datacore Settings
8825
- # Override in settings.local.yaml
9251
+ writeFileSync4(join7(DATACORE_DIR, "settings.yaml"), `# Datacore Settings
9252
+ # Override in settings.local.yaml (gitignored)
8826
9253
 
8827
9254
  editor:
8828
9255
  open_markdown_on_generate: true
@@ -8839,95 +9266,162 @@ nightshift:
8839
9266
  server: ""
8840
9267
  auto_trigger: false
8841
9268
  `);
8842
- result.created.push(join6(DATACORE_DIR, "settings.yaml"));
8843
- writeFileSync4(join6(DATACORE_DIR, "registry", "agents.yaml"), `# Agent Registry
8844
- # Agents are discovered from .datacore/agents/ and module agents/
8845
-
9269
+ result.created.push(join7(DATACORE_DIR, "settings.yaml"));
9270
+ writeFileSync4(join7(DATACORE_DIR, "registry", "agents.yaml"), `# Agent Registry
8846
9271
  agents: []
8847
9272
  `);
8848
- result.created.push(join6(DATACORE_DIR, "registry", "agents.yaml"));
8849
- writeFileSync4(join6(DATACORE_DIR, "registry", "commands.yaml"), `# Command Registry
8850
- # Commands are discovered from .datacore/commands/ and module commands/
8851
-
9273
+ writeFileSync4(join7(DATACORE_DIR, "registry", "commands.yaml"), `# Command Registry
8852
9274
  commands: []
8853
9275
  `);
8854
- result.created.push(join6(DATACORE_DIR, "registry", "commands.yaml"));
8855
9276
  if (isTTY) {
8856
9277
  console.log();
8857
- console.log(` \x1B[32m✓\x1B[0m Created settings.yaml`);
8858
- console.log(" \x1B[90mCustomize in settings.local.yaml (gitignored)\x1B[0m");
9278
+ console.log(` ${c2.green}✓${c2.reset} Created settings.yaml`);
9279
+ console.log(` ${c2.dim}Customize in settings.local.yaml${c2.reset}`);
8859
9280
  }
8860
- } else if (isTTY) {
8861
- console.log(` \x1B[32m✓\x1B[0m Found existing .datacore/`);
9281
+ } else {
9282
+ if (isTTY)
9283
+ console.log(` ${c2.green}✓${c2.reset} Found existing .datacore/`);
8862
9284
  }
9285
+ if (isTTY)
9286
+ console.log();
8863
9287
  op.completeStep("create_datacore_dir");
8864
9288
  op.addStep("create_personal_space");
8865
9289
  op.startStep("create_personal_space");
8866
9290
  if (isTTY) {
8867
- console.log();
8868
- section("Creating Personal Space");
8869
- console.log(" \x1B[90mSpaces are separate knowledge areas (personal, work, projects).\x1B[0m");
8870
- console.log(" \x1B[90mEach space has its own GTD inbox, notes, and journals.\x1B[0m");
9291
+ section("Step 4: Creating Personal Space");
9292
+ console.log(` ${c2.dim}Your personal GTD system and knowledge base.${c2.reset}`);
8871
9293
  console.log();
8872
9294
  }
8873
- const spaces = listSpaces();
8874
- if (spaces.length === 0) {
8875
- try {
8876
- const space = createSpace("personal", "personal");
8877
- result.created.push(space.path);
8878
- if (isTTY) {
8879
- console.log(` \x1B[32m✓\x1B[0m Created 0-personal/`);
8880
- console.log(" \x1B[90morg/inbox.org - Capture tasks here\x1B[0m");
8881
- console.log(" \x1B[90mnotes/ - Your knowledge base\x1B[0m");
8882
- console.log(" \x1B[90mjournal/ - Daily entries\x1B[0m");
8883
- }
8884
- } catch (err) {
8885
- result.warnings.push(`Could not create personal space: ${err.message}`);
9295
+ const existingSpaces = listSpaces();
9296
+ const hasPersonal = existingSpaces.some((s) => s.number === 0);
9297
+ if (!hasPersonal) {
9298
+ const space = createSpace("personal", "personal");
9299
+ result.created.push(space.path);
9300
+ result.spacesCreated.push(space.name);
9301
+ if (isTTY) {
9302
+ console.log(` ${c2.green}✓${c2.reset} Created 0-personal/`);
9303
+ console.log();
9304
+ console.log(` ${c2.bold}GTD Inbox:${c2.reset} org/inbox.org`);
9305
+ console.log(` ${c2.dim}Capture everything here, process to zero daily${c2.reset}`);
9306
+ console.log();
9307
+ console.log(` ${c2.bold}Next Actions:${c2.reset} org/next_actions.org`);
9308
+ console.log(` ${c2.dim}Tasks by context: @computer, @phone, @errands${c2.reset}`);
9309
+ console.log(` ${c2.dim}Tag with :AI: to delegate to agents${c2.reset}`);
9310
+ console.log();
9311
+ console.log(` ${c2.bold}Knowledge:${c2.reset} notes/`);
9312
+ console.log(` ${c2.dim}Your personal wiki and note archive${c2.reset}`);
8886
9313
  }
8887
- } else if (isTTY) {
8888
- console.log(` \x1B[32m✓\x1B[0m Found ${spaces.length} existing space(s):`);
8889
- for (const space of spaces) {
8890
- console.log(` \x1B[90m${space.name}/\x1B[0m`);
9314
+ } else {
9315
+ if (isTTY) {
9316
+ console.log(` ${c2.green}✓${c2.reset} Found existing personal space`);
8891
9317
  }
8892
9318
  }
9319
+ if (isTTY)
9320
+ console.log();
8893
9321
  op.completeStep("create_personal_space");
9322
+ if (interactive) {
9323
+ section("Step 5: Additional Spaces");
9324
+ console.log(` ${c2.dim}Spaces separate different areas of your life (work, projects, teams).${c2.reset}`);
9325
+ console.log(` ${c2.dim}Each space is a separate git repo with its own GTD system.${c2.reset}`);
9326
+ console.log();
9327
+ const wantMoreSpaces = await confirm("Would you like to create additional spaces?", false);
9328
+ if (wantMoreSpaces) {
9329
+ let creating = true;
9330
+ while (creating) {
9331
+ const name = await prompt('Space name (e.g., "work", "acme-corp")');
9332
+ if (!name) {
9333
+ creating = false;
9334
+ continue;
9335
+ }
9336
+ try {
9337
+ const space = createSpace(name, "team");
9338
+ result.created.push(space.path);
9339
+ result.spacesCreated.push(space.name);
9340
+ console.log(` ${c2.green}✓${c2.reset} Created ${space.name}/`);
9341
+ } catch (err) {
9342
+ console.log(` ${c2.red}✗${c2.reset} ${err.message}`);
9343
+ }
9344
+ creating = await confirm("Create another space?", false);
9345
+ }
9346
+ }
9347
+ console.log();
9348
+ }
9349
+ if (interactive) {
9350
+ section("Step 6: Install Modules");
9351
+ console.log(` ${c2.dim}Modules add features like overnight AI processing, CRM, and more.${c2.reset}`);
9352
+ console.log();
9353
+ const available = getAvailableModules();
9354
+ if (available.length > 0) {
9355
+ const wantModules = await confirm("Would you like to install modules?", true);
9356
+ if (wantModules) {
9357
+ console.log();
9358
+ console.log(" Available modules:");
9359
+ console.log();
9360
+ for (let i = 0;i < available.length; i++) {
9361
+ const mod = available[i];
9362
+ console.log(` ${c2.cyan}${i + 1}${c2.reset}) ${c2.bold}${mod.name}${c2.reset} - ${mod.description}`);
9363
+ for (const feature of mod.features) {
9364
+ console.log(` ${c2.dim}• ${feature}${c2.reset}`);
9365
+ }
9366
+ console.log();
9367
+ }
9368
+ const choices = await prompt('Enter numbers to install (comma-separated, or "all", or "none")');
9369
+ let toInstall = [];
9370
+ if (choices.toLowerCase() === "all") {
9371
+ toInstall = available.map((m) => m.name);
9372
+ } else if (choices && choices.toLowerCase() !== "none") {
9373
+ const nums = choices.split(",").map((s) => parseInt(s.trim(), 10));
9374
+ toInstall = nums.filter((n) => n >= 1 && n <= available.length).map((n) => available[n - 1].name);
9375
+ }
9376
+ for (const modName of toInstall) {
9377
+ const mod = available.find((m) => m.name === modName);
9378
+ if (!mod)
9379
+ continue;
9380
+ const spinner = new Spinner(`Installing ${modName}...`);
9381
+ spinner.start();
9382
+ try {
9383
+ await sleep(100);
9384
+ installModule(mod.repo);
9385
+ spinner.succeed(`Installed ${modName}`);
9386
+ result.modulesInstalled.push(modName);
9387
+ } catch (err) {
9388
+ spinner.fail(`Failed to install ${modName}: ${err.message}`);
9389
+ result.warnings.push(`Failed to install ${modName}`);
9390
+ }
9391
+ }
9392
+ }
9393
+ } else {
9394
+ console.log(` ${c2.dim}No additional modules available to install.${c2.reset}`);
9395
+ }
9396
+ console.log();
9397
+ }
8894
9398
  op.addStep("create_claude_symlink");
8895
9399
  op.startStep("create_claude_symlink");
8896
9400
  if (isTTY) {
8897
- console.log();
8898
- section("Linking Claude Code");
8899
- console.log(" \x1B[90mClaude Code looks for .claude/ to find project context.\x1B[0m");
8900
- console.log(" \x1B[90mThis symlink connects it to your Datacore configuration.\x1B[0m");
9401
+ section("Step 7: Claude Code Integration");
9402
+ console.log(` ${c2.dim}Connecting Datacore to Claude Code AI assistant.${c2.reset}`);
8901
9403
  console.log();
8902
9404
  }
8903
- const claudeDir = join6(DATA_DIR4, ".claude");
8904
- if (!existsSync6(claudeDir)) {
9405
+ const claudeDir = join7(DATA_DIR5, ".claude");
9406
+ if (!existsSync7(claudeDir)) {
8905
9407
  try {
8906
9408
  symlinkSync(DATACORE_DIR, claudeDir);
8907
9409
  result.created.push(claudeDir);
8908
9410
  if (isTTY)
8909
- console.log(` \x1B[32m✓\x1B[0m Created .claude -> .datacore symlink`);
9411
+ console.log(` ${c2.green}✓${c2.reset} Created .claude -> .datacore symlink`);
8910
9412
  } catch {
8911
9413
  result.warnings.push("Could not create .claude symlink");
8912
9414
  if (isTTY)
8913
- console.log(` \x1B[33m○\x1B[0m Could not create symlink (run manually if needed)`);
9415
+ console.log(` ${c2.yellow}○${c2.reset} Could not create symlink`);
8914
9416
  }
8915
- } else if (isTTY) {
8916
- console.log(` \x1B[32m✓\x1B[0m Found existing .claude/`);
8917
- }
8918
- op.completeStep("create_claude_symlink");
8919
- op.addStep("create_claude_md");
8920
- op.startStep("create_claude_md");
8921
- if (isTTY) {
8922
- console.log();
8923
- section("Creating CLAUDE.md");
8924
- console.log(" \x1B[90mThis file tells Claude Code about your Datacore system.\x1B[0m");
8925
- console.log(" \x1B[90mIt auto-loads when you run `claude` in ~/Data.\x1B[0m");
8926
- console.log();
9417
+ } else {
9418
+ if (isTTY)
9419
+ console.log(` ${c2.green}✓${c2.reset} Found existing .claude/`);
8927
9420
  }
8928
- const claudeMd = join6(DATA_DIR4, "CLAUDE.md");
8929
- const claudeBaseMd = join6(DATA_DIR4, "CLAUDE.base.md");
8930
- if (!existsSync6(claudeMd) && !existsSync6(claudeBaseMd)) {
9421
+ const claudeMd = join7(DATA_DIR5, "CLAUDE.md");
9422
+ const claudeBaseMd = join7(DATA_DIR5, "CLAUDE.base.md");
9423
+ if (!existsSync7(claudeMd) && !existsSync7(claudeBaseMd)) {
9424
+ const allSpaces = listSpaces();
8931
9425
  writeFileSync4(claudeBaseMd, `# Datacore
8932
9426
 
8933
9427
  AI-powered second brain built on GTD methodology.
@@ -8938,16 +9432,24 @@ AI-powered second brain built on GTD methodology.
8938
9432
  cd ~/Data && claude
8939
9433
  \`\`\`
8940
9434
 
9435
+ ## Daily Workflow
9436
+
9437
+ 1. **Morning**: Run \`/today\` for your daily briefing
9438
+ 2. **Capture**: Add tasks to \`0-personal/org/inbox.org\`
9439
+ 3. **Process**: Clear inbox, organize by context
9440
+ 4. **Work**: Use \`:AI:\` tags to delegate tasks
9441
+ 5. **Evening**: Run \`/tomorrow\` for wrap-up
9442
+
8941
9443
  ## Commands
8942
9444
 
8943
- - \`datacore today\` - Daily briefing
8944
- - \`datacore tomorrow\` - End-of-day wrap-up
8945
- - \`datacore sync\` - Sync all repos
9445
+ - \`/today\` - Daily briefing with priorities
9446
+ - \`/tomorrow\` - End-of-day wrap-up
9447
+ - \`/sync\` - Sync all repos
8946
9448
  - \`datacore doctor\` - Check system health
8947
9449
 
8948
9450
  ## Spaces
8949
9451
 
8950
- ${listSpaces().map((s) => `- ${s.name}`).join(`
9452
+ ${allSpaces.map((s) => `- ${s.name}`).join(`
8951
9453
  `) || "- 0-personal"}
8952
9454
 
8953
9455
  ## Documentation
@@ -8956,30 +9458,47 @@ See .datacore/specs/ for detailed documentation.
8956
9458
  `);
8957
9459
  result.created.push(claudeBaseMd);
8958
9460
  if (isTTY)
8959
- console.log(` \x1B[32m✓\x1B[0m Created CLAUDE.base.md`);
8960
- } else if (isTTY) {
8961
- console.log(` \x1B[32m✓\x1B[0m Found existing CLAUDE.md`);
9461
+ console.log(` ${c2.green}✓${c2.reset} Created CLAUDE.base.md`);
9462
+ } else {
9463
+ if (isTTY)
9464
+ console.log(` ${c2.green}✓${c2.reset} Found existing CLAUDE.md`);
8962
9465
  }
8963
- op.completeStep("create_claude_md");
9466
+ if (isTTY)
9467
+ console.log();
9468
+ op.completeStep("create_claude_symlink");
8964
9469
  result.success = true;
8965
9470
  result.nextSteps = [
8966
- "Run `datacore doctor` to verify your setup",
8967
- "Start working: `cd ~/Data && claude`"
9471
+ "cd ~/Data && claude",
9472
+ "Add tasks to 0-personal/org/inbox.org",
9473
+ "Run /today for your first daily briefing"
8968
9474
  ];
8969
9475
  if (isTTY) {
8970
- console.log();
8971
9476
  console.log(INIT_COMPLETE);
8972
9477
  console.log();
8973
- console.log(" \x1B[1mNext steps:\x1B[0m");
9478
+ console.log(` ${c2.bold}Setup Complete!${c2.reset}`);
9479
+ console.log();
9480
+ if (result.spacesCreated.length > 0) {
9481
+ console.log(` ${c2.green}Spaces created:${c2.reset} ${result.spacesCreated.join(", ")}`);
9482
+ }
9483
+ if (result.modulesInstalled.length > 0) {
9484
+ console.log(` ${c2.green}Modules installed:${c2.reset} ${result.modulesInstalled.join(", ")}`);
9485
+ }
9486
+ if (result.warnings.length > 0) {
9487
+ console.log(` ${c2.yellow}Warnings:${c2.reset} ${result.warnings.length}`);
9488
+ }
9489
+ console.log();
9490
+ console.log(` ${c2.bold}Get Started:${c2.reset}`);
9491
+ console.log();
9492
+ console.log(` ${c2.cyan}1.${c2.reset} cd ~/Data && claude`);
9493
+ console.log(` ${c2.dim}Start Claude Code in your Datacore directory${c2.reset}`);
8974
9494
  console.log();
8975
- console.log(" 1. \x1B[36mcd ~/Data && claude\x1B[0m");
8976
- console.log(" \x1B[90mStart using your second brain with AI assistance\x1B[0m");
9495
+ console.log(` ${c2.cyan}2.${c2.reset} Type ${c2.cyan}/today${c2.reset}`);
9496
+ console.log(` ${c2.dim}Get your first daily briefing${c2.reset}`);
8977
9497
  console.log();
8978
- console.log(" 2. \x1B[36mdatacore doctor\x1B[0m");
8979
- console.log(" \x1B[90mVerify everything is set up correctly\x1B[0m");
9498
+ console.log(` ${c2.cyan}3.${c2.reset} Add tasks to ${c2.cyan}0-personal/org/inbox.org${c2.reset}`);
9499
+ console.log(` ${c2.dim}Your GTD capture inbox${c2.reset}`);
8980
9500
  console.log();
8981
- console.log(" 3. Add tasks to \x1B[36m0-personal/org/inbox.org\x1B[0m");
8982
- console.log(" \x1B[90mYour GTD capture inbox - process daily\x1B[0m");
9501
+ console.log(` ${c2.dim}Run 'datacore doctor' anytime to check system health.${c2.reset}`);
8983
9502
  console.log();
8984
9503
  }
8985
9504
  op.complete();
@@ -8990,150 +9509,14 @@ See .datacore/specs/ for detailed documentation.
8990
9509
  return result;
8991
9510
  }
8992
9511
 
8993
- // src/lib/module.ts
8994
- import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync4, rmSync } from "fs";
8995
- import { join as join7, basename as basename3 } from "path";
8996
- import { execSync as execSync4 } from "child_process";
8997
- var DATA_DIR5 = join7(process.env.HOME || "~", "Data");
8998
- var MODULES_DIR = join7(DATA_DIR5, ".datacore", "modules");
8999
- function listModules() {
9000
- if (!existsSync7(MODULES_DIR)) {
9001
- return [];
9002
- }
9003
- const entries = readdirSync2(MODULES_DIR, { withFileTypes: true });
9004
- const modules = [];
9005
- for (const entry of entries) {
9006
- if (!entry.isDirectory())
9007
- continue;
9008
- if (entry.name.startsWith("."))
9009
- continue;
9010
- const modulePath = join7(MODULES_DIR, entry.name);
9011
- const info2 = getModuleInfo(modulePath);
9012
- if (info2) {
9013
- modules.push(info2);
9014
- }
9015
- }
9016
- return modules;
9017
- }
9018
- function getModuleInfo(modulePath) {
9019
- const name = basename3(modulePath);
9020
- const yamlPath = join7(modulePath, "module.yaml");
9021
- const ymlPath = join7(modulePath, "module.yml");
9022
- const configPath = existsSync7(yamlPath) ? yamlPath : existsSync7(ymlPath) ? ymlPath : null;
9023
- let version;
9024
- let description;
9025
- if (configPath) {
9026
- try {
9027
- const { parse: parse2 } = require_dist();
9028
- const content = readFileSync4(configPath, "utf-8");
9029
- const config = parse2(content);
9030
- version = config.version;
9031
- description = config.description;
9032
- } catch {}
9033
- }
9034
- const agentsDir = join7(modulePath, "agents");
9035
- const agents = [];
9036
- if (existsSync7(agentsDir)) {
9037
- const agentFiles = readdirSync2(agentsDir);
9038
- for (const file of agentFiles) {
9039
- if (file.endsWith(".md")) {
9040
- agents.push(file.replace(".md", ""));
9041
- }
9042
- }
9043
- }
9044
- const commandsDir = join7(modulePath, "commands");
9045
- const commands = [];
9046
- if (existsSync7(commandsDir)) {
9047
- const cmdFiles = readdirSync2(commandsDir);
9048
- for (const file of cmdFiles) {
9049
- if (file.endsWith(".md")) {
9050
- commands.push(file.replace(".md", ""));
9051
- }
9052
- }
9053
- }
9054
- return {
9055
- name,
9056
- path: modulePath,
9057
- version,
9058
- description,
9059
- agents,
9060
- commands
9061
- };
9062
- }
9063
- function installModule(source) {
9064
- if (!existsSync7(MODULES_DIR)) {
9065
- const { mkdirSync: mkdirSync5 } = __require("fs");
9066
- mkdirSync5(MODULES_DIR, { recursive: true });
9067
- }
9068
- let name;
9069
- let isGit = false;
9070
- if (source.includes("github.com") || source.startsWith("git@") || source.endsWith(".git")) {
9071
- isGit = true;
9072
- const match = source.match(/([^/]+?)(?:\.git)?$/);
9073
- name = match?.[1] ?? source.split("/").pop() ?? "unknown";
9074
- name = name.replace(/^module-/, "");
9075
- } else if (source.startsWith("@")) {
9076
- name = source.split("/").pop()?.replace(/^datacore-/, "") ?? "unknown";
9077
- } else {
9078
- name = source.replace(/^datacore-/, "").replace(/^module-/, "");
9079
- }
9080
- const modulePath = join7(MODULES_DIR, name);
9081
- if (existsSync7(modulePath)) {
9082
- throw new Error(`Module already installed: ${name}`);
9083
- }
9084
- if (isGit) {
9085
- execSync4(`git clone ${source} "${modulePath}"`, { stdio: "pipe" });
9086
- } else {
9087
- const gitUrl = `https://github.com/datacore/module-${name}.git`;
9088
- try {
9089
- execSync4(`git clone ${gitUrl} "${modulePath}"`, { stdio: "pipe" });
9090
- } catch {
9091
- throw new Error(`Could not install module: ${source}`);
9092
- }
9093
- }
9094
- const info2 = getModuleInfo(modulePath);
9095
- if (!info2) {
9096
- rmSync(modulePath, { recursive: true, force: true });
9097
- throw new Error("Invalid module: missing module.yaml");
9098
- }
9099
- return info2;
9100
- }
9101
- function updateModules(name) {
9102
- const modules = listModules();
9103
- const results = [];
9104
- const toUpdate = name ? modules.filter((m) => m.name === name) : modules;
9105
- for (const mod of toUpdate) {
9106
- try {
9107
- const gitDir = join7(mod.path, ".git");
9108
- if (existsSync7(gitDir)) {
9109
- execSync4("git pull", { cwd: mod.path, stdio: "pipe" });
9110
- results.push({ name: mod.name, updated: true });
9111
- } else {
9112
- results.push({ name: mod.name, updated: false, error: "Not a git repository" });
9113
- }
9114
- } catch (err) {
9115
- results.push({ name: mod.name, updated: false, error: err.message });
9116
- }
9117
- }
9118
- return results;
9119
- }
9120
- function removeModule(name) {
9121
- const modulePath = join7(MODULES_DIR, name);
9122
- if (!existsSync7(modulePath)) {
9123
- return false;
9124
- }
9125
- rmSync(modulePath, { recursive: true, force: true });
9126
- return true;
9127
- }
9128
-
9129
9512
  // src/lib/snapshot.ts
9130
9513
  var import_yaml2 = __toESM(require_dist(), 1);
9131
- import { existsSync as existsSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
9514
+ import { existsSync as existsSync8, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
9132
9515
  import { execSync as execSync5 } from "child_process";
9133
9516
  import { join as join8 } from "path";
9134
9517
  var DATA_DIR6 = join8(process.env.HOME || "~", "Data");
9135
9518
  var LOCK_FILE = join8(DATA_DIR6, "datacore.lock.yaml");
9136
- var CLI_VERSION = "1.0.4";
9519
+ var CLI_VERSION = "1.0.5";
9137
9520
  function getGitInfo(path) {
9138
9521
  if (!existsSync8(join8(path, ".git"))) {
9139
9522
  return {};
@@ -9199,7 +9582,7 @@ function createSnapshot(options = {}) {
9199
9582
  const settingsPath = join8(DATA_DIR6, ".datacore", "settings.yaml");
9200
9583
  if (existsSync8(settingsPath)) {
9201
9584
  try {
9202
- const content = readFileSync5(settingsPath, "utf-8");
9585
+ const content = readFileSync4(settingsPath, "utf-8");
9203
9586
  snapshot.settings = import_yaml2.parse(content);
9204
9587
  } catch {}
9205
9588
  }
@@ -9220,7 +9603,7 @@ function loadSnapshot(path) {
9220
9603
  return null;
9221
9604
  }
9222
9605
  try {
9223
- const content = readFileSync5(lockPath, "utf-8");
9606
+ const content = readFileSync4(lockPath, "utf-8");
9224
9607
  return import_yaml2.parse(content);
9225
9608
  } catch {
9226
9609
  return null;
@@ -9352,7 +9735,7 @@ function restoreFromSnapshot(snapshot, options = {}) {
9352
9735
  }
9353
9736
 
9354
9737
  // src/index.ts
9355
- var VERSION = "1.0.4";
9738
+ var VERSION = "1.0.5";
9356
9739
  var args = process.argv.slice(2);
9357
9740
  var parsed = parseArgs(args);
9358
9741
  async function handleMeta(command, cmdArgs, flags, format) {
@@ -9400,8 +9783,8 @@ async function handleMeta(command, cmdArgs, flags, format) {
9400
9783
  }
9401
9784
  console.log();
9402
9785
  console.log("Next steps:");
9403
- for (const step2 of result.nextSteps) {
9404
- console.log(` → ${step2}`);
9786
+ for (const step of result.nextSteps) {
9787
+ console.log(` → ${step}`);
9405
9788
  }
9406
9789
  } else {
9407
9790
  error("Initialization failed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datacore-one/cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "CLI for setting up and managing Datacore installations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",