@hacksmith/doraval 0.2.23 → 0.2.26

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 (3) hide show
  1. package/README.md +1 -0
  2. package/bin/doraval.js +301 -64
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -144,6 +144,7 @@ doraval journal update # pull latest from remote
144
144
 
145
145
  Requires the GitHub CLI (`gh`). Journal lives in a private GitHub repo you control.
146
146
 
147
+ doraval update # self-update doraval to the latest version
147
148
  doraval claude new # interactive wizard for skills/plugins (follows official table)
148
149
 
149
150
  ## Options
package/bin/doraval.js CHANGED
@@ -595,6 +595,71 @@ var init_dist = __esm(() => {
595
595
  negativePrefixRe = /^no[-A-Z]/;
596
596
  });
597
597
 
598
+ // package.json
599
+ var require_package = __commonJS((exports, module) => {
600
+ module.exports = {
601
+ name: "@hacksmith/doraval",
602
+ version: "0.2.26",
603
+ author: "Saif",
604
+ repository: {
605
+ type: "git",
606
+ url: "git+https://github.com/saif-shines/doraval.git"
607
+ },
608
+ devDependencies: {
609
+ "@types/bun": "latest"
610
+ },
611
+ bin: {
612
+ doraval: "bin/doraval-wrapper.js",
613
+ dora: "bin/doraval-wrapper.js"
614
+ },
615
+ description: "The context engineering toolkit for coding agents",
616
+ engines: {
617
+ bun: ">=1.2.0",
618
+ node: ">=14.18.0"
619
+ },
620
+ files: [
621
+ "bin/",
622
+ "dist/",
623
+ "README.md"
624
+ ],
625
+ keywords: [
626
+ "cli",
627
+ "skills",
628
+ "plugins",
629
+ "agent",
630
+ "validation",
631
+ "lint",
632
+ "claude-code",
633
+ "grok",
634
+ "cursor",
635
+ "windsurf",
636
+ "mcp"
637
+ ],
638
+ license: "MIT",
639
+ workspaces: [
640
+ "apps/*"
641
+ ],
642
+ scripts: {
643
+ build: "bun build ./src/cli/index.ts --outfile ./bin/doraval.js --target bun",
644
+ dev: "bun run ./src/cli/index.ts",
645
+ test: "bun test",
646
+ typecheck: "bunx tsc --noEmit --skipLibCheck",
647
+ prepublishOnly: `bun run build && node -e "const p=require('./package.json'),j=require('./jsr.json');if(p.version!==j.version){console.error('Version mismatch: package.json='+p.version+' jsr.json='+j.version);process.exit(1)}"`,
648
+ bump: "bun run scripts/bump.ts",
649
+ release: "bun run scripts/release.ts",
650
+ "jsr:publish": "bunx jsr publish",
651
+ "site:dev": "cd apps/website && bun run dev",
652
+ "site:build": "cd apps/website && bun run build",
653
+ "site:preview": "cd apps/website && bun run preview"
654
+ },
655
+ type: "module",
656
+ dependencies: {
657
+ citty: "^0.2.2",
658
+ picocolors: "^1.1.1"
659
+ }
660
+ };
661
+ });
662
+
598
663
  // node_modules/.bun/picocolors@1.1.1/node_modules/picocolors/picocolors.js
599
664
  var require_picocolors = __commonJS((exports, module) => {
600
665
  var p = process || {};
@@ -4756,72 +4821,243 @@ Project-specific decisions.
4756
4821
  });
4757
4822
  });
4758
4823
 
