Repository navigation
JSON output for every command (MCP readiness), with arm64-first builds #1
Description
awless-ro is going to become the backend of an MCP server: one tool per read command, each returning structured data. That needs machine-readable output from every command, not only from list. Today list is the only command with --format json; everything else prints text meant for a terminal, and the README leads with "readable tables instead of JSON".
Where things stand
Checked on master at 5ff53f6 (v0.5.0), with the binary built locally.
list <type> --format jsonandlist <service> --format jsonwork.console/displayer.gohasjsonDisplayerandmultiResourcesJSONDisplayer, byte-for-byte the same as elkargig/awless's. So JSON was never removed fromlist; the README line is the pitch, not a behaviour change. Nothing to restore there, only to extend.list ... --format jsonon an empty graph printsnull, not[].showhas no--formatflag.showResource(commands/show.go) already passeslistingFormatto the displayer, but the flag is bound tolistCmdonly, so forshowit is alwaystable. Same in elkargig/awless.whoami,inspect,tail,config,switch,sync,version: text only.whoamiis afmt.Printlnper field; inspectors print their own tables.search imagesprints JSON by default and has no table form. The outlier, in the other direction.
Reference: the upstream lineage
Upstream for the port is elkargig/awless, itself a fork of wallix/awless and last pushed 2022-02-09. Its JSON support is the same list --format json, plus JSON in log and run, which are out of scope here (templates are gone). An earlier attempt to move that code base to AWS SDK v2 was never finished. awless-ro is fully on v2 (v1.47.3) with Go 1.26, so the port goes from there to here: take the output ideas, not the code.
Plan
- One output flag for every command. Promote
--formatto a persistent flag on the root command, defaulttable.list --formatkeeps working unchanged, andshow --format jsonstarts working for free becauseshowResourcealready passes it. Completion values staytable, csv, tsv, json, porcelain; the non-table formats only need to be meaningful where they apply. show --format json: the resource's properties plus its relations (parents, children, and siblings when--siblings), as one object. A resource should have the same shape whether it comes fromlistorshow.whoami --format json: account, user id, resource, type, attached and inlined policies, IP when--ip.inspect --format json: each inspector emits its rows as an array of objects.tail --format json: one object per event, newline-delimited, so--followstreams.config,switch,sync,version: small objects.- Empty results are
[]or{}, nevernull. - Stable value types. Fix type-dependent encodings once per Go type, in one place, the way --format json renders IP netmasks as base64 ("Mask": "//8AAA==") theazz/awless-ro#27 did for netmasks, rather than per displayer. Dates in RFC 3339, numbers as numbers.
- Nothing but JSON on stdout in JSON mode. Logging already goes to stderr; check the first-run banner, the
Now running:line and sync progress, with and without--silent. - Tests: a golden-file test per command for the JSON form, following
console/displayer_test.go. - README and CHANGELOG. By the README's versioning rule output formats are public API; this is additive, so MINOR.
arm64 as the default build
Where awless-ro stands: release.go already builds darwin/{amd64,arm64}, linux/{amd64,arm64} and windows/amd64, and a local go run release.go defaults to the host's runtime.GOARCH. But ci.yml and release.yml run on ubuntu-latest only, so the arm64 binaries are built and never executed, and the tests never run on arm64.
Deliverables (done in #2):
- Tests and the built binary run on arm64 in CI, natively, on GitHub-hosted runners (
ubuntu-24.04-armandmacos-latest). Keep-race; it works on darwin/arm64 and linux/arm64. The release waits for it. make builddefaults to arm64:GOARCH ?= arm64in theMakefile, overridable.release.golists arm64 first per OS and the README's install section leads with the arm64 artefacts.- Homebrew: confirm
update_homebrew_formula.pyand the tap formula select the arm64 archive on Apple Silicon and the amd64 one on Intel. - Any container image added for the MCP server is built for
linux/amd64,linux/arm64with a named buildx builder, both architectures or nothing, so a multi-arch:latestis never replaced by a single-arch push.
To decide
- Persistent
--formatversus a new--output/-o. The former reuses what exists and keepslist --formatstable; recommended. - Whether
show --format jsonembeds related resources or only lists their ids. - Whether
search imagesgets a table form, or stays JSON-only. For the MCP use it is fine as is.
Repository home
Transferred from alfaha/awless-ro to OpenSystemsLab/awless-ro on 2026-10-14, so the LLC stands behind the project and the future MCP server. GitHub redirects the old URLs, the fork relationship to theazz/awless-ro is kept, and this issue moved with the repository. The module path stays github.com/theazz/awless-ro: nothing in the build depends on the owner.
Upstream linkage
GitHub does not link a PR to an issue in another repository, so an upstream PR on theazz/awless-ro will not show this ticket. When the JSON work is ready for review, open a short issue on theazz/awless-ro stating the goal and linking #1 for the detail; the upstream PR then says Closes #N against that issue, and the discussion stays in one place. The arm64 CI part is in #2.
Activity
alfaha commentedon Oct 14, 2026
JSON output: theazz#69 (closes theazz#68). arm64 builds: #2.
ci: test and run the binary on arm64; arm64-first builds
alfaha commentedon Oct 14, 2026
arm64 (#2): CI and the release workflow run the tests and the binary on GitHub's hosted arm64 runners (ubuntu-24.04-arm, macos-latest). Nothing to set up.
Merge the JSON output work into the fork