예전에는 CLI를 사람만 썼다. 지금은 Claude Code 같은 AI 에이전트가 CLI를 호출해 업무를 자동화한다. 같은 도구라도 "에이전트가 쓰기 좋게" 설계하면 자동화가 훨씬 매끄럽고, 그러지 않으면 자동화가 자주 깨진다. 여러 업무 자동화 CLI를 직접 만들어 에이전트로 호출해 보면서 정리한 설계 원칙을 공유한다. (예시는 공개한 개인 도구 door...
예전에는 CLI를 사람만 썼다. 지금은 Claude Code 같은 AI 에이전트가 CLI를 호출해 업무를 자동화한다. 같은 도구라도 "에이전트가 쓰기 좋게" 설계하면 자동화가 훨씬 매끄럽고, 그러지 않으면 자동화가 자주 깨진다.
여러 업무 자동화 CLI를 직접 만들어 에이전트로 호출해 보면서 정리한 설계 원칙을 공유한다. (예시는 공개한 개인 도구 dooray-cli·nhncloud-cli에서 가져왔다.)
사람은 출력을 눈으로 읽고, 모호하면 다시 입력하고, 위험한 작업은 알아서 조심한다. 에이전트는 그렇지 못하다. 출력을 기계적으로 파싱해야 하고, 입력 형식이 어긋나면 멈추며, 위험한 작업도 시키면 그냥 한다. 그래서 에이전트가 쓸 CLI는 출력·확인·안전을 사람용과 다르게 설계해야 한다.
--json)사람용 표 출력은 에이전트가 파싱하기 어렵다.
--json 플래그로 구조화된 결과를 내보내면, 에이전트가 결과를 받아 다음 단계로 바로 넘길 수 있다.--dry-run)에이전트는 위험한 작업도 망설임 없이 실행한다.
--dry-run으로 "실행하면 무엇이 일어나는지"만 보여주고 실제로는 바꾸지 않는 모드를 둔다.--quiet, --no-confirm)대화형 프롬프트("정말 진행할까요? y/n")는 사람에겐 친절하지만 에이전트·자동화 환경에선 멈춤의 원인이다.
--no-confirm으로 확인 단계를 건너뛰고, --quiet으로 진행 로그를 줄여 결과만 깔끔하게 남긴다.비대화형으로 만들수록 안전장치를 도구 안에 내장해야 한다.
에이전트는 정확한 입력 형식을 항상 알지는 못한다.
에이전트는 stdout 만 파싱하는 경우가 많다.
진행 표시, 경고, 에러 메시지가 같은 스트림에 섞이면 --json 출력도 JSON 으로 읽히지 않는다.
에이전트는 메시지 문장이 아니라 종료 코드로 성공과 실패를 판단한다.
명령마다 process.exit 를 흩어 두면 같은 실패가 명령에 따라 다른 코드로 끝난다.
DoorayCliError(message, exitCode) 를 던지고, 진입점의 최상위 핸들러가 한 번만 stderr 에 출력한 뒤 그 코드로 종료한다.process.exit 를 직접 부르지 않고 에러를 던지기만 한다. 일부만 실패한 파일 일괄 내려받기처럼 끝까지 진행해야 하는 경우에만 process.exitCode 를 설정한다. 종료 방식이 한 곳에 모이므로 코드 체계를 바꿔도 명령을 고칠 필요가 없다.업무, 문서처럼 다른 시스템의 대상을 가리킬 때는 ID 만 출력하지 않고 그 시스템이 인식하는 표준 링크로 출력한다.
dooray-cli 는 업무를 dooray://<조직 ID>/tasks/<업무 ID> 형태의 deeplink(앱 내 특정 화면으로 바로 이동하는 URI)로 출력한다.
이름을 ID 로 바꾸는 resolver 는 명령마다 같은 목록 API 를 다시 호출하기 쉽다. 에이전트는 한 세션에서 명령을 수십 번 부르므로 이 낭비가 그대로 쌓인다.
cache clear)도 함께 둔다.에이전트가 호출할 도구는 다음을 갖추면 자동화가 잘 깨지지 않는다.
--json)--dry-run)--quiet/--no-confirm)이렇게 만든 CLI를, 반복 작업을 절차로 고정한 skill이 호출하면 업무 자동화가 한 단계 더 매끄러워진다. skill로 절차를 고정하는 쪽은 Claude Code의 Skill 시스템에서 다룬다.