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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +352 -0
  3. package/dist/src/anchors.d.ts +1 -0
  4. package/dist/src/anchors.js +50 -0
  5. package/dist/src/anchors.js.map +1 -0
  6. package/dist/src/cli.d.ts +2 -0
  7. package/dist/src/cli.js +231 -0
  8. package/dist/src/cli.js.map +1 -0
  9. package/dist/src/constants.d.ts +12 -0
  10. package/dist/src/constants.js +13 -0
  11. package/dist/src/constants.js.map +1 -0
  12. package/dist/src/export.d.ts +1 -0
  13. package/dist/src/export.js +70 -0
  14. package/dist/src/export.js.map +1 -0
  15. package/dist/src/frontmatter.d.ts +3 -0
  16. package/dist/src/frontmatter.js +119 -0
  17. package/dist/src/frontmatter.js.map +1 -0
  18. package/dist/src/fsx.d.ts +14 -0
  19. package/dist/src/fsx.js +129 -0
  20. package/dist/src/fsx.js.map +1 -0
  21. package/dist/src/info.d.ts +3 -0
  22. package/dist/src/info.js +65 -0
  23. package/dist/src/info.js.map +1 -0
  24. package/dist/src/init.d.ts +12 -0
  25. package/dist/src/init.js +145 -0
  26. package/dist/src/init.js.map +1 -0
  27. package/dist/src/next.d.ts +2 -0
  28. package/dist/src/next.js +65 -0
  29. package/dist/src/next.js.map +1 -0
  30. package/dist/src/project-config.d.ts +6 -0
  31. package/dist/src/project-config.js +41 -0
  32. package/dist/src/project-config.js.map +1 -0
  33. package/dist/src/scopes.d.ts +1 -0
  34. package/dist/src/scopes.js +52 -0
  35. package/dist/src/scopes.js.map +1 -0
  36. package/dist/src/status.d.ts +1 -0
  37. package/dist/src/status.js +38 -0
  38. package/dist/src/status.js.map +1 -0
  39. package/dist/src/templates.d.ts +19 -0
  40. package/dist/src/templates.js +82 -0
  41. package/dist/src/templates.js.map +1 -0
  42. package/dist/src/types.d.ts +51 -0
  43. package/dist/src/types.js +2 -0
  44. package/dist/src/types.js.map +1 -0
  45. package/dist/src/validate.d.ts +5 -0
  46. package/dist/src/validate.js +542 -0
  47. package/dist/src/validate.js.map +1 -0
  48. package/package.json +45 -0
  49. 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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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(argv?: string[], cwd?: string): Promise<number>;
@@ -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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"}