본문으로 건너뛰기

© 2026 Molayo

HN요약2026. 05. 14. 19:24

Show HN: CodeRLM – LLM 에이전트를 위한 Tree-sitter 기반 코드 인덱싱

요약

이 문서는 LLM 에이전트가 코드베이스를 효과적으로 탐색하고 상호작용할 수 있도록 설계된 API 엔드포인트와 기술을 설명합니다. 핵심은 모든 요청에 세션 ID(`X-Session-Id`)를 포함하여 특정 프로젝트 작업 디렉토리(cwd) 기반의 세션을 생성하는 것입니다. 이를 통해 에이전트는 코드 구조, 심볼 목록, 그리고 다양한 작업을 관리할 수 있습니다. 제공된 API는 세션 관리(생성, 조회, 종료), 코드 구조 정의 및 마킹(`structure`), 그리고 코드베이스 내의 모든 심볼을 나열(`symbols`)하는 기능을 제공하며, 이는 에이전트가 프로젝트에 대한 깊은 이해를 구축하는 데 필수적입니다.

핵심 포인트

  • LLM 에이전트를 위한 API는 세션 기반으로 설계되어 있으며, 각 요청은 `X-Session-Id` 헤더를 통해 특정 프로젝트 작업 디렉토리(cwd)와 연결됩니다.
  • 세션을 생성할 때 서버는 해당 디렉토리를 인덱싱하고 파일 트리 구조(`structure`) 및 초기 정보를 제공합니다.
  • 에이전트는 `/structure` 엔드포인트를 사용하여 코드베이스의 계층적 구조를 확인하거나, 특정 심볼을 정의/마킹하여 지식을 확장할 수 있습니다.
  • `/symbols` 엔드포인트는 함수, 클래스 등 다양한 종류별로 필터링된 방식으로 코드베이스 내 모든 심볼 목록을 조회하는 기능을 제공합니다.

이 문서는 CoderLM 설계( PURPOSE.md 참조)의 각 REPL 작업을 그에 상응하는 API 엔드포인트(endpoint)로 매핑합니다. 이러한 HTTP 호출을 래핑(wrap)하는 에이전트 기술(agent skill)을 구축할 때 이를 참조로 사용하십시오.

모든 엔드포인트는 http://<host>:<port>/api/v1로 접두사가 붙습니다. 예시는 localhost:3000을 가정합니다.

모든 요청(상태 확인(health), 세션 생성 및 관리자(admin) 엔드포인트 제외)은 반드시 X-Session-Id 헤더를 포함해야 합니다. 세션은 요청을 특정 프로젝트에 연결합니다.

다른 작업을 사용하기 전에, 에이전트는 탐색하고자 하는 프로젝트의 **작업 디렉토리(working directory)**를 사용하여 세션을 생성합니다. 서버는 해당 디렉토리를(이미 알려져 있지 않은 경우) 인덱싱(indexing)하고 해당 프로젝트에 범위가 지정된 session_id를 반환합니다.

작업 (Operation)메서드 (Method)엔드포인트 (Endpoint)본문 / 파라미터 (Body / Params)비고 (Notes)
세션 목록 조회 (List sessions)GET/sessions모든 활성 세션 (관리자용). 세션 헤더가 필요하지 않음
세션 생성 (Create session)POST/sessions{ "cwd": "/path/to/project" }새 프로젝트인 경우 인덱싱; { session_id, created_at, project, structure } 반환 (structure는 L1 파일 트리이며, 에이전트가 세션 생성 시 방향을 잡을 수 있도록 무료로 포함됨)
세션 확인 (Check session)GET/sessions/:id프로젝트 경로를 포함한 세션 정보 반환
세션 종료 (End session)DELETE/sessions/:id히스토리(history) 정리
# 생성 — 프로젝트 디렉토리를 cwd로 전달
SESSION=$(curl -s -X POST localhost:3000/api/v1/sessions \
-H "Content-Type: application/json" \
...

용량 제한으로 인해 프로젝트가 축출(evicted)된 경우, 해당 세션을 사용하는 요청은 410 Gone을 반환합니다. 다시 인덱싱하려면 새 세션을 생성하십시오.

코드베이스 파일 트리(file tree)를 확인합니다. 무시 필터링(ignore filtering)이 적용된 tree 명령어를 실행하는 것과 동일합니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)파라미터 / 바디 (Params / Body)
structureGET/structure?depth=N&detail=L (depth 0 = 무제한; detail 0–3)
structure define $filePOST/structure/define{ "file": "...", "definition": "..." }
structure redefine $filePOST/structure/redefine{ "file": "...", "definition": "..." }
structure mark $file $typePOST/structure/mark{ "file": "...", "mark": "..." }

