Volver a las novedades

¿En qué señales de la salida de codex exec puedes confiar?

El código de salida es la única señal que no puedes usar. En 9 ejecuciones de codex exec el 19 de agosto de 2026 (codex-cli 0.147.0, macOS 26.5.2 en arm64) el proceso salió con 0 todas las veces, incluidas las 6 ejecuciones que dejaron el repositorio idéntico byte a byte. Otras cuatro señales de la misma salida sí llevan la verdad, y cada una responde a una pregunta distinta: un ítem file_change en la salida estándar dice que hubo un intento de escritura, su campo status dice si la escritura entró (coincidió con la realidad en los 10 ítems de las 9 ejecuciones del 21 de agosto de 2026, codex-cli 0.148.0), su campo kind leído como saldo por ruta es lo único en la salida que detecta un archivo creado y luego borrado, y una línea ERROR con patch rejected en la salida de error apareció en 6 de 6 ejecuciones bloqueadas. Esta página es un índice. No mide nada nuevo: consolida 25 ejecuciones de codex exec que publicamos el 19 y el 21 de agosto de 2026, más una comparación con Claude Code del 18 de agosto de 2026, y cada número de ella lleva la fecha y el build del que salió.

El orden importa más que cualquier señal aislada, porque estas señales fallan en direcciones distintas. Una calla cuando falta trabajo. Otra se dispara cuando no sobrevivió nada. Una tercera es la única honesta en una escritura que falló, y solo la hemos observado en el build más nuevo.

¿Qué prueba realmente el código de salida de codex exec?

El código de salida de codex exec prueba que el proceso terminó, y nada más sobre el trabajo. Le dimos la misma tarea pequeña a codex exec nueve veces el 19 de agosto de 2026, en nueve repositorios git desechables, en codex-cli 0.147.0 y macOS 26.5.2: añadir una función slugify a src/utils.js, exportarla y ejecutar npm test. Los tres brazos se diferenciaban solo en la política de sandbox: -s workspace-write, ninguna bandera -s, y -s read-only. El proceso salió con 0 en 9 de 9 ejecuciones. En 6 de esas 9 el repositorio terminó idéntico byte a byte a como empezó, porque el sandbox rechazó el parche. Una tubería que decide por $? habría marcado las nueve en verde.

Hay un caso en el que el código de salida sí habla, y lo encontramos por accidente. En una batería aparte del mismo día, una ejecución murió antes de hacer nada, con código de salida 1 y un evento turn.failed que llevaba el mensaje Selected model is at capacity. Es decir: una salida distinta de cero avisa que la ejecución se rompió; una salida cero no dice nada sobre si el archivo se escribió. El juez en todas estas ejecuciones no fue el agente: el aparato calculó el hash de cada archivo fuera de .git antes y después de cada ejecución y comparó las huellas, así que la pregunta "¿cambió algo?" se respondió fuera del alcance del agente. La tabla completa de las nueve ejecuciones está en cómo saber si Codex cambió realmente un archivo.

¿Qué señal de codex exec dice que hubo un intento de escritura?

La señal de que hubo un intento de escritura es un evento item.completed de tipo file_change en la salida estándar, que codex exec --json emite por ruta modificada. En las nueve ejecuciones del 19 de agosto de 2026 apareció en 3 de 3 ejecuciones que editaron el archivo y en 0 de 6 que no lo editaron, una separación limpia y la razón por la que lo recomendamos al principio. Cada ítem lleva una lista changes, y cada cambio lleva un path y un campo kind cuyos valores hemos observado como add y delete.

Lee esa frase al pie de la letra, porque la trampa está en el verbo. El evento responde "¿hubo una escritura en esta ruta?", no "¿ocurrió el trabajo?". Esas dos preguntas se separan en situaciones corrientes, no exóticas, y la siguiente sección es donde publicamos el contraejemplo contra nuestra propia recomendación. Si estás conectando codex exec a una tubería hoy y solo tienes tiempo de cambiar una cosa, cambiar $? por la presencia de un ítem file_change ya es la mitad más grande de la mejora, en las ejecuciones que medimos.

¿Un evento file_change significa que el trabajo ocurrió?

No. Un evento file_change en codex exec se dispara con la escritura y no con el desenlace, y medimos dos formas corrientes de que te engañe, las dos el 19 de agosto de 2026 con codex-cli 0.147.0. En el primer brazo, tres ejecuciones, la tarea pedía a Codex crear sum.js, ejecutar una prueba trucada que exige que sum(2, 2) sea 5, y revertir todo si la prueba fallaba. Codex hizo exactamente eso. La huella del repositorio después de la ejecución era igual a la de antes en 3 de 3 ejecuciones, y file_change se disparó igualmente en 3 de 3, una vez con kind: "add" y una vez con kind: "delete". En el segundo brazo, tres ejecuciones, un prompt llevaba dos tareas independientes, una posible y una imposible con la red apagada. Codex completó una mitad y saltó la otra, y file_change se disparó en 3 de 3 exactamente como lo hace con trabajo completo.

