---
title: "Scripts & agents"
description: The non-interactive JSON contract, stable reason codes, and how the CLI behaves when an agent is driving.
canonical_url: https://wiblo.app/docs/developers/cli/automation
last_updated: 2026-07-28T17:12:38+02:00
md_url: https://wiblo.app/docs/developers/cli/automation.md
---

# Scripts & agents

The CLI is built to be driven by scripts and AI agents as much as by people.

## Non-interactive mode

The CLI switches to non-interactive automatically when it is not attached to a terminal, when `WIBLO_TOKEN` is set without a TTY, or when it detects an agent environment. You can force it either way with `--non-interactive` / `--non-interactive=false` or `WIBLO_NON_INTERACTIVE=1`.

Non-interactive runs never prompt. Anything that would have been a prompt becomes a structured JSON answer on stdout:

```json
{
  "ok": false,
  "reason": "workspace_required",
  "message": "Pass --workspace or run: wiblo workspaces use <slug>",
  "choices": [{ "slug": "acme-studio", "name": "Acme Studio" }],
  "next": ["wiblo workspaces use acme-studio"]
}
```

- `reason` is a **stable machine-readable code** — switch on it, never on `message`.
- `choices` lists the options a human would have been prompted with.
- `next` suggests the exact follow-up commands.

## Reason codes

`missing_arguments`, `confirmation_required`, `not_authenticated`, `device_flow_pending`, `ambient_credentials`, `workspace_required`, `workspace_not_found`, `current_workspace_invalid`, `rate_limited`, `permission_denied`, `not_found`, `validation_failed`, `timeout`, `internal_error`, `logged_out`, `workspace_activated`.

Two more (`token_expired`, `token_revoked`) are reserved but never emitted today — the API deliberately answers every bad token with the same `401`, so the CLI cannot tell those cases apart and reports `not_authenticated`.

## Agent detection

When the CLI sees a known agent environment (Claude Code, Cursor, Gemini CLI, Codex, and others) it tags the session, suppresses browser auto-open during login, and defaults to structured output. Detection is self-reported telemetry — it never grants or denies anything server-side.

## Sign-in from automation

If an auth-required command runs with no token at all, the CLI starts the [device flow](/docs/developers/cli/authentication/login) inline and prints the verification URL. In non-interactive mode it instead returns `not_authenticated` (or `device_flow_pending` while an approval is outstanding) so your runner can decide what to do.
