@hacksmith/doraval 0.2.20 → 0.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/bin/doraval.js +288 -100
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,6 +142,8 @@ doraval journal update # pull latest from remote
|
|
|
142
142
|
|
|
143
143
|
Requires the GitHub CLI (`gh`). Journal lives in a private GitHub repo you control.
|
|
144
144
|
|
|
145
|
+
doraval claude new # interactive wizard for skills/plugins (follows official table)
|
|
146
|
+
|
|
145
147
|
## Options
|
|
146
148
|
|
|
147
149
|
| Flag | Short | Description |
|
package/bin/doraval.js
CHANGED
|
@@ -2588,8 +2588,183 @@ var init_sync = __esm(() => {
|
|
|
2588
2588
|
});
|
|
2589
2589
|
});
|
|
2590
2590
|
|
|
2591
|
+
// src/cli/commands/claude/context.ts
|
|
2592
|
+
import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
|
|
2593
|
+
import { join as join7 } from "path";
|
|
2594
|
+
function detectContext(cwd = process.cwd()) {
|
|
2595
|
+
const hasClaudeDir = existsSync8(join7(cwd, ".claude"));
|
|
2596
|
+
const hasPluginManifest = existsSync8(join7(cwd, ".claude-plugin", "plugin.json"));
|
|
2597
|
+
let looseSkillFiles = [];
|
|
2598
|
+
try {
|
|
2599
|
+
const files = readdirSync3(cwd);
|
|
2600
|
+
looseSkillFiles = files.filter((f) => {
|
|
2601
|
+
if (!f.endsWith(".md") || f.startsWith("."))
|
|
2602
|
+
return false;
|
|
2603
|
+
const lower = f.toLowerCase();
|
|
2604
|
+
if (lower === "readme.md" || lower === "changelog.md" || lower === "license.md" || lower.includes("contributing"))
|
|
2605
|
+
return false;
|
|
2606
|
+
return lower.includes("skill") || lower === "skill.md";
|
|
2607
|
+
});
|
|
2608
|
+
} catch {}
|
|
2609
|
+
const isEmpty = !hasClaudeDir && !hasPluginManifest && looseSkillFiles.length === 0;
|
|
2610
|
+
return {
|
|
2611
|
+
cwd,
|
|
2612
|
+
hasClaudeDir,
|
|
2613
|
+
hasPluginManifest,
|
|
2614
|
+
looseSkillFiles,
|
|
2615
|
+
isEmpty
|
|
2616
|
+
};
|
|
2617
|
+
}
|
|
2618
|
+
var init_context = () => {};
|
|
2619
|
+
|
|
2620
|
+
// src/cli/commands/claude/new.ts
|
|
2621
|
+
var exports_new = {};
|
|
2622
|
+
__export(exports_new, {
|
|
2623
|
+
scaffold: () => scaffold,
|
|
2624
|
+
default: () => new_default,
|
|
2625
|
+
decidePath: () => decidePath
|
|
2626
|
+
});
|
|
2627
|
+
import { join as join8 } from "path";
|
|
2628
|
+
import { mkdirSync as mkdirSync2, writeFileSync, existsSync as existsSync9 } from "fs";
|
|
2629
|
+
function decidePath(ctx, intent, providedName) {
|
|
2630
|
+
const rawName = providedName || "";
|
|
2631
|
+
let path = "standalone";
|
|
2632
|
+
let targetDir = ctx.cwd;
|
|
2633
|
+
let shouldCreateDir = false;
|
|
2634
|
+
let migrateExisting = false;
|
|
2635
|
+
const useCurrentDirAsRoot = rawName === "." || rawName === path.basename(ctx.cwd) || !rawName;
|
|
2636
|
+
if (intent === "distribute" || intent === "self-later" && ctx.looseSkillFiles.length > 0 && !ctx.hasClaudeDir) {
|
|
2637
|
+
path = "plugin";
|
|
2638
|
+
if (useCurrentDirAsRoot) {
|
|
2639
|
+
targetDir = ctx.cwd;
|
|
2640
|
+
shouldCreateDir = false;
|
|
2641
|
+
} else {
|
|
2642
|
+
targetDir = join8(ctx.cwd, rawName);
|
|
2643
|
+
shouldCreateDir = true;
|
|
2644
|
+
}
|
|
2645
|
+
migrateExisting = ctx.looseSkillFiles.length > 0;
|
|
2646
|
+
} else if (intent === "self-later" && !ctx.hasClaudeDir) {
|
|
2647
|
+
path = "plugin";
|
|
2648
|
+
if (useCurrentDirAsRoot) {
|
|
2649
|
+
targetDir = ctx.cwd;
|
|
2650
|
+
shouldCreateDir = false;
|
|
2651
|
+
} else {
|
|
2652
|
+
targetDir = join8(ctx.cwd, rawName);
|
|
2653
|
+
shouldCreateDir = true;
|
|
2654
|
+
}
|
|
2655
|
+
} else if (path === "standalone") {
|
|
2656
|
+
if (useCurrentDirAsRoot) {
|
|
2657
|
+
targetDir = ctx.cwd;
|
|
2658
|
+
shouldCreateDir = false;
|
|
2659
|
+
} else {
|
|
2660
|
+
targetDir = join8(ctx.cwd, rawName);
|
|
2661
|
+
shouldCreateDir = true;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
return { path, targetDir, shouldCreateDir, migrateExisting };
|
|
2665
|
+
}
|
|
2666
|
+
function scaffold(decision, ctx, migrateContent) {
|
|
2667
|
+
const { targetDir, path, shouldCreateDir } = decision;
|
|
2668
|
+
if (existsSync9(targetDir) && shouldCreateDir) {
|
|
2669
|
+
ui.fail("Target already exists");
|
|
2670
|
+
process.exit(1);
|
|
2671
|
+
}
|
|
2672
|
+
if (shouldCreateDir) {
|
|
2673
|
+
mkdirSync2(targetDir, { recursive: true });
|
|
2674
|
+
}
|
|
2675
|
+
if (path === "plugin") {
|
|
2676
|
+
const pluginJson = {
|
|
2677
|
+
name: decision.targetDir.split("/").pop(),
|
|
2678
|
+
description: "Scaffolded by doraval claude new",
|
|
2679
|
+
version: "0.1.0"
|
|
2680
|
+
};
|
|
2681
|
+
mkdirSync2(join8(targetDir, ".claude-plugin"), { recursive: true });
|
|
2682
|
+
writeFileSync(join8(targetDir, ".claude-plugin", "plugin.json"), JSON.stringify(pluginJson, null, 2));
|
|
2683
|
+
mkdirSync2(join8(targetDir, "skills", "my-skill"), { recursive: true });
|
|
2684
|
+
const skillBody = migrateContent || `# My Skill
|
|
2685
|
+
|
|
2686
|
+
Basic starter skill.`;
|
|
2687
|
+
writeFileSync(join8(targetDir, "skills", "my-skill", "SKILL.md"), `---
|
|
2688
|
+
name: my-skill
|
|
2689
|
+
description: Starter skill
|
|
2690
|
+
---
|
|
2691
|
+
|
|
2692
|
+
${skillBody}`);
|
|
2693
|
+
writeFileSync(join8(targetDir, "README.md"), "# " + pluginJson.name + `
|
|
2694
|
+
|
|
2695
|
+
Claude Code plugin scaffolded by doraval.`);
|
|
2696
|
+
} else {
|
|
2697
|
+
mkdirSync2(join8(targetDir, ".claude", "skills", "my-skill"), { recursive: true });
|
|
2698
|
+
const skillBody = migrateContent || `# My Skill
|
|
2699
|
+
|
|
2700
|
+
Basic starter.`;
|
|
2701
|
+
writeFileSync(join8(targetDir, ".claude", "skills", "my-skill", "SKILL.md"), `---
|
|
2702
|
+
name: my-skill
|
|
2703
|
+
description: Starter
|
|
2704
|
+
---
|
|
2705
|
+
|
|
2706
|
+
${skillBody}`);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
var import_picocolors10, new_default;
|
|
2710
|
+
var init_new = __esm(() => {
|
|
2711
|
+
init_dist();
|
|
2712
|
+
init_out();
|
|
2713
|
+
init_context();
|
|
2714
|
+
init_prompt();
|
|
2715
|
+
import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
2716
|
+
new_default = defineCommand({
|
|
2717
|
+
meta: {
|
|
2718
|
+
name: "new",
|
|
2719
|
+
description: "Create a new skill or plugin following Claude Code packaging rules"
|
|
2720
|
+
},
|
|
2721
|
+
args: {
|
|
2722
|
+
name: {
|
|
2723
|
+
type: "positional",
|
|
2724
|
+
description: "Optional name for the skill or plugin",
|
|
2725
|
+
required: false
|
|
2726
|
+
},
|
|
2727
|
+
yes: {
|
|
2728
|
+
type: "boolean",
|
|
2729
|
+
description: "Skip interactive prompts (use defaults and flags)",
|
|
2730
|
+
default: false
|
|
2731
|
+
},
|
|
2732
|
+
intent: {
|
|
2733
|
+
type: "string",
|
|
2734
|
+
description: 'Intent: "self" | "self-later" | "distribute"',
|
|
2735
|
+
required: false
|
|
2736
|
+
}
|
|
2737
|
+
},
|
|
2738
|
+
run({ args }) {
|
|
2739
|
+
ui.heading("doraval claude new \u2014 Context-aware scaffolding");
|
|
2740
|
+
const ctx = detectContext();
|
|
2741
|
+
let intent = args.intent || "self-later";
|
|
2742
|
+
if (!args.yes) {
|
|
2743
|
+
const ans = prompt(" Intent (self | self-later | distribute)", intent);
|
|
2744
|
+
intent = ans || intent;
|
|
2745
|
+
}
|
|
2746
|
+
const decision = decidePath(ctx, intent, args.name);
|
|
2747
|
+
ui.info(` Decision: path=${decision.path}, target=${decision.targetDir}`);
|
|
2748
|
+
let migrateContent;
|
|
2749
|
+
if (decision.migrateExisting && !args.yes) {
|
|
2750
|
+
migrateContent = "Content from your existing SKILL.md (user-confirmed).";
|
|
2751
|
+
}
|
|
2752
|
+
scaffold(decision, ctx, migrateContent);
|
|
2753
|
+
ui.write(`
|
|
2754
|
+
${import_picocolors10.default.green("\u2713")} Created ${decision.path} at ${import_picocolors10.default.bold(decision.targetDir)}`);
|
|
2755
|
+
ui.info(` Command: ${decision.path === "plugin" ? `/${decision.targetDir.split("/").pop()}:my-skill` : "/my-skill"}`);
|
|
2756
|
+
ui.info(` Test: claude --plugin-dir ${decision.targetDir} (or use normally for standalone)`);
|
|
2757
|
+
ui.info(` Validate: doraval validate ${decision.targetDir}`);
|
|
2758
|
+
if (decision.path === "plugin" && decision.migrateExisting) {
|
|
2759
|
+
ui.info(" (Existing content migrated where confirmed.)");
|
|
2760
|
+
}
|
|
2761
|
+
process.exit(0);
|
|
2762
|
+
}
|
|
2763
|
+
});
|
|
2764
|
+
});
|
|
2765
|
+
|
|
2591
2766
|
// src/validators/claude/skill.ts
|
|
2592
|
-
import { existsSync as
|
|
2767
|
+
import { existsSync as existsSync10 } from "fs";
|
|
2593
2768
|
import { resolve as resolve3 } from "path";
|
|
2594
2769
|
var OPTIONAL_DIRS2, claudeSkillValidator;
|
|
2595
2770
|
var init_skill = __esm(() => {
|
|
@@ -2602,7 +2777,7 @@ var init_skill = __esm(() => {
|
|
|
2602
2777
|
name: "Claude Skill",
|
|
2603
2778
|
description: "Validates SKILL.md per current Claude Code spec: frontmatter (name/description relaxed to recommended; directory name usually provides the /command), body, supporting files, dynamic injection (!`cmd`), substitutions ($ARGUMENTS, ${CLAUDE_*}), and advanced fields (allowed-tools, context, disable-model-invocation, when_to_use, etc.)",
|
|
2604
2779
|
detect(dir) {
|
|
2605
|
-
return
|
|
2780
|
+
return existsSync10(resolve3(dir, "SKILL.md"));
|
|
2606
2781
|
},
|
|
2607
2782
|
async validate(dir, _opts) {
|
|
2608
2783
|
const skillMd = resolve3(dir, "SKILL.md");
|
|
@@ -2617,15 +2792,15 @@ var init_skill = __esm(() => {
|
|
|
2617
2792
|
passes: []
|
|
2618
2793
|
};
|
|
2619
2794
|
}
|
|
2620
|
-
const existingDirs = OPTIONAL_DIRS2.filter((d) =>
|
|
2795
|
+
const existingDirs = OPTIONAL_DIRS2.filter((d) => existsSync10(resolve3(dir, d)));
|
|
2621
2796
|
return validateSkillModel(parsed, { existingDirs: [...existingDirs] });
|
|
2622
2797
|
}
|
|
2623
2798
|
};
|
|
2624
2799
|
});
|
|
2625
2800
|
|
|
2626
2801
|
// src/validators/claude/plugin.ts
|
|
2627
|
-
import { existsSync as
|
|
2628
|
-
import { resolve as resolve4, join as
|
|
2802
|
+
import { existsSync as existsSync11, readdirSync as readdirSync4 } from "fs";
|
|
2803
|
+
import { resolve as resolve4, join as join9 } from "path";
|
|
2629
2804
|
var NAME_REGEX2, RELATIVE_PATH_REGEX, claudePluginValidator;
|
|
2630
2805
|
var init_plugin = __esm(() => {
|
|
2631
2806
|
NAME_REGEX2 = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
@@ -2636,7 +2811,7 @@ var init_plugin = __esm(() => {
|
|
|
2636
2811
|
name: "Claude Plugin",
|
|
2637
2812
|
description: "Validates .claude-plugin/plugin.json manifest, component directories, and structure",
|
|
2638
2813
|
detect(dir) {
|
|
2639
|
-
return
|
|
2814
|
+
return existsSync11(resolve4(dir, ".claude-plugin", "plugin.json"));
|
|
2640
2815
|
},
|
|
2641
2816
|
async validate(dir, _opts) {
|
|
2642
2817
|
const errors = [];
|
|
@@ -2686,7 +2861,7 @@ var init_plugin = __esm(() => {
|
|
|
2686
2861
|
errors.push(`${field}: path "${s}" must start with "./" (relative)`);
|
|
2687
2862
|
} else if (s.includes("..")) {
|
|
2688
2863
|
errors.push(`${field}: path "${s}" must not use ".." (no parent traversal)`);
|
|
2689
|
-
} else if (
|
|
2864
|
+
} else if (existsSync11(resolve4(dir, s))) {
|
|
2690
2865
|
passes.push(`${field}: path "${s}" exists`);
|
|
2691
2866
|
} else {
|
|
2692
2867
|
warnings.push(`${field}: path "${s}" does not exist on disk`);
|
|
@@ -2699,11 +2874,11 @@ var init_plugin = __esm(() => {
|
|
|
2699
2874
|
}
|
|
2700
2875
|
}
|
|
2701
2876
|
const skillsDir = resolve4(dir, "skills");
|
|
2702
|
-
if (
|
|
2703
|
-
const skillEntries =
|
|
2877
|
+
if (existsSync11(skillsDir)) {
|
|
2878
|
+
const skillEntries = readdirSync4(skillsDir, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
2704
2879
|
for (const skill of skillEntries) {
|
|
2705
|
-
const skillMd =
|
|
2706
|
-
if (
|
|
2880
|
+
const skillMd = join9(skillsDir, skill.name, "SKILL.md");
|
|
2881
|
+
if (existsSync11(skillMd)) {
|
|
2707
2882
|
passes.push(`skills/${skill.name}/SKILL.md exists`);
|
|
2708
2883
|
} else {
|
|
2709
2884
|
errors.push(`skills/${skill.name}/ missing SKILL.md`);
|
|
@@ -2711,8 +2886,8 @@ var init_plugin = __esm(() => {
|
|
|
2711
2886
|
}
|
|
2712
2887
|
}
|
|
2713
2888
|
const commandsDir = resolve4(dir, "commands");
|
|
2714
|
-
if (
|
|
2715
|
-
const mdFiles =
|
|
2889
|
+
if (existsSync11(commandsDir)) {
|
|
2890
|
+
const mdFiles = readdirSync4(commandsDir).filter((f) => f.endsWith(".md"));
|
|
2716
2891
|
if (mdFiles.length > 0) {
|
|
2717
2892
|
passes.push(`commands/ has ${mdFiles.length} .md file(s)`);
|
|
2718
2893
|
} else {
|
|
@@ -2720,8 +2895,8 @@ var init_plugin = __esm(() => {
|
|
|
2720
2895
|
}
|
|
2721
2896
|
}
|
|
2722
2897
|
const agentsDir = resolve4(dir, "agents");
|
|
2723
|
-
if (
|
|
2724
|
-
const mdFiles =
|
|
2898
|
+
if (existsSync11(agentsDir)) {
|
|
2899
|
+
const mdFiles = readdirSync4(agentsDir).filter((f) => f.endsWith(".md"));
|
|
2725
2900
|
if (mdFiles.length > 0) {
|
|
2726
2901
|
passes.push(`agents/ has ${mdFiles.length} .md file(s)`);
|
|
2727
2902
|
} else {
|
|
@@ -2734,8 +2909,8 @@ var init_plugin = __esm(() => {
|
|
|
2734
2909
|
});
|
|
2735
2910
|
|
|
2736
2911
|
// src/validators/claude/marketplace.ts
|
|
2737
|
-
import { existsSync as
|
|
2738
|
-
import { resolve as resolve5, join as
|
|
2912
|
+
import { existsSync as existsSync12, readdirSync as readdirSync5 } from "fs";
|
|
2913
|
+
import { resolve as resolve5, join as join10 } from "path";
|
|
2739
2914
|
var claudeMarketplaceValidator;
|
|
2740
2915
|
var init_marketplace = __esm(() => {
|
|
2741
2916
|
claudeMarketplaceValidator = {
|
|
@@ -2745,15 +2920,15 @@ var init_marketplace = __esm(() => {
|
|
|
2745
2920
|
description: "Validates marketplace structure: plugins/ directory with valid plugin subdirectories",
|
|
2746
2921
|
detect(dir) {
|
|
2747
2922
|
const pluginsDir = resolve5(dir, "plugins");
|
|
2748
|
-
if (!
|
|
2923
|
+
if (!existsSync12(pluginsDir))
|
|
2749
2924
|
return false;
|
|
2750
2925
|
try {
|
|
2751
|
-
const entries =
|
|
2926
|
+
const entries = readdirSync5(pluginsDir, { withFileTypes: true });
|
|
2752
2927
|
for (const entry of entries) {
|
|
2753
2928
|
if (!entry.isDirectory())
|
|
2754
2929
|
continue;
|
|
2755
|
-
const hasSkills =
|
|
2756
|
-
const hasManifest =
|
|
2930
|
+
const hasSkills = existsSync12(join10(pluginsDir, entry.name, "skills"));
|
|
2931
|
+
const hasManifest = existsSync12(join10(pluginsDir, entry.name, ".claude-plugin", "plugin.json"));
|
|
2757
2932
|
if (hasSkills || hasManifest)
|
|
2758
2933
|
return true;
|
|
2759
2934
|
}
|
|
@@ -2765,32 +2940,32 @@ var init_marketplace = __esm(() => {
|
|
|
2765
2940
|
const warnings = [];
|
|
2766
2941
|
const passes = [];
|
|
2767
2942
|
const pluginsDir = resolve5(dir, "plugins");
|
|
2768
|
-
if (!
|
|
2943
|
+
if (!existsSync12(pluginsDir)) {
|
|
2769
2944
|
errors.push("Missing plugins/ directory");
|
|
2770
2945
|
return { errors, warnings, passes };
|
|
2771
2946
|
}
|
|
2772
2947
|
passes.push("plugins/ directory exists");
|
|
2773
|
-
const pluginEntries =
|
|
2948
|
+
const pluginEntries = readdirSync5(pluginsDir, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
2774
2949
|
if (pluginEntries.length === 0) {
|
|
2775
2950
|
errors.push("plugins/ directory is empty \u2014 expected at least one plugin");
|
|
2776
2951
|
return { errors, warnings, passes };
|
|
2777
2952
|
}
|
|
2778
2953
|
passes.push(`${pluginEntries.length} plugin(s) found`);
|
|
2779
|
-
if (
|
|
2954
|
+
if (existsSync12(resolve5(dir, "README.md"))) {
|
|
2780
2955
|
passes.push("README.md exists at marketplace root");
|
|
2781
2956
|
} else {
|
|
2782
2957
|
warnings.push("No README.md at marketplace root \u2014 recommended for discoverability");
|
|
2783
2958
|
}
|
|
2784
|
-
if (
|
|
2959
|
+
if (existsSync12(resolve5(dir, "LICENSE"))) {
|
|
2785
2960
|
passes.push("LICENSE exists at marketplace root");
|
|
2786
2961
|
} else {
|
|
2787
2962
|
warnings.push("No LICENSE at marketplace root \u2014 recommended");
|
|
2788
2963
|
}
|
|
2789
2964
|
for (const plugin of pluginEntries) {
|
|
2790
|
-
const pluginPath =
|
|
2791
|
-
const hasSkills =
|
|
2792
|
-
const hasManifest =
|
|
2793
|
-
const hasReadme =
|
|
2965
|
+
const pluginPath = join10(pluginsDir, plugin.name);
|
|
2966
|
+
const hasSkills = existsSync12(join10(pluginPath, "skills"));
|
|
2967
|
+
const hasManifest = existsSync12(join10(pluginPath, ".claude-plugin", "plugin.json"));
|
|
2968
|
+
const hasReadme = existsSync12(join10(pluginPath, "README.md"));
|
|
2794
2969
|
if (hasManifest || hasSkills) {
|
|
2795
2970
|
passes.push(`Plugin "${plugin.name}" has ${hasManifest ? "manifest" : "skills/"}`);
|
|
2796
2971
|
} else {
|
|
@@ -2806,7 +2981,7 @@ var init_marketplace = __esm(() => {
|
|
|
2806
2981
|
});
|
|
2807
2982
|
|
|
2808
2983
|
// src/validators/claude/hooks.ts
|
|
2809
|
-
import { existsSync as
|
|
2984
|
+
import { existsSync as existsSync13 } from "fs";
|
|
2810
2985
|
import { resolve as resolve6 } from "path";
|
|
2811
2986
|
var KNOWN_EVENTS, claudeHooksValidator;
|
|
2812
2987
|
var init_hooks = __esm(() => {
|
|
@@ -2828,13 +3003,13 @@ var init_hooks = __esm(() => {
|
|
|
2828
3003
|
name: "Claude Hooks",
|
|
2829
3004
|
description: "Validates hooks/hooks.json: event names, matcher structure, hook types",
|
|
2830
3005
|
detect(dir) {
|
|
2831
|
-
return
|
|
3006
|
+
return existsSync13(resolve6(dir, "hooks", "hooks.json")) || existsSync13(resolve6(dir, "hooks.json"));
|
|
2832
3007
|
},
|
|
2833
3008
|
async validate(dir, _opts) {
|
|
2834
3009
|
const errors = [];
|
|
2835
3010
|
const warnings = [];
|
|
2836
3011
|
const passes = [];
|
|
2837
|
-
const hooksPath =
|
|
3012
|
+
const hooksPath = existsSync13(resolve6(dir, "hooks", "hooks.json")) ? resolve6(dir, "hooks", "hooks.json") : resolve6(dir, "hooks.json");
|
|
2838
3013
|
let config;
|
|
2839
3014
|
try {
|
|
2840
3015
|
const raw = await Bun.file(hooksPath).text();
|
|
@@ -2858,7 +3033,7 @@ var init_hooks = __esm(() => {
|
|
|
2858
3033
|
});
|
|
2859
3034
|
|
|
2860
3035
|
// src/validators/claude/mcp.ts
|
|
2861
|
-
import { existsSync as
|
|
3036
|
+
import { existsSync as existsSync14 } from "fs";
|
|
2862
3037
|
import { resolve as resolve7 } from "path";
|
|
2863
3038
|
var claudeMcpValidator;
|
|
2864
3039
|
var init_mcp = __esm(() => {
|
|
@@ -2868,7 +3043,7 @@ var init_mcp = __esm(() => {
|
|
|
2868
3043
|
name: "Claude MCP Config",
|
|
2869
3044
|
description: "Validates .mcp.json: server definitions, required fields, path portability",
|
|
2870
3045
|
detect(dir) {
|
|
2871
|
-
return
|
|
3046
|
+
return existsSync14(resolve7(dir, ".mcp.json"));
|
|
2872
3047
|
},
|
|
2873
3048
|
async validate(dir, _opts) {
|
|
2874
3049
|
const errors = [];
|
|
@@ -2900,8 +3075,8 @@ var init_mcp = __esm(() => {
|
|
|
2900
3075
|
});
|
|
2901
3076
|
|
|
2902
3077
|
// src/validators/claude/subagent.ts
|
|
2903
|
-
import { existsSync as
|
|
2904
|
-
import { resolve as resolve8, join as
|
|
3078
|
+
import { existsSync as existsSync15, readdirSync as readdirSync6 } from "fs";
|
|
3079
|
+
import { resolve as resolve8, join as join11 } from "path";
|
|
2905
3080
|
var claudeSubagentValidator;
|
|
2906
3081
|
var init_subagent = __esm(() => {
|
|
2907
3082
|
init_frontmatter();
|
|
@@ -2912,10 +3087,10 @@ var init_subagent = __esm(() => {
|
|
|
2912
3087
|
description: "Validates agents/ directory: .md files with frontmatter and description",
|
|
2913
3088
|
detect(dir) {
|
|
2914
3089
|
const agentsDir = resolve8(dir, "agents");
|
|
2915
|
-
if (!
|
|
3090
|
+
if (!existsSync15(agentsDir))
|
|
2916
3091
|
return false;
|
|
2917
3092
|
try {
|
|
2918
|
-
return
|
|
3093
|
+
return readdirSync6(agentsDir).some((f) => f.endsWith(".md"));
|
|
2919
3094
|
} catch {
|
|
2920
3095
|
return false;
|
|
2921
3096
|
}
|
|
@@ -2925,14 +3100,14 @@ var init_subagent = __esm(() => {
|
|
|
2925
3100
|
const warnings = [];
|
|
2926
3101
|
const passes = [];
|
|
2927
3102
|
const agentsDir = resolve8(dir, "agents");
|
|
2928
|
-
const mdFiles =
|
|
3103
|
+
const mdFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md"));
|
|
2929
3104
|
if (mdFiles.length === 0) {
|
|
2930
3105
|
errors.push("agents/ directory has no .md files");
|
|
2931
3106
|
return { errors, warnings, passes };
|
|
2932
3107
|
}
|
|
2933
3108
|
passes.push(`${mdFiles.length} agent definition(s) found`);
|
|
2934
3109
|
for (const file of mdFiles) {
|
|
2935
|
-
const filePath =
|
|
3110
|
+
const filePath = join11(agentsDir, file);
|
|
2936
3111
|
const raw = await Bun.file(filePath).text();
|
|
2937
3112
|
try {
|
|
2938
3113
|
const parsed = parseFrontmatter(raw);
|
|
@@ -2956,8 +3131,8 @@ var init_subagent = __esm(() => {
|
|
|
2956
3131
|
});
|
|
2957
3132
|
|
|
2958
3133
|
// src/validators/claude/command.ts
|
|
2959
|
-
import { existsSync as
|
|
2960
|
-
import { resolve as resolve9, join as
|
|
3134
|
+
import { existsSync as existsSync16, readdirSync as readdirSync7 } from "fs";
|
|
3135
|
+
import { resolve as resolve9, join as join12 } from "path";
|
|
2961
3136
|
var claudeCommandValidator;
|
|
2962
3137
|
var init_command = __esm(() => {
|
|
2963
3138
|
init_frontmatter();
|
|
@@ -2968,10 +3143,10 @@ var init_command = __esm(() => {
|
|
|
2968
3143
|
description: "Validates commands/ (or legacy .claude/commands/) .md files: frontmatter (including rich skill fields), description, body",
|
|
2969
3144
|
detect(dir) {
|
|
2970
3145
|
const commandsDir = resolve9(dir, "commands");
|
|
2971
|
-
if (!
|
|
3146
|
+
if (!existsSync16(commandsDir))
|
|
2972
3147
|
return false;
|
|
2973
3148
|
try {
|
|
2974
|
-
return
|
|
3149
|
+
return readdirSync7(commandsDir).some((f) => f.endsWith(".md"));
|
|
2975
3150
|
} catch {
|
|
2976
3151
|
return false;
|
|
2977
3152
|
}
|
|
@@ -2981,14 +3156,14 @@ var init_command = __esm(() => {
|
|
|
2981
3156
|
const warnings = [];
|
|
2982
3157
|
const passes = [];
|
|
2983
3158
|
const commandsDir = resolve9(dir, "commands");
|
|
2984
|
-
const mdFiles =
|
|
3159
|
+
const mdFiles = readdirSync7(commandsDir).filter((f) => f.endsWith(".md"));
|
|
2985
3160
|
if (mdFiles.length === 0) {
|
|
2986
3161
|
errors.push("commands/ directory has no .md files");
|
|
2987
3162
|
return { errors, warnings, passes };
|
|
2988
3163
|
}
|
|
2989
3164
|
passes.push(`${mdFiles.length} command definition(s) found`);
|
|
2990
3165
|
for (const file of mdFiles) {
|
|
2991
|
-
const filePath =
|
|
3166
|
+
const filePath = join12(commandsDir, file);
|
|
2992
3167
|
const raw = await Bun.file(filePath).text();
|
|
2993
3168
|
try {
|
|
2994
3169
|
const parsed = parseFrontmatter(raw);
|
|
@@ -3017,7 +3192,7 @@ var init_command = __esm(() => {
|
|
|
3017
3192
|
});
|
|
3018
3193
|
|
|
3019
3194
|
// src/validators/claude/memory.ts
|
|
3020
|
-
import { existsSync as
|
|
3195
|
+
import { existsSync as existsSync17 } from "fs";
|
|
3021
3196
|
import { resolve as resolve10 } from "path";
|
|
3022
3197
|
var claudeMemoryValidator;
|
|
3023
3198
|
var init_memory = __esm(() => {
|
|
@@ -3027,7 +3202,7 @@ var init_memory = __esm(() => {
|
|
|
3027
3202
|
name: "Claude CLAUDE.md",
|
|
3028
3203
|
description: "Validates CLAUDE.md: non-empty, length recommendations, @path imports",
|
|
3029
3204
|
detect(dir) {
|
|
3030
|
-
return
|
|
3205
|
+
return existsSync17(resolve10(dir, "CLAUDE.md"));
|
|
3031
3206
|
},
|
|
3032
3207
|
async validate(dir, _opts) {
|
|
3033
3208
|
const errors = [];
|
|
@@ -3052,7 +3227,7 @@ var init_memory = __esm(() => {
|
|
|
3052
3227
|
while ((match = importRegex.exec(raw)) !== null) {
|
|
3053
3228
|
const importPath = match[1];
|
|
3054
3229
|
const resolvedImport = resolve10(dir, importPath);
|
|
3055
|
-
if (
|
|
3230
|
+
if (existsSync17(resolvedImport)) {
|
|
3056
3231
|
passes.push(`@import "${importPath}" exists`);
|
|
3057
3232
|
} else {
|
|
3058
3233
|
warnings.push(`@import "${importPath}" \u2014 file not found at ${resolvedImport}`);
|
|
@@ -3112,7 +3287,7 @@ var init_validators = __esm(() => {
|
|
|
3112
3287
|
// src/core/remote.ts
|
|
3113
3288
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
3114
3289
|
import { mkdtempSync, rmSync } from "fs";
|
|
3115
|
-
import { join as
|
|
3290
|
+
import { join as join13 } from "path";
|
|
3116
3291
|
import { tmpdir } from "os";
|
|
3117
3292
|
function parseRemoteUrl(input) {
|
|
3118
3293
|
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) {
|
|
@@ -3149,7 +3324,7 @@ function isGhAvailable() {
|
|
|
3149
3324
|
return ghAvailable;
|
|
3150
3325
|
}
|
|
3151
3326
|
async function cloneToTemp(parsed) {
|
|
3152
|
-
const tmpDir = mkdtempSync(
|
|
3327
|
+
const tmpDir = mkdtempSync(join13(tmpdir(), "dora-"));
|
|
3153
3328
|
const cleanup = () => {
|
|
3154
3329
|
try {
|
|
3155
3330
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
@@ -3197,15 +3372,15 @@ var exports_validate_top = {};
|
|
|
3197
3372
|
__export(exports_validate_top, {
|
|
3198
3373
|
default: () => validate_top_default
|
|
3199
3374
|
});
|
|
3200
|
-
import { existsSync as
|
|
3375
|
+
import { existsSync as existsSync19 } from "fs";
|
|
3201
3376
|
import { resolve as resolve11 } from "path";
|
|
3202
|
-
var
|
|
3377
|
+
var import_picocolors11, validate_top_default;
|
|
3203
3378
|
var init_validate_top = __esm(() => {
|
|
3204
3379
|
init_dist();
|
|
3205
3380
|
init_out();
|
|
3206
3381
|
init_validators();
|
|
3207
3382
|
init_remote();
|
|
3208
|
-
|
|
3383
|
+
import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
3209
3384
|
validate_top_default = defineCommand({
|
|
3210
3385
|
meta: {
|
|
3211
3386
|
name: "validate",
|
|
@@ -3245,7 +3420,7 @@ var init_validate_top = __esm(() => {
|
|
|
3245
3420
|
let cleanup;
|
|
3246
3421
|
if (remote) {
|
|
3247
3422
|
ui.info(`
|
|
3248
|
-
Cloning ${
|
|
3423
|
+
Cloning ${import_picocolors11.default.dim(args.path)}...`);
|
|
3249
3424
|
try {
|
|
3250
3425
|
const result = await cloneToTemp(remote);
|
|
3251
3426
|
fullPath = remote.subpath ? resolve11(result.dir, remote.subpath) : result.dir;
|
|
@@ -3255,14 +3430,14 @@ var init_validate_top = __esm(() => {
|
|
|
3255
3430
|
ui.fail(msg);
|
|
3256
3431
|
process.exit(1);
|
|
3257
3432
|
}
|
|
3258
|
-
if (!
|
|
3433
|
+
if (!existsSync19(fullPath)) {
|
|
3259
3434
|
cleanup();
|
|
3260
3435
|
ui.fail(`Subdirectory not found in repo: ${remote.subpath}`);
|
|
3261
3436
|
process.exit(1);
|
|
3262
3437
|
}
|
|
3263
3438
|
} else {
|
|
3264
3439
|
fullPath = resolve11(args.path);
|
|
3265
|
-
if (!
|
|
3440
|
+
if (!existsSync19(fullPath)) {
|
|
3266
3441
|
ui.fail(`Path not found: ${args.path}
|
|
3267
3442
|
|
|
3268
3443
|
Check that the path is correct and the directory exists.`);
|
|
@@ -3293,13 +3468,13 @@ Check that the path is correct and the directory exists.`);
|
|
|
3293
3468
|
` + `Available providers:
|
|
3294
3469
|
` + providers.map((p) => {
|
|
3295
3470
|
const pvs = validators.filter((v) => v.provider === p);
|
|
3296
|
-
return ` ${
|
|
3297
|
-
` + pvs.map((v) => ` \u2022 ${
|
|
3471
|
+
return ` ${import_picocolors11.default.bold(p)}
|
|
3472
|
+
` + pvs.map((v) => ` \u2022 ${import_picocolors11.default.dim(v.id)} \u2014 ${v.description}`).join(`
|
|
3298
3473
|
`);
|
|
3299
3474
|
}).join(`
|
|
3300
3475
|
`) + `
|
|
3301
3476
|
|
|
3302
|
-
Use ${
|
|
3477
|
+
Use ${import_picocolors11.default.dim("--for <provider>")} or ${import_picocolors11.default.dim("--for <provider:type>")} to target explicitly.`);
|
|
3303
3478
|
process.exit(1);
|
|
3304
3479
|
}
|
|
3305
3480
|
const allResults = [];
|
|
@@ -3320,7 +3495,7 @@ Use ${import_picocolors10.default.dim("--for <provider>")} or ${import_picocolor
|
|
|
3320
3495
|
} else {
|
|
3321
3496
|
for (const { id, name, result } of allResults) {
|
|
3322
3497
|
ui.write(`
|
|
3323
|
-
${
|
|
3498
|
+
${import_picocolors11.default.bold("dora validate")} \u2014 ${import_picocolors11.default.white(name)} ${import_picocolors11.default.dim(`(${id})`)}
|
|
3324
3499
|
`);
|
|
3325
3500
|
ui.info(` Path: ${args.path}
|
|
3326
3501
|
`);
|
|
@@ -3335,7 +3510,7 @@ Use ${import_picocolors10.default.dim("--for <provider>")} or ${import_picocolor
|
|
|
3335
3510
|
}
|
|
3336
3511
|
if (result.errors.length === 0 && result.warnings.length === 0) {
|
|
3337
3512
|
ui.write(`
|
|
3338
|
-
${
|
|
3513
|
+
${import_picocolors11.default.green("\u2713")} ${import_picocolors11.default.white("All checks passed.")}
|
|
3339
3514
|
`);
|
|
3340
3515
|
} else {
|
|
3341
3516
|
ui.info(`
|
|
@@ -3357,16 +3532,16 @@ var exports_init2 = {};
|
|
|
3357
3532
|
__export(exports_init2, {
|
|
3358
3533
|
default: () => init_default2
|
|
3359
3534
|
});
|
|
3360
|
-
import { basename as basename2, join as
|
|
3535
|
+
import { basename as basename2, join as join14 } from "path";
|
|
3361
3536
|
var {spawnSync: spawnSync5 } = globalThis.Bun;
|
|
3362
|
-
var
|
|
3537
|
+
var import_picocolors12, init_default2;
|
|
3363
3538
|
var init_init2 = __esm(() => {
|
|
3364
3539
|
init_dist();
|
|
3365
3540
|
init_out();
|
|
3366
3541
|
init_journal_config();
|
|
3367
3542
|
init_journal_remote();
|
|
3368
3543
|
init_prompt();
|
|
3369
|
-
|
|
3544
|
+
import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
3370
3545
|
init_default2 = defineCommand({
|
|
3371
3546
|
meta: {
|
|
3372
3547
|
name: "init",
|
|
@@ -3393,17 +3568,17 @@ var init_init2 = __esm(() => {
|
|
|
3393
3568
|
ui.heading("dora init \u2014 Set up doraval, your journal, and the coding agent dora should use on the fly");
|
|
3394
3569
|
const ghCheck = ensureGhCli();
|
|
3395
3570
|
if (!ghCheck.ok) {
|
|
3396
|
-
ui.write(` ${
|
|
3571
|
+
ui.write(` ${import_picocolors12.default.red("\u2717")} ${import_picocolors12.default.white("The GitHub CLI (")}${import_picocolors12.default.bold("gh")}${import_picocolors12.default.white(") is not installed.")}
|
|
3397
3572
|
`);
|
|
3398
|
-
ui.info(` doraval uses ${
|
|
3573
|
+
ui.info(` doraval uses ${import_picocolors12.default.bold("gh")} to fetch and sync journal files with GitHub.
|
|
3399
3574
|
`);
|
|
3400
3575
|
ui.info(` Install it:
|
|
3401
3576
|
`);
|
|
3402
|
-
ui.info(` macOS: ${
|
|
3403
|
-
ui.info(` Linux: ${
|
|
3404
|
-
ui.info(` Windows: ${
|
|
3577
|
+
ui.info(` macOS: ${import_picocolors12.default.dim("brew install gh")}`);
|
|
3578
|
+
ui.info(` Linux: ${import_picocolors12.default.dim("https://github.com/cli/cli/blob/trunk/docs/install_linux.md")}`);
|
|
3579
|
+
ui.info(` Windows: ${import_picocolors12.default.dim("winget install --id GitHub.cli")}
|
|
3405
3580
|
`);
|
|
3406
|
-
ui.info(` Then authenticate: ${
|
|
3581
|
+
ui.info(` Then authenticate: ${import_picocolors12.default.dim("gh auth login")}
|
|
3407
3582
|
`);
|
|
3408
3583
|
process.exit(1);
|
|
3409
3584
|
}
|
|
@@ -3416,28 +3591,28 @@ var init_init2 = __esm(() => {
|
|
|
3416
3591
|
if (gitOwner) {
|
|
3417
3592
|
defaultRepo = `${gitOwner}/${gitOwner}.md`;
|
|
3418
3593
|
if (ghLogin && ghLogin !== gitOwner) {
|
|
3419
|
-
sourceNote = ` ${
|
|
3594
|
+
sourceNote = ` ${import_picocolors12.default.dim("(from git remote; your active gh account is " + ghLogin + ")")}
|
|
3420
3595
|
`;
|
|
3421
3596
|
} else {
|
|
3422
|
-
sourceNote = ` ${
|
|
3597
|
+
sourceNote = ` ${import_picocolors12.default.dim("(from git remote)")}
|
|
3423
3598
|
`;
|
|
3424
3599
|
}
|
|
3425
3600
|
} else if (ghLogin) {
|
|
3426
3601
|
defaultRepo = `${ghLogin}/${ghLogin}.md`;
|
|
3427
|
-
sourceNote = ` ${
|
|
3602
|
+
sourceNote = ` ${import_picocolors12.default.dim("(from your active gh account)")}
|
|
3428
3603
|
`;
|
|
3429
3604
|
} else {
|
|
3430
|
-
ui.warn(`Not logged in to GitHub. Run ${
|
|
3605
|
+
ui.warn(`Not logged in to GitHub. Run ${import_picocolors12.default.dim("gh auth login")} first.
|
|
3431
3606
|
`);
|
|
3432
3607
|
process.exit(1);
|
|
3433
3608
|
}
|
|
3434
3609
|
const existingConfig = await readConfig();
|
|
3435
3610
|
if (existingConfig?.journal.repo) {
|
|
3436
3611
|
defaultRepo = existingConfig.journal.repo;
|
|
3437
|
-
sourceNote = ` ${
|
|
3612
|
+
sourceNote = ` ${import_picocolors12.default.dim("(from your previous journal setup)")}
|
|
3438
3613
|
`;
|
|
3439
3614
|
}
|
|
3440
|
-
ui.info(` Journal repo ${
|
|
3615
|
+
ui.info(` Journal repo ${import_picocolors12.default.dim("(owner/name)")}`);
|
|
3441
3616
|
if (sourceNote)
|
|
3442
3617
|
ui.write(sourceNote);
|
|
3443
3618
|
repo = prompt(" >", defaultRepo);
|
|
@@ -3449,11 +3624,11 @@ var init_init2 = __esm(() => {
|
|
|
3449
3624
|
}
|
|
3450
3625
|
project = sanitizeProjectName(project);
|
|
3451
3626
|
if (!repoExists(repo)) {
|
|
3452
|
-
ui.write(` ${
|
|
3627
|
+
ui.write(` ${import_picocolors12.default.red("\u2717")} ${import_picocolors12.default.white("Repository")} ${import_picocolors12.default.bold(repo)} ${import_picocolors12.default.white("not found on GitHub.")}
|
|
3453
3628
|
`);
|
|
3454
3629
|
ui.info(` Create it first:
|
|
3455
3630
|
`);
|
|
3456
|
-
ui.info(` ${
|
|
3631
|
+
ui.info(` ${import_picocolors12.default.dim(`gh repo create ${repo} --private --description "Personal journal for agent decisions"`)}
|
|
3457
3632
|
`);
|
|
3458
3633
|
process.exit(1);
|
|
3459
3634
|
}
|
|
@@ -3461,16 +3636,16 @@ var init_init2 = __esm(() => {
|
|
|
3461
3636
|
const alreadyRegistered = existing?.journal.projects[project];
|
|
3462
3637
|
const isRefresh = alreadyRegistered && args.refresh;
|
|
3463
3638
|
if (alreadyRegistered && !isRefresh) {
|
|
3464
|
-
ui.write(` ${
|
|
3639
|
+
ui.write(` ${import_picocolors12.default.yellow("\u26A0")} ${import_picocolors12.default.white("Project")} ${import_picocolors12.default.bold(project)} ${import_picocolors12.default.white("is already registered.")}
|
|
3465
3640
|
`);
|
|
3466
3641
|
ui.info(` Repo: ${existing.journal.repo}
|
|
3467
3642
|
`);
|
|
3468
|
-
ui.info(` To refresh journal files, use ${
|
|
3643
|
+
ui.info(` To refresh journal files, use ${import_picocolors12.default.dim("dora journal update")} (or ${import_picocolors12.default.dim("dora init --refresh")}).
|
|
3469
3644
|
`);
|
|
3470
3645
|
}
|
|
3471
3646
|
const journalsDir = getJournalsDir();
|
|
3472
3647
|
const remotePath = `projects/${project}.md`;
|
|
3473
|
-
const localPath =
|
|
3648
|
+
const localPath = join14(journalsDir, `${project}.md`);
|
|
3474
3649
|
const effectiveRepo = isRefresh && !args.repo ? existing.journal.repo : repo;
|
|
3475
3650
|
const config = existing ?? {
|
|
3476
3651
|
journal: { repo: effectiveRepo, projects: {} }
|
|
@@ -3481,9 +3656,9 @@ var init_init2 = __esm(() => {
|
|
|
3481
3656
|
local_path: localPath
|
|
3482
3657
|
};
|
|
3483
3658
|
ensureDoravalDirs();
|
|
3484
|
-
ui.write(` ${
|
|
3659
|
+
ui.write(` ${import_picocolors12.default.dim(import_picocolors12.default.gray("Fetching journal files from"))} ${import_picocolors12.default.gray(effectiveRepo)}${import_picocolors12.default.dim(import_picocolors12.default.gray("..."))}
|
|
3485
3660
|
`);
|
|
3486
|
-
const globalDest =
|
|
3661
|
+
const globalDest = join14(journalsDir, "global.md");
|
|
3487
3662
|
const refreshGlobalRes = await refreshLocalJournalFile(effectiveRepo, "global.md", globalDest);
|
|
3488
3663
|
let wroteGlobal;
|
|
3489
3664
|
if (!refreshGlobalRes.ok) {
|
|
@@ -3500,7 +3675,7 @@ var init_init2 = __esm(() => {
|
|
|
3500
3675
|
if (wroteGlobal) {
|
|
3501
3676
|
ui.success("global.md");
|
|
3502
3677
|
} else {
|
|
3503
|
-
ui.write(` ${
|
|
3678
|
+
ui.write(` ${import_picocolors12.default.dim("\xB7")} global.md ${import_picocolors12.default.dim("(not found \u2014 will be created on first sync)")}`);
|
|
3504
3679
|
await Bun.write(globalDest, `# Global Journal
|
|
3505
3680
|
|
|
3506
3681
|
Cross-project principles.
|
|
@@ -3522,7 +3697,7 @@ Cross-project principles.
|
|
|
3522
3697
|
if (wroteProject) {
|
|
3523
3698
|
ui.success(remotePath);
|
|
3524
3699
|
} else {
|
|
3525
|
-
ui.write(` ${
|
|
3700
|
+
ui.write(` ${import_picocolors12.default.dim("\xB7")} ${remotePath} ${import_picocolors12.default.dim("(not found \u2014 will be created on first sync)")}`);
|
|
3526
3701
|
await Bun.write(localPath, `# ${project} Journal
|
|
3527
3702
|
|
|
3528
3703
|
Project-specific decisions.
|
|
@@ -3530,13 +3705,13 @@ Project-specific decisions.
|
|
|
3530
3705
|
}
|
|
3531
3706
|
await writeConfig(config);
|
|
3532
3707
|
ui.write(`
|
|
3533
|
-
${
|
|
3708
|
+
${import_picocolors12.default.green("\u2713")} ${import_picocolors12.default.white("Journal ready for project")} ${import_picocolors12.default.bold(import_picocolors12.default.white(project))}.
|
|
3534
3709
|
`);
|
|
3535
3710
|
const existingAgent = (await readConfig())?.agent;
|
|
3536
3711
|
if (existingAgent?.command) {
|
|
3537
|
-
ui.write(` ${
|
|
3712
|
+
ui.write(` ${import_picocolors12.default.bold(import_picocolors12.default.white("Coding agent (already configured)"))}
|
|
3538
3713
|
`);
|
|
3539
|
-
ui.write(` Current: ${
|
|
3714
|
+
ui.write(` Current: ${import_picocolors12.default.dim(import_picocolors12.default.gray(existingAgent.command))} template: ${import_picocolors12.default.dim(import_picocolors12.default.gray(existingAgent.prompt_template || "(default)"))}
|
|
3540
3715
|
`);
|
|
3541
3716
|
const change = prompt(" Reconfigure / change the coding agent for on-the-fly enrichment? (y/N)", "n");
|
|
3542
3717
|
if (!/^y/i.test(String(change))) {
|
|
@@ -3546,16 +3721,16 @@ Project-specific decisions.
|
|
|
3546
3721
|
if (existingAgent)
|
|
3547
3722
|
cfg.agent = existingAgent;
|
|
3548
3723
|
await writeConfig(cfg);
|
|
3549
|
-
ui.write(` ${
|
|
3724
|
+
ui.write(` ${import_picocolors12.default.green("\u2713")} ${import_picocolors12.default.white("Try:")} ${import_picocolors12.default.dim(import_picocolors12.default.gray('dora journal add "short decision"'))}
|
|
3550
3725
|
`);
|
|
3551
3726
|
process.exit(0);
|
|
3552
3727
|
return;
|
|
3553
3728
|
}
|
|
3554
3729
|
ui.blank();
|
|
3555
3730
|
} else {
|
|
3556
|
-
ui.write(` ${
|
|
3731
|
+
ui.write(` ${import_picocolors12.default.bold(import_picocolors12.default.white("Coding agent for journal add"))}
|
|
3557
3732
|
`);
|
|
3558
|
-
ui.info(` When configured, ${
|
|
3733
|
+
ui.info(` When configured, ${import_picocolors12.default.dim(import_picocolors12.default.gray('dora journal add ".."'))} will use your agent to enrich entries with tags and rationale automatically.
|
|
3559
3734
|
`);
|
|
3560
3735
|
}
|
|
3561
3736
|
const common = [
|
|
@@ -3574,7 +3749,7 @@ Project-specific decisions.
|
|
|
3574
3749
|
}
|
|
3575
3750
|
}
|
|
3576
3751
|
let agentCmd = detected || "claude";
|
|
3577
|
-
ui.write(` Detected / default agent command: ${
|
|
3752
|
+
ui.write(` Detected / default agent command: ${import_picocolors12.default.dim(import_picocolors12.default.gray(agentCmd))}`);
|
|
3578
3753
|
agentCmd = prompt(" Agent command (the binary you run for prompts)", agentCmd);
|
|
3579
3754
|
let template = detected ? common.find((c) => c.name === detected)?.template || '-p "{{prompt}}" --output-format json' : '-p "{{prompt}}" --output-format json';
|
|
3580
3755
|
ui.info(` Prompt template (use {{prompt}} placeholder):`);
|
|
@@ -3586,11 +3761,11 @@ Project-specific decisions.
|
|
|
3586
3761
|
};
|
|
3587
3762
|
await writeConfig(finalConfig);
|
|
3588
3763
|
ui.write(`
|
|
3589
|
-
${
|
|
3764
|
+
${import_picocolors12.default.green("\u2713")} ${import_picocolors12.default.white("Agent configured.")}
|
|
3590
3765
|
`);
|
|
3591
|
-
ui.info(` Re-run ${
|
|
3766
|
+
ui.info(` Re-run ${import_picocolors12.default.dim(import_picocolors12.default.gray("dora init"))} anytime to change it.
|
|
3592
3767
|
`);
|
|
3593
|
-
ui.info(` Next: ${
|
|
3768
|
+
ui.info(` Next: ${import_picocolors12.default.dim(import_picocolors12.default.gray('dora journal add ".."'))}, ${import_picocolors12.default.dim(import_picocolors12.default.gray("dora journal list"))}, or ${import_picocolors12.default.dim(import_picocolors12.default.gray("dora journal update"))}.
|
|
3594
3769
|
`);
|
|
3595
3770
|
process.exit(0);
|
|
3596
3771
|
}
|
|
@@ -3602,7 +3777,7 @@ init_dist();
|
|
|
3602
3777
|
// package.json
|
|
3603
3778
|
var package_default = {
|
|
3604
3779
|
name: "@hacksmith/doraval",
|
|
3605
|
-
version: "0.2.
|
|
3780
|
+
version: "0.2.21",
|
|
3606
3781
|
author: "Saif",
|
|
3607
3782
|
repository: {
|
|
3608
3783
|
type: "git",
|
|
@@ -3663,7 +3838,7 @@ var package_default = {
|
|
|
3663
3838
|
};
|
|
3664
3839
|
|
|
3665
3840
|
// src/cli/index.ts
|
|
3666
|
-
var
|
|
3841
|
+
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
3667
3842
|
var skill = defineCommand({
|
|
3668
3843
|
meta: {
|
|
3669
3844
|
name: "skill",
|
|
@@ -3694,6 +3869,18 @@ var journal = defineCommand({
|
|
|
3694
3869
|
showUsage(journal);
|
|
3695
3870
|
}
|
|
3696
3871
|
});
|
|
3872
|
+
var claude = defineCommand({
|
|
3873
|
+
meta: {
|
|
3874
|
+
name: "claude",
|
|
3875
|
+
description: "Claude Code-specific commands (packaging, scaffolding, distribution)"
|
|
3876
|
+
},
|
|
3877
|
+
subCommands: {
|
|
3878
|
+
new: () => Promise.resolve().then(() => (init_new(), exports_new)).then((m) => m.default)
|
|
3879
|
+
},
|
|
3880
|
+
run() {
|
|
3881
|
+
showUsage(claude);
|
|
3882
|
+
}
|
|
3883
|
+
});
|
|
3697
3884
|
var doraemonArt = `
|
|
3698
3885
|
\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2880\u28E0\u28E4\u28F4\u28F6\u28F6\u28F6\u28F6\u28F6\u2836\u28F6\u28E4\u28E4\u28C0\u2800\u2800\u2800\u2800\u2800\u2800
|
|
3699
3886
|
\u2800\u2800\u2800\u2800\u2800\u2800\u2800\u2880\u28E4\u28FE\u28FF\u28FF\u28FF\u2801\u2800\u2880\u2808\u28BF\u2880\u28C0\u2800\u2839\u28FF\u28FF\u28FF\u28E6\u28C4\u2800\u2800\u2800
|
|
@@ -3716,11 +3903,12 @@ var main = defineCommand({
|
|
|
3716
3903
|
validate: () => Promise.resolve().then(() => (init_validate_top(), exports_validate_top)).then((m) => m.default),
|
|
3717
3904
|
init: () => Promise.resolve().then(() => (init_init2(), exports_init2)).then((m) => m.default),
|
|
3718
3905
|
skill: () => Promise.resolve(skill),
|
|
3719
|
-
journal: () => Promise.resolve(journal)
|
|
3906
|
+
journal: () => Promise.resolve(journal),
|
|
3907
|
+
claude: () => Promise.resolve(claude)
|
|
3720
3908
|
},
|
|
3721
3909
|
run() {
|
|
3722
3910
|
console.log(`
|
|
3723
|
-
` +
|
|
3911
|
+
` + import_picocolors13.default.blue(doraemonArt) + `
|
|
3724
3912
|
`);
|
|
3725
3913
|
showUsage(main);
|
|
3726
3914
|
}
|