Files
bare-operating-system/packages/bare-os-coreutils/scripts/seed-man-pages.mjs
T
2026-04-26 06:19:47 -04:00

1128 lines
41 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* One-shot generator for man/pages/*.json (run after changing commands list).
* node packages/bare-os-coreutils/scripts/seed-man-pages.mjs
*/
import { mkdir, writeFile } from 'fs/promises'
import { dirname, join } from 'path'
import { fileURLToPath } from 'url'
import { COREUTILS_COMMANDS, MAN_EXTRA_PAGES } from '../lib/commands.mjs'
const __dirname = dirname(fileURLToPath(import.meta.url))
const pagesDir = join(__dirname, '../man/pages')
/** Commands whose man pages are explicitly marked stub/unsupported (keep empty in production). */
const STUB = new Set()
const POSIX_TITLE = {
awk: 'pattern scanning and processing language',
basename: 'strip directory and suffix from pathnames',
cat: 'concatenate and print files',
chgrp: 'change file group ownership',
chmod: 'change file mode bits',
chown: 'change file owner and group',
cksum: 'write file checksums and sizes',
clear: 'clear the terminal screen',
cp: 'copy files',
crontab: 'user crontab manipulation',
cut: 'cut out selected fields of each line',
date: 'display or set date and time',
dirname: 'return directory portion of a pathname',
du: 'estimate file space usage',
echo: 'write arguments to standard output',
env: 'set the environment for command invocation',
exit: 'exit the shell or booter session',
false: 'return false value',
find: 'find files',
getconf: 'get configuration values',
grep: 'pattern matching utility',
head: 'copy the first part of files',
hdms: 'Hyperswarm distributed map store',
help: 'Bare OS help summary',
hostname: 'set or print hostname',
id: 'return user identity',
jq: 'command-line JSON processor (jq language subset)',
ln: 'link files',
login: 'begin a session on the system',
logout: 'end session (save vault)',
logname: "return the user's login name",
ls: 'list directory contents',
man: 'display on-line manual pages',
mkdir: 'make directories',
mkfifo: 'make FIFO special files',
mv: 'move or rename files',
nl: 'line numbering utility',
nohup: 'run command (hangup is a no-op in Bare OS)',
od: 'octal dump',
pathchk: 'check pathname portability',
printenv: 'print environment variables',
printf: 'format and print',
pwd: 'return working directory name',
readlink: 'print symbolic link targets',
rm: 'remove files',
rmdir: 'remove empty directories',
savevault: 'encrypt snapshot of personal drive',
sed: 'stream editor',
seq: 'print sequences of numbers',
sleep: 'suspend execution for an interval',
sort: 'sort lines',
stat: 'display file status',
tail: 'copy the last part of a file',
tee: 'duplicate standard input',
test: 'evaluate a condition',
time: 'time a simple command',
timeout: 'run command with bounded wall time',
touch: 'change file timestamps or create files',
tr: 'translate or delete characters',
true: 'return true value',
tty: "return user's terminal name",
uname: 'return operating system name',
wc: 'word, line, and byte or character count',
which: 'locate a command',
whoami: 'display effective user ID',
xargs: 'construct argument lists and invoke utility'
}
/**
* cheat.sh-style snippets: { caption?, code } — shown under EXAMPLES in man output.
* @type {Record<string, Array<{ caption?: string, code: string }>>}
*/
const EXAMPLES = {}
EXAMPLES.awk = [
{ caption: 'print column 1', code: "awk '{print $1}' file.txt" },
{ caption: 'field separator', code: "awk -F: '{print $1}' /etc/passwd" },
{
caption: 'sum numbers in first column',
code: "awk '{s+=$1} END{print s}' nums.txt"
},
{
caption: 'lines matching /re/',
code: 'awk \'/error/{print NR": "$0}\' log.txt'
}
]
EXAMPLES.basename = [
{ caption: 'strip directory', code: 'basename /home/user/docs/readme.md' },
{ caption: 'strip suffix', code: 'basename -s .md /path/readme.md' }
]
EXAMPLES.cat = [
{ caption: 'stdout several files', code: 'cat a.txt b.txt' },
{
caption: 'number lines (use nl)',
code: 'cat -n file.txt # if supported; else nl file'
},
{ caption: 'here-string via echo pipe', code: 'echo hello | cat' }
]
EXAMPLES.chgrp = [
{ caption: 'set group by name', code: 'chgrp guest shared.conf' }
]
EXAMPLES.chmod = [
{ caption: 'octal', code: 'chmod 644 ~/.profile' },
{
caption: 'recursive-ish (run find + chmod per file)',
code: 'find . -type f -name "*.sh" -print'
},
{ caption: 'symbolic user bits', code: 'chmod u+x script.sh' },
{ caption: 'all read, owner write', code: 'chmod a+r,u+w shared.txt' }
]
EXAMPLES.chown = [
{ caption: 'group only', code: 'chown :guest file.txt' },
{ caption: 'numeric ids', code: 'chown 1000:1000 notes.txt' }
]
EXAMPLES.cksum = [
{ caption: 'checksum file', code: 'cksum iso.img' },
{ caption: 'verify pipeline', code: 'cat f | cksum' }
]
EXAMPLES.clear = [{ caption: 'wipe screen', code: 'clear' }]
EXAMPLES.cp = [
{ caption: 'copy file', code: 'cp src.txt dest.txt' },
{ caption: 'into directory', code: 'cp a b c ~/backup/' },
{ caption: 'preserve implied (if implemented)', code: 'cp -R proj proj.bak' }
]
EXAMPLES.crontab = [
{ caption: 'list jobs', code: 'crontab -l' },
{ caption: 'install from file', code: 'crontab ~/.crontab' },
{ caption: 'remove all', code: 'crontab -r' }
]
EXAMPLES.cut = [
{ caption: 'fields by delimiter', code: 'cut -d: -f1,3 /etc/passwd' },
{ caption: 'characters', code: 'cut -c1-16 file.txt' }
]
EXAMPLES.date = [
{ caption: 'RFC-ish output', code: 'date' },
{ caption: 'epoch seconds', code: 'date +%s' }
]
EXAMPLES.dirname = [
{ caption: 'parent path', code: 'dirname /a/b/c.txt' },
{
caption: 'compose with basename',
code: 'p=/x/y/z; echo $(dirname $p)/$(basename $p)'
}
]
EXAMPLES.du = [
{ caption: 'sizes under cwd', code: 'du .' },
{ caption: 'human (if supported)', code: 'du -h ~' }
]
EXAMPLES.echo = [
{ caption: 'literal', code: 'echo hello world' },
{ caption: 'no newline (if -n supported)', code: 'echo -n OK' }
]
EXAMPLES.env = [
{ caption: 'print environment', code: 'env' },
{ caption: 'run with override', code: 'env PATH=/bin:/usr/bin man ls' }
]
EXAMPLES.exit = [
{ caption: 'leave session with status', code: 'exit 0' },
{ caption: 'from script', code: '/bin/exit 42' }
]
EXAMPLES.false = [
{ caption: 'force failure in pipeline tests', code: 'false; echo $?' }
]
EXAMPLES.find = [
{ caption: 'files by name glob', code: 'find . -name "*.js"' },
{ caption: 'directories only', code: 'find . -type d' },
{ caption: 'max depth', code: 'find . -maxdepth 2 -type f' },
{ caption: 'OR names', code: 'find . \\( -name "*.c" -o -name "*.h" \\)' }
]
EXAMPLES.getconf = [
{ caption: 'path length limit', code: 'getconf PATH_MAX' },
{ caption: 'list known names and values', code: 'getconf -a' }
]
EXAMPLES.grep = [
{ caption: 'recursive feel (grep each file)', code: 'grep -n error *.log' },
{ caption: 'case insensitive', code: 'grep -i todo NOTES.md' },
{ caption: 'invert (lines without)', code: "grep -v '^#' config" },
{ caption: 'fixed string (no regex)', code: 'grep -F "v1.0" CHANGES' },
{ caption: 'count matches', code: 'grep -c FAIL build.log' },
{ caption: 'only filenames', code: 'grep -l main *.js' },
{ caption: 'multiple patterns', code: 'grep -e foo -e bar file.txt' }
]
EXAMPLES.head = [
{ caption: 'first 10 lines', code: 'head /etc/os-release' },
{ caption: 'first N', code: 'head -n 50 big.log' },
{ caption: 'stdin', code: 'cat long.txt | head' }
]
EXAMPLES.hdms = [
{ caption: 'when booter wires HDMS', code: 'hdms ls /mnt' },
{ caption: 'otherwise', code: '# prints unavailable without ctx.runHdms' }
]
EXAMPLES.help = [
{ caption: 'quick index', code: 'help' },
{ caption: 'then deep dive', code: 'man grep' }
]
EXAMPLES.hostname = [{ caption: 'show host', code: 'hostname' }]
EXAMPLES.id = [{ caption: 'who am I numerically', code: 'id' }]
EXAMPLES.ln = [
{ caption: 'symlink', code: 'ln -s target name' },
{ caption: 'hard link (if supported)', code: 'ln file linkname' }
]
EXAMPLES.login = [
{
caption: 'unlock: run login, then type passphrase at prompt (multi-word ok)',
code: 'login'
},
{ caption: 'register new identity', code: 'login --new' }
]
EXAMPLES.logout = [
{ caption: 'end session', code: 'logout' },
{ caption: 'save vault hint', code: 'logout --save' }
]
EXAMPLES.logname = [{ caption: 'login name', code: 'logname' }]
EXAMPLES.ls = [
{ caption: 'long + hidden', code: 'ls -la ~' },
{ caption: 'one per line', code: 'ls -1 /bin | head' },
{ caption: 'multiple paths', code: 'ls /bin /etc' }
]
EXAMPLES.man = [
{ caption: 'open page', code: 'man sed' },
{ caption: 'handbook TOC (section 7)', code: 'man handbook' },
{
caption: 'handbook chapter by section',
code: 'man 7 handbook-01-introduction'
},
{ caption: 'apropos', code: 'man -k copy' },
{ caption: 'whatis', code: 'man -f grep' },
{ caption: 'all pages', code: 'man -l' },
{ caption: 'fixed width (overrides TTY)', code: 'MANWIDTH=64 man awk' }
]
EXAMPLES.mkdir = [
{ caption: 'one dir', code: 'mkdir proj' },
{ caption: 'parents', code: 'mkdir -p a/b/c' }
]
EXAMPLES.mkfifo = [
{ caption: 'stub', code: '# FIFOs not on Hyperdrive — use shell pipelines' }
]
EXAMPLES.mv = [
{ caption: 'rename', code: 'mv old.txt new.txt' },
{ caption: 'into dir', code: 'mv *.txt ~/inbox/' }
]
EXAMPLES.nohup = [
{
caption: 'run utility (no real SIGHUP in guest)',
code: 'nohup long-job.sh'
}
]
EXAMPLES.nl = [{ caption: 'number all lines', code: 'nl README.md' }]
EXAMPLES.od = [{ caption: 'hex dump vibe', code: 'od -c file.bin | head' }]
EXAMPLES.pathchk = [
{ caption: 'portable path check', code: 'pathchk -p "$HOME/file name"' }
]
EXAMPLES.printenv = [
{ caption: 'one variable', code: 'printenv HOME' },
{ caption: 'all', code: 'printenv' }
]
EXAMPLES.printf = [
{ caption: 'format', code: 'printf "hex=%x dec=%d\\n" 255 255' },
{ caption: 'no newline', code: 'printf "%s" OK' }
]
EXAMPLES.pwd = [{ caption: 'where am I', code: 'pwd' }]
EXAMPLES.readlink = [{ caption: 'symlink target', code: 'readlink ~/.config' }]
EXAMPLES.rm = [
{ caption: 'file', code: 'rm tmp.txt' },
{ caption: 'tree', code: 'rm -rf build/' }
]
EXAMPLES.rmdir = [{ caption: 'empty dir', code: 'rmdir olddir' }]
EXAMPLES.savevault = [
{ caption: 'snapshot encrypted vault', code: 'savevault' }
]
EXAMPLES.sed = [
{ caption: 'substitute first per line', code: "sed 's/foo/bar/' file.txt" },
{ caption: 'global per line', code: "sed 's/ //g' spaced.txt" },
{ caption: 'in-place (if supported)', code: "sed -i.bak 's/^/# /' f.cfg" },
{ caption: 'print line 5 only', code: "sed -n '5p' file" },
{ caption: 'delete blank lines', code: "sed '/^$/d' file" }
]
EXAMPLES.seq = [
{ caption: '1..10', code: 'seq 1 10' },
{ caption: 'step', code: 'seq 0 2 20' }
]
EXAMPLES.sleep = [{ caption: 'pause seconds', code: 'sleep 2' }]
EXAMPLES.sort = [
{ caption: 'lexicographic', code: 'sort names.txt' },
{ caption: 'numeric', code: 'sort -n scores.txt' },
{ caption: 'unique', code: 'sort -u tags.txt' }
]
EXAMPLES.stat = [{ caption: 'metadata', code: 'stat ~/README.md' }]
EXAMPLES.tail = [
{ caption: 'last lines', code: 'tail -n 20 app.log' },
{ caption: 'follow vibe (Bare: poll manually)', code: 'tail error.log' }
]
EXAMPLES.tee = [
{ caption: 'copy stdout to file', code: 'cat x | tee copy.txt | wc -l' }
]
EXAMPLES.test = [
{ caption: 'file exists', code: 'test -f ~/.barerc && echo yes' },
{ caption: 'directory', code: 'test -d /home/user' },
{ caption: 'string equal', code: 'test "$USER" = guest' }
]
EXAMPLES.time = [{ caption: 'wall time a command', code: 'time sort big.txt' }]
EXAMPLES.timeout = [
{ caption: 'kill long job after 5s', code: 'timeout 5 slow-cmd' }
]
EXAMPLES.touch = [
{ caption: 'create empty', code: 'touch newfile' },
{ caption: 'refresh mtime', code: 'touch -c existing' }
]
EXAMPLES.tr = [
{ caption: 'uppercase', code: "echo hi | tr 'a-z' 'A-Z'" },
{ caption: 'delete chars', code: "tr -d '\\r' < win.txt" }
]
EXAMPLES.true = [{ caption: 'always success', code: 'true && echo ok' }]
EXAMPLES.tty = [{ caption: 'am I a tty', code: 'tty' }]
EXAMPLES.uname = [{ caption: 'kernel-ish info', code: 'uname -a' }]
EXAMPLES.wc = [
{ caption: 'lines words bytes', code: 'wc README.md' },
{ caption: 'stdin only', code: 'cat f | wc -l' }
]
EXAMPLES.which = [{ caption: 'resolve on PATH', code: 'which ls' }]
EXAMPLES.whoami = [{ caption: 'effective user', code: 'whoami' }]
EXAMPLES.xargs = [
{
caption: 'pass lines as arguments',
code: "printf 'a\\nb\\n' | xargs echo"
},
{
caption: 'one argument per run',
code: "printf 'a\\nb\\n' | xargs -n1 echo"
},
{
caption: 'workaround for complex scripts',
code: '# for f in *.txt; do grep -l foo $f; done'
}
]
/** @type {Record<string, Record<string, unknown>>} */
const EXTRA = {}
EXTRA.chgrp = {
description:
'Updates group metadata on the personal Hyperdrive for writable paths (session home, $HOME, /tmp, /var/log).',
bareOsNotes:
'Uses vfs.chown with preserved uid; system image paths are read-only. See packages/bare-os-booter/lib/vfs.js.'
}
EXTRA.chown = {
description:
'Updates uid/gid metadata on the personal Hyperdrive where the booter allows writes; euid 0 may set any owner.',
bareOsNotes:
'OWNER/GROUP may be numeric or root/guest/nobody/current user. See vfs chown and identity env UID/GID.'
}
EXTRA.xargs = {
description:
'Reads stdin into argument batches and runs **`ctx.runBinCommand`** (same as the shell). Enforces stdin size, token count, batch size, and invocation limits for safety.',
options: [
{
flag: '-0, --null',
meaning: 'Input items are null-terminated, not whitespace-separated'
},
{
flag: '-n, --max-args',
meaning: 'Up to N arguments per utility invocation (capped at 128)'
}
],
bareOsNotes:
'No host process spawn; not full POSIX xargs (no -I, -P, etc.). See src/xargs.js for limits.'
}
EXTRA.getconf = {
description:
'Prints a fixed subset of configuration limits for Bare OS (JavaScript runtime and VFS). There is no host sysconf(3); values are documented constants, not live kernel queries.',
options: [
{
flag: '-a',
meaning: 'Write all known variables (name then value per pair)'
}
],
bareOsNotes:
'Unknown variable names exit with status 1. Not a full Issue 7 getconf implementation.'
}
EXTRA.mkfifo = {
description:
'Creates in-memory FIFO endpoints under /run/bare-os/ipc/<name> (not Hyperdrive specials).',
bareOsNotes:
'Uses ctx.bareOsIpc.create; optional BARE_OS_IPC_NAMESPACE prefixes keys. BARE_OS_IPC_MAX_CHANNELS caps distinct channels; see metrics_live.ipcTelemetry.'
}
EXTRA.chmod = {
synopsis: [
'chmod MODE FILE...',
'MODE is octal (e.g. 644) or symbolic (e.g. u+rw)'
],
description:
'Sets file mode bits on the VFS. Supports POSIX-style symbolic modes (u/g/o/a, +/-/=, rwxX) and octal modes.',
options: [],
keywords: ['chmod', 'mode', 'permission', 'octal', 'symbolic'],
diagnostics: ['chmod: No such file', 'chmod: invalid mode'],
bareOsNotes: 'Applies to Hyperdrive metadata; not a host inode.'
}
EXTRA.grep = {
synopsis: [
'grep [-E|-F] [-i] [-v] [-n] [-c] [-l] [-q] [-s] [-H|-h] [-e pat] ... [-f file] ... [pattern] [file...]'
],
description:
'Searches input or files for lines matching a pattern. Uses JavaScript RegExp unless -F (fixed string). Not bit-identical to GNU grep.',
options: [
{
flag: '-E',
meaning: 'Extended regex (accepted; patterns use JS RegExp)'
},
{ flag: '-F', meaning: 'Fixed string match' },
{ flag: '-i', meaning: 'Ignore case' },
{ flag: '-v', meaning: 'Invert match' },
{ flag: '-n', meaning: 'Prefix lines with line number' },
{ flag: '-c', meaning: 'Count matching lines only' },
{ flag: '-l', meaning: 'List files with matches' },
{ flag: '-q', meaning: 'Quiet (exit status only)' },
{ flag: '-s', meaning: 'Suppress error messages' },
{ flag: '-H / -h', meaning: 'Force / suppress filename prefix' },
{ flag: '-e pat', meaning: 'Specify pattern' },
{ flag: '-f file', meaning: 'Read patterns from file' }
],
keywords: ['grep', 'search', 'regex', 'pattern', 'filter'],
seeAlso: [
{ name: 'sed', section: 1 },
{ name: 'awk', section: 1 }
],
bareOsNotes: 'UTF-16 strings and JS regex differ from strict POSIX/GNU.'
}
EXTRA.sed = {
description:
'Stream editor with a subset of POSIX sed. Large engine is vendored in lib/sed-engine.js.',
keywords: ['sed', 'stream', 'edit', 'substitute'],
seeAlso: [
{ name: 'awk', section: 1 },
{ name: 'grep', section: 1 }
],
bareOsNotes: 'JavaScript implementation; edge cases differ from GNU sed.'
}
EXTRA.awk = {
description:
'Pattern-directed scanning and processing. Engine in lib/awk-engine.js; not full POSIX awk.',
keywords: ['awk', 'pattern', 'field', 'script'],
seeAlso: [
{ name: 'sed', section: 1 },
{ name: 'grep', section: 1 }
],
bareOsNotes: 'See handbook ch.9 for divergence from Issue 7.'
}
EXTRA.dircolors = {
synopsis: ['dircolors [-b] [FILE]', 'dircolors -p'],
description:
'Print LS_COLORS from a dircolors database (GNU subset: TERM blocks, key/value pairs). -p prints the default Bare OS database.',
options: [
{ flag: '-b, --sh', meaning: 'Bourne-shell export LS_COLORS' },
{ flag: '-p, --print-database', meaning: 'Print default database' }
],
keywords: ['dircolors', 'LS_COLORS', 'color'],
bareOsNotes: 'FILE read via VFS.'
}
EXTRA.theme = {
synopsis: ['theme [list|current|set <name>|apply]'],
description:
'Switch Bare OS UI preset: updates ~/.barerc theme line, sets BARE_OS_THEME, calls bareOsApplyTheme when available.',
keywords: ['theme', 'colors', 'prompt'],
bareOsNotes: 'list/current work without booter hooks; set/apply need ctx.bareOsApplyTheme.'
}
EXTRA.ls = {
synopsis: ['ls [-1al] [--color[=never|auto|always]] [FILE...]'],
description:
'Lists directory contents. Long format shows mode, links, owner, group, size, mtime, and symlink targets. With color (default auto on a TTY), directories, symlinks, executables, and permission bits are highlighted.',
options: [
{ flag: '-a', meaning: 'Include names starting with .' },
{ flag: '-l', meaning: 'Long listing' },
{ flag: '-1', meaning: 'One name per line (short format)' },
{
flag: '--color[=never|auto|always]',
meaning:
'ANSI colors: never, auto (TTY only), or always; plain --color is auto'
}
],
environment: ['NO_COLOR — disable color even when a TTY or --color=always'],
keywords: ['ls', 'list', 'directory', 'dir'],
bareOsNotes: 'Hides .bareos_empty marker like other tools.'
}
EXTRA.man = {
synopsis: [
'man [-k keyword] [-f name] [-l] [[section] name]',
'man reads /share/man/man.json on the system drive.'
],
description:
'Displays manual pages from the merged JSON database. Section 1: /bin and git/shell pages. Section 7: handbook (man handbook), user manual (man users-manual), developer guide (man devguide), and docs/ (man docs), merged at build from handbook/*.md, users-manual/*.md, developer-guide/*.md, and docs/**/*.md.',
options: [
{
flag: '-k, --apropos',
meaning: 'Search keywords and titles (substring)'
},
{ flag: '-f, --whatis', meaning: 'One-line description for exact name' },
{
flag: '-l, --list',
meaning:
'List pages grouped by category (/bin, git/shell, handbook, user manual, developer guide, docs/), then alphabetically'
}
],
environment: [
'MANWIDTH — if set, wrap width (clamped 40200); overrides auto width',
'COLUMNS — when stdout is not a TTY (or output is captured), used if MANWIDTH unset',
'NO_COLOR — disable bold headings on TTY'
],
keywords: [
'man',
'manual',
'help',
'documentation',
'apropos',
'whatis',
'cheat',
'examples'
],
seeAlso: [
{ name: 'help', section: 1 },
{ name: 'bare-os-handbook', section: 7 },
{ name: 'bare-os-developer-guide', section: 7 },
{ name: 'bare-os-docs', section: 7 },
{ name: 'bare-os-users-manual', section: 7 }
],
bareOsNotes: 'No troff; no embedded DB fallback in v1.'
}
EXTRA.help = {
synopsis: ['help'],
description:
'Prints a one-screen summary of shell builtins and /bin command names. Use man for long-form documentation.',
keywords: ['help', 'summary', 'builtins', 'commands'],
seeAlso: [
{ name: 'man', section: 1 },
{ name: 'bare-os-shell', section: 1 }
]
}
EXTRA.exit = {
synopsis: ['exit [status]'],
description:
'When run as /bin/exit, requests the booter to end the session via ctx.requestBooterExit. Status defaults to 0.',
bareOsNotes: 'Also available as a shell builtin with different wiring.'
}
EXTRA.hdms = {
description:
'Invokes ctx.runHdms when the booter provides HDMS integration; otherwise prints unavailable.',
keywords: ['hdms', 'hyperswarm', 'map'],
bareOsNotes: 'Optional booter capability.'
}
EXTRA.find = {
synopsis: ['find [PATH...] [EXPRESSION]'],
description:
'Walks directories and applies expressions (-name, -type, -print, -maxdepth, logical -and/-or/-not).',
keywords: ['find', 'directory', 'walk', 'search'],
bareOsNotes: 'Expression syntax is a simplified subset.'
}
EXTRA.jq = {
synopsis: [
'jq [-n] [-R] [-s] [-c] [-r] [-e] [-f file] filter [file...]',
'jq reads JSON (concatenated values or NDJSON-style streams) from files or stdin.'
],
description:
'Runs a jq filter program against JSON values. The engine is vendored jqjs (pure JavaScript), not the C implementation at https://github.com/jqlang/jq — language coverage and edge cases differ.',
options: [
{
flag: '-n, --null-input',
meaning: 'Use null as the sole input (ignore file/stdin for input)'
},
{
flag: '-R, --raw-input',
meaning: 'Treat each line as a string instead of JSON'
},
{
flag: '-s, --slurp',
meaning: 'Read all inputs into one array; run the filter once'
},
{ flag: '-c, --compact-output', meaning: 'Compact JSON on output' },
{ flag: '-r, --raw-output', meaning: 'Print strings without JSON quotes' },
{
flag: '-e, --exit-status',
meaning:
'Set exit status from outputs (no output → 4; last false/null → 1)'
},
{ flag: '-f, --from-file', meaning: 'Read filter program from file' }
],
keywords: ['jq', 'json', 'query', 'filter', 'jqjs'],
seeAlso: [
{ name: 'grep', section: 1 },
{ name: 'awk', section: 1 }
],
bareOsNotes:
'Engine: lib/jq-engine.js from @sscots/jqjs (mwh/jqjs). Missing vs C jq: try/catch, user-defined functions, recurse, many builtins, modules, full Unicode. See upstream jqjs README for the feature matrix.',
examples: [
{ caption: 'pretty-print', code: 'jq . data.json' },
{ caption: 'field', code: 'jq .version package.json' },
{ caption: 'slurp array', code: "jq -s 'map(.x) | add' parts.jsonl" },
{ caption: 'compact', code: "jq -c '.[] | select(.ok)' items.json" }
]
}
EXTRA.login = {
description:
'When invoked from /bin, behavior aligns with session identity hooks (see booter). Prefer the shell builtin for passphrase entry.',
keywords: ['login', 'identity', 'passphrase'],
seeAlso: [{ name: 'logout', section: 1 }]
}
EXTRA.logout = {
description: 'Ends session; may persist vault depending on booter and flags.',
keywords: ['logout', 'session'],
seeAlso: [{ name: 'login', section: 1 }]
}
EXTRA.savevault = {
description:
'Encrypts a copy of the personal drive under /.bare/vault/ when identity services are available.',
keywords: ['savevault', 'vault', 'encrypt', 'backup'],
seeAlso: [{ name: 'login', section: 1 }]
}
function basePage(name) {
const title = POSIX_TITLE[name] || name
const p = {
name,
section: 1,
title,
synopsis: [`${name} [OPTION]... [OPERAND]...`],
description: `Bare OS implementation of ${title}. Full behavior is defined in packages/bare-os-coreutils/src/${name}.js.`,
options: [],
keywords: [name, 'bare-os', 'coreutils']
}
if (STUB.has(name)) {
p.stub = true
p.keywords.push('stub')
}
const ex = EXTRA[name]
if (ex) Object.assign(p, ex)
if (EXAMPLES[name]) p.examples = EXAMPLES[name]
return p
}
function gitPage() {
return {
name: 'git',
section: 1,
title: 'Bare OS git front-end (isomorphic-git)',
synopsis: ['git [-C dir] <subcommand> [ARGUMENTS...]'],
description:
'Runs isomorphic-git against the VFS-backed adapter. Remote HTTP(S) uses BARE_OS_GIT_HTTP when set; otherwise Pear bare module fetch.',
options: [{ flag: '-C dir', meaning: 'Run as if git was started in dir' }],
environment: [
'BARE_OS_GIT_HTTP — optional fetch implementation for remotes',
'GIT_* — standard hints where supported'
],
keywords: [
'git',
'version control',
'repository',
'clone',
'commit',
'isomorphic-git'
],
bareOsNotes:
'Not a separate /bin script; booter delegates argv[0]=git to git-cli.js.',
seeAlso: [{ name: 'bare-os-shell', section: 1 }],
examples: [
{ caption: 'new repo', code: 'git init -C ~/myrepo' },
{ caption: 'status', code: 'git -C ~/myrepo status' },
{
caption: 'clone over HTTP (needs remote + fetch)',
code: 'git clone https://example.com/repo.git ~/work/repo'
},
{
caption: 'config local',
code: 'git -C ~/myrepo config user.email "[email protected]"'
},
{ caption: 'log one line', code: 'git -C ~/myrepo log --oneline -5' }
]
}
}
function curlPage() {
return {
name: 'curl',
section: 1,
title: 'transfer a URL (Fetch-based client, not libcurl)',
synopsis: [
'curl [options] URL...',
'curl uses Fetch in the booter (Node fetch or bare-fetch), not libcurl.'
],
description:
'HTTP/HTTPS client delegated from the booter. Subset of curl(1) flags; see man page JSON for full options and exit codes.',
options: [
{ flag: '-X, --request METHOD', meaning: 'HTTP method' },
{ flag: '-H, --header LINE', meaning: 'Request header (repeatable)' },
{ flag: '-d, --data / --json', meaning: 'Request body' },
{ flag: '-o, --output FILE', meaning: 'Write response to VFS path' },
{ flag: '-T, --upload-file PATH', meaning: 'PUT file from VFS' },
{
flag: '-I / -i / -L / -f / -s / -S / -v / -u / -m / -w',
meaning: 'See full man curl.json'
}
],
keywords: ['curl', 'http', 'https', 'fetch', 'download'],
bareOsNotes:
'Not https://curl.se libcurl; booter curl-cli.js. URLs: http(s), data:, file://.',
seeAlso: [
{ name: 'git', section: 1 },
{ name: 'jq', section: 1 }
]
}
}
function wgetPage() {
return {
name: 'wget',
section: 1,
title: 'non-interactive network download (Fetch-based, not GNU wget2)',
synopsis: [
'wget [options] URL...',
'wget is implemented in the booter with the Fetch API (Node fetch or bare-fetch), not the C GNU wget2 tree.'
],
description:
'Downloads resources over HTTP or HTTPS into the VFS. Bare OS does not ship GNU wget or wget2 (C); this command is a small compatibility-oriented subset built on JavaScript fetch. It is delegated from the booter (like curl and git), not loaded from a /bin script on the system drive.',
options: [
{
flag: '-O, --output-document FILE',
meaning:
'Write the body to FILE; use - for stdout. Only one URL allowed.'
},
{
flag: '-P, --directory-prefix DIR',
meaning:
'Save under DIR using a name derived from the URL (last path segment, or index.html if the path ends with /)'
},
{
flag: '-q, --quiet',
meaning: 'Suppress non-error messages on stderr (saved path lines)'
},
{
flag: '-U, --user-agent STRING',
meaning: 'Set User-Agent request header'
},
{
flag: '-T, --timeout SECONDS',
meaning: 'Abort the request after SECONDS (AbortController)'
},
{
flag: '--header LINE',
meaning: 'Extra header Name: value (repeatable)'
},
{
flag: '--post-data STRING',
meaning:
'POST body (sets method POST; default Content-Type application/x-www-form-urlencoded)'
},
{
flag: '--post-file PATH',
meaning: 'POST body read from a file on the VFS'
},
{ flag: '-V, --version', meaning: 'Print Bare OS wget version string' },
{ flag: '-h, --help', meaning: 'Short usage' }
],
environment: [],
keywords: ['wget', 'download', 'http', 'https', 'fetch', 'mirror'],
bareOsNotes:
'Not GNU wget2 (https://gitlab.com/gnuwget/wget2). URLs must start with http://, https://, data:, or file://. No recursive retrieval, FTP, or WARC. Cannot combine -O and -P. On Pear/Bare, use bare-fetch for global fetch. Tests may set ctx.httpFetch.',
seeAlso: [
{ name: 'curl', section: 1 },
{ name: 'git', section: 1 }
],
examples: [
{
caption: 'save with default name in cwd',
code: 'wget https://example.com/README'
},
{
caption: 'choose output path',
code: 'wget -O ~/page.html https://example.com/'
},
{
caption: 'directory prefix',
code: 'wget -P ~/dl https://example.com/a/b.bin'
},
{ caption: 'stdout', code: 'wget -O - -q https://example.com/robots.txt' }
],
exitStatus: [
'0 — success',
'1 — generic error (reserved)',
'2 — bad usage or options',
'3 — file I/O error (e.g. --post-file unreadable)',
'4 — network failure or no fetch implementation',
'8 — HTTP 4xx/5xx response'
]
}
}
function ctxBarePage() {
return {
name: 'bare-os-ctx-bare',
section: 7,
title: 'ctx.bare library and drive bundles',
synopsis: ['# reference — not a shell command'],
description:
'Documents BARE_OS_BARE_MODULES and BARE_OS_BARE_DRIVE_BUNDLES for the booter ctx.bare registry. In-image scripts (AsyncFunction) use ctx.bare.<key> instead of import(). Keys come from host dynamic import of packages listed in packages/bare-os-booter/lib/bare-module-manifest.json, then optional merge from trusted IIFE bundles under /lib/bare/bundles/ on the system image (see manifest.json there). Set BARE_OS_BARE_MODULES=0 to omit ctx.bare entirely. Set BARE_OS_BARE_DRIVE_BUNDLES=0 to skip executing drive bundles (host imports only). Rebuild bundles with npm run build -w bare-os-bare-libs.',
options: [],
keywords: [
'BARE_OS_BARE_MODULES',
'BARE_OS_BARE_DRIVE_BUNDLES',
'ctx.bare',
'bare-module-manifest',
'bare-os-bare-libs'
],
environment: [
'BARE_OS_BARE_MODULES — set to 0 or false to disable ctx.bare (hardened sessions).',
'BARE_OS_BARE_DRIVE_BUNDLES — set to 0 or false to skip loading /lib/bare/bundles/*.js into ctx.bare.'
],
seeAlso: [{ name: 'bare-os-developer-guide', section: 7 }],
bareOsNotes:
'See developer-guide/05-modules-and-imports.md and 12-bare-modules-and-pear-ecosystem.md.',
examples: []
}
}
function bareCronPage() {
return {
name: 'bare-cron',
section: 1,
title: 'Bare OS minute scheduler (bare-initd unit)',
synopsis: [
'Managed via systemctl(1): systemctl status bare-cron',
'Crontab files: /etc/bare-os/crontab, ~/.crontab, ~/.config/bare-os/timers/*.timer'
],
description:
'The **bare-cron** bare-initd unit runs a bounded in-process scheduler: classic five-field lines, **@reboot**, optional **JitterSec=**, and systemd-inspired timer drop-ins (**OnCalendar=**, **EveryMs=**, **OnInactiveSec=**, **Persistent=**). Jobs execute through **ctx.execLine**; errors may be logged under **/var/log/bare-os/cron.log** when configured. This is not full **cron**(8) or **systemd.timer**(5) parity.',
options: [],
keywords: ['cron', 'scheduler', 'bare-initd', 'timer', 'crontab'],
seeAlso: [
{ name: 'systemctl', section: 1 },
{ name: 'crontab', section: 1 }
],
bareOsNotes:
'Implementation: packages/bare-os-booter/lib/bare-cron.js. Dependency: **kernel-logger** before **bare-cron** in the default initd graph.',
examples: [
{ caption: 'list scheduler unit', code: 'systemctl status bare-cron' },
{
caption: 'user crontab line (five-field)',
code: '0 * * * * echo hourly'
}
]
}
}
function systemctlPage() {
return {
name: 'systemctl',
section: 1,
title: 'bare-initd service control (systemd-like subset)',
synopsis: [
'systemctl list|list-units',
'systemctl status [UNIT] [--lines N]',
'systemctl logs UNIT [--lines N]',
'systemctl start|stop|restart UNIT',
'systemctl enable|disable UNIT',
'systemctl is-enabled UNIT',
'systemctl is-active UNIT',
'journalctl -u UNIT [--lines N]'
],
description:
'Lists and manages session-scoped bare-initd units (kernel-logger, bare-cron, …). Implemented by the booter (kernel-runner); /bin stubs exist for PATH and man(1). enable/disable toggle the personal-drive preset file ~/.config/bare-os/initd/disabled.txt for future boots in the same image. is-enabled reports enabled or disabled; is-active reports active vs inactive from runtime phase (exit 0 vs 3). Logs live under /var/log/bare-os/ when the unit defines a logPath. The legacy name bare-initctl is still accepted by the booter as an alias.',
options: [
{
flag: '--lines N',
meaning: 'Tail N lines from the unit log (status, logs, journalctl)'
}
],
aliases: ['bare-initctl'],
keywords: [
'bare-initd',
'initctl',
'service',
'supervisor',
'cron',
'systemd'
],
bareOsNotes:
'journalctl supports -u UNIT and --lines / -n. Other systemd verbs are unavailable on Bare OS (exit 2).',
seeAlso: [
{ name: 'crontab', section: 1 },
{ name: 'bare-os-shell', section: 1 }
],
examples: [
{ caption: 'list units', code: 'systemctl list-units' },
{ caption: 'restart scheduler', code: 'systemctl restart bare-cron' },
{ caption: 'tail cron errors', code: 'journalctl -u bare-cron --lines 20' }
]
}
}
function sshdConfigPage() {
return {
name: 'sshd_config',
section: 5,
title: 'OpenSSH sshd configuration file (Bare OS subset)',
synopsis: ['/etc/ssh/sshd_config'],
description:
'Bare OS reads a subset of OpenSSH sshd_config directives from the system image. Supported keys include Port, ListenAddress, HostKey (repeatable; tilde expands to $HOME on the personal drive), PasswordAuthentication, PubkeyAuthentication, PermitRootLogin, AllowTcpForwarding, MaxAuthTries, ClientAliveInterval, AuthorizedKeysFile (relative paths resolve under $HOME), and Subsystem sftp. Unsupported lines are ignored. Strong ciphers default to bare-ssh2 stock algorithm lists.',
options: [],
keywords: ['ssh', 'sshd', 'config', 'security'],
bareOsNotes:
'HostKey paths must be writable; the stock config places keys under ~/.config/bare-os/ssh/host/.',
seeAlso: [
{ name: 'sshd', section: 8 },
{ name: 'man', section: 1 }
]
}
}
function shellPage() {
return {
name: 'bare-os-shell',
section: 1,
title: 'Bare OS interactive shell (Issue 7inspired subset)',
synopsis: [
'# Interactive session: builtins + /bin via ctx.execLine (see handbook §9)',
'# /bin/sh is a separate script runner — see man sh'
],
description:
'The interactive shell runs in the booter: tokenization, pipelines (simulated capture), redirection, AND-OR lists (; && ||), bounded compound commands (if/fi, while/for/case), background jobs (&), optional command substitution ($(…)) when BARE_OS_SHELL_CMDSUBST=1, globbing, and subsets of errexit (-e), nounset (-u), and pipefail. There are no forked subshells and no full POSIX sh grammar. Canonical narrative: handbook ch.9; completion/REPL: docs/reference/shell-completion-and-repl-editor.md.',
options: [],
aliases: ['sh-builtins'],
keywords: [
'shell',
'builtin',
'pipeline',
'jobs',
'execLine',
'bare-os-shell',
'sh-builtins'
],
builtins: [
{
name: 'alias',
synopsis: ['alias', 'alias name=value ...', 'unalias name ...'],
description:
'Define or list command aliases; unalias removes definitions.'
},
{
name: 'cd',
synopsis: ['cd [DIR]'],
description: 'Change working directory via vfs.chdir; default is HOME.'
},
{
name: 'export',
synopsis: ['export NAME=value ...'],
description:
'Set environment variables visible to child /bin invocations.'
},
{
name: 'unset',
synopsis: ['unset NAME ...'],
description: 'Remove variables; readonly names cannot be unset.'
},
{
name: 'readonly',
synopsis: ['readonly NAME[=value] ...'],
description: 'Mark variables read-only.'
},
{
name: 'umask',
synopsis: ['umask [octal]'],
description:
'Show or set shell file creation mask (stored in env UMASK).'
},
{
name: 'set',
synopsis: [
'set -o',
'set +o',
'set -e | +e | -u | +u | -f | +f',
'set -o errexit|nounset|pipefail',
'set +o errexit|nounset|pipefail'
],
description:
'Toggle errexit (BARE_OS_SHELL_ERREXIT), nounset (BARE_OS_SHELL_NOUNSET), pipefail (BARE_OS_SHELL_PIPEFAIL), noglob (BARE_OS_SHELL_NOGLOB). Use set -o / set +o alone to print current shell options (subset).'
},
{
name: 'command',
synopsis: ['command -v|-V NAME', 'command ARGV...'],
description: 'Resolve or run a command; -v/-V skip aliases.'
},
{
name: 'type',
synopsis: ['type NAME'],
description: 'Report whether NAME is a builtin or a path under PATH.'
},
{
name: 'jobs',
synopsis: ['jobs [-l] [-p]'],
description:
'List logical background jobs. -p prints pgid only; -l includes pgid/sid in the listing.'
},
{
name: 'fg / bg / wait',
synopsis: [
'fg [%job]',
'bg [%job]',
'wait [n | %n]',
'wait -n (with BARE_OS_SHELL_POSIX_MODE=1)'
],
description:
'Cooperative job control: fg awaits a job; bg resumes stopped jobs; wait waits for jobs by id or all.'
},
{
name: 'suspend-job',
synopsis: ['suspend-job [%job]'],
description:
'Mark a running background job stopped (logical); resume with fg or bg.'
},
{
name: 'disown',
synopsis: ['disown [%job]'],
description:
'Remove a job from the jobs table without cancelling its async work (still runs to completion).'
},
{
name: 'trap',
synopsis: ['trap -l', 'trap -p', 'trap CMD SIGNAL'],
description:
'List signals, print handlers, or register synthetic trap handlers (ctx.shellTrapHandlers).'
},
{
name: 'login / logout',
synopsis: ['login [--new]', 'logout [--save]'],
description:
'login is a /bin utility: run it with no passphrase on the command line, then type the passphrase at the TTY prompt (hidden). logout remains a shell builtin for session teardown; both require booter hooks.'
},
{
name: ':',
synopsis: [':'],
description: 'No-op builtin.'
},
{
name: 'exit',
synopsis: ['exit [n]'],
description: 'Request booter exit with status n (builtin path).'
},
{
name: 'read',
synopsis: ['read [-r] [NAME ...]'],
description:
'Optional when BARE_OS_SHELL_READ_BUILTIN=1; bounded line from shell stdin or readLine.'
}
],
seeAlso: [
{ name: 'sh', section: 1 },
{ name: 'help', section: 1 },
{ name: 'man', section: 1 }
],
bareOsNotes:
'Pipelines use simulated capture (not OS pipes). kill and wait accept %n job specs when shellBackgroundJobs is populated. Full UX (history file, tab menu, Ctrl+R) uses BARE_OS_FISH≠0 on a TTY; see shell-completion-and-repl-editor.md.',
examples: [
{ caption: 'pipeline (simulated)', code: 'ls -1 /bin | grep man' },
{
caption: 'errexit + compound',
code: 'set -e\nif true; then echo ok; fi'
},
{ caption: 'background job', code: 'sleep 1 &\njobs' },
{ caption: 'redirect out', code: 'echo hi > ~/hello.txt' },
{ caption: 'alias + use', code: "alias ll='ls -la'\nll ~" }
]
}
}
async function main() {
await mkdir(pagesDir, { recursive: true })
for (const name of COREUTILS_COMMANDS) {
const p = basePage(name)
await writeFile(
join(pagesDir, `${name}.json`),
JSON.stringify(p, null, 2) + '\n'
)
}
for (const name of MAN_EXTRA_PAGES) {
const p =
name === 'git'
? gitPage()
: name === 'curl'
? curlPage()
: name === 'wget'
? wgetPage()
: name === 'bare-cron'
? bareCronPage()
: name === 'bare-os-ctx-bare'
? ctxBarePage()
: name === 'systemctl'
? systemctlPage()
: name === 'sshd_config'
? sshdConfigPage()
: name === 'bare-os-shell'
? shellPage()
: (() => {
throw new Error(
`seed-man-pages: unknown MAN_EXTRA_PAGES entry: ${name}`
)
})()
await writeFile(
join(pagesDir, `${name}.json`),
JSON.stringify(p, null, 2) + '\n'
)
}
}
await main()