dotmd-cli 0.38.1 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/claude-commands.mjs +23 -4
- 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: "Wrap the current session cleanly: update the in-flight plan, save ONE resume prompt via 'dotmd new prompt', release the lease. 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,7 +66,7 @@ function generatePlansCommand(config) {
|
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
function generateBatonCommand() {
|
|
50
|
-
const lines = [VERSION_MARKER, ''];
|
|
69
|
+
const lines = [...frontmatterFor('baton'), VERSION_MARKER, ''];
|
|
51
70
|
lines.push('You are wrapping this session. Hand the baton cleanly to the next one.');
|
|
52
71
|
lines.push('');
|
|
53
72
|
lines.push('1. **Update the in-flight plan.** Find it via `dotmd plans --status in-session`. Edit its `current_state:` / `next_step:` frontmatter so they reflect where things actually stand. If status should change (shipped → archive, stuck on a human decision → awaiting, etc.), transition with `dotmd status <file> <status>` — or `dotmd archive <file>` if work is done.');
|
|
@@ -66,7 +85,7 @@ function generateDocsCommand(config) {
|
|
|
66
85
|
const roots = Array.isArray(config.raw?.root) ? config.raw.root : [config.raw?.root ?? 'docs'];
|
|
67
86
|
const rootCount = roots.length;
|
|
68
87
|
|
|
69
|
-
const lines = [VERSION_MARKER, ''];
|
|
88
|
+
const lines = [...frontmatterFor('docs'), VERSION_MARKER, ''];
|
|
70
89
|
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
90
|
lines.push('');
|
|
72
91
|
|
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
|
}
|