1128 lines
41 KiB
JavaScript
1128 lines
41 KiB
JavaScript
/**
|
||
* 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/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/engines/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/engines/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 40–200); 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/engines/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/ctx/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/initd/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 7–inspired 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()
|