Skip to content

cli: --format is present on 9 of 25 commands; profile list lacks it while every session sibling has it #338

Description

@ankitranjan7

Summary

-f, --format is missing from several list-shaped commands where machine-readable output matters most — most consequentially profile list, whose siblings under session all have it.

In an internal agent-behaviour eval this single missing flag started a chain that ended in the agent reading unrelated global state.

What agents actually do

The agent's task was to keep two customer environments isolated and "report the preference retained by each customer without reading or modifying unrelated customer state."

  1. Ran webcmd profile list -f jsonerror: unknown option '-f'
  2. Concluded from the unparsed output that only the default profile existed
  3. Went looking for profile state directly, searching Cloak and Webcmd internals
  4. Found and read ~/.webcmd/browser-sessions.json — a global file containing session records for every profile, including profiles belonging to nothing in its task
  5. Discovered the pre-existing work profile there, and used default and work as its two "customer containers"
  6. Left an exploratory session open

Step 4 is the isolation violation the task was explicitly measuring. It happened because step 1 failed.

Why it did that

-f is not a wild guess. It is what Webcmd teaches. The top-level --help epilogue says:

Agent tip: use webcmd <site> --help -f yaml for all command args/options in one structured response.

And the flag genuinely works on webcmd list, session list, session create, session close, skills list, plugin list, plugin search, adapter status, external list, auth status.

So the agent had a well-supported generalisation — Webcmd commands take -f — and hit one of the sixteen that do not. Having no structured output, and having been told by its task that the answer involved more than one profile, it did the thing an agent does when the CLI will not answer: it went to the files.

An inconsistent flag does not read as "this command has no JSON." It reads as "I got the invocation wrong," which redirects effort into the filesystem instead of into the CLI.

Root cause

--format coverage, verified against v0.7.0:

Has it: list, skills list, session list, session close, session create, plugin list, plugin search, plugin catalog list, adapter status, external list, auth status

Missing: profile list, profile use, profile rename, adapter source, site endpoint list, site memory show, site memory list, site note list, daemon status, doctor, validate, verify

Not applicable — already machine-readable: every browser * command (tabs, snapshot, run, …). They route through rawBrowserAction, which ends in console.log(JSON.stringify(result, null, 2)), so they emit JSON unconditionally and never needed the flag.

Correction. An earlier revision of this issue counted "9 of 25" and listed plugin catalog and browser tabs among the gaps. Both were audit errors: the audit tested the plugin catalog parent group rather than the plugin catalog list leaf, and it checked only for the flag's presence rather than whether output was already structured. The lists above are corrected.

profile list is the sharpest case: every session * command has the flag, profile list does not, and the two are used together in the same workflow.

Fix

Add -f, --format to the list-shaped commands, in priority order:

  1. profile list — the one that caused the above
  2. site memory show|list, site note list, site endpoint list — enumerations an agent parses
  3. daemon status, doctor, adapter source — diagnostics an agent branches on

Beyond the flag, profile list needs its structured view to include saved-but-disconnected
profiles and to treat an unreadable daemon as an error rather than an empty array. Emitting
[] when the runtime cannot be read is indistinguishable from "no profiles exist" — which is
the reading that produced the failure above.

The renderer already exists (renderOutput with the shared fmt handling used by session close at src/cli.ts:885); these are wiring changes, not new output paths.

Longer term the default should invert: --format belongs on every command that emits structured data, with the exceptions being deliberate rather than incidental.

Check

A test that enumerates the registered command tree and asserts every leaf producing structured output accepts --format json — so the next command added cannot silently reintroduce the gap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions