dotmd-cli 0.78.0 → 0.79.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/README.md +66 -63
- package/assets/opencode/plugin.js +11 -6
- package/bin/dotmd.mjs +272 -285
- package/package.json +2 -2
- package/scripts/postinstall.mjs +4 -4
- package/src/atomic-mutation.mjs +1 -1
- package/src/baton.mjs +7 -7
- package/src/check-collapse.mjs +5 -5
- package/src/claude-commands.mjs +6 -2
- package/src/commands.mjs +4 -4
- package/src/config.mjs +2 -2
- package/src/deps.mjs +1 -1
- package/src/doctor.mjs +17 -17
- package/src/fix-membership.mjs +4 -2
- package/src/frontmatter-fix.mjs +1 -1
- package/src/git.mjs +1 -1
- package/src/glossary.mjs +3 -3
- package/src/graph.mjs +1 -1
- package/src/guard.mjs +8 -8
- package/src/health.mjs +2 -2
- package/src/hints.mjs +7 -7
- package/src/host-integration.mjs +41 -22
- package/src/hub-membership.mjs +1 -1
- package/src/hud.mjs +14 -14
- package/src/index-file.mjs +2 -2
- package/src/init.mjs +24 -24
- package/src/install.mjs +4 -4
- package/src/journal.mjs +40 -7
- package/src/lifecycle.mjs +17 -17
- package/src/lint.mjs +1 -1
- package/src/migrate-prompts.mjs +1 -1
- package/src/migrate-template.mjs +2 -2
- package/src/migrate.mjs +1 -1
- package/src/misuse-read.mjs +4 -5
- package/src/modules.mjs +3 -3
- package/src/new.mjs +11 -11
- package/src/output-identity.mjs +7 -2
- package/src/pickup-card.mjs +2 -2
- package/src/pickup.mjs +2 -2
- package/src/prompts.mjs +12 -12
- package/src/query.mjs +9 -9
- package/src/rename.mjs +2 -2
- package/src/render.mjs +20 -20
- package/src/roadmap.mjs +5 -5
- package/src/runlist.mjs +11 -11
- package/src/ship.mjs +2 -2
- package/src/skill-drift.mjs +19 -6
- package/src/statuses.mjs +16 -16
- package/src/summary.mjs +1 -1
- package/src/surfaces.mjs +1 -1
- package/src/sync-status.mjs +4 -4
- package/src/update.mjs +11 -11
- package/src/validate.mjs +9 -9
- package/src/watch.mjs +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# runlist
|
|
2
2
|
|
|
3
3
|
CLI for managing Markdown documents with YAML frontmatter.
|
|
4
4
|
|
|
5
|
-
dotmd indexes, queries, validates, graphs, exports, and lifecycle-manages plans,
|
|
5
|
+
runlist (formerly dotmd) indexes, queries, validates, graphs, exports, and lifecycle-manages plans,
|
|
6
6
|
ADRs, RFCs, design docs, and other structured Markdown. It is built for
|
|
7
7
|
AI-assisted development workflows where documents need to remain current and
|
|
8
8
|
safe to mutate.
|
|
@@ -22,7 +22,9 @@ npx dotmd-cli init # try it without installing
|
|
|
22
22
|
|
|
23
23
|
`runlist` is the canonical executable, `rl` is its short convenience alias, and
|
|
24
24
|
`dotmd` remains supported during the compatibility window. All three invoke the
|
|
25
|
-
same CLI
|
|
25
|
+
same CLI. The package is still published as `dotmd-cli`, and the Claude Code
|
|
26
|
+
plugin is still `dotmd@dotmd`; those names change in a later release. Legacy
|
|
27
|
+
`dotmd.config.*` files, `DOTMD_*` variables and `.dotmd/` state keep working.
|
|
26
28
|
|
|
27
29
|
Maintainer release automation is POSIX-only because it uses Bash and POSIX
|
|
28
30
|
command-line tools. The published Node.js CLI remains cross-platform.
|
|
@@ -33,19 +35,19 @@ The CLI alone gives an agent no orientation and no session identity. Install the
|
|
|
33
35
|
integration for whichever host you run:
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
runlist install # what's installed for each host
|
|
39
|
+
runlist install claude # Claude Code plugin (marketplace + plugin)
|
|
40
|
+
runlist install opencode # OpenCode plugin (one auto-discovered file)
|
|
41
|
+
runlist doctor --session # what identity runlist sees here, and from where
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
Both are one-time and global; `
|
|
44
|
+
Both are one-time and global; `runlist update` keeps them in step with the CLI.
|
|
43
45
|
Codex needs no install for identity: it exports `CODEX_THREAD_ID` to every tool
|
|
44
|
-
shell, and
|
|
46
|
+
shell, and runlist reads it as a per-session identity automatically.
|
|
45
47
|
|
|
46
48
|
### Claude Code Plugin
|
|
47
49
|
|
|
48
|
-
`
|
|
50
|
+
`runlist install claude` runs the two steps below for you. From inside a session:
|
|
49
51
|
|
|
50
52
|
```text
|
|
51
53
|
/plugin marketplace add reowens/dotmd
|
|
@@ -58,32 +60,33 @@ guard, the canonical workflow skill, and `/plans`, `/docs`, `/prompts`, and
|
|
|
58
60
|
|
|
59
61
|
### OpenCode Plugin
|
|
60
62
|
|
|
61
|
-
`
|
|
63
|
+
`runlist install opencode` writes one plugin file into OpenCode's global config
|
|
62
64
|
directory, where OpenCode auto-discovers it — no `opencode.json` edit. It
|
|
63
65
|
supplies the two things the CLI cannot get on its own:
|
|
64
66
|
|
|
65
67
|
- **Per-session plan ownership.** OpenCode exports no session id to a tool
|
|
66
|
-
shell. Without the plugin,
|
|
68
|
+
shell. Without the plugin, runlist falls back to `OPENCODE_PID`, which names the
|
|
67
69
|
OpenCode *process* — so every session in one OpenCode instance shares an
|
|
68
70
|
identity and can release the others' in-session plans.
|
|
69
71
|
- **A session-start briefing**, the equivalent of Claude Code's SessionStart
|
|
70
72
|
hook. OpenCode's Claude Code compatibility covers skills and the system
|
|
71
|
-
prompt, not hooks, so nothing else runs `
|
|
73
|
+
prompt, not hooks, so nothing else runs `runlist hud`.
|
|
72
74
|
|
|
73
|
-
Restart OpenCode after installing. The file is version-stamped
|
|
74
|
-
|
|
75
|
+
Restart OpenCode after installing. The file is version-stamped (`runlist-generated:`, or
|
|
76
|
+
`dotmd-generated:` from older releases); a `dotmd.js` without either stamp is
|
|
77
|
+
treated as hand-authored and is never overwritten.
|
|
75
78
|
|
|
76
|
-
The plugin requires a global CLI install because its hooks resolve `dotmd` from
|
|
79
|
+
The plugin requires a global CLI install because its hooks resolve `runlist` (or `dotmd`) from
|
|
77
80
|
`PATH`. A project devDependency is useful for npm scripts but does not put the
|
|
78
81
|
CLI on the hook's `PATH`.
|
|
79
82
|
|
|
80
83
|
Keep the CLI and plugin aligned with:
|
|
81
84
|
|
|
82
85
|
```bash
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
runlist update
|
|
87
|
+
runlist update --check
|
|
88
|
+
runlist update --cli-only
|
|
89
|
+
runlist update --plugin-only
|
|
87
90
|
```
|
|
88
91
|
|
|
89
92
|
Restart Claude Code, or run `/reload-plugins`, after a plugin update.
|
|
@@ -91,29 +94,29 @@ Restart Claude Code, or run `/reload-plugins`, after a plugin update.
|
|
|
91
94
|
## Quick Start
|
|
92
95
|
|
|
93
96
|
```bash
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
runlist init # create config, docs/, and the generated index
|
|
98
|
+
runlist new plan auth-refresh # scaffold a typed document
|
|
99
|
+
runlist briefing # compact active-work orientation
|
|
100
|
+
runlist plans # live plan dashboard
|
|
101
|
+
runlist check # validate schema, references, and lifecycle shape
|
|
102
|
+
runlist doctor # preview repairs; add --apply to write
|
|
100
103
|
```
|
|
101
104
|
|
|
102
|
-
`
|
|
103
|
-
human/LLM briefing, while `
|
|
105
|
+
`runlist briefing` is the compact orientation view. `runlist context` is the fuller
|
|
106
|
+
human/LLM briefing, while `runlist agent-context` emits bounded structured JSON for
|
|
104
107
|
agent integrations.
|
|
105
108
|
|
|
106
109
|
## Core Workflow
|
|
107
110
|
|
|
108
111
|
```bash
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
runlist briefing
|
|
113
|
+
runlist use docs/plans/auth-refresh.md
|
|
114
|
+
runlist set awaiting docs/plans/auth-refresh.md --note "Need API owner decision"
|
|
115
|
+
runlist set active docs/plans/auth-refresh.md --note "Decision received"
|
|
116
|
+
runlist archive docs/plans/auth-refresh.md --note "Shipped and verified"
|
|
114
117
|
```
|
|
115
118
|
|
|
116
|
-
Use `
|
|
119
|
+
Use `runlist set <status> [<file>]` for lifecycle changes rather than editing a
|
|
117
120
|
`status:` line. It validates the status for the document type, updates history,
|
|
118
121
|
runs lifecycle hooks, repairs references after moves, and synchronizes the
|
|
119
122
|
index.
|
|
@@ -122,18 +125,18 @@ For unfinished session work, save the handoff and release the owned plan in one
|
|
|
122
125
|
operation:
|
|
123
126
|
|
|
124
127
|
```bash
|
|
125
|
-
|
|
128
|
+
runlist baton @/tmp/resume.md
|
|
126
129
|
```
|
|
127
130
|
|
|
128
131
|
Baton refuses when a handoff for the same work is already pending, so one piece
|
|
129
132
|
of work never has two resume prompts.
|
|
130
133
|
|
|
131
|
-
Saved prompts are local session state. Consume them with `
|
|
132
|
-
without consuming via `
|
|
133
|
-
its plan; `
|
|
134
|
+
Saved prompts are local session state. Consume them with `runlist use`; inspect
|
|
135
|
+
without consuming via `runlist prompts show`. Consuming a baton prompt also claims
|
|
136
|
+
its plan; `runlist use --no-claim` reads and archives it without starting the plan.
|
|
134
137
|
|
|
135
|
-
New plans are created `planned`; `
|
|
136
|
-
`
|
|
138
|
+
New plans are created `planned`; `runlist use` starts one, and
|
|
139
|
+
`runlist new plan <name> --status <status>` sets a different starting status.
|
|
137
140
|
|
|
138
141
|
## Document Format
|
|
139
142
|
|
|
@@ -160,11 +163,11 @@ related_docs:
|
|
|
160
163
|
|
|
161
164
|
`status` is the only universally required field. A `type` enables type-specific
|
|
162
165
|
statuses, validation, templates, and briefing behavior. Explicit frontmatter
|
|
163
|
-
wins, but
|
|
166
|
+
wins, but runlist can also derive titles, summaries, state, next steps, checklist
|
|
164
167
|
progress, and Markdown links from the body.
|
|
165
168
|
|
|
166
169
|
Use plural `modules:` and `surfaces:` arrays. The old singular keys remain
|
|
167
|
-
readable for compatibility and can be migrated with `
|
|
170
|
+
readable for compatibility and can be migrated with `runlist lint --fix`.
|
|
168
171
|
|
|
169
172
|
### Built-In Types
|
|
170
173
|
|
|
@@ -183,19 +186,19 @@ A sprint runlist is an ordered `runlist:` array on a hub plan. Scaffold a hub
|
|
|
183
186
|
and children together:
|
|
184
187
|
|
|
185
188
|
```bash
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
+
runlist new plan auth-revamp --runlist extract,rewrite,cleanup
|
|
190
|
+
runlist runlist auth-revamp
|
|
191
|
+
runlist runlist next auth-revamp
|
|
189
192
|
```
|
|
190
193
|
|
|
191
194
|
Mutate the structure through the CLI so the array, child `parent_plan` refs, and
|
|
192
195
|
body order list remain synchronized:
|
|
193
196
|
|
|
194
197
|
```bash
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
runlist runlist add auth-revamp docs/plans/existing-plan.md
|
|
199
|
+
runlist runlist add auth-revamp follow-up
|
|
200
|
+
runlist runlist reorder auth-revamp follow-up --before cleanup
|
|
201
|
+
runlist runlist remove auth-revamp extract --clear-parent
|
|
199
202
|
```
|
|
200
203
|
|
|
201
204
|
Archived children count as complete. Parked children (`blocked`, `partial`,
|
|
@@ -205,16 +208,16 @@ pickup but do not count as done.
|
|
|
205
208
|
For a larger prose-first domain map, create a coordination runlist:
|
|
206
209
|
|
|
207
210
|
```bash
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
runlist new plan platform-work --coordination
|
|
212
|
+
runlist runlists
|
|
210
213
|
```
|
|
211
214
|
|
|
212
215
|
For progress across several runlists, create a roadmap:
|
|
213
216
|
|
|
214
217
|
```bash
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
runlist new plan platform-roadmap --roadmap
|
|
219
|
+
runlist roadmap platform-roadmap
|
|
220
|
+
runlist roadmap platform-roadmap next
|
|
218
221
|
```
|
|
219
222
|
|
|
220
223
|
Roadmaps roll up progress recursively and choose the first startable plan across
|
|
@@ -236,17 +239,17 @@ counts so dashboards do not double-count their children.
|
|
|
236
239
|
The CLI is the source of truth for command syntax and options:
|
|
237
240
|
|
|
238
241
|
```bash
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
242
|
+
runlist --help
|
|
243
|
+
runlist help all
|
|
244
|
+
runlist help statuses
|
|
245
|
+
runlist <command> --help
|
|
243
246
|
```
|
|
244
247
|
|
|
245
248
|
Shell completion is generated from the same command registry:
|
|
246
249
|
|
|
247
250
|
```bash
|
|
248
|
-
eval "$(
|
|
249
|
-
eval "$(
|
|
251
|
+
eval "$(runlist completions bash)"
|
|
252
|
+
eval "$(runlist completions zsh)"
|
|
250
253
|
```
|
|
251
254
|
|
|
252
255
|
This README intentionally documents onboarding and concepts instead of
|
|
@@ -254,7 +257,7 @@ duplicating the complete command catalog.
|
|
|
254
257
|
|
|
255
258
|
## Configuration
|
|
256
259
|
|
|
257
|
-
Run `
|
|
260
|
+
Run `runlist init` to create `runlist.config.mjs` (a legacy `dotmd.config.mjs` is still read). A minimal typed configuration:
|
|
258
261
|
|
|
259
262
|
```js
|
|
260
263
|
export const root = 'docs';
|
|
@@ -280,12 +283,12 @@ export const types = {
|
|
|
280
283
|
|
|
281
284
|
Configuration supports multiple roots, custom types and templates, taxonomy,
|
|
282
285
|
reference fields, presets, rendering, lifecycle hooks, validation hooks, and
|
|
283
|
-
AI summarization hooks. See [`
|
|
286
|
+
AI summarization hooks. See [`runlist.config.example.mjs`](runlist.config.example.mjs)
|
|
284
287
|
for the complete annotated reference.
|
|
285
288
|
|
|
286
289
|
## Hooks
|
|
287
290
|
|
|
288
|
-
Functions exported from `
|
|
291
|
+
Functions exported from `runlist.config.mjs` are detected as hooks. They can add
|
|
289
292
|
validation, customize rendering and summaries, or react to lifecycle events.
|
|
290
293
|
Hooks receive the resolved config and command context; mutation hooks participate
|
|
291
294
|
in the command's dry-run and failure contracts.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// runlist's OpenCode integration. Installed by `runlist install opencode`, which
|
|
2
2
|
// copies this file (with a version banner prepended) to the OpenCode plugin
|
|
3
3
|
// directory, where OpenCode auto-discovers it — it globs
|
|
4
4
|
// `{plugin,plugins}/*.{ts,js}` under `.opencode/` and the global config dir, so
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
//
|
|
14
14
|
// 2. NO HOOK MAY THROW. OpenCode awaits hook callbacks inside the request it
|
|
15
15
|
// is serving; a rejected promise fails the user's chat turn. Every hook
|
|
16
|
-
// body is wrapped, and a failure degrades to "
|
|
16
|
+
// body is wrapped, and a failure degrades to "runlist does nothing here"
|
|
17
17
|
// rather than to a broken session.
|
|
18
18
|
//
|
|
19
19
|
// Runs under Bun inside the OpenCode process. Node builtins only, no deps.
|
|
@@ -46,6 +46,10 @@ function runCli(directory, args, input = null) {
|
|
|
46
46
|
cwd: directory,
|
|
47
47
|
timeout: PRIMER_TIMEOUT_MS,
|
|
48
48
|
windowsHide: true,
|
|
49
|
+
// Node refuses to execFile a `.cmd` without a shell (EINVAL since the
|
|
50
|
+
// 2024 batch-file fix), and npm installs the CLI on Windows as one.
|
|
51
|
+
// The arguments are fixed strings, never user input.
|
|
52
|
+
shell: process.platform === 'win32',
|
|
49
53
|
env: { ...process.env, NO_COLOR: '1' },
|
|
50
54
|
}, (error, stdout) => {
|
|
51
55
|
if (error?.code === 'ENOENT') attempt(index + 1);
|
|
@@ -60,7 +64,7 @@ function runCli(directory, args, input = null) {
|
|
|
60
64
|
});
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
// OpenCode runs no Claude Code hooks, so `
|
|
67
|
+
// OpenCode runs no Claude Code hooks, so `runlist guard` never sees its tool
|
|
64
68
|
// calls, and sessions opened pending prompts with the read tool, which prints a
|
|
65
69
|
// prompt without archiving it. The guard's answer for a prompt read is a
|
|
66
70
|
// warning, not a block, so it is applied after the call: the teaching text is
|
|
@@ -98,7 +102,7 @@ export default async function dotmdOpencodePlugin({ directory }) {
|
|
|
98
102
|
|
|
99
103
|
return {
|
|
100
104
|
// Ownership identity. OpenCode sets no session-id variable of its own, and
|
|
101
|
-
// `OPENCODE_PID` — what
|
|
105
|
+
// `OPENCODE_PID` — what runlist falls back to without this plugin — names the
|
|
102
106
|
// OpenCode *process*, so every session in one TUI shares it and can release
|
|
103
107
|
// the others' plans. This is the only place the real session id is
|
|
104
108
|
// available to a tool shell.
|
|
@@ -106,11 +110,12 @@ export default async function dotmdOpencodePlugin({ directory }) {
|
|
|
106
110
|
try {
|
|
107
111
|
if (input?.sessionID) {
|
|
108
112
|
output.env.RUNLIST_SESSION_ID = `opencode:${input.sessionID}`;
|
|
113
|
+
// Legacy name, kept for an older CLI (before 0.77.0) still on PATH.
|
|
109
114
|
output.env.DOTMD_SESSION_ID = `opencode:${input.sessionID}`;
|
|
110
115
|
}
|
|
111
116
|
// The OpenCode server process hosts the session and outlives every tool
|
|
112
117
|
// shell, so it is the process whose liveness answers "is this claim's
|
|
113
|
-
// owner still there?" — `
|
|
118
|
+
// owner still there?" — `runlist doctor --claims` probes exactly this.
|
|
114
119
|
output.env.RUNLIST_SESSION_PID = String(process.pid);
|
|
115
120
|
output.env.DOTMD_SESSION_PID = String(process.pid);
|
|
116
121
|
} catch { /* never break a shell over this */ }
|
|
@@ -130,7 +135,7 @@ export default async function dotmdOpencodePlugin({ directory }) {
|
|
|
130
135
|
},
|
|
131
136
|
|
|
132
137
|
// Session priming — the equivalent of the SessionStart hook that runs
|
|
133
|
-
// `
|
|
138
|
+
// `runlist hud` under Claude Code. Silent outside a runlist repo (hud prints
|
|
134
139
|
// nothing and exits 0), so this is inert in unrelated projects.
|
|
135
140
|
'experimental.chat.system.transform': async (input, output) => {
|
|
136
141
|
try {
|