Phase 4 of plans/exit.md: the aux/terminal sub-entrypoints. pkg/auxents and
pkg/terminals are now os.Exit-free; even the dispatchers return exit codes
instead of exiting.
- auxents.Dispatch returns (handled bool, exitCode int); entrypoint.Main --
the one sanctioned exit point -- exits with the code.
- terminals.Dispatch returns an exit code; the climain caller wraps it in a
lib.ExitRequest, which also retires the 'terminal did not exit the process'
panic.
- Usage functions (hex, unhex, lecat, termcvt, repl, script, regtest) no
longer take an exitCode parameter and exit; call sites print usage and
return the code explicitly.
- Inner I/O helpers (hexDumpFile, unhexFile, lecatFile, termcvtFile) return
errors; each sub-main prints 'mlr {verb}: ...' as before and returns 1.
lecatFile formerly looped forever on a non-EOF read error; it now returns
the error.
- The regtest directory walk (Execute / executeSinglePath /
executeSingleDirectory / hasCaseSubdirectories) plumbs errors up to
RegTestMain; regression_test.go updated for the new Execute signature.
Stderr messages and exit codes are unchanged across mlr aux-list, hex, unhex,
lecat, termcvt, help, version, repl, script, and regtest surfaces (checked by
hand); all 4779 regression cases pass; make lint is clean; docs rebuild with
zero churn.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Plan: flesh out PR7 (MCP server + Agent Skill) design
stdio transport (no HTTP port), mlr mcp terminal in the main binary,
SDK-vs-handroll decision, tool list, in-process vs subprocess split,
run-tool safety (--no-shell prerequisite), single-sourced skill, tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Add mlr mcp: MCP server + agent playbook; --no-shell gate (#2098 PR7)
New terminal `mlr mcp` runs a Model Context Protocol server over stdio
(spawned by MCP clients; no network port), exposing five tools --
list_capabilities, which, validate_dsl, describe_data, run -- plus an
agent playbook as MCP prompt/resource. Catalog tools are served
in-process from the help registries; the rest subprocess this same
binary with MLR_ERRORS_JSON=1, a timeout, and an output cap.
Prerequisite: a new --no-shell flag / MLR_NO_SHELL env var (one-way
gate) disables the DSL system/exec functions, piped redirects, and
--prepipe/--prepipex; the MCP server sets it on the commands it runs
unless started with --allow-shell.
Adds the github.com/modelcontextprotocol/go-sdk dependency.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Force LF checkout for the embedded SKILL.md (Windows CI fix)
go:embed embeds checkout bytes, so a CRLF checkout on Windows made the
embedded playbook differ per platform and failed
TestPlaybookHasFrontmatter. Pin the file to eol=lf in .gitattributes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Move no-shell test DSL into per-case mlr files (Windows CI fix)
Inline single-quoted DSL in cmd files is mangled by the Windows shell
(single quotes are not quote characters there); the harness's
put -f ${CASEDIR}/mlr pattern avoids shell quoting entirely.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Add JSON index and mlr which capability router (#2098)
PR 2 of the AI-friendly roadmap (plans/plan-2098-llm.md):
- `mlr help --as-json --index` emits a lightweight [{kind,name,summary}]
index across all 651 catalog items (verbs, functions, flags, keywords),
sorted by kind then name. Agents use this as a cheap first call to pick
a verb before fetching its full entry.
- `mlr which "<query>"` is a new terminal that tokenizes a natural-language
query, scores every catalog item (name match +20/token, body match +5/token),
and returns ranked JSON [{kind,name,score,summary}]. Exit code 0 means a
confident match (at least one token hit the item name); exit code 2 means
low confidence. Agents branch on the exit code rather than parsing prose.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* Move mlr which into pkg/terminals/help, deduplicate firstLine
pkg/terminals/which/ was a misplaced package: it imported the same four
catalog registries as pkg/terminals/help/ and duplicated the firstLine
helper. Moving the logic into help/entry_which.go fixes both issues:
- WhichMain and all which helpers now live alongside the other --as-json
catalog machinery in pkg/terminals/help/
- indexFirstLine (entry_json.go) and firstLine (which/entry.go) collapse
into a single firstLine shared by both files
- pkg/terminals/terminals.go calls help.WhichMain directly; the
pkg/terminals/which/ package is deleted
No behavior change.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* Fix five Go-purity issues found in code review
1. Exit-code false positive: whichScore now returns (int, bool) where the
bool records whether any token hit the item name. WhichMain uses
results[0].nameHit for exit-code 0, so 4 body-only token hits (4×5=20)
no longer incorrectly signal a confident match.
2. Flag Summary inconsistency: whichSearch was setting Summary: fl.Help
directly for flags while using firstLine(...) for functions and keywords.
Changed to firstLine(fl.Help) so all four kinds behave consistently.
3+5. kindOrder/whichKindRank duplication: the verb<function<flag<keyword
ordering was encoded twice — as a local map[string]int in buildIndex and
as a switch in whichKindRank. Replaced both with a single package-level
kindRank() function. The map lookup also silently returned 0 (= verb rank)
for unknown kinds; the switch correctly returns 4 (sorts last).
4. extractIndexFlag/extractAsJSONFlag duplication: both had identical loop
bodies differing only in the sentinel string. Introduced a generic
extractFlag(args, flag) helper; both are now one-liners.
Also promoted whichStopwords to a package-level var so whichTokenize does
not allocate a new map on every call.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* initial attempt
* fix bash
* fix zsh
* Add shell-completion docs page
Documents the new 'mlr completion {bash,zsh}' feature: the then-chain
context model, install instructions for bash and zsh (including the macOS
bash-3.2 'eval' caveat and zsh compinit self-init), and examples of
context-aware completion. Added to the nav under "Miller in more detail".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Add enum value completion for format and separator flags
Completes the argument value for arg-taking main flags whose values are a
known set: file-format names for -i/-o/--io, separator aliases for
--ifs/--ofs/--ips/etc., and regex-separator aliases for --ifs-regex/--ips-regex.
Other arg-taking flags continue to fall back to filename completion.
Candidate sets come from new cli getters (GetFileFormatNames,
GetSeparatorAliasNames, GetSeparatorRegexAliasNames) that read the same maps
Miller uses at runtime, so there is no separate list to keep in sync. The
command-line walk now records which flag a value position belongs to.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Include format-conversion keystroke-savers in bare-dash completion
Reverts the suppression of --c2j/--x2y-style flags from 'mlr -<TAB>'. The full
set of main flags (297) is now offered, matching what is valid on the command
line. GetFlagNames no longer takes an includeSuppressed argument.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Complete terminal subcommands and top-level help/version flags
'mlr <TAB>' now offers subcommand names (help, version, repl, regtest, script,
completion, terminal-list) alongside verb names, and 'mlr -<TAB>' offers the
top-level terminal flags (-h, --help, --version, --bare-version, and the help
shorthands -g/-l/-L/-f/-F/-k/-K). Subcommand names are offered only as the
first non-flag token, where they are valid.
To let the completion engine know these names without an import cycle
(pkg/terminals imports pkg/terminals/completion), the canonical terminal names
and version-flag spellings are factored into a new leaf package
pkg/terminals/registry, imported by pkg/terminals, pkg/climain, and completion.
The help-flag spellings come from a new help.GetTerminalFlagNames derived from
the existing shorthand table, so nothing drifts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Complete 'mlr help' topics and topic arguments
'mlr help <TAB>' now completes help topics (flags, verb, function, keyword,
list-verbs, ...), and topics that take a name argument complete it too:
'mlr help verb <TAB>' -> verb names, 'mlr help function <TAB>' -> function
names, 'mlr help keyword <TAB>' -> keyword names, 'mlr help flag <TAB>' ->
flag names. 'mlr completion <TAB>' completes bash/zsh.
A terminal subcommand consumes the rest of the command line, so the walk now
returns a ctxTerminalArgs context carrying the terminal name and the words
typed after it. New getters supply the candidate names without drift:
help.GetTopicNames, help.GetFunctionNames/GetKeywordNames (wrapping new
cst.BuiltinFunctionManager.GetBuiltinFunctionNames and cst.GetKeywordNames).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs-neaten
* Move flag-value-candidate logic into pkg/cli; fix verb-flag collision
The mapping of which flags take a format/separator/regex-separator argument is
flag metadata, so it now lives with the flags in pkg/cli as
cli.FlagValueCandidates, alongside the existing GetFileFormatNames /
GetSeparatorAliasNames getters, replacing the maps that were in
pkg/terminals/completion/value_completion.go (now removed).
This also fixes a bug: value completion now applies only to main flags, not to
identically-spelled verb flags. Previously 'mlr uniq -o <TAB>' offered file
formats because uniq's -o (an output field name) collided with the main -o
format flag; it now correctly falls back to filename completion.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>