?detail=

트리와 함께 반환될 파일별 심볼 (symbol) 정보의 양을 제어합니다:

레벨 (Level)내용 (Contents)
0파일 트리만 반환 (기본값)
...
{
"tree": "├── src/\n│ ├── main.rs\n│ └── lib.rs\n└── Cargo.toml\n",
"file_count": 42,
...
}
{
"tree": "├── src/\n│ ├── main.rs\n│ └── lib.rs\n",
"file_count": 42,
...
}

documentation

, ignore

, test

, config

, generated

, custom

# 1. 방향을 잡기 위해 구조(structure) 가져오기
curl -s -H "X-Session-Id: $SID" "localhost:3000/api/v1/structure?depth=2"
# 2. 에이전트가 파일을 학습함에 따라 주석 달기 (Annotate)
...

코드베이스에서 추출된 심볼 (symbols) 목록을 나열합니다. 기본값은 모든 종류이며, 쿼리 파라미터 (query params)로 필터링할 수 있습니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)파라미터 (Params)
symbol listGET/symbols?limit=100
symbol list (함수만)GET/symbols?kind=function&limit=100
symbol list (단일 파일)GET/symbols?file=src/main.rs&limit=100
symbol list (결합 필터)GET/symbols?kind=function&file=src/main.rs&limit=100

function

, method

, class

, struct

, enum

, trait

, interface

, constant

, variable

, type

, module

{
"count": 3,
"symbols": [
...

이름의 부분 문자열 (substring)로 심볼을 찾습니다. 선택적으로 단일 파일로 제한할 수 있습니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)파라미터 (Params)
symbol search $queryGET/symbols/search?q=handler&limit=20&file=src/main.rs
# 프로젝트 전체 (Project-wide)
curl -s -H "X-Session-Id: $SID" "localhost:3000/api/v1/symbols/search?q=parse&limit=10"
# 단일 파일로 제한 (Restrict to one file)
...

심볼(Symbol)에 사람이 읽을 수 있는 설명을 주석으로 답니다. 동일한 프로젝트 내의 모든 세션에서 볼 수 있습니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)바디 (Body)
symbol define $symbolPOST/symbols/define{ "symbol": "...", "file": "...", "definition": "..." }
symbol redefine $symbolPOST/symbols/redefine{ "symbol": "...", "file": "...", "definition": "..." }

define은 이미 정의가 존재하는 경우 실패합니다 (업데이트하려면 redefine을 사용하세요). 두 작업 모두 파일 간에 이름이 같은 심볼을 구분하기 위해 파일 경로가 필요합니다.

curl -s -X POST -H "X-Session-Id: $SID" -H "Content-Type: application/json" \
localhost:3000/api/v1/symbols/define \
-d '{"symbol":"scan_directory","file":"src/index/walker.rs","definition":"Walks codebase respecting gitignore, populates file tree"}'

