Cursor Agent CLI는 --print와 함께 사용할 때 --output-format 옵션으로 여러 출력 형식을 제공해. 여기에는 프로그램적 사용을 위한 구조화된 형식(json, stream-json)과 사람이 읽기 쉬운 진행 상황 추적을 위한 단순화된 텍스트 형식이 포함돼.
기본 --output-formatstream-json이야. 이 옵션은 출력 중이거나(--print) 출력 모드가 추론되는 경우(비 TTY stdout 또는 파이프로 연결된 stdin)에만 유효해.

JSON 형식

json 출력 형식은 실행이 성공적으로 완료되면 단일 JSON 객체를 한 줄로 출력해. 델타와 도구 이벤트는 출력되지 않고, 텍스트는 최종 결과에 집계돼. 실패하면 프로세스는 0이 아닌 코드로 종료하고 stderr에 오류 메시지를 기록해. 실패한 경우에는 올바른 JSON 객체가 출력되지 않아.

성공 응답

성공하면 CLI는 다음 구조의 JSON 객체를 출력해:
{
  "type": "result",
  "subtype": "success",
  "is_error": false,
  "duration_ms": 1234,
  "duration_api_ms": 1234,
  "result": "<full assistant text>",
  "session_id": "<uuid>",
  "request_id": "<optional request id>"
}
FieldDescription
type터미널 결과에서는 항상 "result"
subtype성공적인 완료에서는 항상 "success"
is_error성공 응답에서는 항상 false
duration_ms총 실행 시간(밀리초)
duration_api_msAPI 요청 시간(밀리초) (현재는 duration_ms와 동일)
result전체 assistant 응답 텍스트(모든 텍스트 델타의 연결 결과)
session_id고유한 세션 식별자
request_id선택적 요청 식별자(생략될 수 있음)

Stream JSON 형식

stream-json 출력 형식은 줄바꿈으로 구분된 JSON(NDJSON)을 출력해. 각 줄에는 실행 중 실시간 이벤트를 나타내는 단일 JSON 객체가 포함되어 있어. 스트림은 성공 시 터미널 result 이벤트로 끝나. 실패 시에는 프로세스가 0이 아닌 코드로 종료되고 스트림이 터미널 이벤트 없이 일찍 끝날 수 있으며, 오류 메시지는 stderr에 기록돼.

이벤트 타입

시스템 초기화

각 세션 시작 시 한 번 출력됨:
{
  "type": "system",
  "subtype": "init",
  "apiKeySource": "env|flag|login",
  "cwd": "/absolute/path",
  "session_id": "<uuid>",
  "model": "<model display name>",
  "permissionMode": "default"
}
향후 toolsmcp_servers 같은 필드가 이 이벤트에 추가될 수 있어.

사용자 메시지

사용자의 입력 프롬프트를 포함:
{
  "type": "user",
  "message": {
    "role": "user",
    "content": [{ "type": "text", "text": "<prompt>" }]
  },
  "session_id": "<uuid>"
}

어시스턴트 텍스트 델타

어시스턴트가 응답을 생성하면서 여러 번 출력됨. 이 이벤트들은 증분 텍스트 청크를 포함:
{
  "type": "assistant",
  "message": {
    "role": "assistant",
    "content": [{ "type": "text", "text": "<delta chunk>" }]
  },
  "session_id": "<uuid>"
}
완전한 어시스턴트 응답을 재구성하려면 모든 message.content[].text 값을 순서대로 연결해야 해.

도구 호출 이벤트

도구 호출은 시작 및 완료 이벤트로 추적됨: 도구 호출 시작:
{
  "type": "tool_call",
  "subtype": "started",
  "call_id": "<string id>",
  "tool_call": {
    "readToolCall": {
      "args": { "path": "file.txt" }
    }
  },
  "session_id": "<uuid>"
}
도구 호출 완료:
{
  "type": "tool_call",
  "subtype": "completed",
  "call_id": "<string id>",
  "tool_call": {
    "readToolCall": {
      "args": { "path": "file.txt" },
      "result": {
        "success": {
          "content": "file contents...",
          "isEmpty": false,
          "exceededLimit": false,
          "totalLines": 54,
          "totalChars": 1254
        }
      }
    }
  },
  "session_id": "<uuid>"
}

도구 호출 타입

파일 읽기 도구:
  • 시작: tool_call.readToolCall.args{ "path": "file.txt" } 포함
  • 완료: tool_call.readToolCall.result.success에 파일 메타데이터와 내용 포함
파일 쓰기 도구:
  • 시작: tool_call.writeToolCall.args{ "path": "file.txt", "fileText": "content...", "toolCallId": "id" } 포함
  • 완료: tool_call.writeToolCall.result.success{ "path": "/absolute/path", "linesCreated": 19, "fileSize": 942 } 포함
기타 도구:
  • { "name": "tool_name", "arguments": "..." }와 함께 tool_call.function 구조를 사용할 수 있음

터미널 결과

성공적으로 완료 시 출력되는 최종 이벤트:
{
  "type": "result",
  "subtype": "success",
  "duration_ms": 1234,
  "duration_api_ms": 1234,
  "is_error": false,
  "result": "<full assistant text>",
  "session_id": "<uuid>",
  "request_id": "<optional request id>"
}

예시 시퀀스

다음은 일반적인 이벤트 흐름을 보여주는 대표적인 NDJSON 시퀀스야:
{"type":"system","subtype":"init","apiKeySource":"login","cwd":"/Users/user/project","session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff","model":"Claude 4 Sonnet","permissionMode":"default"}
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"README.md 읽고 요약 만들어줘"}]},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"README.md 파일을 "}]},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"읽어볼게"}]},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"tool_call","subtype":"started","call_id":"toolu_vrtx_01NnjaR886UcE8whekg2MGJd","tool_call":{"readToolCall":{"args":{"path":"README.md"}}},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"tool_call","subtype":"completed","call_id":"toolu_vrtx_01NnjaR886UcE8whekg2MGJd","tool_call":{"readToolCall":{"args":{"path":"README.md"},"result":{"success":{"content":"# Project\n\nThis is a sample project...","isEmpty":false,"exceededLimit":false,"totalLines":54,"totalChars":1254}}}},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":" 그리고 요약 만들어줄게"}]},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"tool_call","subtype":"started","call_id":"toolu_vrtx_01Q3VHVnWFSKygaRPT7WDxrv","tool_call":{"writeToolCall":{"args":{"path":"summary.txt","fileText":"# README Summary\n\nThis project contains...","toolCallId":"toolu_vrtx_01Q3VHVnWFSKygaRPT7WDxrv"}}},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"tool_call","subtype":"completed","call_id":"toolu_vrtx_01Q3VHVnWFSKygaRPT7WDxrv","tool_call":{"writeToolCall":{"args":{"path":"summary.txt","fileText":"# README Summary\n\nThis project contains...","toolCallId":"toolu_vrtx_01Q3VHVnWFSKygaRPT7WDxrv"},"result":{"success":{"path":"/Users/user/project/summary.txt","linesCreated":19,"fileSize":942}}}},"session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff"}
{"type":"result","subtype":"success","duration_ms":5234,"duration_api_ms":5234,"is_error":false,"result":"README.md 파일을 읽고 요약 만들어줄게","session_id":"c6b62c6f-7ead-4fd6-9922-e952131177ff","request_id":"10e11780-df2f-45dc-a1ff-4540af32e9c0"}

텍스트 형식

text 출력 형식은 에이전트 동작을 단순화해 사람이 읽기 쉬운 스트림으로 보여줘. 자세한 JSON 이벤트 대신, 에이전트가 실시간으로 무엇을 하는지 간결한 텍스트로 설명해. 이 형식은 구조화된 데이터를 파싱하는 오버헤드 없이 에이전트의 진행 상황을 모니터링하기에 유용해서, 로깅, 디버깅, 간단한 진행 추적에 딱 좋아.

출력 예시

Read file
Edited file
Ran terminal command
Created new file
각 동작은 에이전트가 수행할 때마다 새 줄에 표시돼서, 작업 진행 중 에이전트의 상태를 즉각적으로 확인할 수 있어.

구현 참고사항

  • 각 이벤트는 \n으로 끝나는 한 줄로 출력됩니다
  • thinking 이벤트는 print 모드에서 숨겨지며 두 출력 형식 모두에 표시되지 않습니다
  • 필드 추가는 시간이 지남에 따라 하위 호환성을 유지하는 방식으로 발생할 수 있습니다 (클라이언트는 알 수 없는 필드를 무시해야 합니다)
  • 스트림 형식은 실시간 업데이트를 제공하는 반면, JSON 형식은 완료될 때까지 기다린 후 결과를 출력합니다
  • 완전한 응답을 재구성하려면 모든 assistant 메시지 델타를 연결하세요
  • 도구 호출 ID를 사용해 시작/완료 이벤트를 연결할 수 있습니다
  • 세션 ID는 단일 에이전트 실행 전체에서 일관되게 유지됩니다