dotmd-cli 0.38.1 → 0.39.1
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/package.json +1 -1
- package/src/claude-commands.mjs +31 -8
- package/src/hud.mjs +16 -1
package/package.json
CHANGED
package/src/claude-commands.mjs
CHANGED
|
@@ -6,10 +6,29 @@ import { green, dim, yellow } from './color.mjs';
|
|
|
6
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
const pkg = JSON.parse(readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
|
8
8
|
const VERSION_MARKER = `<!-- dotmd-generated: ${pkg.version} -->`;
|
|
9
|
-
|
|
9
|
+
// Marker is no longer pinned to line 1 — it now lives below the YAML
|
|
10
|
+
// frontmatter that Claude Code surfaces as the slash command's description.
|
|
11
|
+
// The regex is intentionally non-anchored so getInstalledVersion finds it
|
|
12
|
+
// wherever it sits, and the marker string is specific enough that a false
|
|
13
|
+
// positive elsewhere in a user-edited file is not a realistic concern.
|
|
14
|
+
const VERSION_REGEX = /<!-- dotmd-generated: ([\d.]+) -->/;
|
|
15
|
+
|
|
16
|
+
// Trigger sentences surfaced by Claude Code's available-skills system reminder.
|
|
17
|
+
// Keep each ≤200 chars (well under the 1,536-char auto-load truncation limit)
|
|
18
|
+
// and front-load the "when to reach for it" cue so Claude can route to the
|
|
19
|
+
// right slash command without the user having to type the slash.
|
|
20
|
+
const SLASH_DESCRIPTIONS = {
|
|
21
|
+
plans: "dotmd-managed plan briefing for this repo. Use when the user asks what's on the plate, references a plan slug, queues work, or wants to pick up / release / archive a plan.",
|
|
22
|
+
docs: "dotmd-managed docs briefing for this repo. Use when the user asks to list, scaffold, query, validate, archive, or rename non-plan docs (reference docs, ADRs, RFCs, design notes), or asks how the dotmd doc lifecycle works here.",
|
|
23
|
+
baton: "Save a resume prompt for the held plan and release the lease — the minimum handoff. Use when the user says hand off / save a resume / wrap up, or when context is getting tight.",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function frontmatterFor(name) {
|
|
27
|
+
return ['---', `description: ${SLASH_DESCRIPTIONS[name]}`, '---'];
|
|
28
|
+
}
|
|
10
29
|
|
|
11
30
|
function generatePlansCommand(config) {
|
|
12
|
-
const lines = [VERSION_MARKER, ''];
|
|
31
|
+
const lines = [...frontmatterFor('plans'), VERSION_MARKER, ''];
|
|
13
32
|
lines.push('Run `dotmd context` to get the current plans briefing, then use it to orient yourself.');
|
|
14
33
|
lines.push('');
|
|
15
34
|
lines.push(`Plans are managed by **dotmd** (v${pkg.version}). Config at \`dotmd.config.mjs\`. Always use \`dotmd\` directly.`);
|
|
@@ -47,14 +66,18 @@ function generatePlansCommand(config) {
|
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
function generateBatonCommand() {
|
|
50
|
-
const lines = [VERSION_MARKER, ''];
|
|
51
|
-
lines.push('
|
|
69
|
+
const lines = [...frontmatterFor('baton'), VERSION_MARKER, ''];
|
|
70
|
+
lines.push('Wrap this session. Minimum required (two commands):');
|
|
71
|
+
lines.push('');
|
|
72
|
+
lines.push('1. **Save the resume prompt.** `dotmd new prompt resume-<plan-slug>` with a 10-20 line body via heredoc: the next concrete decision plus any gotchas. NOT a recap of the plan body. The saved prompt IS the handoff — never print it into chat for copy-paste.');
|
|
52
73
|
lines.push('');
|
|
53
|
-
lines.push('
|
|
74
|
+
lines.push('2. **Release the lease.** `dotmd release` — or `dotmd archive <file>` if the work is fully shipped (archive auto-releases).');
|
|
54
75
|
lines.push('');
|
|
55
|
-
lines.push('
|
|
76
|
+
lines.push('Optional, only when genuinely needed:');
|
|
77
|
+
lines.push('- Status really changed (paused / awaiting / partial / blocked): `dotmd status <file> <status>` BEFORE `dotmd release`.');
|
|
78
|
+
lines.push('- Plan dashboard text is misleading the user: edit `next_step:` in the plan frontmatter. Cosmetic — the next session reads the resume prompt, not the plan frontmatter.');
|
|
56
79
|
lines.push('');
|
|
57
|
-
lines.push('
|
|
80
|
+
lines.push('If you don\'t already know which plan you hold: `dotmd hud --json` and read `.owned`. Do NOT use `dotmd plans --status in-session` — that lists every session\'s holdings, not just yours.');
|
|
58
81
|
lines.push('');
|
|
59
82
|
lines.push('The next session\'s `dotmd hud` (SessionStart hook) surfaces the pending prompt automatically.');
|
|
60
83
|
lines.push('');
|
|
@@ -66,7 +89,7 @@ function generateDocsCommand(config) {
|
|
|
66
89
|
const roots = Array.isArray(config.raw?.root) ? config.raw.root : [config.raw?.root ?? 'docs'];
|
|
67
90
|
const rootCount = roots.length;
|
|
68
91
|
|
|
69
|
-
const lines = [VERSION_MARKER, ''];
|
|
92
|
+
const lines = [...frontmatterFor('docs'), VERSION_MARKER, ''];
|
|
70
93
|
lines.push(`All documentation in this repo is managed by **dotmd** (v${pkg.version}). Docs across ${rootCount} root${rootCount > 1 ? 's' : ''}: ${roots.join(', ')}. Config at \`dotmd.config.mjs\`.`);
|
|
71
94
|
lines.push('');
|
|
72
95
|
|
package/src/hud.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { readLeases, findStaleLeases, currentSessionId } from './lease.mjs';
|
|
4
4
|
import { extractFrontmatter, parseSimpleFrontmatter } from './frontmatter.mjs';
|
|
@@ -124,6 +124,21 @@ export function runHud(argv, config) {
|
|
|
124
124
|
lines.push(dim(`↻ slash commands refreshed (v${from} → v${to}): ${names}`));
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
// Teach-once primer for fresh installs. The first session that runs hud in
|
|
128
|
+
// a dotmd-managed repo gets one line explaining what dotmd is and how to
|
|
129
|
+
// hand off — without this, a clean repo emits nothing and Claude has no
|
|
130
|
+
// signal that dotmd is the prompt/handoff machinery here. Gated on a
|
|
131
|
+
// marker under .dotmd/ (already the per-repo state dir, already gitignored
|
|
132
|
+
// by `dotmd init`) so subsequent sessions stay silent.
|
|
133
|
+
const primerMarker = path.join(config.repoRoot, '.dotmd', 'primer-shown');
|
|
134
|
+
if (!existsSync(primerMarker)) {
|
|
135
|
+
lines.push(dim('dotmd: managing this repo\'s docs. Use `dotmd new prompt` for handoffs (never hand-write docs/prompts/*.md). `dotmd plans` shows the queue. `dotmd --help` for more.'));
|
|
136
|
+
try {
|
|
137
|
+
mkdirSync(path.dirname(primerMarker), { recursive: true });
|
|
138
|
+
writeFileSync(primerMarker, '');
|
|
139
|
+
} catch { /* best-effort — failed marker write just means the primer reprints next session */ }
|
|
140
|
+
}
|
|
141
|
+
|
|
127
142
|
if (lines.length === 0) return; // silent when clean
|
|
128
143
|
process.stdout.write(lines.join('\n') + '\n');
|
|
129
144
|
}
|