문서로 건너뛰기
CLI

AI 에이전트용

Claude Code, Codex 또는 CI 작업에서 `openemail`을 다룹니다: 사람 없이 로그인, 데이터로 된 도움말, 드라이 런, 부족한 범위, 인증 코드.

내장 가이드

openemail agents는 Claude Code나 Codex 같은 AI 에이전트, 또는 CI의 스크립트를 위한 짧은 가이드를 Markdown으로 출력합니다: 사람 없이 로그인하는 법, 출력을 읽는 법, 명령을 찾는 법, 안전하게 바꾸는 법, 목록을 페이지별로 넘기는 법, 인증 코드나 범위가 부족할 때 할 일, 그리고 복사해 쓸 수 있는 레시피 다섯 개입니다. openemail agent도 같은 명령입니다.

터미널
openemail agentsopenemail agents --json | jq -r '.recipes[].commands[]'

--json을 붙이면 가이드는 schemaVersion, title, intro, { id, title, points }로 된 sections, exitCodes, { id, title, commands }로 된 recipes를 가진 하나의 문서가 됩니다. 이 규칙을 매번 프롬프트에 붙여 넣는 대신, 프로젝트가 이미 에이전트에게 주는 지침 파일에서 한 번만, CLI를 쓰기 전에 openemail agents를 실행하라고 알려 주세요.

사람 없이 로그인하기

  • API 키를 쓰세요. OPENEMAIL_API_KEY를 설정하거나 한 명령에 --api-key를 넘깁니다. 키는 설정 → API 키(openemail open api-keys)에서 에이전트에 필요한 범위만 주어 만드세요. 키는 브라우저를 열지 않으며 인증 코드도 필요 없습니다.
  • 또는 사람이 이 컴퓨터에서 한 번 openemail login으로 해 둔 브라우저 로그인을 다시 쓰고, --profile <name>으로 고르세요. CLI가 토큰을 스스로 갱신합니다.
  • 터미널이 없으면 아무것도 묻지 않습니다. --json, --no-input, CI 아래에서나 터미널이 연결되지 않았을 때, CLI가 물었을 값은 종료 코드 2로 멈추고 넘겨야 할 플래그를 알려 줍니다.
  • 브라우저 로그인은 사람이 승인해야 하므로, 사람 없이 실행된 openemail login은 아무것도 등록하기 전에 종료 코드 2와 코드 unattended로 멈추고 openemail login --with-token을 안내합니다.
  • openemail whoami --json은 워크스페이스, 로그인 종류, 그 scopes를 보여 줍니다.

출력 읽기

모든 명령에 --json을 넘기세요. 그러면 stdout에는 정확히 하나의 JSON 문서, --ndjson이면 한 줄에 객체 하나만 나오고, 진행 상황은 stderr에 남습니다. 실패하면 stderr에 {"error":{...}} 한 줄이 출력됩니다: 종료 코드와 그 code로 분기하고, next는 사람에게 보여 주고, 문구가 바뀔 수 있는 message는 절대 파싱하지 마세요. 모든 필드와 종료 코드는 스크립트 페이지에 있습니다.

데이터로 된 명령

--help --json은 CLI가 파싱에 쓰는 것과 같은 명령 레지스트리로 만든 하나의 JSON 문서로 도움말을 출력하므로, 설치된 버전과 항상 일치합니다. 루트, 그룹, 명령 어디서든 되고, openemail help <command> --json도 같은 것을 출력합니다.

터미널
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'

문서

schemaVersionnumber
필드의 의미가 바뀌면 올라갑니다
cli, versionstring
항상 `openemail`, 그리고 출력한 버전
pathstring[]
물어본 명령, 루트면 비어 있음
commandsobject[]
루트면 모든 최상위 명령, 아니면 물어본 명령, 각각 하위 명령과 함께
globalFlagsobject[]
모든 명령이 받는 플래그, 명령의 플래그와 같은 모양
subcommandAliasesobject
`ls`나 `rm` 같은 공통 별칭과 그것이 대신하는 동사
exitCodesobject[]
모든 종료 코드를 `{ code, name, meaning }` 모양으로

