“나도 만들 수 있을까?”

AI 에이전트 라이브러리를 만들어 배포했다. 이걸로 Claude Code 같은 CLI를 만들 수 있을까?

10개월 전, AI 에이전트를 쉽게 개발할 수 있는 Robota SDK를 만들어 npm에 공개했다. Robota SDK로 멀티 AI 프로바이더, 도구, 플러그인, Team 에이전트까지 테스트했다.

최근 매일 Claude Code를 쓰면서 AGENTS.md를 알게 됐고, 내 SDK로 코딩 에이전트 CLI를 만들어 보고 싶었다.

Robota SDK 구성

계층패키지역할
핵심 라이브러리agent-core, sessions, tools, sdk실행 루프, 대화 관리, 플러그인
AI 프로바이더anthropic / openai / googleClaude, GPT-4, Gemini
플러그인 (9개)agent-plugin-*로깅, 분석, 에러, 성능 등
DAG (8개)dag-core ~ dag-worker워크플로우 실행 엔진
기타team, remote, mcp멀티 에이전트, 원격, MCP

AGENTS.md란 무엇인가

대화가 시작되면 시스템 프롬프트로 주입하는 지시문이다

Claude Code를 쓰면서 AGENTS.md 파일 하나가 에이전트의 행동을 완전히 바꾸는 걸 봤다. 열어보니 그냥 마크다운 형식의 파일이었다.

AGENTS.md, CLAUDE.md 같은 파일은 프로젝트 루트에서 탐색한 뒤 시스템 프롬프트에 주입한다. LLM은 이 내용을 프로젝트 규칙으로 인식하고 따른다.

동작 방식

  • 대화가 시작되면 AGENTS.md 내용을 시스템 프롬프트로 넣는다
  • 문서 안에 다른 .md 파일 링크가 있으면 기억해 두었다가, 필요할 때 해당 파일을 읽는다
  • LLM은 이 규칙을 따르면서 도구를 호출하고, 결과를 받아서 다시 판단한다

코딩 에이전트 핵심은 결국 이 세 가지다: 시스템 프롬프트 + 도구 + 실행 루프.

에이전트가 읽는 프로젝트 구조

프로젝트 폴더에 넣으면 에이전트가 자동으로 인식한다

코딩 에이전트는 프로젝트 루트의 특정 폴더를 탐색해서 스킬, 훅, 설정을 자동으로 로딩한다.

경로내용
.agents/skills/프로젝트 전용 스킬 — 슬래시 명령으로 실행 가능
.agents/rules/프로젝트 규칙 — AGENTS.md에서 참조
.agents/tasks/백로그, 진행 중 작업 추적
.claude/settings.json훅 설정, 퍼미션 allow/deny 목록
.claude/commands/Claude Code 커스텀 명령

코딩 에이전트 기본 도구

에이전트의 손발 — 이 6개로 코드를 읽고, 쓰고, 실행한다

처음에는 도구가 수십 개 필요할 줄 알았는데, 실제로는 6개로 거의 모든 코딩 작업을 처리했다.

도구역할예시
Bash셸 명령 실행pnpm test, git status, ls
Read파일 읽기소스 코드, 설정 파일 확인
Write파일 생성새 파일 작성
Edit파일 부분 수정함수 하나만 고치기
Glob파일 검색*/.ts 패턴 매칭
Grep내용 검색코드에서 함수 이름 찾기

LLM이 이 도구를 자유롭게 조합해서 호출한다. 파일을 읽고, 수정하고, 테스트를 돌리고, 결과를 확인한다. 개발자가 터미널에서 하는 일 그대로다.

실행 루프 구조

LLM 호출 → 도구 실행 → 결과 재주입을 반복한다

LLM을 한 번 호출하면 답이 나오는 줄 알았다. 실제로는 도구를 호출하고, 결과를 돌려주고, 다시 판단하는 루프를 계속 돈다.

