Ir a la documentación
CLI

Para agentes de IA

Maneja `openemail` desde Claude Code, Codex o un trabajo de CI: inicio de sesión desatendido, ayuda como datos, simulaciones, scopes que faltan y códigos de verificación.

La guía integrada

openemail agents muestra una guía breve en Markdown para un agente de IA como Claude Code o Codex, o para un script en CI: cómo iniciar sesión sin una persona, leer la salida, encontrar comandos, cambiar cosas con seguridad y recorrer listas, qué hacer cuando falta un código de verificación o un scope, y cinco recetas para copiar. openemail agent es el mismo comando.

Terminal
openemail agentsopenemail agents --json | jq -r '.recipes[].commands[]'

Con --json la guía es un único documento con schemaVersion, title, intro, sections de { id, title, points }, exitCodes y recipes de { id, title, commands }. En lugar de pegar estas reglas en cada prompt, dile al agente una sola vez, en el archivo de instrucciones que tu proyecto ya le da, que ejecute openemail agents antes de usar la CLI.

Iniciar sesión sin una persona

  • Usa una clave de API. Define OPENEMAIL_API_KEY, o pasa --api-key a un solo comando. Créala en Configuración → Claves API (openemail open api-keys) con solo los scopes que necesita el agente. Una clave nunca abre un navegador y nunca necesita un código de verificación.
  • O reutiliza un inicio de sesión con el navegador que una persona hizo una vez en esta máquina con openemail login, y elígelo con --profile <name>. La CLI renueva sus tokens por sí sola.
  • Sin un terminal nada pregunta. Con --json, --no-input o CI, o sin un terminal conectado, un valor que la CLI habría pedido se detiene con el código de salida 2 y nombra la opción que hay que pasar.
  • Un inicio de sesión con el navegador necesita que una persona lo apruebe, así que un openemail login desatendido se detiene con el código de salida 2 y el código unattended antes de registrar nada, y remite a openemail login --with-token.
  • openemail whoami --json muestra el espacio de trabajo, el tipo de inicio de sesión y sus scopes.

Leer la salida

Pasa --json a cada comando. stdout contiene entonces exactamente un documento JSON, o un objeto por línea con --ndjson, y el progreso se queda en stderr. Un fallo muestra una línea {"error":{...}} en stderr: decide según el código de salida y su code, muestra next a una persona y nunca analices message, cuya redacción puede cambiar. La página Scripts enumera cada campo y cada código de salida.

Comandos como datos

--help --json muestra la ayuda como un único documento JSON, construido a partir del mismo registro de comandos con el que la CLI analiza, así que siempre coincide con la versión instalada. Funciona en la raíz, en un grupo o en un comando, y openemail help <command> --json muestra lo mismo.

Terminal
openemail send --help --jsonopenemail domains delete --help --json | jq '.commands[0] | {scopes, destructive}'openemail help domains --json | jq -r '.commands[0].subcommands[].command'openemail --help --json | jq -r '.commands[].command'

El documento

schemaVersionnumber
Cambia cuando un campo cambia de significado
cli, versionstring
Siempre `openemail`, y la versión que lo generó
pathstring[]
El comando consultado, vacío para la raíz
commandsobject[]
Para la raíz, cada comando de primer nivel; si no, el consultado, cada uno con sus subcomandos
globalFlagsobject[]
Las opciones que acepta cada comando, con la misma forma que las opciones de un comando
subcommandAliasesobject
Cada alias compartido, como `ls` o `rm`, y los verbos a los que sustituye
exitCodesobject[]
Cada código de salida como `{ code, name, meaning }`

Un comando

namestring
La última palabra del comando
commandstring
El comando completo, como `openemail domains delete`
path, aliasesstring[]
Las palabras tras `openemail` que llevan a él, y sus otros nombres
summary, descriptionstring
Lo que hace, en una línea y en detalle
usagestring[]
Cómo llamarlo
categorystring | null
Su sección en `openemail --help` para un comando de primer nivel; si no, `null`
group, runnable, hiddenboolean
Si tiene subcomandos, si se ejecuta por sí solo y si la ayuda lo omite
authstring
El inicio de sesión que necesita: `required`, `browser` solo para un inicio de sesión con el navegador, `optional` o `none`
scopesstring[]
Los scopes de la API que necesita cada ejecución
destructiveboolean
Si pide confirmación antes, que `--yes` responde
argumentsobject[]
`name`, `description`, `required` y `variadic` de cada argumento
flagsobject[]
`name`, `short`, `kind`, `required`, `repeatable`, `choices`, `placeholder`, `description` y `hidden` de cada opción
notes, examplesobject[]
Los bloques de ayuda adicionales como `{ title, lines }`, y los ejemplos como `{ command, note }`
resourceobject | null
Para un comando de recurso, el método del SDK y la llamada REST que hay detrás; si no, `null`
subcommandsobject[]
Los comandos bajo un grupo, con la misma forma

Un recurso

namespacestring
El namespace del SDK, como `domains`
sdkMethodstring
El método del SDK, como `openemail.domains.delete`
sdkMethodAllstring | null
Para una lista, el método `listAll` que recorre `--all --json`
httpMethod, httpPathstring
La llamada REST, como `DELETE` y `/domains/{id}`
scopesstring[]
Los scopes que necesita el método
authstring
`apiKey`, o `none` e `inboxToken` para un método que no envía ninguna clave de API
returnsobject
`{ shape, type }`: la forma de la respuesta, como `object` o `page`, y su tipo del SDK
paginatesboolean
Si devuelve una página de una lista

El árbol completo ocupa alrededor de un megabyte, casi todo los 198 comandos de recursos, así que pide el comando que necesitas o filtra el árbol con jq. El texto conserva sus comillas invertidas y no lleva códigos de color, y los comandos ocultos como security se incluyen con hidden en true.

Simulaciones

--dry-run funciona en todos los comandos menos mcp serve. Las lecturas se ejecutan como siempre, luego la primera solicitud que cambiaría algo se muestra en lugar de enviarse, y el comando termina con el código 0 sin hacer nada más. Las confirmaciones se saltan, ya que no se envía nada, así que un agente puede ver lo que haría un comando destructivo sin pasar --yes.

Terminal
openemail domains delete <domain-id> --dry-runopenemail send --from [email protected] --to [email protected] --subject "Hi" --text "Hello" --dry-run --json
stdout
{  "dryRun": true,  "request": {    "method": "POST",    "url": "https://api.openemail.uk/emails",    "headers": {      "accept": "application/json",      "authorization": "Bearer [redacted]",      "content-type": "application/json",      "idempotency-key": "58e6fb61-ad2e-401e-b141-7a0546c7c749",      "user-agent": "openemail-cli/0.0.1 openemail-sdk/0.0.5"    },    "body": {      "from": "[email protected]",      "to": [        "[email protected]"      ],      "subject": "Hi",      "text": "Hello"    },    "raw": null  }}
  • Un cambio es cualquier solicitud salvo GET y HEAD, una llamada a una herramienta MCP, y las solicitudes de inicio y cierre de sesión de login y logout. La renovación de tokens y docs ask se siguen ejecutando.
  • El plan muestra el método, la URL completa, las cabeceras con el valor de Authorization reducido a Bearer [redacted], y el cuerpo JSON con los campos secretos, como una clave de Resend, ocultos. Una subida muestra solo su tamaño y su tipo de contenido.
  • Un cambio que se queda en esta máquina, como profile use, login --with-token u olvidar una clave de API guardada, muestra {"dryRun":true,"local":{"action","profile"}} y no guarda nada.
  • Un comando que muestra lo que leyó antes de su primer cambio lo muestra primero: read muestra el hilo y luego la solicitud que lo marcaría como leído. Pasa --no-mark-read para omitir la segunda.
  • mcp serve rechaza --dry-run con el código de salida 2, porque su cliente decide qué enviar. En su lugar, previsualiza una llamada a una herramienta con openemail mcp call <tool> --dry-run.

Scopes que faltan

Cada comando conoce los scopes de la API que siempre necesita, y su ayuda los enumera. Cuando a un inicio de sesión guardado le falta uno, el comando pide una vez a la API la lista actual, así que el acceso concedido en el sitio web después del inicio de sesión cuenta al momento. Si el scope sigue faltando, se detiene con el código de salida 4 y el código insufficient_scope antes de preguntar nada o enviar una solicitud:

stderr
{"error":{"type":"cli_error","code":"insufficient_scope","message":"This sign-in does not have the emails:send permission, which openemail send needs.","hint":null,"next":"Give this app more access in Account settings, Connected apps (openemail open apps, then Edit access), or run openemail login --force and choose more access.","status":null,"requestId":null,"param":null,"docUrl":null,"exitCode":4}}
  • Para un inicio de sesión con el navegador, next dice que des más acceso a la app en Cuenta → Línea de comandos (openemail open cli, luego Editar acceso), o que ejecutes openemail login --force y elijas más acceso. Un inicio de sesión con el navegador nunca recibe keys:write ni keys:manage, así que para esos remite a una clave de API.
  • Para una clave de API, next dice que uses una clave que tenga el scope.
  • Una clave de --api-key o de OPENEMAIL_API_KEY no se comprueba de antemano, y decide la API. Cuando la API rechaza una llamada por un scope que falta, el error lleva el mismo next.

Códigos de verificación

Una clave de API nunca necesita un código de verificación. Un inicio de sesión con el navegador necesita uno antes de un cambio delicado, como añadir un webhook, crear una regla, cambiar un miembro o quitar un dominio, y un agente no puede escribirlo. Así que, antes de que el agente se ejecute, una persona ejecuta openemail verify en un terminal con el mismo perfil, o elige Permitir cambios durante 60 minutos para ese inicio de sesión en Cuenta → Línea de comandos. Cualquiera de los dos cubre los 60 minutos siguientes.

Terminal
openemail verifyopenemail verify --status --json

verify --status --json le dice al agente si el perfil está verificado, en elevated, y hasta cuándo, en elevatedUntil. Sin verificación, el cambio se detiene con el código de salida 4 y el código step_up_required, y no se cambia nada:

stderr
{"error":{"type":"cli_error","code":"step_up_required","message":"This action needs a verification code, and there is no interactive terminal to ask for one.","hint":null,"next":"Run openemail verify in an interactive terminal first, then run this again within 60 minutes. An API key never needs a code.","status":403,"requestId":"req_9Qm4tV","param":null,"docUrl":"https://openemail.uk/docs/api/errors#step_up_required","exitCode":4}}

Por MCP

Un agente que habla MCP puede usar el servidor MCP de OpenEmail en su lugar. openemail mcp config --client claude-code, o codex, cursor y los demás clientes que enumera, muestra la configuración, y openemail mcp serve es un puente local que reutiliza el inicio de sesión con el navegador de esta CLI. Las claves de API no pueden llegar al servidor MCP. La página IA y MCP tiene los detalles.

Recetas

Hilos sin leer como JSON
openemail inbox --unread --limit 20 --jsonopenemail inbox --unread --json | jq -r '.items[].id'
Leer un hilo sin marcarlo como leído
openemail read CAHk7pQ2x9LmZ4 --no-mark-read --json
Enviar desde un archivo, seguro al reintentar
openemail send --from [email protected] --to [email protected] --subject "Weekly report" --body-file report.md --idempotency-key weekly-report-39 --json
Añadir un dominio tras una simulación
openemail domains create --domain example.com --dry-run --jsonopenemail domains create --domain example.com --json
Comprobar lo que puede hacer la credencial
openemail whoami --json | jq '.scopes'

Tu bandeja de entrada,
en tus propios términos.

Infraestructura de correo para empresas, IA, agentes y correo personal. Creada para escalar, con privacidad y control. Todo lo que el correo debería haber tenido desde el primer día.

OpenEmail

Infraestructura de correo para empresas, IA, agentes y correo personal. Creada para escalar, con privacidad y control. Todo lo que el correo debería haber tenido desde el primer día.

© 2026 OpenEmail. Todos los derechos reservados.