명령

namestring
명령의 마지막 단어
commandstring
`openemail domains delete` 같은 명령 전체
path, aliasesstring[]
`openemail` 뒤에서 그 명령에 이르는 단어들과 다른 이름
summary, descriptionstring
무엇을 하는지, 한 줄로 그리고 자세히
usagestring[]
호출하는 법
categorystring | null
최상위 명령이면 `openemail --help`에서의 구역, 아니면 `null`
group, runnable, hiddenboolean
하위 명령이 있는지, 혼자 실행되는지, 도움말에서 숨겨지는지
authstring
필요한 로그인: `required`, 브라우저 로그인만 되는 `browser`, `optional`, `none`
scopesstring[]
매번 실행할 때 필요한 API 범위
destructiveboolean
먼저 확인을 요청하는지, 그 확인에는 `--yes`가 답합니다
argumentsobject[]
각 인수의 `name`, `description`, `required`, `variadic`
flagsobject[]
각 플래그의 `name`, `short`, `kind`, `required`, `repeatable`, `choices`, `placeholder`, `description`, `hidden`
notes, examplesobject[]
추가 도움말 블록은 `{ title, lines }`로, 예시는 `{ command, note }`로
resourceobject | null
리소스 명령이면 그 뒤의 SDK 메서드와 REST 호출, 아니면 `null`
subcommandsobject[]
그룹 아래의 명령들, 같은 모양

리소스

namespacestring
`domains` 같은 SDK 네임스페이스
sdkMethodstring
`openemail.domains.delete` 같은 SDK 메서드
sdkMethodAllstring | null
목록이면 `--all --json`이 훑는 `listAll` 메서드
httpMethod, httpPathstring
`DELETE`와 `/domains/{id}` 같은 REST 호출
scopesstring[]
메서드에 필요한 범위
authstring
`apiKey`, 또는 API 키를 보내지 않는 메서드면 `none`과 `inboxToken`
returnsobject
`{ shape, type }`: `object`나 `page` 같은 응답의 모양과 그 SDK 타입
paginatesboolean
목록의 한 페이지를 돌려주는지

트리 전체는 약 1메가바이트이고 거의 전부가 198개의 리소스 명령이므로, 필요한 명령만 요청하거나 jq로 트리를 거르세요. 텍스트는 백틱을 그대로 두고 색상 코드를 담지 않으며, security 같은 숨겨진 명령도 hidden을 true로 해서 포함됩니다.

드라이 런

--dry-run은 mcp serve를 뺀 모든 명령에서 됩니다. 읽기는 평소처럼 실행되고, 무언가를 바꿀 첫 요청은 보내지 않고 출력되며, 명령은 다른 일은 하지 않고 코드 0으로 끝납니다. 아무것도 보내지 않으므로 확인은 건너뛰고, 그래서 에이전트는 --yes를 넘기지 않고도 파괴적인 명령이 무엇을 할지 볼 수 있습니다.

터미널
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  }}
  • 변경이란 GET과 HEAD를 뺀 모든 요청, MCP 도구 호출, 그리고 login과 logout의 로그인과 로그아웃 요청입니다. 토큰 갱신과 docs ask는 그대로 실행됩니다.
  • 계획에는 메서드, 전체 URL, Authorization 값을 Bearer [redacted]로 줄인 헤더, 그리고 Resend 키 같은 비밀 필드를 가린 JSON 본문이 나옵니다. 업로드는 크기와 콘텐츠 유형만 보여 줍니다.
  • profile use, login --with-token, 저장된 API 키 지우기처럼 이 컴퓨터 안에서만 일어나는 변경은 {"dryRun":true,"local":{"action","profile"}}를 출력하고 아무것도 저장하지 않습니다.
  • 첫 변경 전에 읽은 내용을 출력하는 명령은 그것을 먼저 보여 줍니다: read는 스레드를 출력한 다음, 그것을 읽음으로 표시할 요청을 출력합니다. 뒤의 것을 빼려면 --no-mark-read를 넘기세요.
  • mcp serve는 무엇을 보낼지 클라이언트가 정하므로 --dry-run을 종료 코드 2로 거부합니다. 대신 openemail mcp call <tool> --dry-run으로 도구 호출 하나를 미리 보세요.

부족한 범위

모든 명령은 늘 필요한 API 범위를 알고 있으며 도움말에 나열합니다. 저장된 로그인에 그중 하나가 없으면 명령은 API에 현재 목록을 한 번 물어보므로, 로그인한 뒤 웹사이트에서 준 접근도 바로 반영됩니다. 그래도 범위가 없으면, 무언가를 묻거나 요청을 보내기 전에 종료 코드 4와 코드 insufficient_scope로 멈춥니다:

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}}
  • 브라우저 로그인이면 next는 계정 → 명령줄에서 앱에 접근을 더 주거나(openemail open cli, 그다음 접근 편집), openemail login --force를 실행해 접근을 더 고르라고 안내합니다. 브라우저 로그인에는 keys:write나 keys:manage가 주어지지 않으므로, 그것들에는 API 키를 안내합니다.
  • API 키면 next는 그 범위를 가진 키를 쓰라고 안내합니다.
  • --api-key나 OPENEMAIL_API_KEY에서 온 키는 미리 확인하지 않으며, API가 판단합니다. 범위가 부족해 API가 호출을 거부하면 오류에도 같은 next가 담깁니다.

인증 코드

API 키에는 인증 코드가 필요 없습니다. 브라우저 로그인은 웹훅 추가, 규칙 만들기, 멤버 변경, 도메인 제거 같은 민감한 변경 전에 코드가 필요하고, 에이전트는 그것을 입력할 수 없습니다. 그래서 에이전트를 실행하기 전에 사람이 같은 프로필로 터미널에서 openemail verify를 실행하거나, 계정 → 명령줄에서 그 로그인에 60분 동안 변경 허용을 고릅니다. 어느 쪽이든 이후 60분 동안 유효합니다.

터미널
openemail verifyopenemail verify --status --json

verify --status --json은 프로필이 인증되었는지를 elevated로, 언제까지인지를 elevatedUntil로 에이전트에게 알려 줍니다. 인증이 없으면 변경은 종료 코드 4와 코드 step_up_required로 멈추고, 아무것도 바뀌지 않습니다:

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}}

MCP로

MCP를 쓰는 에이전트는 대신 OpenEmail MCP 서버를 쓸 수 있습니다. openemail mcp config --client claude-code, 또는 codex, cursor와 목록에 있는 다른 클라이언트로 설정을 출력하고, openemail mcp serve는 이 CLI의 브라우저 로그인을 다시 쓰는 로컬 브리지입니다. API 키로는 MCP 서버에 닿을 수 없습니다. 자세한 내용은 AI와 MCP 페이지에 있습니다.

레시피

읽지 않은 스레드를 JSON으로
openemail inbox --unread --limit 20 --jsonopenemail inbox --unread --json | jq -r '.items[].id'
읽음으로 표시하지 않고 스레드 읽기
openemail read CAHk7pQ2x9LmZ4 --no-mark-read --json
파일에서 보내기, 다시 시도해도 안전하게
openemail send --from [email protected] --to [email protected] --subject "Weekly report" --body-file report.md --idempotency-key weekly-report-39 --json
드라이 런 뒤에 도메인 추가하기
openemail domains create --domain example.com --dry-run --jsonopenemail domains create --domain example.com --json
자격 증명으로 할 수 있는 일 확인하기
openemail whoami --json | jq '.scopes'

받은편지함을,
내 방식대로.

기업, AI, 에이전트, 개인 메일을 위한 이메일 인프라. 규모와 프라이버시, 통제권을 위해 만들었습니다. 이메일이 처음부터 갖췄어야 할 모든 것.

OpenEmail

기업, AI, 에이전트, 개인 메일을 위한 이메일 인프라. 규모와 프라이버시, 통제권을 위해 만들었습니다. 이메일이 처음부터 갖췄어야 할 모든 것.

© 2026 OpenEmail. 모든 권리 보유.