단계동작
1LLM에 메시지를 보낸다
2응답에 도구 호출이 포함되면 도구를 실행한다
3실행 결과를 대화에 추가하고 LLM을 다시 호출한다
4도구 호출이 없으면 최종 응답을 출력한다

각 라운드에서 LLM 응답은 토큰 단위로 실시간 출력(스트리밍)한다. 사용자는 AI가 생각하는 과정을 실시간으로 본다.

도구 실행 권한

어떤 도구를 허용하고 어떤 도구를 차단할지 결정하는 구조

에이전트가 파일을 수정하고 셸 명령을 실행한다. 모든 도구 호출에 대해 실행 전에 권한을 평가한다.

3단계 평가

  • deny 목록 — 명시적으로 차단한 패턴 (예: rm -rf /)
  • allow 목록 — 미리 허용한 패턴 (예: pnpm test:*)
  • 모드 정책 — 나머지는 현재 모드에 따라 결정

4단계 모드

모드동작
plan읽기만 허용, 수정 전부 차단
default위험한 도구는 사용자에게 확인
acceptEdits파일 수정 자동 허용, 셸 명령만 확인
bypassPermissions전부 자동 허용 (위험)

훅(Hook)

도구 실행, 세션 시작/종료, 사용자 입력 등 주요 시점에 끼어든다

코딩 에이전트 동작 흐름 곳곳에 커스텀 로직을 끼워 넣는다. 도구 실행 전후뿐 아니라, 세션 시작/종료, 사용자 입력 직후에도 훅이 동작한다.

훅 이벤트시점활용 예시
PreToolUse도구 실행 전브랜치 보호, 위험 명령 차단
PostToolUse도구 실행 후자동 포매팅, 린트 실행
SessionStart세션 시작컨텍스트 로딩, 상태 체크
Stop세션 종료로그 저장, 정리 작업
UserPromptSubmit사용자 입력 후입력 전처리, 검증

훅은 셸 커맨드, HTTP 호출, 프롬프트, 에이전트 실행 등 여러 방식으로 구현한다.

체크포인트와 되돌리기

파일 수정을 자동으로 추적하고, 언제든 이전 상태로 되돌린다

매 프롬프트마다 파일 상태를 자동으로 스냅샷한다. Write, Edit 도구로 수정한 파일만 추적하고, Bash 명령(rm, mv 등)으로 변경한 파일은 추적하지 않는다.

되돌리기 옵션

옵션동작
코드 + 대화 복원파일과 대화 모두 해당 시점으로 되돌린다
대화만 복원대화를 되돌리되 현재 파일은 유지한다
코드만 복원파일을 되돌리되 대화는 유지한다
여기서부터 요약선택 시점 이후 대화를 압축한다 (파일 변경 없음)

체크포인트는 세션 단위의 빠른 복구용이다. Git을 대체하지 않는다.

스킬(Skill)

폴더에 스킬 파일을 넣으면 슬래시 명령으로 실행한다

스킬 파일 구조

---
name: commit
description: 변경 사항을 커밋
context: fork
---
스킬 프롬프트 내용...
  • name — 슬래시 명령 이름 (/commit)
  • description — 메뉴에 표시할 설명
  • context: fork — 별도 세션에서 실행 (서브에이전트)

스킬은 프로젝트마다 다르게 구성한다. 코드 리뷰, 커밋, 테스트, 문서 생성 등 반복 작업을 스킬로 만들어두면 슬래시 명령 한 번으로 실행한다.

컨텍스트 관리 문제

대화가 길어지면 AI가 앞의 내용을 잊는다

도구를 10번 호출하는 프롬프트 하나가 컨텍스트의 절반을 채우는 걸 보고 나서야, 이게 진짜 문제라는 걸 알았다.

AI 모델은 한 번에 처리하는 컨텍스트 크기를 제한한다. Sonnet 4.5는 200K 토큰, Opus 4.6은 1M 토큰. 많아 보이지만, 코딩 에이전트는 엄청난 양을 컨텍스트에 쌓는다.

왜 문제인가

  • 대화 내용뿐 아니라 도구 실행 내역, 파일 내용, 명령 결과가 전부 컨텍스트에 쌓인다
  • 도구가 파일을 읽을 때마다 그 내용이 대화에 추가된다
  • 한 번의 프롬프트에 도구가 10번 돌면, 10개의 결과가 전부 컨텍스트를 차지한다
  • 모델이 허용하는 컨텍스트 크기를 넘으면 API가 에러를 낸다

코딩 에이전트가 해결해야 하는 과제

  • 컨텍스트가 얼마나 찼는지 추적
  • 한계에 가까워지면 이전 대화를 요약해서 압축
  • 시스템 프롬프트(AGENTS.md)는 압축하지 않고 보존
  • 도구 출력이 너무 크면 잘라내기

이 구조로 직접 CLI를 만들어 봤다

기존 에이전트에 실행 루프, 도구, 퍼미션을 조립했다

여기까지 파악하고 나니 내 SDK로 만들 수 있겠다는 확신이 들었다. AGENTS.md와 실행 루프만 조립했더니 정말 Claude Code처럼 동작했다. 핵심은 기본 도구 6개(Bash, Read, Write, Edit, Glob, Grep)였다. 그리고 이 구조는 Anthropic API에 종속하지 않는다 — OpenAI API를 써도 동일하게 돌아갈 구조다.

기존 Robota SDK 위에 계층을 나눠서 쌓았다:

  • agent-cli — 터미널 UI (Ink/React)
  • agent-sdk — InteractiveSession, 커맨드, 스킬, 플러그인
  • agent-sessions — Session, 퍼미션, 훅, 컨텍스트
  • agent-core — Robota 라이브러리, 프로바이더, 도구, 실행 루프

구현한 기능 목록

결국 다 만들어야 한다

Claude Code를 쓰는 사람이 넘어오려면 익숙한 기능을 다 갖춰야 한다. 하나하나 구현하는 건 따분하지만, 빠지면 쓰기 불편하다.

터미널 UI

  • React 기반 TUI (Ink)
  • 스트리밍 마크다운 렌더링 + 디바운스
  • 도구 실행 실시간 표시 + Edit Diff
  • CJK(한국어) 입력 지원

세션과 입력

  • 세션 이어가기 / 분기 / 이름 지정
  • 슬래시 커맨드 + Tab 자동완성
  • 멀티라인 붙여넣기
  • 실행 중단(ESC, Ctrl+C) + 프롬프트 큐

시스템

  • 퍼미션 4단계 모드, 훅 시스템
  • 서브에이전트 실행
  • 비대화형 모드 (Headless Transport)
  • 모델 선택, 언어 설정, 첫 실행 설정

만들면서 부딪힌 문제 (1)

터미널에서 한국어를 쓰는 건 쉽지 않았다

CJK 입력

  • 문제 — 터미널 raw mode에서 한국어 IME가 정상 작동하지 않았다. 글자 탈락, 잘못된 위치에 입력
  • 원인 — React useState가 비동기로 배칭하는데, IME는 동기로 키스트로크를 보낸다
  • 해결 — ink-text-input을 버리고 CjkTextInput을 직접 작성. useRef로 즉시 반영, useState는 렌더링 트리거로만

Mac Terminal.app 크래시 (SIGSEGV)

  • 문제 — Terminal.app에서 한국어를 입력하면 터미널 앱 자체가 크래시
  • 원인 — Ink의 setCursorPosition()이 커서를 잘못된 위치로 이동시키면 IME가 세그멘테이션 폴트를 일으킨다
  • 해결 — setCursorPosition 호출을 제거

만들면서 부딪힌 문제 (2)

데이터 구조를 바로잡으니 나머지가 풀렸다

컨텍스트 오버플로우

  • 문제 — 도구 결과가 실시간으로 쌓이면서 컨텍스트가 급격히 커지고, LLM이 오류로 중단
  • 해결 — 임계값 초과 시 “컨텍스트 문제로 누락됨” 메시지를 삽입. LLM이 이를 보고 자연스럽게 복구

히스토리 확장

기존 에이전트는 API 호출에 필요한 채팅 내용만 대화 목록에 담았다. 하지만 CLI에서 세션을 관리하려면 대화뿐 아니라 도구 실행, 스킬 호출, 이벤트 등 다양한 정보를 함께 기록해야 했다.

agent-core에 IHistoryEntry 타입을 신설하고, 모든 정보를 하나의 타임라인에 담았다:

  • append-only, read-only — 수정/삭제 없음. 데이터가 없으면 fallback이 아니라 버그
  • 투명한 저장 — resume 시 가공 없이 그대로 불러옴. 변환이 필요하면 저장 로직을 고친다

이 구조 덕분에 세션 이어가기, 히스토리 표시, 이벤트 추적이 모두 단순하게 만들었다.

컨텍스트 압축 — 내가 구현한 방법

5가지 방법으로 컨텍스트를 관리한다

전략설명
사전 감지매 라운드 전 토큰 추정 (chars/2). 83.5% 초과 시 경고
자동 압축/compact 또는 자동. AI가 이전 메시지를 요약
시스템 프롬프트 보존AGENTS.md 등은 압축하지 않고 유지
도구 출력 캡30K 문자 초과 시 자동 절삭
도구 결과 스킵80% 초과 시 나머지 건너뜀 + LLM에 누락 알림

핵심: 압축 한 번에 토큰 40~60% 절약. 단, 세부 맥락을 잃는다.

Claude Code와 호환하는 플러그인 기능

생태계와 호환하지 않으면 혼자만 쓰는 도구로 끝난다

플러그인 명령어

/plugin marketplace add owner/repo    ← 마켓플레이스 등록
/plugin install name@marketplace      ← 플러그인 설치

마켓플레이스를 등록하고, 거기서 플러그인을 설치/제거할 수 있다. Claude Code와 동일한 경로 구조를 지원한다.

서브에이전트

서브에이전트도 구현했다. Claude Code의 스킬 파일 중 프론트매터에 context: fork가 있으면 메인 대화와 분리한 별도 세션에서 실행한다.

그래서, 지금 쓸 수 있나?

실제로 코딩 작업에 사용해 봤고, 일상 개발 작업을 할 수 있는 수준이다

쓸 수 있다. 이제 Robota를 Robota CLI로 개발할 수 있다.

  • Claude Code와 동일한 도구 세트 (Bash, Read, Write, Edit, Glob, Grep)
  • 스킬/플러그인 생태계 호환
  • 퍼미션 시스템과 훅 시스템 구현
  • 컨텍스트 압축으로 긴 세션 유지
  • 세션을 이어가며 며칠에 걸친 작업 가능
  • 서브에이전트로 병렬 작업 위임
  • 스트리밍 마크다운 렌더링
  • CJK(한국어) 입력 지원
  • agent-sdk를 분리했기 때문에 다른 프로젝트에서 SDK만 불러와서 동일한 코딩 어시스턴트를 구성한다

단, 조건이 있다.

  • 아직 Claude Code가 더 안정적이다
  • API 종량제라 구독 대비 비용이 더 들 수 있다
  • API 키가 필요해서 개발자가 아니면 진입 장벽이 높다

대신 내가 만든 라이브러리 위에서 돌아가므로 프로바이더 교체, 커스터마이징, 확장이 자유롭다.

마무리

9일 동안 385커밋, 53번의 npm 릴리즈. 만드는 과정에서 에이전트 작동 원리를 훨씬 정확하게 이해했다.

이제 이 기반 위에서 만들고 싶은 것이 계속 떠오른다. 앞으로 하나씩 만들어보겠습니다.

궁금한 점이나 피드백이 있다면 GitHub에 남겨주세요.

# https://robota.io

$ npm install -g @robota-sdk/agent-cli
$ robota