심볼의 전체 소스 코드(함수 본문, 구조체 정의 등)를 가져옵니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)파라미터 (Params)
symbol implementation $symbolGET/symbols/implementation?symbol=...&file=...
{
"symbol": "scan_directory",
"file": "src/index/walker.rs",
...

코드베이스 전체에서 심볼의 호출 지점(Call sites)을 찾습니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)파라미터 (Params)
symbol callers $symbolGET/symbols/callers?symbol=...&file=...&limit=50
{
"count": 2,
"callers": [
...

주어진 심볼을 참조하는 테스트 함수를 찾습니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)파라미터 (Params)
symbol tests $symbolGET/symbols/tests?symbol=...&file=...&limit=20
{
"count": 1,
"tests": [
...

함수 내부에 선언된 지역 변수(Local variables)를 나열합니다.

REPL 작업메서드 (Method)엔드포인트 (Endpoint)파라미터 (Params)
symbol list variables $functionGET/symbols/variables?function=...&file=...
{
"count": 5,
"variables": [
...

파일에서 특정 범위의 라인을 읽습니다. 라인 번호는 0-indexed (시작 인덱스 포함, 종료 인덱스 제외)입니다.

REPL operationMethodEndpointParams
peek $file $start $endGET/peek?file=...&start=0&end=100
{
"file": "src/main.rs",
"start_line": 1,
...
# 처음 50개 라인 읽기
curl -s -H "X-Session-Id: $SID" "localhost:3000/api/v1/peek?file=src/main.rs&start=0&end=50"
# 100-120 라인 읽기
...

인덱싱된 모든 파일에 대해 정규 표현식 (Regex) 검색을 수행합니다. 스코프 인식 필터링 (scope-aware filtering) 및 파일별 제한을 지원합니다.

REPL operationMethodEndpointParams
grep $patternGET/grep?pattern=...&max_matches=50&context_lines=2&scope=all
ParamDefaultNotes
pattern전체 Rust 정규 표현식 (regex) 문법
max_matches50반환되는 매치(matches) 수의 상한선
context_lines2각 매치 전후의 컨텍스트 라인 수
scopeallall은 모든 곳에서 매치됨; code는 주석/문자열 AST 노드 내부의 매치를 건너뜀 (언어별 Tree-sitter 인식)
filegrep을 단일 파일 경로로 제한
{
"pattern": "DashMap",
"total_matches": 8,
...
# 주석 및 문자열 리터럴 내부의 매치 건너뛰기
curl -s -H "X-Session-Id: $SID" \
"localhost:3000/api/v1/grep?pattern=TODO&scope=code"
...

파일의 바이트 오프셋 청크 경계 (byte-offset chunk boundaries)를 계산합니다. 대용량 파일을 증분 처리 (incremental processing)를 위해 조각으로 나눌 때 유용합니다.

REPL operationMethodEndpointParams
chunk_indices $file $size $overlapGET/chunk_indices?file=...&size=5000&overlap=200
{
"file": "src/main.rs",
"total_bytes": 3521,
...

명령 기록 (command history)을 가져옵니다. 두 가지 모드를 지원합니다:

REPL operationMethodEndpointParamsSession header
historyGET/history?limit=50X-Session-Id 포함 시: 단일 세션 기록
history (admin)GET/history?limit=50헤더 미포함 시: 모든 세션의 기록
{
"count": 3,
"history": [
...
{
"total_entries": 7,
"sessions": [
...

서버 상태를 확인합니다. 세션이 필요하지 않습니다.

작업 (Operation)메서드 (Method)엔드포인트 (Endpoint)
healthGET/health

curl -s localhost:3000/api/v1/health

{
"status": "ok",
"projects": 2,
...

등록된 모든 프로젝트를 나열합니다. 디버깅(debugging) 및 관리자 가시성 확보에 유용합니다. 세션이 필요하지 않습니다.

작업 (Operation)메서드 (Method)엔드포인트 (Endpoint)
rootsGET/roots

curl -s localhost:3000/api/v1/roots

{
"count": 2,
"roots": [
...

어노테이션 (Annotations; 파일 정의, 심볼 정의, 마크)은 기본적으로 메모리에 상주합니다. 이 엔드포인트들은 프로젝트 루트의 .coderlm/annotations.json에 어노테이션을 영구 저장(persist)하거나, 해당 파일로부터 불러옵니다(hydrate). 어노테이션은 세션 생성 시에도 자동으로 로드되며, Stop 훅(hook)이 정리(cleanup) 전 자동으로 저장합니다.

작업 (Operation)메서드 (Method)엔드포인트 (Endpoint)바디 (Body)비고 (Notes)
어노테이션 저장 (Save annotations)POST/annotations/save프로젝트 루트에 .coderlm/annotations.json을 기록합니다
어노테이션 로드 (Load annotations)POST/annotations/load.coderlm/annotations.json을 읽어 적용하며, 로드된 항목의 개수를 반환합니다
curl -s -X POST -H "X-Session-Id: $SID" localhost:3000/api/v1/annotations/save
# {"ok":true}
curl -s -X POST -H "X-Session-Id: $SID" localhost:3000/api/v1/annotations/load
...

프로젝트 범위의 이름이 지정된 스크래치 버퍼 (scratch buffers). 소스 코드의 일부, 작성 중인 스니펫(snippet), 또는 파일 트리를 오염시키지 않으면서 단일 요청보다 오래 유지되어야 하는 일시적인 컨텍스트(transient context)를 캡처하는 데 유용합니다. 버퍼는 메모리에만 존재하며, 서버 재시작 시에는 유지되지 않습니다.

작업 (Operation)메서드 (Method)엔드포인트 (Endpoint)본문 / 파라미터 (Body / Params)
버퍼 목록 조회 (List buffers)GET/buffers
버퍼 생성 (raw) (Create buffer (raw))POST/buffers{ "name": "...", "content": "...", "description": "..." } (description은 선택 사항)
파일로부터 버퍼 생성 (Create buffer from file)POST/buffers/from-file{ "name": "...", "file": "...", "start_line": 0, "end_line": 100 } (start/end는 선택 사항 — 생략 시 전체 파일)
심볼로부터 버퍼 생성 (Create buffer from symbol)POST/buffers/from-symbol{ "name": "...", "symbol": "...", "file": "..." } (tree-sitter 바이트 범위를 사용함)
버퍼 조회 (전체) (Get buffer (full))GET/buffers/{name}
버퍼 미리보기 (라인 범위) (Peek buffer (line range))GET/buffers/{name}/peek?start=0&end=100
버퍼 삭제 (Delete buffer)DELETE/buffers/{name}
{
"buffers": [
{
...
{
"name": "scan_dir_snapshot",
"content": "pub fn scan_directory(...) { ... }",
...

프로젝트 범위의 JSON 키/값 저장소 (Project-scoped JSON key/value store). 세션 내의 여러 요청에 걸쳐 임의의 중간 상태(예: 다시 방문할 파일 경로 목록)를 임시 저장하는 데 유용합니다. 값은 임의의 JSON입니다. 메모리에만 존재합니다.

작업 (Operation)메서드 (Method)엔드포인트 (Endpoint)본문 (Body)
변수 목록 조회 (List variables)GET/vars
변수 설정 (Set variable)POST/vars{ "name": "...", "value": <json> }
변수 조회 (Get variable)GET/vars/{name}
변수 삭제 (Delete variable)DELETE/vars/{name}

list_vars는 전체 값 대신 각 항목을 해당 타입과 함께 요약합니다:

{
"variables": [
{ "name": "todo_files", "value_type": "array[7]" },
...

{ "name": "todo_files", "value": ["src/main.rs", "src/lib.rs"] }

서브 에이전트(sub-agent) 호출 결과를 위한 프로젝트 범위 저장소 (재귀적 탐색 패턴(recursive exploration pattern)에서 사용되며, 이 패턴에서는 부모 에이전트가 자식 에이전트에게 질문을 전달하고 그 결과를 다시 읽어옵니다). 메모리에만 존재합니다.

작업 (Operation)메서드 (Method)엔드포인트 (Endpoint)바디 (Body)
결과 목록 조회 (List results)GET/subcall_results
결과 추가 (Append result)POST/subcall_resultsSubcallResult (아래 참조)
모든 결과 삭제 (Clear all results)DELETE/subcall_results
{
"chunk_id": "src/server/routes.rs:0-300",
"query": "Where do we register the /annotations/save route?",
...

findingssuggested_queries는 자유 형식의 문자열 배열 (string arrays)입니다. answer_if_complete는 서브콜 (subcall)이 최종 답변을 생성했을 때 (더 이상의 홉 (hop)이 필요 없을 때) 설정되어야 합니다. depth는 서브콜이 재귀 (recursion) 과정 중 얼마나 깊은 단계에서 호출되었는지를 기록합니다.

스킬 (skill)이 코드베이스 (codebase)와 작업할 때 따라야 하는 순서는 다음과 같습니다:

1. GET /health → 서버가 실행 중인지 확인
2. POST /sessions { "cwd": "/path/..." } → session_id 획득, 프로젝트 인덱싱 완료
(응답에 L1 구조가 무료로 포함됨)
...

3~13단계는 필요에 따라 반복됩니다. 에이전트는 코드베이스에 대한 정신적 지도 (mental map)를 점진적으로 구축하며, 진행 과정에서 주석 (annotation)을 달아 이후의 쿼리 (동일한 에이전트 또는 스웜 (swarm) 내의 다른 에이전트에 의한 쿼리)가 축적된 정의 (definitions)로부터 이득을 얻을 수 있도록 합니다.

단일 서버 인스턴스는 여러 프로젝트를 동시에 지원합니다. 각 프로젝트는 에이전트가 해당 프로젝트의 cwd로 세션 (session)을 생성할 때 온디맨드 (on-demand) 방식으로 인덱싱됩니다. 리포지토리 (repo)마다 별도의 서버 인스턴스를 실행할 필요가 없습니다.

# 서버 시작 (프로젝트 경로 불필요)
coderlm-server serve --port 3000
# 에이전트 A가 백엔드에 연결
...

AI 자동 생성 콘텐츠

본 콘텐츠는 HN Claude Code Search의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0