El arreglo es pequeño y vive en el payload que ya tienes: lee kind y calcula un saldo por ruta, en vez de contar eventos. Una ruta con un add y un delete queda en cero y la reversión se hace visible. Nada en la salida detecta la mitad que faltó en una tarea de dos partes, y no encontramos una señal que lo haga. Ese es un límite real del formato, no un descuido en nuestra lectura, y la medición está en ¿codex exec muestra cuándo el agente hizo solo la mitad del trabajo?.

¿Qué campo de codex exec detecta una escritura que falló?

El campo que detecta la escritura fallida es status en el ítem file_change, y en nuestra medición es lo más honesto que hay legible por máquina en la ejecución. El 21 de agosto de 2026, en codex-cli 0.148.0 y macOS 26.5.2, ejecutamos codex exec nueve veces, con un perfil sandbox-exec de macOS negando la escritura en el directorio de trabajo en tres de ellas. Esas nueve ejecuciones emitieron diez ítems file_change en total, y el campo coincidió con la realidad en todos: status: "failed" en los 4 ítems emitidos por las tres ejecuciones bloqueadas, status: "completed" en los 6 ítems emitidos por las seis que escribieron. Aquí va un ítem, literal y completo, de una ejecución bloqueada:

{
 "id": "item_1",
 "type": "file_change",
 "changes": [
  {
   "path": "/private/tmp/codex-sandbox-21ago-n1/N1/run1/report.txt",
   "kind": "add"
  }
 ],
 "status": "failed"
}

Esto refina la sección anterior en vez de contradecirla. Las dos afirmaciones valen a la vez: el evento es honesto sobre si la escritura entró, y callado sobre si el trabajo valió algo. Una advertencia pertenece a este lugar y ningún artículo hijo la lleva, porque cada uno se escribió dentro de un build. Nosotros observamos status en codex-cli 0.148.0. Las mediciones del 19 de agosto corrieron en 0.147.0 y no leímos ese campo allí, así que no podemos decir, a partir de nuestros datos, si estaba presente y lo ignoramos, o si se añadió después. Compruébalo en tu propio build antes de hacer que una tubería dependa de él.

¿Qué detecta la línea ERROR en la salida de error?

La línea ERROR en la salida de error detecta la escritura bloqueada, y en nuestra batería del 19 de agosto de 2026 fue la imagen especular de file_change. Una línea con patch rejected apareció en 6 de 6 ejecuciones en las que el sandbox rechazó la escritura, y en 0 de 3 ejecuciones que escribieron con éxito. La salida estándar y la salida de error responden, por lo tanto, a preguntas opuestas en la misma ejecución, y una tubería que captura solo uno de los dos flujos está tirando la mitad de la evidencia sobre un fallo que después tendrá que explicar.

Dos de aquellos tres brazos merecen una nota que preferimos publicar antes que esconder. El brazo sin bandera -s y el brazo con -s read-only llegaron al mismo estado de sandbox por dos caminos distintos, así que sus filas no son evidencia independiente: en nuestra medición, codex exec sin bandera de sandbox se comportó exactamente como -s read-only. Dejamos las dos filas en la tabla original con esa nota, en vez de descartar un brazo en silencio, y la misma honestidad vale para el recuento de aquí: 6 de 6 ejecuciones bloqueadas es tres más tres, de dos brazos que resultaron ser una sola condición.

¿La prosa del propio agente es una señal que se pueda usar?

La prosa de Codex es honesta sobre el fallo y poco fiable sobre la causa, y las dos mitades importan si piensas leer transcripciones. En todas las ejecuciones bloqueadas del 19 de agosto de 2026, Codex dijo en inglés claro que no podía escribir el archivo. Nunca reivindicó un éxito que no tuvo. Esa es la mitad buena, y vale decirla con todas las letras porque el comportamiento opuesto es común lo bastante como para ser la razón de que esta serie exista.

La mitad mala apareció el 21 de agosto de 2026, cuando el bloqueo vino de un perfil sandbox-exec de macOS aplicado desde fuera del proceso. Codex reportó Operation not permitted y culpó al directorio actual en 3 de 3 ejecuciones bloqueadas. El directorio era drwxr-xr-x y pertenecía al usuario, así que la explicación estaba equivocada mientras el reporte del fallo era correcto. Nunca nombró la capa que de hecho lo detuvo. Para la automatización la consecuencia es estrecha y práctica: usa la prosa para saber que algo falló, nunca para saber qué falló, y lee status antes de leer la frase. La medición del diagnóstico está en por qué Codex dice Operation not permitted cuando el directorio parece escribible.

