Protocolo (legacy) CLI <-> Desktop, version v1
Fecha: 2026-05-03
Version del protocolo: v1 (alineado con --output-format stream-json actual del CLI Context Code).
Este documento describe el contrato NDJSON para la ruta legacy en la que el Desktop conversa con el runtime CLI/headless.
El Desktop actual usa un motor agéntico nativo (Rust) para el chat y mantiene este protocolo solo por compatibilidad/rollback y ejecuciones headless que aún lo requieran.
1. Spawn
Comando completo:
context -p \
--output-format stream-json \
--verbose \
--input-format stream-json \
--model <alias-o-nombre> \
[--permission-mode <mode>] \
[--allowed-tools <lista>] \
[--disallowed-tools <lista>] \
[--system-prompt <texto>]Notas:
--verbosees OBLIGATORIO cuando--output-format=stream-json. El CLI rechaza el spawn sin el (CLI/src/main.tsx:1862-1867).cwddel proceso = ruta del workspace.- En Windows el desktop wrappea con
cmd /C context ...para resolver el shim.cmdde npm. - No setear
CONTEXT_PROVIDERniCONTEXT_MODEL: el CLI no los lee. El modelo se pasa por--model.
2. Input - stdin (NDJSON)
Cada turno del usuario es una linea JSON terminada en \n. Forma SDKUserMessage:
{
"type": "user",
"message": {
"role": "user",
"content": [{ "type": "text", "text": "Tu prompt aqui" }]
},
"parent_tool_use_id": null,
"session_id": "<chat_id>"
}- Multi-turn: stdin se mantiene abierto entre turnos. EOF en stdin = fin de sesion.
- El desktop no escribe texto plano: siempre serializa el envelope.
3. Output - stdout (NDJSON)
Cada linea de stdout es un objeto JSON. Tipos posibles, agrupados por type y subtype.
3.1 system / init
Emitido al inicio de cada sesion.
{
"type": "system",
"subtype": "init",
"cwd": "/ruta/del/workspace",
"tools": ["Bash", "Edit", "Read", "..."],
"mcp_servers": [{ "name": "...", "status": "connected" }],
"model": "claude-sonnet-4-6",
"permissionMode": "default",
"session_id": "abc123",
"uuid": "..."
}3.2 system / status
Cambios de estado del runtime (compactacion, etc.).
{ "type": "system", "subtype": "status", "status": "compacting", "session_id": "abc123" }3.3 system / session_state_changed
{ "type": "system", "subtype": "session_state_changed", "state": "running", "session_id": "abc123" }3.4 system / hook_*
Hooks del ciclo de vida (SessionStart, PreToolUse, etc.).
{
"type": "system",
"subtype": "hook_started",
"hook_id": "hook_123",
"hook_name": "my-hook",
"hook_event": "SessionStart",
"session_id": "abc123"
}Subtypes: hook_started, hook_progress, hook_response. hook_response incluye exit_code, outcome, stdout, stderr.
3.5 system / task_* (subagentes / AgentTool)
Cuando el modelo invoca el AgentTool/Task, el CLI emite eventos estructurados por subagente. La clave de agrupacion es task_id.
{
"type": "system",
"subtype": "task_started",
"task_id": "task_abc",
"tool_use_id": "tool_use_xyz",
"description": "Reviewing code",
"task_type": "agent_task",
"workflow_name": "code_review",
"prompt": "Review the code and...",
"session_id": "abc123"
}{
"type": "system",
"subtype": "task_progress",
"task_id": "task_abc",
"tool_use_id": "tool_use_xyz",
"summary": "Analyzed 5 files",
"last_tool_name": "Read",
"usage": { "total_tokens": 1024, "tool_uses": 3, "duration_ms": 2000 },
"session_id": "abc123"
}{
"type": "system",
"subtype": "task_notification",
"task_id": "task_abc",
"tool_use_id": "tool_use_xyz",
"status": "completed",
"summary": "Code review complete: 3 issues found",
"usage": { "total_tokens": 2048, "tool_uses": 5, "duration_ms": 5000 },
"output_file": "/tmp/task_output.jsonl",
"session_id": "abc123"
}Mapeo a estado en UI: task_started -> running, task_progress -> running (acumula lastTool, summary, usage), task_notification -> completed | failed | waiting | queued segun status.
3.6 user
Replay del input del usuario (con --replay-user-messages) o tool_results sinteticos.
{
"type": "user",
"message": {
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "tool_use_xyz", "content": "Resultado", "is_error": false }
]
},
"parent_tool_use_id": null,
"session_id": "abc123"
}3.7 assistant
Mensaje completo del modelo (no streaming por caracteres). message.content es un array que mezcla bloques text y tool_use.
{
"type": "assistant",
"message": {
"role": "assistant",
"content": [
{ "type": "text", "text": "Voy a revisar el archivo." },
{ "type": "tool_use", "id": "tool_use_xyz", "name": "Read", "input": { "file_path": "src/foo.ts" } }
]
},
"parent_tool_use_id": null,
"session_id": "abc123"
}3.8 tool_progress
Heartbeat de una herramienta en ejecucion.
{
"type": "tool_progress",
"tool_use_id": "tool_use_xyz",
"tool_name": "Bash",
"elapsed_time_seconds": 2.5,
"task_id": "task_abc",
"session_id": "abc123"
}3.9 result
Cierre del turno. Subtypes:
successerror_during_executionerror_max_turnserror_max_budget_usderror_max_structured_output_retries
{
"type": "result",
"subtype": "success",
"duration_ms": 5000,
"duration_api_ms": 4500,
"is_error": false,
"num_turns": 1,
"result": "Archivo creado",
"stop_reason": "end_turn",
"total_cost_usd": 0.00123,
"usage": {
"inputTokens": 512,
"outputTokens": 256,
"cacheReadInputTokens": 0,
"cacheCreationInputTokens": 0
},
"session_id": "abc123"
}3.10 stream_event
Solo si se invoca con --include-partial-messages. Contiene RawMessageStreamEvent de la SDK Anthropic. El desktop hoy no lo usa (mensajes completos via assistant).
3.11 rate_limit_event
{
"type": "rate_limit_event",
"rate_limit_info": {
"status": "allowed",
"resetsAt": 1704067200000,
"rateLimitType": "five_hour",
"utilization": 0.5
},
"session_id": "abc123"
}4. Asociacion tool_use <-> tool_result
- El bloque
tool_useenassistant.message.content[]llevaid. - El correspondiente
tool_resultaparece en el siguienteuser.message.content[]contool_use_idigual alidanterior. - Para subagentes, el
tool_use_idraiz se mantiene en los eventossystem/task_*para correlacionar.
5. Permisos y filtrado de herramientas
--permission-mode <mode> admite (segun CLI/src/entrypoints/sdk/coreSchemas.ts:339):
default- comportamiento estandar; pide confirmacion para acciones peligrosas.acceptEdits- auto-acepta ediciones de archivos.bypassPermissions- omite todos los permisos. Requiere ademas--allow-dangerously-skip-permissions.plan- modo planificacion; no ejecuta herramientas.dontAsk- no pregunta; deniega lo no preaprobado.
--allowed-tools <lista> permite reglas granulares como "Bash(git:*)" o "Edit". --disallowed-tools <lista> lista herramientas a bloquear (ej. "WebFetch,WebSearch" para deshabilitar red).
6. Stderr
stderr puede contener warnings de bootstrap, errores de carga de plugins, etc. El desktop los muestra como eventos rojos sin parsear.
7. Compatibilidad y versionado
v1es el contrato actual. Cualquier cambio incompatible (renombre de campos, eliminacion detype/subtype) bumpea av2.- Cambios aditivos (nuevos
typeosubtype, nuevos campos opcionales) siguen siendov1y son backward compatible. El desktop debe ignorar campos desconocidos sin romper. - Tests de contrato (Fase 6 del Roadmap): grabar transcripts NDJSON reales y replicarlos en CI para detectar regresiones.
