Skip to content

JSON output for every command (MCP readiness), with arm64-first builds #1

Open

Description

@alfaha

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 json and list <service> --format json work. console/displayer.go has jsonDisplayer and multiResourcesJSONDisplayer, byte-for-byte the same as elkargig/awless's. So JSON was never removed from list; the README line is the pitch, not a behaviour change. Nothing to restore there, only to extend.
  • list ... --format json on an empty graph prints null, not [].
  • show has no --format flag. showResource (commands/show.go) already passes listingFormat to the displayer, but the flag is bound to listCmd only, so for show it is always table. Same in elkargig/awless.
  • whoami, inspect, tail, config, switch, sync, version: text only. whoami is a fmt.Println per field; inspectors print their own tables.
  • search images prints 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

  1. One output flag for every command. Promote --format to a persistent flag on the root command, default table. list --format keeps working unchanged, and show --format json starts working for free because showResource already passes it. Completion values stay table, csv, tsv, json, porcelain; the non-table formats only need to be meaningful where they apply.
  2. 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 from list or show.
  3. whoami --format json: account, user id, resource, type, attached and inlined policies, IP when --ip.
  4. inspect --format json: each inspector emits its rows as an array of objects.
  5. tail --format json: one object per event, newline-delimited, so --follow streams.
  6. config, switch, sync, version: small objects.
  7. Empty results are [] or {}, never null.
  8. 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.
  9. 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.
  10. Tests: a golden-file test per command for the JSON form, following console/displayer_test.go.
  11. 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-arm and macos-latest). Keep -race; it works on darwin/arm64 and linux/arm64. The release waits for it.
  • make build defaults to arm64: GOARCH ?= arm64 in the Makefile, overridable. release.go lists arm64 first per OS and the README's install section leads with the arm64 artefacts.
  • Homebrew: confirm update_homebrew_formula.py and 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/arm64 with a named buildx builder, both architectures or nothing, so a multi-arch :latest is never replaced by a single-arch push.

To decide

  • Persistent --format versus a new --output/-o. The former reuses what exists and keeps list --format stable; recommended.
  • Whether show --format json embeds related resources or only lists their ids.
  • Whether search images gets 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

  1. alfaha commented on Oct 14, 2026

    @alfaha
    CollaboratorAuthor

    JSON output: theazz#69 (closes theazz#68). arm64 builds: #2.

  2. alfaha commented on Oct 14, 2026

    @alfaha
    CollaboratorAuthor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions