benjamin-docs 0.1.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/LICENSE +21 -0
- package/README.md +352 -0
- package/dist/src/anchors.d.ts +1 -0
- package/dist/src/anchors.js +50 -0
- package/dist/src/anchors.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +231 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/constants.d.ts +12 -0
- package/dist/src/constants.js +13 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/export.d.ts +1 -0
- package/dist/src/export.js +70 -0
- package/dist/src/export.js.map +1 -0
- package/dist/src/frontmatter.d.ts +3 -0
- package/dist/src/frontmatter.js +119 -0
- package/dist/src/frontmatter.js.map +1 -0
- package/dist/src/fsx.d.ts +14 -0
- package/dist/src/fsx.js +129 -0
- package/dist/src/fsx.js.map +1 -0
- package/dist/src/info.d.ts +3 -0
- package/dist/src/info.js +65 -0
- package/dist/src/info.js.map +1 -0
- package/dist/src/init.d.ts +12 -0
- package/dist/src/init.js +145 -0
- package/dist/src/init.js.map +1 -0
- package/dist/src/next.d.ts +2 -0
- package/dist/src/next.js +65 -0
- package/dist/src/next.js.map +1 -0
- package/dist/src/project-config.d.ts +6 -0
- package/dist/src/project-config.js +41 -0
- package/dist/src/project-config.js.map +1 -0
- package/dist/src/scopes.d.ts +1 -0
- package/dist/src/scopes.js +52 -0
- package/dist/src/scopes.js.map +1 -0
- package/dist/src/status.d.ts +1 -0
- package/dist/src/status.js +38 -0
- package/dist/src/status.js.map +1 -0
- package/dist/src/templates.d.ts +19 -0
- package/dist/src/templates.js +82 -0
- package/dist/src/templates.js.map +1 -0
- package/dist/src/types.d.ts +51 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/validate.d.ts +5 -0
- package/dist/src/validate.js +542 -0
- package/dist/src/validate.js.map +1 -0
- package/package.json +45 -0
- package/skills/benjamin-docs/SKILL.md +129 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 marty
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# benjamin-docs
|
|
2
|
+
|
|
3
|
+
Repo-local project memory for humans and AI agents.
|
|
4
|
+
|
|
5
|
+
`benjamin-docs` turns planning and build conversations into structured Markdown docs that live inside your project. It works before code exists, inside existing codebases, and for individual feature scopes.
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
Early MVP. The CLI is prepared for its first public `0.1.0` package release as `benjamin-docs`.
|
|
10
|
+
|
|
11
|
+
The current goal is to make the open-source repo useful, understandable, and safe to try before adding hosted publishing or SaaS features.
|
|
12
|
+
|
|
13
|
+
## Why It Exists
|
|
14
|
+
|
|
15
|
+
Long agent sessions create valuable project context: product decisions, rejected options, feature plans, user-facing notes, handoff context, and code references. That context is easy to lose.
|
|
16
|
+
|
|
17
|
+
`benjamin-docs` keeps that memory close to the work:
|
|
18
|
+
|
|
19
|
+
- human-readable Markdown in `benjamin-docs/`
|
|
20
|
+
- machine-readable metadata in `.benjamin-docs/`
|
|
21
|
+
- local validation before docs are shared or exported
|
|
22
|
+
- agent skill guidance so future sessions can update docs without drifting
|
|
23
|
+
|
|
24
|
+
## Try It From Any Chat
|
|
25
|
+
|
|
26
|
+
If a conversation already contains a useful project idea, ask your agent:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
Use benjamin-docs to create a project from this chat.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The agent should suggest a local folder like:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
~/Documents/Benjamin Docs/Atelier Edits
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
After you confirm, it creates:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
README.md
|
|
42
|
+
benjamin-docs/
|
|
43
|
+
.benjamin-docs/
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The top-level `README.md` explains the project in plain language. The `benjamin-docs/` folder captures the project brief, roadmap, open questions, and handoff notes. Nothing is uploaded by the CLI.
|
|
47
|
+
|
|
48
|
+
## For Non-Programmers
|
|
49
|
+
|
|
50
|
+
You can use `benjamin-docs` even if you are planning an app, product, service, or creative project before any code exists.
|
|
51
|
+
|
|
52
|
+
Think of it as a project notebook that your AI agent keeps inside your project folder. The agent does the writing; the CLI creates the folders, checks that the notes are valid, and gives the next prompt to use.
|
|
53
|
+
|
|
54
|
+
You need:
|
|
55
|
+
|
|
56
|
+
- a place on your computer where the agent can create a project folder, such as `~/Documents/Benjamin Docs/Project Name`
|
|
57
|
+
- an AI coding agent that can run terminal commands and edit files
|
|
58
|
+
- the `benjamin-docs` CLI installed with pnpm, or a local source checkout while developing
|
|
59
|
+
|
|
60
|
+
If all you have is the current chat, start by asking your agent:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
Use benjamin-docs to create a project from this chat.
|
|
64
|
+
Suggest ~/Documents/Benjamin Docs/<Project Name> as the folder,
|
|
65
|
+
initialize it as a planning-only project, write a simple top-level README.md,
|
|
66
|
+
then capture the current context in plain language.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
After that, ask:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
Show me the benjamin-docs project brief, roadmap, open questions,
|
|
73
|
+
and handoff. Explain what each file is for.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Nothing is uploaded or published by the CLI. The docs stay in your project folder unless you choose to share them.
|
|
77
|
+
|
|
78
|
+
## Create A Project From A Chat
|
|
79
|
+
|
|
80
|
+
This is the simplest first use case: you do not have a repo, codebase, or project folder yet. You only have a useful conversation.
|
|
81
|
+
|
|
82
|
+
Ask your agent:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
Use benjamin-docs to create a project from this chat.
|
|
86
|
+
Suggest ~/Documents/Benjamin Docs/<Project Name> unless I choose a different place.
|
|
87
|
+
Create the folder, initialize benjamin-docs there, add a simple README.md,
|
|
88
|
+
and turn this conversation into a project brief, roadmap, open questions,
|
|
89
|
+
and handoff.
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The agent should:
|
|
93
|
+
|
|
94
|
+
- infer a human-readable project name when the chat makes one obvious
|
|
95
|
+
- suggest `~/Documents/Benjamin Docs/<Project Name>` as the default location
|
|
96
|
+
- ask for confirmation before creating files
|
|
97
|
+
- summarize what it will capture in short bullets
|
|
98
|
+
- create the project folder
|
|
99
|
+
- run `benjamin-docs init --mode planning` inside that folder
|
|
100
|
+
- write a top-level `README.md` that explains what the project is and where to start
|
|
101
|
+
- update the Benjamin docs under `benjamin-docs/` from the chat context
|
|
102
|
+
- run `benjamin-docs validate`
|
|
103
|
+
- show you what was created and what is still uncertain
|
|
104
|
+
|
|
105
|
+
The CLI creates and validates the docs workspace. The agent turns the chat into useful project memory.
|
|
106
|
+
|
|
107
|
+
## Install The CLI
|
|
108
|
+
|
|
109
|
+
Install globally with pnpm:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pnpm add -g benjamin-docs
|
|
113
|
+
benjamin-docs introduce
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Initialize docs in the current project folder:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
benjamin-docs init
|
|
120
|
+
benjamin-docs status
|
|
121
|
+
benjamin-docs validate
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`init` prints the recommended agent prompt. Run `next` later if you want to see that prompt again.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
benjamin-docs next
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
In an interactive terminal, `init` asks what you are setting up. In scripts or agent workflows, pass a mode explicitly.
|
|
131
|
+
|
|
132
|
+
For an existing codebase:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
benjamin-docs init --mode codebase
|
|
136
|
+
benjamin-docs validate
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
For a single feature:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
benjamin-docs init --mode feature --feature billing-reminders
|
|
143
|
+
benjamin-docs validate
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
If you prefer a project-local dev dependency:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
cd /path/to/your-project
|
|
150
|
+
pnpm add -D benjamin-docs
|
|
151
|
+
pnpm exec benjamin-docs init
|
|
152
|
+
pnpm exec benjamin-docs validate
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Install The Agent Skill Locally
|
|
156
|
+
|
|
157
|
+
The skill teaches an agent how to capture planning/build conversations into the docs created by the CLI.
|
|
158
|
+
|
|
159
|
+
For Codex local skills:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
mkdir -p ~/.codex/skills/benjamin-docs
|
|
163
|
+
cp skills/benjamin-docs/SKILL.md ~/.codex/skills/benjamin-docs/SKILL.md
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Then ask your agent:
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
Capture this conversation with benjamin-docs.
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
For a first planning session, a clearer prompt is:
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
Use the benjamin-docs skill.
|
|
176
|
+
If there is no project folder yet, ask me where to create one.
|
|
177
|
+
Suggest ~/Documents/Benjamin Docs/<Project Name> by default.
|
|
178
|
+
Initialize it as a planning-only project, add a simple README.md,
|
|
179
|
+
and capture what we know, what we decided, what is still unclear,
|
|
180
|
+
and what I should do next. Keep it understandable for a non-technical reader.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Local Development
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
git clone https://github.com/msiksnis/benjamin-docs.git
|
|
187
|
+
cd benjamin-docs
|
|
188
|
+
pnpm install
|
|
189
|
+
pnpm build
|
|
190
|
+
node dist/src/cli.js introduce
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
To test the source CLI inside another local project without installing the package:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
cd /path/to/your-project
|
|
197
|
+
node /path/to/benjamin-docs/dist/src/cli.js init
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Checks
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pnpm check
|
|
204
|
+
node dist/src/cli.js validate
|
|
205
|
+
npm pack --dry-run
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Before publishing:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
pnpm run release:check
|
|
212
|
+
pnpm publish
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Common Commands
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
benjamin-docs introduce
|
|
219
|
+
benjamin-docs help
|
|
220
|
+
benjamin-docs --version
|
|
221
|
+
benjamin-docs init
|
|
222
|
+
benjamin-docs init --mode codebase
|
|
223
|
+
benjamin-docs init --mode feature --feature booking-capacity
|
|
224
|
+
benjamin-docs next
|
|
225
|
+
benjamin-docs status
|
|
226
|
+
benjamin-docs validate
|
|
227
|
+
benjamin-docs scope create feature booking-capacity
|
|
228
|
+
benjamin-docs anchor add booking-capacity-rules src/features/booking/capacity.ts
|
|
229
|
+
benjamin-docs export --audience developer
|
|
230
|
+
benjamin-docs promote --to codebase
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
In a source checkout, use `node dist/src/cli.js ...` after `pnpm build`.
|
|
234
|
+
|
|
235
|
+
## What It Creates
|
|
236
|
+
|
|
237
|
+
```text
|
|
238
|
+
benjamin-docs/
|
|
239
|
+
.benjamin-docs/
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`benjamin-docs/` contains human-readable Markdown. `.benjamin-docs/` contains machine metadata for validation, exports, anchors, and future publishing.
|
|
243
|
+
|
|
244
|
+
The default workspace is:
|
|
245
|
+
|
|
246
|
+
```text
|
|
247
|
+
benjamin-docs/
|
|
248
|
+
project/
|
|
249
|
+
handoff/
|
|
250
|
+
engineering/
|
|
251
|
+
features/
|
|
252
|
+
releases/
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Existing project docs in `docs/` are left alone. They may be useful context, but they are not the Benjamin-managed workspace unless `.benjamin-docs/config.json` explicitly says so.
|
|
256
|
+
|
|
257
|
+
## Agent Workflow
|
|
258
|
+
|
|
259
|
+
The CLI owns structure and validation. Codex or Claude skills own synthesis from the current conversation.
|
|
260
|
+
|
|
261
|
+
Ask your agent:
|
|
262
|
+
|
|
263
|
+
```text
|
|
264
|
+
Capture this conversation with benjamin-docs.
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The agent should update the relevant docs, run validation, and report what changed.
|
|
268
|
+
|
|
269
|
+
Good capture prompts:
|
|
270
|
+
|
|
271
|
+
```text
|
|
272
|
+
Use benjamin-docs to create a project from this chat.
|
|
273
|
+
Suggest ~/Documents/Benjamin Docs/<Project Name>, then initialize it and capture the project.
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
Capture this planning conversation with benjamin-docs.
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
```text
|
|
281
|
+
Capture the current project baseline with benjamin-docs.
|
|
282
|
+
Read the existing docs and codebase, then update the Benjamin docs
|
|
283
|
+
under benjamin-docs/. Mark uncertain items.
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
Create a benjamin-docs feature scope for billing-reminders
|
|
288
|
+
and capture the plan, decisions, risks, and handoff.
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Capture A Baseline
|
|
292
|
+
|
|
293
|
+
A baseline capture turns the current state of a project into durable docs. It is the first useful pass after `init`, and it should capture decisions, rejected options, risks, open questions, and next actions instead of saving a raw transcript.
|
|
294
|
+
|
|
295
|
+
For a new idea or planning-only project:
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
benjamin-docs init --mode planning
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
```text
|
|
302
|
+
Capture the baseline for this new idea with benjamin-docs.
|
|
303
|
+
Update the project brief, roadmap, open questions, and handoff docs.
|
|
304
|
+
Mark assumptions clearly and challenge any overbuilt V1 scope.
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
For an existing codebase:
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
benjamin-docs init --mode codebase
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
Capture the current codebase baseline with benjamin-docs.
|
|
315
|
+
Read the README, package/config files, existing docs, and major source areas.
|
|
316
|
+
Update the project, engineering, and handoff docs under benjamin-docs/.
|
|
317
|
+
Include important code references, risks, and uncertain findings.
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
For one feature:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
benjamin-docs init --mode feature --feature billing-reminders
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
```text
|
|
327
|
+
Capture the billing-reminders feature with benjamin-docs.
|
|
328
|
+
Update the feature brief, plan, decisions, and handoff.
|
|
329
|
+
Include user goals, constraints, rejected options, test ideas, and next actions.
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
After any baseline capture:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
benjamin-docs validate
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Design Boundaries
|
|
339
|
+
|
|
340
|
+
- The repo-local docs are the source of truth.
|
|
341
|
+
- The CLI should stay deterministic and dependency-light.
|
|
342
|
+
- Ordinary local commands should not make network calls.
|
|
343
|
+
- Existing docs in a repo should not be overwritten.
|
|
344
|
+
- Hosted publishing, auth, comments, and web editing are future layers.
|
|
345
|
+
|
|
346
|
+
## Contributing
|
|
347
|
+
|
|
348
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
349
|
+
|
|
350
|
+
## Security
|
|
351
|
+
|
|
352
|
+
See [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function addAnchor(root: string, id: string, file: string, docs?: string[]): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, relative, sep, win32 } from "node:path";
|
|
3
|
+
import { ANCHORS_FILE, CONFIG_DIR } from "./constants.js";
|
|
4
|
+
import { pathExists, readGeneratedJson, rootPath, writeGeneratedJson } from "./fsx.js";
|
|
5
|
+
const ANCHOR_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
6
|
+
const METADATA_LABEL = "Metadata path";
|
|
7
|
+
export function addAnchor(root, id, file, docs = []) {
|
|
8
|
+
if (!ANCHOR_ID_PATTERN.test(id)) {
|
|
9
|
+
throw new Error(`Invalid anchor id: ${id}`);
|
|
10
|
+
}
|
|
11
|
+
const filePath = validateRelativePath(root, file, "anchor file");
|
|
12
|
+
const safeDocs = docs.map((doc) => validateRelativePath(root, doc, "anchor docs path"));
|
|
13
|
+
if (!pathExists(filePath.full)) {
|
|
14
|
+
throw new Error(`Anchor file does not exist: ${file}`);
|
|
15
|
+
}
|
|
16
|
+
assertRegularFileInsideRoot(root, filePath.full, file);
|
|
17
|
+
const anchorsPath = `${CONFIG_DIR}/${ANCHORS_FILE}`;
|
|
18
|
+
const anchors = readGeneratedJson(root, anchorsPath, METADATA_LABEL);
|
|
19
|
+
anchors.anchors[id] = { file, docs: safeDocs.map((doc) => doc.relative) };
|
|
20
|
+
writeGeneratedJson(root, anchorsPath, anchors, METADATA_LABEL);
|
|
21
|
+
}
|
|
22
|
+
function validateRelativePath(root, path, label) {
|
|
23
|
+
if (!path || path.includes("\\") || win32.isAbsolute(path) || hasDotSegment(path)) {
|
|
24
|
+
throw new Error(`Invalid ${label}: ${path}`);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return { full: rootPath(root, path), relative: path };
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new Error(`Invalid ${label}: ${path}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function hasDotSegment(path) {
|
|
34
|
+
return path.split("/").some((part) => part === "." || part === ".." || part === "");
|
|
35
|
+
}
|
|
36
|
+
function assertRegularFileInsideRoot(root, fullPath, originalPath) {
|
|
37
|
+
if (!statSync(fullPath).isFile()) {
|
|
38
|
+
throw new Error(`Anchor target must be a regular file: ${originalPath}`);
|
|
39
|
+
}
|
|
40
|
+
const realRoot = realpathSync(root);
|
|
41
|
+
const realTarget = realpathSync(fullPath);
|
|
42
|
+
if (!isInsideRoot(realRoot, realTarget)) {
|
|
43
|
+
throw new Error(`Anchor target must remain inside project root: ${originalPath}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function isInsideRoot(root, target) {
|
|
47
|
+
const relativePath = relative(root, target);
|
|
48
|
+
return relativePath === "" || (!relativePath.startsWith(`..${sep}`) && relativePath !== ".." && !isAbsolute(relativePath));
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=anchors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchors.js","sourceRoot":"","sources":["../../src/anchors.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { emitKeypressEvents } from "node:readline";
|
|
3
|
+
import { createInterface } from "node:readline/promises";
|
|
4
|
+
import { addAnchor } from "./anchors.js";
|
|
5
|
+
import { exportAudience } from "./export.js";
|
|
6
|
+
import { initProject, promoteToCodebase } from "./init.js";
|
|
7
|
+
import { getHelpText, getIntroductionText, getPackageVersion } from "./info.js";
|
|
8
|
+
import { formatNextMessage, getNextPrompt } from "./next.js";
|
|
9
|
+
import { createScope } from "./scopes.js";
|
|
10
|
+
import { getStatus } from "./status.js";
|
|
11
|
+
import { validateProject } from "./validate.js";
|
|
12
|
+
export async function main(argv = process.argv.slice(2), cwd = process.cwd()) {
|
|
13
|
+
const [command] = argv;
|
|
14
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
15
|
+
console.log(getHelpText());
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
if (command === "--version" || command === "-v") {
|
|
19
|
+
console.log(getPackageVersion());
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
if (command === "introduce") {
|
|
23
|
+
console.log(getIntroductionText());
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
if (command === "init") {
|
|
27
|
+
const options = await resolveInitOptions(argv.slice(1));
|
|
28
|
+
const result = initProject(cwd, options);
|
|
29
|
+
console.log(`Initialized benjamin-docs. ${result.written.length} files created.`);
|
|
30
|
+
console.log("");
|
|
31
|
+
console.log(formatNextMessage(getNextPrompt(cwd)));
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
if (command === "next") {
|
|
35
|
+
console.log(formatNextMessage(getNextPrompt(cwd)));
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
if (command === "status") {
|
|
39
|
+
console.log(getStatus(cwd));
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
if (command === "scope") {
|
|
43
|
+
if (argv[1] !== "create") {
|
|
44
|
+
throw new Error("Usage: benjamin-docs scope create feature <slug>");
|
|
45
|
+
}
|
|
46
|
+
const kind = argv[2];
|
|
47
|
+
const id = argv[3];
|
|
48
|
+
if (!kind || !id) {
|
|
49
|
+
throw new Error("Usage: benjamin-docs scope create feature <slug>");
|
|
50
|
+
}
|
|
51
|
+
const written = createScope(cwd, kind, id);
|
|
52
|
+
console.log(`Created ${kind} scope ${id}. ${written.length} files created.`);
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
if (command === "anchor") {
|
|
56
|
+
if (argv[1] !== "add") {
|
|
57
|
+
throw new Error("Usage: benjamin-docs anchor add <id> <file>");
|
|
58
|
+
}
|
|
59
|
+
const id = argv[2];
|
|
60
|
+
const file = argv[3];
|
|
61
|
+
if (!id || !file) {
|
|
62
|
+
throw new Error("Usage: benjamin-docs anchor add <id> <file>");
|
|
63
|
+
}
|
|
64
|
+
addAnchor(cwd, id, file);
|
|
65
|
+
console.log(`Added anchor ${id}.`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
if (command === "validate") {
|
|
69
|
+
const result = validateProject(cwd);
|
|
70
|
+
for (const warning of result.warnings)
|
|
71
|
+
console.warn(`Warning: ${warning}`);
|
|
72
|
+
if (result.errors.length > 0) {
|
|
73
|
+
for (const error of result.errors)
|
|
74
|
+
console.error(`Error: ${error}`);
|
|
75
|
+
return 1;
|
|
76
|
+
}
|
|
77
|
+
console.log("Validation passed.");
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
if (command === "export") {
|
|
81
|
+
const audienceIndex = argv.indexOf("--audience");
|
|
82
|
+
const audience = audienceIndex === -1 ? undefined : argv[audienceIndex + 1];
|
|
83
|
+
if (!audience) {
|
|
84
|
+
throw new Error("Usage: benjamin-docs export --audience <audience>");
|
|
85
|
+
}
|
|
86
|
+
const written = exportAudience(cwd, audience);
|
|
87
|
+
console.log(`Exported ${audience} bundle. ${written.length} files written.`);
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
if (command === "promote") {
|
|
91
|
+
if (argv[1] !== "--to" || argv[2] !== "codebase") {
|
|
92
|
+
throw new Error("Usage: benjamin-docs promote --to codebase");
|
|
93
|
+
}
|
|
94
|
+
const written = promoteToCodebase(cwd);
|
|
95
|
+
console.log(`Promoted benjamin-docs to codebase mode. ${written.length} files created.`);
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
console.error(`Unknown command: ${command}`);
|
|
99
|
+
console.error("");
|
|
100
|
+
console.error(getHelpText());
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
async function resolveInitOptions(args) {
|
|
104
|
+
const parsed = parseInitArgs(args);
|
|
105
|
+
if (parsed.setup)
|
|
106
|
+
return parsed;
|
|
107
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
108
|
+
return promptForInitOptions();
|
|
109
|
+
}
|
|
110
|
+
return { setup: "project" };
|
|
111
|
+
}
|
|
112
|
+
function parseInitArgs(args) {
|
|
113
|
+
const options = {};
|
|
114
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
115
|
+
const arg = args[index];
|
|
116
|
+
if (arg === "--mode" || arg === "--type" || arg === "--setup") {
|
|
117
|
+
const value = args[index + 1];
|
|
118
|
+
if (!value)
|
|
119
|
+
throw new Error("Usage: benjamin-docs init --mode <planning|codebase|feature>");
|
|
120
|
+
options.setup = parseSetup(value);
|
|
121
|
+
index += 1;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (arg === "--feature") {
|
|
125
|
+
const value = args[index + 1];
|
|
126
|
+
if (!value)
|
|
127
|
+
throw new Error("Usage: benjamin-docs init --mode feature --feature <slug>");
|
|
128
|
+
options.feature = value;
|
|
129
|
+
index += 1;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (arg === "--docs-root") {
|
|
133
|
+
const value = args[index + 1];
|
|
134
|
+
if (!value)
|
|
135
|
+
throw new Error("Usage: benjamin-docs init --docs-root <path>");
|
|
136
|
+
options.docsRoot = value;
|
|
137
|
+
index += 1;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
throw new Error(`Unknown init option: ${arg}`);
|
|
141
|
+
}
|
|
142
|
+
return options;
|
|
143
|
+
}
|
|
144
|
+
function parseSetup(value) {
|
|
145
|
+
if (value === "planning" || value === "project")
|
|
146
|
+
return "project";
|
|
147
|
+
if (value === "codebase")
|
|
148
|
+
return "codebase";
|
|
149
|
+
if (value === "feature")
|
|
150
|
+
return "feature";
|
|
151
|
+
throw new Error("Usage: benjamin-docs init --mode <planning|codebase|feature>");
|
|
152
|
+
}
|
|
153
|
+
async function promptForInitOptions() {
|
|
154
|
+
const choices = [
|
|
155
|
+
{ label: "Planning a new project", setup: "project" },
|
|
156
|
+
{ label: "Documenting an existing codebase", setup: "codebase" },
|
|
157
|
+
{ label: "Planning/documenting one feature", setup: "feature" },
|
|
158
|
+
];
|
|
159
|
+
const selected = await selectChoice("What are you setting up?", choices.map((choice) => choice.label));
|
|
160
|
+
const setup = choices[selected]?.setup ?? "project";
|
|
161
|
+
if (setup !== "feature")
|
|
162
|
+
return { setup };
|
|
163
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
164
|
+
try {
|
|
165
|
+
const feature = (await rl.question("Feature slug: ")).trim();
|
|
166
|
+
return { setup, feature };
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
rl.close();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function selectChoice(question, choices) {
|
|
173
|
+
let selected = 0;
|
|
174
|
+
const input = process.stdin;
|
|
175
|
+
emitKeypressEvents(input);
|
|
176
|
+
input.setRawMode(true);
|
|
177
|
+
const render = () => {
|
|
178
|
+
process.stdout.write("\x1Bc");
|
|
179
|
+
process.stdout.write(`${question}\n\n`);
|
|
180
|
+
choices.forEach((choice, index) => {
|
|
181
|
+
process.stdout.write(`${index === selected ? "> " : " "}${choice}\n`);
|
|
182
|
+
});
|
|
183
|
+
process.stdout.write("\nNavigate to select. Press Enter to continue.\n");
|
|
184
|
+
};
|
|
185
|
+
return new Promise((resolve) => {
|
|
186
|
+
const cleanup = () => {
|
|
187
|
+
input.setRawMode(false);
|
|
188
|
+
input.off("keypress", onKeypress);
|
|
189
|
+
process.stdout.write("\n");
|
|
190
|
+
};
|
|
191
|
+
const onKeypress = (str, key) => {
|
|
192
|
+
if (key.ctrl && key.name === "c") {
|
|
193
|
+
cleanup();
|
|
194
|
+
process.exit(130);
|
|
195
|
+
}
|
|
196
|
+
if (key.name === "up" || str === "k") {
|
|
197
|
+
selected = selected === 0 ? choices.length - 1 : selected - 1;
|
|
198
|
+
render();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (key.name === "down" || str === "j") {
|
|
202
|
+
selected = selected === choices.length - 1 ? 0 : selected + 1;
|
|
203
|
+
render();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (/^[1-9]$/.test(str)) {
|
|
207
|
+
const index = Number(str) - 1;
|
|
208
|
+
if (index >= 0 && index < choices.length) {
|
|
209
|
+
selected = index;
|
|
210
|
+
render();
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (key.name === "return" || key.name === "enter") {
|
|
215
|
+
cleanup();
|
|
216
|
+
resolve(selected);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
input.on("keypress", onKeypress);
|
|
220
|
+
render();
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
main()
|
|
224
|
+
.then((code) => {
|
|
225
|
+
process.exitCode = code;
|
|
226
|
+
})
|
|
227
|
+
.catch((error) => {
|
|
228
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
229
|
+
process.exitCode = 1;
|
|
230
|
+
});
|
|
231
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|