Skip to content

fix(cli): repair --help layout; feat(web): show server version on login - #56

Merged
tatelilith merged 2 commits into
mainfrom
tatelilith/cli-help-and-version
Aug 17, 2026
Merged

fix(cli): repair --help layout; feat(web): show server version on login#56
tatelilith merged 2 commits into
mainfrom
tatelilith/cli-help-and-version

Conversation

@tatelilith

Copy link
Copy Markdown
Contributor

Two independent changes that happened to share a branch.

1. fix(cli): --help wrapped every command onto a blank second line

a2wave --help rendered a blank-looking line after each command, and long descriptions broke mid-sentence at column 0.

The cause was not description length. citty's formatLineColumns pads every column to the widest entry, including the last one. The 250-character api description padded all 24 rows out to 332 columns, so any terminal narrower than that wrapped the trailing whitespace into a second line. Two defects compounded it: the renderer never consulted the terminal width, and it right-aligned names with padStart, making the left edge step in and out raggedly.

Before (every row padded to 332 cols → wraps):

       schema    Machine-readable spec for a command (no argument lists every command path)

         docs    Print the agent guide, or one section of it

        setup    Install a local a2wave platform: generate .env + docker-compose.yml, start the co
w image, or --down to uninstall.

After:

  schema        Machine-readable spec for a command (no argument lists every command path)
  docs          Print the agent guide, or one section of it
  setup         Install a local a2wave platform: generate .env + docker-compose.yml, start the
                container, and wait until healthy. Use --upgrade to move an existing install to a
                new image, or --down to uninstall.

citty's renderUsage is replaced rather than post-processed: the padding is applied inside citty's function, so there is no seam to patch from outside, and stripping trailing spaces afterwards cannot recover text already wrapped at the wrong width. The layout now matches claude / codex / lark-cli — two-space indent, left-aligned names, one gutter, hanging-indent wrapping, no trailing whitespace.

Descriptions are kept whole rather than truncated. The page wraps to the terminal width, falling back to a fixed 100 columns when stdout is not a TTY, so agent-facing output stays byte-stable across runs and machines.

Two further bugs surfaced while fixing this, both pinned by tests:

  • The pipe-joined subcommand list is a single space-free token (165 chars for the root's 24 commands) that word-wrapping alone cannot split. It now breaks after |.
  • The renderer never falls back to process.argv[1] the way citty does, so the published binary's absolute path can no longer leak into a usage line whose meta.name is missing.

The preformatted AGENT QUICKSTART block keeps its hand-alignment — an indented line is passed through unreflowed rather than rewrapped.

New: apps/cli/src/lib/usage.ts (wrapping/column primitives) and apps/cli/src/lib/render-usage.ts (page renderer), with 31 tests written red-first.

2. feat(web): server version in the login footer

Adds GET /api/version, a use-version hook, and the login-page footer.

Verification

Gate Result
Lint clean on changed files; repo-wide warning count identical to HEAD (no new debt)
Typecheck green, test files included
Tests API 6164 · web 938 · CLI 1072 — all pass

Help output checked across --help, agents, runs list, setup, api: zero overflowing lines, zero trailing-space lines.

Also deployed to a local PostgreSQL-backed install to confirm /api/version serves JSON (it previously fell through to the HTML app shell).

Note for reviewers

apps/cli is not built into the container image, so the CLI fix ships via the npm package only; the web change ships in the image.

The login page had no version indicator, so anyone reporting a bug from a
deployment had to guess which build they were on — the version was only
reachable after signing in, via the About dialog.

Append it to the copyright line rather than giving it its own row: the
footer is already the page's meta-info zone, and a six-character string
does not earn a full line. When the version is unknown (still loading, or
the request failed) the copyright renders alone, with no orphaned
separator left behind.

Add GET /api/version for this. /health answers the same question, but only
after probing the database, both data directories and every execution
engine — far too much work, and far too much detail, to drag into an
unauthenticated page load. The About dialog was doing exactly that via an
inline fetch, so point both surfaces at one shared useVersion() hook and
let them share its cache. getVersion() moves to lib/ so the two routes
resolve the version identically.

The hook resolves to null instead of rejecting on failure: every surface
showing the version is decorative, and the login page should never have to
render an error state for it.
`a2wave --help` rendered each command with a blank-looking line after it,
and long descriptions broke mid-sentence at column 0. The cause was not
description length: citty's `formatLineColumns` pads *every* column to the
widest entry, including the last one. The 250-character `api` description
therefore padded all 24 rows out to 332 columns, and any terminal narrower
than that wrapped the trailing whitespace into a second line.

Two further defects compounded it: the renderer never consulted the
terminal width, so overflowing descriptions lost the column alignment
entirely, and it right-aligned command names with `padStart`, making the
left edge step in and out raggedly.

Replace citty's `renderUsage` with our own. Post-processing could not fix
this — the padding is applied inside citty's function, so there is no seam
to patch from outside, and stripping trailing spaces afterwards cannot
recover text already wrapped at the wrong width. The layout now matches
what every mainstream CLI uses (claude, codex, lark-cli): two-space indent,
left-aligned names, one gutter, descriptions wrapped with a hanging indent,
and no trailing whitespace on any line.

Descriptions are kept whole rather than truncated; the page wraps to the
terminal width, falling back to a fixed 100 columns when stdout is not a
TTY so that agent-facing output stays byte-stable across runs and machines.

Two bugs surfaced while fixing this and are pinned by tests:

- The pipe-joined subcommand list is a single space-free token (165 chars
  for the root's 24 commands), which word-wrapping alone cannot split. It
  now breaks after `|`.
- The renderer never falls back to `process.argv[1]` the way citty does,
  so the published binary's absolute path can no longer leak into a usage
  line whose `meta.name` is missing.

The preformatted AGENT QUICKSTART block keeps its hand-alignment: an
indented line is passed through unreflowed rather than rewrapped.

Verified across --help, agents, runs list, setup and api: zero overflowing
lines and zero trailing-space lines.
@tatelilith
tatelilith merged commit 1001972 into main Aug 17, 2026
17 checks passed
@tatelilith
tatelilith deleted the tatelilith/cli-help-and-version branch August 17, 2026 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant