dotmd-cli 0.28.1 → 0.28.2

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/bin/dotmd.mjs CHANGED
@@ -571,12 +571,16 @@ Subcommands:
571
571
  list List pending prompts (default)
572
572
  next Consume the oldest pending prompt:
573
573
  print body to stdout, flip status to archived
574
- use <file> Consume a specific prompt (same as next, but
575
- targets <file> instead of picking oldest)
576
- archive <file> Archive a prompt without printing its body
574
+ use <file-or-slug> Consume a specific prompt (same as next, but
575
+ targets the named prompt instead of picking oldest)
576
+ archive <file-or-slug> Archive a prompt without printing its body
577
577
  new <slug> [body] Create a new prompt (alias for
578
578
  \`dotmd new prompt <slug> [body]\`)
579
579
 
580
+ \`<file-or-slug>\` accepts: an exact path (with or without .md), a bare
581
+ slug matching a prompt basename, or a unique substring of a prompt
582
+ path. Ambiguous substrings error with the candidate list.
583
+
580
584
  Default prompt statuses: pending, claimed, archived.
581
585
 
582
586
  Examples:
@@ -586,10 +590,11 @@ Examples:
586
590
  dotmd prompts --json # JSON output
587
591
 
588
592
  claude "$(dotmd prompts next)" # consume oldest pending + run claude
589
- claude "$(dotmd prompts use docs/prompts/foo.md)"
593
+ claude "$(dotmd prompts use resume-foo)" # by slug
594
+ claude "$(dotmd prompts use docs/prompts/foo.md)" # by path
590
595
 
591
596
  dotmd prompts next --dry-run # preview without consuming
592
- dotmd prompts archive docs/prompts/old.md
597
+ dotmd prompts archive old-thing
593
598
  dotmd prompts new my-prompt "Body text here"`,
594
599
 
595
600
  stale: `dotmd stale — list stale documents
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotmd-cli",
3
- "version": "0.28.1",
3
+ "version": "0.28.2",
4
4
  "description": "CLI for managing markdown documents with YAML frontmatter — index, query, validate, graph, export, Notion sync, AI summaries.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/prompts.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { readFileSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
2
3
  import { extractFrontmatter, parseSimpleFrontmatter } from './frontmatter.mjs';
3
4
  import { asString, toRepoPath, die, resolveDocPath } from './util.mjs';
4
5
  import { buildIndex } from './index.mjs';
@@ -74,11 +75,46 @@ function runPromptsNext(argv, config, opts = {}) {
74
75
  consumePrompt(head.abs, config, opts);
75
76
  }
76
77
 
78
+ // Resolve user input to a prompt path. Tries (in order): exact path,
79
+ // path + '.md', exact basename match across type: prompt docs, substring
80
+ // match across type: prompt docs. Returns the absolute path or dies with a
81
+ // helpful message (no match / ambiguous match).
82
+ function resolvePromptInput(input, config) {
83
+ const direct = resolveDocPath(input, config);
84
+ if (direct) return direct;
85
+
86
+ if (!input.endsWith('.md')) {
87
+ const withExt = resolveDocPath(input + '.md', config);
88
+ if (withExt) return withExt;
89
+ }
90
+
91
+ const index = buildIndex(config);
92
+ const prompts = index.docs.filter(d => d.type === 'prompt');
93
+ if (prompts.length === 0) die(`No prompts in the index.`);
94
+
95
+ const slug = input.replace(/\.md$/, '');
96
+
97
+ const byBasename = prompts.filter(d => path.basename(d.path, '.md') === slug);
98
+ if (byBasename.length === 1) return path.resolve(config.repoRoot, byBasename[0].path);
99
+ if (byBasename.length > 1) {
100
+ die(`Multiple prompts match "${input}" by basename:\n${byBasename.map(d => ' ' + d.path).join('\n')}`);
101
+ }
102
+
103
+ const bySubstring = prompts.filter(d =>
104
+ d.path.includes(slug) || path.basename(d.path).includes(slug),
105
+ );
106
+ if (bySubstring.length === 1) return path.resolve(config.repoRoot, bySubstring[0].path);
107
+ if (bySubstring.length > 1) {
108
+ die(`Multiple prompts match "${input}":\n${bySubstring.map(d => ' ' + d.path).join('\n')}`);
109
+ }
110
+
111
+ die(`No prompt found matching: ${input}`);
112
+ }
113
+
77
114
  function runPromptsUse(argv, config, opts = {}) {
78
115
  const input = argv.find(a => !a.startsWith('-'));
79
- if (!input) die('Usage: dotmd prompts use <file>');
80
- const filePath = resolveDocPath(input, config);
81
- if (!filePath) die(`File not found: ${input}`);
116
+ if (!input) die('Usage: dotmd prompts use <file-or-slug>');
117
+ const filePath = resolvePromptInput(input, config);
82
118
  consumePrompt(filePath, config, opts);
83
119
  }
84
120
 
@@ -113,9 +149,8 @@ function consumePrompt(filePath, config, opts) {
113
149
 
114
150
  function runPromptsArchive(argv, config, opts = {}) {
115
151
  const input = argv.find(a => !a.startsWith('-'));
116
- if (!input) die('Usage: dotmd prompts archive <file>');
117
- const filePath = resolveDocPath(input, config);
118
- if (!filePath) die(`File not found: ${input}`);
152
+ if (!input) die('Usage: dotmd prompts archive <file-or-slug>');
153
+ const filePath = resolvePromptInput(input, config);
119
154
 
120
155
  const raw = readFileSync(filePath, 'utf8');
121
156
  const { frontmatter } = extractFrontmatter(raw);