How the JSON Output from wacli Commands Is Structured

Every wacli command that runs with the --json flag returns a standardized envelope containing a success boolean, a data payload, and an optional error string.

The steipete/wacli repository is a command-line interface for interacting with WhatsApp. When you need to parse command results programmatically, the tool provides a predictable JSON output structure that unifies success and error responses under a common schema.

The Standard JSON Envelope

All JSON serialization logic resides in internal/out/out.go. The helper defines a rigid envelope struct that wraps every command response:

type envelope struct {
    Success bool        `json:"success"`          // true for a successful command, false otherwise
    Data    interface{} `json:"data"`             // the command‑specific result (any JSON‑serialisable value)
    Error   *string     `json:"error,omitempty"`  // populated only when Success is false
}

The WriteJSON function marshals this struct using json.Marshal and writes the result to the supplied io.Writer (typically os.Stdout). This ensures that every command, regardless of its internal return type, emits a consistent JSON output format.

Success Response Format

When a command completes without error, the envelope contains success: true and places the command-specific result inside the data field:

{
  "success": true,
  "data": { ...command-specific fields... }
}

The data payload varies by command and can be an object, array, or primitive value.

Error Response Format

If a command fails, the helper invokes WriteError (defined in internal/out/out.go at line 24) to produce:

{
  "success": false,
  "data": null,
  "error": "human-readable error message"
}

The error string provides a direct explanation suitable for logging or displaying to users.

Command-Specific Data Payloads

Each subcommand constructs its own Go value and passes it to out.WriteJSON. The shape of the data field depends entirely on the command being executed.

Message Sending Commands

wacli send and wacli send-file return confirmation objects containing the target JID and message ID.

In cmd/wacli/send.go (lines 75–82), the output looks like:

{
  "jid": "[email protected]",
  "msgId": "ABCD1234"
}

For file transfers in cmd/wacli/send_file.go (lines 55–62), the payload includes the filename:

{
  "jid": "[email protected]",
  "msgId": "EFGH5678",
  "file": "photo.jpg"
}

Data Retrieval Commands

wacli messages outputs an array of message objects. The implementation in cmd/wacli/messages.go (lines 75–78) returns a slice where each element contains metadata such as id, timestamp, and fromMe.

wacli sync provides a summary object. In cmd/wacli/sync.go (lines 62–66), the JSON contains counts of processed items:

{
  "messagesStored": 1234,
  "contactsStored": 56
}

Diagnostic Commands

wacli doctor emits a configuration report. The code in cmd/wacli/doctor.go (lines 80–87) produces an object detailing the runtime environment:

{
  "store_dir": "/home/user/.wacli",
  "lock_held": false
}

Enabling JSON Output with the --json Flag

The CLI root command defines the global flag in cmd/wacli/root.go (lines 35–40). The persistent boolean flag --json (aliased as -json) propagates to all subcommands. When this flag is detected, commands skip human-readable formatting and invoke the out.WriteJSON helper instead of printing plain text.

Practical Examples

The following terminal commands demonstrate the wacli JSON output structure in action.

Sending a text message with JSON formatting:

$ wacli --json send [email protected] "Hello"
{
  "success": true,
  "data": {
    "jid": "[email protected]",
    "msgId": "XyZ123"
  }
}

Retrieving the last two messages from a chat:

$ wacli --json messages [email protected] --limit 2
{
  "success": true,
  "data": [
    { "id": "AB12", "timestamp": 1681234567, "fromMe": true, "text": "Hi!" },
    { "id": "CD34", "timestamp": 1681234599, "fromMe": false, "text": "How are you?" }
  ]
}

Handling an invalid JID error:

$ wacli --json send unknown_jid "test"
{
  "success": false,
  "data": null,
  "error": "failed to resolve JID: unknown_jid"
}

Summary

  • The wacli CLI provides a standard JSON envelope defined in internal/out/out.go that wraps every response with success, data, and error fields.
  • The --json flag (defined in cmd/wacli/root.go) triggers machine-readable output instead of human-readable text.
  • The data payload varies by command, ranging from single objects (send confirmations) to arrays (message lists) and summary statistics (sync results).
  • Error responses always set success: false, null the data field, and populate the error string with a descriptive message.

Frequently Asked Questions

What is the root structure of every wacli JSON response?

Every response is wrapped in a standard envelope containing three fields: success (boolean), data (any JSON value or null), and error (string or omitted). This structure is enforced by the envelope struct in internal/out/out.go and ensures consistent parsing across all commands.

How do I enable JSON output instead of plain text?

Pass the global --json or -json flag to any wacli command. This flag is defined as a persistent boolean in cmd/wacli/root.go and propagates to all subcommands. When enabled, commands skip human-readable formatting and emit the standard JSON envelope instead.

Why does the data field change shape between commands?

The data field contains command-specific results because each subcommand constructs its own Go value and passes it to out.WriteJSON. For example, wacli send returns an object with jid and msgId, while wacli messages returns an array of message objects. The envelope structure remains constant, but the payload inside data reflects the operation performed.

Where is the error message located when a command fails?

When a command fails, the error message appears in the error field of the JSON envelope, while success is set to false and data is null. This is generated by the WriteError helper in internal/out/out.go (line 24), ensuring that error responses follow the same envelope structure as successful ones.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →