@any-nav/cli 0.0.0-stage → 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/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 — 2026-10-21
4
+
5
+ First registry release.
6
+
7
+ - Command roster: `any-nav init / list [path] / help [topic]`, exit ladder
8
+ 0 (success — including empty results and rendered help/version) / 1
9
+ (runtime failure) / 2 (usage error).
10
+ - `list` answers rows by default; `--write` materializes the listing into an
11
+ idempotent marked section of the entry file; `--depth` bounds the walk.
12
+ - `--json` — the machine face: the routing projection as pure JSON on
13
+ stdout, diagnostics triaged by audience (maintainer-class notes go to
14
+ stderr, never into the JSON stream).
15
+ - Budget cuts are visible on the surface: `list` rows render ≥N floors
16
+ for cut folders; the `config` help topic's `maxFiles` row states the
17
+ same semantics.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CatheadOwl
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 CHANGED
@@ -1,3 +1,47 @@
1
- # Temporary Holding Version
1
+ # @any-nav/cli
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > Point any-nav at any Markdown folder. No more hand-maintained index files.
4
+
5
+ The Any-Nav CLI integration adapter: it discovers config, answers navigation
6
+ queries, and materializes generated listings into marked file sections. This
7
+ package owns all disk writes and exit codes — the SDK (`@any-nav/core`) it
8
+ wraps is read-only.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ npm install -g @any-nav/cli
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```sh
19
+ any-nav init # scaffold an any-nav.toml in the current folder
20
+ any-nav list [path] # render the navigation listing for a folder
21
+ any-nav list --depth N # bound the walk depth
22
+ any-nav list --write # materialize the listing into the marked section
23
+ any-nav list --json # machine face: pure JSON (routing projection) on stdout
24
+ any-nav help [command] # command help, plus non-command help topics
25
+ ```
26
+
27
+ - Empty results are legal answers (`exit 0`) — this is a data-presentation
28
+ tool, not a filter.
29
+ - Exit ladder: `0` success (including rendered help/version), `1` runtime
30
+ failure, `2` usage error.
31
+ - `--json` keeps stdout a pure JSON stream: maintainer-class diagnostics go
32
+ to stderr, consumer-facing notes ride the listing itself.
33
+
34
+ ## Config
35
+
36
+ `any-nav.toml` — states only exceptions; every key defaults:
37
+
38
+ - `local` — curation list: paths expanded into the default listing.
39
+ - `budget` — the context-budget guard (warns, never silently collapses).
40
+ - `scan` — scan boundary policy, additive over the engine's built-in floor.
41
+
42
+ `list` walks up from the target folder for the nearest `any-nav.toml`;
43
+ without one it lists on pure defaults.
44
+
45
+ ## License
46
+
47
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export interface Io {
2
+ stdout: {
3
+ write(s: string): void;
4
+ };
5
+ stderr: {
6
+ write(s: string): void;
7
+ };
8
+ }
9
+ export declare function run(argv: string[], io?: Io): Promise<number>;
package/dist/cli.js ADDED
@@ -0,0 +1,332 @@
1
+ /**
2
+ * any-nav CLI — integration adapter A1 (L0). Surface design and every
3
+ * 【权衡】 ruling live in the project's ADR-0007 (cli-dev walkthrough);
4
+ * the unified list model (framework decision 9) sets the roster: init /
5
+ * list / help — generate retired into list's --write form, so the write
6
+ * is the very payload the listing prints, spliced between markers.
7
+ *
8
+ * Family rules have a single implementation point here: run(argv, io)
9
+ * routes commander errors by typed code (helpDisplayed/version → 0,
10
+ * other commander.* → usage error 2, runtime → 1); data goes to stdout,
11
+ * diagnostics to stderr; output ends with exactly one newline.
12
+ */
13
+ import { Command, CommanderError, InvalidArgumentError, Option } from 'commander';
14
+ import { exec } from 'node:child_process';
15
+ import { existsSync } from 'node:fs';
16
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
17
+ import { promisify } from 'node:util';
18
+ import { createRequire } from 'node:module';
19
+ import { dirname, join, relative, resolve } from 'node:path';
20
+ import { ConfigError, CURATED_OMISSION_CLAUSE, defaultMarkers, estimateTokens, listFolder, materialize, routingViewJson, toolBlockLines, } from '@any-nav/core';
21
+ import { renderHelpTopic, renderHelpTopicsBlock, topicNames } from './help-topics.js';
22
+ const DEFAULT_CONFIG_NAME = 'any-nav.toml';
23
+ // src/ and dist/ sit one level below the package root, so this resolves in
24
+ // dev, packed, and installed forms alike.
25
+ const { version: VERSION } = createRequire(import.meta.url)('../package.json');
26
+ function nonNegativeInt(value) {
27
+ const n = Number.parseInt(value, 10);
28
+ if (!Number.isInteger(n) || n < 0) {
29
+ throw new InvalidArgumentError('must be a non-negative integer');
30
+ }
31
+ return n;
32
+ }
33
+ /**
34
+ * Marker-key sanitizer — the same rule core's formats apply to source
35
+ * paths (fileSafeName), applied here to the listed folder's
36
+ * config-root-relative path so one target file can carry one idempotent
37
+ * section per folder ('' — the config root itself — reads as 'root').
38
+ */
39
+ function markerKey(relPosix) {
40
+ return relPosix.replace(/[^a-zA-Z0-9-]+/g, '-').replace(/^-+|-+$/g, '') || 'root';
41
+ }
42
+ function emit(io, text) {
43
+ io.stdout.write(text.trimEnd() + '\n');
44
+ }
45
+ function emitDiagnostics(io, diagnostics, suppressWarnings) {
46
+ // no-description rides its own row as an inline marker (terminalLines);
47
+ // every other code keeps one stderr line each.
48
+ for (const diagnostic of diagnostics) {
49
+ if (diagnostic.code === 'no-description')
50
+ continue;
51
+ if (suppressWarnings && diagnostic.severity === 'warning')
52
+ continue;
53
+ io.stderr.write(`${diagnostic.severity}: [${diagnostic.code}] ${diagnostic.message}\n`);
54
+ }
55
+ }
56
+ export async function run(argv, io = process) {
57
+ let result = 0;
58
+ const program = new Command();
59
+ program
60
+ .name('any-nav')
61
+ .description('Agent navigation for any Markdown folder — query the live tree.')
62
+ // Long-only version flag: -v/-V stay unassigned (ADR-0007 §3, clig.dev route)
63
+ .version(VERSION, '--version', 'output the version number')
64
+ .exitOverride()
65
+ // ADR-0016: reference content rides the help subsystem as non-command
66
+ // topics (gh's HELP TOPICS expression; roster in help-topics.ts). The
67
+ // help command is ours, not commander's builtin: pseudo-topic dispatch
68
+ // needs one place that knows commands, topics, and itself (gh's
69
+ // 'gh help help' renders the help command's own help; the builtin
70
+ // cannot target itself).
71
+ .helpCommand(false)
72
+ .addHelpText('after', renderHelpTopicsBlock())
73
+ .configureOutput({
74
+ writeOut: (s) => io.stdout.write(s),
75
+ writeErr: (s) => io.stderr.write(s),
76
+ });
77
+ const withConfig = (cmd) => cmd.option('-c, --config <path>', 'pin a specific any-nav.toml (paths outside its root then error)');
78
+ program
79
+ .command('init')
80
+ .description('seed a comment-only any-nav.toml — the home for exceptions; list itself runs without one')
81
+ .option('-c, --config <path>', 'config path to write (default: any-nav.toml in the current directory)')
82
+ .action(async (opts) => {
83
+ result = await cmdInit(opts, io);
84
+ });
85
+ withConfig(program
86
+ .command('list')
87
+ .description('list a folder as path | description rows (default: the current directory)')
88
+ .argument('[path]', 'folder to list, any directory (default: the current directory)')
89
+ .option('--depth <n>', 'expand this many levels below the listed folder, ignoring the local list', nonNegativeInt)
90
+ .option('--no-warnings', 'hide [no-description] row markers and warning diagnostics')
91
+ .option('--write <file>', 'write the markdown rendering of the same view into <file> as an idempotent marked section')
92
+ .addOption(
93
+ // JSON and the write artifact are two packagings of one projection;
94
+ // asking for both is a usage error, not a precedence call.
95
+ new Option('--json', 'print the same view as machine-readable JSON (stdout stays pure JSON)').conflicts('write'))
96
+ .addHelpText('after', '\nRows are the interactive format; every row\'s path is relative to the\nfolder you listed. Rows print as "path | description"; folders at the\nboundary print as "[N below] path", with " | description" too when the\nfolder carries one — its README or a _category_.yml/.yaml/.json sidecar\n(N = the folder\'s recursive .md count); a file\'s description is its own —\nfrontmatter \'description:\' or its first substantive line; a row with no\ndescription prints a trailing " [no-description]" marker instead — off\nwith --no-warnings, and --write output never carries it. Folders on the listed folder\'s\nown local list expand by default — their children print inline and the\nfolder row itself is absorbed; deep entries need no ancestor chain —\nfolders between are transparent corridors whose own rows are omitted,\nand when that omits anything a leading \"# curated\" note says so (every\nfolder still lists by path); --depth overrides. --json prints the same\nprojection as JSON instead of rows — the machine-readable face: stdout is\npure JSON (maintainer-class diagnostics still go to stderr); entries are\nthe view\'s nodes (path, kind, description when present — absent means\nnone; truncated folders carry their exact recursive .md count), and the\nenvelope carries root, depth, routeCount, and truncation facts; row\ntext, markdown, and tool content are not part of it, so declared\ncommands are not executed. A toml\'s top-level\ncommands (tool declarations, e.g. \"coggit instructions\") render their\noutput into the listing ahead of the files — any-nav runs them\ncapture-only (10s timeout, 10,000-char cap); an unavailable tool becomes\na one-line skip note; ANY_NAV_NO_TOOLS=1 skips execution. Strict\nlocality — scan,\nexpansion, budget, and entry commands all belong to the listed folder alone: only its own\nany-nav.toml curates its view and an ancestor\'s never applies; a folder\nwith no toml of its own lists under pure defaults (built-in excludes +\n.gitignore), and nesting tomls is how curation follows directories.\nExcluded names bound the excluding view only — the folder itself stays\nlistable by path (exclusion is not access control). Listings\npast 100 rows are cut with a trailing note, never silently; a --write\nsection that would exceed the budget collapses expanded branches\nfirst, then trims lines, with a note in the section. --write <file>\nsplices the markdown rendering — preamble + tree, self-describing for a\nlife outside the terminal — between any-nav markers; reruns replace only\nthat section, and it requires an any-nav.toml (the section key anchors\nto its root).\n')).action(async (path, opts) => {
97
+ result = await cmdList(path, opts, io);
98
+ });
99
+ // search is unexposed (framework decision 9, owner ruling 2026-10-06:
100
+ // retrieval belongs to the host's tools; the core kernel stays for a
101
+ // future correct pattern). generate retired into list --write; retired
102
+ // commands exit 2 like guide/read.
103
+ const helpCmd = program
104
+ .command('help')
105
+ .description('display help for a command or topic')
106
+ .argument('[target]', 'a command name or a help topic')
107
+ // gh ignores trailing args after a help target ('gh help <topic> extra')
108
+ .allowExcessArguments(true);
109
+ helpCmd.action((target) => {
110
+ if (target === undefined) {
111
+ program.help(); // bare 'help' = program help (stdout, exit 0 via catch)
112
+ return;
113
+ }
114
+ const topic = renderHelpTopic(target);
115
+ if (topic !== null) {
116
+ emit(io, topic); // trailing extra args ignored (gh behaves the same)
117
+ return;
118
+ }
119
+ const command = program.commands.find((c) => c.name() === target);
120
+ if (command !== undefined) {
121
+ command.help(); // HelpRequestError → exit 0 via the catch below
122
+ return;
123
+ }
124
+ const knownCommands = program.commands.map((c) => c.name());
125
+ io.stderr.write(`error: unknown help target '${target}'. Commands: ${knownCommands.join(', ')}; ` +
126
+ `topics: ${topicNames().join(', ')}; run 'any-nav help' to see both.\n`);
127
+ result = 2;
128
+ });
129
+ try {
130
+ await program.parseAsync(argv, { from: 'user' });
131
+ return result;
132
+ }
133
+ catch (err) {
134
+ if (err instanceof CommanderError) {
135
+ // Typed routing (ADR-0007 §7): commander declares its own exit intent —
136
+ // help/version carry exitCode 0 (including the builtin `help` command,
137
+ // code 'commander.help'); usage errors carry 1 and are remapped to 2.
138
+ return err.exitCode === 0 ? 0 : 2;
139
+ }
140
+ io.stderr.write(`${err.message}\n`);
141
+ return 1;
142
+ }
143
+ }
144
+ async function cmdInit(opts, io) {
145
+ // init owns its -c flag: it names the write target, not a discovery override.
146
+ const configPath = resolve(opts.config ?? join(process.cwd(), DEFAULT_CONFIG_NAME));
147
+ if (existsSync(configPath)) {
148
+ io.stderr.write(`any-nav: ${configPath} already exists — edit it, or pass --config <path> to write elsewhere; ` +
149
+ `schema: 'any-nav help config'\n`);
150
+ return 1;
151
+ }
152
+ // ADR-0016 option C: minimal config + pointer line — the template is a
153
+ // config, not a documentation carrier; the schema lives in 'help config'.
154
+ // A comment-only file is a complete config: the opt-in and the boundary.
155
+ const text = `# full schema: any-nav help config\n` +
156
+ `# list runs without this file (pure defaults); it exists to state exceptions —\n` +
157
+ `# [scan] excludes, local default-expansion, budget, commands entry-declarations.\n` +
158
+ `# Comment-only is complete.\n`;
159
+ await mkdir(dirname(configPath), { recursive: true });
160
+ await writeFile(configPath, text, 'utf8');
161
+ io.stdout.write(`${configPath} created (comment-only — the home for exceptions)\n`);
162
+ io.stdout.write(`next: 'any-nav list' — the navigation is queryable right away\n`);
163
+ io.stdout.write(`then: 'any-nav help telling-agents' — the two-line entry for AGENTS.md\n`);
164
+ io.stdout.write(`schema: 'any-nav help config'\n`);
165
+ return 0;
166
+ }
167
+ const execAsync = promisify(exec);
168
+ // Execution fuses (ADR-0018 ruling 13, CC-parity): a tool that hangs or
169
+ // floods must not hang or flood the listing — timeout, char cap, and a
170
+ // pointer past a head instead of a mid-body truncation.
171
+ const TOOL_TIMEOUT_MS = 10_000;
172
+ const TOOL_MAX_CHARS = 10_000;
173
+ const TOOL_HEAD_CHARS = 2_000;
174
+ // Trust gate (ADR-0018 ruling 12): opt-out switch — set to skip tool
175
+ // execution entirely and render the declaration rows instead. The gate
176
+ // lives here (adapter layer); core never reads the environment.
177
+ const NO_TOOLS_ENV = 'ANY_NAV_NO_TOOLS';
178
+ /**
179
+ * The CLI's CommandRunner (full-render ruling, 2026-10-16): runs each
180
+ * declared command through the shell in the governing toml's directory,
181
+ * capture-only — stdout becomes nav content, a failure becomes the
182
+ * one-line skip note (the reason rides stderr, never the payload).
183
+ */
184
+ async function shellCommandRunner(command, ctx) {
185
+ try {
186
+ const { stdout } = await execAsync(command, {
187
+ cwd: ctx.cwd,
188
+ timeout: TOOL_TIMEOUT_MS,
189
+ maxBuffer: TOOL_MAX_CHARS * 4,
190
+ windowsHide: true,
191
+ encoding: 'utf8',
192
+ });
193
+ const text = stdout.trim();
194
+ return {
195
+ ok: true,
196
+ stdout: text.length > TOOL_MAX_CHARS
197
+ ? `${text.slice(0, TOOL_HEAD_CHARS)}\n[capped at ${TOOL_HEAD_CHARS} of ${text.length} chars — run the command for the full output]`
198
+ : text,
199
+ };
200
+ }
201
+ catch (err) {
202
+ // The tool's own stderr first line says why better than Node's wrapper.
203
+ const e = err;
204
+ return { ok: false, reason: (e.stderr ?? e.message).split('\n')[0]?.trim() || 'failed' };
205
+ }
206
+ }
207
+ /**
208
+ * Terminal payload: the row rendering with the breadth-guard note appended.
209
+ * Rows are THE interactive format regardless of governance (packaging axis:
210
+ * write, not toml, decides the markdown envelope). Tool blocks declared by
211
+ * the governing toml frame here in the presentation layer from ToolSection
212
+ * data (ADR-0018 ruling 10) — view.lines keeps its pure row contract. A
213
+ * leading corridor note rides the payload when the curated view actually omitted
214
+ * content — reader knowledge, not a warning, so --no-warnings never hides
215
+ * it (the sentence is canonical in core; only the '# ' sigil is ours).
216
+ */
217
+ function terminalLines(listed, noDescription) {
218
+ const lines = [
219
+ // Ruling 10: framed blocks come from ToolSection data here in the
220
+ // presentation layer — view.lines stays pure `path | description`.
221
+ ...(listed.tools ?? []).flatMap((section) => [...toolBlockLines(section), '']),
222
+ ...(listed.view.omittedByCuration !== undefined ? [`# ${CURATED_OMISSION_CLAUSE}`] : []),
223
+ ];
224
+ // A description-less file's row is exactly its path (no " | " half), so
225
+ // exact-line membership marks it without touching described rows.
226
+ lines.push(...listed.view.lines.map((line) => noDescription.has(line) ? `${line} [no-description]` : line));
227
+ if (listed.view.rowsTruncated !== undefined) {
228
+ lines.push(`(listing truncated at ${listed.view.rowsTruncated.shown} rows, ${listed.view.rowsTruncated.omitted} omitted — narrow the path, search the folder yourself, or split the folder / nest an any-nav.toml)`);
229
+ }
230
+ return lines.length === 0 ? '(empty)' : lines.join('\n');
231
+ }
232
+ async function cmdList(path, opts, io) {
233
+ // Governance is the listed folder's business (2026-10-07 optionality
234
+ // ruling): nearest toml at or above it, pure defaults when none — cwd
235
+ // never participates. --config pins a specific config instead.
236
+ let listed;
237
+ try {
238
+ // Ruling 12: the opt-out gate decides at injection — a gated run
239
+ // renders the declaration rows (the no-runner fallback), never executes.
240
+ const toolsGated = ['1', 'true'].includes((process.env[NO_TOOLS_ENV] ?? '').toLowerCase());
241
+ // The JSON face v1 carries no tool content: declared commands neither
242
+ // run (no side-effectful spawns for output this face drops) nor
243
+ // re-express — the no-runner fallback rides `lines` only, which the
244
+ // JSON face does not serialize.
245
+ listed = await listFolder(resolve(process.cwd(), path ?? '.'), {
246
+ configPath: opts.config,
247
+ depth: opts.depth,
248
+ commandRunner: toolsGated || opts.json === true ? undefined : shellCommandRunner,
249
+ });
250
+ }
251
+ catch (err) {
252
+ if (err instanceof ConfigError) {
253
+ // E2 shape: core names the file; the CLI names the action + schema.
254
+ throw new Error(`any-nav: ${err.message}; fix the config or create one with 'any-nav init'; schema: 'any-nav help config'`);
255
+ }
256
+ // SG-4/5 family: prefix + recovery pointer on runtime errors.
257
+ throw new Error(`any-nav: ${err.message}; run 'any-nav list --help' for usage`);
258
+ }
259
+ // Warning switch (--no-warnings): hides row markers and warning-severity
260
+ // stderr lines. Interactive listing defaults to markers ON; --write never
261
+ // marks rows — a materialized section must not carry transient tree state.
262
+ const suppressWarnings = opts.warnings === false;
263
+ if (opts.json === true) {
264
+ // Audience triage (payload discipline): the payload carries
265
+ // consumer-class diagnostics — core's serialization filters them in —
266
+ // while maintainer diagnostics keep the stderr side-channel, so stdout
267
+ // stays pure JSON. `no-description` stays structural here (description
268
+ // absent means none); emitDiagnostics skips it as on rows.
269
+ const maintainer = listed.diagnostics.filter((diagnostic) => diagnostic.audience === 'maintainer' && diagnostic.face !== 'write');
270
+ emitDiagnostics(io, maintainer, suppressWarnings);
271
+ io.stdout.write(routingViewJson(listed.view) + '\n');
272
+ return 0;
273
+ }
274
+ // Packaging triage: write-artifact diagnostics (face 'write') report only
275
+ // where that artifact is produced — the --write flow. The rows answer is
276
+ // never touched by the budget guard, so a plain listing never hears about
277
+ // a section it did not ask for.
278
+ const surfaced = opts.write === undefined
279
+ ? listed.diagnostics.filter((diagnostic) => diagnostic.face !== 'write')
280
+ : listed.diagnostics;
281
+ emitDiagnostics(io, surfaced, suppressWarnings);
282
+ // Unavailable tools: the payload carries the canonical skip line; the
283
+ // reason (why it failed) is maintainer-side debugging — stderr, hideable.
284
+ if (!suppressWarnings) {
285
+ for (const section of listed.tools ?? []) {
286
+ if (section.output === undefined) {
287
+ io.stderr.write(`any-nav: tool '${section.command}' unavailable (${section.unavailableReason ?? 'no reason'})` + '\n');
288
+ }
289
+ }
290
+ }
291
+ if (opts.write === undefined) {
292
+ const noDescription = suppressWarnings
293
+ ? new Set()
294
+ : new Set(listed.diagnostics
295
+ .filter((diagnostic) => diagnostic.code === 'no-description')
296
+ .map((diagnostic) => diagnostic.path)
297
+ .filter((path) => path !== undefined));
298
+ emit(io, terminalLines(listed, noDescription));
299
+ return 0;
300
+ }
301
+ // Write form (generate's successor): the markdown rendering — preamble +
302
+ // tree, self-describing for a life outside the terminal — becomes a marked
303
+ // section in the user-named target (any path: writes are user-directed
304
+ // while only scanning is boundary-guarded). Markers key by the listed
305
+ // folder relative to the config root, so each folder owns its own
306
+ // idempotent section per target file — which is why the write axis keeps
307
+ // the toml anchor (optionality ruling, ruling 4).
308
+ if (listed.governingConfig === null) {
309
+ throw new Error(`any-nav: list --write needs an any-nav.toml to anchor the section key; ` +
310
+ `create one with 'any-nav init' (comment-only is enough) or pass --config <path>`);
311
+ }
312
+ const configRoot = dirname(resolve(listed.governingConfig));
313
+ const relPosix = relative(configRoot, listed.root).split('\\').join('/');
314
+ const markers = defaultMarkers(`list:${markerKey(relPosix)}`);
315
+ const fragment = { formatId: 'list', text: listed.markdown, targets: [], markers };
316
+ const target = resolve(process.cwd(), opts.write);
317
+ try {
318
+ const existing = await readFile(target, 'utf8').catch(() => null);
319
+ const next = materialize(existing ?? '', fragment, markers);
320
+ await mkdir(dirname(target), { recursive: true });
321
+ await writeFile(target, next, 'utf8');
322
+ }
323
+ catch (err) {
324
+ // SG-4/5 family: prefix + recovery pointer on runtime write errors too.
325
+ throw new Error(`any-nav: cannot write ${opts.write}: ${err.message}; run 'any-nav list --help' for usage`);
326
+ }
327
+ // Write mode: stdout carries only the report line — the payload's one
328
+ // home is the file; re-printing it would split the data face.
329
+ io.stdout.write(`wrote ${opts.write} (markdown, ~${estimateTokens(listed.markdown)} tokens)\n`);
330
+ return 0;
331
+ }
332
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * guide topic text — config (reference quadrant, Diataxis).
3
+ * The schema's canonical home is @any-nav/core parseConfig
4
+ * (core/src/config.ts); this copy restates it for humans and is kept
5
+ * from drifting by the SG-6/SG-7 guards (example blocks must parse,
6
+ * every accepted key and mode value must appear).
7
+ */
8
+ declare const _default = "any-nav config \u2014 the any-nav.toml schema\n\nGoal: the complete key set with defaults. The file states only exceptions:\nan absent key means automatic behavior, and unknown keys are rejected\nwith an error.\n\nTop-level tables:\n nav required, non-empty array \u2014 one [[nav]] entry per source folder\n budget optional \u2014 token budget for auto mode sizing\n ('any-nav guide modes')\n scan optional \u2014 traversal boundary policy\n\n[[nav]] entries:\n path required, string folder to navigate, relative to the\n config file location\n mode optional auto | inject | drill | recall\n (default auto \u2014 see 'any-nav guide\n modes')\n bind optional, v2 push bindings \u2014 parsed, no effect\n today\n\n[budget]:\n share optional, number fraction of the assumed context\n window (100,000 tokens) that\n injected sections may occupy,\n 0 < share <= 1 (default 0.02)\n maxTokens optional, integer hard cap in estimated tokens\n (default: none \u2014 share rules)\n\n[scan]:\n excludeDirs optional, strings directory names skipped in\n traversal (default: .git, .hg, .svn,\n node_modules, .pnpm, dist, build,\n lib, out)\n excludeFiles optional, strings markdown file names excluded,\n case-insensitive\n (default: AGENTS.md, CLAUDE.md)\n excludeDotEntries optional, boolean skip entries whose name starts\n with '.' (default true)\n respectGitignore optional, boolean traversal respects .gitignore\n files (default true)\n maxFiles optional, integer markdown files read per source\n (default 2000); past the cap files are\n skipped with a diagnostic, never silently\n\nMinimal example:\n\n```toml\n[[nav]]\npath = \"docs\"\n```\n\nFull example (every key, values illustrative):\n\n```toml\n[[nav]]\npath = \"docs\"\nmode = \"auto\"\n\n[[nav]]\npath = \"TODO\"\n\n[budget]\nshare = 0.1\nmaxTokens = 4000\n\n[scan]\nexcludeDirs = [\"node_modules\", \"dist\"]\nexcludeFiles = [\"AGENTS.md\"]\nexcludeDotEntries = true\nrespectGitignore = true\nmaxFiles = 500\n```\n\nKey boundaries:\n- Discovery: any-nav searches for any-nav.toml upward from the current\n directory; '--config <path>' overrides.\n- Mode semantics (what auto picks, what an explicit mode freezes):\n 'any-nav guide modes'.\n- A key is only real if this page lists it; the example blocks above are\n checked against the live parser by the test suite.\n\nRemember:\n- First config without writing one: 'any-nav init <path...>'.\n- Budget and chain semantics: 'any-nav guide modes'.\n";
9
+ export default _default;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * guide topic text — config (reference quadrant, Diataxis).
3
+ * The schema's canonical home is @any-nav/core parseConfig
4
+ * (core/src/config.ts); this copy restates it for humans and is kept
5
+ * from drifting by the SG-6/SG-7 guards (example blocks must parse,
6
+ * every accepted key and mode value must appear).
7
+ */
8
+ export default `any-nav config — the any-nav.toml schema
9
+
10
+ Goal: the complete key set with defaults. The file states only exceptions:
11
+ an absent key means automatic behavior, and unknown keys are rejected
12
+ with an error.
13
+
14
+ Top-level tables:
15
+ nav required, non-empty array — one [[nav]] entry per source folder
16
+ budget optional — token budget for auto mode sizing
17
+ ('any-nav guide modes')
18
+ scan optional — traversal boundary policy
19
+
20
+ [[nav]] entries:
21
+ path required, string folder to navigate, relative to the
22
+ config file location
23
+ mode optional auto | inject | drill | recall
24
+ (default auto — see 'any-nav guide
25
+ modes')
26
+ bind optional, v2 push bindings — parsed, no effect
27
+ today
28
+
29
+ [budget]:
30
+ share optional, number fraction of the assumed context
31
+ window (100,000 tokens) that
32
+ injected sections may occupy,
33
+ 0 < share <= 1 (default 0.02)
34
+ maxTokens optional, integer hard cap in estimated tokens
35
+ (default: none — share rules)
36
+
37
+ [scan]:
38
+ excludeDirs optional, strings directory names skipped in
39
+ traversal (default: .git, .hg, .svn,
40
+ node_modules, .pnpm, dist, build,
41
+ lib, out)
42
+ excludeFiles optional, strings markdown file names excluded,
43
+ case-insensitive
44
+ (default: AGENTS.md, CLAUDE.md)
45
+ excludeDotEntries optional, boolean skip entries whose name starts
46
+ with '.' (default true)
47
+ respectGitignore optional, boolean traversal respects .gitignore
48
+ files (default true)
49
+ maxFiles optional, integer markdown files read per source
50
+ (default 2000); past the cap files are
51
+ skipped with a diagnostic, never silently
52
+
53
+ Minimal example:
54
+
55
+ \`\`\`toml
56
+ [[nav]]
57
+ path = "docs"
58
+ \`\`\`
59
+
60
+ Full example (every key, values illustrative):
61
+
62
+ \`\`\`toml
63
+ [[nav]]
64
+ path = "docs"
65
+ mode = "auto"
66
+
67
+ [[nav]]
68
+ path = "TODO"
69
+
70
+ [budget]
71
+ share = 0.1
72
+ maxTokens = 4000
73
+
74
+ [scan]
75
+ excludeDirs = ["node_modules", "dist"]
76
+ excludeFiles = ["AGENTS.md"]
77
+ excludeDotEntries = true
78
+ respectGitignore = true
79
+ maxFiles = 500
80
+ \`\`\`
81
+
82
+ Key boundaries:
83
+ - Discovery: any-nav searches for any-nav.toml upward from the current
84
+ directory; '--config <path>' overrides.
85
+ - Mode semantics (what auto picks, what an explicit mode freezes):
86
+ 'any-nav guide modes'.
87
+ - A key is only real if this page lists it; the example blocks above are
88
+ checked against the live parser by the test suite.
89
+
90
+ Remember:
91
+ - First config without writing one: 'any-nav init <path...>'.
92
+ - Budget and chain semantics: 'any-nav guide modes'.
93
+ `;
94
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/guide-content/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqFd,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * guide topic text — modes (explanation quadrant, Diataxis).
3
+ * Semantics restated from docs/specs/mode.md (the living spec); this copy
4
+ * teaches, the spec rules.
5
+ */
6
+ declare const _default = "any-nav modes \u2014 exposure modes and the budget chain\n\nGoal: understand what any-nav injects and why a large source sometimes\ninjects less than the whole tree.\n\nThe chain (auto only):\n inject-full the whole navigation injected\n inject-top top level plus an \"omitted below\" pointer\n recall a stub pointing at search/read\nWith mode absent (auto), any-nav walks this chain and picks the cheapest\nform that fits the budget: [budget] share / maxTokens bound the estimated\ntokens the section may occupy.\n\nExplicit mode = hard constraint:\n inject full injection, never degraded for budget\n drill top level plus a drill-down pointer, never collapses to recall\n recall recall stub only, never upgrades because the source is small\nOver budget with an explicit mode, any-nav warns and ships the declared\nform anyway; the warning is expected, not a failure.\n\nDeclaration \u2194 chain form: inject = inject-full, drill = inject-top,\nrecall = recall. Declaring a mode freezes the auto chain at that form;\nthe chain-level names are what generate reports.\n\nKey boundaries:\n- Omission notices belong to auto only: an auto degradation explains\n itself and how to recover (list / search). Explicit modes never degrade,\n so they never explain omissions.\n- The budget bounds the injected map only. list / search / read always\n answer over the full tree.\n\nRemember:\n- Modes are declared per source in any-nav.toml ('any-nav guide config').\n";
7
+ export default _default;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * guide topic text — modes (explanation quadrant, Diataxis).
3
+ * Semantics restated from docs/specs/mode.md (the living spec); this copy
4
+ * teaches, the spec rules.
5
+ */
6
+ export default `any-nav modes — exposure modes and the budget chain
7
+
8
+ Goal: understand what any-nav injects and why a large source sometimes
9
+ injects less than the whole tree.
10
+
11
+ The chain (auto only):
12
+ inject-full the whole navigation injected
13
+ inject-top top level plus an "omitted below" pointer
14
+ recall a stub pointing at search/read
15
+ With mode absent (auto), any-nav walks this chain and picks the cheapest
16
+ form that fits the budget: [budget] share / maxTokens bound the estimated
17
+ tokens the section may occupy.
18
+
19
+ Explicit mode = hard constraint:
20
+ inject full injection, never degraded for budget
21
+ drill top level plus a drill-down pointer, never collapses to recall
22
+ recall recall stub only, never upgrades because the source is small
23
+ Over budget with an explicit mode, any-nav warns and ships the declared
24
+ form anyway; the warning is expected, not a failure.
25
+
26
+ Declaration ↔ chain form: inject = inject-full, drill = inject-top,
27
+ recall = recall. Declaring a mode freezes the auto chain at that form;
28
+ the chain-level names are what generate reports.
29
+
30
+ Key boundaries:
31
+ - Omission notices belong to auto only: an auto degradation explains
32
+ itself and how to recover (list / search). Explicit modes never degrade,
33
+ so they never explain omissions.
34
+ - The budget bounds the injected map only. list / search / read always
35
+ answer over the full tree.
36
+
37
+ Remember:
38
+ - Modes are declared per source in any-nav.toml ('any-nav guide config').
39
+ `;
40
+ //# sourceMappingURL=modes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modes.js","sourceRoot":"","sources":["../../src/guide-content/modes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCd,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * guide topic text — quickstart (tutorial quadrant, Diataxis).
3
+ * Teaching home per ADR-0013: this is product documentation, not
4
+ * navigation-fact text, so it lives in the CLI package as static copy.
5
+ */
6
+ declare const _default = "any-nav quickstart \u2014 first navigation from any Markdown folder\n\nGoal: point any-nav at Markdown folders and get a generated navigation\nsection that agents can list, search, and read.\n\nFast path:\n1. Create the config\n any-nav init docs\n Writes any-nav.toml with one [[nav]] entry per path. Already have a\n config? Skip this step. Full schema: 'any-nav guide config'.\n\n2. Generate the navigation section\n any-nav generate\n Scans the configured sources and writes a marked section between\n '<!-- any-nav:...:begin -->' and '<!-- any-nav:...:end -->' markers in\n each target file (default format generic-markdown: any-nav/<source>.md;\n --format agents-md writes into AGENTS.md).\n\n3. Use it\n any-nav list top-level map of the first source\n any-nav list --source docs --depth 1 drill one level\n any-nav search <keywords> no result is not an error\n (exit 0)\n any-nav read <locator> locator = path relative to a\n source root, e.g. sub/deploy.md\n\nKey boundaries:\n- Map, not territory: marked sections are generated. Never hand-edit\n between the markers \u2014 edit the source documents and regenerate.\n- Only exceptions go in the config; absent keys fall back to defaults.\n- After adding or renaming documents, rerun 'any-nav generate'.\n\nRemember:\n- 'any-nav guide config' for the complete any-nav.toml schema.\n- 'any-nav guide workflow' for the edit-regenerate loop.\n- 'any-nav guide modes' when a section comes out smaller than the folder.\n";
7
+ export default _default;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * guide topic text — quickstart (tutorial quadrant, Diataxis).
3
+ * Teaching home per ADR-0013: this is product documentation, not
4
+ * navigation-fact text, so it lives in the CLI package as static copy.
5
+ */
6
+ export default `any-nav quickstart — first navigation from any Markdown folder
7
+
8
+ Goal: point any-nav at Markdown folders and get a generated navigation
9
+ section that agents can list, search, and read.
10
+
11
+ Fast path:
12
+ 1. Create the config
13
+ any-nav init docs
14
+ Writes any-nav.toml with one [[nav]] entry per path. Already have a
15
+ config? Skip this step. Full schema: 'any-nav guide config'.
16
+
17
+ 2. Generate the navigation section
18
+ any-nav generate
19
+ Scans the configured sources and writes a marked section between
20
+ '<!-- any-nav:...:begin -->' and '<!-- any-nav:...:end -->' markers in
21
+ each target file (default format generic-markdown: any-nav/<source>.md;
22
+ --format agents-md writes into AGENTS.md).
23
+
24
+ 3. Use it
25
+ any-nav list top-level map of the first source
26
+ any-nav list --source docs --depth 1 drill one level
27
+ any-nav search <keywords> no result is not an error
28
+ (exit 0)
29
+ any-nav read <locator> locator = path relative to a
30
+ source root, e.g. sub/deploy.md
31
+
32
+ Key boundaries:
33
+ - Map, not territory: marked sections are generated. Never hand-edit
34
+ between the markers — edit the source documents and regenerate.
35
+ - Only exceptions go in the config; absent keys fall back to defaults.
36
+ - After adding or renaming documents, rerun 'any-nav generate'.
37
+
38
+ Remember:
39
+ - 'any-nav guide config' for the complete any-nav.toml schema.
40
+ - 'any-nav guide workflow' for the edit-regenerate loop.
41
+ - 'any-nav guide modes' when a section comes out smaller than the folder.
42
+ `;
43
+ //# sourceMappingURL=quickstart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quickstart.js","sourceRoot":"","sources":["../../src/guide-content/quickstart.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCd,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * guide topic text — workflow (how-to quadrant, Diataxis).
3
+ */
4
+ declare const _default = "any-nav workflow \u2014 the edit-regenerate loop\n\nGoal: keep the generated navigation in step with the documents it maps.\n\nHow-to:\n1. Add or rename documents in a configured source\n Just edit files. Nothing registers \u2014 the scan discovers Markdown by\n traversal under the [scan] policy ('any-nav guide config').\n\n2. Regenerate\n any-nav generate rewrite marked sections in place\n any-nav generate -n dry-run: report targets and sizes only\n any-nav generate --format agents-md write into AGENTS.md\n\n3. Add or remove a source folder\n Edit the [[nav]] entries in any-nav.toml (or run 'any-nav init' where no\n config exists yet), then regenerate.\n\n4. Check what the consumer sees\n any-nav list [--source <path>] [--prefix <sub>] [--depth n]\n any-nav search <keywords>\n any-nav read <locator>\n\nKey boundaries:\n- Marked sections are generated: everything between\n '<!-- any-nav:...:begin -->' and '<!-- any-nav:...:end -->' is rewritten\n by the next generate. Hand edits there are lost by design.\n- Descriptions come from each file's front matter 'description:'; files\n without one render as Undocumented placeholders and warn on generate.\n- Generate is idempotent: rerunning without document changes rewrites\n identical content.\n\nRemember:\n- 'any-nav guide quickstart' for the first-run path.\n- 'any-nav guide modes' when a section comes out smaller than expected.\n";
5
+ export default _default;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * guide topic text — workflow (how-to quadrant, Diataxis).
3
+ */
4
+ export default `any-nav workflow — the edit-regenerate loop
5
+
6
+ Goal: keep the generated navigation in step with the documents it maps.
7
+
8
+ How-to:
9
+ 1. Add or rename documents in a configured source
10
+ Just edit files. Nothing registers — the scan discovers Markdown by
11
+ traversal under the [scan] policy ('any-nav guide config').
12
+
13
+ 2. Regenerate
14
+ any-nav generate rewrite marked sections in place
15
+ any-nav generate -n dry-run: report targets and sizes only
16
+ any-nav generate --format agents-md write into AGENTS.md
17
+
18
+ 3. Add or remove a source folder
19
+ Edit the [[nav]] entries in any-nav.toml (or run 'any-nav init' where no
20
+ config exists yet), then regenerate.
21
+
22
+ 4. Check what the consumer sees
23
+ any-nav list [--source <path>] [--prefix <sub>] [--depth n]
24
+ any-nav search <keywords>
25
+ any-nav read <locator>
26
+
27
+ Key boundaries:
28
+ - Marked sections are generated: everything between
29
+ '<!-- any-nav:...:begin -->' and '<!-- any-nav:...:end -->' is rewritten
30
+ by the next generate. Hand edits there are lost by design.
31
+ - Descriptions come from each file's front matter 'description:'; files
32
+ without one render as Undocumented placeholders and warn on generate.
33
+ - Generate is idempotent: rerunning without document changes rewrites
34
+ identical content.
35
+
36
+ Remember:
37
+ - 'any-nav guide quickstart' for the first-run path.
38
+ - 'any-nav guide modes' when a section comes out smaller than expected.
39
+ `;
40
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/guide-content/workflow.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCd,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const GUIDE_TOPICS: ReadonlyArray<readonly [topic: string, summary: string]>;
2
+ export declare const topicNames: () => string[];
3
+ export declare function renderGuideList(): string;
4
+ export declare function renderGuide(topic: string): string | null;
package/dist/guide.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * guide — the in-CLI teaching home (ADR-0013).
3
+ *
4
+ * Topic texts are static string modules under guide-content/ (product
5
+ * documentation, not navigation-fact text, so they live in the CLI package
6
+ * rather than core). GUIDE_TOPICS is the single source of the roster: the
7
+ * topic list, guide's own help, and the root-help "Start here" line all
8
+ * render from it. The config topic restates the schema parsed by
9
+ * @any-nav/core; the SG-6/SG-7 guards keep that copy from drifting.
10
+ */
11
+ import quickstart from './guide-content/quickstart.js';
12
+ import config from './guide-content/config.js';
13
+ import workflow from './guide-content/workflow.js';
14
+ import modes from './guide-content/modes.js';
15
+ export const GUIDE_TOPICS = [
16
+ ['quickstart', 'first run: init a config, generate the navigation section, use list/search/read'],
17
+ ['config', 'the complete any-nav.toml schema with defaults; absent keys mean automatic'],
18
+ ['workflow', 'the edit-regenerate loop: sources, markers, descriptions, idempotency'],
19
+ ['modes', 'exposure modes and the budget chain: auto degrades, explicit modes are hard constraints'],
20
+ ];
21
+ const TEXTS = { quickstart, config, workflow, modes };
22
+ export const topicNames = () => GUIDE_TOPICS.map(([topic]) => topic);
23
+ export function renderGuideList() {
24
+ const rows = GUIDE_TOPICS.map(([topic, summary]) => ` ${topic.padEnd(12)} ${summary}`);
25
+ return ['Guides:', ...rows, '', `Run 'any-nav guide <topic>' to read one.`].join('\n');
26
+ }
27
+ export function renderGuide(topic) {
28
+ return TEXTS[topic] ?? null;
29
+ }
30
+ //# sourceMappingURL=guide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide.js","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,UAAU,MAAM,+BAA+B,CAAC;AACvD,OAAO,MAAM,MAAM,2BAA2B,CAAC;AAC/C,OAAO,QAAQ,MAAM,6BAA6B,CAAC;AACnD,OAAO,KAAK,MAAM,0BAA0B,CAAC;AAE7C,MAAM,CAAC,MAAM,YAAY,GAA6D;IACpF,CAAC,YAAY,EAAE,iFAAiF,CAAC;IACjG,CAAC,QAAQ,EAAE,4EAA4E,CAAC;IACxF,CAAC,UAAU,EAAE,uEAAuE,CAAC;IACrF,CAAC,OAAO,EAAE,yFAAyF,CAAC;CACrG,CAAC;AAEF,MAAM,KAAK,GAAqC,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAExF,MAAM,CAAC,MAAM,UAAU,GAAG,GAAa,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAE/E,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;IACxF,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,0CAA0C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * help topic text — config: the one-time setup knowledge for any-nav.toml
3
+ * (ADR-0016). The schema's canonical home is @any-nav/core parseConfig
4
+ * (core/src/config.ts); this copy restates it and is kept from drifting by
5
+ * the SG-6/SG-7 guards (example blocks must parse, every accepted key must
6
+ * appear). Four keys total: scan bounds, local curates, budget guards,
7
+ * commands declares. Burden rules SB-1/SB-2 (specs/surface.md) keep the
8
+ * page light: SG-10.
9
+ */
10
+ declare const _default = "any-nav config \u2014 the any-nav.toml schema\n\nThe complete key set with defaults. The file states only exceptions: an\nabsent key means automatic behavior, and unknown keys are rejected.\nEvery key serves its own file's folder view \u2014 strict locality: a\nfolder's own toml curates its view, an ancestor's never applies, and a\nfolder with no toml of its own lists under pure defaults (built-in\nexcludes + .gitignore).\n\nTop-level keys:\n local optional array \u2014 folders whose rows expand by default\n (config-relative paths)\n budget optional table \u2014 write-face token guard\n scan optional table \u2014 traversal boundary policy\n commands optional array \u2014 tool declarations, e.g. \"coggit\n instructions\": output renders into the listing ahead of\n the files (capture-only; 10s timeout; 10,000-char cap; skip\n note if unavailable; ANY_NAV_NO_TOOLS=1 gates execution).\n\nlocal (default: no expansion \u2014 depth-0 everywhere):\n Plain folder paths relative to the config file, no globs. A listed\n folder's row expands inline; a deep entry needs no ancestor chain \u2014\n folders between are transparent corridors whose own rows are omitted\n (a leading note line says so when that omits anything, and every\n folder still lists by path). Membership says expansion, not\n existence. 'any-nav list <folder> --depth N' overrides the list for\n one query (the escape hatch).\n\n[budget]:\n share optional, number fraction of the assumed\n 100,000-token context window\n the fragment may occupy (default\n 0.02; 0 < share <= 1)\n maxTokens optional, integer hard cap in estimated tokens\n (default: none \u2014 share rules; share\n 0.02 of 100,000 = 2000 tokens)\n\nThe budget guards the write face: an over-budget section collapses\nexpanded branches first, then trims lines \u2014 always with a note in the\nsection, never a silent cut. The rows face is never collapsed by\nbudget; its own guard is the flat 100-row cut.\n\n[scan]:\n excludeDirs optional, strings directory names additionally\n skipped in traversal. Appends to\n the always-on built-in list (.git,\n .hg, .svn, node_modules, .pnpm,\n dist, build, lib, out) \u2014 stating\n the key never removes a default.\n excludeFiles optional, strings markdown file names additionally\n excluded, case-insensitive.\n Appends to the built-in list\n (AGENTS.md, CLAUDE.md).\n excludeDotEntries optional, boolean skip entries whose name starts\n with '.' (default true)\n respectGitignore optional, boolean traversal respects .gitignore\n files (default true)\n maxFiles optional, integer markdown files examined per source\n walk (default 2000); past the cap\n entries go unexamined with a\n diagnostic \u2014 cut rows show \u2265N\n\nThe exclude names apply at any depth of this file's own view-walk.\nAn excluded folder stays listable by path, serving its own view.\n\nMinimal example (the whole file can be just comments):\n\n```toml\n# any-nav.toml \u2014 the home for exceptions: [scan] excludes, local\n# default-expansion, budget. list runs without it (pure defaults).\n```\n\nCurated example (the handbooks shelf expands inline; docs is a\ntransparent corridor \u2014 its other children stay off this view but list\nby path):\n\n```toml\nlocal = [\n \"docs/handbooks\",\n]\n\ncommands = [\"coggit entry --kind standard\"]\n```\n\nKey boundaries:\n- '--config <path>' pins a specific toml (paths outside its root then\n error). 'list --write' needs a toml and anchors to the nearest\n any-nav.toml at or above the listed folder (the section key's\n config root).\n- The file is optional; comment-only is complete.\n- list prints `path | description` rows; descriptions are the files'\n own \u2014 front-matter 'description:' or its first substantive line; a\n folder row carries its README's (or a `_category_` sidecar's).\n- 'list --write <file>' wraps the same view as a self-describing\n markdown section. The written target is ordinary navigable content \u2014\n give it a front-matter 'description:' (or gitignore / excludeFiles\n it) or it shows up as a bare row with a warning.\n- A key is only real if this page lists it.\n\nTelling agents about the navigation: 'any-nav help telling-agents'.\n";
11
+ export default _default;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * help topic text — config: the one-time setup knowledge for any-nav.toml
3
+ * (ADR-0016). The schema's canonical home is @any-nav/core parseConfig
4
+ * (core/src/config.ts); this copy restates it and is kept from drifting by
5
+ * the SG-6/SG-7 guards (example blocks must parse, every accepted key must
6
+ * appear). Four keys total: scan bounds, local curates, budget guards,
7
+ * commands declares. Burden rules SB-1/SB-2 (specs/surface.md) keep the
8
+ * page light: SG-10.
9
+ */
10
+ export default `any-nav config — the any-nav.toml schema
11
+
12
+ The complete key set with defaults. The file states only exceptions: an
13
+ absent key means automatic behavior, and unknown keys are rejected.
14
+ Every key serves its own file's folder view — strict locality: a
15
+ folder's own toml curates its view, an ancestor's never applies, and a
16
+ folder with no toml of its own lists under pure defaults (built-in
17
+ excludes + .gitignore).
18
+
19
+ Top-level keys:
20
+ local optional array — folders whose rows expand by default
21
+ (config-relative paths)
22
+ budget optional table — write-face token guard
23
+ scan optional table — traversal boundary policy
24
+ commands optional array — tool declarations, e.g. "coggit
25
+ instructions": output renders into the listing ahead of
26
+ the files (capture-only; 10s timeout; 10,000-char cap; skip
27
+ note if unavailable; ANY_NAV_NO_TOOLS=1 gates execution).
28
+
29
+ local (default: no expansion — depth-0 everywhere):
30
+ Plain folder paths relative to the config file, no globs. A listed
31
+ folder's row expands inline; a deep entry needs no ancestor chain —
32
+ folders between are transparent corridors whose own rows are omitted
33
+ (a leading note line says so when that omits anything, and every
34
+ folder still lists by path). Membership says expansion, not
35
+ existence. 'any-nav list <folder> --depth N' overrides the list for
36
+ one query (the escape hatch).
37
+
38
+ [budget]:
39
+ share optional, number fraction of the assumed
40
+ 100,000-token context window
41
+ the fragment may occupy (default
42
+ 0.02; 0 < share <= 1)
43
+ maxTokens optional, integer hard cap in estimated tokens
44
+ (default: none — share rules; share
45
+ 0.02 of 100,000 = 2000 tokens)
46
+
47
+ The budget guards the write face: an over-budget section collapses
48
+ expanded branches first, then trims lines — always with a note in the
49
+ section, never a silent cut. The rows face is never collapsed by
50
+ budget; its own guard is the flat 100-row cut.
51
+
52
+ [scan]:
53
+ excludeDirs optional, strings directory names additionally
54
+ skipped in traversal. Appends to
55
+ the always-on built-in list (.git,
56
+ .hg, .svn, node_modules, .pnpm,
57
+ dist, build, lib, out) — stating
58
+ the key never removes a default.
59
+ excludeFiles optional, strings markdown file names additionally
60
+ excluded, case-insensitive.
61
+ Appends to the built-in list
62
+ (AGENTS.md, CLAUDE.md).
63
+ excludeDotEntries optional, boolean skip entries whose name starts
64
+ with '.' (default true)
65
+ respectGitignore optional, boolean traversal respects .gitignore
66
+ files (default true)
67
+ maxFiles optional, integer markdown files examined per source
68
+ walk (default 2000); past the cap
69
+ entries go unexamined with a
70
+ diagnostic — cut rows show ≥N
71
+
72
+ The exclude names apply at any depth of this file's own view-walk.
73
+ An excluded folder stays listable by path, serving its own view.
74
+
75
+ Minimal example (the whole file can be just comments):
76
+
77
+ \`\`\`toml
78
+ # any-nav.toml — the home for exceptions: [scan] excludes, local
79
+ # default-expansion, budget. list runs without it (pure defaults).
80
+ \`\`\`
81
+
82
+ Curated example (the handbooks shelf expands inline; docs is a
83
+ transparent corridor — its other children stay off this view but list
84
+ by path):
85
+
86
+ \`\`\`toml
87
+ local = [
88
+ "docs/handbooks",
89
+ ]
90
+
91
+ commands = ["coggit entry --kind standard"]
92
+ \`\`\`
93
+
94
+ Key boundaries:
95
+ - '--config <path>' pins a specific toml (paths outside its root then
96
+ error). 'list --write' needs a toml and anchors to the nearest
97
+ any-nav.toml at or above the listed folder (the section key's
98
+ config root).
99
+ - The file is optional; comment-only is complete.
100
+ - list prints \`path | description\` rows; descriptions are the files'
101
+ own — front-matter 'description:' or its first substantive line; a
102
+ folder row carries its README's (or a \`_category_\` sidecar's).
103
+ - 'list --write <file>' wraps the same view as a self-describing
104
+ markdown section. The written target is ordinary navigable content —
105
+ give it a front-matter 'description:' (or gitignore / excludeFiles
106
+ it) or it shows up as a bare row with a warning.
107
+ - A key is only real if this page lists it.
108
+
109
+ Telling agents about the navigation: 'any-nav help telling-agents'.
110
+ `;
111
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/help-topics/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoGd,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * help topic text — telling-agents: the context-file entry (2026-10-08;
3
+ * v2 2026-10-09: capability line + one-shot procedural line — knowing the
4
+ * entry is not using it, so the entry itself schedules one pull per
5
+ * session, restoring what a hand-written navigation section used to
6
+ * guarantee. Two-line cap, derivation-free, never stale — SB-3). The
7
+ * materialized section is not taught here: '--write' is a list flag and
8
+ * its teaching stays with 'any-nav help list' (an exception for
9
+ * consumers without command access, not day-one knowledge). Burden
10
+ * rules SB-1/SB-2 (specs/surface.md): SG-10.
11
+ */
12
+ declare const _default = "any-nav telling-agents \u2014 the AGENTS.md entry\n\nFirst time? Put two lines in AGENTS.md:\n\n This repo's Markdown is dynamically indexed (name + description)\n by 'any-nav list <any-folder>' instead of a hand-written index.\n Run 'any-nav list' once when you start working here \u2014 it replaces\n the navigation this file would otherwise carry.\n\nHandwritten and derivation-free, so it never goes stale. If the\nlines are already there, you are done. The second line restores the\nguarantee a hand-written navigation section used to carry: the map\nis consumed once per session \u2014 pulled fresh instead of injected.\n\nThe rows are only as good as each file's own description: front-matter\n'description:' or the first substantive line (folders: their README).\nDocs that matter deserve a real one \u2014 'any-nav help config' has the\nsourcing rules.\n\nNotes:\n- Keep the entry to the two lines. Agents get the rest from\n 'any-nav --help' themselves; anything longer only goes stale.\n- Default expansion, excludes, budget: 'any-nav help config'. No\n config is needed to start.\n";
13
+ export default _default;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * help topic text — telling-agents: the context-file entry (2026-10-08;
3
+ * v2 2026-10-09: capability line + one-shot procedural line — knowing the
4
+ * entry is not using it, so the entry itself schedules one pull per
5
+ * session, restoring what a hand-written navigation section used to
6
+ * guarantee. Two-line cap, derivation-free, never stale — SB-3). The
7
+ * materialized section is not taught here: '--write' is a list flag and
8
+ * its teaching stays with 'any-nav help list' (an exception for
9
+ * consumers without command access, not day-one knowledge). Burden
10
+ * rules SB-1/SB-2 (specs/surface.md): SG-10.
11
+ */
12
+ export default `any-nav telling-agents — the AGENTS.md entry
13
+
14
+ First time? Put two lines in AGENTS.md:
15
+
16
+ This repo's Markdown is dynamically indexed (name + description)
17
+ by 'any-nav list <any-folder>' instead of a hand-written index.
18
+ Run 'any-nav list' once when you start working here — it replaces
19
+ the navigation this file would otherwise carry.
20
+
21
+ Handwritten and derivation-free, so it never goes stale. If the
22
+ lines are already there, you are done. The second line restores the
23
+ guarantee a hand-written navigation section used to carry: the map
24
+ is consumed once per session — pulled fresh instead of injected.
25
+
26
+ The rows are only as good as each file's own description: front-matter
27
+ 'description:' or the first substantive line (folders: their README).
28
+ Docs that matter deserve a real one — 'any-nav help config' has the
29
+ sourcing rules.
30
+
31
+ Notes:
32
+ - Keep the entry to the two lines. Agents get the rest from
33
+ 'any-nav --help' themselves; anything longer only goes stale.
34
+ - Default expansion, excludes, budget: 'any-nav help config'. No
35
+ config is needed to start.
36
+ `;
37
+ //# sourceMappingURL=telling-agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telling-agents.js","sourceRoot":"","sources":["../../src/help-topics/telling-agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAe;;;;;;;;;;;;;;;;;;;;;;;;CAwBd,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const HELP_TOPICS: ReadonlyArray<readonly [topic: string, summary: string]>;
2
+ export declare const topicNames: () => string[];
3
+ /** HELP TOPICS block appended to root help (gh's uppercase section form). */
4
+ export declare function renderHelpTopicsBlock(): string;
5
+ export declare function renderHelpTopic(topic: string): string | null;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * help topics — non-command reference pages rendered through the help
3
+ * subsystem (ADR-0016, gh-anchored expression; see the gh-cli handbook).
4
+ *
5
+ * A topic is not a command: `any-nav help config` and `any-nav help
6
+ * <command>` share one verb, `help` (no arguments) lists topics alongside
7
+ * commands, and unknown help targets list both. Topic texts are static
8
+ * string modules under help-topics/ (product documentation, not
9
+ * navigation-fact text). The config topic restates the schema parsed by
10
+ * @any-nav/core; SG-6/SG-7 guards keep that copy from drifting.
11
+ */
12
+ import config from './help-topics/config.js';
13
+ import tellingAgents from './help-topics/telling-agents.js';
14
+ export const HELP_TOPICS = [
15
+ ['config', 'the complete any-nav.toml schema: keys, defaults, the local list'],
16
+ ['telling-agents', "first time? the two-line AGENTS.md entry — never goes stale"],
17
+ ];
18
+ const TEXTS = { config, 'telling-agents': tellingAgents };
19
+ export const topicNames = () => HELP_TOPICS.map(([topic]) => topic);
20
+ /** HELP TOPICS block appended to root help (gh's uppercase section form). */
21
+ export function renderHelpTopicsBlock() {
22
+ const rows = HELP_TOPICS.map(([topic, summary]) => ` ${topic}: ${summary}`);
23
+ return `\nHELP TOPICS\n${rows.join('\n')}\n`;
24
+ }
25
+ export function renderHelpTopic(topic) {
26
+ return TEXTS[topic] ?? null;
27
+ }
28
+ //# sourceMappingURL=help-topics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-topics.js","sourceRoot":"","sources":["../src/help-topics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,aAAa,MAAM,iCAAiC,CAAC;AAE5D,MAAM,CAAC,MAAM,WAAW,GAA6D;IACnF,CAAC,QAAQ,EAAE,kEAAkE,CAAC;IAC9E,CAAC,gBAAgB,EAAE,6DAA6D,CAAC;CAClF,CAAC;AAEF,MAAM,KAAK,GAAqC,EAAE,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC;AAE5F,MAAM,CAAC,MAAM,UAAU,GAAG,GAAa,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAE9E,6EAA6E;AAC7E,MAAM,UAAU,qBAAqB;IACnC,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC;IAC9E,OAAO,kBAAkB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AAC9B,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ // Thin shim: all behavior lives in cli.ts (run is the single family-rule point).
3
+ import { run } from './cli.js';
4
+ process.exitCode = await run(process.argv.slice(2));
5
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,iFAAiF;AACjF,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,28 @@
1
1
  {
2
2
  "name": "@any-nav/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Any-Nav CLI integration adapter (L0): discovers config, materializes generated navigation fragments into agent files (AGENTS.md and other registered formats). Owns all disk writes and exit codes.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "any-nav": "./dist/main.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "CHANGELOG.md"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "dependencies": {
18
+ "@any-nav/core": "0.1.0",
19
+ "commander": "^15.0.0"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.build.json && node scripts/check-bin.mjs",
23
+ "typecheck": "tsc --noEmit",
24
+ "test": "node --test \"test/*.test.ts\"",
25
+ "pretest": "pnpm --filter @any-nav/core run build",
26
+ "pretypecheck": "pnpm --filter @any-nav/core run build"
27
+ }
6
28
  }