Commit graph

9326 commits

Author SHA1 Message Date
John Kerl
07daa6fe03 docs/src/release-docs.md.in 2026-07-04 15:46:33 -04:00
John Kerl
d5e6ceddc9 docs: Miller 6.20.2 Documentation site_name 2026-07-04 15:35:09 -04:00
John Kerl
05190f3bda fix timing issue in tools/release.sh preflight step 2026-07-04 15:18:18 -04:00
John Kerl
f5a799f630 Prepare 6.20.2 release 2026-07-04 14:59:19 -04:00
John Kerl
394f4774df 6.20.1-dev 2026-07-04 14:56:25 -04:00
John Kerl
5222f9beea glossary entries for AI 2026-07-04 14:51:03 -04:00
John Kerl
54237c04d6
More AI skill/MCP docs (#2140)
* Iterating on AI/MCP docs

* docs iterate

* mlr skill

* docs iterate

* agent-skill.md.in

* docs iterate

* docs iterate

* edits

* codex/gemini info
2026-07-04 14:45:29 -04:00
John Kerl
f87bb37194
Update to MCP docs (#2139) 2026-07-04 10:17:48 -04:00
John Kerl
12131ea755
Miller 6.20.1 (#2138)
* Miller 6.20.1

* make dev
2026-07-04 09:59:15 -04:00
John Kerl
3682077d32
tools/release.sh: fix idempotency gaps in branch checks, SRPM reuse, release notes (#2136) 2026-07-03 20:56:51 -04:00
John Kerl
486f013870 Post-6.20.0 release: back to 6.20.0-dev 2026-07-03 20:55:25 -04:00
John Kerl
9a1c49be76 Prepare 6.20.0 release 2026-07-03 20:39:31 -04:00
John Kerl
a9de5824ba
docs: add "Miller and AI" page (#2098) (#2134)
* docs: add "Miller and AI agents" quick-start page (#2098)

Umbrella page for the AI-friendly feature stack: one-line MCP setup as
the fast path, plus the plain-CLI path (which, help --as-json,
describe, --explain, --errors-json, --no-shell) with live CI-tested
examples, and the discover -> constrain -> validate -> run loop.
Cross-linked with the MCP server page; listed under Getting started.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: reframe AI page as "Miller and AI" (#2098)

Rename ai-agents.md to ai.md and restructure around the pre-MCP
feature stack, organized as the loop each feature serves: Discover
(catalog/index/which, cache keys, single-sourced usage text),
Constrain (enum value-sets + describe: tool shape vs data shape),
Validate (--explain), Run and recover (--errors-json, --no-shell,
env-var trio). MCP is now one closing section pointing at the
mcp-server.md detail page. All examples are live and CI-tested,
including Miller querying its own catalog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: retitle MCP page to "The MCP server" under the Miller-and-AI umbrella

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: add bare-minimum getting-started section to Miller-and-AI page

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: AI features land in Miller 6.20

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: hyperlink SKILL.md references to the repo

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: rename section to 'The essentials'

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 20:31:20 -04:00
John Kerl
41f5188bd0
Add mlr mcp MCP server + agent playbook, with a --no-shell gate (#2098 PR7) (#2133)
* 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>
2026-07-03 19:41:49 -04:00
John Kerl
d415ca7655
Add mlr describe schema/shape introspection verb (#2098 PR6) (#2132)
One output record per input field: types seen with counts, occurrence
count, null count, cardinality, min/max, and -- for fields within the
-n/--max-values cap -- the complete distinct-value list in first-seen
order. `mlr --ojson describe` is the machine-readable form; nested
types/values flatten in tabular formats.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 18:43:49 -04:00
John Kerl
7f60e7da57
Add DSL validate/dry-run: put/filter --explain (#2098 PR5) (#2131)
Lets an agent type-check a DSL expression before spending a full input
pass. `mlr put --explain '...'` (and filter) runs the existing
parse -> ValidateAST -> CST build -> Resolve path, then:

- valid: prints "mlr {put,filter}: DSL expression is valid." and exits 0
- invalid: returns the build error up the normal path, so --errors-json
  emits a structured document; exits 1
- -W with fatal warnings: reports and exits 1

The gate lives in the pass-two constructor, before any input file is
opened, so no input stream is read (verified with a nonexistent input
file still validating OK).

Also categorize bare "parse error: ..." messages from the DSL parser as
kind "dsl-parse-error" rather than "generic" (climain/errors_json.go),
so --explain --errors-json gives an agent a useful error kind. The CSV
reader's "parse error on line ..." is stream-time and never reaches this
command-line-parse categorizer.

Tests: dsl-explain/0001-0004 regression cases (valid put/filter, invalid
plain, invalid --errors-json) and categorize unit tests. Regenerated
verb docs, manpage, and the help usage-verbs golden case.

The older -X ("exit after parsing") still exits 0 even on a parse error;
left as-is since --explain is the correct validation path.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 18:12:23 -04:00
John Kerl
78ed1563db
Add --errors-json structured error output (#2098) (#2113)
* Tier-2 structured verb options: OptionSpec, initial migration (#2098)

PR 3 of the AI-friendly roadmap (plans/plan-2098-llm.md).

Infrastructure:
- Add OptionSpec{Flag,Arg,Type,Desc,Repeatable,Values} to
  pkg/transformers/aaa_record_transformer.go alongside TransformerSetup.
  Type is one of: bool, string, int, float, csv-list, regex, filename,
  format, enum. For type=="enum", Values lists the valid choices.
- Add Options []OptionSpec to TransformerSetup (nil = not yet migrated).
- Emit Options in VerbInfoForJSON (omitempty so unmigrated verbs stay
  backward-compatible; agents check key presence for Tier-2 availability).
  UsageText is always present as the Tier-1 prose fallback.
- Add VerbOptionsNilCheck() in aaa_verb_options_check.go: progress report
  of migrated vs. unmigrated verbs, analogous to FLAG_TABLE.NilCheck().
- Wire verb-options-nil-check into mlr help (internal/docgen section).

Initial migration (5/70 verbs):
- nothing: empty Options (no verb-specific options, explicitly migrated)
- cat: -n (bool), -N (string), -g (csv-list), --filename, --filenum (bool)
- head: -g (csv-list), -n (int)
- tail: -g (csv-list), -n (int)
- tee: -a, -p (bool)

Tests:
- 5 new unit tests in aaa_transformer_json_test.go covering migrated/
  unmigrated paths, field population, JSON round-trip, and key-presence.
- Regression test case 0003: mlr help verb-options-nil-check golden output.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* Migrate all 70 verbs to structured OptionSpec; bump catalog schema to v2

Completes the Tier-2 migration started in the previous commit. Every verb
in TRANSFORMER_LOOKUP_TABLE now has a non-nil Options field.

- Workflow-migrated all 65 remaining verbs. Each Setup var now carries
  Options: []OptionSpec{...} with Flag/Arg/Type/Desc fields. Verbs with
  no verb-specific options (altkv, check, group-like, nothing, etc.) use
  an empty slice to signal "migrated but no options."
- Drop `omitempty` from VerbInfoForJSON.Options: empty slices were silently
  dropped, making migrated-no-option verbs indistinguishable from unmigrated
  ones in JSON. Without omitempty: null=unmigrated, []=migrated-no-options,
  [...]= migrated-with-options. Bump catalogSchemaVersion 1→2 for this shape
  change.
- Replace the two "unmigrated-verb" unit tests (which used stats1 as an
  example) with TestAllVerbsFullyMigrated (asserts every verb has non-nil
  Options) and TestAllVerbsHaveOptionsKeyInJSON (asserts every migrated
  verb emits the "options" key in JSON).
- Regenerate test/cases/cli-help/0003/expout: now reads
  "Verb options migration: 70/70 migrated."

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* Add --errors-json structured error output (#2098)

PR 4 of the AI-friendly roadmap (plans/plan-2098-llm.md).

Agents previously had to regex-match English prose to branch on error
kind; this PR lets them do it structurally.

Interface:
- mlr --errors-json <bad command> emits a JSON object to stderr and
  exits 1; same behavior as prose path but machine-readable.
- MLR_ERRORS_JSON=1 (truthy) is the env-var equivalent.
- Without the flag, prose output is byte-for-byte unchanged.

JSON shape: {error, kind, token, verb, hint, did_you_mean[]}
Error kinds: unknown-verb, unknown-flag, verb-option-error, generic.

Implementation:
- New pkg/climain/errors_json.go: CLIError typed error, StructuredError
  DTO, WantErrorsJSON pre-scan, Levenshtein edit distance, topMatches,
  EmitStructuredError.
- Convert two direct os.Exit sites in parseCommandLinePassOne (unknown
  verb, unknown flag) to return CLIError values; verb-option-error
  likewise returns CLIError from pass-one ParseCLIFunc handling.
- parseCommandLinePassOne gains an error return; ParseCommandLine
  propagates it.
- entrypoint.go pre-scans os.Args for --errors-json before calling
  ParseCommandLine; routes errors to EmitStructuredError or printError.
- did_you_mean: Levenshtein nearest-match over verb catalog, flag
  catalog, or the verb own OptionSpec flags (PR3 catalog) for
  verb-option-error. Closes the self-correction loop the catalog
  enables.
- --errors-json registered in Miscellaneous flags so it appears in
  mlr --help and is not treated as an unrecognized flag.

Tests: 16 unit tests covering Levenshtein, topMatches, threshold,
WantErrorsJSON, CLIError interface, and all categorize paths.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-07-03 14:49:48 -04:00
John Kerl
f637633420
Tier-2 structured verb options: OptionSpec, initial migration (#2098) (#2111)
* Tier-2 structured verb options: OptionSpec, initial migration (#2098)

PR 3 of the AI-friendly roadmap (plans/plan-2098-llm.md).

Infrastructure:
- Add OptionSpec{Flag,Arg,Type,Desc,Repeatable,Values} to
  pkg/transformers/aaa_record_transformer.go alongside TransformerSetup.
  Type is one of: bool, string, int, float, csv-list, regex, filename,
  format, enum. For type=="enum", Values lists the valid choices.
- Add Options []OptionSpec to TransformerSetup (nil = not yet migrated).
- Emit Options in VerbInfoForJSON (omitempty so unmigrated verbs stay
  backward-compatible; agents check key presence for Tier-2 availability).
  UsageText is always present as the Tier-1 prose fallback.
- Add VerbOptionsNilCheck() in aaa_verb_options_check.go: progress report
  of migrated vs. unmigrated verbs, analogous to FLAG_TABLE.NilCheck().
- Wire verb-options-nil-check into mlr help (internal/docgen section).

Initial migration (5/70 verbs):
- nothing: empty Options (no verb-specific options, explicitly migrated)
- cat: -n (bool), -N (string), -g (csv-list), --filename, --filenum (bool)
- head: -g (csv-list), -n (int)
- tail: -g (csv-list), -n (int)
- tee: -a, -p (bool)

Tests:
- 5 new unit tests in aaa_transformer_json_test.go covering migrated/
  unmigrated paths, field population, JSON round-trip, and key-presence.
- Regression test case 0003: mlr help verb-options-nil-check golden output.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* Migrate all 70 verbs to structured OptionSpec; bump catalog schema to v2

Completes the Tier-2 migration started in the previous commit. Every verb
in TRANSFORMER_LOOKUP_TABLE now has a non-nil Options field.

- Workflow-migrated all 65 remaining verbs. Each Setup var now carries
  Options: []OptionSpec{...} with Flag/Arg/Type/Desc fields. Verbs with
  no verb-specific options (altkv, check, group-like, nothing, etc.) use
  an empty slice to signal "migrated but no options."
- Drop `omitempty` from VerbInfoForJSON.Options: empty slices were silently
  dropped, making migrated-no-option verbs indistinguishable from unmigrated
  ones in JSON. Without omitempty: null=unmigrated, []=migrated-no-options,
  [...]= migrated-with-options. Bump catalogSchemaVersion 1→2 for this shape
  change.
- Replace the two "unmigrated-verb" unit tests (which used stats1 as an
  example) with TestAllVerbsFullyMigrated (asserts every verb has non-nil
  Options) and TestAllVerbsHaveOptionsKeyInJSON (asserts every migrated
  verb emits the "options" key in JSON).
- Regenerate test/cases/cli-help/0003/expout: now reads
  "Verb options migration: 70/70 migrated."

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* remove a transitional helper

* git rms

* Render verb usage Options blocks from structured OptionSpec

Each verb's usage message and its Tier-2 OptionSpec list previously
duplicated the option text. New WriteVerbOptions (aaa_verb_usage.go)
renders the "Options:" block from the specs: aligned flag column,
descriptions word-wrapped at 80, uniform trailing -h|--help line.

- OptionSpec gains Aliases (JSON "aliases") so long-form spellings
  like join's --lk|--left-keep-field-names survive in both outputs
- All 70 verbs migrated; options literals hoisted to package-level
  vars (usage funcs can't reference their Setup var without a Go
  init cycle)
- Hand-written per-option details the specs had condensed away are
  merged into Desc, enriching the JSON catalog
- Non-option prose (examples, cross-references, dynamic accumulator
  listings) kept verbatim
- Regenerated the six usage-embedding regression expectations and
  the two affected doc pages

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix pre-existing usage-text bugs surfaced by the OptionSpec migration

- gap: usage said "One of -f or -g is required" but the parser takes
  -n or -g
- seqgen: drop description line copy-pasted from cat ("Passes input
  records directly to output...") which contradicted "Discards the
  input record stream"
- utf8-to-latin1: description read inverted ("from Latin-1 to UTF-8")
- sec2gmtdate: usage said "../c/mlr" instead of "mlr"
- top: document the accepted-but-undocumented --max flag
- stats2: add linreg-pca to the -a enum values, matching the runtime
  accumulator table

Regression expectations and docs regenerated accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix check usage sentence order; stats1 usage blank line to usage stream

- check: the description's second and third lines were swapped,
  reading "Consumes records without printing any output, / Useful for
  doing a well-formatted check on input data. / with the exception
  that warnings are printed to stderr."
- stats1: a bare fmt.Println() in the usage func wrote its blank line
  to process stdout instead of the usage output stream

Regression expectation and docs regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-07-03 14:27:23 -04:00
John Kerl
12c96298b9
Add a first-class bytes type to the DSL, with b"..." literals and base64/hex codecs (#2122)
* Add MT_BYTES mlrval type: foundation and disposition tables

First step toward a first-class bytes type in the DSL (#1231).
Adds MT_BYTES (payload []byte, rendered as lowercase hex in all output
formats, JSON-encoded as a hex string), extends every disposition
matrix/vector with the new row/column -- real cells for comparison,
sorting, and dot-concat of bytes with bytes; type-error stubs
elsewhere -- and adds sweep tests asserting no table has nil cells,
since Go zero-fills short array literals when MT_DIM grows.

Bytes values are not yet constructible from the DSL; b"..." literals
and constructor/codec functions follow in subsequent commits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Add b"..." bytes-literal syntax to the DSL

Adds a bytes_literal token to the grammar (regenerating the PGPG lexer
and parser) and a BytesLiteralNode in the CST which evaluates to an
MT_BYTES mlrval. Escape handling reuses UnbackslashStringLiteral,
which is already byte-oriented: b"\xff" is the single byte 0xff.
Unlike string literals, bytes literals never participate in
regex-capture replacement. A bare identifier b is unaffected.

Part of #1231.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Add bytes DSL functions: conversions, codecs, and bytes-aware built-ins

- bytes(x) converts strings to bytes; string(b) reinterprets raw bytes
  as UTF-8 text (the reverse)
- base64_decode now always returns bytes (superseding the interim
  string-or-hex behavior); base64_encode accepts string or bytes
- New hex_encode/hex_decode functions
- is_bytes and asserting_bytes predicates
- md5/sha1/sha256/sha512 accept bytes, hashing the raw payload
- strlen of bytes is the byte count; substr/substr0/substr1 on bytes
  slice by byte position and return bytes

The Cyrillic-LDAP scenario from #1231 now works without exec
workarounds: string(base64_decode($x)) recovers the text, and binary
payloads survive undamaged as bytes.

Closes #1231.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Add bytes-type docs and regression cases

Documents the bytes type on the data-types page, regenerates the
function-reference/man-page material, and adds regression coverage:
literal escape forms, operators (concat/compare/slice/sort and
type errors), conversions and codec round-trips, and CSV-to-JSON
output rendering of bytes fields.

Part of #1231.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Reposition MT_BYTES to sort adjacent to MT_STRING in the type enum

MT_BYTES was appended after MT_ABSENT for index stability; move it
right after MT_STRING instead, since that's where it conceptually
belongs and where it already sorts in the cmp disposition matrices.
Mechanically re-derive all ~40 disposition tables in pkg/bifs and
pkg/mlrval accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix windows CI

* fix merge

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 11:58:44 -04:00
John Kerl
91eaff1341
Lint round 5+6: staticcheck and errcheck to zero (#2130)
* refine the plan

* Fix all staticcheck lint findings (uncapped)

golangci-lint's default max-same-issues=3 was hiding most of the backlog:
the true pre-fix count was 69 staticcheck findings, not 34. This fixes all
of them, driving staticcheck to zero:

- ST1023/QF1011 (37): omit explicit types inferred from the RHS
- S1009/S1031 (15): drop redundant nil checks before len()/range
- SA9003 (9): remove comment-only empty branches, keeping the comments
- QF1007 (3): merge conditional assignment into declaration
- QF1006 (3): lift break conditions into loop conditions
- QF1001 (3): apply De Morgan's law / name the negated predicate

Also updates plans/lintfixes.md with the cap discovery and the corrected
errcheck picture (1202 uncapped, ~949 of them fmt.Fprint*).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Drive errcheck to zero: config for bulk categories, propagate real errors

Adds .golangci.yml with errcheck exclude-functions for fmt.Fprint* (usage
printers), (*bufio.Writer).Write/WriteString (sticky errors, surfaced at the
now-checked final Flush), and (*strings.Builder).WriteString; pins
max-issues-per-linter/max-same-issues to 0 so CI reports true counts.

Real error paths now propagate instead of being dropped:
- Finalize{Reader,Writer}Options in join/put/filter/split/tee and the
  repl/script entry points: 'mlr join -i badformat' now errors instead of
  silently using wrong separators
- final output-stream Flush in pkg/stream: write failure no longer exits 0
- DSL emit/print/dump redirect writes, matching their sibling branches
- CSV writer WriteCSVRecordMaybeColorized, close-time Flush in file output
  handlers, ENV[...] Setenv, REPL record-write and redirect-close errors
- termcvt write-side Close before rename (had "TODO: check return status")

The rest are deliberate ignores, marked with _ = and a comment where the
reason isn't obvious: unset-of-missing-path no-ops, read-side closes,
mid-stream FlushOnEveryRecord, init-time strftime registrations, in-memory
usage-capture pipes, and regtest-harness env/temp-file teardown.

golangci-lint now reports 0 issues on ./cmd/mlr ./pkg/... with all caps off.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 11:42:08 -04:00
John Kerl
2bec10fc54
Fix govet lint findings; fix masked unset-on-array error path (#2129)
* plans/lintfixes.md

* plans/lintfixes.md

* Fix remaining govet lint findings

- Rename MarshalJSON -> FormatAsJSON on Mlrval and Mlrmap (govet
  stdmethods): the methods shadowed json.Marshaler with an
  incompatible signature.
- Remove unreachable return after exhaustive if-else in
  pkg/mlrval/mlrval_collections.go (govet unreachable).
- Update plans/lintfixes.md with current status: 84 findings remain
  (50 errcheck, 34 staticcheck).

Part of #2109.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Return nil on successful single-index array unset

removeIndexedOnArray removed the element on the in-bounds path but
then fell through to return an "array index out of bounds for unset"
error, so the success path never returned nil. Callers currently
ignore the error, which masked this; return nil on success so that
upcoming errcheck fixes can propagate the error meaningfully. This
matches removeIndexedOnMap, which returns nil on success.

Add unit tests for RemoveIndexed on arrays.

Part of #2109.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:31:08 -04:00
John Kerl
7fa7b1914f typofix 2026-07-03 10:22:31 -04:00
John Kerl
f4d365bbde
Page-refactor for CSV/JSON troubleshooting (#2128)
* new troubleshooting-csv-and-json-input.md.in page

* ../README-docs.md

* ../README-docs.md
2026-07-03 10:19:09 -04:00
Kral
e682484a2a
docs: add CSV and JSON troubleshooting tips (#2123)
Co-authored-by: John Kerl <kerl.john.r@gmail.com>
2026-07-02 20:44:42 -04:00
Theodore Tsirpanis
5eafa1c9f9
Enable windows-arm64 releases. (#2127)
Co-authored-by: John Kerl <kerl.john.r@gmail.com>
2026-07-02 12:16:53 -04:00
dependabot[bot]
324a11f644
Bump github/codeql-action/autobuild from 4.36.2 to 4.36.3 (#2126)
Bumps [github/codeql-action/autobuild](https://github.com/github/codeql-action) from 4.36.2 to 4.36.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](8aad20d150...54f647b7e1)

---
updated-dependencies:
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kerl <kerl.john.r@gmail.com>
2026-07-02 12:15:26 -04:00
dependabot[bot]
afb8943d32
Bump github/codeql-action/analyze from 4.36.2 to 4.36.3 (#2125)
Bumps [github/codeql-action/analyze](https://github.com/github/codeql-action) from 4.36.2 to 4.36.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](8aad20d150...54f647b7e1)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 12:14:57 -04:00
dependabot[bot]
a8bd5bd889
Bump github/codeql-action/init from 4.36.2 to 4.36.3 (#2124)
Bumps [github/codeql-action/init](https://github.com/github/codeql-action) from 4.36.2 to 4.36.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](8aad20d150...54f647b7e1)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 09:10:04 -04:00
John Kerl
b817040747
Strip dead code from pkg/ (#2121)
Found with golang.org/x/tools/cmd/deadcode (rooted at cmd/mlr + tests)
and staticcheck U1000; each finding verified by hand before deletion.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 19:32:13 -04:00
Kral
6d7c3000aa
docs: document time conversion thread safety (#2115)
Co-authored-by: John Kerl <kerl.john.r@gmail.com>
2026-07-01 19:04:09 -04:00
dependabot[bot]
9a02055670
Bump github.com/klauspost/compress from 1.18.7 to 1.19.0 (#2120)
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.18.7 to 1.19.0.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Commits](https://github.com/klauspost/compress/compare/v1.18.7...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-version: 1.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-01 09:33:27 -04:00
John Kerl
e98185f59c
Update snapcore/action-build to node24 SHA, drop unused matrix (#2119)
* Update snapcore/action-build to node24 SHA, drop unused matrix

snapcore/action-build@v1 targets Node.js 20, which is deprecated on
GitHub Actions runners (forced to run on Node.js 24 with a warning).
Upstream has an open PR to update (https://github.com/snapcore/action-build/pull/1)
but it has been stale for a while, so we pin directly to its HEAD SHA
(edf78ca) until upstream merges and cuts a new tag.

Also removes the `strategy.matrix.node-version: [20.x]` block, which
was dead config — there was no `actions/setup-node` step consuming it.

Fixes the warning seen in:
https://github.com/johnkerl/miller/actions/runs/28449033140

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* comment

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-30 13:24:15 -04:00
dependabot[bot]
cf85fff555
Bump goreleaser/goreleaser-action from 7.2.2 to 7.2.3 (#2116)
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 7.2.2 to 7.2.3.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](5daf1e915a...f06c13b6b1)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-version: 7.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-30 09:44:14 -04:00
dependabot[bot]
9e8abbe159
Bump github.com/klauspost/compress from 1.18.6 to 1.18.7 (#2117)
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.18.6 to 1.18.7.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Commits](https://github.com/klauspost/compress/compare/v1.18.6...v1.18.7)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-version: 1.18.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-30 09:43:01 -04:00
dependabot[bot]
f82317480a
Bump golangci/golangci-lint-action from 9.2.1 to 9.3.0 (#2118)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 9.2.1 to 9.3.0.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v9.2.1...v9.3.0)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: 9.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-30 09:42:34 -04:00
dependabot[bot]
c9bac45161
Bump actions/cache from 6.0.0 to 6.1.0 (#2114)
Bumps [actions/cache](https://github.com/actions/cache) from 6.0.0 to 6.1.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](2c8a9bd745...55cc834586)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 09:23:27 -04:00
John Kerl
d56eafff97
Convert if/else-if chains to typed switch statements (staticcheck QF1003) (#2112)
Replaces 100+ if/else-if chains on a single variable with tagged switch
statements across 72 files. The bulk are transformer option-parsing loops
(switch on opt string), plus a handful of value-dispatch sites in mlrval,
dsl/cst, repl, lib, auxents, and bifs. One case (surv.go) required a
labeled break to preserve the loop-exit behavior of the original else branch.

Fixes staticcheck QF1003 findings.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-28 18:27:42 -04:00
John Kerl
b5f5de04a6
Next batch of lint fixes (#2110) 2026-06-28 17:42:34 -04:00
John Kerl
6a357d5df9
Add JSON index and mlr which capability router (#2098) (#2107)
* 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>
2026-06-28 17:40:50 -04:00
John Kerl
7e1c9b4119
Next batch of lint fixes (#2108) 2026-06-28 17:36:36 -04:00
John Kerl
6f1b3958ed
Switch to --as-json (#2106) 2026-06-28 17:04:10 -04:00
John Kerl
2dd94cb181
Add machine-readable help catalog: mlr help --json (#2098) (#2099)
Emit Miller's existing help catalog (verbs, functions, flags, keywords)
as structured JSON so AI agents and tooling can model Miller's surface
without scraping prose. The --json token may appear anywhere on a
`mlr help ...` command line; plain text help is unchanged.

  mlr help --json                  # full catalog
  mlr help verb cat --json         # one or more verbs
  mlr help function splitax --json # one or more functions
  mlr help flag --ifs --json       # one or more flags
  mlr help keyword ENV --json      # one or more keywords

Functions and flags serialize fully (name/class/arity/help/examples;
section/name/alt_names/arg/help). Verbs carry a summary, ignores_input,
and captured raw usage_text as a Tier-1 fallback, since per-verb options
are prose-only today (each verb hand-writes its UsageFunc). Structured
verb options are a planned follow-on (see #2098).

This is a serialization layer over the existing registries -- no
refactor of the text-help path.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:55:54 -04:00
dependabot[bot]
7073be3661
Bump actions/checkout from 6.0.1 to 7.0.0 (#2104)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 7.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v6.0.1...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-26 10:25:32 -04:00
dependabot[bot]
8d2975dc16
Bump actions/setup-go from 6.4.0 to 6.5.0 (#2105)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.4.0 to 6.5.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v6.4.0...924ae3a1cded613372ab5595356fb5720e22ba16)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 6.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-26 09:52:29 -04:00
John Kerl
931c80c728
Add roadmap doc for making Miller AI-friendly (#2098) (#2103)
* Add roadmap doc for making Miller AI-friendly (#2098)

Living roadmap derived from issue #2098 and @aborruso's comment:
PR-by-PR arc from a machine-readable help catalog (mlr help --as-json)
through structured verb options, structured errors, DSL validate,
mlr describe, and an MCP server + agent skill.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Clarify PR3 enums are static codelists, not data-dependent constraints

Distinguish @aborruso's codelist (binary-fixed values, PR3) from
constraint (input-dependent values, PR6 mlr describe).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 12:06:10 -04:00
Kral
c5ee752b5a
ci: add golangci-lint workflow (#2076)
* ci: add golangci-lint workflow

- Adds a GitHub Actions workflow that runs golangci-lint on push and PR
  against the main branch, complementing the existing build/test matrix
  in go.yml.
- Pins Go 1.25 to match go.mod and golangci-lint v1.61.0 for reproducible
  linting; the job is run on ubuntu-latest with a 5-minute timeout.
- Uses concurrency cancellation per ref to keep the CI queue short and
  read-only contents permissions per least-privilege guidance.

* ci: use valid golangci-lint action release

Signed-off-by: dashitongzhi <civilization.cn@outlook.com>

* ci: scope golangci-lint to production packages

* ci: make golangci-lint job advisory (continue-on-error)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Signed-off-by: dashitongzhi <civilization.cn@outlook.com>
Co-authored-by: John Kerl <kerl.john.r@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 08:30:34 -04:00
John Kerl
809d312bd4
Add long-over --md flag (#2100) 2026-06-24 13:58:12 -04:00
dependabot[bot]
f178f9ee3d
Bump actions/cache from 5.0.5 to 6.0.0 (#2101)
Bumps [actions/cache](https://github.com/actions/cache) from 5.0.5 to 6.0.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](27d5ce7f10...2c8a9bd745)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 09:08:05 -04:00
dependabot[bot]
a950042570
Bump actions/setup-go from 6.4.0 to 6.5.0 (#2102)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.4.0 to 6.5.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](4a3601121d...924ae3a1cd)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 6.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 09:07:56 -04:00
John Kerl
299636038c
Shell tab-completion for bash and zsh (#2096)
* 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>
2026-06-21 12:47:54 -04:00