¿En qué orden debe leer tu tubería las señales de codex exec?

Léelas en el orden de lo que cada una puede probar, de la más débil a la más fuerte, porque una tubería que las lee en el orden equivocado reporta lo equivocado. En las 25 ejecuciones de codex exec publicadas el 19 y el 21 de agosto de 2026, la escalera salió así.

  • Código de salida. Úsalo solo para detectar que la ejecución en sí se rompió, como en el caso de turn.failed con Selected model is at capacity. Fue 0 en 9 de 9 ejecuciones, incluidas 6 que no cambiaron nada, así que no puede significar éxito.
  • Presencia de un ítem file_change. Hubo un intento de escritura en esa ruta. Separación limpia en nuestras ejecuciones, 3 de 3 contra 0 de 6.
  • status en ese ítem. Si la escritura entró. Correcto en 10 de 10 ítems en codex-cli 0.148.0, no verificado por nosotros en 0.147.0.
  • kind, como saldo por ruta. Si sobrevivió algo. Es lo que detecta el crear y borrar que el recuento de eventos deja pasar.
  • ERROR en la salida de error. Por qué fue rechazado. Presente en 6 de 6 ejecuciones bloqueadas.
  • Un hash del árbol de trabajo antes y después. El único juez que no es el agente, y el que usamos para calificar todos los brazos anteriores.

La última línea es la que hay que guardar, si guardas solo una. Todo número de esta página existe porque el aparato tomó la huella del repositorio fuera del alcance del agente, y cualquiera de las señales anteriores puede verificarse en tu propia máquina contra esa misma comprobación.

¿Cómo se compara el envoltorio de codex exec con el de Claude Code?

El envoltorio de codex exec lleva un evento por archivo y el envoltorio de Claude Code, en nuestra medición, no llevaba nada equivalente. Corrimos el mismo tipo de medición contra Claude Code el 18 de agosto de 2026 (Claude Code 2.1.235, modelo sonnet, macOS 26.5.2): 13 de 13 ejecuciones volvieron con subtype: "success" e is_error: false, y 10 de esas 13 no habían cambiado nada en el repositorio. No había un campo que hiciera el papel que file_change hace para Codex, así que el envoltorio por sí solo no podía distinguir trabajo de silencio.

Trata eso como una comparación de dos envoltorios en dos fechas y dos builds, no como un veredicto sobre ninguno de los agentes. El número de Claude Code es del 18 de agosto de 2026 y los de Codex son del 19 y el 21 de agosto de 2026, en codex-cli 0.147.0 y 0.148.0, y los agentes de esta categoría publican versión varias veces por semana. Lo que generaliza es la forma de la pregunta, no el marcador: antes de automatizar alrededor de cualquier agente de programación, averigua qué campos de su salida responden "¿hubo un intento de escritura?", "¿entró?" y "¿sobrevivió algo?", y si la respuesta a cualquiera de las tres es "ningún campo", esa laguna es tuya y se cubre con un hash.

Lo que este índice no muestra

Este índice carga los límites de las mediciones que consolida, y son reales. Todo número viene de una máquina, macOS 26.5.2 en arm64, en repositorios git desechables con un puñado de archivos, el 18, el 19 y el 21 de agosto de 2026. Las muestras son de un dígito por brazo, tres ejecuciones cada uno, y un recuento de un dígito no separa un fallo raro de uno imposible. Aquí se mezclan dos builds de codex-cli, 0.147.0 y 0.148.0, y decimos cuál es cuál en cada afirmación precisamente porque no son la misma herramienta.

Varias cosas quedaron sin probar. No leímos status en 0.147.0, así que su historia nos es desconocida. No probamos la interfaz interactiva de Codex, solo codex exec. No probamos una escritura parcial, un archivo dejado a medias por un proceso interrumpido, que es el caso en el que un saldo por ruta puede ser honesto e inútil a la vez. No probamos ningún sandbox aparte del perfil de macOS y las políticas -s integradas, y Linux puede comportarse de otra forma. Dos contaminaciones del aparato del 21 de agosto de 2026 viajan con el hallazgo sobre la prosa y están declaradas en el artículo de origen: el directorio de trabajo se llamaba /private/tmp/codex-sandbox-21ago-n1, así que la palabra codex-sandbox se imprimió en pantalla con pwd y ls en 3 de 3 ejecuciones bloqueadas, y en una de ellas el agente abrió el stderr.txt de nuestro aparato y leyó el registro de errores del envoltorio. Ninguna cambió el resultado, y las dos significan que ninguna frase de aquí puede afirmar que el agente vio solo lo que Codex muestra. En CanvasCode ejecutamos varios agentes de programación en paralelo, que es exactamente donde un envoltorio incapaz de distinguir trabajo de silencio sale más caro, porque la ejecución que no miraste es aquella cuyo resumen vas a creer.