4759
- // src/cli/index.ts
4760
- init_dist();
4761
- // package.json
4762
- var package_default = {
4763
- name: "@hacksmith/doraval",
4764
- version: "0.2.23",
4765
- author: "Saif",
4766
- repository: {
4767
- type: "git",
4768
- url: "git+https://github.com/saif-shines/doraval.git"
4769
- },
4770
- devDependencies: {
4771
- "@types/bun": "latest"
4772
- },
4773
- bin: {
4774
- doraval: "bin/doraval-wrapper.js",
4775
- dora: "bin/doraval-wrapper.js"
4776
- },
4777
- description: "The context engineering toolkit for coding agents",
4778
- engines: {
4779
- bun: ">=1.2.0",
4780
- node: ">=14.18.0"
4781
- },
4782
- files: [
4783
- "bin/",
4784
- "dist/",
4785
- "README.md"
4786
- ],
4787
- keywords: [
4788
- "cli",
4789
- "skills",
4790
- "plugins",
4791
- "agent",
4792
- "validation",
4793
- "lint",
4794
- "claude-code",
4795
- "grok",
4796
- "cursor",
4797
- "windsurf",
4798
- "mcp"
4799
- ],
4800
- license: "MIT",
4801
- workspaces: [
4802
- "apps/*"
4803
- ],
4804
- scripts: {
4805
- build: "bun build ./src/cli/index.ts --outfile ./bin/doraval.js --target bun",
4806
- dev: "bun run ./src/cli/index.ts",
4807
- test: "bun test",
4808
- typecheck: "bunx tsc --noEmit --skipLibCheck",
4809
- prepublishOnly: `bun run build && node -e "const p=require('./package.json'),j=require('./jsr.json');if(p.version!==j.version){console.error('Version mismatch: package.json='+p.version+' jsr.json='+j.version);process.exit(1)}"`,
4810
- bump: "bun run scripts/bump.ts",
4811
- release: "bun run scripts/release.ts",
4812
- "jsr:publish": "bunx jsr publish",
4813
- "site:dev": "cd apps/website && bun run dev",
4814
- "site:build": "cd apps/website && bun run build",
4815
- "site:preview": "cd apps/website && bun run preview"
4816
- },
4817
- type: "module",
4818
- dependencies: {
4819
- citty: "^0.2.2",
4820
- picocolors: "^1.1.1"
4824
+ // src/core/update.ts
4825
+ import { execSync } from "child_process";
4826
+ import { existsSync as existsSync25 } from "fs";
4827
+ import { resolve as resolve15 } from "path";
4828
+ import { homedir as homedir2 } from "os";
4829
+ function isInPath(cmd) {
4830
+ try {
4831
+ execSync(`which ${cmd}`, { stdio: "ignore" });
4832
+ return true;
4833
+ } catch {
4834
+ return false;
4821
4835
  }
4822
- };
4836
+ }
4837
+ async function autoDetect() {
4838
+ const execPath = process.execPath;
4839
+ const argv0 = process.argv[0] || "";
4840
+ if (execPath.includes("/Cellar/") || execPath.includes("/homebrew/") || execPath.includes("/opt/homebrew/")) {
4841
+ if (isInPath("brew"))
4842
+ return { type: "homebrew" };
4843
+ }
4844
+ if (execPath.includes("/.npm/") || argv0.includes("npm")) {
4845
+ return { type: "npm" };
4846
+ }
4847
+ if (execPath.includes("/.bun/") || argv0.includes("bun")) {
4848
+ return { type: "bun" };
4849
+ }
4850
+ const home = homedir2();
4851
+ const possibleGlobals = [
4852
+ resolve15(home, ".npm-global/bin/doraval"),
4853
+ resolve15(home, ".bun/bin/doraval")
4854
+ ];
4855
+ for (const p of possibleGlobals) {
4856
+ if (existsSync25(p)) {
4857
+ if (p.includes(".npm"))
4858
+ return { type: "npm" };
4859
+ if (p.includes(".bun"))
4860
+ return { type: "bun" };
4861
+ }
4862
+ }
4863
+ return null;
4864
+ }
4865
+ async function detectInstallMethod(options) {
4866
+ if (options?.force) {
4867
+ if (["homebrew", "npm", "bun"].includes(options.force)) {
4868
+ return { type: options.force };
4869
+ }
4870
+ if (options.force === "npx" || options.force === "bunx") {
4871
+ return { type: "transient", via: options.force };
4872
+ }
4873
+ }
4874
+ const auto = await autoDetect();
4875
+ if (auto)
4876
+ return auto;
4877
+ const marker = await readInstallMarker();
4878
+ if (marker)
4879
+ return marker;
4880
+ return { type: "transient", via: "npx" };
4881
+ }
4882
+ async function fetchLatestVersionInfo() {
4883
+ const npmRes = await fetch("https://registry.npmjs.org/@hacksmith/doraval/latest");
4884
+ if (!npmRes.ok)
4885
+ throw new Error("Failed to fetch from npm");
4886
+ const npmData = await npmRes.json();
4887
+ const version = npmData.version;
4888
+ let summary = "New release available.";
4889
+ try {
4890
+ const ghRes = await fetch("https://api.github.com/repos/saif-shines/doraval/releases/latest", {
4891
+ headers: { "User-Agent": "doraval-update" }
4892
+ });
4893
+ if (ghRes.ok) {
4894
+ const ghData = await ghRes.json();
4895
+ const body = (ghData.body || "").trim();
4896
+ const lines = body.split(`
4897
+ `).filter((l) => l.trim().startsWith("-") || l.trim().startsWith("*")).slice(0, 2);
4898
+ if (lines.length)
4899
+ summary = lines.join(" ").slice(0, 200);
4900
+ else if (body)
4901
+ summary = body.split(`
4902
+ `)[0].slice(0, 150);
4903
+ }
4904
+ } catch {}
4905
+ return { version, summary };
4906
+ }
4907
+ function buildUpgradeCommand(method) {
4908
+ switch (method.type) {
4909
+ case "homebrew":
4910
+ return ["brew", "upgrade", "doraval"];
4911
+ case "npm":
4912
+ return ["npm", "install", "-g", "@hacksmith/doraval@latest"];
4913
+ case "bun":
4914
+ return ["bun", "add", "-g", "@hacksmith/doraval@latest"];
4915
+ default:
4916
+ throw new Error("Cannot build upgrade command for transient installs");
4917
+ }
4918
+ }
4919
+ function shouldUpdate(current, latest) {
4920
+ if (current === latest)
4921
+ return false;
4922
+ const c = current.split(".").map(Number);
4923
+ const l = latest.split(".").map(Number);
4924
+ for (let i = 0;i < 3; i++) {
4925
+ if ((l[i] || 0) > (c[i] || 0))
4926
+ return true;
4927
+ if ((l[i] || 0) < (c[i] || 0))
4928
+ return false;
4929
+ }
4930
+ return false;
4931
+ }
4932
+ async function readInstallMarker() {
4933
+ try {
4934
+ const { readFile } = await import("fs/promises");
4935
+ const data = await readFile(MARKER_PATH, "utf8");
4936
+ const parsed = JSON.parse(data);
4937
+ if (parsed && parsed.type)
4938
+ return parsed;
4939
+ } catch {}
4940
+ return null;
4941
+ }
4942
+ async function writeInstallMarker(method) {
4943
+ try {
4944
+ const { mkdir, writeFile } = await import("fs/promises");
4945
+ const { dirname: dirname2 } = await import("path");
4946
+ await mkdir(dirname2(MARKER_PATH), { recursive: true });
4947
+ await writeFile(MARKER_PATH, JSON.stringify(method, null, 2));
4948
+ } catch {}
4949
+ }
4950
+ var MARKER_PATH;
4951
+ var init_update2 = __esm(() => {
4952
+ MARKER_PATH = resolve15(homedir2(), ".doraval", "install.json");
4953
+ });
4954
+
4955
+ // src/cli/commands/update.ts
4956
+ var exports_update2 = {};
4957
+ __export(exports_update2, {
4958
+ default: () => update_default2
4959
+ });
4960
+ import { spawnSync as spawnSync6 } from "child_process";
4961
+ async function confirmUpdate() {
4962
+ const { createInterface } = await import("readline");
4963
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
4964
+ return new Promise((resolve16) => {
4965
+ rl.question("Update now? (y/N) ", (answer) => {
4966
+ rl.close();
4967
+ resolve16(answer.toLowerCase().startsWith("y"));
4968
+ });
4969
+ });
4970
+ }
4971
+ var update_default2;
4972
+ var init_update3 = __esm(() => {
4973
+ init_dist();
4974
+ init_out();
4975
+ init_update2();
4976
+ update_default2 = defineCommand({
4977
+ meta: {
4978
+ name: "update",
4979
+ description: "Update doraval to the latest version"
4980
+ },
4981
+ args: {
4982
+ check: {
4983
+ type: "boolean",
4984
+ description: "Only check for updates, do not install",
4985
+ default: false
4986
+ },
4987
+ yes: {
4988
+ type: "boolean",
4989
+ description: "Skip confirmation prompt",
4990
+ default: false
4991
+ }
4992
+ },
4993
+ async run({ args }) {
4994
+ const currentVersion = require_package().version;
4995
+ const argv1 = process.argv[1] || "";
4996
+ const isNpx = process.env.npm_execpath?.includes("npx") || argv1.includes("/.npm/") || process.env.npm_lifecycle_script?.includes("npx");
4997
+ const isBunx = process.env.BUN_INSTALL || argv1.includes(".bun/bin/bunx") || argv1.includes("bunx");
4998
+ if (isNpx || isBunx) {
4999
+ ui.info("It looks like you're using doraval via npx or bunx.");
5000
+ ui.info("These always fetch the latest version on the next run.");
5001
+ ui.info("");
5002
+ ui.info("For easier updates, install globally:");
5003
+ ui.info(" brew install saif-shines/tap/doraval");
5004
+ ui.info(" npm install -g @hacksmith/doraval");
5005
+ ui.info(" bun add -g @hacksmith/doraval");
5006
+ process.exit(0);
5007
+ }
5008
+ const method = await detectInstallMethod();
5009
+ if (method.type === "transient") {
5010
+ ui.info("Transient usage detected. Install globally for update support.");
5011
+ process.exit(0);
5012
+ }
5013
+ const latestInfo = await fetchLatestVersionInfo();
5014
+ if (!shouldUpdate(currentVersion, latestInfo.version)) {
5015
+ ui.success(`doraval is up to date (${currentVersion}).`);
5016
+ process.exit(0);
5017
+ }
5018
+ if (args.check) {
5019
+ ui.info(`Update available: ${currentVersion} \u2192 ${latestInfo.version}`);
5020
+ process.exit(1);
5021
+ }
5022
+ ui.heading("doraval update");
5023
+ ui.info(` Current: ${currentVersion}`);
5024
+ ui.info(` Latest: ${latestInfo.version}
5025
+ `);
5026
+ ui.info(` ${latestInfo.summary}
5027
+ `);
5028
+ if (!args.yes) {
5029
+ const confirmed = await confirmUpdate();
5030
+ if (!confirmed) {
5031
+ ui.info("Update cancelled.");
5032
+ process.exit(0);
5033
+ }
5034
+ }
5035
+ const cmd = buildUpgradeCommand(method);
5036
+ ui.info(`Running: ${cmd.join(" ")}
5037
+ `);
5038
+ const result = spawnSync6(cmd[0], cmd.slice(1), { stdio: "inherit" });
5039
+ if (result.status === 0) {
5040
+ ui.success(`Successfully updated to ${latestInfo.version}.`);
5041
+ ui.info("You may need to restart your shell to pick up the new version.");
5042
+ await writeInstallMarker(method);
5043
+ } else {
5044
+ ui.fail("Update failed.");
5045
+ ui.info("Common fixes:");
5046
+ if (cmd[0] === "brew")
5047
+ ui.info(" \u2022 Try: sudo brew upgrade doraval or ensure you are in the admin group");
5048
+ if (cmd[0] === "npm" || cmd[0] === "bun")
5049
+ ui.info(" \u2022 Try running with appropriate permissions or check network.");
5050
+ ui.info(`
5051
+ Raw output above.`);
5052
+ process.exit(result.status ?? 1);
5053
+ }
5054
+ }
5055
+ });
5056
+ });
4823
5057
 
4824
5058
  // src/cli/index.ts
5059
+ init_dist();
5060
+ var import__package = __toESM(require_package(), 1);
4825
5061
  var import_picocolors15 = __toESM(require_picocolors(), 1);
4826
5062
  var skill = defineCommand({
4827
5063
  meta: {
@@ -4894,13 +5130,14 @@ var doraemonArt = `
4894
5130
  var main = defineCommand({
4895
5131
  meta: {
4896
5132
  name: "doraval",
4897
- version: package_default.version,
5133
+ version: import__package.default.version,
4898
5134
  description: "The context engineering toolkit for coding agents"
4899
5135
  },
4900
5136
  subCommands: {
4901
5137
  validate: () => Promise.resolve().then(() => (init_validate_top(), exports_validate_top)).then((m) => m.default),
4902
5138
  init: () => Promise.resolve().then(() => (init_init2(), exports_init2)).then((m) => m.default),
4903
5139
  bump: () => Promise.resolve().then(() => (init_bump(), exports_bump)).then((m) => m.default),
5140
+ update: () => Promise.resolve().then(() => (init_update3(), exports_update2)).then((m) => m.default),
4904
5141
  skill: () => Promise.resolve(skill),
4905
5142
  journal: () => Promise.resolve(journal),
4906
5143
  claude: () => Promise.resolve(claude),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hacksmith/doraval",
3
- "version": "0.2.23",
3
+ "version": "0.2.26",
4
4
  "author": "Saif",
5
5
  "repository": {
6
6
  "type": "git",